]> git.meshlink.io Git - meshlink/commitdiff
Add meshlink_set_storage_policy().
authorGuus Sliepen <guus@meshlink.io>
Fri, 29 Jan 2021 21:59:57 +0000 (22:59 +0100)
committerGuus Sliepen <guus@meshlink.io>
Wed, 3 Mar 2021 11:39:50 +0000 (12:39 +0100)
This allows control over when MeshLink stores configuration files:

- MESHLINK_STORAGE_ENABLED: on all updates
- MESHLINK_STORAGE_KEYS_ONLY: only on new keys and black/whitelist updates
- MESHLINK_STORAGE_DISABLED: never

src/conf.c
src/graph.c
src/meshlink++.h
src/meshlink.c
src/meshlink.h
src/meshlink.sym
src/meshlink_internal.h
src/net.c
src/net.h
src/net_setup.c
src/protocol_auth.c

index dd0761705ee0b3ff356d195500a4269b56299309..af080384d4f40a588eabad1fb1b61ecbe21ea5e4 100644 (file)
@@ -405,7 +405,7 @@ bool config_rename(meshlink_handle_t *mesh, const char *old_conf_subdir, const c
 bool config_sync(meshlink_handle_t *mesh, const char *conf_subdir) {
        assert(conf_subdir);
 
-       if(!mesh->confbase) {
+       if(!mesh->confbase || mesh->storage_policy == MESHLINK_STORAGE_DISABLED) {
                return true;
        }
 
index b73a35e69f749c98bc839c5f2ed9b3a414bdbe21..c7401b6a6341e669f0dfc7c5535d74a15fc54de5 100644 (file)
@@ -177,7 +177,7 @@ static void check_reachability(meshlink_handle_t *mesh) {
                                        n->last_reachable = time(NULL);
 
                                        if(first_time_reachable) {
-                                               if(!node_write_config(mesh, n)) {
+                                               if(!node_write_config(mesh, n, false)) {
                                                        logger(mesh, MESHLINK_WARNING, "Could not write host config file for node %s!\n", n->name);
 
                                                }
index 51bc5e37a91792523bfeb8633b951886f7e4a1b9..1f109849b6408e5cd7487f4365c92b3493a32185 100644 (file)
@@ -705,6 +705,19 @@ public:
                meshlink_set_scheduling_granularity(handle, granularity);
        }
 
+       /// Sets the storage policy used by MeshLink
+       /** This sets the policy MeshLink uses when it has new information about nodes.
+        *  By default, all udpates will be stored to disk (unless an ephemeral instance has been opened).
+        *  Setting the policy to MESHLINK_STORAGE_KEYS_ONLY, only updates that contain new keys for nodes
+        *  are stored, as well as blacklist/whitelist settings.
+        *  By setting the policy to MESHLINK_STORAGE_DISABLED, no updates will be stored.
+        *
+        *  @param policy  The storage policy to use.
+        */
+       void set_storage_policy(meshlink_storage_policy_t policy) {
+               meshlink_set_storage_policy(handle, policy);
+       }
+
        /// Invite another node into the mesh.
        /** This function generates an invitation that can be used by another node to join the same mesh as the local node.
         *  The generated invitation is a string containing a URL.
index 1540df37344ace42cc87c70cc07160401fd914e7..26bcada773151a382772e2117e05d5bb101ce67f 100644 (file)
@@ -689,7 +689,7 @@ static bool write_main_config_files(meshlink_handle_t *mesh) {
        }
 
        /* Write our own host config file */
-       if(!node_write_config(mesh, mesh->self)) {
+       if(!node_write_config(mesh, mesh->self, true)) {
                return false;
        }
 
@@ -823,7 +823,7 @@ static bool finalize_join(join_state_t *state, const void *buf, uint16_t len) {
                n->last_reachable = 0;
                n->last_unreachable = 0;
 
-               if(!node_write_config(mesh, n)) {
+               if(!node_write_config(mesh, n, true)) {
                        free_node(n);
                        return false;
                }
@@ -1262,6 +1262,17 @@ bool meshlink_open_params_set_storage_key(meshlink_open_params_t *params, const
        return true;
 }
 
+bool meshlink_open_params_set_storage_policy(meshlink_open_params_t *params, meshlink_storage_policy_t policy) {
+       if(!params) {
+               meshlink_errno = MESHLINK_EINVAL;
+               return false;
+       }
+
+       params->storage_policy = policy;
+
+       return true;
+}
+
 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");
@@ -1544,6 +1555,8 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) {
 
        // If no configuration exists yet, create it.
 
+       bool new_configuration = false;
+
        if(!meshlink_confbase_exists(mesh)) {
                if(!mesh->name) {
                        logger(NULL, MESHLINK_ERROR, "No configuration files found!\n");
@@ -1557,6 +1570,8 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) {
                        meshlink_close(mesh);
                        return NULL;
                }
+
+               new_configuration = true;
        } else {
                if(!meshlink_read_config(mesh)) {
                        logger(NULL, MESHLINK_ERROR, "Cannot read main configuration\n");
@@ -1565,6 +1580,8 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) {
                }
        }
 
+       mesh->storage_policy = params->storage_policy;
+
 #ifdef HAVE_MINGW
        struct WSAData wsa_state;
        WSAStartup(MAKEWORD(2, 2), &wsa_state);
@@ -1601,7 +1618,7 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) {
 
        add_local_addresses(mesh);
 
-       if(!node_write_config(mesh, mesh->self)) {
+       if(!node_write_config(mesh, mesh->self, new_configuration)) {
                logger(NULL, MESHLINK_ERROR, "Cannot update configuration\n");
                return NULL;
        }
@@ -1829,7 +1846,7 @@ void meshlink_stop(meshlink_handle_t *mesh) {
        if(mesh->nodes) {
                for splay_each(node_t, n, mesh->nodes) {
                        if(n->status.dirty) {
-                               n->status.dirty = !node_write_config(mesh, n);
+                               n->status.dirty = !node_write_config(mesh, n, false);
                        }
                }
        }
@@ -2645,7 +2662,7 @@ bool meshlink_set_canonical_address(meshlink_handle_t *mesh, meshlink_node_t *no
        free(n->canonical_address);
        n->canonical_address = canonical_address;
 
-       if(!node_write_config(mesh, n)) {
+       if(!node_write_config(mesh, n, false)) {
                pthread_mutex_unlock(&mesh->mutex);
                return false;
        }
@@ -2669,7 +2686,7 @@ bool meshlink_clear_canonical_address(meshlink_handle_t *mesh, meshlink_node_t *
        free(n->canonical_address);
        n->canonical_address = NULL;
 
-       if(!node_write_config(mesh, n)) {
+       if(!node_write_config(mesh, n, false)) {
                pthread_mutex_unlock(&mesh->mutex);
                return false;
        }
@@ -2919,7 +2936,7 @@ char *meshlink_invite_ex(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, c
 
        // If we changed our own host config file, write it out now
        if(mesh->self->status.dirty) {
-               if(!node_write_config(mesh, mesh->self)) {
+               if(!node_write_config(mesh, mesh->self, false)) {
                        logger(mesh, MESHLINK_ERROR, "Could not write our own host config file!\n");
                        pthread_mutex_unlock(&mesh->mutex);
                        return NULL;
@@ -3415,7 +3432,7 @@ bool meshlink_import(meshlink_handle_t *mesh, const char *data) {
                n->last_reachable = 0;
                n->last_unreachable = 0;
 
-               if(!node_write_config(mesh, n)) {
+               if(!node_write_config(mesh, n, true)) {
                        free_node(n);
                        return false;
                }
@@ -3489,7 +3506,7 @@ static bool blacklist(meshlink_handle_t *mesh, node_t *n) {
        /* Remove any outstanding invitations */
        invitation_purge_node(mesh, n->name);
 
-       return node_write_config(mesh, n) && config_sync(mesh, "current");
+       return node_write_config(mesh, n, true) && config_sync(mesh, "current");
 }
 
 bool meshlink_blacklist(meshlink_handle_t *mesh, meshlink_node_t *node) {
@@ -3561,7 +3578,7 @@ static bool whitelist(meshlink_handle_t *mesh, node_t *n) {
                update_node_status(mesh, n);
        }
 
-       return node_write_config(mesh, n) && config_sync(mesh, "current");
+       return node_write_config(mesh, n, true) && config_sync(mesh, "current");
 }
 
 bool meshlink_whitelist(meshlink_handle_t *mesh, meshlink_node_t *node) {
@@ -3695,7 +3712,7 @@ void meshlink_hint_address(meshlink_handle_t *mesh, meshlink_node_t *node, const
        node_t *n = (node_t *)node;
 
        if(node_add_recent_address(mesh, n, (sockaddr_t *)addr)) {
-               if(!node_write_config(mesh, n)) {
+               if(!node_write_config(mesh, n, false)) {
                        logger(mesh, MESHLINK_DEBUG, "Could not update %s\n", n->name);
                }
        }
@@ -4644,6 +4661,20 @@ void meshlink_set_scheduling_granularity(struct meshlink_handle *mesh, long gran
        utcp_set_clock_granularity(granularity);
 }
 
+void meshlink_set_storage_policy(struct meshlink_handle *mesh, meshlink_storage_policy_t policy) {
+       if(!mesh) {
+               meshlink_errno = EINVAL;
+               return;
+       }
+
+       if(pthread_mutex_lock(&mesh->mutex) != 0) {
+               abort();
+       }
+
+       mesh->storage_policy = policy;
+       pthread_mutex_unlock(&mesh->mutex);
+}
+
 void handle_network_change(meshlink_handle_t *mesh, bool online) {
        (void)online;
 
index 822e314b68929a5186eb3cbbd046517b8576bb70..3be94710309da0a13c36b231578456156279b8fc 100644 (file)
@@ -83,6 +83,13 @@ typedef enum {
        DEV_CLASS_COUNT
 } dev_class_t;
 
+/// Storage policy
+typedef enum {
+       MESHLINK_STORAGE_ENABLED,    ///< Store all updates.
+       MESHLINK_STORAGE_DISABLED,   ///< Don't store any updates.
+       MESHLINK_STORAGE_KEYS_ONLY,  ///< Only store updates when a node's key has changed.
+} meshlink_storage_policy_t;
+
 /// Invitation flags
 static const uint32_t MESHLINK_INVITE_LOCAL = 1;    // Only use local addresses in the URL
 static const uint32_t MESHLINK_INVITE_PUBLIC = 2;   // Only use public or canonical addresses in the URL
@@ -189,6 +196,16 @@ bool meshlink_open_params_set_netns(meshlink_open_params_t *params, int netns) _
  */
 bool meshlink_open_params_set_storage_key(meshlink_open_params_t *params, const void *key, size_t keylen) __attribute__((__warn_unused_result__));
 
+/// Set the encryption key MeshLink should use for local storage.
+/** This function changes the open parameters to use the given storage policy.
+ *
+ *  @param params   A pointer to a meshlink_open_params_t which must have been created earlier with meshlink_open_params_init().
+ *  @param policy   The storage policy to use.
+ *
+ *  @return         This function will return true if the open parameters have been successfully updated, false otherwise.
+ */
+bool meshlink_open_params_set_storage_policy(meshlink_open_params_t *params, meshlink_storage_policy_t policy) __attribute__((__warn_unused_result__));
+
 /// Open or create a MeshLink instance.
 /** This function opens or creates a MeshLink instance.
  *  All parameters needed by MeshLink are passed via a meshlink_open_params_t struct,
@@ -1780,6 +1797,19 @@ void meshlink_set_external_address_discovery_url(struct meshlink_handle *mesh, c
  */
 void meshlink_set_scheduling_granularity(struct meshlink_handle *mesh, long granularity);
 
+/// Sets the storage policy used by MeshLink
+/** This sets the policy MeshLink uses when it has new information about nodes.
+ *  By default, all udpates will be stored to disk (unless an ephemeral instance has been opened).
+ *  Setting the policy to MESHLINK_STORAGE_KEYS_ONLY, only updates that contain new keys for nodes
+ *  are stored, as well as blacklist/whitelist settings.
+ *  By setting the policy to MESHLINK_STORAGE_DISABLED, no updates will be stored.
+ *
+ *  \memberof meshlink_handle
+ *  @param mesh    A handle which represents an instance of MeshLink.
+ *  @param policy  The storage policy to use.
+ */
+void meshlink_set_storage_policy(struct meshlink_handle *mesh, meshlink_storage_policy_t policy);
+
 #ifdef __cplusplus
 }
 #endif
index 6c29df36b877b60735f1f35267ac4519cfa9169d..f8df23e1dc9b0181a2f393c3f9f0a80cb0a1461e 100644 (file)
@@ -67,6 +67,7 @@ meshlink_open_params_free
 meshlink_open_params_init
 meshlink_open_params_set_netns
 meshlink_open_params_set_storage_key
+meshlink_open_params_set_storage_policy
 meshlink_reset_timers
 meshlink_send
 meshlink_set_blacklisted_cb
@@ -100,6 +101,7 @@ meshlink_set_scheduling_granularity
 meshlink_sign
 meshlink_start
 meshlink_stop
+meshlink_set_storage_policy
 meshlink_strerror
 meshlink_submesh_open
 meshlink_verify
index 011075079e86473166c17a1dd28bfb389ff0325f..6cbe6093f42258f84ecb5b0c133b7d2018965ffa 100644 (file)
@@ -67,6 +67,7 @@ struct meshlink_open_params {
 
        const void *key;
        size_t keylen;
+       meshlink_storage_policy_t storage_policy;
 };
 
 /// Device class traits
@@ -170,6 +171,7 @@ struct meshlink_handle {
        void *config_key;
        char *external_address_url;
        struct list_t *invitation_addresses;
+       meshlink_storage_policy_t storage_policy;
 
        // Thread management
        pthread_t thread;
index 99c29c943290b1ea7636b7b01dd9ed072a965665..9a062f41482536f4f1d7fc4e1051e8240bae9ea6 100644 (file)
--- a/src/net.c
+++ b/src/net.c
@@ -620,11 +620,9 @@ static void periodic_handler(event_loop_t *loop, void *data) {
 
        for splay_each(node_t, n, mesh->nodes) {
                if(n->status.dirty) {
-                       if(!node_write_config(mesh, n)) {
+                       if(!node_write_config(mesh, n, false)) {
                                logger(mesh, MESHLINK_DEBUG, "Could not update %s", n->name);
                        }
-
-                       n->status.dirty = false;
                }
 
                if(n->status.reachable && n->status.validkey && n->last_req_key + 3600 < mesh->loop.now.tv_sec) {
index 5ad279793aa022c1721fafb477f93e551044f45c..9994fac6fe700bbeca2750205aeb168a2bf0d5e4 100644 (file)
--- a/src/net.h
+++ b/src/net.h
@@ -106,7 +106,7 @@ bool node_read_public_key(struct meshlink_handle *mesh, struct node_t *) __attri
 bool node_read_from_config(struct meshlink_handle *mesh, struct node_t *, const config_t *config) __attribute__((__warn_unused_result__));
 bool read_ecdsa_public_key(struct meshlink_handle *mesh, struct connection_t *) __attribute__((__warn_unused_result__));
 bool read_ecdsa_private_key(struct meshlink_handle *mesh) __attribute__((__warn_unused_result__));
-bool node_write_config(struct meshlink_handle *mesh, struct node_t *) __attribute__((__warn_unused_result__));
+bool node_write_config(struct meshlink_handle *mesh, struct node_t *, bool new_key) __attribute__((__warn_unused_result__));
 void send_mtu_probe(struct meshlink_handle *mesh, struct node_t *);
 void handle_meta_connection_data(struct meshlink_handle *mesh, struct connection_t *);
 void retry(struct meshlink_handle *mesh);
index 6168c4ca340dfc92f9551c2c17f78eb624600758..a7a538f01c75d1b4ed66fa77114391bbce123ce1 100644 (file)
@@ -218,11 +218,26 @@ bool node_read_from_config(meshlink_handle_t *mesh, node_t *n, const config_t *c
        return packmsg_done(&in);
 }
 
-bool node_write_config(meshlink_handle_t *mesh, node_t *n) {
+bool node_write_config(meshlink_handle_t *mesh, node_t *n, bool new_key) {
        if(!mesh->confbase) {
                return true;
        }
 
+       switch(mesh->storage_policy) {
+       case MESHLINK_STORAGE_KEYS_ONLY:
+               if(!new_key) {
+                       return true;
+               }
+
+               break;
+
+       case MESHLINK_STORAGE_DISABLED:
+               return true;
+
+       default:
+               break;
+       }
+
        uint8_t buf[4096];
        packmsg_output_t out = {buf, sizeof(buf)};
 
@@ -271,6 +286,7 @@ bool node_write_config(meshlink_handle_t *mesh, node_t *n) {
                return false;
        }
 
+       n->status.dirty = false;
        return true;
 }
 
index 1f2e24a2ce8d9d6def723ee1a851ac4b5928ccef..5f2fc1c38cc35a9b48698aa1e38771f9a300132d 100644 (file)
@@ -71,7 +71,7 @@ static bool commit_invitation(meshlink_handle_t *mesh, connection_t *c, const vo
        // Remember its current address
        node_add_recent_address(mesh, n, &c->address);
 
-       if(!node_write_config(mesh, n) || !config_sync(mesh, "current")) {
+       if(!node_write_config(mesh, n, true) || !config_sync(mesh, "current")) {
                logger(mesh, MESHLINK_ERROR, "Error writing configuration file for invited node %s!\n", c->name);
                free_node(n);
                return false;