From: Guus Sliepen Date: Fri, 22 Aug 2014 08:58:47 +0000 (+0200) Subject: Merge branch 'channels' X-Git-Url: http://git.meshlink.io/?p=meshlink;a=commitdiff_plain;h=01eaeb3c9fa60ae9c6e5b866acd9baef79622d99 Merge branch 'channels' Conflicts: .gitmodules src/node.h --- 01eaeb3c9fa60ae9c6e5b866acd9baef79622d99 diff --cc .gitmodules index 0e6f5440,add1976b..e938b091 --- a/.gitmodules +++ b/.gitmodules @@@ -1,4 -1,3 +1,7 @@@ +[submodule "avahi"] + path = avahi + url = git@chicago.everbase.net:meshlink/avahi-noptr.git + branch = noptr + [submodule "src/utcp"] + path = src/utcp + url = git://meshlink.io/utcp diff --cc src/Makefile.am index cae2ab95,c1d887e9..a2a9305a --- a/src/Makefile.am +++ b/src/Makefile.am @@@ -99,13 -101,13 +102,14 @@@ libmeshlink_la_SOURCES = system.h \ utils.c utils.h \ xalloc.h \ + devtools.c devtools.h \ $(ed25519_SOURCES) \ - $(chacha_poly1305_SOURCES) + $(chacha_poly1305_SOURCES) \ + $(utcp_SOURCES) -libmeshlink_la_CFLAGS = -fPIC +libmeshlink_la_CFLAGS = -fPIC -I../avahi/ -libmeshlink_la_LIBADD = -lpthread +libmeshlink_la_LIBADD = -lpthread -luuid ../avahi/avahi-core/.libs/libavahi-core.a ../avahi/avahi-common/.libs/libavahi-common.a libmeshlink_la_SOURCES += \ ed25519/ecdh.c \ diff --cc src/meshlink.c index ddaa740b,f44dba47..ef02580e --- a/src/meshlink.c +++ b/src/meshlink.c @@@ -1798,122 -1377,80 +1798,192 @@@ void meshlink_blacklist(meshlink_handle //Make blacklisting persistent in the config file append_config_file(mesh, n->name, "blacklisted", "yes"); - return; + pthread_mutex_unlock(&(mesh->mesh_mutex)); + return; +} + +void meshlink_whitelist(meshlink_handle_t *mesh, meshlink_node_t *node) { + if(!mesh || !node) { + meshlink_errno = MESHLINK_EINVAL; + return; + } + + pthread_mutex_lock(&(mesh->mesh_mutex)); + + node_t *n = (node_t *)node; + n->status.blacklisted = false; + + //TODO: remove blacklisted = yes from the config file + + pthread_mutex_unlock(&(mesh->mesh_mutex)); + return; +} + +/* Hint that a hostname may be found at an address + * See header file for detailed comment. + */ +void meshlink_hint_address(meshlink_handle_t *mesh, meshlink_node_t *node, const struct sockaddr *addr) { + if(!mesh || !node || !addr) + 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 ) ) + append_config_file(mesh, node->name, "Address", str); + else + logger(mesh, MESHLINK_DEBUG, "Not adding Link Local IPv6 Address to config\n"); + } + + free(str); + free(host); + free(port); + + pthread_mutex_unlock(&(mesh->mesh_mutex)); + // @TODO do we want to fire off a connection attempt right away? +} + +/* Return an array of edges in the current network graph. + * Data captures the current state and will not be updated. + * Caller must deallocate data when done. + */ +meshlink_edge_t **meshlink_get_all_edges_state(meshlink_handle_t *mesh, meshlink_edge_t **edges, size_t *nmemb) { + if(!mesh || !nmemb || (*nmemb && !edges)) { + meshlink_errno = MESHLINK_EINVAL; + return NULL; + } + + pthread_mutex_lock(&(mesh->mesh_mutex)); + + meshlink_edge_t **result = NULL; + meshlink_edge_t *copy = NULL; + int result_size = 0; + + 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 { + result = edges; + } + + if(result) { + meshlink_edge_t **p = result; + int n = 0; + for splay_each(edge_t, e, mesh->edges) { + // skip edges that do not represent a two-directional connection + if((!e->reverse) || (e->reverse->to != e->from)) { + result_size--; + continue; + } + n++; + // the first *nmemb members of result can be re-used + if(n > *nmemb) { + copy = xzalloc(sizeof *copy); + } + else { + copy = *p; + } + copy->from = (meshlink_node_t*)e->from; + copy->to = (meshlink_node_t*)e->to; + copy->address = e->address.storage; + copy->options = e->options; + copy->weight = e->weight; + *p++ = copy; + } + // shrink result to the actual amount of memory used + for(int i = *nmemb; i > result_size; i--) { + free(result[i - 1]); + } + result = realloc(result, result_size * sizeof (meshlink_edge_t*)); + *nmemb = result_size; + } else { + *nmemb = 0; + free(result); + meshlink_errno = MESHLINK_ENOMEM; + } + + pthread_mutex_unlock(&(mesh->mesh_mutex)); + + return result; } + static bool channel_pre_accept(struct utcp *utcp, uint16_t port) { + //TODO: implement + return false; + } + + static void channel_accept(struct utcp_connection *utcp_connection, uint16_t port) { + //TODO: implement + } + + static int channel_recv(struct utcp_connection *connection, const void *data, size_t len) { + meshlink_channel_t *channel = connection->priv; + node_t *n = channel->node; + meshlink_handle_t *mesh = n->mesh; + if(!channel->receive_cb) + return -1; + else { + channel->receive_cb(mesh, channel, data, len); + return 0; + } + } + + static int channel_send(struct utcp *utcp, const void *data, size_t len) { + node_t *n = utcp->priv; + meshlink_handle_t *mesh = n->mesh; + return meshlink_send(mesh, (meshlink_node_t *)n, data, len) ? len : -1; + } + + void meshlink_set_channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_accept_cb_t cb) { + mesh->channel_accept_cb = cb; + } + + void meshlink_set_channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, meshlink_channel_receive_cb_t cb) { + channel->receive_cb = cb; + } + + meshlink_channel_t *meshlink_channel_open(meshlink_handle_t *mesh, meshlink_node_t *node, uint16_t port, meshlink_channel_receive_cb_t cb, const void *data, size_t len) { + node_t *n = (node_t *)node; + if(!n->utcp) { + n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n); + if(!n->utcp) + return NULL; + } + meshlink_channel_t *channel = xzalloc(sizeof *channel); + channel->node = n; + channel->receive_cb = cb; + channel->c = utcp_connect(n->utcp, port, channel_recv, channel); + if(!channel->c) { + free(channel); + return NULL; + } + return channel; + } + + void meshlink_channel_shutdown(meshlink_handle_t *mesh, meshlink_channel_t *channel, int direction) { + utcp_shutdown(channel->c, direction); + } + + void meshlink_channel_close(meshlink_handle_t *mesh, meshlink_channel_t *channel) { + utcp_close(channel->c); + free(channel); + } + + ssize_t meshlink_channel_send(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) { + // TODO: locking. + // Ideally we want to put the data into the UTCP connection's send buffer. + // Then, preferrably only if there is room in the receiver window, + // kick the meshlink thread to go send packets. + return utcp_send(channel->c, data, len); + } + static void __attribute__((constructor)) meshlink_init(void) { crypto_init(); } diff --cc src/node.h index c86c3cee,427bc83a..5761e4d7 --- a/src/node.h +++ b/src/node.h @@@ -40,9 -41,9 +41,10 @@@ typedef struct node_status_t typedef struct node_t { char *name; /* name of this node */ + void *priv; + uint32_t options; /* options turned on for this node */ + dev_class_t devclass; - void *priv; struct meshlink_handle *mesh; /* The mesh this node belongs to */