X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;ds=sidebyside;f=src%2Fmeshlink.c;h=cbe88a3ed256e06f25a72663fc60991ff4189af3;hb=80d7a91d86f8cde7b1a550ef18ae7b84e2236ab6;hp=bd74b1d8d358ba93ee6afbbb42c7e1df4b5f9d39;hpb=ac24ceb9a5976628dd4ac31b2b502f1caac2b2ec;p=meshlink diff --git a/src/meshlink.c b/src/meshlink.c index bd74b1d8..cbe88a3e 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -660,7 +660,7 @@ static bool ecdsa_keygen(meshlink_handle_t *mesh) { logger(mesh, MESHLINK_DEBUG, "Done.\n"); snprintf(privname, sizeof privname, "%s" SLASH "ecdsa_key.priv", mesh->confbase); - f = fopen(privname, "w"); + f = fopen(privname, "wb"); if(!f) { meshlink_errno = MESHLINK_ESTORAGE; @@ -699,6 +699,20 @@ static bool ecdsa_keygen(meshlink_handle_t *mesh) { return true; } +static struct timeval idle(event_loop_t *loop, void *data) { + meshlink_handle_t *mesh = data; + int t, tmin = -1; + for splay_each(node_t, n, mesh->nodes) { + if(!n->utcp) + continue; + t = utcp_timeout(n->utcp); + if(t >= 0 && t < tmin) + tmin = t; + } + struct timeval tv = {.tv_sec = t}; + return tv; +} + static bool meshlink_setup(meshlink_handle_t *mesh) { if(mkdir(mesh->confbase, 0777) && errno != EEXIST) { logger(mesh, MESHLINK_DEBUG, "Could not create directory %s: %s\n", mesh->confbase, strerror(errno)); @@ -744,11 +758,6 @@ 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) { - return meshlink_open_with_size(confbase, name, appname, devclass, sizeof(meshlink_handle_t)); -} - -meshlink_handle_t *meshlink_open_with_size(const char *confbase, const char *name, const char* appname, dev_class_t devclass, size_t size) { - // Validate arguments provided by the application bool usingname = false; @@ -785,7 +794,7 @@ meshlink_handle_t *meshlink_open_with_size(const char *confbase, const char *nam return NULL; } - meshlink_handle_t *mesh = xzalloc(size); + meshlink_handle_t *mesh = xzalloc(sizeof(meshlink_handle_t)); mesh->confbase = xstrdup(confbase); mesh->appname = xstrdup(appname); mesh->devclass = devclass; @@ -845,6 +854,8 @@ meshlink_handle_t *meshlink_open_with_size(const char *confbase, const char *nam return NULL; } + idle_set(&mesh->loop, idle, mesh); + logger(NULL, MESHLINK_DEBUG, "meshlink_open returning\n"); return mesh; } @@ -1039,8 +1050,10 @@ bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const hdr = (meshlink_packethdr_t *)packet->data; memset(hdr, 0, sizeof *hdr); - memcpy(hdr->destination, destination->name, sizeof hdr->destination); - memcpy(hdr->source, mesh->self->name, sizeof hdr->source); + // 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 ); memcpy(packet->data + sizeof *hdr, data, len); @@ -1279,7 +1292,7 @@ static bool refresh_invitation_key(meshlink_handle_t *mesh) { } // Create a new key if necessary. - FILE *f = fopen(filename, "r"); + FILE *f = fopen(filename, "rb"); if(!f) { if(errno != ENOENT) { logger(mesh, MESHLINK_DEBUG, "Could not read %s: %s\n", filename, strerror(errno)); @@ -1295,7 +1308,7 @@ static bool refresh_invitation_key(meshlink_handle_t *mesh) { pthread_mutex_unlock(&(mesh->mesh_mutex)); return false; } - f = fopen(filename, "w"); + f = fopen(filename, "wb"); if(!f) { logger(mesh, MESHLINK_DEBUG, "Could not write %s: %s\n", filename, strerror(errno)); meshlink_errno = MESHLINK_ESTORAGE; @@ -1809,6 +1822,10 @@ void meshlink_whitelist(meshlink_handle_t *mesh, meshlink_node_t *node) { return; } +void meshlink_set_default_blacklist(meshlink_handle_t *mesh, bool blacklist) { + mesh->default_blacklist = blacklist; +} + /* Hint that a hostname may be found at an address * See header file for detailed comment. */ @@ -1948,6 +1965,11 @@ static ssize_t channel_send(struct utcp *utcp, const void *data, size_t len) { } void meshlink_set_channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, meshlink_channel_receive_cb_t cb) { + if(!mesh || !channel) { + meshlink_errno = MESHLINK_EINVAL; + return; + } + channel->receive_cb = cb; } @@ -1961,7 +1983,27 @@ static void channel_receive(meshlink_handle_t *mesh, meshlink_node_t *source, co utcp_recv(n->utcp, data, len); } +static void channel_poll(struct utcp_connection *connection, size_t len) { + meshlink_channel_t *channel = connection->priv; + if(!channel) + abort(); + node_t *n = channel->node; + meshlink_handle_t *mesh = n->mesh; + if(channel->poll_cb) + channel->poll_cb(mesh, channel, len); +} + +void meshlink_set_channel_poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, meshlink_channel_poll_cb_t cb) { + channel->poll_cb = cb; + utcp_set_poll_cb(channel->c, cb ? channel_poll : NULL); +} + void meshlink_set_channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_accept_cb_t cb) { + if(!mesh) { + meshlink_errno = MESHLINK_EINVAL; + return; + } + pthread_mutex_lock(&mesh->mesh_mutex); mesh->channel_accept_cb = cb; mesh->receive_cb = channel_receive; @@ -1974,10 +2016,12 @@ void meshlink_set_channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_ac pthread_mutex_unlock(&mesh->mesh_mutex); } -void meshlink_channel_init(meshlink_handle_t *mesh) { -} - 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) { + if(!mesh || !node) { + meshlink_errno = MESHLINK_EINVAL; + return NULL; + } + logger(mesh, MESHLINK_WARNING, "meshlink_channel_open(%p, %s, %u, %p, %p, %zu)\n", mesh, node->name, port, cb, data, len); node_t *n = (node_t *)node; if(!n->utcp) { @@ -2001,20 +2045,50 @@ meshlink_channel_t *meshlink_channel_open(meshlink_handle_t *mesh, meshlink_node } void meshlink_channel_shutdown(meshlink_handle_t *mesh, meshlink_channel_t *channel, int direction) { + if(!mesh || !channel) { + meshlink_errno = MESHLINK_EINVAL; + return; + } + utcp_shutdown(channel->c, direction); } void meshlink_channel_close(meshlink_handle_t *mesh, meshlink_channel_t *channel) { + if(!mesh || !channel) { + meshlink_errno = MESHLINK_EINVAL; + return; + } + 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. + if(!mesh || !channel) { + meshlink_errno = MESHLINK_EINVAL; + return -1; + } + + if(!len) + return 0; + + if(!data) { + meshlink_errno = MESHLINK_EINVAL; + return -1; + } + + // TODO: more finegrained 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); + + pthread_mutex_lock(&mesh->mesh_mutex); + ssize_t retval = utcp_send(channel->c, data, len); + pthread_mutex_unlock(&mesh->mesh_mutex); + + if(retval < 0) + meshlink_errno = MESHLINK_ENETWORK; + return retval; } void update_node_status(meshlink_handle_t *mesh, node_t *n) {