X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fmeshlink.c;h=c7a6c0b2f3ad8d3e4fbf982c7a5951c50a4be6a5;hb=afa120900edda1e48a5e91bd6697a6e48395526c;hp=0da4cbbed0e4fe38d1d5cd6d8ce4666b5284fb8c;hpb=f8be16a427a3eeb89c3489975ba5099943262c59;p=meshlink diff --git a/src/meshlink.c b/src/meshlink.c index 0da4cbbe..c7a6c0b2 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -21,6 +21,8 @@ #define VAR_MULTIPLE 4 /* Multiple statements allowed */ #define VAR_OBSOLETE 8 /* Should not be used anymore */ #define VAR_SAFE 16 /* Variable is safe when accepting invitations */ +#define MAX_ADDRESS_LENGTH 45 /* Max length of an (IPv6) address */ +#define MAX_PORT_LENGTH 5 /* 0-65535 */ typedef struct { const char *name; int type; @@ -39,11 +41,15 @@ typedef struct { #include "utils.h" #include "xalloc.h" #include "ed25519/sha512.h" +#include "discovery.h" #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif +static pthread_mutex_t global_mutex; +static bool discovery_started; + __thread meshlink_errno_t meshlink_errno; //TODO: this can go away completely @@ -347,12 +353,7 @@ static bool try_bind(int port) { } static int check_port(meshlink_handle_t *mesh) { - if(try_bind(655)) - return 655; - - fprintf(stderr, "Warning: could not bind to port 655.\n"); - - for(int i = 0; i < 100; i++) { + for(int i = 0; i < 1000; i++) { int port = 0x1000 + (rand() & 0x7fff); if(try_bind(port)) { char filename[PATH_MAX]; @@ -365,7 +366,6 @@ static int check_port(meshlink_handle_t *mesh) { fprintf(f, "Port = %d\n", port); fclose(f); - fprintf(stderr, "MeshLink will instead listen on port %d.\n", port); return port; } } @@ -740,13 +740,12 @@ static bool meshlink_setup(meshlink_handle_t *mesh) { return true; } - -meshlink_handle_t *meshlink_open(const char *confbase, const char *name) { - return meshlink_open_with_size(confbase, name, sizeof(meshlink_handle_t) ); +meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const char* appname) { + return meshlink_open_with_size(confbase, name, appname, sizeof(meshlink_handle_t)); } +meshlink_handle_t *meshlink_open_with_size(const char *confbase, const char *name, const char* appname, size_t size) { -meshlink_handle_t *meshlink_open_with_size(const char *confbase, const char *name, size_t size) { // Validate arguments provided by the application bool usingname = false; @@ -756,6 +755,12 @@ meshlink_handle_t *meshlink_open_with_size(const char *confbase, const char *nam return NULL; } + if(!appname || !*appname) { + fprintf(stderr, "No appname given!\n"); + meshlink_errno = MESHLINK_EINVAL; + return NULL; + } + if(!name || !*name) { fprintf(stderr, "No name given!\n"); //return NULL; @@ -771,6 +776,7 @@ meshlink_handle_t *meshlink_open_with_size(const char *confbase, const char *nam meshlink_handle_t *mesh = xzalloc(size); mesh->confbase = xstrdup(confbase); + mesh->appname = xstrdup(appname); if (usingname) mesh->name = xstrdup(name); pthread_mutex_init ( &(mesh->nodes_mutex), NULL); mesh->threadstarted = false; @@ -865,19 +871,41 @@ bool meshlink_start(meshlink_handle_t *mesh) { mesh->threadstarted=true; + // Start discovery + // Since only one Avahi instance can run in one program at the moment, make sure we only start one, ignore it otherwise. + + bool discovery_on = false; + pthread_mutex_lock(&global_mutex); + if(!discovery_started) + discovery_on = discovery_started = true; + pthread_mutex_unlock(&global_mutex); + + if(discovery_on) + discovery_start(mesh); + return true; } void meshlink_stop(meshlink_handle_t *mesh) { + if(!mesh) { meshlink_errno = MESHLINK_EINVAL; return; } - listen_socket_t *s = &mesh->listen_socket[0]; + // Stop discovery + + bool discovery_on = mesh->discovery_threadstarted; + discovery_stop(mesh); + if(discovery_on) { + pthread_mutex_lock(&global_mutex); + discovery_started = false; + pthread_mutex_unlock(&global_mutex); + } // Shut down a listening socket to signal the main thread to shut down + listen_socket_t *s = &mesh->listen_socket[0]; shutdown(s->tcp.fd, SHUT_RDWR); // Wait for the main thread to finish @@ -1398,7 +1426,7 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { } if(!port) - port = "655"; + goto invalid; if(!b64decode(slash, mesh->hash, 18) || !b64decode(slash + 24, mesh->cookie, 18)) goto invalid; @@ -1659,6 +1687,46 @@ void meshlink_whitelist(meshlink_handle_t *mesh, meshlink_node_t *node) { return; } +/* Hint that a hostname may be found at an address + * See header file for detailed comment. + */ +extern void meshlink_hint_address(meshlink_handle_t *mesh, meshlink_node_t *node, struct sockaddr *addr) { + if(!mesh || !node || !addr) + return; + + char *addr_str = malloc(MAX_ADDRESS_LENGTH*sizeof(char)); + memset(addr_str, 0, MAX_ADDRESS_LENGTH*sizeof(char)); + + char *port_str = malloc(MAX_PORT_LENGTH*sizeof(char)); + memset(port_str, 0, MAX_PORT_LENGTH*sizeof(char)); + + // extra byte for a space, and one to make sure string is null-terminated + int full_addr_len = MAX_ADDRESS_LENGTH + MAX_PORT_LENGTH + 2; + + char *full_addr_str = malloc(full_addr_len*sizeof(char)); + memset(full_addr_str, 0, full_addr_len*sizeof(char)); + + // get address and port number + if(!get_ip_str(addr, addr_str, MAX_ADDRESS_LENGTH)) + goto fail; + if(!get_port_str(addr, port_str, MAX_ADDRESS_LENGTH)) + goto fail; + + // append_config_file expects an address, a space, and then a port number + strcat(full_addr_str, addr_str); + strcat(full_addr_str, " "); + strcat(full_addr_str, port_str); + + append_config_file(mesh, node->name, "Address", full_addr_str); + +fail: + free(addr_str); + free(port_str); + free(full_addr_str); + + // @TODO do we want to fire off a connection attempt right away? +} + static void __attribute__((constructor)) meshlink_init(void) { crypto_init(); }