]> git.meshlink.io Git - meshlink/commitdiff
Make the join commit order configurable. feature/join-commit-order
authorGuus Sliepen <guus@meshlink.io>
Tue, 11 Feb 2020 21:28:24 +0000 (22:28 +0100)
committerGuus Sliepen <guus@meshlink.io>
Tue, 11 Feb 2020 21:32:00 +0000 (22:32 +0100)
By default, when an invitee joins a mesh, it will commit its configuration
to disk first, then the inviter. This adds a function to reverse that order.

src/meshlink++.h
src/meshlink.c
src/meshlink.h
src/meshlink.sym
src/meshlink_internal.h
src/protocol_auth.c

index 6374a86d3b3725920c4b464da91afb6dbfaa744c..4d900448baae145a0b91616190d09c8e5766328e 100644 (file)
@@ -1019,6 +1019,17 @@ public:
                meshlink_set_dev_class_fast_retry_period(handle, devclass, fast_retry_period);
        }
 
+       /// Set which order invitations are committed
+       /** This determines in which order configuration files are written to disk during an invitation.
+        *  By default, the invitee saves the configuration to disk first, then the inviter.
+        *  By calling this function with @a inviter_commits_first set to true, the order is reversed.
+        *
+        *  @param inviter_commits_first  If true, then the node that invited a peer will commit data to disk first.
+        */
+       void set_inviter_commits_first(bool inviter_commits_first) {
+               meshlink_set_inviter_commits_first(handle, inviter_commits_first);
+       }
+
 private:
        // non-copyable:
        mesh(const mesh &) /* TODO: C++11: = delete */;
index eb9142cc743d842c7f8967e0b9a4408aa170113e..903ff09a2040049d1b979bf8b3689bcb0ee42657 100644 (file)
@@ -775,21 +775,44 @@ static bool invitation_receive(void *handle, uint8_t type, const void *msg, uint
        join_state_t *state = handle;
        meshlink_handle_t *mesh = state->mesh;
 
-       switch(type) {
-       case SPTPS_HANDSHAKE:
-               return sptps_send_record(&state->sptps, 0, state->cookie, 18);
+       if(mesh->inviter_commits_first) {
+               switch(type) {
+               case SPTPS_HANDSHAKE:
+                       return sptps_send_record(&state->sptps, 2, state->cookie, 18 + 32);
 
-       case 0:
-               return finalize_join(state, msg, len);
+               case 1:
+                       break;
 
-       case 1:
-               logger(mesh, MESHLINK_DEBUG, "Invitation successfully accepted.\n");
-               shutdown(state->sock, SHUT_RDWR);
-               state->success = true;
-               break;
+               case 0:
+                       if(!finalize_join(state, msg, len)) {
+                               return false;
+                       }
 
-       default:
-               return false;
+                       logger(mesh, MESHLINK_DEBUG, "Invitation successfully accepted.\n");
+                       shutdown(state->sock, SHUT_RDWR);
+                       state->success = true;
+                       break;
+
+               default:
+                       return false;
+               }
+       } else {
+               switch(type) {
+               case SPTPS_HANDSHAKE:
+                       return sptps_send_record(&state->sptps, 0, state->cookie, 18);
+
+               case 0:
+                       return finalize_join(state, msg, len);
+
+               case 1:
+                       logger(mesh, MESHLINK_DEBUG, "Invitation successfully accepted.\n");
+                       shutdown(state->sock, SHUT_RDWR);
+                       state->success = true;
+                       break;
+
+               default:
+                       return false;
+               }
        }
 
        return true;
@@ -2647,6 +2670,10 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) {
                goto invalid;
        }
 
+       if(mesh->inviter_commits_first) {
+               memcpy(state.cookie + 18, ecdsa_get_public_key(mesh->private_key), 32);
+       }
+
        // Generate a throw-away key for the invitation.
        key = ecdsa_generate();
 
index 8a3c1a19ab78fef1ee763faa522d48b8e9aa94a7..385c12cec44b17f5a5609e62d5ad42b6607ba507 100644 (file)
@@ -1551,6 +1551,17 @@ extern void meshlink_set_dev_class_timeouts(struct meshlink_handle *mesh, dev_cl
  */
 extern void meshlink_set_dev_class_fast_retry_period(struct meshlink_handle *mesh, dev_class_t devclass, int fast_retry_period);
 
+/// Set which order invitations are committed
+/** This determines in which order configuration files are written to disk during an invitation.
+ *  By default, the invitee saves the configuration to disk first, then the inviter.
+ *  By calling this function with @a inviter_commits_first set to true, the order is reversed.
+ *
+ *  \memberof meshlink_handle
+ *  @param mesh               A handle which represents an instance of MeshLink.
+ *  @param inviter_commits_first  If true, then the node that invited a peer will commit data to disk first.
+ */
+extern void meshlink_set_inviter_commits_first(struct meshlink_handle *mesh, bool inviter_commits_first);
+
 #ifdef __cplusplus
 }
 #endif
index 9c3d9065dd940965e7f0f3d9061bdf6c8b6d1c4e..4a89b5eac6394c8c2d675c4a2d4723bcc41f825c 100644 (file)
@@ -70,6 +70,7 @@ meshlink_set_dev_class_fast_retry_period
 meshlink_set_dev_class_timeouts
 meshlink_set_error_cb
 meshlink_set_invitation_timeout
+meshlink_set_inviter_commits_first
 meshlink_set_log_cb
 meshlink_set_node_channel_timeout
 meshlink_set_node_duplicate_cb
index 8104ba60e4c953489ca1102651d25675d90cd451..f895e02f6b50dffebc28e80232fd0f3ef8141eaa 100644 (file)
@@ -168,7 +168,7 @@ struct meshlink_handle {
 
        bool default_blacklist;
        bool discovery;         // Whether Catta is enabled or not
-
+       bool inviter_commits_first;
 
        // Configuration
        char *confbase;
index 6517d9ceef8765bcb5493d03b75daecd98c9865a..1ece41cea592bf6e62d607104447c8bcc15ec0c1 100644 (file)
@@ -152,12 +152,7 @@ bool send_id(meshlink_handle_t *mesh, connection_t *c) {
        return send_request(mesh, c, NULL, "%d %s %d.%d %s", ID, mesh->self->name, PROT_MAJOR, PROT_MINOR, mesh->appname);
 }
 
-static bool finalize_invitation(meshlink_handle_t *mesh, connection_t *c, const void *data, uint16_t len) {
-       if(len != 32) {
-               logger(mesh, MESHLINK_ERROR, "Received invalid key from invited node %s!\n", c->name);
-               return false;
-       }
-
+static bool commit_invitation(meshlink_handle_t *mesh, connection_t *c, const void *data) {
        // Create a new node
        node_t *n = new_node();
        n->name = xstrdup(c->name);
@@ -186,22 +181,7 @@ static bool finalize_invitation(meshlink_handle_t *mesh, connection_t *c, const
        return true;
 }
 
-static bool receive_invitation_sptps(void *handle, uint8_t type, const void *data, uint16_t len) {
-       connection_t *c = handle;
-       meshlink_handle_t *mesh = c->mesh;
-
-       if(type == 128) {
-               return true;
-       }
-
-       if(type == 1 && c->status.invitation_used) {
-               return finalize_invitation(mesh, c, data, len);
-       }
-
-       if(type != 0 || len != 18 || c->status.invitation_used) {
-               return false;
-       }
-
+static bool process_invitation(meshlink_handle_t *mesh, connection_t *c, const void *data) {
        // Recover the filename from the cookie and the key
        char *fingerprint = ecdsa_get_base64_public_key(mesh->invitation_key);
        char hash[64];
@@ -248,6 +228,10 @@ static bool receive_invitation_sptps(void *handle, uint8_t type, const void *dat
                }
        }
 
+       if(mesh->inviter_commits_first && !commit_invitation(mesh, c, (const char *)data + 18)) {
+               return false;
+       }
+
        // Send the node the contents of the invitation file
        sptps_send_record(&c->sptps, 0, config.buf, config.len);
 
@@ -259,6 +243,30 @@ static bool receive_invitation_sptps(void *handle, uint8_t type, const void *dat
        return true;
 }
 
+static bool receive_invitation_sptps(void *handle, uint8_t type, const void *data, uint16_t len) {
+       connection_t *c = handle;
+       meshlink_handle_t *mesh = c->mesh;
+
+       if(type == SPTPS_HANDSHAKE) {
+               // The peer should send its cookie first.
+               return true;
+       }
+
+       if(mesh->inviter_commits_first) {
+               if(type == 2 && len == 18 + 32 && !c->status.invitation_used) {
+                       return process_invitation(mesh, c, data);
+               }
+       } else {
+               if(type == 0 && len == 18 && !c->status.invitation_used) {
+                       return process_invitation(mesh, c, data);
+               } else if(type == 1 && len == 32 && c->status.invitation_used) {
+                       return commit_invitation(mesh, c, data);
+               }
+       }
+
+       return false;
+}
+
 bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
        assert(request);
        assert(*request);