]> git.meshlink.io Git - meshlink/blobdiff - src/meshlink.c
Fix processing of mixed ID and SPTPS data.
[meshlink] / src / meshlink.c
index c67be83087ee7f32f17afbeae5cb4c6f4c6954bb..418be9e878d636b59844356d10b6a28e05bea162 100644 (file)
@@ -39,6 +39,7 @@ typedef struct {
 #include "node.h"
 #include "protocol.h"
 #include "route.h"
+#include "sockaddr.h"
 #include "utils.h"
 #include "xalloc.h"
 #include "ed25519/sha512.h"
@@ -180,27 +181,24 @@ static void scan_for_hostname(const char *filename, char **hostname, char **port
 
        fclose(f);
 }
-static char *get_my_hostname(meshlink_handle_t* mesh) {
-       char *hostname = NULL;
-       char *port = NULL;
-       char *hostport = NULL;
-       char *name = mesh->self->name;
-       char filename[PATH_MAX] = "";
-       char line[4096];
-       FILE *f;
 
-       // Use first Address statement in own host config file
-       snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
-       scan_for_hostname(filename, &hostname, &port);
+static bool is_valid_hostname(const char *hostname) {
+       for(const char *p = hostname; *p; p++) {
+               if(!(isalnum(*p) || *p == '-' || *p == '.' || *p == ':'))
+                       return false;
+       }
 
-       if(hostname)
-               goto done;
+       return true;
+}
+
+char *meshlink_get_external_address(meshlink_handle_t *mesh) {
+       char *hostname = NULL;
 
-       // If that doesn't work, guess externally visible hostname
        logger(mesh, MESHLINK_DEBUG, "Trying to discover externally visible hostname...\n");
        struct addrinfo *ai = str2addrinfo("meshlink.io", "80", SOCK_STREAM);
        struct addrinfo *aip = ai;
        static const char request[] = "GET http://www.meshlink.io/host.cgi HTTP/1.0\r\n\r\n";
+       char line[256];
 
        while(aip) {
                int s = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
@@ -233,17 +231,33 @@ static char *get_my_hostname(meshlink_handle_t* mesh) {
                freeaddrinfo(ai);
 
        // Check that the hostname is reasonable
-       if(hostname) {
-               for(char *p = hostname; *p; p++) {
-                       if(isalnum(*p) || *p == '-' || *p == '.' || *p == ':')
-                               continue;
-                       // If not, forget it.
-                       free(hostname);
-                       hostname = NULL;
-                       break;
-               }
+       if(hostname && !is_valid_hostname(hostname)) {
+               free(hostname);
+               hostname = NULL;
        }
 
+       if(!hostname)
+               meshlink_errno = MESHLINK_ERESOLV;
+
+       return hostname;
+}
+
+static char *get_my_hostname(meshlink_handle_t* mesh) {
+       char *hostname = NULL;
+       char *port = NULL;
+       char *hostport = NULL;
+       char *name = mesh->self->name;
+       char filename[PATH_MAX] = "";
+       FILE *f;
+
+       // Use first Address statement in own host config file
+       snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
+       scan_for_hostname(filename, &hostname, &port);
+
+       if(hostname)
+               goto done;
+
+       hostname = meshlink_get_external_address(mesh);
        if(!hostname)
                return NULL;
 
@@ -940,10 +954,17 @@ bool meshlink_start(meshlink_handle_t *mesh) {
                meshlink_errno = MESHLINK_EINVAL;
                return false;
        }
-       pthread_mutex_lock(&(mesh->mesh_mutex));
        
        logger(mesh, MESHLINK_DEBUG, "meshlink_start called\n");
 
+       pthread_mutex_lock(&(mesh->mesh_mutex));
+
+       if(mesh->threadstarted) {
+               logger(mesh, MESHLINK_DEBUG, "thread was already running\n");
+               pthread_mutex_unlock(&(mesh->mesh_mutex));
+               return true;
+       }
+
        if(mesh->listen_socket[0].tcp.fd < 0) {
                logger(mesh, MESHLINK_ERROR, "Listening socket not open\n");
                meshlink_errno = MESHLINK_ENETWORK;
@@ -964,6 +985,8 @@ bool meshlink_start(meshlink_handle_t *mesh) {
 
        // Start the main thread
 
+       event_loop_start(&mesh->loop);
+
        if(pthread_create(&mesh->thread, NULL, meshlink_main_loop, mesh) != 0) {
                logger(mesh, MESHLINK_DEBUG, "Could not start thread: %s\n", strerror(errno));
                memset(&mesh->thread, 0, sizeof mesh->thread);
@@ -992,10 +1015,16 @@ void meshlink_stop(meshlink_handle_t *mesh) {
        // Stop discovery
        discovery_stop(mesh);
 
-       // Shut down a listening socket to signal the main thread to shut down
+       pthread_mutex_lock(&(mesh->mesh_mutex));
+       logger(mesh, MESHLINK_DEBUG, "meshlink_stop called\n");
+
+       // Shut down the main thread
+       event_loop_stop(&mesh->loop);
 
+       // Send ourselves a UDP packet to kick the event loop
        listen_socket_t *s = &mesh->listen_socket[0];
-       shutdown(s->tcp.fd, SHUT_RDWR);
+       if(sendto(s->udp.fd, "", 1, MSG_NOSIGNAL, &s->sa.sa, SALEN(s->sa.sa)) == -1)
+               logger(mesh, MESHLINK_ERROR, "Could not send a UDP packet to ourself");
 
        // Wait for the main thread to finish
        pthread_mutex_unlock(&(mesh->mesh_mutex));
@@ -1004,16 +1033,6 @@ void meshlink_stop(meshlink_handle_t *mesh) {
 
        mesh->threadstarted = false;
 
-       // Fix the socket
-       
-       closesocket(s->tcp.fd);
-       io_del(&mesh->loop, &s->tcp);
-       s->tcp.fd = setup_listen_socket(&s->sa);
-       if(s->tcp.fd < 0)
-               logger(mesh, MESHLINK_ERROR, "Could not repair listenen socket!");
-       else
-               io_add(&mesh->loop, &s->tcp, handle_new_meta_connection, s, s->tcp.fd, IO_READ);
-       
        pthread_mutex_unlock(&(mesh->mesh_mutex));
 }
 
@@ -1457,22 +1476,39 @@ bool meshlink_add_address(meshlink_handle_t *mesh, const char *address) {
                meshlink_errno = MESHLINK_EINVAL;
                return false;
        }
-       
+
+       if(!is_valid_hostname(address)) {
+               logger(mesh, MESHLINK_DEBUG, "Invalid character in address: %s\n", address);
+               meshlink_errno = MESHLINK_EINVAL;
+               return false;
+       }
+
        bool rval = false;
 
        pthread_mutex_lock(&(mesh->mesh_mutex));
+       rval = append_config_file(mesh, mesh->self->name, "Address", address);
+       pthread_mutex_unlock(&(mesh->mesh_mutex));
 
-       for(const char *p = address; *p; p++) {
-               if(isalnum(*p) || *p == '-' || *p == '.' || *p == ':')
-                       continue;
-               logger(mesh, MESHLINK_DEBUG, "Invalid character in address: %s\n", address);
+       return rval;
+}
+
+bool meshlink_add_external_address(meshlink_handle_t *mesh) {
+       if(!mesh) {
                meshlink_errno = MESHLINK_EINVAL;
-               pthread_mutex_unlock(&(mesh->mesh_mutex));
                return false;
        }
 
+       char *address = meshlink_get_external_address(mesh);
+       if(!address)
+               return false;
+
+       bool rval = false;
+
+       pthread_mutex_lock(&(mesh->mesh_mutex));
        rval = append_config_file(mesh, mesh->self->name, "Address", address);
        pthread_mutex_unlock(&(mesh->mesh_mutex));
+
+       free(address);
        return rval;
 }
 
@@ -2036,7 +2072,6 @@ meshlink_edge_t **meshlink_get_all_edges_state(meshlink_handle_t *mesh, meshlink
                *nmemb = result_size;
        } else {
                *nmemb = 0;
-               free(result);
                meshlink_errno = MESHLINK_ENOMEM;
        }