]> git.meshlink.io Git - meshlink/blobdiff - src/meshlink.c
Remove global variables.
[meshlink] / src / meshlink.c
index 185f6689af767d6e3ab207816619962ede74e4fe..7e2e20e5c358b08b4ad7a57789055671cca3d626 100644 (file)
@@ -599,7 +599,7 @@ static bool finalize_join(meshlink_handle_t *mesh, const void *buf, uint16_t len
        free(mesh->self->name);
        mesh->name = name;
        mesh->self->name = xstrdup(name);
-       mesh->self->devclass = devclass;
+       mesh->self->devclass = devclass == DEV_CLASS_UNKNOWN ? mesh->devclass : devclass;
 
        // Initialize configuration directory
        if(!config_init(mesh, "current")) {
@@ -744,8 +744,9 @@ static bool recvline(meshlink_handle_t *mesh, size_t len) {
 
        return true;
 }
+
 static bool sendline(int fd, char *format, ...) {
-       static char buffer[4096];
+       char buffer[4096];
        char *p = buffer;
        int blen = 0;
        va_list ap;
@@ -1058,19 +1059,82 @@ bool meshlink_open_params_set_storage_key(meshlink_open_params_t *params, const
 }
 
 bool meshlink_encrypted_key_rotate(meshlink_handle_t *mesh, const void *new_key, size_t new_keylen) {
+       if(!mesh || !new_key || !new_keylen) {
+               logger(mesh, MESHLINK_ERROR, "Invalid arguments given!\n");
+               meshlink_errno = MESHLINK_EINVAL;
+               return false;
+       }
+
+       pthread_mutex_lock(&(mesh->mesh_mutex));
+
+       // Create hash for the new key
+       void *new_config_key;
+       new_config_key = xmalloc(CHACHA_POLY1305_KEYLEN);
+
+       if(!prf(new_key, new_keylen, "MeshLink configuration key", 26, new_config_key, CHACHA_POLY1305_KEYLEN)) {
+               logger(mesh, MESHLINK_ERROR, "Error creating new configuration key!\n");
+               meshlink_errno = MESHLINK_EINTERNAL;
+               pthread_mutex_unlock(&(mesh->mesh_mutex));
+               return false;
+       }
+
+       // Copy contents of the "current" confbase sub-directory to "new" confbase sub-directory with the new key
+
+       if(!config_copy(mesh, "current", mesh->config_key, "new", new_config_key)) {
+               logger(mesh, MESHLINK_ERROR, "Could not set up configuration in %s/old: %s\n", mesh->confbase, strerror(errno));
+               meshlink_errno = MESHLINK_ESTORAGE;
+               pthread_mutex_unlock(&(mesh->mesh_mutex));
+               return false;
+       }
 
-       // While copying old config files to new config files
        devtool_keyrotate_probe(1);
-       // After completed creating new config files in confbase/new/
+
+       main_config_unlock(mesh);
+
+       // Rename confbase/current/ to confbase/old
+
+       if(!config_rename(mesh, "current", "old")) {
+               logger(mesh, MESHLINK_ERROR, "Cannot rename %s/current to %s/old\n", mesh->confbase, mesh->confbase);
+               meshlink_errno = MESHLINK_ESTORAGE;
+               main_config_lock(mesh);
+               pthread_mutex_unlock(&(mesh->mesh_mutex));
+               return false;
+       }
+
        devtool_keyrotate_probe(2);
-       // Rename confbase/current to confbase/old/
-       devtool_keyrotate_probe(3);
+
        // Rename confbase/new/ to confbase/current
-       devtool_keyrotate_probe(4);
-       // Before deleting old sub-directory
-       devtool_keyrotate_probe(5);
 
-       return false;
+       if(!config_rename(mesh, "new", "current")) {
+               logger(mesh, MESHLINK_ERROR, "Cannot rename %s/new to %s/current\n", mesh->confbase, mesh->confbase);
+               meshlink_errno = MESHLINK_ESTORAGE;
+               main_config_lock(mesh);
+               pthread_mutex_unlock(&(mesh->mesh_mutex));
+               return false;
+       }
+
+       devtool_keyrotate_probe(3);
+
+       if(!main_config_lock(mesh)) {
+               pthread_mutex_unlock(&(mesh->mesh_mutex));
+               return false;
+       }
+
+       // Cleanup the "old" confbase sub-directory
+
+       if(!config_destroy(mesh->confbase, "old")) {
+               pthread_mutex_unlock(&(mesh->mesh_mutex));
+               return false;
+       }
+
+       // Change the mesh handle key with new key
+
+       free(mesh->config_key);
+       mesh->config_key = new_config_key;
+
+       pthread_mutex_unlock(&(mesh->mesh_mutex));
+
+       return true;
 }
 
 void meshlink_open_params_free(meshlink_open_params_t *params) {
@@ -1328,10 +1392,27 @@ static void *meshlink_main_loop(void *arg) {
 
        pthread_mutex_lock(&(mesh->mesh_mutex));
 
+#if HAVE_CATTA
+
+       if(mesh->discovery) {
+               discovery_start(mesh);
+       }
+
+#endif
+
        logger(mesh, MESHLINK_DEBUG, "Starting main_loop...\n");
        main_loop(mesh);
        logger(mesh, MESHLINK_DEBUG, "main_loop returned.\n");
 
+#if HAVE_CATTA
+
+       // Stop discovery
+       if(mesh->discovery) {
+               discovery_stop(mesh);
+       }
+
+#endif
+
        pthread_mutex_unlock(&(mesh->mesh_mutex));
        return NULL;
 }
@@ -1390,14 +1471,6 @@ bool meshlink_start(meshlink_handle_t *mesh) {
 
        mesh->threadstarted = true;
 
-#if HAVE_CATTA
-
-       if(mesh->discovery) {
-               discovery_start(mesh);
-       }
-
-#endif
-
        assert(mesh->self->ecdsa);
        assert(!memcmp((uint8_t *)mesh->self->ecdsa + 64, (uint8_t *)mesh->private_key + 64, 32));
 
@@ -1415,15 +1488,6 @@ void meshlink_stop(meshlink_handle_t *mesh) {
        pthread_mutex_lock(&(mesh->mesh_mutex));
        logger(mesh, MESHLINK_DEBUG, "meshlink_stop called\n");
 
-#if HAVE_CATTA
-
-       // Stop discovery
-       if(mesh->discovery) {
-               discovery_stop(mesh);
-       }
-
-#endif
-
        // Shut down the main thread
        event_loop_stop(&mesh->loop);
 
@@ -2247,7 +2311,15 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) {
 
        //Before doing meshlink_join make sure we are not connected to another mesh
        if(mesh->threadstarted) {
-               logger(mesh, MESHLINK_DEBUG, "Already connected to a mesh\n");
+               logger(mesh, MESHLINK_ERROR, "Cannot join while started\n");
+               meshlink_errno = MESHLINK_EINVAL;
+               pthread_mutex_unlock(&(mesh->mesh_mutex));
+               return false;
+       }
+
+       // Refuse to join a mesh if we are already part of one. We are part of one if we know at least one other node.
+       if(mesh->nodes->count > 1) {
+               logger(mesh, MESHLINK_ERROR, "Already part of an existing mesh\n");
                meshlink_errno = MESHLINK_EINVAL;
                pthread_mutex_unlock(&(mesh->mesh_mutex));
                return false;
@@ -3019,6 +3091,16 @@ end:
 #endif
 }
 
+void handle_network_change(meshlink_handle_t *mesh, bool online) {
+       (void)online;
+
+       if(!mesh->connections) {
+               return;
+       }
+
+       retry(mesh);
+}
+
 static void __attribute__((constructor)) meshlink_init(void) {
        crypto_init();
        unsigned int seed;
@@ -3031,7 +3113,7 @@ static void __attribute__((destructor)) meshlink_exit(void) {
 }
 
 /// Device class traits
-dev_class_traits_t dev_class_traits[_DEV_CLASS_MAX + 1] = {
+const 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