From 43d8f901c4bbb693643bb6f188c97dd28c1d0b0a Mon Sep 17 00:00:00 2001 From: Lakshminarayana Gurram Date: Wed, 6 Feb 2019 08:17:30 +0530 Subject: [PATCH] Modified meshlink_invite to generate invites for submesh --- examples/channels.c | 2 +- examples/chat.c | 2 +- examples/chatpp.cc | 2 +- examples/manynodes.c | 2 +- src/meshlink++.h | 4 +-- src/meshlink.c | 28 ++++++++++++++--- src/meshlink.h | 8 +++-- src/net_setup.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ src/node.h | 2 +- src/submesh.c | 4 +-- src/submesh.h | 2 +- 11 files changed, 114 insertions(+), 17 deletions(-) diff --git a/examples/channels.c b/examples/channels.c index 2059b387..d4e378f6 100644 --- a/examples/channels.c +++ b/examples/channels.c @@ -96,7 +96,7 @@ static void parse_command(meshlink_handle_t *mesh, char *buf) { return; } - invitation = meshlink_invite(mesh, arg); + invitation = meshlink_invite(mesh, NULL, arg); if(!invitation) { fprintf(stderr, "Could not invite '%s': %s\n", arg, meshlink_strerror(meshlink_errno)); diff --git a/examples/chat.c b/examples/chat.c index c26a642d..d0e511ca 100644 --- a/examples/chat.c +++ b/examples/chat.c @@ -59,7 +59,7 @@ static void parse_command(meshlink_handle_t *mesh, char *buf) { return; } - invitation = meshlink_invite(mesh, arg); + invitation = meshlink_invite(mesh, NULL, arg); if(!invitation) { fprintf(stderr, "Could not invite '%s': %s\n", arg, meshlink_strerror(meshlink_errno)); diff --git a/examples/chatpp.cc b/examples/chatpp.cc index 10870ef5..d3690404 100644 --- a/examples/chatpp.cc +++ b/examples/chatpp.cc @@ -49,7 +49,7 @@ static void parse_command(meshlink::mesh *mesh, char *buf) { return; } - invitation = mesh->invite(arg); + invitation = mesh->invite(NULL, arg); if(!invitation) { fprintf(stderr, "Could not invite '%s': %s\n", arg, meshlink::strerror()); diff --git a/examples/manynodes.c b/examples/manynodes.c index 9e4a95c0..f9150ef7 100644 --- a/examples/manynodes.c +++ b/examples/manynodes.c @@ -208,7 +208,7 @@ static void parse_command(char *buf) { return; } - invitation = meshlink_invite(mesh[nodeindex], arg); + invitation = meshlink_invite(mesh[nodeindex], NULL, arg); if(!invitation) { fprintf(stderr, "Could not invite '%s': %s\n", arg, meshlink_strerror(meshlink_errno)); diff --git a/src/meshlink++.h b/src/meshlink++.h index f7b0e1ac..b9889aa1 100644 --- a/src/meshlink++.h +++ b/src/meshlink++.h @@ -537,8 +537,8 @@ public: * @return This function returns a string that contains the invitation URL. * The application should call free() after it has finished using the URL. */ - char *invite(const char *name, uint32_t flags = 0) { - return meshlink_invite_ex(handle, name, flags); + char *invite(submesh *submesh, const char *name, uint32_t flags = 0) { + return meshlink_invite_ex(handle, submesh, name, flags); } /// Use an invitation to join a mesh. diff --git a/src/meshlink.c b/src/meshlink.c index 0ea38dbb..d0944527 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -60,6 +60,7 @@ const var_t variables[] = { {"ConnectTo", VAR_SERVER | VAR_MULTIPLE | VAR_SAFE}, {"Name", VAR_SERVER}, /* Host configuration */ + {"SubMesh", VAR_HOST | VAR_SAFE}, {"CanonicalAddress", VAR_HOST}, {"Address", VAR_HOST | VAR_MULTIPLE}, {"ECDSAPublicKey", VAR_HOST}, @@ -1305,6 +1306,7 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) { mesh->discovery = true; mesh->invitation_timeout = 604800; // 1 week mesh->netns = params->netns; + mesh->submeshes = NULL; if(usingname) { mesh->name = xstrdup(params->name); @@ -1418,6 +1420,7 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) { meshlink_submesh_t *meshlink_submesh_open(meshlink_handle_t *mesh, const char *submesh) { meshlink_submesh_t *s = NULL; + if(!mesh) { logger(NULL, MESHLINK_ERROR, "No mesh handle given!\n"); meshlink_errno = MESHLINK_EINVAL; @@ -1432,7 +1435,7 @@ meshlink_submesh_t *meshlink_submesh_open(meshlink_handle_t *mesh, const char * s = (meshlink_submesh_t *)lookup_submesh(mesh, submesh); - if (s) { + if(s) { logger(NULL, MESHLINK_ERROR, "SubMesh Already exists!\n"); meshlink_errno = MESHLINK_EEXIST; return NULL; @@ -2248,12 +2251,24 @@ void meshlink_set_invitation_timeout(meshlink_handle_t *mesh, int timeout) { mesh->invitation_timeout = timeout; } -char *meshlink_invite_ex(meshlink_handle_t *mesh, const char *name, uint32_t flags) { +char *meshlink_invite_ex(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, const char *name, uint32_t flags) { + meshlink_submesh_t *s = NULL; + if(!mesh) { meshlink_errno = MESHLINK_EINVAL; return NULL; } + if(submesh) { + s = (meshlink_submesh_t *)lookup_submesh(mesh, submesh->name); + + if(s != submesh) { + logger(mesh, MESHLINK_DEBUG, "Invalid SubMesh Handle.\n"); + meshlink_errno = MESHLINK_EINVAL; + return NULL; + } + } + pthread_mutex_lock(&(mesh->mesh_mutex)); // Check validity of the new node's name @@ -2341,6 +2356,11 @@ char *meshlink_invite_ex(meshlink_handle_t *mesh, const char *name, uint32_t fla // Fill in the details. fprintf(f, "Name = %s\n", name); + + if(s) { + fprintf(f, "SubMesh = %s\n", s->name); + } + fprintf(f, "ConnectTo = %s\n", mesh->self->name); // Copy Broadcast and Mode @@ -2386,8 +2406,8 @@ char *meshlink_invite_ex(meshlink_handle_t *mesh, const char *name, uint32_t fla return url; } -char *meshlink_invite(meshlink_handle_t *mesh, const char *name) { - return meshlink_invite_ex(mesh, name, 0); +char *meshlink_invite(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, const char *name) { + return meshlink_invite_ex(mesh, submesh, name, 0); } bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { diff --git a/src/meshlink.h b/src/meshlink.h index 6e03343b..b7c2fca6 100644 --- a/src/meshlink.h +++ b/src/meshlink.h @@ -219,7 +219,7 @@ extern meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) extern meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const char *appname, dev_class_t devclass); /// Create Sub-Mesh. -/** This function causes MeshLink to open a new Sub-Mesh network +/** This function causes MeshLink to open a new Sub-Mesh network * create a new thread, which will handle all network I/O. * * It is allowed to call this function even if MeshLink is already started, in which case it will return true. @@ -693,6 +693,7 @@ extern void meshlink_set_invitation_timeout(meshlink_handle_t *mesh, int timeout * The URL can only be used once, after the user has joined the mesh the URL is no longer valid. * * @param mesh A handle which represents an instance of MeshLink. + * @param submesh A handle which represents an instance of SubMesh. * @param name A nul-terminated C string containing the name that the invitee will be allowed to use in the mesh. * After this function returns, the application is free to overwrite or free @a name @a. * @param flags A bitwise-or'd combination of flags that controls how the URL is generated. @@ -700,7 +701,7 @@ extern void meshlink_set_invitation_timeout(meshlink_handle_t *mesh, int timeout * @return This function returns a nul-terminated C string that contains the invitation URL, or NULL in case of an error. * The application should call free() after it has finished using the URL. */ -extern char *meshlink_invite_ex(meshlink_handle_t *mesh, const char *name, uint32_t flags); +extern char *meshlink_invite_ex(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, const char *name, uint32_t flags); /// Invite another node into the mesh. /** This function generates an invitation that can be used by another node to join the same mesh as the local node. @@ -711,13 +712,14 @@ extern char *meshlink_invite_ex(meshlink_handle_t *mesh, const char *name, uint3 * Calling this function is equal to callen meshlink_invite_ex() with flags set to 0. * * @param mesh A handle which represents an instance of MeshLink. + * @param submesh A handle which represents an instance of SubMesh. * @param name A nul-terminated C string containing the name that the invitee will be allowed to use in the mesh. * After this function returns, the application is free to overwrite or free @a name @a. * * @return This function returns a nul-terminated C string that contains the invitation URL, or NULL in case of an error. * The application should call free() after it has finished using the URL. */ -extern char *meshlink_invite(meshlink_handle_t *mesh, const char *name); +extern char *meshlink_invite(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, const char *name); /// Use an invitation to join a mesh. /** This function allows the local node to join an existing mesh using an invitation URL generated by another node. diff --git a/src/net_setup.c b/src/net_setup.c index 10fb37b0..47ed32e0 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -31,6 +31,7 @@ #include "route.h" #include "utils.h" #include "xalloc.h" +#include "submesh.h" bool node_read_ecdsa_public_key(meshlink_handle_t *mesh, node_t *n) { if(ecdsa_active(n->ecdsa)) { @@ -156,6 +157,39 @@ exit: return n->devclass != 0; } +bool node_read_submesh(meshlink_handle_t *mesh, node_t *n) { + + splay_tree_t *config_tree; + char *p; + + init_configuration(&config_tree); + + if(!read_host_config(mesh, config_tree, n->name)) { + goto exit; + } + + if(get_config_string(lookup_config(config_tree, "SubMesh"), &p)) { + n->submesh = NULL; + + for list_each(submesh_t, s, mesh->submeshes) { + if(!strcmp(p, s->name)) { + n->submesh = s; + break; + } + } + + if(!n->submesh) { + n->submesh = (submesh_t *)meshlink_submesh_open(mesh, p); + } + + free(p); + } + +exit: + exit_configuration(&config_tree); + return n->submesh != NULL; +} + bool node_write_devclass(meshlink_handle_t *mesh, node_t *n) { if((int)n->devclass < 0 || n->devclass > _DEV_CLASS_MAX) { @@ -191,6 +225,41 @@ fail: return result; } +bool node_write_submesh(meshlink_handle_t *mesh, node_t *n) { + + if(!n->submesh) { + return false; + } + + bool result = false; + + splay_tree_t *config_tree; + init_configuration(&config_tree); + + // ignore read errors; in case the file does not exist we will create it + read_host_config(mesh, config_tree, n->name); + + config_t *cnf = lookup_config(config_tree, "SubMesh"); + + if(!cnf) { + cnf = new_config(); + cnf->variable = xstrdup("SubMesh"); + config_add(config_tree, cnf); + } + + set_config_string(cnf, n->submesh->name); + + if(!write_host_config(mesh, config_tree, n->name)) { + goto fail; + } + + result = true; + +fail: + exit_configuration(&config_tree); + return result; +} + void load_all_nodes(meshlink_handle_t *mesh) { DIR *dir; struct dirent *ent; @@ -212,12 +281,17 @@ void load_all_nodes(meshlink_handle_t *mesh) { node_t *n = lookup_node(mesh, ent->d_name); if(n) { + if(n == mesh->self && !n->submesh) { + node_read_submesh(mesh, n); + } + continue; } n = new_node(); n->name = xstrdup(ent->d_name); node_read_devclass(mesh, n); + node_read_submesh(mesh, n); node_add(mesh, n); } @@ -463,6 +537,7 @@ bool setup_myself(meshlink_handle_t *mesh) { */ bool setup_network(meshlink_handle_t *mesh) { init_connections(mesh); + init_submeshes(mesh); init_nodes(mesh); init_edges(mesh); init_requests(mesh); diff --git a/src/node.h b/src/node.h index acbf2e8b..9fad5545 100644 --- a/src/node.h +++ b/src/node.h @@ -50,7 +50,7 @@ typedef struct node_t { dev_class_t devclass; struct meshlink_handle *mesh; /* The mesh this node belongs to */ - struct submesh_t *submesh; /* Nodes Sub-Mesh Handle*/ + struct submesh_t *submesh; /* Nodes Sub-Mesh Handle*/ int sock; /* Socket to use for outgoing UDP packets */ sockaddr_t address; /* his real (internet) ip to send UDP packets to */ diff --git a/src/submesh.c b/src/submesh.c index 0a2bfb09..317328c8 100644 --- a/src/submesh.c +++ b/src/submesh.c @@ -67,12 +67,12 @@ void submesh_del(meshlink_handle_t *mesh, submesh_t *s) { submesh_t *lookup_submesh(struct meshlink_handle *mesh, const char *submesh_name) { submesh_t *submesh = NULL; - if ( !mesh->submeshes ) { + if(!mesh->submeshes) { return NULL; } for list_each(submesh_t, s, mesh->submeshes) { - if ( !strcmp(submesh_name, s->name) ) { + if(!strcmp(submesh_name, s->name)) { submesh = s; break; } diff --git a/src/submesh.h b/src/submesh.h index 958ce9c7..b5d90b30 100644 --- a/src/submesh.h +++ b/src/submesh.h @@ -26,7 +26,7 @@ typedef struct submesh_t { char *name; /* name of this Sub-Mesh */ void *priv; - struct meshlink_handle *mesh; /* the mesh this submesh belongs to */ + struct meshlink_handle *mesh; /* the mesh this submesh belongs to */ } submesh_t; extern void init_submeshes(struct meshlink_handle *mesh); -- 2.39.5