From 196806f90f40fcc0cf727abd4bed6bc5aefff5ff Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Thu, 27 Jul 2017 14:26:47 +0200 Subject: [PATCH] Add an astylerc file and reformat all code. This allows astyle to be used as a pre-commit hook. --- .astylerc | 5 + .gitignore | 2 + examples/channels.c | 28 +- examples/chat.c | 28 +- examples/chatpp.cc | 37 +- examples/manynodes.c | 132 ++--- examples/meshlinkapp.c | 2 +- src/conf.c | 25 +- src/conf.h | 2 +- src/connection.h | 32 +- src/devtools.c | 34 +- src/discovery.c | 996 ++++++++++++++++------------------- src/dropin.h | 16 +- src/ecdh.h | 4 +- src/ecdsa.h | 10 +- src/ecdsagen.h | 6 +- src/edge.h | 4 +- src/event.c | 12 +- src/event.h | 4 +- src/fake-getaddrinfo.c | 26 +- src/graph.c | 16 +- src/hash.c | 3 +- src/hash.h | 2 +- src/list.h | 2 +- src/logger.h | 2 +- src/meshlink++.h | 1103 +++++++++++++++++++-------------------- src/meshlink.c | 138 +++-- src/meshlink.h | 18 +- src/meshlink_internal.h | 6 +- src/meshlink_queue.h | 4 +- src/meta.c | 9 +- src/net.c | 304 +++++------ src/net_packet.c | 81 ++- src/net_setup.c | 13 +- src/net_socket.c | 39 +- src/netutl.c | 79 ++- src/netutl.h | 4 +- src/node.h | 2 +- src/prf.h | 2 +- src/protocol.c | 35 +- src/protocol.h | 2 +- src/protocol_auth.c | 171 +++--- src/protocol_edge.c | 34 +- src/protocol_key.c | 138 ++--- src/protocol_misc.c | 10 +- src/route.c | 2 +- src/splay_tree.c | 13 +- src/splay_tree.h | 4 +- src/sptps.c | 74 ++- src/sptps_keypair.c | 28 +- src/sptps_speed.c | 8 +- src/sptps_test.c | 105 ++-- src/utils.c | 68 +-- src/xalloc.h | 8 +- test/channels-fork.c | 2 +- test/channels.c | 18 +- test/echo-fork.c | 6 +- test/import-export.c | 2 +- test/invite-join.c | 2 +- 59 files changed, 1913 insertions(+), 2049 deletions(-) create mode 100644 .astylerc mode change 100755 => 100644 test/channels-fork.c mode change 100755 => 100644 test/echo-fork.c diff --git a/.astylerc b/.astylerc new file mode 100644 index 00000000..957d426c --- /dev/null +++ b/.astylerc @@ -0,0 +1,5 @@ +--indent=tab=8 +--convert-tabs +-xj +-A2 +-U diff --git a/.gitignore b/.gitignore index 36010ddd..ba18fee0 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ Makefile.in *~ .* !.gitignore +!.gitmodules +!.astylerc core core.* /config.* diff --git a/examples/channels.c b/examples/channels.c index 1fceb0b4..c0c7210d 100644 --- a/examples/channels.c +++ b/examples/channels.c @@ -123,9 +123,9 @@ static void parse_command(meshlink_handle_t *mesh, char *buf) { } else if(!strcasecmp(buf, "who")) { if(!arg) { nodes = meshlink_get_all_nodes(mesh, nodes, &nnodes); - if(!nnodes) { + if(!nnodes) fprintf(stderr, "Could not get list of nodes: %s\n", meshlink_strerror(meshlink_errno)); - } else { + else { printf("%zu known nodes:", nnodes); for(int i = 0; i < nnodes; i++) printf(" %s", nodes[i]->name); @@ -133,28 +133,26 @@ static void parse_command(meshlink_handle_t *mesh, char *buf) { } } else { meshlink_node_t *node = meshlink_get_node(mesh, arg); - if(!node) { + if(!node) fprintf(stderr, "Error looking up '%s': %s\n", arg, meshlink_strerror(meshlink_errno)); - } else { + else printf("Node %s found\n", arg); - } } } 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" - "/quit Exit this program.\n" - ); - } else { + ": 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" + "/quit Exit this program.\n" + ); + } else fprintf(stderr, "Unknown command '/%s'\n", buf); - } } static void parse_input(meshlink_handle_t *mesh, char *buf) { diff --git a/examples/chat.c b/examples/chat.c index 37e06734..4d65d10e 100644 --- a/examples/chat.c +++ b/examples/chat.c @@ -89,9 +89,9 @@ static void parse_command(meshlink_handle_t *mesh, char *buf) { } else if(!strcasecmp(buf, "who")) { if(!arg) { nodes = meshlink_get_all_nodes(mesh, nodes, &nnodes); - if(!nnodes) { + if(!nnodes) fprintf(stderr, "Could not get list of nodes: %s\n", meshlink_strerror(meshlink_errno)); - } else { + else { printf("%zu known nodes:", nnodes); for(int i = 0; i < nnodes; i++) printf(" %s", nodes[i]->name); @@ -99,28 +99,26 @@ static void parse_command(meshlink_handle_t *mesh, char *buf) { } } else { meshlink_node_t *node = meshlink_get_node(mesh, arg); - if(!node) { + if(!node) fprintf(stderr, "Error looking up '%s': %s\n", arg, meshlink_strerror(meshlink_errno)); - } else { + else printf("Node %s found\n", arg); - } } } 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" - "/quit Exit this program.\n" - ); - } else { + ": 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" + "/quit Exit this program.\n" + ); + } else fprintf(stderr, "Unknown command '/%s'\n", buf); - } } static void parse_input(meshlink_handle_t *mesh, char *buf) { diff --git a/examples/chatpp.cc b/examples/chatpp.cc index 97f87406..8c925231 100644 --- a/examples/chatpp.cc +++ b/examples/chatpp.cc @@ -4,22 +4,21 @@ #include #include "../src/meshlink++.h" -class ChatMesh : public meshlink::mesh -{ +class ChatMesh : public meshlink::mesh { public: void log(meshlink::log_level_t level, const char *text) { const char *levelstr[] = {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}; fprintf(stderr, "%s: %s\n", levelstr[level], text); - } + } void receive(meshlink::node *source, const void *data, size_t len) { const char *msg = (const char *)data; - + if(!len || msg[len - 1]) { fprintf(stderr, "Received invalid data from %s\n", source->name); return; } - + printf("%s says: %s\n", source->name, msg); } @@ -90,9 +89,9 @@ static void parse_command(meshlink::mesh *mesh, char *buf) { } else if(!strcasecmp(buf, "who")) { if(!arg) { nodes = mesh->get_all_nodes(nodes, &nnodes); - if(!nodes) { + if(!nodes) fprintf(stderr, "Could not get list of nodes: %s\n", meshlink::strerror()); - } else { + else { printf("%zu known nodes:", nnodes); for(size_t i = 0; i < nnodes; i++) printf(" %s", nodes[i]->name); @@ -100,28 +99,26 @@ static void parse_command(meshlink::mesh *mesh, char *buf) { } } else { meshlink::node *node = mesh->get_node(arg); - if(!node) { + if(!node) fprintf(stderr, "Error looking up '%s': %s\n", arg, meshlink::strerror()); - } else { + else printf("Node %s found\n", arg); - } } } 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" - "/quit Exit this program.\n" - ); - } else { + ": 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" + "/quit Exit this program.\n" + ); + } else fprintf(stderr, "Unknown command '/%s'\n", buf); - } } static void parse_input(meshlink::mesh *mesh, char *buf) { diff --git a/examples/manynodes.c b/examples/manynodes.c index 0aafbcef..0089c206 100644 --- a/examples/manynodes.c +++ b/examples/manynodes.c @@ -41,24 +41,23 @@ static void log_message(meshlink_handle_t *mesh, meshlink_log_level_t level, con } //Test mesh sending data -static void testmesh () { +static void testmesh() { 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(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)); } + } + } } // Make all nodes know about each other by importing each others public keys and addresses. @@ -77,31 +76,27 @@ static void linkmesh() { } } -static bool exportmeshgraph(const char* path) -{ +static bool exportmeshgraph(const char* path) { struct stat ps; int psr = stat(path, &ps); - if(psr == 0 || errno != ENOENT) - { + if(psr == 0 || errno != ENOENT) { if(psr == -1) - { perror("stat"); } + perror("stat"); else - { fprintf(stderr, "%s exists already\n", path); } + fprintf(stderr, "%s exists already\n", path); return false; } 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(mesh[0], stream)) { fclose(stream); fprintf(stderr, "could not export graph\n"); return false; @@ -112,8 +107,7 @@ static bool exportmeshgraph(const char* path) } -void exportmeshgraph_timer(int signum) -{ +void exportmeshgraph_timer(int signum) { struct timeval ts; gettimeofday(&ts, NULL); @@ -126,26 +120,23 @@ void exportmeshgraph_timer(int signum) #ifndef _WIN32 static bool exportmeshgraph_started = false; -static bool exportmeshgraph_end(const char* none) -{ +static bool exportmeshgraph_end(const char* none) { if(!exportmeshgraph_started) - { return false; } + return false; 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) -{ +static bool exportmeshgraph_begin(const char* timeout_str) { if(!timeout_str) return false; - if(exportmeshgraph_started) - { + if(exportmeshgraph_started) { if(!exportmeshgraph_end(NULL)) return false; } @@ -154,7 +145,7 @@ static bool exportmeshgraph_begin(const char* timeout_str) int timeout = atoi(timeout_str); if(timeout < 100) - { timeout = 100; } + timeout = 100; int timeout_sec = timeout / 1000; int timeout_msec = timeout % 1000; @@ -172,20 +163,18 @@ 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(const char* none) -{ +static bool exportmeshgraph_end(const char* none) { return false; } -static bool exportmeshgraph_begin(const char* timeout_str) -{ +static bool exportmeshgraph_begin(const char* timeout_str) { return false; } #endif @@ -219,9 +208,8 @@ static void parse_command(char *buf) { meshlink_stop(mesh[nodeindex]); if(!meshlink_join(mesh[nodeindex], arg)) fprintf(stderr, "Could not join using invitation: %s\n", meshlink_strerror(meshlink_errno)); - else { + else fprintf(stderr, "Invitation accepted!\n"); - } if(!meshlink_start(mesh[nodeindex])) { fprintf(stderr, "Could not restart MeshLink: %s\n", meshlink_strerror(meshlink_errno)); exit(1); @@ -244,9 +232,9 @@ static void parse_command(char *buf) { } else if(!strcasecmp(buf, "who")) { if(!arg) { nodes = meshlink_get_all_nodes(mesh[nodeindex], nodes, &nnodes); - if(!nodes) { + if(!nodes) fprintf(stderr, "Could not get list of nodes: %s\n", meshlink_strerror(meshlink_errno)); - } else { + else { printf("%zu known nodes:", nnodes); for(int i = 0; i < nnodes; i++) printf(" %s", nodes[i]->name); @@ -254,52 +242,50 @@ static void parse_command(char *buf) { } } else { meshlink_node_t *node = meshlink_get_node(mesh[nodeindex], arg); - if(!node) { + if(!node) fprintf(stderr, "Unknown node '%s'\n", arg); - } else { + else printf("Node %s found, pmtu %zd\n", arg, meshlink_get_pmtu(mesh[nodeindex], node)); - } } - } else if(!strcasecmp(buf, "link")) { + } else if(!strcasecmp(buf, "link")) linkmesh(); - } else if(!strcasecmp(buf, "eg")) { + else if(!strcasecmp(buf, "eg")) exportmeshgraph(arg); - } else if(!strcasecmp(buf, "egb")) { + else if(!strcasecmp(buf, "egb")) exportmeshgraph_begin(arg); - } else if(!strcasecmp(buf, "ege")) { + else if(!strcasecmp(buf, "ege")) exportmeshgraph_end(NULL); - } else if(!strcasecmp(buf, "test")) { + else if(!strcasecmp(buf, "test")) testmesh(); - } else if(!strcasecmp(buf, "select")) { + 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")) { + } else if(!strcasecmp(buf, "stop")) meshlink_stop(mesh[nodeindex]); - } else if(!strcasecmp(buf, "quit")) { + 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" - "/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 { + ": 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); - } } static void parse_input(char *buf) { @@ -397,12 +383,10 @@ int main(int argc, char *argv[]) { snprintf(nodename, sizeof nodename, "%snode%d", namesprefix,i); snprintf(filename, sizeof filename, "%s/%s", basebase, nodename); bool itsnew = access(filename, R_OK); - if (n/(i+1) > n/4) { + if(n/(i+1) > n/4) mesh[i] = meshlink_open(filename, nodename, "manynodes", DEV_CLASS_BACKBONE); - } - else { + else mesh[i] = meshlink_open(filename, nodename, "manynodes", DEV_CLASS_PORTABLE); - } meshlink_set_log_cb(mesh[i], MESHLINK_DEBUG, log_message); if(!mesh[i]) { fprintf(stderr, "errno is: %d\n", meshlink_errno); @@ -426,7 +410,7 @@ int main(int argc, char *argv[]) { } if(graphexporttimeout) - { exportmeshgraph_begin(graphexporttimeout); } + exportmeshgraph_begin(graphexporttimeout); printf("%d nodes started.\nType /help for a list of commands.\n", started); diff --git a/examples/meshlinkapp.c b/examples/meshlinkapp.c index d9e5b7e0..cb15cae8 100644 --- a/examples/meshlinkapp.c +++ b/examples/meshlinkapp.c @@ -6,7 +6,7 @@ void handle_recv_data(meshlink_handle_t *mesh, meshlink_node_t *source, void *da printf("Received %zu bytes from %s: %s\n", len, source->name, (char*)data); } -int main(int argc , char **argv){ +int main(int argc, char **argv) { char *confbase = argc > 1 ? argv[1] : "/tmp/meshlink/"; char *name = argc > 2 ? argv[2] : "foo"; diff --git a/src/conf.c b/src/conf.c index af8b0b0e..426f6dc4 100644 --- a/src/conf.c +++ b/src/conf.c @@ -127,7 +127,7 @@ bool get_config_bool(const config_t *cfg, bool *result) { } logger(NULL, MESHLINK_ERROR, "\"yes\" or \"no\" expected for configuration variable %s in %s line %d", - cfg->variable, cfg->file, cfg->line); + cfg->variable, cfg->file, cfg->line); return false; } @@ -140,13 +140,12 @@ bool get_config_int(const config_t *cfg, int *result) { return true; logger(NULL, MESHLINK_ERROR, "Integer expected for configuration variable %s in %s line %d", - cfg->variable, cfg->file, cfg->line); + cfg->variable, cfg->file, cfg->line); return false; } -bool set_config_int(config_t *cfg, int val) -{ +bool set_config_int(config_t *cfg, int val) { if(!cfg) return false; @@ -170,8 +169,7 @@ bool get_config_string(const config_t *cfg, char **result) { return true; } -bool set_config_string(config_t *cfg, const char* val) -{ +bool set_config_string(config_t *cfg, const char* val) { if(!cfg) return false; @@ -197,7 +195,7 @@ bool get_config_address(const config_t *cfg, struct addrinfo **result) { } logger(NULL, MESHLINK_ERROR, "Hostname or IP address expected for configuration variable %s in %s line %d", - cfg->variable, cfg->file, cfg->line); + cfg->variable, cfg->file, cfg->line); return false; } @@ -252,7 +250,7 @@ config_t *parse_config_line(char *line, const char *fname, int lineno) { if(!*value) { const char err[] = "No value for variable"; logger(NULL, MESHLINK_ERROR, "%s `%s' on line %d while reading config file %s", - err, variable, lineno, fname); + err, variable, lineno, fname); return NULL; } @@ -311,7 +309,7 @@ bool read_config_file(splay_tree_t *config_tree, const char *fname) { } cfg = parse_config_line(line, fname, lineno); - if (!cfg) + if(!cfg) break; config_add(config_tree, cfg); } @@ -321,8 +319,7 @@ bool read_config_file(splay_tree_t *config_tree, const char *fname) { return result; } -bool write_config_file(const struct splay_tree_t *config_tree, const char *fname) -{ +bool write_config_file(const struct splay_tree_t *config_tree, const char *fname) { FILE *fp; fp = fopen(fname, "w+"); @@ -332,8 +329,7 @@ bool write_config_file(const struct splay_tree_t *config_tree, const char *fname return false; } - for splay_each(config_t, cnf, config_tree) - { + for splay_each(config_t, cnf, config_tree) { if(fwrite(cnf->variable, sizeof(char), strlen(cnf->variable), fp) < strlen(cnf->variable)) goto error; @@ -380,8 +376,7 @@ bool read_host_config(meshlink_handle_t *mesh, splay_tree_t *config_tree, const return x; } -bool write_host_config(struct meshlink_handle *mesh, const struct splay_tree_t *config_tree, const char *name) -{ +bool write_host_config(struct meshlink_handle *mesh, const struct splay_tree_t *config_tree, const char *name) { char filename[PATH_MAX]; snprintf(filename,PATH_MAX, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name); diff --git a/src/conf.h b/src/conf.h index 46f1c89e..74849a21 100644 --- a/src/conf.h +++ b/src/conf.h @@ -33,7 +33,7 @@ typedef struct config_t { extern void init_configuration(struct splay_tree_t **); extern void exit_configuration(struct splay_tree_t **); -extern config_t *new_config(void) __attribute__ ((__malloc__)); +extern config_t *new_config(void) __attribute__((__malloc__)); extern void free_config(config_t *); extern void config_add(struct splay_tree_t *, config_t *); extern config_t *lookup_config(struct splay_tree_t *, char *); diff --git a/src/connection.h b/src/connection.h index c3c219be..a79d6b13 100644 --- a/src/connection.h +++ b/src/connection.h @@ -31,21 +31,21 @@ #define OPTION_VERSION(x) ((x) >> 24) /* Top 8 bits are for protocol minor version */ typedef struct connection_status_t { - unsigned int pinged:1; /* sent ping */ - unsigned int active:1; /* 1 if active.. */ - unsigned int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */ - unsigned int unused_termreq:1; /* the termination of this connection was requested */ - unsigned int remove_unused:1; /* Set to 1 if you want this connection removed */ - unsigned int timeout_unused:1; /* 1 if gotten timeout */ - unsigned int unused_encryptout:1; /* 1 if we can encrypt outgoing traffic */ - unsigned int unused_decryptin:1; /* 1 if we have to decrypt incoming traffic */ - unsigned int mst:1; /* 1 if this connection is part of a minimum spanning tree */ - unsigned int control:1; /* 1 if this is a control connection */ - unsigned int pcap:1; /* 1 if this is a control connection requesting packet capture */ - unsigned int log:1; /* 1 if this is a control connection requesting log dump */ - unsigned int invitation:1; /* 1 if this is an invitation */ - unsigned int invitation_used:1; /* 1 if the invitation has been consumed */ - unsigned int unused:19; + unsigned int pinged:1; /* sent ping */ + unsigned int active:1; /* 1 if active.. */ + unsigned int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */ + unsigned int unused_termreq:1; /* the termination of this connection was requested */ + unsigned int remove_unused:1; /* Set to 1 if you want this connection removed */ + unsigned int timeout_unused:1; /* 1 if gotten timeout */ + unsigned int unused_encryptout:1; /* 1 if we can encrypt outgoing traffic */ + unsigned int unused_decryptin:1; /* 1 if we have to decrypt incoming traffic */ + unsigned int mst:1; /* 1 if this connection is part of a minimum spanning tree */ + unsigned int control:1; /* 1 if this is a control connection */ + unsigned int pcap:1; /* 1 if this is a control connection requesting packet capture */ + unsigned int log:1; /* 1 if this is a control connection requesting log dump */ + unsigned int invitation:1; /* 1 if this is an invitation */ + unsigned int invitation_used:1; /* 1 if the invitation has been consumed */ + unsigned int unused:19; } connection_status_t; #include "ecdsa.h" @@ -89,7 +89,7 @@ typedef struct connection_t { extern void init_connections(struct meshlink_handle *mesh); extern void exit_connections(struct meshlink_handle *mesh); -extern connection_t *new_connection(void) __attribute__ ((__malloc__)); +extern connection_t *new_connection(void) __attribute__((__malloc__)); extern void free_connection(connection_t *); extern void connection_add(struct meshlink_handle *mesh, connection_t *); extern void connection_del(struct meshlink_handle *mesh, connection_t *); diff --git a/src/devtools.c b/src/devtools.c index 2102e9bc..1cb2d5e8 100644 --- a/src/devtools.c +++ b/src/devtools.c @@ -10,8 +10,7 @@ #include "devtools.h" -static int node_compare(const void *a, const void *b) -{ +static int node_compare(const void *a, const void *b) { if(a < b) return -1; @@ -21,8 +20,7 @@ static int node_compare(const void *a, const void *b) return 0; } -static bool fstrwrite(const char* str, FILE* stream) -{ +static bool fstrwrite(const char* str, FILE* stream) { size_t len = strlen(str); if(fwrite((void*)str, 1, len, stream) != len) @@ -31,9 +29,8 @@ static bool fstrwrite(const char* str, FILE* stream) return true; } -static const char* __itoa(int value) -{ - static char buffer[sizeof(int) * 8 + 1]; // not thread safe +static const char* __itoa(int value) { + static char buffer[sizeof(int) * 8 + 1]; // not thread safe if(snprintf(buffer, sizeof(buffer), "%d", value) == -1) return ""; @@ -41,8 +38,7 @@ static const char* __itoa(int value) return buffer; } -bool devtool_export_json_all_edges_state(meshlink_handle_t *mesh, FILE* stream) -{ +bool devtool_export_json_all_edges_state(meshlink_handle_t *mesh, FILE* stream) { bool result = true; pthread_mutex_lock(&(mesh->mesh_mutex)); @@ -55,7 +51,7 @@ bool devtool_export_json_all_edges_state(meshlink_handle_t *mesh, FILE* stream) meshlink_edge_t **edges = meshlink_get_all_edges_state(mesh, NULL, &edge_count); if((!nodes && node_count != 0) || (!edges && edge_count != 0)) - { goto fail; } + goto fail; // export begin if(!fstrwrite("{\n", stream)) @@ -65,8 +61,7 @@ bool devtool_export_json_all_edges_state(meshlink_handle_t *mesh, FILE* stream) if(!fstrwrite("\t\"nodes\": {\n", stream)) goto fail; - for(size_t i = 0; i < node_count; ++i) - { + for(size_t i = 0; i < node_count; ++i) { if(!fstrwrite("\t\t\"", stream) || !fstrwrite(((node_t*)nodes[i])->name, stream) || !fstrwrite("\": {\n", stream)) goto fail; @@ -91,8 +86,7 @@ bool devtool_export_json_all_edges_state(meshlink_handle_t *mesh, FILE* stream) if(!fstrwrite("\t\"edges\": {\n", stream)) goto fail; - for(size_t i = 0; i < edge_count; ++i) - { + for(size_t i = 0; i < edge_count; ++i) { if(!fstrwrite("\t\t\"", stream) || !fstrwrite(edges[i]->from->name, stream) || !fstrwrite("_to_", stream) || !fstrwrite(edges[i]->to->name, stream) || !fstrwrite("\": {\n", stream)) goto fail; @@ -105,15 +99,13 @@ bool devtool_export_json_all_edges_state(meshlink_handle_t *mesh, FILE* stream) char *host = NULL, *port = NULL, *address = NULL; sockaddr2str((const sockaddr_t *)&(edges[i]->address), &host, &port); - if(host && port) { + if(host && port) xasprintf(&address, "{ \"host\": \"%s\", \"port\": %s }", host, port); - } free(host); free(port); - if(!fstrwrite("\t\t\t\"address\": ", stream) || !fstrwrite(address ? address : "null", stream) || !fstrwrite(",\n", stream)) - { + if(!fstrwrite("\t\t\t\"address\": ", stream) || !fstrwrite(address ? address : "null", stream) || !fstrwrite(",\n", stream)) { free(address); goto fail; } @@ -146,13 +138,13 @@ fail: done: if(nodes) - { free(nodes); } + free(nodes); for(size_t i = 0; edges && i < edge_count; ++i) - { free(edges[i]); } + free(edges[i]); if(nodes) - { free(edges); } + free(edges); pthread_mutex_unlock(&(mesh->mesh_mutex)); diff --git a/src/discovery.c b/src/discovery.c index b6ed37c5..885b2bfd 100644 --- a/src/discovery.c +++ b/src/discovery.c @@ -20,509 +20,448 @@ #define MESHLINK_MDNS_NAME_KEY "name" #define MESHLINK_MDNS_FINGERPRINT_KEY "fingerprint" -static void generate_rand_string(char* buffer, size_t size) -{ - for(size_t i = 0; i < (size - 1); ++i) - { - buffer[i] = 'a' + (rand() % ('z' - 'a' + 1)); - } - - buffer[size-1] = '\0'; +static void generate_rand_string(char* buffer, size_t size) { + for(size_t i = 0; i < (size - 1); ++i) + buffer[i] = 'a' + (rand() % ('z' - 'a' + 1)); + + buffer[size-1] = '\0'; } -static void discovery_entry_group_callback(CattaServer *server, CattaSEntryGroup *group, CattaEntryGroupState state, void *userdata) -{ - meshlink_handle_t *mesh = userdata; - - // asserts - assert(mesh != NULL); - assert(mesh->catta_server != NULL); - assert(mesh->catta_poll != NULL); - - pthread_mutex_lock(&(mesh->mesh_mutex)); - - /* Called whenever the entry group state changes */ - switch(state) - { - case CATTA_ENTRY_GROUP_ESTABLISHED: - /* The entry group has been established successfully */ - logger(mesh, MESHLINK_DEBUG, "Catta Service successfully established.\n"); - break; - - case CATTA_ENTRY_GROUP_COLLISION: - logger(mesh, MESHLINK_WARNING, "Catta Service collision.\n"); - // @TODO can we just set a new name and retry? - break; - - case CATTA_ENTRY_GROUP_FAILURE : - /* Some kind of failure happened while we were registering our services */ - logger(mesh, MESHLINK_ERROR, "Catta Entry group failure: %s\n", catta_strerror(catta_server_errno(mesh->catta_server))); - catta_simple_poll_quit(mesh->catta_poll); - break; - - case CATTA_ENTRY_GROUP_UNCOMMITED: - case CATTA_ENTRY_GROUP_REGISTERING: - ; - } - - pthread_mutex_unlock(&(mesh->mesh_mutex)); +static void discovery_entry_group_callback(CattaServer *server, CattaSEntryGroup *group, CattaEntryGroupState state, void *userdata) { + meshlink_handle_t *mesh = userdata; + + // asserts + assert(mesh != NULL); + assert(mesh->catta_server != NULL); + assert(mesh->catta_poll != NULL); + + pthread_mutex_lock(&(mesh->mesh_mutex)); + + /* Called whenever the entry group state changes */ + switch(state) { + case CATTA_ENTRY_GROUP_ESTABLISHED: + /* The entry group has been established successfully */ + logger(mesh, MESHLINK_DEBUG, "Catta Service successfully established.\n"); + break; + + case CATTA_ENTRY_GROUP_COLLISION: + logger(mesh, MESHLINK_WARNING, "Catta Service collision.\n"); + // @TODO can we just set a new name and retry? + break; + + case CATTA_ENTRY_GROUP_FAILURE : + /* Some kind of failure happened while we were registering our services */ + logger(mesh, MESHLINK_ERROR, "Catta Entry group failure: %s\n", catta_strerror(catta_server_errno(mesh->catta_server))); + catta_simple_poll_quit(mesh->catta_poll); + break; + + case CATTA_ENTRY_GROUP_UNCOMMITED: + case CATTA_ENTRY_GROUP_REGISTERING: + ; + } + + pthread_mutex_unlock(&(mesh->mesh_mutex)); } -static void discovery_create_services(meshlink_handle_t *mesh) -{ - char *txt_name = NULL; - - // asserts - assert(mesh != NULL); - assert(mesh->name != NULL); - assert(mesh->myport != NULL); - assert(mesh->catta_server != NULL); - assert(mesh->catta_poll != NULL); - assert(mesh->catta_servicetype != NULL); - assert(mesh->self != NULL); - - pthread_mutex_lock(&(mesh->mesh_mutex)); - - logger(mesh, MESHLINK_DEBUG, "Adding service\n"); - - /* Ifthis is the first time we're called, let's create a new entry group */ - if(!mesh->catta_group) - { - if(!(mesh->catta_group = catta_s_entry_group_new(mesh->catta_server, discovery_entry_group_callback, mesh))) - { - logger(mesh, MESHLINK_ERROR, "catta_entry_group_new() failed: %s\n", catta_strerror(catta_server_errno(mesh->catta_server))); - goto fail; - } - } - - /* Create txt records */ - size_t txt_name_len = sizeof(MESHLINK_MDNS_NAME_KEY) + 1 + strlen(mesh->name) + 1; - txt_name = malloc(txt_name_len); - - if(txt_name == NULL) - { - logger(mesh, MESHLINK_ERROR, "Could not allocate memory for TXT record\n"); - goto fail; - } - - snprintf(txt_name, txt_name_len, "%s=%s", MESHLINK_MDNS_NAME_KEY, mesh->name); - - char txt_fingerprint[sizeof(MESHLINK_MDNS_FINGERPRINT_KEY) + 1 + MESHLINK_FINGERPRINTLEN + 1]; - snprintf(txt_fingerprint, sizeof(txt_fingerprint), "%s=%s", MESHLINK_MDNS_FINGERPRINT_KEY, meshlink_get_fingerprint(mesh, (meshlink_node_t *)mesh->self)); - - /* Add the service */ - int ret = 0; - if((ret = catta_server_add_service(mesh->catta_server, mesh->catta_group, CATTA_IF_UNSPEC, CATTA_PROTO_UNSPEC, 0, meshlink_get_fingerprint(mesh, (meshlink_node_t *)mesh->self), mesh->catta_servicetype, NULL, NULL, atoi(mesh->myport), txt_name, txt_fingerprint, NULL)) < 0) - { - logger(mesh, MESHLINK_ERROR, "Failed to add service: %s\n", catta_strerror(ret)); - goto fail; - } - - /* Tell the server to register the service */ - if((ret = catta_s_entry_group_commit(mesh->catta_group)) < 0) - { - logger(mesh, MESHLINK_ERROR, "Failed to commit entry_group: %s\n", catta_strerror(ret)); - goto fail; - } - - goto done; +static void discovery_create_services(meshlink_handle_t *mesh) { + char *txt_name = NULL; + + // asserts + assert(mesh != NULL); + assert(mesh->name != NULL); + assert(mesh->myport != NULL); + assert(mesh->catta_server != NULL); + assert(mesh->catta_poll != NULL); + assert(mesh->catta_servicetype != NULL); + assert(mesh->self != NULL); + + pthread_mutex_lock(&(mesh->mesh_mutex)); + + logger(mesh, MESHLINK_DEBUG, "Adding service\n"); + + /* Ifthis is the first time we're called, let's create a new entry group */ + if(!mesh->catta_group) { + if(!(mesh->catta_group = catta_s_entry_group_new(mesh->catta_server, discovery_entry_group_callback, mesh))) { + logger(mesh, MESHLINK_ERROR, "catta_entry_group_new() failed: %s\n", catta_strerror(catta_server_errno(mesh->catta_server))); + goto fail; + } + } + + /* Create txt records */ + size_t txt_name_len = sizeof(MESHLINK_MDNS_NAME_KEY) + 1 + strlen(mesh->name) + 1; + txt_name = malloc(txt_name_len); + + if(txt_name == NULL) { + logger(mesh, MESHLINK_ERROR, "Could not allocate memory for TXT record\n"); + goto fail; + } + + snprintf(txt_name, txt_name_len, "%s=%s", MESHLINK_MDNS_NAME_KEY, mesh->name); + + char txt_fingerprint[sizeof(MESHLINK_MDNS_FINGERPRINT_KEY) + 1 + MESHLINK_FINGERPRINTLEN + 1]; + snprintf(txt_fingerprint, sizeof(txt_fingerprint), "%s=%s", MESHLINK_MDNS_FINGERPRINT_KEY, meshlink_get_fingerprint(mesh, (meshlink_node_t *)mesh->self)); + + /* Add the service */ + int ret = 0; + if((ret = catta_server_add_service(mesh->catta_server, mesh->catta_group, CATTA_IF_UNSPEC, CATTA_PROTO_UNSPEC, 0, meshlink_get_fingerprint(mesh, (meshlink_node_t *)mesh->self), mesh->catta_servicetype, NULL, NULL, atoi(mesh->myport), txt_name, txt_fingerprint, NULL)) < 0) { + logger(mesh, MESHLINK_ERROR, "Failed to add service: %s\n", catta_strerror(ret)); + goto fail; + } + + /* Tell the server to register the service */ + if((ret = catta_s_entry_group_commit(mesh->catta_group)) < 0) { + logger(mesh, MESHLINK_ERROR, "Failed to commit entry_group: %s\n", catta_strerror(ret)); + goto fail; + } + + goto done; fail: - catta_simple_poll_quit(mesh->catta_poll); + catta_simple_poll_quit(mesh->catta_poll); done: - if(txt_name) - { free(txt_name); } + if(txt_name) + free(txt_name); - pthread_mutex_unlock(&(mesh->mesh_mutex)); + pthread_mutex_unlock(&(mesh->mesh_mutex)); } -static void discovery_server_callback(CattaServer *server, CattaServerState state, void * userdata) -{ +static void discovery_server_callback(CattaServer *server, CattaServerState state, void * userdata) { meshlink_handle_t *mesh = userdata; - // asserts - assert(mesh != NULL); - - pthread_mutex_lock(&(mesh->mesh_mutex)); - - switch(state) - { - case CATTA_SERVER_RUNNING: - { - /* The serve has startup successfully and registered its host - * name on the network, so it's time to create our services */ - if(!mesh->catta_group) - { - discovery_create_services(mesh); - } - } - break; - - case CATTA_SERVER_COLLISION: - { - // asserts - assert(mesh->catta_server != NULL); - assert(mesh->catta_poll != NULL); - - /* A host name collision happened. Let's pick a new name for the server */ - char hostname[17]; - generate_rand_string(hostname, sizeof(hostname)); - - logger(mesh, MESHLINK_WARNING, "Catta host name collision, retrying with '%s'\n", hostname); - int result = catta_server_set_host_name(mesh->catta_server, hostname); - - if(result < 0) - { - logger(mesh, MESHLINK_ERROR, "Catta failed to set new host name: %s\n", catta_strerror(result)); - catta_simple_poll_quit(mesh->catta_poll); - } - } - break; - - case CATTA_SERVER_REGISTERING: - { - /* Let's drop our registered services. When the server is back - * in CATTA_SERVER_RUNNING state we will register them - * again with the new host name. */ - if(mesh->catta_group) - { - catta_s_entry_group_reset(mesh->catta_group); - mesh->catta_group = NULL; - } - } - break; - - case CATTA_SERVER_FAILURE: - { - // asserts - assert(mesh->catta_server != NULL); - assert(mesh->catta_poll != NULL); - - /* Terminate on failure */ - logger(mesh, MESHLINK_ERROR, "Catta server failure: %s\n", catta_strerror(catta_server_errno(mesh->catta_server))); - catta_simple_poll_quit(mesh->catta_poll); - } - break; - - case CATTA_SERVER_INVALID: - break; - } - - pthread_mutex_unlock(&(mesh->mesh_mutex)); + // asserts + assert(mesh != NULL); + + pthread_mutex_lock(&(mesh->mesh_mutex)); + + switch(state) { + case CATTA_SERVER_RUNNING: { + /* The serve has startup successfully and registered its host + * name on the network, so it's time to create our services */ + if(!mesh->catta_group) + discovery_create_services(mesh); + } + break; + + case CATTA_SERVER_COLLISION: { + // asserts + assert(mesh->catta_server != NULL); + assert(mesh->catta_poll != NULL); + + /* A host name collision happened. Let's pick a new name for the server */ + char hostname[17]; + generate_rand_string(hostname, sizeof(hostname)); + + logger(mesh, MESHLINK_WARNING, "Catta host name collision, retrying with '%s'\n", hostname); + int result = catta_server_set_host_name(mesh->catta_server, hostname); + + if(result < 0) { + logger(mesh, MESHLINK_ERROR, "Catta failed to set new host name: %s\n", catta_strerror(result)); + catta_simple_poll_quit(mesh->catta_poll); + } + } + break; + + case CATTA_SERVER_REGISTERING: { + /* Let's drop our registered services. When the server is back + * in CATTA_SERVER_RUNNING state we will register them + * again with the new host name. */ + if(mesh->catta_group) { + catta_s_entry_group_reset(mesh->catta_group); + mesh->catta_group = NULL; + } + } + break; + + case CATTA_SERVER_FAILURE: { + // asserts + assert(mesh->catta_server != NULL); + assert(mesh->catta_poll != NULL); + + /* Terminate on failure */ + logger(mesh, MESHLINK_ERROR, "Catta server failure: %s\n", catta_strerror(catta_server_errno(mesh->catta_server))); + catta_simple_poll_quit(mesh->catta_poll); + } + break; + + case CATTA_SERVER_INVALID: + break; + } + + pthread_mutex_unlock(&(mesh->mesh_mutex)); } -static void discovery_resolve_callback(CattaSServiceResolver *resolver, CattaIfIndex interface_, CattaProtocol protocol, CattaResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const CattaAddress *address, uint16_t port, CattaStringList *txt, CattaLookupResultFlags flags, void *userdata) -{ - meshlink_handle_t *mesh = userdata; - - // asserts - assert(resolver != NULL); - assert(mesh != NULL); - assert(mesh->catta_server != NULL); - - pthread_mutex_lock(&(mesh->mesh_mutex)); - - /* Called whenever a service has been resolved successfully or timed out */ - switch(event) - { - case CATTA_RESOLVER_FAILURE: - { - // asserts - assert(name != NULL); - assert(type != NULL); - assert(domain != NULL); - - logger(mesh, MESHLINK_WARNING, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, catta_strerror(catta_server_errno(mesh->catta_server))); - } - break; - - case CATTA_RESOLVER_FOUND: - { - // asserts - assert(name != NULL); - assert(type != NULL); - assert(domain != NULL); - assert(host_name != NULL); - assert(address != NULL); - assert(txt != NULL); - - char straddr[CATTA_ADDRESS_STR_MAX], *strtxt; - - logger(mesh, MESHLINK_DEBUG, "(Resolver) Service '%s' of type '%s' in domain '%s':\n", name, type, domain); - - catta_address_snprint(straddr, sizeof(straddr), address); - strtxt = catta_string_list_to_string(txt); - logger(mesh, MESHLINK_DEBUG, - "\t%s:%u (%s)\n" - "\tTXT=%s\n" - "\tcookie is %u\n" - "\tis_local: %i\n" - "\twide_area: %i\n" - "\tmulticast: %i\n" - "\tcached: %i\n", - host_name, port, straddr, - strtxt, - catta_string_list_get_service_cookie(txt), - !!(flags & CATTA_LOOKUP_RESULT_LOCAL), - !!(flags & CATTA_LOOKUP_RESULT_WIDE_AREA), - !!(flags & CATTA_LOOKUP_RESULT_MULTICAST), - !!(flags & CATTA_LOOKUP_RESULT_CACHED)); - catta_free(strtxt); - - // retrieve fingerprint - CattaStringList *node_name_li = catta_string_list_find(txt, MESHLINK_MDNS_NAME_KEY); - CattaStringList *node_fp_li = catta_string_list_find(txt, MESHLINK_MDNS_FINGERPRINT_KEY); - - if(node_name_li != NULL && node_fp_li != NULL) - { - char *node_name = (char*)catta_string_list_get_text(node_name_li) + strlen(MESHLINK_MDNS_NAME_KEY); - char *node_fp = (char*)catta_string_list_get_text(node_fp_li) + strlen(MESHLINK_MDNS_FINGERPRINT_KEY); - - if(node_name[0] == '=' && node_fp[0] == '=') - { - node_name += 1; - node_fp += 1; - - meshlink_node_t *node = meshlink_get_node(mesh, node_name); - - if(node != NULL) - { - logger(mesh, MESHLINK_INFO, "Node %s is part of the mesh network.\n", node->name); - - sockaddr_t naddress; - memset(&naddress, 0, sizeof(naddress)); - - switch(address->proto) - { - case CATTA_PROTO_INET: - { - naddress.in.sin_family = AF_INET; - naddress.in.sin_port = htons(port); - naddress.in.sin_addr.s_addr = address->data.ipv4.address; - } - break; - - case CATTA_PROTO_INET6: - { - naddress.in6.sin6_family = AF_INET6; - naddress.in6.sin6_port = htons(port); - memcpy(naddress.in6.sin6_addr.s6_addr, address->data.ipv6.address, sizeof(naddress.in6.sin6_addr.s6_addr)); - } - break; - - default: - naddress.unknown.family = AF_UNKNOWN; - break; - } - - if(naddress.unknown.family != AF_UNKNOWN) - { - meshlink_hint_address(mesh, (meshlink_node_t *)node, (struct sockaddr*)&naddress); - } - else - { - logger(mesh, MESHLINK_WARNING, "Could not resolve node %s to a known address family type.\n", node->name); - } - } - else - { - logger(mesh, MESHLINK_WARNING, "Node %s is not part of the mesh network.\n", node_name); - } - } - else - { - logger(mesh, MESHLINK_WARNING, "TXT records invalid.\n"); - } - } - else - { - logger(mesh, MESHLINK_WARNING, "TXT records missing.\n"); - } - } - break; - } - - catta_s_service_resolver_free(resolver); - - pthread_mutex_unlock(&(mesh->mesh_mutex)); +static void discovery_resolve_callback(CattaSServiceResolver *resolver, CattaIfIndex interface_, CattaProtocol protocol, CattaResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const CattaAddress *address, uint16_t port, CattaStringList *txt, CattaLookupResultFlags flags, void *userdata) { + meshlink_handle_t *mesh = userdata; + + // asserts + assert(resolver != NULL); + assert(mesh != NULL); + assert(mesh->catta_server != NULL); + + pthread_mutex_lock(&(mesh->mesh_mutex)); + + /* Called whenever a service has been resolved successfully or timed out */ + switch(event) { + case CATTA_RESOLVER_FAILURE: { + // asserts + assert(name != NULL); + assert(type != NULL); + assert(domain != NULL); + + logger(mesh, MESHLINK_WARNING, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, catta_strerror(catta_server_errno(mesh->catta_server))); + } + break; + + case CATTA_RESOLVER_FOUND: { + // asserts + assert(name != NULL); + assert(type != NULL); + assert(domain != NULL); + assert(host_name != NULL); + assert(address != NULL); + assert(txt != NULL); + + char straddr[CATTA_ADDRESS_STR_MAX], *strtxt; + + logger(mesh, MESHLINK_DEBUG, "(Resolver) Service '%s' of type '%s' in domain '%s':\n", name, type, domain); + + catta_address_snprint(straddr, sizeof(straddr), address); + strtxt = catta_string_list_to_string(txt); + logger(mesh, MESHLINK_DEBUG, + "\t%s:%u (%s)\n" + "\tTXT=%s\n" + "\tcookie is %u\n" + "\tis_local: %i\n" + "\twide_area: %i\n" + "\tmulticast: %i\n" + "\tcached: %i\n", + host_name, port, straddr, + strtxt, + catta_string_list_get_service_cookie(txt), + !!(flags & CATTA_LOOKUP_RESULT_LOCAL), + !!(flags & CATTA_LOOKUP_RESULT_WIDE_AREA), + !!(flags & CATTA_LOOKUP_RESULT_MULTICAST), + !!(flags & CATTA_LOOKUP_RESULT_CACHED)); + catta_free(strtxt); + + // retrieve fingerprint + CattaStringList *node_name_li = catta_string_list_find(txt, MESHLINK_MDNS_NAME_KEY); + CattaStringList *node_fp_li = catta_string_list_find(txt, MESHLINK_MDNS_FINGERPRINT_KEY); + + if(node_name_li != NULL && node_fp_li != NULL) { + char *node_name = (char*)catta_string_list_get_text(node_name_li) + strlen(MESHLINK_MDNS_NAME_KEY); + char *node_fp = (char*)catta_string_list_get_text(node_fp_li) + strlen(MESHLINK_MDNS_FINGERPRINT_KEY); + + if(node_name[0] == '=' && node_fp[0] == '=') { + node_name += 1; + node_fp += 1; + + meshlink_node_t *node = meshlink_get_node(mesh, node_name); + + if(node != NULL) { + logger(mesh, MESHLINK_INFO, "Node %s is part of the mesh network.\n", node->name); + + sockaddr_t naddress; + memset(&naddress, 0, sizeof(naddress)); + + switch(address->proto) { + case CATTA_PROTO_INET: { + naddress.in.sin_family = AF_INET; + naddress.in.sin_port = htons(port); + naddress.in.sin_addr.s_addr = address->data.ipv4.address; + } + break; + + case CATTA_PROTO_INET6: { + naddress.in6.sin6_family = AF_INET6; + naddress.in6.sin6_port = htons(port); + memcpy(naddress.in6.sin6_addr.s6_addr, address->data.ipv6.address, sizeof(naddress.in6.sin6_addr.s6_addr)); + } + break; + + default: + naddress.unknown.family = AF_UNKNOWN; + break; + } + + if(naddress.unknown.family != AF_UNKNOWN) + meshlink_hint_address(mesh, (meshlink_node_t *)node, (struct sockaddr*)&naddress); + else + logger(mesh, MESHLINK_WARNING, "Could not resolve node %s to a known address family type.\n", node->name); + } else + logger(mesh, MESHLINK_WARNING, "Node %s is not part of the mesh network.\n", node_name); + } else + logger(mesh, MESHLINK_WARNING, "TXT records invalid.\n"); + } else + logger(mesh, MESHLINK_WARNING, "TXT records missing.\n"); + } + break; + } + + catta_s_service_resolver_free(resolver); + + pthread_mutex_unlock(&(mesh->mesh_mutex)); } -static void discovery_browse_callback(CattaSServiceBrowser *browser, CattaIfIndex interface_, CattaProtocol protocol, CattaBrowserEvent event, const char *name, const char *type, const char *domain, CattaLookupResultFlags flags, void* userdata) -{ +static void discovery_browse_callback(CattaSServiceBrowser *browser, CattaIfIndex interface_, CattaProtocol protocol, CattaBrowserEvent event, const char *name, const char *type, const char *domain, CattaLookupResultFlags flags, void* userdata) { meshlink_handle_t *mesh = userdata; - // asserts - assert(mesh != NULL); - assert(mesh->catta_server != NULL); - assert(mesh->catta_poll != NULL); - - pthread_mutex_lock(&(mesh->mesh_mutex)); - - /* Called whenever a new services becomes available on the LAN or is removed from the LAN */ - switch (event) - { - case CATTA_BROWSER_FAILURE: - { - logger(mesh, MESHLINK_ERROR, "(Browser) %s\n", catta_strerror(catta_server_errno(mesh->catta_server))); - catta_simple_poll_quit(mesh->catta_poll); - } - break; - - case CATTA_BROWSER_NEW: - { - // asserts - assert(name != NULL); - assert(type != NULL); - assert(domain != NULL); - - logger(mesh, MESHLINK_DEBUG, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain); - /* We ignore the returned resolver object. In the callback - function we free it. Ifthe server is terminated before - the callback function is called the server will free - the resolver for us. */ - if(!(catta_s_service_resolver_new(mesh->catta_server, interface_, protocol, name, type, domain, CATTA_PROTO_UNSPEC, 0, discovery_resolve_callback, mesh))) - { - logger(mesh, MESHLINK_DEBUG, "Failed to resolve service '%s': %s\n", name, catta_strerror(catta_server_errno(mesh->catta_server))); - } - } - break; - - case CATTA_BROWSER_REMOVE: - { - // asserts - assert(name != NULL); - assert(type != NULL); - assert(domain != NULL); - - logger(mesh, MESHLINK_DEBUG, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", name, type, domain); - } - break; - - case CATTA_BROWSER_ALL_FOR_NOW: - case CATTA_BROWSER_CACHE_EXHAUSTED: - { - logger(mesh, MESHLINK_DEBUG, "(Browser) %s\n", event == CATTA_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); - } - break; - } - - pthread_mutex_unlock(&(mesh->mesh_mutex)); + // asserts + assert(mesh != NULL); + assert(mesh->catta_server != NULL); + assert(mesh->catta_poll != NULL); + + pthread_mutex_lock(&(mesh->mesh_mutex)); + + /* Called whenever a new services becomes available on the LAN or is removed from the LAN */ + switch(event) { + case CATTA_BROWSER_FAILURE: { + logger(mesh, MESHLINK_ERROR, "(Browser) %s\n", catta_strerror(catta_server_errno(mesh->catta_server))); + catta_simple_poll_quit(mesh->catta_poll); + } + break; + + case CATTA_BROWSER_NEW: { + // asserts + assert(name != NULL); + assert(type != NULL); + assert(domain != NULL); + + logger(mesh, MESHLINK_DEBUG, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain); + /* We ignore the returned resolver object. In the callback + function we free it. Ifthe server is terminated before + the callback function is called the server will free + the resolver for us. */ + if(!(catta_s_service_resolver_new(mesh->catta_server, interface_, protocol, name, type, domain, CATTA_PROTO_UNSPEC, 0, discovery_resolve_callback, mesh))) + logger(mesh, MESHLINK_DEBUG, "Failed to resolve service '%s': %s\n", name, catta_strerror(catta_server_errno(mesh->catta_server))); + } + break; + + case CATTA_BROWSER_REMOVE: { + // asserts + assert(name != NULL); + assert(type != NULL); + assert(domain != NULL); + + logger(mesh, MESHLINK_DEBUG, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", name, type, domain); + } + break; + + case CATTA_BROWSER_ALL_FOR_NOW: + case CATTA_BROWSER_CACHE_EXHAUSTED: { + logger(mesh, MESHLINK_DEBUG, "(Browser) %s\n", event == CATTA_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); + } + break; + } + + pthread_mutex_unlock(&(mesh->mesh_mutex)); } -static void *discovery_loop(void *userdata) -{ +static void *discovery_loop(void *userdata) { meshlink_handle_t *mesh = userdata; - // asserts - assert(mesh != NULL); - assert(mesh->catta_poll != NULL); + // asserts + assert(mesh != NULL); + assert(mesh->catta_poll != NULL); - catta_simple_poll_loop(mesh->catta_poll); - - return NULL; + catta_simple_poll_loop(mesh->catta_poll); + + return NULL; } -static void discovery_log_cb(CattaLogLevel level, const char *txt) -{ - meshlink_log_level_t mlevel = MESHLINK_CRITICAL; +static void discovery_log_cb(CattaLogLevel level, const char *txt) { + meshlink_log_level_t mlevel = MESHLINK_CRITICAL; - switch(level) - { - case CATTA_LOG_ERROR: - mlevel = MESHLINK_ERROR; - break; + switch(level) { + case CATTA_LOG_ERROR: + mlevel = MESHLINK_ERROR; + break; - case CATTA_LOG_WARN: - mlevel = MESHLINK_WARNING; - break; + case CATTA_LOG_WARN: + mlevel = MESHLINK_WARNING; + break; - case CATTA_LOG_NOTICE: - case CATTA_LOG_INFO: - mlevel = MESHLINK_INFO; - break; + case CATTA_LOG_NOTICE: + case CATTA_LOG_INFO: + mlevel = MESHLINK_INFO; + break; - case CATTA_LOG_DEBUG: - mlevel = MESHLINK_DEBUG; - break; - } + case CATTA_LOG_DEBUG: + mlevel = MESHLINK_DEBUG; + break; + } - logger(NULL, mlevel, "%s\n", txt); + logger(NULL, mlevel, "%s\n", txt); } -bool discovery_start(meshlink_handle_t *mesh) -{ - logger(mesh, MESHLINK_DEBUG, "discovery_start called\n"); - - // asserts - assert(mesh != NULL); - assert(mesh->catta_poll == NULL); - assert(mesh->catta_server == NULL); - assert(mesh->catta_browser == NULL); - assert(mesh->discovery_threadstarted == false); - assert(mesh->catta_servicetype == NULL); - - // handle catta logs - catta_set_log_function(discovery_log_cb); - - // create service type string - size_t servicetype_strlen = sizeof(MESHLINK_MDNS_SERVICE_TYPE) + strlen(mesh->appname) + 1; - mesh->catta_servicetype = malloc(servicetype_strlen); - - if(mesh->catta_servicetype == NULL) - { - logger(mesh, MESHLINK_ERROR, "Failed to allocate memory for service type string.\n"); - goto fail; - } - - snprintf(mesh->catta_servicetype, servicetype_strlen, MESHLINK_MDNS_SERVICE_TYPE, mesh->appname); - - // Allocate discovery loop object - if(!(mesh->catta_poll = catta_simple_poll_new())) - { - logger(mesh, MESHLINK_ERROR, "Failed to create discovery poll object.\n"); +bool discovery_start(meshlink_handle_t *mesh) { + logger(mesh, MESHLINK_DEBUG, "discovery_start called\n"); + + // asserts + assert(mesh != NULL); + assert(mesh->catta_poll == NULL); + assert(mesh->catta_server == NULL); + assert(mesh->catta_browser == NULL); + assert(mesh->discovery_threadstarted == false); + assert(mesh->catta_servicetype == NULL); + + // handle catta logs + catta_set_log_function(discovery_log_cb); + + // create service type string + size_t servicetype_strlen = sizeof(MESHLINK_MDNS_SERVICE_TYPE) + strlen(mesh->appname) + 1; + mesh->catta_servicetype = malloc(servicetype_strlen); + + if(mesh->catta_servicetype == NULL) { + logger(mesh, MESHLINK_ERROR, "Failed to allocate memory for service type string.\n"); goto fail; - } - - // generate some unique host name (we actually do not care about it) - char hostname[17]; - generate_rand_string(hostname, sizeof(hostname)); - - // Let's set the host name for this server. - CattaServerConfig config; - catta_server_config_init(&config); - config.host_name = catta_strdup(hostname); - config.publish_workstation = 0; - config.disallow_other_stacks = 0; - config.publish_hinfo = 0; - config.publish_addresses = 1; - config.publish_no_reverse = 1; - - /* Allocate a new server */ - int error; - mesh->catta_server = catta_server_new(catta_simple_poll_get(mesh->catta_poll), &config, discovery_server_callback, mesh, &error); - - /* Free the configuration data */ - catta_server_config_free(&config); - - /* Check wether creating the server object succeeded */ - if(!mesh->catta_server) - { - logger(mesh, MESHLINK_ERROR, "Failed to create discovery server: %s\n", catta_strerror(error)); - goto fail; - } - - // Create the service browser - if(!(mesh->catta_browser = catta_s_service_browser_new(mesh->catta_server, CATTA_IF_UNSPEC, CATTA_PROTO_UNSPEC, mesh->catta_servicetype, NULL, 0, discovery_browse_callback, mesh))) - { - logger(mesh, MESHLINK_ERROR, "Failed to create discovery service browser: %s\n", catta_strerror(catta_server_errno(mesh->catta_server))); - goto fail; - } + } + + snprintf(mesh->catta_servicetype, servicetype_strlen, MESHLINK_MDNS_SERVICE_TYPE, mesh->appname); + + // Allocate discovery loop object + if(!(mesh->catta_poll = catta_simple_poll_new())) { + logger(mesh, MESHLINK_ERROR, "Failed to create discovery poll object.\n"); + goto fail; + } + + // generate some unique host name (we actually do not care about it) + char hostname[17]; + generate_rand_string(hostname, sizeof(hostname)); + + // Let's set the host name for this server. + CattaServerConfig config; + catta_server_config_init(&config); + config.host_name = catta_strdup(hostname); + config.publish_workstation = 0; + config.disallow_other_stacks = 0; + config.publish_hinfo = 0; + config.publish_addresses = 1; + config.publish_no_reverse = 1; + + /* Allocate a new server */ + int error; + mesh->catta_server = catta_server_new(catta_simple_poll_get(mesh->catta_poll), &config, discovery_server_callback, mesh, &error); + + /* Free the configuration data */ + catta_server_config_free(&config); + + /* Check wether creating the server object succeeded */ + if(!mesh->catta_server) { + logger(mesh, MESHLINK_ERROR, "Failed to create discovery server: %s\n", catta_strerror(error)); + goto fail; + } + + // Create the service browser + if(!(mesh->catta_browser = catta_s_service_browser_new(mesh->catta_server, CATTA_IF_UNSPEC, CATTA_PROTO_UNSPEC, mesh->catta_servicetype, NULL, 0, discovery_browse_callback, mesh))) { + logger(mesh, MESHLINK_ERROR, "Failed to create discovery service browser: %s\n", catta_strerror(catta_server_errno(mesh->catta_server))); + goto fail; + } // Start the discovery thread - if(pthread_create(&mesh->discovery_thread, NULL, discovery_loop, mesh) != 0) - { + if(pthread_create(&mesh->discovery_thread, NULL, discovery_loop, mesh) != 0) { logger(mesh, MESHLINK_ERROR, "Could not start discovery thread: %s\n", strerror(errno)); memset(&mesh->discovery_thread, 0, sizeof mesh->discovery_thread); goto fail; @@ -533,82 +472,69 @@ bool discovery_start(meshlink_handle_t *mesh) return true; fail: - if(mesh->catta_browser != NULL) - { - catta_s_service_browser_free(mesh->catta_browser); - mesh->catta_browser = NULL; - } - - if(mesh->catta_server != NULL) - { - catta_server_free(mesh->catta_server); - mesh->catta_server = NULL; - } - - if(mesh->catta_poll != NULL) - { - catta_simple_poll_free(mesh->catta_poll); - mesh->catta_poll = NULL; - } - - if(mesh->catta_servicetype != NULL) - { - free(mesh->catta_servicetype); - mesh->catta_servicetype = NULL; - } - - return false; + if(mesh->catta_browser != NULL) { + catta_s_service_browser_free(mesh->catta_browser); + mesh->catta_browser = NULL; + } + + if(mesh->catta_server != NULL) { + catta_server_free(mesh->catta_server); + mesh->catta_server = NULL; + } + + if(mesh->catta_poll != NULL) { + catta_simple_poll_free(mesh->catta_poll); + mesh->catta_poll = NULL; + } + + if(mesh->catta_servicetype != NULL) { + free(mesh->catta_servicetype); + mesh->catta_servicetype = NULL; + } + + return false; } -void discovery_stop(meshlink_handle_t *mesh) -{ - logger(mesh, MESHLINK_DEBUG, "discovery_stop called\n"); +void discovery_stop(meshlink_handle_t *mesh) { + logger(mesh, MESHLINK_DEBUG, "discovery_stop called\n"); - // asserts - assert(mesh != NULL); + // asserts + assert(mesh != NULL); // Shut down - if(mesh->catta_poll) - { - catta_simple_poll_quit(mesh->catta_poll); - } + if(mesh->catta_poll) + catta_simple_poll_quit(mesh->catta_poll); // Wait for the discovery thread to finish - if(mesh->discovery_threadstarted == true) - { - pthread_join(mesh->discovery_thread, NULL); - mesh->discovery_threadstarted = false; - } + if(mesh->discovery_threadstarted == true) { + pthread_join(mesh->discovery_thread, NULL); + mesh->discovery_threadstarted = false; + } // Clean up resources - if(mesh->catta_browser != NULL) - { - catta_s_service_browser_free(mesh->catta_browser); - mesh->catta_browser = NULL; - } - - if(mesh->catta_group) - { - catta_s_entry_group_reset(mesh->catta_group); - catta_s_entry_group_free(mesh->catta_group); - mesh->catta_group = NULL; - } - - if(mesh->catta_server != NULL) - { - catta_server_free(mesh->catta_server); - mesh->catta_server = NULL; - } - - if(mesh->catta_poll != NULL) - { - catta_simple_poll_free(mesh->catta_poll); - mesh->catta_poll = NULL; - } - - if(mesh->catta_servicetype != NULL) - { - free(mesh->catta_servicetype); - mesh->catta_servicetype = NULL; - } + if(mesh->catta_browser != NULL) { + catta_s_service_browser_free(mesh->catta_browser); + mesh->catta_browser = NULL; + } + + if(mesh->catta_group) { + catta_s_entry_group_reset(mesh->catta_group); + catta_s_entry_group_free(mesh->catta_group); + mesh->catta_group = NULL; + } + + if(mesh->catta_server != NULL) { + catta_server_free(mesh->catta_server); + mesh->catta_server = NULL; + } + + if(mesh->catta_poll != NULL) { + catta_simple_poll_free(mesh->catta_poll); + mesh->catta_poll = NULL; + } + + if(mesh->catta_servicetype != NULL) { + free(mesh->catta_servicetype); + mesh->catta_servicetype = NULL; + } } diff --git a/src/dropin.h b/src/dropin.h index ed6b3856..78c0760f 100644 --- a/src/dropin.h +++ b/src/dropin.h @@ -42,19 +42,19 @@ extern int usleep(long long usec); #ifndef timeradd #define timeradd(a, b, r) do {\ - (r)->tv_sec = (a)->tv_sec + (b)->tv_sec;\ - (r)->tv_usec = (a)->tv_usec + (b)->tv_usec;\ - if((r)->tv_usec >= 1000000)\ - (r)->tv_sec++, (r)->tv_usec -= 1000000;\ + (r)->tv_sec = (a)->tv_sec + (b)->tv_sec;\ + (r)->tv_usec = (a)->tv_usec + (b)->tv_usec;\ + if((r)->tv_usec >= 1000000)\ + (r)->tv_sec++, (r)->tv_usec -= 1000000;\ } while (0) #endif #ifndef timersub #define timersub(a, b, r) do {\ - (r)->tv_sec = (a)->tv_sec - (b)->tv_sec;\ - (r)->tv_usec = (a)->tv_usec - (b)->tv_usec;\ - if((r)->tv_usec < 0)\ - (r)->tv_sec--, (r)->tv_usec += 1000000;\ + (r)->tv_sec = (a)->tv_sec - (b)->tv_sec;\ + (r)->tv_usec = (a)->tv_usec - (b)->tv_usec;\ + if((r)->tv_usec < 0)\ + (r)->tv_sec--, (r)->tv_usec += 1000000;\ } while (0) #endif diff --git a/src/ecdh.h b/src/ecdh.h index ac6bf029..92be3ed5 100644 --- a/src/ecdh.h +++ b/src/ecdh.h @@ -27,8 +27,8 @@ typedef struct ecdh ecdh_t; #endif -extern ecdh_t *ecdh_generate_public(void *pubkey) __attribute__ ((__malloc__)); -extern bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) __attribute__ ((__warn_unused_result__)); +extern ecdh_t *ecdh_generate_public(void *pubkey) __attribute__((__malloc__)); +extern bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) __attribute__((__warn_unused_result__)); extern void ecdh_free(ecdh_t *ecdh); #endif diff --git a/src/ecdsa.h b/src/ecdsa.h index 707b02cf..ef10fe71 100644 --- a/src/ecdsa.h +++ b/src/ecdsa.h @@ -24,13 +24,13 @@ typedef struct ecdsa ecdsa_t; #endif -extern ecdsa_t *ecdsa_set_base64_public_key(const char *p) __attribute__ ((__malloc__)); +extern ecdsa_t *ecdsa_set_base64_public_key(const char *p) __attribute__((__malloc__)); extern char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa); -extern ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) __attribute__ ((__malloc__)); -extern ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) __attribute__ ((__malloc__)); +extern ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) __attribute__((__malloc__)); +extern ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) __attribute__((__malloc__)); extern size_t ecdsa_size(ecdsa_t *ecdsa); -extern bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t inlen, void *out) __attribute__ ((__warn_unused_result__)); -extern bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t inlen, const void *out) __attribute__ ((__warn_unused_result__)); +extern bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t inlen, void *out) __attribute__((__warn_unused_result__)); +extern bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t inlen, const void *out) __attribute__((__warn_unused_result__)); extern bool ecdsa_active(ecdsa_t *ecdsa); extern void ecdsa_free(ecdsa_t *ecdsa); diff --git a/src/ecdsagen.h b/src/ecdsagen.h index ed36b50e..f4578be6 100644 --- a/src/ecdsagen.h +++ b/src/ecdsagen.h @@ -22,8 +22,8 @@ #include "ecdsa.h" -extern ecdsa_t *ecdsa_generate(void) __attribute__ ((__malloc__)); -extern bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) __attribute__ ((__warn_unused_result__)); -extern bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) __attribute__ ((__warn_unused_result__)); +extern ecdsa_t *ecdsa_generate(void) __attribute__((__malloc__)); +extern bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) __attribute__((__warn_unused_result__)); +extern bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) __attribute__((__warn_unused_result__)); #endif diff --git a/src/edge.h b/src/edge.h index 2a62cb75..53ef354c 100644 --- a/src/edge.h +++ b/src/edge.h @@ -39,9 +39,9 @@ typedef struct edge_t { extern void init_edges(struct meshlink_handle *mesh); extern void exit_edges(struct meshlink_handle *mesh); -extern edge_t *new_edge(void) __attribute__ ((__malloc__)); +extern edge_t *new_edge(void) __attribute__((__malloc__)); extern void free_edge(edge_t *); -extern struct splay_tree_t *new_edge_tree(void) __attribute__ ((__malloc__)); +extern struct splay_tree_t *new_edge_tree(void) __attribute__((__malloc__)); extern void free_edge_tree(struct splay_tree_t *); extern void edge_add(struct meshlink_handle *mesh, edge_t *); extern void edge_del(struct meshlink_handle *mesh, edge_t *); diff --git a/src/event.c b/src/event.c index 1f6ea186..0a5f97e8 100644 --- a/src/event.c +++ b/src/event.c @@ -91,7 +91,9 @@ void io_del(event_loop_t *loop, io_t *io) { void timeout_add(event_loop_t *loop, timeout_t *timeout, timeout_cb_t cb, void *data, struct timeval *tv) { if(!timeout->cb) - timeout->tv = (struct timeval){0, 0}; + timeout->tv = (struct timeval) { + 0, 0 + }; timeout->cb = cb; timeout->data = data; @@ -121,7 +123,9 @@ void timeout_del(event_loop_t *loop, timeout_t *timeout) { splay_unlink_node(&loop->timeouts, &timeout->node); timeout->cb = 0; - timeout->tv = (struct timeval){0, 0}; + timeout->tv = (struct timeval) { + 0, 0 + }; } static int signal_compare(const signal_t *a, const signal_t *b) { @@ -133,7 +137,9 @@ static void signalio_handler(event_loop_t *loop, void *data, int flags) { if(read(loop->pipefd[0], &signum, 1) != 1) return; - signal_t *sig = splay_search(&loop->signals, &((signal_t){.signum = signum})); + signal_t *sig = splay_search(&loop->signals, &((signal_t) { + .signum = signum + })); if(sig) sig->cb(loop, sig->data); } diff --git a/src/event.h b/src/event.h index 02d19583..fe64413e 100644 --- a/src/event.h +++ b/src/event.h @@ -32,7 +32,7 @@ typedef struct event_loop_t event_loop_t; typedef void (*io_cb_t)(event_loop_t *loop, void *data, int flags); typedef void (*timeout_cb_t)(event_loop_t *loop, void *data); typedef void (*signal_cb_t)(event_loop_t *loop, void *data); -typedef struct timeval (*idle_cb_t)(event_loop_t *loop, void *data); +typedef struct timeval(*idle_cb_t)(event_loop_t *loop, void *data); typedef struct io_t { int fd; @@ -63,7 +63,7 @@ struct event_loop_t { volatile bool running; struct timeval now; bool deletion; - + splay_tree_t ios; splay_tree_t timeouts; splay_tree_t signals; diff --git a/src/fake-getaddrinfo.c b/src/fake-getaddrinfo.c index 72db772d..37a65b89 100644 --- a/src/fake-getaddrinfo.c +++ b/src/fake-getaddrinfo.c @@ -17,15 +17,15 @@ #if !HAVE_DECL_GAI_STRERROR char *gai_strerror(int ecode) { - switch (ecode) { - case EAI_NODATA: - return "No address associated with hostname"; - case EAI_MEMORY: - return "Memory allocation failure"; - case EAI_FAMILY: - return "Address family not supported"; - default: - return "Unknown error"; + switch(ecode) { + case EAI_NODATA: + return "No address associated with hostname"; + case EAI_MEMORY: + return "Memory allocation failure"; + case EAI_FAMILY: + return "Address family not supported"; + default: + return "Unknown error"; } } #endif /* !HAVE_GAI_STRERROR */ @@ -68,15 +68,15 @@ int getaddrinfo(const char *hostname, const char *servname, const struct addrinf if(hints && hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC) return EAI_FAMILY; - if (servname) + if(servname) port = htons(atoi(servname)); - if (hints && hints->ai_flags & AI_PASSIVE) { + if(hints && hints->ai_flags & AI_PASSIVE) { *res = malloc_ai(port, htonl(0x00000000)); return 0; } - if (!hostname) { + if(!hostname) { *res = malloc_ai(port, htonl(0x7f000001)); return 0; } @@ -86,7 +86,7 @@ int getaddrinfo(const char *hostname, const char *servname, const struct addrinf if(!hp || !hp->h_addr_list || !hp->h_addr_list[0]) return EAI_NODATA; - for (i = 0; hp->h_addr_list[i]; i++) { + for(i = 0; hp->h_addr_list[i]; i++) { *res = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr); if(prev) diff --git a/src/graph.c b/src/graph.c index b18d0610..c57cd90f 100644 --- a/src/graph.c +++ b/src/graph.c @@ -150,11 +150,11 @@ static void sssp_bfs(meshlink_handle_t *mesh) { /* Situation: - / - / + / + / ----->(n)---e-->(e->to) - \ - \ + \ + \ Where e is an edge, (n) and (e->to) are nodes. n->address is set to the e->address of the edge left of n to n. @@ -168,8 +168,8 @@ static void sssp_bfs(meshlink_handle_t *mesh) { bool indirect = n->status.indirect || e->options & OPTION_INDIRECT; if(e->to->status.visited - && (!e->to->status.indirect || indirect) - && (e->to->distance != n->distance + 1 || e->weight >= e->to->prevedge->weight)) + && (!e->to->status.indirect || indirect) + && (e->to->distance != n->distance + 1 || e->weight >= e->to->prevedge->weight)) continue; e->to->status.visited = true; @@ -203,10 +203,10 @@ static void check_reachability(meshlink_handle_t *mesh) { if(n->status.reachable) { logger(mesh, MESHLINK_DEBUG, "Node %s (%s) became reachable", - n->name, n->hostname); + n->name, n->hostname); } else { logger(mesh, MESHLINK_DEBUG, "Node %s (%s) became unreachable", - n->name, n->hostname); + n->name, n->hostname); } /* TODO: only clear status.validkey if node is unreachable? */ diff --git a/src/hash.c b/src/hash.c index aabd94c7..e0733386 100644 --- a/src/hash.c +++ b/src/hash.c @@ -76,9 +76,8 @@ void hash_insert(hash_t *hash, const void *key, const void *value) { void *hash_search(const hash_t *hash, const void *key) { uint32_t i = modulo(hash_function(key, hash->size), hash->n); - if(hash->values[i] && !memcmp(key, hash->keys + i * hash->size, hash->size)) { + if(hash->values[i] && !memcmp(key, hash->keys + i * hash->size, hash->size)) return (void *)hash->values[i]; - } return NULL; } diff --git a/src/hash.h b/src/hash.h index 702091d0..182a1c95 100644 --- a/src/hash.h +++ b/src/hash.h @@ -27,7 +27,7 @@ typedef struct hash_t { const void **values; } hash_t; -extern hash_t *hash_alloc(size_t n, size_t size) __attribute__ ((__malloc__)); +extern hash_t *hash_alloc(size_t n, size_t size) __attribute__((__malloc__)); extern void hash_free(hash_t *); extern void hash_insert(hash_t *, const void *key, const void *value); diff --git a/src/list.h b/src/list.h index c9908284..3cda17a6 100644 --- a/src/list.h +++ b/src/list.h @@ -44,7 +44,7 @@ typedef struct list_t { /* (De)constructors */ -extern list_t *list_alloc(list_action_t) __attribute__ ((__malloc__)); +extern list_t *list_alloc(list_action_t) __attribute__((__malloc__)); extern void list_free(list_t *); extern list_node_t *list_alloc_node(void); extern void list_free_node(list_t *, list_node_t *); diff --git a/src/logger.h b/src/logger.h index 94482697..05773d6c 100644 --- a/src/logger.h +++ b/src/logger.h @@ -22,6 +22,6 @@ #include "meshlink_internal.h" -extern void logger(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *format, ...) __attribute__ ((__format__(printf, 3, 4))); +extern void logger(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *format, ...) __attribute__((__format__(printf, 3, 4))); #endif /* __MESHLINK_LOGGER_H__ */ diff --git a/src/meshlink++.h b/src/meshlink++.h index 258d6cf4..df0a72b5 100644 --- a/src/meshlink++.h +++ b/src/meshlink++.h @@ -24,40 +24,172 @@ #include // for 'placement new' namespace meshlink { - class mesh; - class node; - class channel; +class mesh; +class node; +class channel; + +/// Severity of log messages generated by MeshLink. +typedef meshlink_log_level_t log_level_t; + +/// Code of most recent error encountered. +typedef meshlink_errno_t errno_t; + +/// A callback for receiving data from the mesh. +/** @param mesh A handle which represents an instance of MeshLink. + * @param source A pointer to a meshlink::node describing the source of the data. + * @param data A pointer to a buffer containing the data sent by the source. + * @param len The length of the received data. + */ +typedef void (*receive_cb_t)(mesh *mesh, node *source, const void *data, size_t len); + +/// A callback reporting node status changes. +/** @param mesh A handle which represents an instance of MeshLink. + * @param node A pointer to a meshlink::node describing the node whose status changed. + * @param reachable True if the node is reachable, false otherwise. + */ +typedef void (*node_status_cb_t)(mesh *mesh, node *node, bool reachable); + +/// A callback for receiving log messages generated by MeshLink. +/** @param mesh A handle which represents an instance of MeshLink. + * @param level An enum describing the severity level of the message. + * @param text A pointer to a string containing the textual log message. + */ +typedef void (*log_cb_t)(mesh *mesh, log_level_t level, const char *text); + +/// A callback for accepting incoming channels. +/** @param mesh A handle which represents an instance of MeshLink. + * @param channel A handle for the incoming channel. + * @param port The port number the peer wishes to connect to. + * @param data A pointer to a buffer containing data already received. (Not yet used.) + * @param len The length of the data. (Not yet used.) + * + * @return This function should return true if the application accepts the incoming channel, false otherwise. + * If returning false, the channel is invalid and may not be used anymore. + */ +typedef bool (*channel_accept_cb_t)(mesh *mesh, channel *channel, uint16_t port, const void *data, size_t len); + +/// A callback for receiving data from a channel. +/** @param mesh A handle which represents an instance of MeshLink. + * @param channel A handle for the channel. + * @param data A pointer to a buffer containing data sent by the source. + * @param len The length of the data. + */ +typedef void (*channel_receive_cb_t)(mesh *mesh, channel *channel, const void *data, size_t len); + +/// A callback that is called when data can be send on a channel. +/** @param mesh A handle which represents an instance of MeshLink. + * @param channel A handle for the channel. + * @param len The maximum length of data that is guaranteed to be accepted by a call to channel_send(). + */ +typedef void (*channel_poll_cb_t)(mesh *mesh, channel *channel, size_t len); + +/// A class describing a MeshLink node. +class node: public meshlink_node_t { +}; + +/// A class describing a MeshLink channel. +class channel: public meshlink_channel_t { +public: + static const uint32_t RELIABLE = MESHLINK_CHANNEL_RELIABLE; + static const uint32_t ORDERED = MESHLINK_CHANNEL_ORDERED; + static const uint32_t FRAMED = MESHLINK_CHANNEL_FRAMED; + static const uint32_t DROP_LATE = MESHLINK_CHANNEL_DROP_LATE; + static const uint32_t TCP = MESHLINK_CHANNEL_TCP; + static const uint32_t UDP = MESHLINK_CHANNEL_UDP; +}; + +/// A class describing a MeshLink mesh. +class mesh { +public: + mesh() : handle(0) {} + + virtual ~mesh() { + this->close(); + } - /// Severity of log messages generated by MeshLink. - typedef meshlink_log_level_t log_level_t; + bool isOpen() const { + return (handle!=0); + } - /// Code of most recent error encountered. - typedef meshlink_errno_t errno_t; +// TODO: please enable C++11 in autoconf to enable "move constructors": +// mesh(mesh&& other) +// : handle(other.handle) +// { +// if(handle) +// handle->priv = this; +// other.handle = 0; +// } - /// A callback for receiving data from the mesh. - /** @param mesh A handle which represents an instance of MeshLink. - * @param source A pointer to a meshlink::node describing the source of the data. - * @param data A pointer to a buffer containing the data sent by the source. - * @param len The length of the received data. + /// Initialize MeshLink's configuration directory. + /** This function causes MeshLink to initialize its configuration directory, + * if it hasn't already been initialized. + * It only has to be run the first time the application starts, + * but it is not a problem if it is run more than once, as long as + * the arguments given are the same. + * + * This function does not start any network I/O yet. The application should + * first set callbacks, and then call meshlink_start(). + * + * @param confbase The directory in which MeshLink will store its configuration files. + * @param name The name which this instance of the application will use in the mesh. + * @param appname The application name which will be used in the mesh. + * @param dclass The device class which will be used in the mesh. + * + * @return This function will return a pointer to a meshlink::mesh if MeshLink has succesfully set up its configuration files, NULL otherwise. */ - typedef void (*receive_cb_t)(mesh *mesh, node *source, const void *data, size_t len); + bool open(const char *confbase, const char *name, const char* appname, dev_class_t devclass) { + handle = meshlink_open(confbase, name, appname, devclass); + if(handle) + handle->priv = this; + + return isOpen(); + } - /// A callback reporting node status changes. - /** @param mesh A handle which represents an instance of MeshLink. - * @param node A pointer to a meshlink::node describing the node whose status changed. - * @param reachable True if the node is reachable, false otherwise. + mesh(const char *confbase, const char *name, const char* appname, dev_class_t devclass) { + open(confbase, name, appname, devclass); + } + + /// Close the MeshLink handle. + /** This function calls meshlink_stop() if necessary, + * and frees all memory allocated by MeshLink. + * Afterwards, the handle and any pointers to a struct meshlink_node are invalid. */ - typedef void (*node_status_cb_t)(mesh *mesh, node *node, bool reachable); + void close() { + if(handle) { + handle->priv = 0; + meshlink_close(handle); + } + handle=0; + } - /// A callback for receiving log messages generated by MeshLink. - /** @param mesh A handle which represents an instance of MeshLink. - * @param level An enum describing the severity level of the message. - * @param text A pointer to a string containing the textual log message. + /** instead of registerin callbacks you derive your own class and overwrite the following abstract member functions. + * These functions are run in MeshLink's own thread. + * It is therefore important that these functions use apprioriate methods (queues, pipes, locking, etc.) + * to hand the data over to the application's thread. + * These functions should also not block itself and return as quickly as possible. + * The default member functions are no-ops, so you are not required to overwrite all these member functions */ - typedef void (*log_cb_t)(mesh *mesh, log_level_t level, const char *text); - /// A callback for accepting incoming channels. - /** @param mesh A handle which represents an instance of MeshLink. + /// This function is called whenever another node sends data to the local node. + virtual void receive(node* source, const void* data, size_t length) { /* do nothing */ } + + /// This functions is called whenever another node's status changed. + virtual void node_status(node* peer, bool reachable) { /* do nothing */ } + + /// This functions is called whenever MeshLink has some information to log. + virtual void log(log_level_t level, const char* message) { /* do nothing */ } + + /// This functions is called whenever another node attemps to open a channel to the local node. + /** + * If the channel is accepted, the poll_callback will be set to channel_poll and can be + * changed using set_channel_poll_cb(). Likewise, the receive callback is set to + * channel_receive(). + * + * The function is run in MeshLink's own thread. + * It is therefore important that the callback uses apprioriate methods (queues, pipes, locking, etc.) + * to pass data to or from the application's thread. + * The callback should also not block itself and return as quickly as possible. + * * @param channel A handle for the incoming channel. * @param port The port number the peer wishes to connect to. * @param data A pointer to a buffer containing data already received. (Not yet used.) @@ -66,580 +198,439 @@ namespace meshlink { * @return This function should return true if the application accepts the incoming channel, false otherwise. * If returning false, the channel is invalid and may not be used anymore. */ - typedef bool (*channel_accept_cb_t)(mesh *mesh, channel *channel, uint16_t port, const void *data, size_t len); + virtual bool channel_accept(channel *channel, uint16_t port, const void *data, size_t len) { + /* by default reject all channels */ + return false; + } - /// A callback for receiving data from a channel. - /** @param mesh A handle which represents an instance of MeshLink. + /// This function is called by Meshlink for receiving data from a channel. + /** + * The function is run in MeshLink's own thread. + * It is therefore important that the callback uses apprioriate methods (queues, pipes, locking, etc.) + * to pass data to or from the application's thread. + * The callback should also not block itself and return as quickly as possible. + * * @param channel A handle for the channel. * @param data A pointer to a buffer containing data sent by the source. * @param len The length of the data. */ - typedef void (*channel_receive_cb_t)(mesh *mesh, channel *channel, const void *data, size_t len); + virtual void channel_receive(channel *channel, const void *data, size_t len) { /* do nothing */ } - /// A callback that is called when data can be send on a channel. - /** @param mesh A handle which represents an instance of MeshLink. + /// This function is called by Meshlink when data can be send on a channel. + /** + * The function is run in MeshLink's own thread. + * It is therefore important that the callback uses apprioriate methods (queues, pipes, locking, etc.) + * to pass data to or from the application's thread. + * + * The callback should also not block itself and return as quickly as possible. * @param channel A handle for the channel. * @param len The maximum length of data that is guaranteed to be accepted by a call to channel_send(). */ - typedef void (*channel_poll_cb_t)(mesh *mesh, channel *channel, size_t len); - - /// A class describing a MeshLink node. - class node: public meshlink_node_t { - }; - - /// A class describing a MeshLink channel. - class channel: public meshlink_channel_t { - public: - static const uint32_t RELIABLE = MESHLINK_CHANNEL_RELIABLE; - static const uint32_t ORDERED = MESHLINK_CHANNEL_ORDERED; - static const uint32_t FRAMED = MESHLINK_CHANNEL_FRAMED; - static const uint32_t DROP_LATE = MESHLINK_CHANNEL_DROP_LATE; - static const uint32_t TCP = MESHLINK_CHANNEL_TCP; - static const uint32_t UDP = MESHLINK_CHANNEL_UDP; - }; - - /// A class describing a MeshLink mesh. - class mesh { - public: - mesh() : handle(0) {} - - virtual ~mesh() { - this->close(); - } - - bool isOpen() const { - return (handle!=0); - } - -// TODO: please enable C++11 in autoconf to enable "move constructors": -// mesh(mesh&& other) -// : handle(other.handle) -// { -// if(handle) -// handle->priv = this; -// other.handle = 0; -// } + virtual void channel_poll(channel *channel, size_t len) { /* do nothing */ } - /// Initialize MeshLink's configuration directory. - /** This function causes MeshLink to initialize its configuration directory, - * if it hasn't already been initialized. - * It only has to be run the first time the application starts, - * but it is not a problem if it is run more than once, as long as - * the arguments given are the same. - * - * This function does not start any network I/O yet. The application should - * first set callbacks, and then call meshlink_start(). - * - * @param confbase The directory in which MeshLink will store its configuration files. - * @param name The name which this instance of the application will use in the mesh. - * @param appname The application name which will be used in the mesh. - * @param dclass The device class which will be used in the mesh. - * - * @return This function will return a pointer to a meshlink::mesh if MeshLink has succesfully set up its configuration files, NULL otherwise. - */ - bool open(const char *confbase, const char *name, const char* appname, dev_class_t devclass) { - handle = meshlink_open(confbase, name, appname, devclass); - if(handle) - handle->priv = this; - - return isOpen(); - } - - mesh(const char *confbase, const char *name, const char* appname, dev_class_t devclass) { - open(confbase, name, appname, devclass); - } - - /// Close the MeshLink handle. - /** This function calls meshlink_stop() if necessary, - * and frees all memory allocated by MeshLink. - * Afterwards, the handle and any pointers to a struct meshlink_node are invalid. - */ - void close() { - if(handle) - { - handle->priv = 0; - meshlink_close(handle); - } - handle=0; - } - - /** instead of registerin callbacks you derive your own class and overwrite the following abstract member functions. - * These functions are run in MeshLink's own thread. - * It is therefore important that these functions use apprioriate methods (queues, pipes, locking, etc.) - * to hand the data over to the application's thread. - * These functions should also not block itself and return as quickly as possible. - * The default member functions are no-ops, so you are not required to overwrite all these member functions - */ - - /// This function is called whenever another node sends data to the local node. - virtual void receive(node* source, const void* data, size_t length) { /* do nothing */ } - - /// This functions is called whenever another node's status changed. - virtual void node_status(node* peer, bool reachable) { /* do nothing */ } - - /// This functions is called whenever MeshLink has some information to log. - virtual void log(log_level_t level, const char* message) { /* do nothing */ } - - /// This functions is called whenever another node attemps to open a channel to the local node. - /** - * If the channel is accepted, the poll_callback will be set to channel_poll and can be - * changed using set_channel_poll_cb(). Likewise, the receive callback is set to - * channel_receive(). - * - * The function is run in MeshLink's own thread. - * It is therefore important that the callback uses apprioriate methods (queues, pipes, locking, etc.) - * to pass data to or from the application's thread. - * The callback should also not block itself and return as quickly as possible. - * - * @param channel A handle for the incoming channel. - * @param port The port number the peer wishes to connect to. - * @param data A pointer to a buffer containing data already received. (Not yet used.) - * @param len The length of the data. (Not yet used.) - * - * @return This function should return true if the application accepts the incoming channel, false otherwise. - * If returning false, the channel is invalid and may not be used anymore. - */ - virtual bool channel_accept(channel *channel, uint16_t port, const void *data, size_t len) - { - /* by default reject all channels */ - return false; - } + /// Start MeshLink. + /** This function causes MeshLink to open network sockets, make outgoing connections, and + * create a new thread, which will handle all network I/O. + * + * @return This function will return true if MeshLink has succesfully started its thread, false otherwise. + */ + bool start() { + meshlink_set_receive_cb(handle, &receive_trampoline); + meshlink_set_node_status_cb(handle, &node_status_trampoline); + meshlink_set_log_cb(handle, MESHLINK_DEBUG, &log_trampoline); + meshlink_set_channel_accept_cb(handle, &channel_accept_trampoline); + return meshlink_start(handle); + } - /// This function is called by Meshlink for receiving data from a channel. - /** - * The function is run in MeshLink's own thread. - * It is therefore important that the callback uses apprioriate methods (queues, pipes, locking, etc.) - * to pass data to or from the application's thread. - * The callback should also not block itself and return as quickly as possible. - * - * @param channel A handle for the channel. - * @param data A pointer to a buffer containing data sent by the source. - * @param len The length of the data. - */ - virtual void channel_receive(channel *channel, const void *data, size_t len) { /* do nothing */ } - - /// This function is called by Meshlink when data can be send on a channel. - /** - * The function is run in MeshLink's own thread. - * It is therefore important that the callback uses apprioriate methods (queues, pipes, locking, etc.) - * to pass data to or from the application's thread. - * - * The callback should also not block itself and return as quickly as possible. - * @param channel A handle for the channel. - * @param len The maximum length of data that is guaranteed to be accepted by a call to channel_send(). - */ - virtual void channel_poll(channel *channel, size_t len) { /* do nothing */ } - - /// Start MeshLink. - /** This function causes MeshLink to open network sockets, make outgoing connections, and - * create a new thread, which will handle all network I/O. - * - * @return This function will return true if MeshLink has succesfully started its thread, false otherwise. - */ - bool start() { - meshlink_set_receive_cb (handle, &receive_trampoline); - meshlink_set_node_status_cb (handle, &node_status_trampoline); - meshlink_set_log_cb (handle, MESHLINK_DEBUG, &log_trampoline); - meshlink_set_channel_accept_cb(handle, &channel_accept_trampoline); - return meshlink_start (handle); - } + /// Stop MeshLink. + /** This function causes MeshLink to disconnect from all other nodes, + * close all sockets, and shut down its own thread. + */ + void stop() { + meshlink_stop(handle); + } - /// Stop MeshLink. - /** This function causes MeshLink to disconnect from all other nodes, - * close all sockets, and shut down its own thread. - */ - void stop() { - meshlink_stop(handle); - } + /// Send data to another node. + /** This functions sends one packet of data to another node in the mesh. + * The packet is sent using UDP semantics, which means that + * the packet is sent as one unit and is received as one unit, + * and that there is no guarantee that the packet will arrive at the destination. + * The application should take care of getting an acknowledgement and retransmission if necessary. + * + * @param destination A pointer to a meshlink::node describing the destination for the data. + * @param data A pointer to a buffer containing the data to be sent to the source. + * @param len The length of the data. + * @return This function will return true if MeshLink has queued the message for transmission, and false otherwise. + * A return value of true does not guarantee that the message will actually arrive at the destination. + */ + bool send(node *destination, const void *data, unsigned int len) { + return meshlink_send(handle, destination, data, len); + } - /// Send data to another node. - /** This functions sends one packet of data to another node in the mesh. - * The packet is sent using UDP semantics, which means that - * the packet is sent as one unit and is received as one unit, - * and that there is no guarantee that the packet will arrive at the destination. - * The application should take care of getting an acknowledgement and retransmission if necessary. - * - * @param destination A pointer to a meshlink::node describing the destination for the data. - * @param data A pointer to a buffer containing the data to be sent to the source. - * @param len The length of the data. - * @return This function will return true if MeshLink has queued the message for transmission, and false otherwise. - * A return value of true does not guarantee that the message will actually arrive at the destination. - */ - bool send(node *destination, const void *data, unsigned int len) { - return meshlink_send(handle, destination, data, len); - } + /// Get a handle for a specific node. + /** This function returns a handle for the node with the given name. + * + * @param name The name of the node for which a handle is requested. + * + * @return A pointer to a meshlink::node which represents the requested node, + * or NULL if the requested node does not exist. + */ + node *get_node(const char *name) { + return (node *)meshlink_get_node(handle, name); + } - /// Get a handle for a specific node. - /** This function returns a handle for the node with the given name. - * - * @param name The name of the node for which a handle is requested. - * - * @return A pointer to a meshlink::node which represents the requested node, - * or NULL if the requested node does not exist. - */ - node *get_node(const char *name) { - return (node *)meshlink_get_node(handle, name); - } + /// Get a handle for our own node. + /** This function returns a handle for the local node. + * + * @return A pointer to a meshlink::node which represents the local node. + */ + node *get_self() { + return (node *)meshlink_get_self(handle); + } - /// Get a handle for our own node. - /** This function returns a handle for the local node. - * - * @return A pointer to a meshlink::node which represents the local node. - */ - node *get_self() { - return (node *)meshlink_get_self(handle); - } + /// Get a list of all nodes. + /** This function returns a list with handles for all known nodes. + * + * @param nodes A pointer to an array of pointers to meshlink::node, which should be allocated by the application. + * @param nmemb The maximum number of pointers that can be stored in the nodes array. + * + * @return The number of known nodes, or -1 in case of an error. + * This can be larger than nmemb, in which case not all nodes were stored in the nodes array. + */ + node **get_all_nodes(node **nodes, size_t *nmemb) { + return (node **)meshlink_get_all_nodes(handle, (meshlink_node_t **)nodes, nmemb); + } - /// Get a list of all nodes. - /** This function returns a list with handles for all known nodes. - * - * @param nodes A pointer to an array of pointers to meshlink::node, which should be allocated by the application. - * @param nmemb The maximum number of pointers that can be stored in the nodes array. - * - * @return The number of known nodes, or -1 in case of an error. - * This can be larger than nmemb, in which case not all nodes were stored in the nodes array. - */ - node **get_all_nodes(node **nodes, size_t *nmemb) { - return (node **)meshlink_get_all_nodes(handle, (meshlink_node_t **)nodes, nmemb); - } + /// Sign data using the local node's MeshLink key. + /** This function signs data using the local node's MeshLink key. + * The generated signature can be securely verified by other nodes. + * + * @param data A pointer to a buffer containing the data to be signed. + * @param len The length of the data to be signed. + * @param signature A pointer to a buffer where the signature will be stored. + * @param siglen The size of the signature buffer. Will be changed after the call to match the size of the signature itself. + * + * @return This function returns true if the signature is valid, false otherwise. + */ + bool sign(const void *data, size_t len, void *signature, size_t *siglen) { + return meshlink_sign(handle, data, len, signature, siglen); + } - /// Sign data using the local node's MeshLink key. - /** This function signs data using the local node's MeshLink key. - * The generated signature can be securely verified by other nodes. - * - * @param data A pointer to a buffer containing the data to be signed. - * @param len The length of the data to be signed. - * @param signature A pointer to a buffer where the signature will be stored. - * @param siglen The size of the signature buffer. Will be changed after the call to match the size of the signature itself. - * - * @return This function returns true if the signature is valid, false otherwise. - */ - bool sign(const void *data, size_t len, void *signature, size_t *siglen) { - return meshlink_sign(handle, data, len, signature, siglen); - } + /// Verify the signature generated by another node of a piece of data. + /** This function verifies the signature that another node generated for a piece of data. + * + * @param source A pointer to a meshlink_node_t describing the source of the signature. + * @param data A pointer to a buffer containing the data to be verified. + * @param len The length of the data to be verified. + * @param signature A pointer to a string containing the signature. + * @param siglen The size of the signature. + * + * @return This function returns true if the signature is valid, false otherwise. + */ + bool verify(node *source, const void *data, size_t len, const void *signature, size_t siglen) { + return meshlink_verify(handle, source, data, len, signature, siglen); + } - /// Verify the signature generated by another node of a piece of data. - /** This function verifies the signature that another node generated for a piece of data. - * - * @param source A pointer to a meshlink_node_t describing the source of the signature. - * @param data A pointer to a buffer containing the data to be verified. - * @param len The length of the data to be verified. - * @param signature A pointer to a string containing the signature. - * @param siglen The size of the signature. - * - * @return This function returns true if the signature is valid, false otherwise. - */ - bool verify(node *source, const void *data, size_t len, const void *signature, size_t siglen) { - return meshlink_verify(handle, source, data, len, signature, siglen); - } + /// Add an Address for the local node. + /** This function adds an Address for the local node, which will be used for invitation URLs. + * + * @param address A string containing the address, which can be either in numeric format or a hostname. + * + * @return This function returns true if the address was added, false otherwise. + */ + bool add_address(const char *address) { + return meshlink_add_address(handle, address); + } - /// Add an Address for the local node. - /** This function adds an Address for the local node, which will be used for invitation URLs. - * - * @param address A string containing the address, which can be either in numeric format or a hostname. - * - * @return This function returns true if the address was added, false otherwise. - */ - bool add_address(const char *address) { - return meshlink_add_address(handle, address); - } + /** This function performs tries to discover the local node's external address + * by contacting the meshlink.io server. If a reverse lookup of the address works, + * the FQDN associated with the address will be returned. + * + * Please note that this is function only returns a single address, + * even if the local node might have more than one external address. + * In that case, there is no control over which address will be selected. + * Also note that if you have a dynamic IP address, or are behind carrier-grade NAT, + * there is no guarantee that the external address will be valid for an extended period of time. + * + * This function is blocking. It can take several seconds before it returns. + * There is no guarantee it will be able to resolve the external address. + * Failures might be because by temporary network outages. + * + * @return This function returns a pointer to a C string containing the discovered external address, + * or NULL if there was an error looking up the address. + * After get_external_address() returns, the application is free to overwrite or free this string. + */ + bool get_external_address() { + return meshlink_get_external_address(handle); + } - /** This function performs tries to discover the local node's external address - * by contacting the meshlink.io server. If a reverse lookup of the address works, - * the FQDN associated with the address will be returned. - * - * Please note that this is function only returns a single address, - * even if the local node might have more than one external address. - * In that case, there is no control over which address will be selected. - * Also note that if you have a dynamic IP address, or are behind carrier-grade NAT, - * there is no guarantee that the external address will be valid for an extended period of time. - * - * This function is blocking. It can take several seconds before it returns. - * There is no guarantee it will be able to resolve the external address. - * Failures might be because by temporary network outages. - * - * @return This function returns a pointer to a C string containing the discovered external address, - * or NULL if there was an error looking up the address. - * After get_external_address() returns, the application is free to overwrite or free this string. - */ - bool get_external_address() { - return meshlink_get_external_address(handle); - } + /// Try to discover the external address for the local node, and add it to its list of addresses. + /** This function is equivalent to: + * + * mesh->add_address(mesh->get_external_address()); + * + * Read the description of get_external_address() for the limitations of this function. + * + * @return This function returns true if the address was added, false otherwise. + */ + bool add_external_address() { + return meshlink_add_external_address(handle); + } - /// Try to discover the external address for the local node, and add it to its list of addresses. - /** This function is equivalent to: - * - * mesh->add_address(mesh->get_external_address()); - * - * Read the description of get_external_address() for the limitations of this function. - * - * @return This function returns true if the address was added, false otherwise. - */ - bool add_external_address() { - return meshlink_add_external_address(handle); - } + /// Get the network port used by the local node. + /** This function returns the network port that the local node is listening on. + * + * @param mesh A handle which represents an instance of MeshLink. + * + * @return This function returns the port number, or -1 in case of an error. + */ + int get_port() { + return meshlink_get_port(handle); + } - /// Get the network port used by the local node. - /** This function returns the network port that the local node is listening on. - * - * @param mesh A handle which represents an instance of MeshLink. - * - * @return This function returns the port number, or -1 in case of an error. - */ - int get_port() { - return meshlink_get_port(handle); - } + /// Set the network port used by the local node. + /** This function sets the network port that the local node is listening on. + * It may only be called when the mesh is not running. + * If unsure, call stop() before calling this function. + * Also note that if your node is already part of a mesh with other nodes, + * that the other nodes may no longer be able to initiate connections to the local node, + * since they will try to connect to the previously configured port. + * + * @param port The port number to listen on. This must be between 0 and 65535. + * If the port is set to 0, then MeshLink will listen on a port + * that is randomly assigned by the operating system every time open() is called. + * + * @return This function returns true if the port was succesfully changed, false otherwise. + */ + bool set_port(int port) { + return meshlink_set_port(handle, port); + } - /// Set the network port used by the local node. - /** This function sets the network port that the local node is listening on. - * It may only be called when the mesh is not running. - * If unsure, call stop() before calling this function. - * Also note that if your node is already part of a mesh with other nodes, - * that the other nodes may no longer be able to initiate connections to the local node, - * since they will try to connect to the previously configured port. - * - * @param port The port number to listen on. This must be between 0 and 65535. - * If the port is set to 0, then MeshLink will listen on a port - * that is randomly assigned by the operating system every time open() is called. - * - * @return This function returns true if the port was succesfully changed, false otherwise. - */ - bool set_port(int port) { - return meshlink_set_port(handle, port); - } + /// 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. + * The generated invitation is a string containing a URL. + * This URL should be passed by the application to the invitee in a way that no eavesdroppers can see the URL. + * The URL can only be used once, after the user has joined the mesh the URL is no longer valid. + * + * @param name The name that the invitee will use in the mesh. + * + * @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) { + return meshlink_invite(handle, name); + } - /// 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. - * The generated invitation is a string containing a URL. - * This URL should be passed by the application to the invitee in a way that no eavesdroppers can see the URL. - * The URL can only be used once, after the user has joined the mesh the URL is no longer valid. - * - * @param name The name that the invitee will use in the mesh. - * - * @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) { - return meshlink_invite(handle, 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. + * An invitation can only be used if the local node has never connected to other nodes before. + * After a succesfully accepted invitation, the name of the local node may have changed. + * + * This function may only be called on a mesh that has not been started yet and which is not already part of an existing mesh. + * + * This function is blocking. It can take several seconds before it returns. + * There is no guarantee it will perform a successful join. + * Failures might be caused by temporary network outages, or by the invitation having expired. + * + * @param invitation A string containing the invitation URL. + * + * @return This function returns true if the local node joined the mesh it was invited to, false otherwise. + */ + bool join(const char *invitation) { + return meshlink_join(handle, invitation); + } - /// 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. - * An invitation can only be used if the local node has never connected to other nodes before. - * After a succesfully accepted invitation, the name of the local node may have changed. - * - * This function may only be called on a mesh that has not been started yet and which is not already part of an existing mesh. - * - * This function is blocking. It can take several seconds before it returns. - * There is no guarantee it will perform a successful join. - * Failures might be caused by temporary network outages, or by the invitation having expired. - * - * @param invitation A string containing the invitation URL. - * - * @return This function returns true if the local node joined the mesh it was invited to, false otherwise. - */ - bool join(const char *invitation) { - return meshlink_join(handle, invitation); - } + /// Export the local node's key and addresses. + /** This function generates a string that contains the local node's public key and one or more IP addresses. + * The application can pass it in some way to another node, which can then import it, + * granting the local node access to the other node's mesh. + * + * @return This function returns a string that contains the exported key and addresses. + * The application should call free() after it has finished using this string. + */ + char *export_key() { + return meshlink_export(handle); + } - /// Export the local node's key and addresses. - /** This function generates a string that contains the local node's public key and one or more IP addresses. - * The application can pass it in some way to another node, which can then import it, - * granting the local node access to the other node's mesh. - * - * @return This function returns a string that contains the exported key and addresses. - * The application should call free() after it has finished using this string. - */ - char *export_key() { - return meshlink_export(handle); - } + /// Import another node's key and addresses. + /** This function accepts a string containing the exported public key and addresses of another node. + * By importing this data, the local node grants the other node access to its mesh. + * + * @param data A string containing the other node's exported key and addresses. + * + * @return This function returns true if the data was valid and the other node has been granted access to the mesh, false otherwise. + */ + bool import_key(const char *data) { + return meshlink_import(handle, data); + } - /// Import another node's key and addresses. - /** This function accepts a string containing the exported public key and addresses of another node. - * By importing this data, the local node grants the other node access to its mesh. - * - * @param data A string containing the other node's exported key and addresses. - * - * @return This function returns true if the data was valid and the other node has been granted access to the mesh, false otherwise. - */ - bool import_key(const char *data) { - return meshlink_import(handle, data); - } + /// Blacklist a node from the mesh. + /** This function causes the local node to blacklist another node. + * The local node will drop any existing connections to that node, + * and will not send data to it nor accept any data received from it any more. + * + * @param node A pointer to a meshlink::node describing the node to be blacklisted. + */ + void blacklist(node *node) { + return meshlink_blacklist(handle, node); + } - /// Blacklist a node from the mesh. - /** This function causes the local node to blacklist another node. - * The local node will drop any existing connections to that node, - * and will not send data to it nor accept any data received from it any more. - * - * @param node A pointer to a meshlink::node describing the node to be blacklisted. - */ - void blacklist(node *node) { - return meshlink_blacklist(handle, node); - } + /// Set the poll callback. + /** This functions sets the callback that is called whenever data can be sent to another node. + * The callback is run in MeshLink's own thread. + * It is therefore important that the callback uses apprioriate methods (queues, pipes, locking, etc.) + * to pass data to or from the application's thread. + * The callback should also not block itself and return as quickly as possible. + * + * @param channel A handle for the channel. + * @param cb A pointer to the function which will be called when data can be sent to another node. + * If a NULL pointer is given, the callback will be disabled. + */ + void set_channel_poll_cb(channel *channel, channel_poll_cb_t cb) { + meshlink_set_channel_poll_cb(handle, channel, (meshlink_channel_poll_cb_t)cb); + } - /// Set the poll callback. - /** This functions sets the callback that is called whenever data can be sent to another node. - * The callback is run in MeshLink's own thread. - * It is therefore important that the callback uses apprioriate methods (queues, pipes, locking, etc.) - * to pass data to or from the application's thread. - * The callback should also not block itself and return as quickly as possible. - * - * @param channel A handle for the channel. - * @param cb A pointer to the function which will be called when data can be sent to another node. - * If a NULL pointer is given, the callback will be disabled. - */ - void set_channel_poll_cb(channel *channel, channel_poll_cb_t cb) { - meshlink_set_channel_poll_cb(handle, channel, (meshlink_channel_poll_cb_t)cb); - } + /// Open a reliable stream channel to another node. + /** This function is called whenever a remote node wants to open a channel to the local node. + * The application then has to decide whether to accept or reject this channel. + * + * This function sets the channel poll callback to channel_poll_trampoline, which in turn + * calls channel_poll. To set a differnt, channel-specific poll callback, use set_channel_poll_cb. + * + * @param node The node to which this channel is being initiated. + * @param port The port number the peer wishes to connect to. + * @param cb A pointer to the function which will be called when the remote node sends data to the local node. + * @param data A pointer to a buffer containing data to already queue for sending. + * @param len The length of the data. + * @param flags A bitwise-or'd combination of flags that set the semantics for this channel. + * + * @return A handle for the channel, or NULL in case of an error. + */ + channel *channel_open(node *node, uint16_t port, channel_receive_cb_t cb, const void *data, size_t len, uint32_t flags = channel::TCP) { + channel *ch = (channel *)meshlink_channel_open_ex(handle, node, port, (meshlink_channel_receive_cb_t)cb, data, len, flags); + meshlink_set_channel_poll_cb(handle, ch, &channel_poll_trampoline); + return ch; + } - /// Open a reliable stream channel to another node. - /** This function is called whenever a remote node wants to open a channel to the local node. - * The application then has to decide whether to accept or reject this channel. - * - * This function sets the channel poll callback to channel_poll_trampoline, which in turn - * calls channel_poll. To set a differnt, channel-specific poll callback, use set_channel_poll_cb. - * - * @param node The node to which this channel is being initiated. - * @param port The port number the peer wishes to connect to. - * @param cb A pointer to the function which will be called when the remote node sends data to the local node. - * @param data A pointer to a buffer containing data to already queue for sending. - * @param len The length of the data. - * @param flags A bitwise-or'd combination of flags that set the semantics for this channel. - * - * @return A handle for the channel, or NULL in case of an error. - */ - channel *channel_open(node *node, uint16_t port, channel_receive_cb_t cb, const void *data, size_t len, uint32_t flags = channel::TCP) { - channel *ch = (channel *)meshlink_channel_open_ex(handle, node, port, (meshlink_channel_receive_cb_t)cb, data, len, flags); - meshlink_set_channel_poll_cb(handle, ch, &channel_poll_trampoline); - return ch; - } + /** + * @override + * Sets channel_receive_trampoline as cb, which in turn calls this->channel_receive( ... ). + */ + channel *channel_open(node *node, uint16_t port, const void *data, size_t len, uint32_t flags = channel::TCP) { + channel *ch = (channel *)meshlink_channel_open_ex(handle, node, port, &channel_receive_trampoline, data, len, flags); + meshlink_set_channel_poll_cb(handle, ch, &channel_poll_trampoline); + return ch; + } - /** - * @override - * Sets channel_receive_trampoline as cb, which in turn calls this->channel_receive( ... ). - */ - channel *channel_open(node *node, uint16_t port, const void *data, size_t len, uint32_t flags = channel::TCP) { - channel *ch = (channel *)meshlink_channel_open_ex(handle, node, port, &channel_receive_trampoline, data, len, flags); - meshlink_set_channel_poll_cb(handle, ch, &channel_poll_trampoline); - return ch; - } + /// Partially close a reliable stream channel. + /** This shuts down the read or write side of a channel, or both, without closing the handle. + * It can be used to inform the remote node that the local node has finished sending all data on the channel, + * but still allows waiting for incoming data from the remote node. + * + * @param channel A handle for the channel. + * @param direction Must be one of SHUT_RD, SHUT_WR or SHUT_RDWR. + */ + void channel_shutdown(channel *channel, int direction) { + return meshlink_channel_shutdown(handle, channel, direction); + } - /// Partially close a reliable stream channel. - /** This shuts down the read or write side of a channel, or both, without closing the handle. - * It can be used to inform the remote node that the local node has finished sending all data on the channel, - * but still allows waiting for incoming data from the remote node. - * - * @param channel A handle for the channel. - * @param direction Must be one of SHUT_RD, SHUT_WR or SHUT_RDWR. - */ - void channel_shutdown(channel *channel, int direction) { - return meshlink_channel_shutdown(handle, channel, direction); - } + /// Close a reliable stream channel. + /** This informs the remote node that the local node has finished sending all data on the channel. + * It also causes the local node to stop accepting incoming data from the remote node. + * Afterwards, the channel handle is invalid and must not be used any more. + * + * @param channel A handle for the channel. + */ + void channel_close(meshlink_channel_t *channel) { + return meshlink_channel_close(handle, channel); + } - /// Close a reliable stream channel. - /** This informs the remote node that the local node has finished sending all data on the channel. - * It also causes the local node to stop accepting incoming data from the remote node. - * Afterwards, the channel handle is invalid and must not be used any more. - * - * @param channel A handle for the channel. - */ - void channel_close(meshlink_channel_t *channel) { - return meshlink_channel_close(handle, channel); - } + /// Transmit data on a channel + /** This queues data to send to the remote node. + * + * @param channel A handle for the channel. + * @param data A pointer to a buffer containing data sent by the source. + * @param len The length of the data. + * + * @return The amount of data that was queued, which can be less than len, or a negative value in case of an error. + */ + ssize_t channel_send(channel *channel, void *data, size_t len) { + return meshlink_channel_send(handle, channel, data, len); + } - /// Transmit data on a channel - /** This queues data to send to the remote node. - * - * @param channel A handle for the channel. - * @param data A pointer to a buffer containing data sent by the source. - * @param len The length of the data. - * - * @return The amount of data that was queued, which can be less than len, or a negative value in case of an error. - */ - ssize_t channel_send(channel *channel, void *data, size_t len) { - return meshlink_channel_send(handle, channel, data, len); - } +private: + // non-copyable: + mesh(const mesh&) /* TODO: C++11: = delete */; + void operator=(const mesh&) /* TODO: C++11: = delete */ ; + + /// static callback trampolines: + static void receive_trampoline(meshlink_handle_t* handle, meshlink_node_t* source, const void* data, size_t length) { + if(!(handle->priv)) + return; + meshlink::mesh* that = static_cast(handle->priv); + that->receive(static_cast(source), data, length); + } - private: - // non-copyable: - mesh(const mesh&) /* TODO: C++11: = delete */; - void operator=(const mesh&) /* TODO: C++11: = delete */ ; - - /// static callback trampolines: - static void receive_trampoline(meshlink_handle_t* handle, meshlink_node_t* source, const void* data, size_t length) - { - if (!(handle->priv)) - return; - meshlink::mesh* that = static_cast(handle->priv); - that->receive(static_cast(source), data, length); - } - - static void node_status_trampoline(meshlink_handle_t* handle, meshlink_node_t* peer, bool reachable) - { - if (!(handle->priv)) - return; - meshlink::mesh* that = static_cast(handle->priv); - that->node_status(static_cast(peer), reachable); - } + static void node_status_trampoline(meshlink_handle_t* handle, meshlink_node_t* peer, bool reachable) { + if(!(handle->priv)) + return; + meshlink::mesh* that = static_cast(handle->priv); + that->node_status(static_cast(peer), reachable); + } - static void log_trampoline(meshlink_handle_t* handle, log_level_t level, const char* message) - { - if (!(handle->priv)) - return; - meshlink::mesh* that = static_cast(handle->priv); - that->log(level, message); - } + static void log_trampoline(meshlink_handle_t* handle, log_level_t level, const char* message) { + if(!(handle->priv)) + return; + meshlink::mesh* that = static_cast(handle->priv); + that->log(level, message); + } - static bool channel_accept_trampoline(meshlink_handle_t *handle, meshlink_channel *channel, uint16_t port, const void *data, size_t len) - { - if (!(handle->priv)) - return false; - meshlink::mesh* that = static_cast(handle->priv); - bool accepted = that->channel_accept(static_cast(channel), port, data, len); - if (accepted) - { - meshlink_set_channel_receive_cb(handle, channel, &channel_receive_trampoline); - meshlink_set_channel_poll_cb(handle, channel, &channel_poll_trampoline); - } - return accepted; + static bool channel_accept_trampoline(meshlink_handle_t *handle, meshlink_channel *channel, uint16_t port, const void *data, size_t len) { + if(!(handle->priv)) + return false; + meshlink::mesh* that = static_cast(handle->priv); + bool accepted = that->channel_accept(static_cast(channel), port, data, len); + if(accepted) { + meshlink_set_channel_receive_cb(handle, channel, &channel_receive_trampoline); + meshlink_set_channel_poll_cb(handle, channel, &channel_poll_trampoline); } + return accepted; + } - static void channel_receive_trampoline(meshlink_handle_t *handle, meshlink_channel *channel, const void* data, size_t len) - { - if (!(handle->priv)) - return; - meshlink::mesh* that = static_cast(handle->priv); - that->channel_receive(static_cast(channel), data, len); - } + static void channel_receive_trampoline(meshlink_handle_t *handle, meshlink_channel *channel, const void* data, size_t len) { + if(!(handle->priv)) + return; + meshlink::mesh* that = static_cast(handle->priv); + that->channel_receive(static_cast(channel), data, len); + } - static void channel_poll_trampoline(meshlink_handle_t *handle, meshlink_channel *channel, size_t len) - { - if (!(handle->priv)) - return; - meshlink::mesh* that = static_cast(handle->priv); - that->channel_poll(static_cast(channel), len); - } + static void channel_poll_trampoline(meshlink_handle_t *handle, meshlink_channel *channel, size_t len) { + if(!(handle->priv)) + return; + meshlink::mesh* that = static_cast(handle->priv); + that->channel_poll(static_cast(channel), len); + } - meshlink_handle_t* handle; - }; + meshlink_handle_t* handle; +}; - static const char *strerror(errno_t err = meshlink_errno) { - return meshlink_strerror(err); - } +static const char *strerror(errno_t err = meshlink_errno) { + return meshlink_strerror(err); +} - /// Destroy a MeshLink instance. - /** This function remove all configuration files of a MeshLink instance. It should only be called when the application - * does not have an open handle to this instance. Afterwards, a call to meshlink_open() will create a completely - * new instance. - * - * @param confbase The directory in which MeshLink stores its configuration files. - * After the function returns, the application is free to overwrite or free @a confbase @a. - * - * @return This function will return true if the MeshLink instance was succesfully destroyed, false otherwise. - */ - static bool destroy(const char *confbase) { - return meshlink_destroy(confbase); - } +/// Destroy a MeshLink instance. +/** This function remove all configuration files of a MeshLink instance. It should only be called when the application + * does not have an open handle to this instance. Afterwards, a call to meshlink_open() will create a completely + * new instance. + * + * @param confbase The directory in which MeshLink stores its configuration files. + * After the function returns, the application is free to overwrite or free @a confbase @a. + * + * @return This function will return true if the MeshLink instance was succesfully destroyed, false otherwise. + */ +static bool destroy(const char *confbase) { + return meshlink_destroy(confbase); +} } #endif // MESHLINKPP_H diff --git a/src/meshlink.c b/src/meshlink.c index a69b3851..4a8cef20 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -165,9 +165,9 @@ static void scan_for_hostname(const char *filename, char **hostname, char **port p += strspn(p, "\t "); p[strcspn(p, "\t ")] = 0; - if(!*port && !strcasecmp(line, "Port")) { + if(!*port && !strcasecmp(line, "Port")) *port = xstrdup(q); - } else if(!*hostname && !strcasecmp(line, "Address")) { + else if(!*hostname && !strcasecmp(line, "Address")) { *hostname = xstrdup(q); if(*p) { free(*port); @@ -278,9 +278,8 @@ static char *get_my_hostname(meshlink_handle_t* mesh) { if(f) { fprintf(f, "\nAddress = %s\n", hostname); fclose(f); - } else { + } else logger(mesh, MESHLINK_DEBUG, "Could not append Address to %s: %s\n", filename, strerror(errno)); - } done: if(port) { @@ -531,7 +530,7 @@ static bool finalize_join(meshlink_handle_t *mesh) { if(!b64key) { fclose(fh); return false; - } + } fprintf(fh, "ECDSAPublicKey = %s\n", b64key); fprintf(fh, "Port = %s\n", mesh->myport); @@ -570,28 +569,28 @@ static bool invitation_send(void *handle, uint8_t type, const void *data, size_t static bool invitation_receive(void *handle, uint8_t type, const void *msg, uint16_t len) { meshlink_handle_t* mesh = handle; switch(type) { - case SPTPS_HANDSHAKE: - return sptps_send_record(&(mesh->sptps), 0, mesh->cookie, sizeof mesh->cookie); - - case 0: - mesh->data = xrealloc(mesh->data, mesh->thedatalen + len + 1); - memcpy(mesh->data + mesh->thedatalen, msg, len); - mesh->thedatalen += len; - mesh->data[mesh->thedatalen] = 0; - break; + case SPTPS_HANDSHAKE: + return sptps_send_record(&(mesh->sptps), 0, mesh->cookie, sizeof mesh->cookie); - case 1: - mesh->thedatalen = 0; - return finalize_join(mesh); + case 0: + mesh->data = xrealloc(mesh->data, mesh->thedatalen + len + 1); + memcpy(mesh->data + mesh->thedatalen, msg, len); + mesh->thedatalen += len; + mesh->data[mesh->thedatalen] = 0; + break; - case 2: - logger(mesh, MESHLINK_DEBUG, "Invitation succesfully accepted.\n"); - shutdown(mesh->sock, SHUT_RDWR); - mesh->success = true; - break; + case 1: + mesh->thedatalen = 0; + return finalize_join(mesh); - default: - return false; + case 2: + logger(mesh, MESHLINK_DEBUG, "Invitation succesfully accepted.\n"); + shutdown(mesh->sock, SHUT_RDWR); + mesh->success = true; + break; + + default: + return false; } return true; @@ -845,7 +844,7 @@ static bool meshlink_setup(meshlink_handle_t *mesh) { meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const char* appname, dev_class_t devclass) { // Validate arguments provided by the application bool usingname = false; - + logger(NULL, MESHLINK_DEBUG, "meshlink_open called\n"); if(!confbase || !*confbase) { @@ -863,14 +862,14 @@ meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const c if(!name || !*name) { logger(NULL, MESHLINK_ERROR, "No name given!\n"); //return NULL; - } - else { //check name only if there is a name != NULL + } else { //check name only if there is a name != NULL if(!check_id(name)) { logger(NULL, MESHLINK_ERROR, "Invalid name given!\n"); meshlink_errno = MESHLINK_EINVAL; return NULL; - } else { usingname = true;} + } else + usingname = true; } if(devclass < 0 || devclass > _DEV_CLASS_MAX) { @@ -883,14 +882,14 @@ meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const c mesh->confbase = xstrdup(confbase); mesh->appname = xstrdup(appname); mesh->devclass = devclass; - if (usingname) mesh->name = xstrdup(name); + if(usingname) mesh->name = xstrdup(name); // initialize mutex pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&(mesh->mesh_mutex), &attr); - + mesh->threadstarted = false; event_loop_init(&mesh->loop); mesh->loop.data = mesh; @@ -967,7 +966,7 @@ bool meshlink_start(meshlink_handle_t *mesh) { meshlink_errno = MESHLINK_EINVAL; return false; } - + logger(mesh, MESHLINK_DEBUG, "meshlink_start called\n"); pthread_mutex_lock(&(mesh->mesh_mutex)); @@ -989,7 +988,7 @@ bool meshlink_start(meshlink_handle_t *mesh) { // TODO: open listening sockets first //Check that a valid name is set - if(!mesh->name ) { + if(!mesh->name) { logger(mesh, MESHLINK_DEBUG, "No name given!\n"); meshlink_errno = MESHLINK_EINVAL; pthread_mutex_unlock(&(mesh->mesh_mutex)); @@ -1194,7 +1193,7 @@ bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const // leave the last byte as 0 to make sure strings are always // null-terminated if they are longer than the buffer strncpy(hdr->destination, destination->name, (sizeof hdr->destination) - 1); - strncpy(hdr->source, mesh->self->name, (sizeof hdr->source) -1 ); + strncpy(hdr->source, mesh->self->name, (sizeof hdr->source) -1); memcpy(packet->data + sizeof *hdr, data, len); @@ -1207,7 +1206,7 @@ bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const // Notify event loop signal_trigger(&(mesh->loop),&(mesh->datafromapp)); - + return true; } @@ -1232,13 +1231,11 @@ ssize_t meshlink_get_pmtu(meshlink_handle_t *mesh, meshlink_node_t *destination) if(!n->status.reachable) { pthread_mutex_unlock(&(mesh->mesh_mutex)); return 0; - - } - else if(n->mtuprobes > 30 && n->minmtu) { + + } else if(n->mtuprobes > 30 && n->minmtu) { pthread_mutex_unlock(&(mesh->mesh_mutex)); return n->minmtu; - } - else { + } else { pthread_mutex_unlock(&(mesh->mesh_mutex)); return MTU; } @@ -1364,16 +1361,15 @@ bool meshlink_verify(meshlink_handle_t *mesh, meshlink_node_t *source, const voi if(!n->ecdsa) { meshlink_errno = MESHLINK_EINTERNAL; rval = false; - } else { + } else rval = ecdsa_verify(((struct node_t *)source)->ecdsa, data, len, signature); - } pthread_mutex_unlock(&(mesh->mesh_mutex)); return rval; } static bool refresh_invitation_key(meshlink_handle_t *mesh) { char filename[PATH_MAX]; - + pthread_mutex_lock(&(mesh->mesh_mutex)); snprintf(filename, sizeof filename, "%s" SLASH "invitations", mesh->confbase); @@ -1587,7 +1583,7 @@ char *meshlink_invite(meshlink_handle_t *mesh, const char *name) { meshlink_errno = MESHLINK_EINVAL; return NULL; } - + pthread_mutex_lock(&(mesh->mesh_mutex)); // Check validity of the new node's name @@ -1670,7 +1666,7 @@ char *meshlink_invite(meshlink_handle_t *mesh, const char *name) { // Fill in the details. fprintf(f, "Name = %s\n", name); //if(netname) - // fprintf(f, "NetName = %s\n", netname); + // fprintf(f, "NetName = %s\n", netname); fprintf(f, "ConnectTo = %s\n", mesh->self->name); // Copy Broadcast and Mode @@ -1680,7 +1676,7 @@ char *meshlink_invite(meshlink_handle_t *mesh, const char *name) { char buf[1024]; while(fgets(buf, sizeof buf, tc)) { if((!strncasecmp(buf, "Mode", 4) && strchr(" \t=", buf[4])) - || (!strncasecmp(buf, "Broadcast", 9) && strchr(" \t=", buf[9]))) { + || (!strncasecmp(buf, "Broadcast", 9) && strchr(" \t=", buf[9]))) { fputs(buf, f); // Make sure there is a newline character. if(!strchr(buf, '\n')) @@ -1716,7 +1712,7 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { meshlink_errno = MESHLINK_EINVAL; return false; } - + pthread_mutex_lock(&(mesh->mesh_mutex)); //TODO: think of a better name for this variable, or of a different way to tokenize the invitation URL. @@ -1767,9 +1763,8 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { char *b64key = ecdsa_get_base64_public_key(key); //Before doing meshlink_join make sure we are not connected to another mesh - if ( mesh->threadstarted ){ + if(mesh->threadstarted) goto invalid; - } // Connect to the meshlink daemon mentioned in the URL. struct addrinfo *ai = str2addrinfo(address, port, SOCK_STREAM); @@ -1914,7 +1909,7 @@ char *meshlink_export(meshlink_handle_t *mesh) { } pthread_mutex_lock(&(mesh->mesh_mutex)); - + char filename[PATH_MAX]; snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->self->name); FILE *f = fopen(filename, "r"); @@ -1942,7 +1937,7 @@ char *meshlink_export(meshlink_handle_t *mesh) { fclose(f); buf[len - 1] = 0; - + pthread_mutex_unlock(&(mesh->mesh_mutex)); return buf; } @@ -1952,7 +1947,7 @@ bool meshlink_import(meshlink_handle_t *mesh, const char *data) { meshlink_errno = MESHLINK_EINVAL; return false; } - + pthread_mutex_lock(&(mesh->mesh_mutex)); if(strncmp(data, "Name = ", 7)) { @@ -2021,7 +2016,7 @@ void meshlink_blacklist(meshlink_handle_t *mesh, meshlink_node_t *node) { } pthread_mutex_lock(&(mesh->mesh_mutex)); - + node_t *n; n = (node_t*)node; n->status.blacklisted=true; @@ -2041,7 +2036,7 @@ void meshlink_whitelist(meshlink_handle_t *mesh, meshlink_node_t *node) { } pthread_mutex_lock(&(mesh->mesh_mutex)); - + node_t *n = (node_t *)node; n->status.blacklisted = false; @@ -2065,15 +2060,15 @@ void meshlink_hint_address(meshlink_handle_t *mesh, meshlink_node_t *node, const // Ignore hints about ourself. if((node_t *)node == mesh->self) return; - + pthread_mutex_lock(&(mesh->mesh_mutex)); - + char *host = NULL, *port = NULL, *str = NULL; sockaddr2str((const sockaddr_t *)addr, &host, &port); if(host && port) { xasprintf(&str, "%s %s", host, port); - if ( (strncmp ("fe80",host,4) != 0) && ( strncmp("127.",host,4) != 0 ) && ( strcmp("localhost",host) !=0 ) ) + if((strncmp("fe80",host,4) != 0) && (strncmp("127.",host,4) != 0) && (strcmp("localhost",host) !=0)) append_config_file(mesh, node->name, "Address", str); else logger(mesh, MESHLINK_DEBUG, "Not adding Link Local IPv6 Address to config\n"); @@ -2098,7 +2093,7 @@ meshlink_edge_t **meshlink_get_all_edges_state(meshlink_handle_t *mesh, meshlink } pthread_mutex_lock(&(mesh->mesh_mutex)); - + meshlink_edge_t **result = NULL; meshlink_edge_t *copy = NULL; int result_size = 0; @@ -2106,11 +2101,10 @@ meshlink_edge_t **meshlink_get_all_edges_state(meshlink_handle_t *mesh, meshlink result_size = mesh->edges->count; // if result is smaller than edges, we have to dealloc all the excess meshlink_edge_t - if(result_size > *nmemb) { - result = realloc(edges, result_size * sizeof (meshlink_edge_t*)); - } else { + if(result_size > *nmemb) + result = realloc(edges, result_size * sizeof(meshlink_edge_t*)); + else result = edges; - } if(result) { meshlink_edge_t **p = result; @@ -2123,12 +2117,10 @@ meshlink_edge_t **meshlink_get_all_edges_state(meshlink_handle_t *mesh, meshlink } n++; // the first *nmemb members of result can be re-used - if(n > *nmemb) { + if(n > *nmemb) copy = xzalloc(sizeof *copy); - } - else { + else copy = *p; - } copy->from = (meshlink_node_t*)e->from; copy->to = (meshlink_node_t*)e->to; copy->address = e->address.storage; @@ -2137,10 +2129,9 @@ meshlink_edge_t **meshlink_get_all_edges_state(meshlink_handle_t *mesh, meshlink *p++ = copy; } // shrink result to the actual amount of memory used - for(int i = *nmemb; i > result_size; i--) { + for(int i = *nmemb; i > result_size; i--) free(result[i - 1]); - } - result = realloc(result, result_size * sizeof (meshlink_edge_t*)); + result = realloc(result, result_size * sizeof(meshlink_edge_t*)); *nmemb = result_size; } else { *nmemb = 0; @@ -2231,9 +2222,8 @@ void meshlink_set_channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_ac mesh->channel_accept_cb = cb; mesh->receive_cb = channel_receive; for splay_each(node_t, n, mesh->nodes) { - if(!n->utcp && n != mesh->self) { + if(!n->utcp && n != mesh->self) n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n); - } } pthread_mutex_unlock(&mesh->mesh_mutex); } @@ -2345,8 +2335,8 @@ static void __attribute__((destructor)) meshlink_exit(void) { /// Device class traits dev_class_traits_t dev_class_traits[_DEV_CLASS_MAX +1] = { - { .min_connects = 3, .max_connects = 10000, .edge_weight = 1 }, // DEV_CLASS_BACKBONE - { .min_connects = 3, .max_connects = 100, .edge_weight = 3 }, // DEV_CLASS_STATIONARY - { .min_connects = 3, .max_connects = 3, .edge_weight = 6 }, // DEV_CLASS_PORTABLE - { .min_connects = 1, .max_connects = 1, .edge_weight = 9 }, // DEV_CLASS_UNKNOWN + { .min_connects = 3, .max_connects = 10000, .edge_weight = 1 }, // DEV_CLASS_BACKBONE + { .min_connects = 3, .max_connects = 100, .edge_weight = 3 }, // DEV_CLASS_STATIONARY + { .min_connects = 3, .max_connects = 3, .edge_weight = 6 }, // DEV_CLASS_PORTABLE + { .min_connects = 1, .max_connects = 1, .edge_weight = 9 }, // DEV_CLASS_UNKNOWN }; diff --git a/src/meshlink.h b/src/meshlink.h index 5ac1e84d..e307128f 100644 --- a/src/meshlink.h +++ b/src/meshlink.h @@ -115,15 +115,15 @@ struct meshlink_channel { /// An edge in the meshlink network. struct meshlink_edge { struct meshlink_node *from; ///< Pointer to a node. Node memory is - // owned by meshlink and should not be - // deallocated. Node contents may be - // changed by meshlink. + // owned by meshlink and should not be + // deallocated. Node contents may be + // changed by meshlink. struct meshlink_node *to; ///< Pointer to a node. Node memory is - // owned by meshlink and should not be - // deallocated. Node contents may be - // changed by meshlink. + // owned by meshlink and should not be + // deallocated. Node contents may be + // changed by meshlink. struct sockaddr_storage address;///< The address information associated - // with this edge. + // with this edge. uint32_t options; ///< Edge options. @TODO what are edge options? int weight; ///< Weight assigned to this edge. }; @@ -702,7 +702,7 @@ extern void meshlink_set_channel_poll_cb(meshlink_handle_t *mesh, meshlink_chann * @param data A pointer to a buffer containing data to already queue for sending, or NULL if there is no data to send. * After meshlink_send() returns, the application is free to overwrite or free this buffer. * @param len The length of the data, or 0 if there is no data to send. - * @param flags A bitwise-or'd combination of flags that set the semantics for this channel. + * @param flags A bitwise-or'd combination of flags that set the semantics for this channel. * * @return A handle for the channel, or NULL in case of an error. * The handle is valid until meshlink_channel_close() is called. @@ -818,7 +818,7 @@ extern void meshlink_hint_address(meshlink_handle_t *mesh, meshlink_node_t *node * on the array to change its size. * The contents of this variable will be changed to reflect * the new size of the array. - * @return A pointer to an array containing pointers to all known + * @return A pointer to an array containing pointers to all known * edges, or NULL in case of an error. * If the @a edges @a argument was not NULL, then the * retun value can be either the same value or a different diff --git a/src/meshlink_internal.h b/src/meshlink_internal.h index 08f74071..710acdd7 100644 --- a/src/meshlink_internal.h +++ b/src/meshlink_internal.h @@ -122,8 +122,8 @@ struct meshlink_handle { struct connection_t *everyone; struct ecdsa *invitation_key; - int pinginterval; /* seconds between pings */ - int pingtimeout; /* seconds to wait for response */ + int pinginterval; /* seconds between pings */ + int pingtimeout; /* seconds to wait for response */ int maxtimeout; int sock; @@ -165,7 +165,7 @@ struct meshlink_channel { typedef struct meshlink_packethdr { uint8_t destination[16]; uint8_t source[16]; -} __attribute__ ((__packed__)) meshlink_packethdr_t; +} __attribute__((__packed__)) meshlink_packethdr_t; extern void meshlink_send_from_queue(event_loop_t* el,meshlink_handle_t *mesh); extern void update_node_status(meshlink_handle_t *mesh, struct node_t *n); diff --git a/src/meshlink_queue.h b/src/meshlink_queue.h index 05b58d9a..c86bf660 100644 --- a/src/meshlink_queue.h +++ b/src/meshlink_queue.h @@ -26,8 +26,8 @@ #include typedef struct meshlink_queue { - struct meshlink_queue_item *head; - struct meshlink_queue_item *tail; + struct meshlink_queue_item *head; + struct meshlink_queue_item *tail; pthread_mutex_t mutex; } meshlink_queue_t; diff --git a/src/meta.c b/src/meta.c index a51df8dd..9420a49b 100644 --- a/src/meta.c +++ b/src/meta.c @@ -50,7 +50,7 @@ bool send_meta(meshlink_handle_t *mesh, connection_t *c, const char *buffer, int } logger(mesh, MESHLINK_DEBUG, "Sending %d bytes of metadata to %s (%s)", length, - c->name, c->hostname); + c->name, c->hostname); if(c->allow_request == ID) { buffer_add(&c->outbuf, buffer, length); @@ -116,12 +116,12 @@ bool receive_meta(meshlink_handle_t *mesh, connection_t *c) { if(inlen <= 0) { if(!inlen || !errno) { logger(mesh, MESHLINK_INFO, "Connection closed by %s (%s)", - c->name, c->hostname); + c->name, c->hostname); } else if(sockwouldblock(sockerrno)) return true; else logger(mesh, MESHLINK_ERROR, "Metadata socket read error for %s (%s): %s", - c->name, c->hostname, sockstrerror(sockerrno)); + c->name, c->hostname, sockstrerror(sockerrno)); return false; } @@ -145,9 +145,8 @@ bool receive_meta(meshlink_handle_t *mesh, connection_t *c) { if(c->inbuf.len >= sizeof inbuf) { logger(mesh, MESHLINK_ERROR, "Input buffer full for %s (%s)", c->name, c->hostname); return false; - } else { + } else return true; - } } return sptps_receive_data(&c->sptps, inbuf, inlen); diff --git a/src/net.c b/src/net.c index 1e04bc9a..03bac617 100644 --- a/src/net.c +++ b/src/net.c @@ -112,14 +112,13 @@ static void timeout_handler(event_loop_t *loop, void *data) { } if(c->last_ping_time + mesh->pingtimeout <= mesh->loop.now.tv_sec) { if(c->status.active) { - if(c->status.pinged) { + if(c->status.pinged) logger(mesh, MESHLINK_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)mesh->loop.now.tv_sec - c->last_ping_time); - } else if(c->last_ping_time + mesh->pinginterval <= mesh->loop.now.tv_sec) { + else if(c->last_ping_time + mesh->pinginterval <= mesh->loop.now.tv_sec) { send_ping(mesh, c); continue; - } else { + } else continue; - } } else { if(c->status.connecting) logger(mesh, MESHLINK_WARNING, "Timeout while connecting to %s (%s)", c->name, c->hostname); @@ -130,19 +129,20 @@ static void timeout_handler(event_loop_t *loop, void *data) { } } - timeout_set(&mesh->loop, data, &(struct timeval){mesh->pingtimeout, rand() % 100000}); + timeout_set(&mesh->loop, data, &(struct timeval) { + mesh->pingtimeout, rand() % 100000 + }); } // devclass asc, last_successfull_connection desc -static int node_compare_devclass_asc_lsc_desc(const void *a, const void *b) -{ +static int node_compare_devclass_asc_lsc_desc(const void *a, const void *b) { const node_t *na = a, *nb = b; if(na->devclass < nb->devclass) - { return -1; } + return -1; if(na->devclass > nb->devclass) - { return 1; } + return 1; if(na->last_successfull_connection == nb->last_successfull_connection) return 0; @@ -163,8 +163,7 @@ static int node_compare_devclass_asc_lsc_desc(const void *a, const void *b) } // last_successfull_connection desc -static int node_compare_lsc_desc(const void *a, const void *b) -{ +static int node_compare_lsc_desc(const void *a, const void *b) { const node_t *na = a, *nb = b; if(na->last_successfull_connection == nb->last_successfull_connection) @@ -186,15 +185,14 @@ static int node_compare_lsc_desc(const void *a, const void *b) } // devclass desc -static int node_compare_devclass_desc(const void *a, const void *b) -{ +static int node_compare_devclass_desc(const void *a, const void *b) { const node_t *na = a, *nb = b; if(na->devclass < nb->devclass) - { return -1; } + return -1; if(na->devclass > nb->devclass) - { return 1; } + return 1; if(na < nb) return -1; @@ -210,90 +208,90 @@ static int node_compare_devclass_desc(const void *a, const void *b) autoconnect() { - timeout = 5 + timeout = 5 - // find the best one for initial connect + // find the best one for initial connect - if cur < min - newcon = - first from nodes - where dclass <= my.dclass and !connection and (timestamp - last_retry) > retry_timeout - order by dclass asc, last_connection desc - if newcon - timeout = 0 - goto connect + if cur < min + newcon = + first from nodes + where dclass <= my.dclass and !connection and (timestamp - last_retry) > retry_timeout + order by dclass asc, last_connection desc + if newcon + timeout = 0 + goto connect - // find better nodes to connect to: in case we have less than min connections within [BACKBONE, i] and there are nodes which we are not connected to within the range + // find better nodes to connect to: in case we have less than min connections within [BACKBONE, i] and there are nodes which we are not connected to within the range - if min <= cur < max - j = 0 - for i = BACKBONE to my.dclass - j += count(from connections where node.dclass = i) - if j < min - newcon = - first from nodes - where dclass = i and !connection and (timestamp - last_retry) > retry_timeout - order by last_connection desc - if newcon - goto connect - else - break + if min <= cur < max + j = 0 + for i = BACKBONE to my.dclass + j += count(from connections where node.dclass = i) + if j < min + newcon = + first from nodes + where dclass = i and !connection and (timestamp - last_retry) > retry_timeout + order by last_connection desc + if newcon + goto connect + else + break - // heal partitions + // heal partitions - if min <= cur < max - newcon = - first from nodes - where dclass <= my.dclass and !reachable and (timestamp - last_retry) > retry_timeout - order by dclass asc, last_connection desc - if newcon - goto connect + if min <= cur < max + newcon = + first from nodes + where dclass <= my.dclass and !reachable and (timestamp - last_retry) > retry_timeout + order by dclass asc, last_connection desc + if newcon + goto connect - // connect + // connect connect: - if newcon - connect newcon - - - // disconnect outgoing connections in case we have more than min connections within [BACKBONE, i] and there are nodes which we are connected to within the range [i, PORTABLE] - - if min < cur <= max - j = 0 - for i = BACKBONE to my.dclass - j += count(from connections where node.dclass = i) - if min < j - delcon = - first from nodes - where dclass >= i and outgoing_connection - order by dclass desc - if disconnect - goto disconnect - else - break + if newcon + connect newcon + + // disconnect outgoing connections in case we have more than min connections within [BACKBONE, i] and there are nodes which we are connected to within the range [i, PORTABLE] - // disconnect connections in case we have more than enough connections + if min < cur <= max + j = 0 + for i = BACKBONE to my.dclass + j += count(from connections where node.dclass = i) + if min < j + delcon = + first from nodes + where dclass >= i and outgoing_connection + order by dclass desc + if disconnect + goto disconnect + else + break - if max < cur - delcon = - first from nodes - where outgoing_connection - order by dclass desc - goto disconnect - // disconnect + // disconnect connections in case we have more than enough connections + + if max < cur + delcon = + first from nodes + where outgoing_connection + order by dclass desc + goto disconnect + + // disconnect disconnect - if delcon - disconnect delcon + if delcon + disconnect delcon - // next iteration - next (timeout, autoconnect) + // next iteration + next (timeout, autoconnect) } @@ -348,12 +346,9 @@ static void periodic_handler(event_loop_t *loop, void *data) { int cur_connects = 0; - for list_each(connection_t, c, mesh->connections) - { + for list_each(connection_t, c, mesh->connections) { if(c->status.active) - { cur_connects += 1; - } } logger(mesh, MESHLINK_DEBUG, "* cur_connects = %d", cur_connects); @@ -372,26 +367,22 @@ static void periodic_handler(event_loop_t *loop, void *data) { // find the best one for initial connect - if(cur_connects < min_connects) - { + if(cur_connects < min_connects) { splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_asc_lsc_desc, NULL); - for splay_each(node_t, n, mesh->nodes) - { + for splay_each(node_t, n, mesh->nodes) { logger(mesh, MESHLINK_DEBUG, "* n->devclass = %d", n->devclass); if(n != mesh->self && n->devclass <= mesh->devclass && !n->connection && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) - { splay_insert(nodes, n); } + splay_insert(nodes, n); } - if(nodes->head) - { + if(nodes->head) { logger(mesh, MESHLINK_DEBUG, "* found best one for initial connect"); //timeout = 0; connect_to = (node_t*)nodes->head->data; - } - else - { logger(mesh, MESHLINK_DEBUG, "* could not find node for initial connect"); } + } else + logger(mesh, MESHLINK_DEBUG, "* could not find node for initial connect"); splay_free_tree(nodes); } @@ -399,30 +390,24 @@ static void periodic_handler(event_loop_t *loop, void *data) { // find better nodes to connect to - if(!connect_to && min_connects <= cur_connects && cur_connects < max_connects) - { + if(!connect_to && min_connects <= cur_connects && cur_connects < max_connects) { unsigned int connects = 0; - for(int devclass = 0; devclass <= mesh->devclass; ++devclass) - { - for list_each(connection_t, c, mesh->connections) - { + for(int devclass = 0; devclass <= mesh->devclass; ++devclass) { + for list_each(connection_t, c, mesh->connections) { if(c->status.active && c->node && c->node->devclass == devclass) - { connects += 1; } + connects += 1; } - if( connects < min_connects ) - { + if(connects < min_connects) { splay_tree_t *nodes = splay_alloc_tree(node_compare_lsc_desc, NULL); - for splay_each(node_t, n, mesh->nodes) - { + for splay_each(node_t, n, mesh->nodes) { if(n != mesh->self && n->devclass == devclass && !n->connection && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) - { splay_insert(nodes, n); } + splay_insert(nodes, n); } - if(nodes->head) - { + if(nodes->head) { logger(mesh, MESHLINK_DEBUG, "* found better node"); connect_to = (node_t*)nodes->head->data; @@ -431,35 +416,30 @@ static void periodic_handler(event_loop_t *loop, void *data) { } splay_free_tree(nodes); - } - else - { break; } + } else + break; } if(!connect_to) - { logger(mesh, MESHLINK_DEBUG, "* could not find better nodes"); } + logger(mesh, MESHLINK_DEBUG, "* could not find better nodes"); } // heal partitions - if(!connect_to && min_connects <= cur_connects && cur_connects < max_connects) - { + if(!connect_to && min_connects <= cur_connects && cur_connects < max_connects) { splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_asc_lsc_desc, NULL); - for splay_each(node_t, n, mesh->nodes) - { + for splay_each(node_t, n, mesh->nodes) { if(n != mesh->self && n->devclass <= mesh->devclass && !n->status.reachable && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) - { splay_insert(nodes, n); } + splay_insert(nodes, n); } - if(nodes->head) - { + if(nodes->head) { logger(mesh, MESHLINK_DEBUG, "* try to heal partition"); connect_to = (node_t*)nodes->head->data; - } - else - { logger(mesh, MESHLINK_DEBUG, "* could not find nodes for partition healing"); } + } else + logger(mesh, MESHLINK_DEBUG, "* could not find nodes for partition healing"); splay_free_tree(nodes); } @@ -467,61 +447,50 @@ static void periodic_handler(event_loop_t *loop, void *data) { // perform connect - if(connect_to && !connect_to->connection) - { + if(connect_to && !connect_to->connection) { connect_to->last_connect_try = time(NULL); /* check if there is already a connection attempt to this node */ bool found = false; - for list_each(outgoing_t, outgoing, mesh->outgoings) - { - if(!strcmp(outgoing->name, connect_to->name)) - { + for list_each(outgoing_t, outgoing, mesh->outgoings) { + if(!strcmp(outgoing->name, connect_to->name)) { found = true; break; } } - if(!found) - { + if(!found) { logger(mesh, MESHLINK_DEBUG, "Autoconnecting to %s", connect_to->name); outgoing_t *outgoing = xzalloc(sizeof(outgoing_t)); outgoing->mesh = mesh; outgoing->name = xstrdup(connect_to->name); list_insert_tail(mesh->outgoings, outgoing); setup_outgoing_connection(mesh, outgoing); - } - else - { logger(mesh, MESHLINK_DEBUG, "* skip autoconnect since it is an outgoing connection already"); } + } else + logger(mesh, MESHLINK_DEBUG, "* skip autoconnect since it is an outgoing connection already"); } // disconnect suboptimal outgoing connections - if(min_connects < cur_connects /*&& cur_connects <= max_connects*/) - { + if(min_connects < cur_connects /*&& cur_connects <= max_connects*/) { unsigned int connects = 0; - for(int devclass = 0; devclass <= mesh->devclass; ++devclass) - { - for list_each(connection_t, c, mesh->connections) - { + for(int devclass = 0; devclass <= mesh->devclass; ++devclass) { + for list_each(connection_t, c, mesh->connections) { if(c->status.active && c->node && c->node->devclass == devclass) - { connects += 1; } + connects += 1; } - if( min_connects < connects ) - { + if(min_connects < connects) { splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_desc, NULL); - for list_each(connection_t, c, mesh->connections) - { + for list_each(connection_t, c, mesh->connections) { if(c->outgoing && c->node && c->node->devclass >= devclass) - { splay_insert(nodes, c->node); } + splay_insert(nodes, c->node); } - if(nodes->head) - { + if(nodes->head) { logger(mesh, MESHLINK_DEBUG, "* disconnect suboptimal outgoing connection"); disconnect_from = (node_t*)nodes->head->data; } @@ -532,31 +501,27 @@ static void periodic_handler(event_loop_t *loop, void *data) { } if(!disconnect_from) - { logger(mesh, MESHLINK_DEBUG, "* no suboptimal outgoing connections"); } + logger(mesh, MESHLINK_DEBUG, "* no suboptimal outgoing connections"); } // disconnect connections (too many connections) - if(!disconnect_from && max_connects < cur_connects) - { + if(!disconnect_from && max_connects < cur_connects) { splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_desc, NULL); - for list_each(connection_t, c, mesh->connections) - { + for list_each(connection_t, c, mesh->connections) { if(c->status.active && c->node) - { splay_insert(nodes, c->node); } + splay_insert(nodes, c->node); } - if(nodes->head) - { + if(nodes->head) { logger(mesh, MESHLINK_DEBUG, "* disconnect connection (too many connections)"); //timeout = 0; disconnect_from = (node_t*)nodes->head->data; - } - else - { logger(mesh, MESHLINK_DEBUG, "* no node we want to disconnect, even though we have too many connections"); } + } else + logger(mesh, MESHLINK_DEBUG, "* no node we want to disconnect, even though we have too many connections"); splay_free_tree(nodes); } @@ -564,8 +529,7 @@ static void periodic_handler(event_loop_t *loop, void *data) { // perform disconnect - if(disconnect_from && disconnect_from->connection) - { + if(disconnect_from && disconnect_from->connection) { logger(mesh, MESHLINK_DEBUG, "Autodisconnecting from %s", disconnect_from->connection->name); list_delete(mesh->outgoings, disconnect_from->connection->outgoing); disconnect_from->connection->outgoing = NULL; @@ -578,11 +542,13 @@ static void periodic_handler(event_loop_t *loop, void *data) { logger(mesh, MESHLINK_DEBUG, "--- autoconnect end ---"); } - timeout_set(&mesh->loop, data, &(struct timeval){timeout, rand() % 100000}); + timeout_set(&mesh->loop, data, &(struct timeval) { + timeout, rand() % 100000 + }); } void handle_meta_connection_data(meshlink_handle_t *mesh, connection_t *c) { - if (!receive_meta(mesh, c)) { + if(!receive_meta(mesh, c)) { terminate_connection(mesh, c, c->status.active); return; } @@ -593,7 +559,9 @@ void retry(meshlink_handle_t *mesh) { for list_each(outgoing_t, outgoing, mesh->outgoings) { outgoing->timeout = 0; if(outgoing->ev.cb) - timeout_set(&mesh->loop, &outgoing->ev, &(struct timeval){0, 0}); + timeout_set(&mesh->loop, &outgoing->ev, &(struct timeval) { + 0, 0 + }); } /* Check for outgoing connections that are in progress, and reset their ping timers */ @@ -603,15 +571,21 @@ void retry(meshlink_handle_t *mesh) { } /* Kick the ping timeout handler */ - timeout_set(&mesh->loop, &mesh->pingtimer, &(struct timeval){0, 0}); + timeout_set(&mesh->loop, &mesh->pingtimer, &(struct timeval) { + 0, 0 + }); } /* this is where it all happens... */ int main_loop(meshlink_handle_t *mesh) { - timeout_add(&mesh->loop, &mesh->pingtimer, timeout_handler, &mesh->pingtimer, &(struct timeval){mesh->pingtimeout, rand() % 100000}); - timeout_add(&mesh->loop, &mesh->periodictimer, periodic_handler, &mesh->periodictimer, &(struct timeval){0, 0}); + timeout_add(&mesh->loop, &mesh->pingtimer, timeout_handler, &mesh->pingtimer, &(struct timeval) { + mesh->pingtimeout, rand() % 100000 + }); + timeout_add(&mesh->loop, &mesh->periodictimer, periodic_handler, &mesh->periodictimer, &(struct timeval) { + 0, 0 + }); //Add signal handler mesh->datafromapp.signum = 0; diff --git a/src/net_packet.c b/src/net_packet.c index 54c38835..9fabffd7 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -103,9 +103,8 @@ static void send_mtu_probe_handler(event_loop_t *loop, void *data) { if(n->mtuprobes == 31) { timeout = mesh->pinginterval; goto end; - } else if(n->mtuprobes == 32) { + } else if(n->mtuprobes == 32) timeout = mesh->pingtimeout; - } for(int i = 0; i < 4 + mesh->localdiscovery; i++) { int len; @@ -114,11 +113,10 @@ static void send_mtu_probe_handler(event_loop_t *loop, void *data) { if(n->mtuprobes < 30 || n->maxmtu + 8 >= MTU) continue; len = n->maxmtu + 8; - } else if(n->maxmtu <= n->minmtu) { + } else if(n->maxmtu <= n->minmtu) len = n->maxmtu; - } else { + else len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu); - } if(len < 64) len = 64; @@ -138,11 +136,15 @@ static void send_mtu_probe_handler(event_loop_t *loop, void *data) { n->status.broadcast = false; end: - timeout_set(&mesh->loop, &n->mtutimeout, &(struct timeval){timeout, rand() % 100000}); + timeout_set(&mesh->loop, &n->mtutimeout, &(struct timeval) { + timeout, rand() % 100000 + }); } void send_mtu_probe(meshlink_handle_t *mesh, node_t *n) { - timeout_add(&mesh->loop, &n->mtutimeout, send_mtu_probe_handler, n, &(struct timeval){1, 0}); + timeout_add(&mesh->loop, &n->mtutimeout, send_mtu_probe_handler, n, &(struct timeval) { + 1, 0 + }); send_mtu_probe_handler(&mesh->loop, n); } @@ -171,7 +173,7 @@ static void mtu_probe_h(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet /* If we haven't established the PMTU yet, restart the discovery process. */ if(n->mtuprobes > 30) { - if (len == n->maxmtu + 8) { + if(len == n->maxmtu + 8) { logger(mesh, MESHLINK_INFO, "Increase in PMTU to %s (%s) detected, restarting PMTU discovery", n->name, n->hostname); n->maxmtu = MTU; n->mtuprobes = 10; @@ -197,9 +199,9 @@ static uint16_t compress_packet(uint8_t *dest, const uint8_t *source, uint16_t l if(level == 0) { memcpy(dest, source, len); return len; - } else if(level == 10) { + } else if(level == 10) return -1; - } else if(level < 10) { + else if(level < 10) { #ifdef HAVE_ZLIB unsigned long destlen = MAXSIZE; if(compress2(dest, &destlen, source, len, level) == Z_OK) @@ -207,9 +209,8 @@ static uint16_t compress_packet(uint8_t *dest, const uint8_t *source, uint16_t l else #endif return -1; - } else { + } else return -1; - } return -1; } @@ -218,9 +219,8 @@ static uint16_t uncompress_packet(uint8_t *dest, const uint8_t *source, uint16_t if(level == 0) { memcpy(dest, source, len); return len; - } else if(level > 9) { - return -1; - } + } else if(level > 9) + return -1; #ifdef HAVE_ZLIB else { unsigned long destlen = MAXSIZE; @@ -238,16 +238,16 @@ static uint16_t uncompress_packet(uint8_t *dest, const uint8_t *source, uint16_t static void receive_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet) { logger(mesh, MESHLINK_DEBUG, "Received packet of %d bytes from %s (%s)", - packet->len, n->name, n->hostname); + packet->len, n->name, n->hostname); - if (n->status.blacklisted) { - logger(mesh, MESHLINK_WARNING, "Dropping packet from blacklisted node %s", n->name); - } else { - n->in_packets++; - n->in_bytes += packet->len; + if(n->status.blacklisted) + logger(mesh, MESHLINK_WARNING, "Dropping packet from blacklisted node %s", n->name); + else { + n->in_packets++; + n->in_bytes += packet->len; - route(mesh, n, packet); - } + route(mesh, n, packet); + } } static bool try_mac(meshlink_handle_t *mesh, node_t *n, const vpn_packet_t *inpkt) { @@ -259,9 +259,8 @@ static void receive_udppacket(meshlink_handle_t *mesh, node_t *n, vpn_packet_t * if(!n->status.waitingforkey) { logger(mesh, MESHLINK_DEBUG, "Got packet from %s (%s) but we haven't exchanged keys yet", n->name, n->hostname); send_req_key(mesh, n); - } else { + } else logger(mesh, MESHLINK_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname); - } return; } sptps_receive_data(&n->sptps, inpkt->data, inpkt->len); @@ -306,9 +305,9 @@ static void send_sptps_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t * if(n->outcompression) { int len = compress_packet(outpkt.data, origpkt->data, origpkt->len, n->outcompression); - if(len < 0) { + if(len < 0) logger(mesh, MESHLINK_ERROR, "Error while compressing packet to %s (%s)", n->name, n->hostname); - } else if(len < origpkt->len) { + else if(len < origpkt->len) { outpkt.len = len; origpkt = &outpkt; type |= PKT_COMPRESSED; @@ -430,9 +429,8 @@ bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len) { if(!to->status.validkey) { to->incompression = mesh->self->incompression; return send_request(mesh, to->nexthop->connection, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, mesh->self->name, to->name, buf, to->incompression); - } else { + } else return send_request(mesh, to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_SPTPS, buf); - } } /* Otherwise, send the packet via UDP */ @@ -486,9 +484,8 @@ bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t memcpy(inpkt.data, data, len); mtu_probe_h(mesh, from, &inpkt, len); return true; - } else { + } else inpkt.probe = false; - } if(type & ~(PKT_COMPRESSED)) { logger(mesh, MESHLINK_ERROR, "Unexpected SPTPS record type %d len %d from %s (%s)", type, len, from->name, from->hostname); @@ -497,11 +494,10 @@ bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t if(type & PKT_COMPRESSED) { uint16_t ulen = uncompress_packet(inpkt.data, (const uint8_t *)data, len, from->incompression); - if(ulen < 0) { + if(ulen < 0) return false; - } else { + else inpkt.len = ulen; - } if(inpkt.len > MAXSIZE) abort(); } else { @@ -525,11 +521,11 @@ void send_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet) { } logger(mesh, MESHLINK_DEBUG, "Sending packet of %d bytes to %s (%s)", - packet->len, n->name, n->hostname); + packet->len, n->name, n->hostname); if(!n->status.reachable) { logger(mesh, MESHLINK_WARNING, "Node %s (%s) is not reachable", - n->name, n->hostname); + n->name, n->hostname); return; } @@ -548,7 +544,7 @@ void broadcast_packet(meshlink_handle_t *mesh, const node_t *from, vpn_packet_t send_packet(mesh, mesh->self, packet); logger(mesh, MESHLINK_INFO, "Broadcasting packet of %d bytes from %s (%s)", - packet->len, from->name, from->hostname); + packet->len, from->name, from->hostname); for list_each(connection_t, c, mesh->connections) if(c->status.active && c->status.mst && c != from->nexthop->connection) @@ -617,15 +613,14 @@ void handle_incoming_vpn_data(event_loop_t *loop, void *data, int flags) { logger(mesh, MESHLINK_WARNING, "Received UDP packet from unknown source %s", hostname); free(hostname); return; - } - else + } else return; } - if (n->status.blacklisted) { - logger(mesh, MESHLINK_WARNING, "Dropping packet from blacklisted node %s", n->name); - return; - } + if(n->status.blacklisted) { + logger(mesh, MESHLINK_WARNING, "Dropping packet from blacklisted node %s", n->name); + return; + } n->sock = ls - mesh->listen_socket; receive_udppacket(mesh, n, &pkt); diff --git a/src/net_setup.c b/src/net_setup.c index fb0cf8d0..b02dbd14 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -123,7 +123,7 @@ static bool read_invitation_key(meshlink_handle_t *mesh) { } bool node_read_devclass(meshlink_handle_t *mesh, node_t *n) { - + splay_tree_t *config_tree; char *p; @@ -131,14 +131,13 @@ bool node_read_devclass(meshlink_handle_t *mesh, node_t *n) { if(!read_host_config(mesh, config_tree, n->name)) goto exit; - if(get_config_string(lookup_config(config_tree, "DeviceClass"), &p)) - { + if(get_config_string(lookup_config(config_tree, "DeviceClass"), &p)) { n->devclass = atoi(p); free(p); } if(n->devclass < 0 || n->devclass > _DEV_CLASS_MAX) - { n->devclass = _DEV_CLASS_MAX; } + n->devclass = _DEV_CLASS_MAX; exit: exit_configuration(&config_tree); @@ -160,8 +159,7 @@ bool node_write_devclass(meshlink_handle_t *mesh, node_t *n) { config_t* cnf = lookup_config(config_tree, "DeviceClass"); - if(!cnf) - { + if(!cnf) { cnf = new_config(); cnf->variable = xstrdup("DeviceClass"); config_add(config_tree, cnf); @@ -399,9 +397,8 @@ bool setup_myself(meshlink_handle_t *mesh) { return false; if(!add_listen_address(mesh, address, NULL)) return false; - } else { + } else return false; - } } if(!mesh->listen_sockets) { diff --git a/src/net_socket.c b/src/net_socket.c index b147bfdf..251572b9 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -50,15 +50,13 @@ static void configure_tcp(connection_t *c) { #ifdef O_NONBLOCK int flags = fcntl(c->socket, F_GETFL); - if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0) { + if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0) logger(c->mesh, MESHLINK_ERROR, "fcntl for %s: %s", c->hostname, strerror(errno)); - } #elif defined(WIN32) unsigned long arg = 1; - if(ioctlsocket(c->socket, FIONBIO, &arg) != 0) { + if(ioctlsocket(c->socket, FIONBIO, &arg) != 0) logger(c->mesh, MESHLINK_ERROR, "ioctlsocket for %s: %s", c->hostname, sockstrerror(sockerrno)); - } #endif #if defined(SOL_TCP) && defined(TCP_NODELAY) @@ -166,7 +164,7 @@ int setup_vpn_in_socket(meshlink_handle_t *mesh, const sockaddr_t *sa) { if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) { closesocket(nfd); logger(mesh, MESHLINK_ERROR, "System call `%s' failed: %s", "fcntl", - strerror(errno)); + strerror(errno)); return -1; } } @@ -245,7 +243,9 @@ void retry_outgoing(meshlink_handle_t *mesh, outgoing_t *outgoing) { if(outgoing->timeout > mesh->maxtimeout) outgoing->timeout = mesh->maxtimeout; - timeout_add(&mesh->loop, &outgoing->ev, retry_outgoing_handler, outgoing, &(struct timeval){outgoing->timeout, rand() % 100000}); + timeout_add(&mesh->loop, &outgoing->ev, retry_outgoing_handler, outgoing, &(struct timeval) { + outgoing->timeout, rand() % 100000 + }); logger(mesh, MESHLINK_INFO, "Trying to re-establish outgoing connection in %d seconds", outgoing->timeout); } @@ -311,14 +311,13 @@ static void handle_meta_write(meshlink_handle_t *mesh, connection_t *c) { ssize_t outlen = send(c->socket, c->outbuf.data + c->outbuf.offset, c->outbuf.len - c->outbuf.offset, MSG_NOSIGNAL); if(outlen <= 0) { - if(!errno || errno == EPIPE) { + if(!errno || errno == EPIPE) logger(mesh, MESHLINK_INFO, "Connection closed by %s (%s)", c->name, c->hostname); - } else if(sockwouldblock(sockerrno)) { + else if(sockwouldblock(sockerrno)) { logger(mesh, MESHLINK_DEBUG, "Sending %d bytes to %s (%s) would block", c->outbuf.len - c->outbuf.offset, c->name, c->hostname); return; - } else { + } else logger(mesh, MESHLINK_ERROR, "Could not send %d bytes of data to %s (%s): %s", c->outbuf.len - c->outbuf.offset, c->name, c->hostname, strerror(errno)); - } terminate_connection(mesh, c, c->status.active); return; @@ -458,9 +457,9 @@ begin: if(!mesh->proxytype) { c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); configure_tcp(c); - } else if(mesh->proxytype == PROXY_EXEC) { + } else if(mesh->proxytype == PROXY_EXEC) do_outgoing_pipe(mesh, c, mesh->proxyhost); - } else { + else { proxyai = str2addrinfo(mesh->proxyhost, mesh->proxyport, SOCK_STREAM); if(!proxyai) { free_connection(c); @@ -493,11 +492,11 @@ begin: /* Connect */ - if(!mesh->proxytype) { + if(!mesh->proxytype) result = connect(c->socket, &c->address.sa, SALEN(c->address.sa)); - } else if(mesh->proxytype == PROXY_EXEC) { + else if(mesh->proxytype == PROXY_EXEC) result = 0; - } else { + else { result = connect(c->socket, proxyai->ai_addr, proxyai->ai_addrlen); freeaddrinfo(proxyai); } @@ -542,7 +541,7 @@ void setup_outgoing_connection(meshlink_handle_t *mesh, outgoing_t *outgoing) { outgoing->cfg = lookup_config(outgoing->config_tree, "Address"); get_config_bool(lookup_config(outgoing->config_tree, "blacklisted"), &blacklisted); - if (blacklisted) return; + if(blacklisted) return; if(!outgoing->cfg) { if(n) @@ -677,9 +676,9 @@ static void free_outgoing(outgoing_t *outgoing) { void try_outgoing_connections(meshlink_handle_t *mesh) { /* If there is no outgoing list yet, create one. Otherwise, mark all outgoings as deleted. */ - if(!mesh->outgoings) { + if(!mesh->outgoings) mesh->outgoings = list_alloc((list_action_t)free_outgoing); - } else { + else { for list_each(outgoing_t, outgoing, mesh->outgoings) outgoing->timeout = -1; } @@ -693,8 +692,8 @@ void try_outgoing_connections(meshlink_handle_t *mesh) { if(!check_id(name)) { logger(mesh, MESHLINK_ERROR, - "Invalid name for outgoing connection in %s line %d", - cfg->file, cfg->line); + "Invalid name for outgoing connection in %s line %d", + cfg->file, cfg->line); free(name); continue; } diff --git a/src/netutl.c b/src/netutl.c index 11987afd..93e58a80 100644 --- a/src/netutl.c +++ b/src/netutl.c @@ -117,10 +117,9 @@ char *sockaddr2hostname(const sockaddr_t *sa) { } err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof address, port, sizeof port, - hostnames ? 0 : (NI_NUMERICHOST | NI_NUMERICSERV)); - if(err) { + hostnames ? 0 : (NI_NUMERICHOST | NI_NUMERICSERV)); + if(err) logger(NULL, MESHLINK_ERROR, "Error while looking up hostname: %s", err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err)); - } xasprintf(&str, "%s port %s", address, port); @@ -135,23 +134,23 @@ int sockaddrcmp_noport(const sockaddr_t *a, const sockaddr_t *b) { if(result) return result; - switch (a->sa.sa_family) { - case AF_UNSPEC: - return 0; + switch(a->sa.sa_family) { + case AF_UNSPEC: + return 0; - case AF_UNKNOWN: - return strcmp(a->unknown.address, b->unknown.address); + case AF_UNKNOWN: + return strcmp(a->unknown.address, b->unknown.address); - case AF_INET: - return memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr)); + case AF_INET: + return memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr)); - case AF_INET6: - return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)); + case AF_INET6: + return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)); - default: - logger(NULL, MESHLINK_ERROR, "sockaddrcmp() was called with unknown address family %d, exitting!", - a->sa.sa_family); - abort(); + default: + logger(NULL, MESHLINK_ERROR, "sockaddrcmp() was called with unknown address family %d, exitting!", + a->sa.sa_family); + abort(); } } @@ -163,45 +162,45 @@ int sockaddrcmp(const sockaddr_t *a, const sockaddr_t *b) { if(result) return result; - switch (a->sa.sa_family) { - case AF_UNSPEC: - return 0; + switch(a->sa.sa_family) { + case AF_UNSPEC: + return 0; - case AF_UNKNOWN: - result = strcmp(a->unknown.address, b->unknown.address); + case AF_UNKNOWN: + result = strcmp(a->unknown.address, b->unknown.address); - if(result) - return result; + if(result) + return result; - return strcmp(a->unknown.port, b->unknown.port); + return strcmp(a->unknown.port, b->unknown.port); - case AF_INET: - result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof a->in.sin_addr); + case AF_INET: + result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof a->in.sin_addr); - if(result) - return result; + if(result) + return result; - return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof a->in.sin_port); + return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof a->in.sin_port); - case AF_INET6: - result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof a->in6.sin6_addr); + case AF_INET6: + result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof a->in6.sin6_addr); - if(result) - return result; + if(result) + return result; - return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof a->in6.sin6_port); + return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof a->in6.sin6_port); - default: - logger(NULL, MESHLINK_ERROR, "sockaddrcmp() was called with unknown address family %d, exitting!", - a->sa.sa_family); - abort(); + default: + logger(NULL, MESHLINK_ERROR, "sockaddrcmp() was called with unknown address family %d, exitting!", + a->sa.sa_family); + abort(); } } void sockaddrcpy(sockaddr_t *a, const sockaddr_t *b) { - if(b->sa.sa_family != AF_UNKNOWN) { + if(b->sa.sa_family != AF_UNKNOWN) *a = *b; - } else { + else { a->unknown.family = AF_UNKNOWN; a->unknown.address = xstrdup(b->unknown.address); a->unknown.port = xstrdup(b->unknown.port); diff --git a/src/netutl.h b/src/netutl.h index 2d402c2e..065f4b20 100644 --- a/src/netutl.h +++ b/src/netutl.h @@ -24,10 +24,10 @@ extern bool hostnames; -extern struct addrinfo *str2addrinfo(const char *, const char *, int) __attribute__ ((__malloc__)); +extern struct addrinfo *str2addrinfo(const char *, const char *, int) __attribute__((__malloc__)); extern sockaddr_t str2sockaddr(const char *, const char *); extern void sockaddr2str(const sockaddr_t *, char **, char **); -extern char *sockaddr2hostname(const sockaddr_t *) __attribute__ ((__malloc__)); +extern char *sockaddr2hostname(const sockaddr_t *) __attribute__((__malloc__)); extern int sockaddrcmp(const sockaddr_t *, const sockaddr_t *); extern int sockaddrcmp_noport(const sockaddr_t *, const sockaddr_t *); extern void sockaddrunmap(sockaddr_t *); diff --git a/src/node.h b/src/node.h index de33da3b..0140bb38 100644 --- a/src/node.h +++ b/src/node.h @@ -89,7 +89,7 @@ typedef struct node_t { extern void init_nodes(struct meshlink_handle *mesh); extern void exit_nodes(struct meshlink_handle *mesh); -extern node_t *new_node(void) __attribute__ ((__malloc__)); +extern node_t *new_node(void) __attribute__((__malloc__)); extern void free_node(node_t *); extern void node_add(struct meshlink_handle *mesh, node_t *); extern void node_del(struct meshlink_handle *mesh, node_t *); diff --git a/src/prf.h b/src/prf.h index 54c11f5f..67d6845f 100644 --- a/src/prf.h +++ b/src/prf.h @@ -20,6 +20,6 @@ #ifndef __MESHLINK_PRF_H__ #define __MESHLINK_PRF_H__ -extern bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) __attribute__ ((__warn_unused_result__)); +extern bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) __attribute__((__warn_unused_result__)); #endif diff --git a/src/protocol.c b/src/protocol.c index ac7c4009..b51c66b7 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -31,22 +31,22 @@ /* Jumptable for the request handlers */ static bool (*request_handlers[])(meshlink_handle_t *, connection_t *, const char *) = { - id_h, NULL, NULL, NULL /* metakey_h, challenge_h, chal_reply_h */, ack_h, - status_h, error_h, termreq_h, - ping_h, pong_h, - NULL, NULL, //add_subnet_h, del_subnet_h, - add_edge_h, del_edge_h, - key_changed_h, req_key_h, ans_key_h, tcppacket_h, NULL, //control_h, + id_h, NULL, NULL, NULL /* metakey_h, challenge_h, chal_reply_h */, ack_h, + status_h, error_h, termreq_h, + ping_h, pong_h, + NULL, NULL, //add_subnet_h, del_subnet_h, + add_edge_h, del_edge_h, + key_changed_h, req_key_h, ans_key_h, tcppacket_h, NULL, //control_h, }; /* Request names */ static char (*request_name[]) = { - "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY", "ACK", - "STATUS", "ERROR", "TERMREQ", - "PING", "PONG", - "ADD_SUBNET", "DEL_SUBNET", - "ADD_EDGE", "DEL_EDGE", "KEY_CHANGED", "REQ_KEY", "ANS_KEY", "PACKET", "CONTROL", + "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY", "ACK", + "STATUS", "ERROR", "TERMREQ", + "PING", "PONG", + "ADD_SUBNET", "DEL_SUBNET", + "ADD_EDGE", "DEL_EDGE", "KEY_CHANGED", "REQ_KEY", "ANS_KEY", "PACKET", "CONTROL", }; bool check_id(const char *id) { @@ -78,7 +78,7 @@ bool send_request(meshlink_handle_t *mesh, connection_t *c, const char *format, if(len < 0 || len > MAXBUFSIZE - 1) { logger(mesh, MESHLINK_ERROR, "Output buffer overflow while sending request to %s (%s)", - c->name, c->hostname); + c->name, c->hostname); return false; } @@ -125,9 +125,8 @@ bool receive_request(meshlink_handle_t *mesh, connection_t *c, const char *reque if((reqno < 0) || (reqno >= LAST) || !request_handlers[reqno]) { logger(mesh, MESHLINK_DEBUG, "Unknown request from %s (%s): %s", c->name, c->hostname, request); return false; - } else { + } else logger(mesh, MESHLINK_DEBUG, "Got %s from %s (%s): %s", request_name[reqno], c->name, c->hostname, request); - } if((c->allow_request != ALL) && (c->allow_request != reqno)) { logger(mesh, MESHLINK_ERROR, "Unauthorized request from %s (%s)", c->name, c->hostname); @@ -174,7 +173,9 @@ static void age_past_requests(event_loop_t *loop, void *data) { logger(mesh, MESHLINK_DEBUG, "Aging past requests: deleted %d, left %d", deleted, left); if(left) - timeout_set(&mesh->loop, &mesh->past_request_timeout, &(struct timeval){10, rand() % 100000}); + timeout_set(&mesh->loop, &mesh->past_request_timeout, &(struct timeval) { + 10, rand() % 100000 + }); } bool seen_request(meshlink_handle_t *mesh, const char *request) { @@ -190,7 +191,9 @@ bool seen_request(meshlink_handle_t *mesh, const char *request) { new->request = xstrdup(request); new->firstseen = mesh->loop.now.tv_sec; splay_insert(mesh->past_request_tree, new); - timeout_add(&mesh->loop, &mesh->past_request_timeout, age_past_requests, NULL, &(struct timeval){10, rand() % 100000}); + timeout_add(&mesh->loop, &mesh->past_request_timeout, age_past_requests, NULL, &(struct timeval) { + 10, rand() % 100000 + }); return false; } } diff --git a/src/protocol.h b/src/protocol.h index 5869cff4..dd042ec6 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -70,7 +70,7 @@ typedef struct past_request_t { /* Basic functions */ -extern bool send_request(struct meshlink_handle *mesh, struct connection_t *, const char *, ...) __attribute__ ((__format__(printf, 3, 4))); +extern bool send_request(struct meshlink_handle *mesh, struct connection_t *, const char *, ...) __attribute__((__format__(printf, 3, 4))); extern void forward_request(struct meshlink_handle *mesh, struct connection_t *, const char *); extern bool receive_request(struct meshlink_handle *mesh, struct connection_t *, const char *); extern bool check_id(const char *); diff --git a/src/protocol_auth.c b/src/protocol_auth.c index 4a380e77..c748ead7 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -43,92 +43,91 @@ extern bool node_write_devclass(meshlink_handle_t *mesh, node_t *n); static bool send_proxyrequest(meshlink_handle_t *mesh, connection_t *c) { switch(mesh->proxytype) { - case PROXY_HTTP: { - char *host; - char *port; - - sockaddr2str(&c->address, &host, &port); - send_request(mesh, c, "CONNECT %s:%s HTTP/1.1\r\n\r", host, port); - free(host); - free(port); - return true; - } - case PROXY_SOCKS4: { - if(c->address.sa.sa_family != AF_INET) { - logger(mesh, MESHLINK_ERROR, "Cannot connect to an IPv6 host through a SOCKS 4 proxy!"); - return false; - } - char s4req[9 + (mesh->proxyuser ? strlen(mesh->proxyuser) : 0)]; - s4req[0] = 4; - s4req[1] = 1; - memcpy(s4req + 2, &c->address.in.sin_port, 2); - memcpy(s4req + 4, &c->address.in.sin_addr, 4); - if(mesh->proxyuser) - memcpy(s4req + 8, mesh->proxyuser, strlen(mesh->proxyuser)); - s4req[sizeof s4req - 1] = 0; - c->tcplen = 8; - return send_meta(mesh, c, s4req, sizeof s4req); + case PROXY_HTTP: { + char *host; + char *port; + + sockaddr2str(&c->address, &host, &port); + send_request(mesh, c, "CONNECT %s:%s HTTP/1.1\r\n\r", host, port); + free(host); + free(port); + return true; + } + case PROXY_SOCKS4: { + if(c->address.sa.sa_family != AF_INET) { + logger(mesh, MESHLINK_ERROR, "Cannot connect to an IPv6 host through a SOCKS 4 proxy!"); + return false; } - case PROXY_SOCKS5: { - int len = 3 + 6 + (c->address.sa.sa_family == AF_INET ? 4 : 16); - c->tcplen = 2; - if(mesh->proxypass) - len += 3 + strlen(mesh->proxyuser) + strlen(mesh->proxypass); - char s5req[len]; - int i = 0; - s5req[i++] = 5; - s5req[i++] = 1; - if(mesh->proxypass) { - s5req[i++] = 2; - s5req[i++] = 1; - s5req[i++] = strlen(mesh->proxyuser); - memcpy(s5req + i, mesh->proxyuser, strlen(mesh->proxyuser)); - i += strlen(mesh->proxyuser); - s5req[i++] = strlen(mesh->proxypass); - memcpy(s5req + i, mesh->proxypass, strlen(mesh->proxypass)); - i += strlen(mesh->proxypass); - c->tcplen += 2; - } else { - s5req[i++] = 0; - } - s5req[i++] = 5; + char s4req[9 + (mesh->proxyuser ? strlen(mesh->proxyuser) : 0)]; + s4req[0] = 4; + s4req[1] = 1; + memcpy(s4req + 2, &c->address.in.sin_port, 2); + memcpy(s4req + 4, &c->address.in.sin_addr, 4); + if(mesh->proxyuser) + memcpy(s4req + 8, mesh->proxyuser, strlen(mesh->proxyuser)); + s4req[sizeof s4req - 1] = 0; + c->tcplen = 8; + return send_meta(mesh, c, s4req, sizeof s4req); + } + case PROXY_SOCKS5: { + int len = 3 + 6 + (c->address.sa.sa_family == AF_INET ? 4 : 16); + c->tcplen = 2; + if(mesh->proxypass) + len += 3 + strlen(mesh->proxyuser) + strlen(mesh->proxypass); + char s5req[len]; + int i = 0; + s5req[i++] = 5; + s5req[i++] = 1; + if(mesh->proxypass) { + s5req[i++] = 2; s5req[i++] = 1; + s5req[i++] = strlen(mesh->proxyuser); + memcpy(s5req + i, mesh->proxyuser, strlen(mesh->proxyuser)); + i += strlen(mesh->proxyuser); + s5req[i++] = strlen(mesh->proxypass); + memcpy(s5req + i, mesh->proxypass, strlen(mesh->proxypass)); + i += strlen(mesh->proxypass); + c->tcplen += 2; + } else s5req[i++] = 0; - if(c->address.sa.sa_family == AF_INET) { - s5req[i++] = 1; - memcpy(s5req + i, &c->address.in.sin_addr, 4); - i += 4; - memcpy(s5req + i, &c->address.in.sin_port, 2); - i += 2; - c->tcplen += 10; - } else if(c->address.sa.sa_family == AF_INET6) { - s5req[i++] = 3; - memcpy(s5req + i, &c->address.in6.sin6_addr, 16); - i += 16; - memcpy(s5req + i, &c->address.in6.sin6_port, 2); - i += 2; - c->tcplen += 22; - } else { - logger(mesh, MESHLINK_ERROR, "Address family %hx not supported for SOCKS 5 proxies!", c->address.sa.sa_family); - return false; - } - if(i > len) - abort(); - return send_meta(mesh, c, s5req, sizeof s5req); - } - case PROXY_SOCKS4A: - logger(mesh, MESHLINK_ERROR, "Proxy type not implemented yet"); - return false; - case PROXY_EXEC: - return true; - default: - logger(mesh, MESHLINK_ERROR, "Unknown proxy type"); + s5req[i++] = 5; + s5req[i++] = 1; + s5req[i++] = 0; + if(c->address.sa.sa_family == AF_INET) { + s5req[i++] = 1; + memcpy(s5req + i, &c->address.in.sin_addr, 4); + i += 4; + memcpy(s5req + i, &c->address.in.sin_port, 2); + i += 2; + c->tcplen += 10; + } else if(c->address.sa.sa_family == AF_INET6) { + s5req[i++] = 3; + memcpy(s5req + i, &c->address.in6.sin6_addr, 16); + i += 16; + memcpy(s5req + i, &c->address.in6.sin6_port, 2); + i += 2; + c->tcplen += 22; + } else { + logger(mesh, MESHLINK_ERROR, "Address family %hx not supported for SOCKS 5 proxies!", c->address.sa.sa_family); return false; + } + if(i > len) + abort(); + return send_meta(mesh, c, s5req, sizeof s5req); + } + case PROXY_SOCKS4A: + logger(mesh, MESHLINK_ERROR, "Proxy type not implemented yet"); + return false; + case PROXY_EXEC: + return true; + default: + logger(mesh, MESHLINK_ERROR, "Unknown proxy type"); + return false; } } bool send_id(meshlink_handle_t *mesh, connection_t *c) { - + int minor = mesh->self->connection->protocol_minor; if(mesh->proxytype && c->outgoing) @@ -260,7 +259,7 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(sscanf(request, "%*d " MAX_STRING " %d.%d", name, &c->protocol_major, &c->protocol_minor) < 2) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s)", "ID", c->name, - c->hostname); + c->hostname); return false; } @@ -296,7 +295,7 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(!check_id(name)) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s): %s", "ID", c->name, - c->hostname, "invalid name"); + c->hostname, "invalid name"); return false; } @@ -305,7 +304,7 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(c->outgoing) { if(strcmp(c->name, name)) { logger(mesh, MESHLINK_ERROR, "Peer %s is %s instead of %s", c->hostname, name, - c->name); + c->name); return false; } } else { @@ -318,7 +317,7 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(c->protocol_major != mesh->self->connection->protocol_major) { logger(mesh, MESHLINK_ERROR, "Peer %s (%s) uses incompatible version %d.%d", - c->name, c->hostname, c->protocol_major, c->protocol_minor); + c->name, c->hostname, c->protocol_major, c->protocol_minor); return false; } @@ -349,7 +348,7 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(ecdsa_active(c->ecdsa) && c->protocol_minor < 2) { logger(mesh, MESHLINK_ERROR, "Peer %s (%s) tries to roll back protocol version to %d.%d", - c->name, c->hostname, c->protocol_major, c->protocol_minor); + c->name, c->hostname, c->protocol_major, c->protocol_minor); return false; } @@ -392,13 +391,13 @@ bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(sscanf(request, "%*d " MAX_STRING " %d %x", hisport, &devclass, &options) != 3) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s)", "ACK", c->name, - c->hostname); + c->hostname); return false; } if(devclass < 0 || devclass > _DEV_CLASS_MAX) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s): %s", "ACK", c->name, - c->hostname, "devclass invalid"); + c->hostname, "devclass invalid"); return false; } @@ -449,7 +448,7 @@ bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { c->status.active = true; logger(mesh, MESHLINK_INFO, "Connection with %s (%s) activated", c->name, - c->hostname); + c->hostname); /* Send him everything we know */ diff --git a/src/protocol_edge.c b/src/protocol_edge.c index 783da775..8272caa4 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -42,8 +42,8 @@ bool send_add_edge(meshlink_handle_t *mesh, connection_t *c, const edge_t *e) { sockaddr2str(&e->address, &address, &port); x = send_request(mesh, c, "%d %x %s %d %s %s %s %d %x %d", ADD_EDGE, rand(), - e->from->name, e->from->devclass, e->to->name, address, port, e->to->devclass, - e->options, e->weight); + e->from->name, e->from->devclass, e->to->name, address, port, e->to->devclass, + e->options, e->weight); free(address); free(port); @@ -64,9 +64,9 @@ bool add_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { int weight; if(sscanf(request, "%*d %*x "MAX_STRING" %d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %x %d", - from_name, &from_devclass, to_name, to_address, to_port, &to_devclass, &options, &weight) != 8) { + from_name, &from_devclass, to_name, to_address, to_port, &to_devclass, &options, &weight) != 8) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s)", "ADD_EDGE", c->name, - c->hostname); + c->hostname); return false; } @@ -74,7 +74,7 @@ bool add_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(!check_id(from_name) || !check_id(to_name)) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name, - c->hostname, "invalid name"); + c->hostname, "invalid name"); return false; } @@ -82,13 +82,13 @@ bool add_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(from_devclass < 0 || from_devclass > _DEV_CLASS_MAX) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name, - c->hostname, "from devclass invalid"); + c->hostname, "from devclass invalid"); return false; } if(to_devclass < 0 || to_devclass > _DEV_CLASS_MAX) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name, - c->hostname, "to devclass invalid"); + c->hostname, "to devclass invalid"); return false; } @@ -132,12 +132,12 @@ bool add_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) { if(from == mesh->self) { logger(mesh, MESHLINK_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry", - "ADD_EDGE", c->name, c->hostname); + "ADD_EDGE", c->name, c->hostname); send_add_edge(mesh, c, e); return true; } else { logger(mesh, MESHLINK_WARNING, "Got %s from %s (%s) which does not match existing entry", - "ADD_EDGE", c->name, c->hostname); + "ADD_EDGE", c->name, c->hostname); edge_del(mesh, e); graph(mesh); } @@ -145,7 +145,7 @@ bool add_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { return true; } else if(from == mesh->self) { logger(mesh, MESHLINK_WARNING, "Got %s from %s (%s) for ourself which does not exist", - "ADD_EDGE", c->name, c->hostname); + "ADD_EDGE", c->name, c->hostname); mesh->contradicting_add_edge++; e = new_edge(); e->from = from; @@ -176,7 +176,7 @@ bool add_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { bool send_del_edge(meshlink_handle_t *mesh, connection_t *c, const edge_t *e) { return send_request(mesh, c, "%d %x %s %s", DEL_EDGE, rand(), - e->from->name, e->to->name); + e->from->name, e->to->name); } bool del_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { @@ -187,7 +187,7 @@ bool del_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(sscanf(request, "%*d %*x "MAX_STRING" "MAX_STRING, from_name, to_name) != 2) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s)", "DEL_EDGE", c->name, - c->hostname); + c->hostname); return false; } @@ -195,7 +195,7 @@ bool del_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(!check_id(from_name) || !check_id(to_name)) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s): %s", "DEL_EDGE", c->name, - c->hostname, "invalid name"); + c->hostname, "invalid name"); return false; } @@ -209,13 +209,13 @@ bool del_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(!from) { logger(mesh, MESHLINK_ERROR, "Got %s from %s (%s) which does not appear in the edge tree", - "DEL_EDGE", c->name, c->hostname); + "DEL_EDGE", c->name, c->hostname); return true; } if(!to) { logger(mesh, MESHLINK_ERROR, "Got %s from %s (%s) which does not appear in the edge tree", - "DEL_EDGE", c->name, c->hostname); + "DEL_EDGE", c->name, c->hostname); return true; } @@ -225,13 +225,13 @@ bool del_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(!e) { logger(mesh, MESHLINK_WARNING, "Got %s from %s (%s) which does not appear in the edge tree", - "DEL_EDGE", c->name, c->hostname); + "DEL_EDGE", c->name, c->hostname); return true; } if(e->from == mesh->self) { logger(mesh, MESHLINK_WARNING, "Got %s from %s (%s) for ourself", - "DEL_EDGE", c->name, c->hostname); + "DEL_EDGE", c->name, c->hostname); mesh->contradicting_del_edge++; send_add_edge(mesh, c, e); /* Send back a correction */ return true; diff --git a/src/protocol_key.c b/src/protocol_key.c index f493cde7..ec2cde4a 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -47,7 +47,7 @@ bool key_changed_h(meshlink_handle_t *mesh, connection_t *c, const char *request if(sscanf(request, "%*d %*x " MAX_STRING, name) != 1) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s)", "KEY_CHANGED", - c->name, c->hostname); + c->name, c->hostname); return false; } @@ -58,7 +58,7 @@ bool key_changed_h(meshlink_handle_t *mesh, connection_t *c, const char *request if(!n) { logger(mesh, MESHLINK_ERROR, "Got %s from %s (%s) origin %s which does not exist", - "KEY_CHANGED", c->name, c->hostname, name); + "KEY_CHANGED", c->name, c->hostname, name); return true; } @@ -102,83 +102,83 @@ bool send_req_key(meshlink_handle_t *mesh, node_t *to) { static bool req_key_ext_h(meshlink_handle_t *mesh, connection_t *c, const char *request, node_t *from, int reqno) { switch(reqno) { - case REQ_PUBKEY: { - char *pubkey = ecdsa_get_base64_public_key(mesh->self->connection->ecdsa); - send_request(mesh, from->nexthop->connection, "%d %s %s %d %s", REQ_KEY, mesh->self->name, from->name, ANS_PUBKEY, pubkey); - free(pubkey); + case REQ_PUBKEY: { + char *pubkey = ecdsa_get_base64_public_key(mesh->self->connection->ecdsa); + send_request(mesh, from->nexthop->connection, "%d %s %s %d %s", REQ_KEY, mesh->self->name, from->name, ANS_PUBKEY, pubkey); + free(pubkey); + return true; + } + + case ANS_PUBKEY: { + if(node_read_ecdsa_public_key(mesh, from)) { + logger(mesh, MESHLINK_WARNING, "Got ANS_PUBKEY from %s (%s) even though we already have his pubkey", from->name, from->hostname); return true; } - case ANS_PUBKEY: { - if(node_read_ecdsa_public_key(mesh, from)) { - logger(mesh, MESHLINK_WARNING, "Got ANS_PUBKEY from %s (%s) even though we already have his pubkey", from->name, from->hostname); - return true; - } + char pubkey[MAX_STRING_SIZE]; + if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, pubkey) != 1 || !(from->ecdsa = ecdsa_set_base64_public_key(pubkey))) { + logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s): %s", "ANS_PUBKEY", from->name, from->hostname, "invalid pubkey"); + return true; + } - char pubkey[MAX_STRING_SIZE]; - if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, pubkey) != 1 || !(from->ecdsa = ecdsa_set_base64_public_key(pubkey))) { - logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s): %s", "ANS_PUBKEY", from->name, from->hostname, "invalid pubkey"); - return true; - } + logger(mesh, MESHLINK_INFO, "Learned ECDSA public key from %s (%s)", from->name, from->hostname); + append_config_file(mesh, from->name, "ECDSAPublicKey", pubkey); + return true; + } - logger(mesh, MESHLINK_INFO, "Learned ECDSA public key from %s (%s)", from->name, from->hostname); - append_config_file(mesh, from->name, "ECDSAPublicKey", pubkey); + case REQ_KEY: { + if(!node_read_ecdsa_public_key(mesh, from)) { + logger(mesh, MESHLINK_DEBUG, "No ECDSA key known for %s (%s)", from->name, from->hostname); + send_request(mesh, from->nexthop->connection, "%d %s %s %d", REQ_KEY, mesh->self->name, from->name, REQ_PUBKEY); return true; } - case REQ_KEY: { - if(!node_read_ecdsa_public_key(mesh, from)) { - logger(mesh, MESHLINK_DEBUG, "No ECDSA key known for %s (%s)", from->name, from->hostname); - send_request(mesh, from->nexthop->connection, "%d %s %s %d", REQ_KEY, mesh->self->name, from->name, REQ_PUBKEY); + if(from->sptps.label) { + logger(mesh, MESHLINK_DEBUG, "Got REQ_KEY from %s while we already started a SPTPS session!", from->name); + if(strcmp(mesh->self->name, from->name) < 0) { + logger(mesh, MESHLINK_DEBUG, "Ignoring REQ_KEY from %s.", from->name); return true; } + } - if(from->sptps.label) { - logger(mesh, MESHLINK_DEBUG, "Got REQ_KEY from %s while we already started a SPTPS session!", from->name); - if(strcmp(mesh->self->name, from->name) < 0) { - logger(mesh, MESHLINK_DEBUG, "Ignoring REQ_KEY from %s.", from->name); - return true; - } - } - - char buf[MAX_STRING_SIZE]; - int len; - - if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) { - logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s): %s", "REQ_SPTPS_START", from->name, from->hostname, "invalid SPTPS data"); - return true; - } + char buf[MAX_STRING_SIZE]; + int len; - char label[sizeof meshlink_udp_label + strlen(from->name) + strlen(mesh->self->name) + 2]; - snprintf(label, sizeof label, "%s %s %s", meshlink_udp_label, from->name, mesh->self->name); - sptps_stop(&from->sptps); - from->status.validkey = false; - from->status.waitingforkey = true; - from->last_req_key = mesh->loop.now.tv_sec; - sptps_start(&from->sptps, from, false, true, mesh->self->connection->ecdsa, from->ecdsa, label, sizeof label - 1, send_sptps_data, receive_sptps_record); - sptps_receive_data(&from->sptps, buf, len); + if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) { + logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s): %s", "REQ_SPTPS_START", from->name, from->hostname, "invalid SPTPS data"); return true; } - case REQ_SPTPS: { - if(!from->status.validkey) { - logger(mesh, MESHLINK_ERROR, "Got REQ_SPTPS from %s (%s) but we don't have a valid key yet", from->name, from->hostname); - return true; - } + char label[sizeof meshlink_udp_label + strlen(from->name) + strlen(mesh->self->name) + 2]; + snprintf(label, sizeof label, "%s %s %s", meshlink_udp_label, from->name, mesh->self->name); + sptps_stop(&from->sptps); + from->status.validkey = false; + from->status.waitingforkey = true; + from->last_req_key = mesh->loop.now.tv_sec; + sptps_start(&from->sptps, from, false, true, mesh->self->connection->ecdsa, from->ecdsa, label, sizeof label - 1, send_sptps_data, receive_sptps_record); + sptps_receive_data(&from->sptps, buf, len); + return true; + } - char buf[MAX_STRING_SIZE]; - int len; - if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) { - logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s): %s", "REQ_SPTPS", from->name, from->hostname, "invalid SPTPS data"); - return true; - } - sptps_receive_data(&from->sptps, buf, len); + case REQ_SPTPS: { + if(!from->status.validkey) { + logger(mesh, MESHLINK_ERROR, "Got REQ_SPTPS from %s (%s) but we don't have a valid key yet", from->name, from->hostname); return true; } - default: - logger(mesh, MESHLINK_ERROR, "Unknown extended REQ_KEY request from %s (%s): %s", from->name, from->hostname, request); + char buf[MAX_STRING_SIZE]; + int len; + if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) { + logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s): %s", "REQ_SPTPS", from->name, from->hostname, "invalid SPTPS data"); return true; + } + sptps_receive_data(&from->sptps, buf, len); + return true; + } + + default: + logger(mesh, MESHLINK_ERROR, "Unknown extended REQ_KEY request from %s (%s): %s", from->name, from->hostname, request); + return true; } } @@ -190,7 +190,7 @@ bool req_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(sscanf(request, "%*d " MAX_STRING " " MAX_STRING " %d", from_name, to_name, &reqno) < 2) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s)", "REQ_KEY", c->name, - c->hostname); + c->hostname); return false; } @@ -203,7 +203,7 @@ bool req_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(!from) { logger(mesh, MESHLINK_ERROR, "Got %s from %s (%s) origin %s which does not exist in our connection list", - "REQ_KEY", c->name, c->hostname, from_name); + "REQ_KEY", c->name, c->hostname, from_name); return true; } @@ -211,7 +211,7 @@ bool req_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(!to) { logger(mesh, MESHLINK_ERROR, "Got %s from %s (%s) destination %s which does not exist in our connection list", - "REQ_KEY", c->name, c->hostname, to_name); + "REQ_KEY", c->name, c->hostname, to_name); return true; } @@ -227,7 +227,7 @@ bool req_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { } else { if(!to->status.reachable) { logger(mesh, MESHLINK_WARNING, "Got %s from %s (%s) destination %s which is not reachable", - "REQ_KEY", c->name, c->hostname, to_name); + "REQ_KEY", c->name, c->hostname, to_name); return true; } @@ -251,10 +251,10 @@ bool ans_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { node_t *from, *to; if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d "MAX_STRING" "MAX_STRING, - from_name, to_name, key, &cipher, &digest, &maclength, - &compression, address, port) < 7) { + from_name, to_name, key, &cipher, &digest, &maclength, + &compression, address, port) < 7) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s)", "ANS_KEY", c->name, - c->hostname); + c->hostname); return false; } @@ -267,7 +267,7 @@ bool ans_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(!from) { logger(mesh, MESHLINK_ERROR, "Got %s from %s (%s) origin %s which does not exist in our connection list", - "ANS_KEY", c->name, c->hostname, from_name); + "ANS_KEY", c->name, c->hostname, from_name); return true; } @@ -275,7 +275,7 @@ bool ans_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(!to) { logger(mesh, MESHLINK_ERROR, "Got %s from %s (%s) destination %s which does not exist in our connection list", - "ANS_KEY", c->name, c->hostname, to_name); + "ANS_KEY", c->name, c->hostname, to_name); return true; } @@ -284,7 +284,7 @@ bool ans_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(to != mesh->self) { if(!to->status.reachable) { logger(mesh, MESHLINK_WARNING, "Got %s from %s (%s) destination %s which is not reachable", - "ANS_KEY", c->name, c->hostname, to_name); + "ANS_KEY", c->name, c->hostname, to_name); return true; } diff --git a/src/protocol_misc.c b/src/protocol_misc.c index 7e9ebe50..b4470808 100644 --- a/src/protocol_misc.c +++ b/src/protocol_misc.c @@ -46,12 +46,12 @@ bool status_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(sscanf(request, "%*d %d " MAX_STRING, &statusno, statusstring) != 2) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s)", "STATUS", - c->name, c->hostname); + c->name, c->hostname); return false; } logger(mesh, MESHLINK_INFO, "Status message from %s (%s): %d: %s", - c->name, c->hostname, statusno, statusstring); + c->name, c->hostname, statusno, statusstring); return true; } @@ -69,12 +69,12 @@ bool error_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { if(sscanf(request, "%*d %d " MAX_STRING, &err, errorstring) != 2) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s)", "ERROR", - c->name, c->hostname); + c->name, c->hostname); return false; } logger(mesh, MESHLINK_INFO, "Error message from %s (%s): %d: %s", - c->name, c->hostname, err, errorstring); + c->name, c->hostname, err, errorstring); return false; } @@ -139,7 +139,7 @@ bool tcppacket_h(meshlink_handle_t *mesh, connection_t *c, const char *request) if(sscanf(request, "%*d %hd", &len) != 1) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s)", "PACKET", c->name, - c->hostname); + c->hostname); return false; } diff --git a/src/route.c b/src/route.c index 92a360ff..941f3aa0 100644 --- a/src/route.c +++ b/src/route.c @@ -61,7 +61,7 @@ void route(meshlink_handle_t *mesh, node_t *source, vpn_packet_t *packet) { char hex[len*2 + 1]; if(mesh->log_level >= MESHLINK_DEBUG) - bin2hex(payload, hex, len); // don't do this unless it's going to be logged + bin2hex(payload, hex, len); // don't do this unless it's going to be logged logger(mesh, MESHLINK_DEBUG, "I received a packet for me with payload: %s\n", hex); if(mesh->receive_cb) diff --git a/src/splay_tree.c b/src/splay_tree.c index 53cf79ec..d84948ed 100644 --- a/src/splay_tree.c +++ b/src/splay_tree.c @@ -55,7 +55,7 @@ static splay_node_t *splay_top_down(splay_tree_t *tree, const void *data, int *r grandchild->parent = NULL; root = grandchild; - } else if (c > 0 && (grandchild = child->right)) { + } else if(c > 0 && (grandchild = child->right)) { leftbottom->right = child; child->parent = leftbottom; leftbottom = child; @@ -99,7 +99,7 @@ static splay_node_t *splay_top_down(splay_tree_t *tree, const void *data, int *r grandchild->parent = NULL; root = grandchild; - } else if (c < 0 && (grandchild = child->left)) { + } else if(c < 0 && (grandchild = child->left)) { rightbottom->left = child; child->parent = rightbottom; rightbottom = child; @@ -125,9 +125,8 @@ static splay_node_t *splay_top_down(splay_tree_t *tree, const void *data, int *r root = child; break; } - } else { + } else break; - } } /* Merge trees */ @@ -328,9 +327,8 @@ splay_node_t *splay_search_closest_node_nosplay(const splay_tree_t *tree, const node = node->right; else break; - } else { + } else break; - } } if(result) @@ -513,9 +511,8 @@ void splay_unlink_node(splay_tree_t *tree, splay_node_t *node) { } else if(node->next) { tree->root = node->right; node->right->parent = NULL; - } else { + } else tree->root = NULL; - } tree->count--; } diff --git a/src/splay_tree.h b/src/splay_tree.h index da8c2b4e..4b4f18eb 100644 --- a/src/splay_tree.h +++ b/src/splay_tree.h @@ -64,10 +64,10 @@ typedef struct splay_tree_t { /* (De)constructors */ -extern splay_tree_t *splay_alloc_tree(splay_compare_t, splay_action_t) __attribute__ ((__malloc__)); +extern splay_tree_t *splay_alloc_tree(splay_compare_t, splay_action_t) __attribute__((__malloc__)); extern void splay_free_tree(splay_tree_t *); -extern splay_node_t *splay_alloc_node(void) __attribute__ ((__malloc__)); +extern splay_node_t *splay_alloc_node(void) __attribute__((__malloc__)); extern void splay_free_node(splay_tree_t *tree, splay_node_t *); /* Insertion and deletion */ diff --git a/src/sptps.c b/src/sptps.c index ab883027..258d8b88 100644 --- a/src/sptps.c +++ b/src/sptps.c @@ -331,47 +331,47 @@ bool sptps_force_kex(sptps_t *s) { static bool receive_handshake(sptps_t *s, const char *data, uint16_t len) { // Only a few states to deal with handshaking. switch(s->state) { - case SPTPS_SECONDARY_KEX: - // We receive a secondary KEX request, first respond by sending our own. - if(!send_kex(s)) - return false; - case SPTPS_KEX: - // We have sent our KEX request, we expect our peer to sent one as well. - if(!receive_kex(s, data, len)) - return false; - s->state = SPTPS_SIG; - return true; - case SPTPS_SIG: - // If we already sent our secondary public ECDH key, we expect the peer to send his. - if(!receive_sig(s, data, len)) - return false; - if(s->outstate) - s->state = SPTPS_ACK; - else { - s->outstate = true; - if(!receive_ack(s, NULL, 0)) - return false; - s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0); - s->state = SPTPS_SECONDARY_KEX; - } - - return true; - case SPTPS_ACK: - // We expect a handshake message to indicate transition to the new keys. - if(!receive_ack(s, data, len)) + case SPTPS_SECONDARY_KEX: + // We receive a secondary KEX request, first respond by sending our own. + if(!send_kex(s)) + return false; + case SPTPS_KEX: + // We have sent our KEX request, we expect our peer to sent one as well. + if(!receive_kex(s, data, len)) + return false; + s->state = SPTPS_SIG; + return true; + case SPTPS_SIG: + // If we already sent our secondary public ECDH key, we expect the peer to send his. + if(!receive_sig(s, data, len)) + return false; + if(s->outstate) + s->state = SPTPS_ACK; + else { + s->outstate = true; + if(!receive_ack(s, NULL, 0)) return false; s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0); s->state = SPTPS_SECONDARY_KEX; - return true; - // TODO: split ACK into a VERify and ACK? - default: - return error(s, EIO, "Invalid session state %d", s->state); + } + + return true; + case SPTPS_ACK: + // We expect a handshake message to indicate transition to the new keys. + if(!receive_ack(s, data, len)) + return false; + s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0); + s->state = SPTPS_SECONDARY_KEX; + return true; + // TODO: split ACK into a VERify and ACK? + default: + return error(s, EIO, "Invalid session state %d", s->state); } } // Check datagram for valid HMAC bool sptps_verify_datagram(sptps_t *s, const void *data, size_t len) { - if (!s->instate) + if(!s->instate) return error(s, EIO, "SPTPS state not ready to verify this datagram"); if(len < 21) @@ -433,7 +433,7 @@ static bool sptps_receive_data_datagram(sptps_t *s, const void *vdata, size_t le warning(s, "Lost %d packets\n", seqno - s->inseqno); // Mark all packets in the replay window as being late. memset(s->late, 255, s->replaywin); - } else if (seqno < s->inseqno) { + } else if(seqno < s->inseqno) { // If the sequence number is farther in the past than the bitmap goes, or if the packet was already received, drop it. if((s->inseqno >= s->replaywin * 8 && seqno < s->inseqno - s->replaywin * 8) || !(s->late[(seqno / 8) % s->replaywin] & (1 << seqno % 8))) return error(s, EIO, "Received late or replayed packet, seqno %d, last received %d\n", seqno, s->inseqno); @@ -469,9 +469,8 @@ static bool sptps_receive_data_datagram(sptps_t *s, const void *vdata, size_t le } else if(type == SPTPS_HANDSHAKE) { if(!receive_handshake(s, buffer + 1, len - 21)) abort(); - } else { + } else return error(s, EIO, "Invalid record type %d", type); - } return true; } @@ -553,9 +552,8 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) { } else if(type == SPTPS_HANDSHAKE) { if(!receive_handshake(s, s->inbuf + 3, s->reclen)) return false; - } else { + } else return error(s, EIO, "Invalid record type %d", type); - } s->buflen = 0; } diff --git a/src/sptps_keypair.c b/src/sptps_keypair.c index 931f1b41..94d262d2 100644 --- a/src/sptps_keypair.c +++ b/src/sptps_keypair.c @@ -30,8 +30,8 @@ static char *program_name; static void usage() { fprintf(stderr, "Usage: %s [options] private_key_file public_key_file\n\n", program_name); fprintf(stderr, "Valid options are:\n" - " --help Display this help and exit.\n" - "\n"); + " --help Display this help and exit.\n" + "\n"); fprintf(stderr, "Report bugs to bugs@meshlink.io.\n"); } @@ -46,20 +46,20 @@ int main(int argc, char *argv[]) { int option_index = 0; while((r = getopt_long(argc, argv, "", long_options, &option_index)) != EOF) { - switch (r) { - case 0: /* long option */ - break; + switch(r) { + case 0: /* long option */ + break; - case '?': /* wrong options */ - usage(); - return 1; + case '?': /* wrong options */ + usage(); + return 1; - case 1: /* help */ - usage(); - return 0; + case 1: /* help */ + usage(); + return 0; - default: - break; + default: + break; } } @@ -77,7 +77,7 @@ int main(int argc, char *argv[]) { ecdsa_t *key = ecdsa_generate(); if(!key) return 1; - + FILE *fp = fopen(argv[1], "w"); if(fp) { ecdsa_write_pem_private_key(key, fp); diff --git a/src/sptps_speed.c b/src/sptps_speed.c index c27683b5..673efd25 100644 --- a/src/sptps_speed.c +++ b/src/sptps_speed.c @@ -28,11 +28,15 @@ #include "sptps.h" // Symbols necessary to link with logger.o -bool send_request(void *c, const char *msg, ...) { return false; } +bool send_request(void *c, const char *msg, ...) { + return false; +} void *mesh; void *global_log_cb; int global_log_level; -bool send_meta(void *c, const char *msg , int len) { return false; } +bool send_meta(void *c, const char *msg, int len) { + return false; +} char *logfilename = NULL; struct timeval now; diff --git a/src/sptps_test.c b/src/sptps_test.c index b982f387..b38711de 100644 --- a/src/sptps_test.c +++ b/src/sptps_test.c @@ -33,11 +33,15 @@ #include "utils.h" // Symbols necessary to link with logger.o -bool send_request(void *c, const char *msg, ...) { return false; } +bool send_request(void *c, const char *msg, ...) { + return false; +} void *mesh; void *global_log_cb; int global_log_level; -bool send_meta(void *c, const char *msg , int len) { return false; } +bool send_meta(void *c, const char *msg, int len) { + return false; +} char *logfilename = NULL; struct timeval now; @@ -83,17 +87,17 @@ const char *program_name; static void usage() { fprintf(stderr, "Usage: %s [options] my_ecdsa_key_file his_ecdsa_key_file [host] port\n\n", program_name); fprintf(stderr, "Valid options are:\n" - " -d, --datagram Enable datagram mode.\n" - " -q, --quit Quit when EOF occurs on stdin.\n" - " -r, --readonly Only send data from the socket to stdout.\n" + " -d, --datagram Enable datagram mode.\n" + " -q, --quit Quit when EOF occurs on stdin.\n" + " -r, --readonly Only send data from the socket to stdout.\n" #ifdef HAVE_LINUX - " -t, --tun Use a tun device instead of stdio.\n" + " -t, --tun Use a tun device instead of stdio.\n" #endif - " -w, --writeonly Only send data from stdin to the socket.\n" - " -L, --packet-loss RATE Fake packet loss of RATE percent.\n" - " -R, --replay-window N Set replay window to N bytes.\n" - " -v, --verbose Display debug messages.\n" - "\n"); + " -w, --writeonly Only send data from stdin to the socket.\n" + " -L, --packet-loss RATE Fake packet loss of RATE percent.\n" + " -R, --replay-window N Set replay window to N bytes.\n" + " -v, --verbose Display debug messages.\n" + "\n"); fprintf(stderr, "Report bugs to bugs@meshlink.io.\n"); } @@ -111,58 +115,58 @@ int main(int argc, char *argv[]) { bool quit = false; while((r = getopt_long(argc, argv, "dqrtwL:W:v", long_options, &option_index)) != EOF) { - switch (r) { - case 0: /* long option */ - break; + switch(r) { + case 0: /* long option */ + break; - case 'd': /* datagram mode */ - datagram = true; - break; + case 'd': /* datagram mode */ + datagram = true; + break; - case 'q': /* close connection on EOF from stdin */ - quit = true; - break; + case 'q': /* close connection on EOF from stdin */ + quit = true; + break; - case 'r': /* read only */ - readonly = true; - break; + case 'r': /* read only */ + readonly = true; + break; - case 't': /* read only */ + case 't': /* read only */ #ifdef HAVE_LINUX - tun = true; + tun = true; #else - fprintf(stderr, "--tun is only supported on Linux.\n"); - usage(); - return 1; + fprintf(stderr, "--tun is only supported on Linux.\n"); + usage(); + return 1; #endif - break; + break; - case 'w': /* write only */ - writeonly = true; - break; + case 'w': /* write only */ + writeonly = true; + break; - case 'L': /* packet loss rate */ - packetloss = atoi(optarg); - break; + case 'L': /* packet loss rate */ + packetloss = atoi(optarg); + break; - case 'W': /* replay window size */ - sptps_replaywin = atoi(optarg); - break; + case 'W': /* replay window size */ + sptps_replaywin = atoi(optarg); + break; - case 'v': /* be verbose */ - verbose = true; - break; + case 'v': /* be verbose */ + verbose = true; + break; - case '?': /* wrong options */ - usage(); - return 1; + case '?': /* wrong options */ + usage(); + return 1; - case 1: /* help */ - usage(); - return 0; + case 1: /* help */ + usage(); + return 0; - default: - break; + default: + break; } } @@ -327,8 +331,7 @@ int main(int argc, char *argv[]) { sptps_force_kex(&s); if(len > 1) sptps_send_record(&s, 0, buf, len); - } else - if(!sptps_send_record(&s, buf[0] == '!' ? 1 : 0, buf, (len == 1 && buf[0] == '\n') ? 0 : buf[0] == '*' ? sizeof buf : len)) + } else if(!sptps_send_record(&s, buf[0] == '!' ? 1 : 0, buf, (len == 1 && buf[0] == '\n') ? 0 : buf[0] == '*' ? sizeof buf : len)) return 1; } diff --git a/src/utils.c b/src/utils.c index e45e5942..71fe3dea 100644 --- a/src/utils.c +++ b/src/utils.c @@ -79,8 +79,10 @@ int b64decode(const char *src, void *dst, int length) { if((i & 3) == 3) { if(triplet & 0xff000000U) return 0; - udst[0] = triplet & 0xff; triplet >>= 8; - udst[1] = triplet & 0xff; triplet >>= 8; + udst[0] = triplet & 0xff; + triplet >>= 8; + udst[1] = triplet & 0xff; + triplet >>= 8; udst[2] = triplet; triplet = 0; udst += 3; @@ -89,15 +91,15 @@ int b64decode(const char *src, void *dst, int length) { if(triplet & 0xff000000U) return 0; if((i & 3) == 3) { - udst[0] = triplet & 0xff; triplet >>= 8; + udst[0] = triplet & 0xff; + triplet >>= 8; udst[1] = triplet & 0xff; return i / 4 * 3 + 2; } else if((i & 3) == 2) { udst[0] = triplet & 0xff; return i / 4 * 3 + 1; - } else { + } else return i / 4 * 3; - } } static int b64encode_internal(const void *src, char *dst, int length, const char *alphabet) { @@ -107,34 +109,40 @@ static int b64encode_internal(const void *src, char *dst, int length, const char int di = length / 3 * 4; switch(length % 3) { - case 2: - triplet = usrc[si] | usrc[si + 1] << 8; - dst[di] = alphabet[triplet & 63]; triplet >>= 6; - dst[di + 1] = alphabet[triplet & 63]; triplet >>= 6; - dst[di + 2] = alphabet[triplet]; - dst[di + 3] = 0; - length = di + 2; - break; - case 1: - triplet = usrc[si]; - dst[di] = alphabet[triplet & 63]; triplet >>= 6; - dst[di + 1] = alphabet[triplet]; - dst[di + 2] = 0; - length = di + 1; - break; - default: - dst[di] = 0; - length = di; - break; + case 2: + triplet = usrc[si] | usrc[si + 1] << 8; + dst[di] = alphabet[triplet & 63]; + triplet >>= 6; + dst[di + 1] = alphabet[triplet & 63]; + triplet >>= 6; + dst[di + 2] = alphabet[triplet]; + dst[di + 3] = 0; + length = di + 2; + break; + case 1: + triplet = usrc[si]; + dst[di] = alphabet[triplet & 63]; + triplet >>= 6; + dst[di + 1] = alphabet[triplet]; + dst[di + 2] = 0; + length = di + 1; + break; + default: + dst[di] = 0; + length = di; + break; } while(si > 0) { di -= 4; si -= 3; triplet = usrc[si] | usrc[si + 1] << 8 | usrc[si + 2] << 16; - dst[di] = alphabet[triplet & 63]; triplet >>= 6; - dst[di + 1] = alphabet[triplet & 63]; triplet >>= 6; - dst[di + 2] = alphabet[triplet & 63]; triplet >>= 6; + dst[di] = alphabet[triplet & 63]; + triplet >>= 6; + dst[di + 1] = alphabet[triplet & 63]; + triplet >>= 6; + dst[di + 2] = alphabet[triplet & 63]; + triplet >>= 6; dst[di + 3] = alphabet[triplet]; } @@ -159,10 +167,10 @@ const char *winerror(int err) { ptr = buf + sprintf(buf, "(%d) ", err); - if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), ptr, sizeof(buf) - (ptr - buf), NULL)) { + if(!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), ptr, sizeof(buf) - (ptr - buf), NULL)) strncpy(buf, "(unable to format errormessage)", sizeof(buf)); - }; + ; if((ptr = strchr(buf, '\r'))) *ptr = '\0'; diff --git a/src/xalloc.h b/src/xalloc.h index e08e66f7..fba0be90 100644 --- a/src/xalloc.h +++ b/src/xalloc.h @@ -20,7 +20,7 @@ #ifndef __MESHLINK_XALLOC_H__ #define __MESHLINK_XALLOC_H__ -static inline void *xmalloc(size_t n) __attribute__ ((__malloc__)); +static inline void *xmalloc(size_t n) __attribute__((__malloc__)); static inline void *xmalloc(size_t n) { void *p = malloc(n); if(!p) @@ -28,7 +28,7 @@ static inline void *xmalloc(size_t n) { return p; } -static inline void *xzalloc(size_t n) __attribute__ ((__malloc__)); +static inline void *xzalloc(size_t n) __attribute__((__malloc__)); static inline void *xzalloc(size_t n) { void *p = calloc(1, n); if(!p) @@ -43,7 +43,7 @@ static inline void *xrealloc(void *p, size_t n) { return p; } -static inline char *xstrdup(const char *s) __attribute__ ((__malloc__)); +static inline char *xstrdup(const char *s) __attribute__((__malloc__)); static inline char *xstrdup(const char *s) { char *p = strdup(s); if(!p) @@ -66,7 +66,7 @@ static inline int xvasprintf(char **strp, const char *fmt, va_list ap) { return result; } -static inline int xasprintf(char **strp, const char *fmt, ...) __attribute__ ((__format__(printf, 2, 3))); +static inline int xasprintf(char **strp, const char *fmt, ...) __attribute__((__format__(printf, 2, 3))); static inline int xasprintf(char **strp, const char *fmt, ...) { va_list ap; va_start(ap, fmt); diff --git a/test/channels-fork.c b/test/channels-fork.c old mode 100755 new mode 100644 index 3a9615ff..7fdd5b8e --- a/test/channels-fork.c +++ b/test/channels-fork.c @@ -100,7 +100,7 @@ int main1(int rfd, int wfd) { } // Open a channel from foo to bar. - + meshlink_node_t *bar = meshlink_get_node(mesh1, "bar"); if(!bar) { fprintf(stderr, "Foo could not find bar\n"); diff --git a/test/channels.c b/test/channels.c index 1958ad76..c6d9fa8f 100644 --- a/test/channels.c +++ b/test/channels.c @@ -31,13 +31,16 @@ void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) { } void foo_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) { - printf("foo_receive_cb %zu: ", len); fwrite(data, 1, len, stdout); printf("\n"); + printf("foo_receive_cb %zu: ", len); + fwrite(data, 1, len, stdout); + printf("\n"); if(len == 5 && !memcmp(data, "Hello", 5)) bar_responded = true; } void bar_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) { - printf("bar_receive_cb %zu: ", len); fwrite(data, 1, len, stdout); + printf("bar_receive_cb %zu: ", len); + fwrite(data, 1, len, stdout); // Echo the data back. meshlink_channel_send(mesh, channel, data, len); } @@ -48,7 +51,10 @@ bool reject_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t po bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) { printf("accept_cb: (from %s on port %u) ", channel->node->name, (unsigned int)port); - if(data) { fwrite(data, 1, len, stdout); printf("\n"); } + if(data) { + fwrite(data, 1, len, stdout); + printf("\n"); + } if(port != 7) return false; @@ -115,12 +121,12 @@ int main(int argc, char *argv[]) { free(data); // Set the callbacks. - + meshlink_set_channel_accept_cb(mesh1, reject_cb); meshlink_set_channel_accept_cb(mesh2, accept_cb); meshlink_set_node_status_cb(mesh1, status_cb); - + // Start both instances if(!meshlink_start(mesh1)) { @@ -147,7 +153,7 @@ int main(int argc, char *argv[]) { } // Open a channel from foo to bar. - + meshlink_node_t *bar = meshlink_get_node(mesh1, "bar"); if(!bar) { fprintf(stderr, "Foo could not find bar\n"); diff --git a/test/echo-fork.c b/test/echo-fork.c old mode 100755 new mode 100644 index ee24e8cb..289e24a7 --- a/test/echo-fork.c +++ b/test/echo-fork.c @@ -93,7 +93,7 @@ int main1(void) { } // Open a channel from foo to bar. - + meshlink_node_t *bar = meshlink_get_node(mesh1, "bar"); if(!bar) { fprintf(stderr, "Foo could not find bar\n"); @@ -130,9 +130,9 @@ int main1(void) { fprintf(stderr, "Sending message failed\n"); return 1; } - if(!sent) { + if(!sent) usleep(100000); - } else { + else { len -= sent; p += sent; } diff --git a/test/import-export.c b/test/import-export.c index 546ad757..22cd80bb 100644 --- a/test/import-export.c +++ b/test/import-export.c @@ -62,7 +62,7 @@ int main(int argc, char *argv[]) { // Start both instances meshlink_set_node_status_cb(mesh1, status_cb); - + if(!meshlink_start(mesh1)) { fprintf(stderr, "Foo could not start\n"); return 1; diff --git a/test/invite-join.c b/test/invite-join.c index c0fe067d..41b62bd4 100644 --- a/test/invite-join.c +++ b/test/invite-join.c @@ -30,7 +30,7 @@ int main(int argc, char *argv[]) { // Start the first instance and have it generate an invitation. meshlink_set_node_status_cb(mesh1, status_cb); - + if(!meshlink_start(mesh1)) { fprintf(stderr, "Foo could not start\n"); return 1; -- 2.39.2