From: Guus Sliepen Date: Sat, 12 Jun 2021 15:47:58 +0000 (+0200) Subject: Remove support for meshlink_invite(). X-Git-Url: http://git.meshlink.io/?p=meshlink-tiny;a=commitdiff_plain;h=7a9d30b60af9d5e71f1bfee4dd976d5807402a15 Remove support for meshlink_invite(). --- diff --git a/examples/chat.c b/examples/chat.c index 88fe127..4e6f5d6 100644 --- a/examples/chat.c +++ b/examples/chat.c @@ -51,24 +51,7 @@ static void parse_command(meshlink_handle_t *mesh, char *buf) { *arg++ = 0; } - if(!strcasecmp(buf, "invite")) { - char *invitation; - - if(!arg) { - fprintf(stderr, "/invite requires an argument!\n"); - return; - } - - invitation = meshlink_invite(mesh, NULL, arg); - - if(!invitation) { - fprintf(stderr, "Could not invite '%s': %s\n", arg, meshlink_strerror(meshlink_errno)); - return; - } - - printf("Invitation for %s: %s\n", arg, invitation); - free(invitation); - } else if(!strcasecmp(buf, "join")) { + if(!strcasecmp(buf, "join")) { if(!arg) { fprintf(stderr, "/join requires an argument!\n"); return; @@ -155,7 +138,6 @@ static void parse_command(meshlink_handle_t *mesh, char *buf) { printf( ": Send a message to the given node.\n" " Subsequent messages don't need the : prefix.\n" - "/invite Create an invitation for a new node.\n" "/join Join an existing mesh using an invitation.\n" "/kick Blacklist the given node.\n" "/who [] List all nodes or show information about the given node.\n" diff --git a/examples/chatpp.cc b/examples/chatpp.cc index 294ca86..2fa65d0 100644 --- a/examples/chatpp.cc +++ b/examples/chatpp.cc @@ -41,24 +41,7 @@ static void parse_command(meshlink::mesh *mesh, char *buf) { *arg++ = 0; } - if(!strcasecmp(buf, "invite")) { - char *invitation; - - if(!arg) { - fprintf(stderr, "/invite requires an argument!\n"); - return; - } - - invitation = mesh->invite(NULL, arg); - - if(!invitation) { - fprintf(stderr, "Could not invite '%s': %s\n", arg, meshlink::strerror()); - return; - } - - printf("Invitation for %s: %s\n", arg, invitation); - free(invitation); - } else if(!strcasecmp(buf, "join")) { + if(!strcasecmp(buf, "join")) { if(!arg) { fprintf(stderr, "/join requires an argument!\n"); return; @@ -123,7 +106,6 @@ static void parse_command(meshlink::mesh *mesh, char *buf) { printf( ": Send a message to the given node.\n" " Subsequent messages don't need the : prefix.\n" - "/invite Create an invitation for a new node.\n" "/join Join an existing mesh using an invitation.\n" "/kick Blacklist the given node.\n" "/who [] List all nodes or show information about the given node.\n" diff --git a/src/conf.c b/src/conf.c index db91d5f..6ceb23c 100644 --- a/src/conf.c +++ b/src/conf.c @@ -48,26 +48,6 @@ static void make_host_path(meshlink_handle_t *mesh, const char *conf_subdir, con snprintf(path, len, "%s" SLASH "%s" SLASH "hosts" SLASH "%s", mesh->confbase, conf_subdir, name); } -/// Generate a path to an unused invitation file. -static void make_invitation_path(meshlink_handle_t *mesh, const char *conf_subdir, const char *name, char *path, size_t len) { - assert(conf_subdir); - assert(name); - assert(path); - assert(len); - - snprintf(path, len, "%s" SLASH "%s" SLASH "invitations" SLASH "%s", mesh->confbase, conf_subdir, name); -} - -/// Generate a path to a used invitation file. -static void make_used_invitation_path(meshlink_handle_t *mesh, const char *conf_subdir, const char *name, char *path, size_t len) { - assert(conf_subdir); - assert(name); - assert(path); - assert(len); - - snprintf(path, len, "%s" SLASH "%s" SLASH "invitations" SLASH "%s.used", mesh->confbase, conf_subdir, name); -} - /// Remove a directory recursively static bool deltree(const char *dirname) { assert(dirname); @@ -181,13 +161,6 @@ bool config_init(meshlink_handle_t *mesh, const char *conf_subdir) { return false; } - make_invitation_path(mesh, conf_subdir, "", path, sizeof(path)); - - if(mkdir(path, 0700)) { - logger(mesh, MESHLINK_DEBUG, "Could not create directory %s: %s\n", path, strerror(errno)); - return false; - } - return true; } @@ -860,256 +833,3 @@ bool main_config_write(meshlink_handle_t *mesh, const char *conf_subdir, const c return true; } - -/// Read an invitation file from the confbase sub-directory, and immediately delete it. -bool invitation_read(meshlink_handle_t *mesh, const char *conf_subdir, const char *name, config_t *config, void *key) { - assert(conf_subdir); - assert(name); - assert(config); - - if(!mesh->confbase) { - return false; - } - - char path[PATH_MAX]; - char used_path[PATH_MAX]; - make_invitation_path(mesh, conf_subdir, name, path, sizeof(path)); - make_used_invitation_path(mesh, conf_subdir, name, used_path, sizeof(used_path)); - - // Atomically rename the invitation file - if(rename(path, used_path)) { - if(errno == ENOENT) { - logger(mesh, MESHLINK_ERROR, "Peer tried to use non-existing invitation %s\n", name); - } else { - logger(mesh, MESHLINK_ERROR, "Error trying to rename invitation %s\n", name); - } - - return false; - } - - FILE *f = fopen(used_path, "r"); - - if(!f) { - logger(mesh, MESHLINK_ERROR, "Failed to open `%s': %s", path, strerror(errno)); - return false; - } - - // Check the timestamp - struct stat st; - - if(fstat(fileno(f), &st)) { - logger(mesh, MESHLINK_ERROR, "Could not stat invitation file %s\n", name); - fclose(f); - unlink(used_path); - return false; - } - - if(time(NULL) >= st.st_mtime + mesh->invitation_timeout) { - logger(mesh, MESHLINK_ERROR, "Peer tried to use an outdated invitation file %s\n", name); - fclose(f); - unlink(used_path); - return false; - } - - if(!config_read_file(mesh, f, config, key)) { - logger(mesh, MESHLINK_ERROR, "Failed to read `%s': %s", path, strerror(errno)); - fclose(f); - unlink(used_path); - return false; - } - - fclose(f); - - if(unlink(used_path)) { - logger(mesh, MESHLINK_ERROR, "Failed to unlink `%s': %s", path, strerror(errno)); - return false; - } - - snprintf(path, sizeof(path), "%s" SLASH "%s" SLASH "invitations", mesh->confbase, conf_subdir); - - if(!sync_path(path)) { - logger(mesh, MESHLINK_ERROR, "Failed to sync `%s': %s", path, strerror(errno)); - meshlink_errno = MESHLINK_ESTORAGE; - return false; - } - - return true; -} - -/// Write an invitation file. -bool invitation_write(meshlink_handle_t *mesh, const char *conf_subdir, const char *name, const config_t *config, void *key) { - assert(conf_subdir); - assert(name); - assert(config); - - if(!mesh->confbase) { - return false; - } - - char path[PATH_MAX]; - make_invitation_path(mesh, conf_subdir, name, path, sizeof(path)); - - FILE *f = fopen(path, "w"); - - if(!f) { - logger(mesh, MESHLINK_ERROR, "Failed to open `%s': %s", path, strerror(errno)); - meshlink_errno = MESHLINK_ESTORAGE; - return false; - } - - if(!config_write_file(mesh, f, config, key)) { - logger(mesh, MESHLINK_ERROR, "Failed to write `%s': %s", path, strerror(errno)); - fclose(f); - return false; - } - - if(fclose(f)) { - logger(mesh, MESHLINK_ERROR, "Failed to close `%s': %s", path, strerror(errno)); - meshlink_errno = MESHLINK_ESTORAGE; - return false; - } - - snprintf(path, sizeof(path), "%s" SLASH "%s" SLASH "invitations", mesh->confbase, conf_subdir); - - if(!sync_path(path)) { - logger(mesh, MESHLINK_ERROR, "Failed to sync `%s': %s", path, strerror(errno)); - meshlink_errno = MESHLINK_ESTORAGE; - return false; - } - - return true; -} - -/// Purge old invitation files -size_t invitation_purge_old(meshlink_handle_t *mesh, time_t deadline) { - if(!mesh->confbase) { - return true; - } - - char path[PATH_MAX]; - make_invitation_path(mesh, "current", "", path, sizeof(path)); - - DIR *dir = opendir(path); - - if(!dir) { - logger(mesh, MESHLINK_DEBUG, "Could not read directory %s: %s\n", path, strerror(errno)); - meshlink_errno = MESHLINK_ESTORAGE; - return 0; - } - - errno = 0; - size_t count = 0; - struct dirent *ent; - - while((ent = readdir(dir))) { - if(strlen(ent->d_name) != 24) { - continue; - } - - char invname[PATH_MAX]; - struct stat st; - - if(snprintf(invname, sizeof(invname), "%s" SLASH "%s", path, ent->d_name) >= PATH_MAX) { - logger(mesh, MESHLINK_DEBUG, "Filename too long: %s" SLASH "%s", path, ent->d_name); - continue; - } - - if(!stat(invname, &st)) { - if(mesh->invitation_key && deadline < st.st_mtime) { - count++; - } else { - unlink(invname); - } - } else { - logger(mesh, MESHLINK_DEBUG, "Could not stat %s: %s\n", invname, strerror(errno)); - errno = 0; - } - } - - if(errno) { - logger(mesh, MESHLINK_DEBUG, "Error while reading directory %s: %s\n", path, strerror(errno)); - closedir(dir); - meshlink_errno = MESHLINK_ESTORAGE; - return 0; - } - - closedir(dir); - - return count; -} - -/// Purge invitations for the given node -size_t invitation_purge_node(meshlink_handle_t *mesh, const char *node_name) { - if(!mesh->confbase) { - return true; - } - - char path[PATH_MAX]; - make_invitation_path(mesh, "current", "", path, sizeof(path)); - - DIR *dir = opendir(path); - - if(!dir) { - logger(mesh, MESHLINK_DEBUG, "Could not read directory %s: %s\n", path, strerror(errno)); - meshlink_errno = MESHLINK_ESTORAGE; - return 0; - } - - errno = 0; - size_t count = 0; - struct dirent *ent; - - while((ent = readdir(dir))) { - if(strlen(ent->d_name) != 24) { - continue; - } - - char invname[PATH_MAX]; - - if(snprintf(invname, sizeof(invname), "%s" SLASH "%s", path, ent->d_name) >= PATH_MAX) { - logger(mesh, MESHLINK_DEBUG, "Filename too long: %s" SLASH "%s", path, ent->d_name); - continue; - } - - FILE *f = fopen(invname, "r"); - - if(!f) { - errno = 0; - continue; - } - - config_t config; - - if(!config_read_file(mesh, f, &config, mesh->config_key)) { - logger(mesh, MESHLINK_ERROR, "Failed to read `%s': %s", invname, strerror(errno)); - config_free(&config); - fclose(f); - errno = 0; - continue; - } - - packmsg_input_t in = {config.buf, config.len}; - packmsg_get_uint32(&in); // skip version - char *name = packmsg_get_str_dup(&in); - - if(name && !strcmp(name, node_name)) { - logger(mesh, MESHLINK_DEBUG, "Removing invitation for %s", node_name); - unlink(invname); - } - - free(name); - config_free(&config); - fclose(f); - } - - if(errno) { - logger(mesh, MESHLINK_DEBUG, "Error while reading directory %s: %s\n", path, strerror(errno)); - closedir(dir); - meshlink_errno = MESHLINK_ESTORAGE; - return 0; - } - - closedir(dir); - - return count; -} diff --git a/src/meshlink++.h b/src/meshlink++.h index 25fd34f..dc5412a 100644 --- a/src/meshlink++.h +++ b/src/meshlink++.h @@ -560,28 +560,6 @@ public: return meshlink_clear_canonical_address(handle, node); } - /// Add an invitation address for the local node. - /** This function adds an address for the local node, which will be used only for invitation URLs. - * This address is not stored permanently. - * Multiple addresses can be added using multiple calls to this function. - * - * @param address A nul-terminated C string containing the address, which can be either in numeric format or a hostname. - * @param port A nul-terminated C string containing the port, which can be either in numeric or symbolic format. - * If it is NULL, the listening port's number will be used. - * - * @return This function returns true if the address was added, false otherwise. - */ - bool add_invitation_address(const char *address, const char *port) { - return meshlink_add_invitation_address(handle, address, port); - } - - /// Clears all invitation address for the local node. - /** This function removes all addresses added with meshlink_add_invitation_address(). - */ - void clear_invitation_addresses() { - return meshlink_clear_invitation_addresses(handle); - } - /// Add an Address for the local node. /** This function adds an Address for the local node, which will be used for invitation URLs. * @deprecated This function is deprecated, use set_canonical_address() and/or add_invitation_address(). @@ -683,16 +661,6 @@ public: return meshlink_set_port(handle, port); } - /// Set the timeout for invitations. - /** This function sets the timeout for invitations. - * The timeout is retroactively applied to all outstanding invitations. - * - * @param timeout The timeout for invitations in seconds. - */ - void set_invitation_timeout(int timeout) { - meshlink_set_invitation_timeout(handle, timeout); - } - /// Set the scheduling granularity of the application /** This should be set to the effective scheduling granularity for the application. * This depends on the scheduling granularity of the operating system, the application's @@ -718,23 +686,6 @@ public: 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. - * This URL should be passed by the application to the invitee in a way that no eavesdroppers can see the URL. - * The URL can only be used once, after the user has joined the mesh the URL is no longer valid. - * - * @param submesh A handle to the submesh to put the invitee in. - * @param name The name that the invitee will use in the mesh. - * @param flags A bitwise-or'd combination of flags that controls how the URL is generated. - * - * @return This function returns a string that contains the invitation URL. - * The application should call free() after it has finished using the URL. - */ - char *invite(submesh *submesh, const char *name, uint32_t flags = 0) { - return meshlink_invite_ex(handle, submesh, name, flags); - } - /// Use an invitation to join a mesh. /** This function allows the local node to join an existing mesh using an invitation URL generated by another node. * An invitation can only be used if the local node has never connected to other nodes before. diff --git a/src/meshlink.c b/src/meshlink.c index 4cc285d..3941ff0 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -60,20 +60,6 @@ static int rstrip(char *value) { return len; } -static void get_canonical_address(node_t *n, char **hostname, char **port) { - if(!n->canonical_address) { - return; - } - - *hostname = xstrdup(n->canonical_address); - char *space = strchr(*hostname, ' '); - - if(space) { - *space++ = 0; - *port = xstrdup(space); - } -} - static bool is_valid_hostname(const char *hostname) { if(!*hostname) { return false; @@ -445,158 +431,6 @@ char *meshlink_get_local_address_for_family(meshlink_handle_t *mesh, int family) return xstrdup(localaddr); } -static void remove_duplicate_hostnames(char *host[], char *port[], int n) { - for(int i = 0; i < n; i++) { - if(!host[i]) { - continue; - } - - // Ignore duplicate hostnames - bool found = false; - - for(int j = 0; j < i; j++) { - if(!host[j]) { - continue; - } - - if(strcmp(host[i], host[j])) { - continue; - } - - if(strcmp(port[i], port[j])) { - continue; - } - - found = true; - break; - } - - if(found || !is_valid_hostname(host[i])) { - free(host[i]); - free(port[i]); - host[i] = NULL; - port[i] = NULL; - continue; - } - } -} - -// This gets the hostname part for use in invitation URLs -static char *get_my_hostname(meshlink_handle_t *mesh, uint32_t flags) { - int count = 4 + (mesh->invitation_addresses ? mesh->invitation_addresses->count : 0); - int n = 0; - char *hostname[count]; - char *port[count]; - char *hostport = NULL; - - memset(hostname, 0, sizeof(hostname)); - memset(port, 0, sizeof(port)); - - if(!(flags & (MESHLINK_INVITE_LOCAL | MESHLINK_INVITE_PUBLIC))) { - flags |= MESHLINK_INVITE_LOCAL | MESHLINK_INVITE_PUBLIC; - } - - if(!(flags & (MESHLINK_INVITE_IPV4 | MESHLINK_INVITE_IPV6))) { - flags |= MESHLINK_INVITE_IPV4 | MESHLINK_INVITE_IPV6; - } - - // Add all explicitly set invitation addresses - if(mesh->invitation_addresses) { - for list_each(char, combo, mesh->invitation_addresses) { - hostname[n] = xstrdup(combo); - char *slash = strrchr(hostname[n], '/'); - - if(slash) { - *slash = 0; - port[n] = xstrdup(slash + 1); - } - - n++; - } - } - - // Add local addresses if requested - if(flags & MESHLINK_INVITE_LOCAL) { - if(flags & MESHLINK_INVITE_IPV4) { - hostname[n++] = meshlink_get_local_address_for_family(mesh, AF_INET); - } - - if(flags & MESHLINK_INVITE_IPV6) { - hostname[n++] = meshlink_get_local_address_for_family(mesh, AF_INET6); - } - } - - // Add public/canonical addresses if requested - if(flags & MESHLINK_INVITE_PUBLIC) { - // Try the CanonicalAddress first - get_canonical_address(mesh->self, &hostname[n], &port[n]); - - if(!hostname[n] && count == 4) { - if(flags & MESHLINK_INVITE_IPV4) { - hostname[n++] = meshlink_get_external_address_for_family(mesh, AF_INET); - } - - if(flags & MESHLINK_INVITE_IPV6) { - hostname[n++] = meshlink_get_external_address_for_family(mesh, AF_INET6); - } - } else { - n++; - } - } - - for(int i = 0; i < n; i++) { - // Ensure we always have a port number - if(hostname[i] && !port[i]) { - port[i] = xstrdup(mesh->myport); - } - } - - remove_duplicate_hostnames(hostname, port, n); - - // Resolve the hostnames - for(int i = 0; i < n; i++) { - if(!hostname[i]) { - continue; - } - - // Convert what we have to a sockaddr - struct addrinfo *ai_in = adns_blocking_request(mesh, xstrdup(hostname[i]), xstrdup(port[i]), SOCK_STREAM, 5); - - if(!ai_in) { - continue; - } - - // Remember the address(es) - for(struct addrinfo *aip = ai_in; aip; aip = aip->ai_next) { - node_add_recent_address(mesh, mesh->self, (sockaddr_t *)aip->ai_addr); - } - - freeaddrinfo(ai_in); - continue; - } - - // Remove duplicates again, since IPv4 and IPv6 addresses might map to the same hostname - remove_duplicate_hostnames(hostname, port, n); - - // Concatenate all unique address to the hostport string - for(int i = 0; i < n; i++) { - if(!hostname[i]) { - continue; - } - - // Append the address to the hostport string - char *newhostport; - xasprintf(&newhostport, (strchr(hostname[i], ':') ? "%s%s[%s]:%s" : "%s%s%s:%s"), hostport ? hostport : "", hostport ? "," : "", hostname[i], port[i]); - free(hostport); - hostport = newhostport; - - free(hostname[i]); - free(port[i]); - } - - return hostport; -} - static bool try_bind(meshlink_handle_t *mesh, int port) { struct addrinfo *ai = NULL; struct addrinfo hint = { @@ -678,7 +512,7 @@ static bool write_main_config_files(meshlink_handle_t *mesh) { packmsg_add_uint32(&out, MESHLINK_CONFIG_VERSION); packmsg_add_str(&out, mesh->name); packmsg_add_bin(&out, ecdsa_get_private_key(mesh->private_key), 96); - packmsg_add_bin(&out, ecdsa_get_private_key(mesh->invitation_key), 96); + packmsg_add_nil(&out); // Invitation keys are not supported packmsg_add_uint16(&out, atoi(mesh->myport)); if(!packmsg_output_ok(&out)) { @@ -1005,12 +839,11 @@ const char *meshlink_strerror(meshlink_errno_t err) { } static bool ecdsa_keygen(meshlink_handle_t *mesh) { - logger(mesh, MESHLINK_DEBUG, "Generating ECDSA keypairs:\n"); + logger(mesh, MESHLINK_DEBUG, "Generating ECDSA keypair:\n"); mesh->private_key = ecdsa_generate(); - mesh->invitation_key = ecdsa_generate(); - if(!mesh->private_key || !mesh->invitation_key) { + if(!mesh->private_key) { logger(mesh, MESHLINK_ERROR, "Error during key generation!\n"); meshlink_errno = MESHLINK_EINTERNAL; return false; @@ -1133,15 +966,14 @@ static bool meshlink_read_config(meshlink_handle_t *mesh) { packmsg_input_t in = {config.buf, config.len}; const void *private_key; - const void *invitation_key; uint32_t version = packmsg_get_uint32(&in); char *name = packmsg_get_str_dup(&in); uint32_t private_key_len = packmsg_get_bin_raw(&in, &private_key); - uint32_t invitation_key_len = packmsg_get_bin_raw(&in, &invitation_key); + packmsg_skip_element(&in); // Invitation key is not supported uint16_t myport = packmsg_get_uint16(&in); - if(!packmsg_done(&in) || version != MESHLINK_CONFIG_VERSION || private_key_len != 96 || invitation_key_len != 96) { + if(!packmsg_done(&in) || version != MESHLINK_CONFIG_VERSION || private_key_len != 96) { logger(NULL, MESHLINK_ERROR, "Error parsing main configuration file!"); free(name); config_free(&config); @@ -1160,7 +992,6 @@ static bool meshlink_read_config(meshlink_handle_t *mesh) { mesh->name = name; xasprintf(&mesh->myport, "%u", myport); mesh->private_key = ecdsa_set_private_key(private_key); - mesh->invitation_key = ecdsa_set_private_key(invitation_key); config_free(&config); /* Create a node for ourself and read our host configuration file */ @@ -1539,7 +1370,6 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) { mesh->appname = xstrdup(params->appname); mesh->devclass = params->devclass; mesh->discovery.enabled = true; - mesh->invitation_timeout = 604800; // 1 week mesh->netns = params->netns; mesh->submeshes = NULL; mesh->log_cb = global_log_cb; @@ -1922,8 +1752,6 @@ void meshlink_close(meshlink_handle_t *mesh) { #endif - ecdsa_free(mesh->invitation_key); - if(mesh->netns != -1) { close(mesh->netns); } @@ -1942,10 +1770,6 @@ void meshlink_close(meshlink_handle_t *mesh) { free(mesh->packet); ecdsa_free(mesh->private_key); - if(mesh->invitation_addresses) { - list_delete_list(mesh->invitation_addresses); - } - main_config_unlock(mesh); pthread_mutex_unlock(&mesh->mutex); @@ -2687,22 +2511,6 @@ bool meshlink_verify(meshlink_handle_t *mesh, meshlink_node_t *source, const voi return rval; } -static bool refresh_invitation_key(meshlink_handle_t *mesh) { - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - size_t count = invitation_purge_old(mesh, time(NULL) - mesh->invitation_timeout); - - if(!count) { - // TODO: Update invitation key if necessary? - } - - pthread_mutex_unlock(&mesh->mutex); - - return mesh->invitation_key; -} - bool meshlink_set_canonical_address(meshlink_handle_t *mesh, meshlink_node_t *node, const char *address, const char *port) { logger(mesh, MESHLINK_DEBUG, "meshlink_set_canonical_address(%s, %s, %s)", node ? node->name : "(null)", address ? address : "(null)", port ? port : "(null)"); @@ -2778,68 +2586,6 @@ bool meshlink_clear_canonical_address(meshlink_handle_t *mesh, meshlink_node_t * return config_sync(mesh, "current"); } -bool meshlink_add_invitation_address(struct meshlink_handle *mesh, const char *address, const char *port) { - logger(mesh, MESHLINK_DEBUG, "meshlink_add_invitation_address(%s, %s)", address ? address : "(null)", port ? port : "(null)"); - - if(!mesh || !address) { - meshlink_errno = MESHLINK_EINVAL; - return false; - } - - if(!is_valid_hostname(address)) { - logger(mesh, MESHLINK_ERROR, "Invalid character in address: %s\n", address); - meshlink_errno = MESHLINK_EINVAL; - return false; - } - - if(port && !is_valid_port(port)) { - logger(mesh, MESHLINK_ERROR, "Invalid character in port: %s\n", address); - meshlink_errno = MESHLINK_EINVAL; - return false; - } - - char *combo; - - if(port) { - xasprintf(&combo, "%s/%s", address, port); - } else { - combo = xstrdup(address); - } - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - if(!mesh->invitation_addresses) { - mesh->invitation_addresses = list_alloc((list_action_t)free); - } - - list_insert_tail(mesh->invitation_addresses, combo); - pthread_mutex_unlock(&mesh->mutex); - - return true; -} - -void meshlink_clear_invitation_addresses(struct meshlink_handle *mesh) { - logger(mesh, MESHLINK_DEBUG, "meshlink_clear_invitation_addresses()"); - - if(!mesh) { - meshlink_errno = MESHLINK_EINVAL; - return; - } - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - if(mesh->invitation_addresses) { - list_delete_list(mesh->invitation_addresses); - mesh->invitation_addresses = NULL; - } - - pthread_mutex_unlock(&mesh->mutex); -} - bool meshlink_add_address(meshlink_handle_t *mesh, const char *address) { logger(mesh, MESHLINK_DEBUG, "meshlink_add_address(%s)", address ? address : "(null)"); @@ -2958,163 +2704,6 @@ done: return rval && meshlink_get_port(mesh) == port; } -void meshlink_set_invitation_timeout(meshlink_handle_t *mesh, int timeout) { - logger(mesh, MESHLINK_DEBUG, "meshlink_invitation_timeout(%d)", timeout); - - mesh->invitation_timeout = timeout; -} - -char *meshlink_invite_ex(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, const char *name, uint32_t flags) { - logger(mesh, MESHLINK_DEBUG, "meshlink_invite_ex(%s, %s, %u)", submesh ? submesh->name : "(null)", name ? name : "(null)", flags); - - meshlink_submesh_t *s = NULL; - - if(!mesh) { - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - if(submesh) { - s = (meshlink_submesh_t *)lookup_submesh(mesh, submesh->name); - - if(s != submesh) { - logger(mesh, MESHLINK_ERROR, "Invalid submesh handle.\n"); - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - } else { - s = (meshlink_submesh_t *)mesh->self->submesh; - } - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - // Check validity of the new node's name - if(!check_id(name)) { - logger(mesh, MESHLINK_ERROR, "Invalid name for node.\n"); - meshlink_errno = MESHLINK_EINVAL; - pthread_mutex_unlock(&mesh->mutex); - return NULL; - } - - // Ensure no host configuration file with that name exists - if(config_exists(mesh, "current", name)) { - logger(mesh, MESHLINK_ERROR, "A host config file for %s already exists!\n", name); - meshlink_errno = MESHLINK_EEXIST; - pthread_mutex_unlock(&mesh->mutex); - return NULL; - } - - // Ensure no other nodes know about this name - if(lookup_node(mesh, name)) { - logger(mesh, MESHLINK_ERROR, "A node with name %s is already known!\n", name); - meshlink_errno = MESHLINK_EEXIST; - pthread_mutex_unlock(&mesh->mutex); - return NULL; - } - - // Get the local address - char *address = get_my_hostname(mesh, flags); - - if(!address) { - logger(mesh, MESHLINK_ERROR, "No Address known for ourselves!\n"); - meshlink_errno = MESHLINK_ERESOLV; - pthread_mutex_unlock(&mesh->mutex); - return NULL; - } - - if(!refresh_invitation_key(mesh)) { - meshlink_errno = MESHLINK_EINTERNAL; - pthread_mutex_unlock(&mesh->mutex); - return NULL; - } - - // If we changed our own host config file, write it out now - if(mesh->self->status.dirty) { - 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; - } - } - - char hash[64]; - - // Create a hash of the key. - char *fingerprint = ecdsa_get_base64_public_key(mesh->invitation_key); - sha512(fingerprint, strlen(fingerprint), hash); - b64encode_urlsafe(hash, hash, 18); - - // Create a random cookie for this invitation. - char cookie[25]; - randomize(cookie, 18); - - // Create a filename that doesn't reveal the cookie itself - char buf[18 + strlen(fingerprint)]; - char cookiehash[64]; - memcpy(buf, cookie, 18); - memcpy(buf + 18, fingerprint, sizeof(buf) - 18); - sha512(buf, sizeof(buf), cookiehash); - b64encode_urlsafe(cookiehash, cookiehash, 18); - - b64encode_urlsafe(cookie, cookie, 18); - - free(fingerprint); - - /* Construct the invitation file */ - uint8_t outbuf[4096]; - packmsg_output_t inv = {outbuf, sizeof(outbuf)}; - - packmsg_add_uint32(&inv, MESHLINK_INVITATION_VERSION); - packmsg_add_str(&inv, name); - packmsg_add_str(&inv, s ? s->name : CORE_MESH); - packmsg_add_int32(&inv, DEV_CLASS_UNKNOWN); /* TODO: allow this to be set by inviter? */ - - /* TODO: Add several host config files to bootstrap connections. - * Note: make sure we only add config files of nodes that are in the core mesh or the same submesh, - * and are not blacklisted. - */ - config_t configs[5]; - memset(configs, 0, sizeof(configs)); - int count = 0; - - if(config_read(mesh, "current", mesh->self->name, &configs[count], mesh->config_key)) { - count++; - } - - /* Append host config files to the invitation file */ - packmsg_add_array(&inv, count); - - for(int i = 0; i < count; i++) { - packmsg_add_bin(&inv, configs[i].buf, configs[i].len); - config_free(&configs[i]); - } - - config_t config = {outbuf, packmsg_output_size(&inv, outbuf)}; - - if(!invitation_write(mesh, "current", cookiehash, &config, mesh->config_key)) { - logger(mesh, MESHLINK_DEBUG, "Could not create invitation file %s: %s\n", cookiehash, strerror(errno)); - meshlink_errno = MESHLINK_ESTORAGE; - pthread_mutex_unlock(&mesh->mutex); - return NULL; - } - - // Create an URL from the local address, key hash and cookie - char *url; - xasprintf(&url, "%s/%s%s", address, hash, cookie); - free(address); - - pthread_mutex_unlock(&mesh->mutex); - return url; -} - -char *meshlink_invite(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, const char *name) { - logger(mesh, MESHLINK_DEBUG, "meshlink_invite_ex(%s, %s)", submesh ? submesh->name : "(null)", name ? name : "(null)"); - - return meshlink_invite_ex(mesh, submesh, name, 0); -} - bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { logger(mesh, MESHLINK_DEBUG, "meshlink_join(%s)", invitation ? invitation : "(null)"); @@ -3613,9 +3202,6 @@ static bool blacklist(meshlink_handle_t *mesh, node_t *n) { mesh->node_status_cb(mesh, (meshlink_node_t *)n, false); } - /* Remove any outstanding invitations */ - invitation_purge_node(mesh, n->name); - return node_write_config(mesh, n, true) && config_sync(mesh, "current"); } @@ -3805,9 +3391,6 @@ bool meshlink_forget_node(meshlink_handle_t *mesh, meshlink_node_t *node) { return false; } - /* Delete any pending invitations */ - invitation_purge_node(mesh, n->name); - /* Delete the node struct and any remaining edges referencing this node */ node_del(mesh, n); diff --git a/src/meshlink.h b/src/meshlink.h index a6c5b4b..75ce60e 100644 --- a/src/meshlink.h +++ b/src/meshlink.h @@ -922,29 +922,6 @@ bool meshlink_set_canonical_address(struct meshlink_handle *mesh, struct meshlin */ bool meshlink_clear_canonical_address(struct meshlink_handle *mesh, struct meshlink_node *node) __attribute__((__warn_unused_result__)); -/// Add an invitation address for the local node. -/** This function adds an address for the local node, which will be used only for invitation URLs. - * This address is not stored permanently. - * Multiple addresses can be added using multiple calls to this function. - * - * \memberof meshlink_handle - * @param mesh A handle which represents an instance of MeshLink. - * @param address A nul-terminated C string containing the address, which can be either in numeric format or a hostname. - * @param port A nul-terminated C string containing the port, which can be either in numeric or symbolic format. - * If it is NULL, the current listening port's number will be used. - * - * @return This function returns true if the address was added, false otherwise. - */ -bool meshlink_add_invitation_address(struct meshlink_handle *mesh, const char *address, const char *port) __attribute__((__warn_unused_result__)); - -/// Clears all invitation address for the local node. -/** This function removes all addresses added with meshlink_add_invitation_address(). - * - * \memberof meshlink_handle - * @param mesh A handle which represents an instance of MeshLink. - */ -void meshlink_clear_invitation_addresses(struct meshlink_handle *mesh); - /// Add an Address for the local node. /** This function adds an Address for the local node, which will be used for invitation URLs. * @deprecated This function is deprecated, use meshlink_set_canonical_address() and/or meshlink_add_invitation_address(). @@ -1078,55 +1055,6 @@ int meshlink_get_port(struct meshlink_handle *mesh) __attribute__((__warn_unused bool meshlink_set_port(struct meshlink_handle *mesh, int port) __attribute__((__warn_unused_result__)); -/// Set the timeout for invitations. -/** This function sets the timeout for invitations. - * Note that timeouts are only checked at the time a node tries to join using an invitation. - * The default timeout for invitations is 1 week. - * - * \memberof meshlink_handle - * @param mesh A handle which represents an instance of MeshLink. - * @param timeout The timeout for invitations in seconds. - */ -void meshlink_set_invitation_timeout(struct meshlink_handle *mesh, int timeout); - -/// 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. - * This URL should be passed by the application to the invitee in a way that no eavesdroppers can see the URL. - * The URL can only be used once, after the user has joined the mesh the URL is no longer valid. - * - * \memberof meshlink_handle - * @param mesh A handle which represents an instance of MeshLink. - * @param submesh A handle which represents an instance of SubMesh. - * @param name A nul-terminated C string containing the name that the invitee will be allowed to use in the mesh. - * After this function returns, the application is free to overwrite or free @a name. - * @param flags A bitwise-or'd combination of flags that controls how the URL is generated. - * - * @return This function returns a nul-terminated C string that contains the invitation URL, or NULL in case of an error. - * The application should call free() after it has finished using the URL. - */ -char *meshlink_invite_ex(struct meshlink_handle *mesh, struct meshlink_submesh *submesh, const char *name, uint32_t flags) __attribute__((__warn_unused_result__)); - -/// 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. - * This URL should be passed by the application to the invitee in a way that no eavesdroppers can see the URL. - * The URL can only be used once, after the user has joined the mesh the URL is no longer valid. - * - * Calling this function is equal to callen meshlink_invite_ex() with flags set to 0. - * - * \memberof meshlink_handle - * @param mesh A handle which represents an instance of MeshLink. - * @param submesh A handle which represents an instance of SubMesh. - * @param name A nul-terminated C string containing the name that the invitee will be allowed to use in the mesh. - * After this function returns, the application is free to overwrite or free @a name. - * - * @return This function returns a nul-terminated C string that contains the invitation URL, or NULL in case of an error. - * The application should call free() after it has finished using the URL. - */ -char *meshlink_invite(struct meshlink_handle *mesh, struct meshlink_submesh *submesh, const char *name) __attribute__((__warn_unused_result__)); - -/// Use an invitation to join a mesh. /** This function allows the local node to join an existing mesh using an invitation URL generated by another node. * An invitation can only be used if the local node has never connected to other nodes before. * After a successfully accepted invitation, the name of the local node may have changed. diff --git a/src/meshlink.sym b/src/meshlink.sym index 7c4de62..245e254 100644 --- a/src/meshlink.sym +++ b/src/meshlink.sym @@ -10,7 +10,6 @@ devtool_set_inviter_commits_first devtool_trybind_probe meshlink_add_address meshlink_add_external_address -meshlink_add_invitation_address meshlink_blacklist meshlink_blacklist_by_name meshlink_channel_abort @@ -28,7 +27,6 @@ meshlink_channel_open_ex meshlink_channel_send meshlink_channel_shutdown meshlink_clear_canonical_address -meshlink_clear_invitation_addresses meshlink_close meshlink_destroy meshlink_destroy_ex @@ -58,8 +56,6 @@ meshlink_get_submesh meshlink_hint_address meshlink_hint_network_change meshlink_import -meshlink_invite -meshlink_invite_ex meshlink_join meshlink_main_loop meshlink_open @@ -92,7 +88,6 @@ meshlink_set_dev_class_maxtimeout meshlink_set_dev_class_timeouts meshlink_set_error_cb meshlink_set_external_address_discovery_url -meshlink_set_invitation_timeout meshlink_set_inviter_commits_first meshlink_set_log_cb meshlink_set_node_channel_timeout diff --git a/src/meshlink_internal.h b/src/meshlink_internal.h index 2618601..2934925 100644 --- a/src/meshlink_internal.h +++ b/src/meshlink_internal.h @@ -146,11 +146,9 @@ struct meshlink_handle { char *myport; struct ecdsa *private_key; - struct ecdsa *invitation_key; dev_class_t devclass; - int invitation_timeout; int udp_choice; dev_class_traits_t dev_class_traits[DEV_CLASS_COUNT]; @@ -165,7 +163,6 @@ struct meshlink_handle { FILE *lockfile; void *config_key; char *external_address_url; - struct list_t *invitation_addresses; meshlink_storage_policy_t storage_policy; // Thread management diff --git a/src/protocol_auth.c b/src/protocol_auth.c index a0d350d..943040e 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -47,141 +47,6 @@ 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 commit_invitation(meshlink_handle_t *mesh, connection_t *c, const void *data) { - // Check if the node is known - node_t *n = lookup_node(mesh, c->name); - - if(n) { - if(n->status.blacklisted) { - logger(mesh, MESHLINK_ERROR, "Invitee %s is blacklisted", c->name); - } else { - logger(mesh, MESHLINK_ERROR, "Invitee %s already known", c->name); - } - - return false; - } - - // Create a new node - n = new_node(); - n->name = xstrdup(c->name); - n->devclass = DEV_CLASS_UNKNOWN; - n->ecdsa = ecdsa_set_public_key(data); - n->submesh = c->submesh; - - // Remember its current address - node_add_recent_address(mesh, n, &c->address); - - 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; - - } - - node_add(mesh, n); - - logger(mesh, MESHLINK_INFO, "Key successfully received from %s", c->name); - - //TODO: callback to application to inform of an accepted invitation - - sptps_send_record(&c->sptps, 1, "", 0); - - return true; -} - -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]; - char hashbuf[18 + strlen(fingerprint)]; - char cookie[25]; - memcpy(hashbuf, data, 18); - memcpy(hashbuf + 18, fingerprint, sizeof(hashbuf) - 18); - sha512(hashbuf, sizeof(hashbuf), hash); - b64encode_urlsafe(hash, cookie, 18); - free(fingerprint); - - config_t config; - - if(!invitation_read(mesh, "current", cookie, &config, mesh->config_key)) { - logger(mesh, MESHLINK_ERROR, "Error while trying to read invitation file\n"); - return false; - } - - // Read the new node's Name from the file - packmsg_input_t in = {config.buf, config.len}; - packmsg_get_uint32(&in); // skip version - free(c->name); - c->name = packmsg_get_str_dup(&in); - - // Check if the file contains Sub-Mesh information - char *submesh_name = packmsg_get_str_dup(&in); - - if(!strcmp(submesh_name, CORE_MESH)) { - free(submesh_name); - c->submesh = NULL; - } else { - if(!check_id(submesh_name)) { - logger(mesh, MESHLINK_ERROR, "Invalid invitation file %s\n", cookie); - free(submesh_name); - return false; - } - - c->submesh = lookup_or_create_submesh(mesh, submesh_name); - free(submesh_name); - - if(!c->submesh) { - logger(mesh, MESHLINK_ERROR, "Unknown submesh in invitation file %s\n", cookie); - return false; - } - } - - if(mesh->inviter_commits_first && !commit_invitation(mesh, c, (const char *)data + 18)) { - return false; - } - - if(mesh->inviter_commits_first) { - devtool_set_inviter_commits_first(true); - } - - // Send the node the contents of the invitation file - sptps_send_record(&c->sptps, 0, config.buf, config.len); - - config_free(&config); - - c->status.invitation_used = true; - - logger(mesh, MESHLINK_INFO, "Invitation %s successfully sent to %s", cookie, c->name); - 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; - - // Extend the time for the invitation exchange upon receiving a valid message - c->last_ping_time = mesh->loop.now.tv_sec; - - 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); @@ -193,41 +58,6 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { return false; } - /* Check if this is an invitation */ - - if(name[0] == '?') { - if(!mesh->invitation_key) { - logger(mesh, MESHLINK_ERROR, "Got invitation from %s but we don't have an invitation key", c->name); - return false; - } - - c->ecdsa = ecdsa_set_base64_public_key(name + 1); - - if(!c->ecdsa) { - logger(mesh, MESHLINK_ERROR, "Got bad invitation from %s", c->name); - return false; - } - - c->status.invitation = true; - char *mykey = ecdsa_get_base64_public_key(mesh->invitation_key); - - if(!mykey) { - return false; - } - - if(!send_request(mesh, c, NULL, "%d %s", ACK, mykey)) { - return false; - } - - free(mykey); - - c->protocol_minor = 2; - c->allow_request = 1; - c->last_ping_time = mesh->loop.now.tv_sec; - - return sptps_start(&c->sptps, c, false, false, mesh->invitation_key, c->ecdsa, meshlink_invitation_label, sizeof(meshlink_invitation_label), send_meta_sptps, receive_invitation_sptps); - } - /* Check if identity is a valid name */ if(!check_id(name)) { diff --git a/test/Makefile.am b/test/Makefile.am index 65834bb..c0b4838 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -19,7 +19,6 @@ TESTS = \ ephemeral \ get-all-nodes \ import-export \ - invite-join \ meta-connections \ sign-verify \ storage-policy \ @@ -31,9 +30,9 @@ TESTS = \ TESTS += \ api_set_node_status_cb -if BLACKBOX_TESTS -SUBDIRS = blackbox -endif +#if BLACKBOX_TESTS +#SUBDIRS = blackbox +#endif dist_check_SCRIPTS = $(TESTS) @@ -63,7 +62,6 @@ check_PROGRAMS = \ ephemeral \ get-all-nodes \ import-export \ - invite-join \ meta-connections \ sign-verify \ storage-policy \ @@ -141,9 +139,6 @@ get_all_nodes_LDADD = $(top_builddir)/src/libmeshlink.la import_export_SOURCES = import-export.c utils.c utils.h import_export_LDADD = $(top_builddir)/src/libmeshlink.la -invite_join_SOURCES = invite-join.c utils.c utils.h -invite_join_LDADD = $(top_builddir)/src/libmeshlink.la - meta_connections_SOURCES = meta-connections.c netns_utils.c netns_utils.h utils.c utils.h meta_connections_LDADD = $(top_builddir)/src/libmeshlink.la diff --git a/test/blacklist.c b/test/blacklist.c index cd54585..d296745 100644 --- a/test/blacklist.c +++ b/test/blacklist.c @@ -113,12 +113,6 @@ int main(void) { assert(meshlink_get_node_blacklisted(mesh[1], meshlink_get_node(mesh[1], name[2]))); assert(meshlink_get_node_blacklisted(mesh[2], meshlink_get_node(mesh[2], name[1]))); - // Generate an invitation for a node that is about to be blacklisted - - char *invitation = meshlink_invite(mesh[0], NULL, "xyzzy"); - assert(invitation); - free(invitation); - // Whitelisting and blacklisting by name should work. assert(meshlink_whitelist_by_name(mesh[0], "quux")); @@ -142,20 +136,6 @@ int main(void) { free(nodes); - // Check that blacklisted nodes are not allowed to be invited, and no invitations are left on disk. - - assert(!meshlink_invite(mesh[0], NULL, "xyzzy")); - - DIR *dir = opendir("blacklist_conf.0/current/invitations"); - assert(dir); - struct dirent *ent; - - while((ent = readdir(dir))) { - assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")); - } - - closedir(dir); - // Since these nodes now exist we should be able to forget them. assert(meshlink_forget_node(mesh[0], meshlink_get_node(mesh[0], "quux"))); diff --git a/test/netns_utils.c b/test/netns_utils.c index d957d5b..4641c4e 100644 --- a/test/netns_utils.c +++ b/test/netns_utils.c @@ -106,17 +106,17 @@ void change_peer_ip(peer_config_t *peer) { } /// Let the first peer in a list invite all the subsequent peers -static void invite_peers(peer_config_t *peers, int npeers) { - assert(meshlink_start(peers[0].mesh)); - +static void link_peers(peer_config_t *peers, int npeers) { for(int i = 1; i < npeers; i++) { - char *invitation = meshlink_invite_ex(peers[0].mesh, NULL, peers[i].name, MESHLINK_INVITE_LOCAL | MESHLINK_INVITE_NUMERIC); - assert(invitation); - assert(meshlink_join(peers[i].mesh, invitation)); - free(invitation); + char *export_relay = meshlink_export(peers[0].mesh); + char *export_peer = meshlink_export(peers[i].mesh); + assert(export_relay); + assert(export_peer); + assert(meshlink_import(peers[0].mesh, export_peer)); + assert(meshlink_import(peers[i].mesh, export_relay)); + free(export_relay); + free(export_peer); } - - meshlink_stop(peers[0].mesh); } /// Close meshlink instances and clean up @@ -138,7 +138,7 @@ peer_config_t *setup_relay_peer_nut(const char *prefix) { create_peers(peers, 3, prefix); setup_lan_topology(peers, 3); - invite_peers(peers, 3); + link_peers(peers, 3); return peers; } diff --git a/test/storage-policy.c b/test/storage-policy.c index a9aa5f4..4152946 100644 --- a/test/storage-policy.c +++ b/test/storage-policy.c @@ -148,44 +148,6 @@ int main(void) { assert(last_reachable); assert(last_unreachable); - // Start again from scratch, now use invite/join instead of import/export - - close_meshlink_pair(mesh1, mesh2); - - assert(meshlink_destroy("storage-policy_conf.1")); - assert(meshlink_destroy("storage-policy_conf.2")); - - mesh1 = meshlink_open("storage-policy_conf.1", "foo", "storage-policy", DEV_CLASS_BACKBONE); - mesh2 = meshlink_open("storage-policy_conf.2", "bar", "storage-policy", DEV_CLASS_BACKBONE); - assert(mesh1); - assert(mesh2); - meshlink_enable_discovery(mesh1, false); - meshlink_enable_discovery(mesh2, false); - meshlink_set_storage_policy(mesh1, MESHLINK_STORAGE_DISABLED); - meshlink_set_storage_policy(mesh2, MESHLINK_STORAGE_DISABLED); - - // Check that joining is not possible with storage disabled - - assert(meshlink_set_canonical_address(mesh1, meshlink_get_self(mesh1), "localhost", NULL)); - char *invitation = meshlink_invite(mesh1, NULL, "bar"); - assert(invitation); - assert(meshlink_start(mesh1)); - assert(!meshlink_join(mesh2, invitation)); - assert(meshlink_errno == MESHLINK_EINVAL); - meshlink_stop(mesh1); - - // Try again with KEYS_ONLY - - meshlink_set_storage_policy(mesh1, MESHLINK_STORAGE_KEYS_ONLY); - meshlink_set_storage_policy(mesh2, MESHLINK_STORAGE_KEYS_ONLY); - - assert(meshlink_start(mesh1)); - assert(meshlink_join(mesh2, invitation)); - assert(meshlink_errno == MESHLINK_EINVAL); - meshlink_stop(mesh1); - - start_meshlink_pair(mesh1, mesh2); - // Close the instances and reopen them. close_meshlink_pair(mesh1, mesh2); @@ -207,5 +169,4 @@ int main(void) { // Done. close_meshlink_pair(mesh1, mesh2); - free(invitation); }