X-Git-Url: http://git.meshlink.io/?p=meshlink;a=blobdiff_plain;f=examples%2Fmanynodes.c;h=64ccd9c1c855c643fbe08f8c58e556a9098754d4;hp=bc3a1a178e94238eb2853768ee13d4095ad044b3;hb=HEAD;hpb=7ba8f3cc5088eb58fbf46cb74af312449c210051 diff --git a/examples/manynodes.c b/examples/manynodes.c index bc3a1a17..64ccd9c1 100644 --- a/examples/manynodes.c +++ b/examples/manynodes.c @@ -4,7 +4,12 @@ #include #include #include + +#if !defined(_WIN32) && !defined(__APPLE__) #include +#elif defined(__APPLE__) +#include +#endif #include "../src/meshlink.h" #include "../src/devtools.h" @@ -15,9 +20,12 @@ #include #include +#include static int n = 10; -static meshlink_handle_t **mesh; +static meshlink_handle_t **meshes; +static const char *namesprefix = "machine1"; +static int nodeindex = 0; static meshlink_node_t **nodes; static size_t nnodes; @@ -30,39 +38,43 @@ static void log_message(meshlink_handle_t *mesh, meshlink_log_level_t level, con [MESHLINK_ERROR] = "\x1b[31mERROR", [MESHLINK_CRITICAL] = "\x1b[31mCRITICAL", }; - fprintf(stderr, "%s\t%s:\x1b[0m %s\n", mesh ? mesh->name : "global",levelstr[level], text); + fprintf(stderr, "%s\t%s:\x1b[0m %s\n", mesh ? mesh->name : "global", levelstr[level], text); } //Test mesh sending data -static void testmesh () { - +static void testmesh(void) { for(int nindex = 0; nindex < n; nindex++) { - nodes = meshlink_get_all_nodes(mesh[nindex], nodes, &nnodes); - if(!nodes) { - fprintf(stderr, "Could not get list of nodes: %s\n", meshlink_strerror(meshlink_errno)); - } else { - printf("%zu known nodes:\n", nnodes); - for(int i = 0; i < nnodes; i++) { - //printf(" %s\n", nodes[i]->name); - if(!meshlink_send(mesh[nindex], nodes[i], "magic", strlen("magic") + 1)) { - fprintf(stderr, "Could not send message to '%s': %s\n", nodes[i]->name, meshlink_strerror(meshlink_errno)); - } - } + nodes = meshlink_get_all_nodes(meshes[nindex], nodes, &nnodes); + if(!nodes) { + fprintf(stderr, "Could not get list of nodes: %s\n", meshlink_strerror(meshlink_errno)); + } else { + printf("%zu known nodes:\n", nnodes); + + for(size_t i = 0; i < nnodes; i++) { + //printf(" %s\n", nodes[i]->name); + if(!meshlink_send(meshes[nindex], nodes[i], "magic", strlen("magic") + 1)) { + fprintf(stderr, "Could not send message to '%s': %s\n", nodes[i]->name, meshlink_strerror(meshlink_errno)); + } } + } + } } // Make all nodes know about each other by importing each others public keys and addresses. -static void linkmesh() { +static void linkmesh(void) { for(int i = 0; i < n; i++) { - char *datai = meshlink_export(mesh[i]); + char *datai = meshlink_export(meshes[i]); for(int j = i + 1; j < n; j++) { - char *dataj = meshlink_export(mesh[j]); - meshlink_import(mesh[i], dataj); - meshlink_import(mesh[j], datai); + char *dataj = meshlink_export(meshes[j]); + + if(!meshlink_import(meshes[i], dataj) || !meshlink_import(meshes[j], datai)) { + fprintf(stderr, "Could not exchange keys between %s and %s: %s\n", meshes[i]->name, meshes[j]->name, meshlink_strerror(meshlink_errno)); + } + free(dataj); } @@ -70,31 +82,30 @@ static void linkmesh() { } } -static bool exportmeshgraph(const char* path) -{ +static bool exportmeshgraph(const char *path) { + assert(path); + struct stat ps; int psr = stat(path, &ps); - if(psr == 0 || errno != ENOENT) - { - if(psr == -1) - { perror("stat"); } - else - { fprintf(stderr, "%s exists already\n", path); } + if(psr == 0 || errno != ENOENT) { + if(psr == -1) { + perror("stat"); + } else { + fprintf(stderr, "%s exists already\n", path); + } return false; } - FILE* stream = fopen(path, "w"); + FILE *stream = fopen(path, "w"); - if(!stream) - { + if(!stream) { perror("stream"); return false; } - if(!devtool_export_json_all_edges_state(mesh[0], stream)) - { + if(!devtool_export_json_all_edges_state(meshes[0], stream)) { fclose(stream); fprintf(stderr, "could not export graph\n"); return false; @@ -105,48 +116,52 @@ static bool exportmeshgraph(const char* path) } -void exportmeshgraph_timer(int signum) -{ +static void exportmeshgraph_timer(int signum) { + (void)signum; + struct timeval ts; gettimeofday(&ts, NULL); char name[1024]; - snprintf(name, sizeof(name), "graph_%ld_%03ld.json", ts.tv_sec, ts.tv_usec/1000); + snprintf(name, sizeof(name), "%sgraph_%ld_%03ld.json", namesprefix, ts.tv_sec, ts.tv_usec / 1000L); exportmeshgraph(name); } +#ifdef ITIMER_REAL static bool exportmeshgraph_started = false; -static bool exportmeshgraph_end(const char* none) -{ - if(!exportmeshgraph_started) - { return false; } +static bool exportmeshgraph_end(void) { + if(!exportmeshgraph_started) { + return false; + } + + struct itimerval zero_timer; - struct itimerval zero_timer = { 0 }; - setitimer (ITIMER_REAL, &zero_timer, NULL); + setitimer(ITIMER_REAL, &zero_timer, NULL); exportmeshgraph_started = false; return true; } -static bool exportmeshgraph_begin(const char* timeout_str) -{ - if(!timeout_str) +static bool exportmeshgraph_begin(const char *timeout_str) { + if(!timeout_str) { return false; + } - if(exportmeshgraph_started) - { - if(!exportmeshgraph_end(NULL)) + if(exportmeshgraph_started) { + if(!exportmeshgraph_end()) { return false; + } } // get timeout int timeout = atoi(timeout_str); - if(timeout < 100) - { timeout = 100; } + if(timeout < 100) { + timeout = 100; + } int timeout_sec = timeout / 1000; int timeout_msec = timeout % 1000; @@ -164,17 +179,28 @@ static bool exportmeshgraph_begin(const char* timeout_str) timer.it_interval.tv_usec = timeout_msec * 1000; /* Start a real timer. */ - setitimer (ITIMER_REAL, &timer, NULL); + setitimer(ITIMER_REAL, &timer, NULL); exportmeshgraph_started = true; return true; } +#else +static bool exportmeshgraph_end(void) { + return false; +} + +static bool exportmeshgraph_begin(const char *timeout_str) { + return false; +} +#endif static void parse_command(char *buf) { char *arg = strchr(buf, ' '); - if(arg) + + if(arg) { *arg++ = 0; + } if(!strcasecmp(buf, "invite")) { char *invitation; @@ -184,7 +210,8 @@ static void parse_command(char *buf) { return; } - invitation = meshlink_invite(mesh[0], arg); + invitation = meshlink_invite(meshes[nodeindex], NULL, arg); + if(!invitation) { fprintf(stderr, "Could not invite '%s': %s\n", arg, meshlink_strerror(meshlink_errno)); return; @@ -197,12 +224,18 @@ static void parse_command(char *buf) { fprintf(stderr, "/join requires an argument!\n"); return; } - meshlink_stop(mesh[0]); - if(!meshlink_join(mesh[0], arg)) + + meshlink_stop(meshes[nodeindex]); + + if(!meshlink_join(meshes[nodeindex], arg)) { fprintf(stderr, "Could not join using invitation: %s\n", meshlink_strerror(meshlink_errno)); - else { + } else { fprintf(stderr, "Invitation accepted!\n"); - meshlink_start(mesh[0]); + } + + if(!meshlink_start(meshes[nodeindex])) { + fprintf(stderr, "Could not restart MeshLink: %s\n", meshlink_strerror(meshlink_errno)); + exit(1); } } else if(!strcasecmp(buf, "kick")) { if(!arg) { @@ -210,32 +243,60 @@ static void parse_command(char *buf) { return; } - meshlink_node_t *node = meshlink_get_node(mesh[0], arg); + meshlink_node_t *node = meshlink_get_node(meshes[nodeindex], arg); + if(!node) { fprintf(stderr, "Unknown node '%s'\n", arg); return; } - meshlink_blacklist(mesh[0], node); + if(!meshlink_blacklist(meshes[nodeindex], node)) { + fprintf(stderr, "Error blacklising '%s': %s", arg, meshlink_strerror(meshlink_errno)); + return; + } printf("Node '%s' blacklisted.\n", arg); + } else if(!strcasecmp(buf, "whitelist")) { + if(!arg) { + fprintf(stderr, "/whitelist requires an argument!\n"); + return; + } + + meshlink_node_t *node = meshlink_get_node(meshes[nodeindex], arg); + + if(!node) { + fprintf(stderr, "Error looking up '%s': %s\n", arg, meshlink_strerror(meshlink_errno)); + return; + } + + if(!meshlink_whitelist(meshes[nodeindex], node)) { + fprintf(stderr, "Error whitelising '%s': %s", arg, meshlink_strerror(meshlink_errno)); + return; + } + + printf("Node '%s' whitelisted.\n", arg); } else if(!strcasecmp(buf, "who")) { if(!arg) { - nodes = meshlink_get_all_nodes(mesh[0], nodes, &nnodes); + nodes = meshlink_get_all_nodes(meshes[nodeindex], nodes, &nnodes); + if(!nodes) { fprintf(stderr, "Could not get list of nodes: %s\n", meshlink_strerror(meshlink_errno)); } else { printf("%zu known nodes:", nnodes); - for(int i = 0; i < nnodes; i++) + + for(size_t i = 0; i < nnodes; i++) { printf(" %s", nodes[i]->name); + } + printf("\n"); } } else { - meshlink_node_t *node = meshlink_get_node(mesh[0], arg); + meshlink_node_t *node = meshlink_get_node(meshes[nodeindex], arg); + if(!node) { fprintf(stderr, "Unknown node '%s'\n", arg); } else { - printf("Node %s found, pmtu %zd\n", arg, meshlink_get_pmtu(mesh[0], node)); + printf("Node %s found, pmtu %ld\n", arg, (long int)meshlink_get_pmtu(meshes[nodeindex], node)); } } } else if(!strcasecmp(buf, "link")) { @@ -245,25 +306,37 @@ static void parse_command(char *buf) { } else if(!strcasecmp(buf, "egb")) { exportmeshgraph_begin(arg); } else if(!strcasecmp(buf, "ege")) { - exportmeshgraph_end(NULL); + exportmeshgraph_end(); } else if(!strcasecmp(buf, "test")) { testmesh(); + } else if(!strcasecmp(buf, "select")) { + if(!arg) { + fprintf(stderr, "/select requires an argument!\n"); + return; + } + + nodeindex = atoi(arg); + printf("Index is now %d\n", nodeindex); + } else if(!strcasecmp(buf, "stop")) { + meshlink_stop(meshes[nodeindex]); } else if(!strcasecmp(buf, "quit")) { printf("Bye!\n"); fclose(stdin); } else if(!strcasecmp(buf, "help")) { printf( - ": Send a message to the given node.\n" - " Subsequent messages don't need the : prefix.\n" - "/invite Create an invitation for a new node.\n" - "/join Join an existing mesh using an invitation.\n" - "/kick Blacklist the given node.\n" - "/who [] List all nodes or show information about the given node.\n" - "/link Link all nodes together.\n" - "/eg Export graph as json file.\n" - "/test Test functionality sending some data to all nodes\n" - "/quit Exit this program.\n" - ); + ": Send a message to the given node.\n" + " Subsequent messages don't need the : prefix.\n" + "/invite Create an invitation for a new node.\n" + "/join Join an existing mesh using an invitation.\n" + "/kick Blacklist the given node.\n" + "/who [] List all nodes or show information about the given node.\n" + "/link Link all nodes together.\n" + "/eg Export graph as json file.\n" + "/test Test functionality sending some data to all nodes\n" + "/select Select the active node running the user commands\n" + "/stop Call meshlink_stop, use /select first to select which node to stop\n" + "/quit Exit this program.\n" + ); } else { fprintf(stderr, "Unknown command '/%s'\n", buf); } @@ -273,28 +346,34 @@ static void parse_input(char *buf) { static meshlink_node_t *destination; size_t len; - if(!buf) + if(!buf) { return; + } // Remove newline. len = strlen(buf); - if(len && buf[len - 1] == '\n') + if(len && buf[len - 1] == '\n') { buf[--len] = 0; + } - if(len && buf[len - 1] == '\r') + if(len && buf[len - 1] == '\r') { buf[--len] = 0; + } // Ignore empty lines. - if(!len) + if(!len) { return; + } // Commands start with '/' - if(*buf == '/') - return parse_command(buf + 1); + if(*buf == '/') { + parse_command(buf + 1); + return; + } // Lines in the form "name: message..." set the destination node. @@ -304,10 +383,13 @@ static void parse_input(char *buf) { if(colon) { *colon = 0; msg = colon + 1; - if(*msg == ' ') + + if(*msg == ' ') { msg++; + } + + destination = meshlink_get_node(meshes[nodeindex], buf); - destination = meshlink_get_node(mesh[0], buf); if(!destination) { fprintf(stderr, "Unknown node '%s'\n", buf); return; @@ -319,7 +401,7 @@ static void parse_input(char *buf) { return; } - if(!meshlink_send(mesh[0], destination, msg, strlen(msg) + 1)) { + if(!meshlink_send(meshes[nodeindex], destination, msg, strlen(msg) + 1)) { fprintf(stderr, "Could not send message to '%s': %s\n", destination->name, meshlink_strerror(meshlink_errno)); return; } @@ -329,43 +411,55 @@ static void parse_input(char *buf) { int main(int argc, char *argv[]) { const char *basebase = ".manynodes"; - const char *namesprefix = "machine1"; const char *graphexporttimeout = NULL; char buf[1024]; - if(argc > 1) + if(argc > 1) { n = atoi(argv[1]); + } if(n < 1) { fprintf(stderr, "Usage: %s [number of local nodes] [confbase] [prefixnodenames] [graphexport timeout]\n", argv[0]); return 1; } - if(argc > 2) + if(argc > 2) { basebase = argv[2]; + } - if(argc > 3) + if(argc > 3) { namesprefix = argv[3]; + } - if(argc > 4) + if(argc > 4) { graphexporttimeout = argv[4]; + } - mesh = calloc(n, sizeof *mesh); + meshes = calloc(n, sizeof(*meshes)); - meshlink_set_log_cb(NULL, MESHLINK_WARNING, log_message); + meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_message); +#ifndef _WIN32 mkdir(basebase, 0750); +#else + mkdir(basebase); +#endif char filename[PATH_MAX]; char nodename[100]; + for(int i = 0; i < n; i++) { - snprintf(nodename, sizeof nodename, "%snode%d", namesprefix,i); - snprintf(filename, sizeof filename, "%s/%s", basebase, nodename); - bool itsnew = access(filename, R_OK); - mesh[i] = meshlink_open(filename, nodename, "manynodes", i%_DEV_CLASS_MAX); - meshlink_set_log_cb(mesh[i], MESHLINK_WARNING, log_message); - if(itsnew) - meshlink_add_address(mesh[i], "localhost"); - if(!mesh[i]) { + snprintf(nodename, sizeof(nodename), "%snode%d", namesprefix, i); + snprintf(filename, sizeof(filename), "%s/%s", basebase, nodename); + + if(n / (i + 1) > n / 4) { + meshes[i] = meshlink_open(filename, nodename, "manynodes", DEV_CLASS_BACKBONE); + } else { + meshes[i] = meshlink_open(filename, nodename, "manynodes", DEV_CLASS_PORTABLE); + } + + meshlink_set_log_cb(meshes[i], MESHLINK_DEBUG, log_message); + + if(!meshes[i]) { fprintf(stderr, "errno is: %d\n", meshlink_errno); fprintf(stderr, "Could not open %s: %s\n", filename, meshlink_strerror(meshlink_errno)); return 1; @@ -375,10 +469,11 @@ int main(int argc, char *argv[]) { int started = 0; for(int i = 0; i < n; i++) { - if(!meshlink_start(mesh[i])) + if(!meshlink_start(meshes[i])) { fprintf(stderr, "Could not start node %d: %s\n", i, meshlink_strerror(meshlink_errno)); - else + } else { started++; + } } if(!started) { @@ -386,21 +481,24 @@ int main(int argc, char *argv[]) { return 1; } - if(graphexporttimeout) - { exportmeshgraph_begin(graphexporttimeout); } + if(graphexporttimeout) { + exportmeshgraph_begin(graphexporttimeout); + } printf("%d nodes started.\nType /help for a list of commands.\n", started); // handle input - while(fgets(buf, sizeof buf, stdin)) + while(fgets(buf, sizeof(buf), stdin)) { parse_input(buf); + } - exportmeshgraph_end(NULL); + exportmeshgraph_end(); printf("Nodes stopping.\n"); - for(int i = 0; i < n; i++) - meshlink_close(mesh[i]); + for(int i = 0; i < n; i++) { + meshlink_close(meshes[i]); + } return 0; }