X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fmeshlink.c;h=30b386846a7322e261a1b0f4888331773352fe0c;hb=529b8fab8c21e7ae5af91d742ff202eab38e51f3;hp=91be6412f7eb9ad5e5a11c9bc1ba8fd3fd478fa8;hpb=2d9dbeb8ecb2d6220e123564bbfe18ba7fe0a34b;p=meshlink diff --git a/src/meshlink.c b/src/meshlink.c index 91be6412..30b38684 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -393,58 +393,66 @@ static char *get_my_hostname(meshlink_handle_t *mesh, uint32_t flags) { remove_duplicate_hostnames(hostname, port, 4); - if(!(flags & MESHLINK_INVITE_NUMERIC)) { - for(int i = 0; i < 4; i++) { - if(!hostname[i]) { - continue; - } + // Resolve the hostnames + for(int i = 0; i < 4; i++) { + if(!hostname[i]) { + continue; + } - // Convert what we have to a sockaddr - struct addrinfo *ai_in, *ai_out; - struct addrinfo hint = { - .ai_family = AF_UNSPEC, - .ai_flags = AI_NUMERICSERV, - .ai_socktype = SOCK_STREAM, - }; - int err = getaddrinfo(hostname[i], port[i], &hint, &ai_in); + // Convert what we have to a sockaddr + struct addrinfo *ai_in, *ai_out; + struct addrinfo hint = { + .ai_family = AF_UNSPEC, + .ai_flags = AI_NUMERICSERV, + .ai_socktype = SOCK_STREAM, + }; + int err = getaddrinfo(hostname[i], port[i], &hint, &ai_in); - if(err || !ai_in) { - continue; - } + if(err || !ai_in) { + continue; + } - // Convert it to a hostname - char resolved_host[NI_MAXHOST]; - char resolved_port[NI_MAXSERV]; - err = getnameinfo(ai_in->ai_addr, ai_in->ai_addrlen, resolved_host, sizeof resolved_host, resolved_port, sizeof resolved_port, NI_NUMERICSERV); + // Remember the address + node_add_recent_address(mesh, mesh->self, (sockaddr_t *)ai_in->ai_addr); - if(err || !is_valid_hostname(resolved_host)) { - freeaddrinfo(ai_in); - continue; - } + if(flags & MESHLINK_INVITE_NUMERIC) { + // We don't need to do any further conversion + freeaddrinfo(ai_in); + continue; + } - // Convert the hostname back to a sockaddr - hint.ai_family = ai_in->ai_family; - err = getaddrinfo(resolved_host, resolved_port, &hint, &ai_out); + // Convert it to a hostname + char resolved_host[NI_MAXHOST]; + char resolved_port[NI_MAXSERV]; + err = getnameinfo(ai_in->ai_addr, ai_in->ai_addrlen, resolved_host, sizeof resolved_host, resolved_port, sizeof resolved_port, NI_NUMERICSERV); - if(err || !ai_out) { - freeaddrinfo(ai_in); - continue; - } + if(err || !is_valid_hostname(resolved_host)) { + freeaddrinfo(ai_in); + continue; + } - // Check if it's still the same sockaddr - if(ai_in->ai_addrlen != ai_out->ai_addrlen || memcmp(ai_in->ai_addr, ai_out->ai_addr, ai_in->ai_addrlen)) { - freeaddrinfo(ai_in); - freeaddrinfo(ai_out); - continue; - } + // Convert the hostname back to a sockaddr + hint.ai_family = ai_in->ai_family; + err = getaddrinfo(resolved_host, resolved_port, &hint, &ai_out); - // Yes: replace the hostname with the resolved one - free(hostname[i]); - hostname[i] = xstrdup(resolved_host); + if(err || !ai_out) { + freeaddrinfo(ai_in); + continue; + } + // Check if it's still the same sockaddr + if(ai_in->ai_addrlen != ai_out->ai_addrlen || memcmp(ai_in->ai_addr, ai_out->ai_addr, ai_in->ai_addrlen)) { freeaddrinfo(ai_in); freeaddrinfo(ai_out); + continue; } + + // Yes: replace the hostname with the resolved one + free(hostname[i]); + hostname[i] = xstrdup(resolved_host); + + freeaddrinfo(ai_in); + freeaddrinfo(ai_out); } // Remove duplicates again, since IPv4 and IPv6 addresses might map to the same hostname @@ -456,13 +464,6 @@ static char *get_my_hostname(meshlink_handle_t *mesh, uint32_t flags) { continue; } - // Ensure we have the same addresses in our own host config file. - char *tmphostport; - xasprintf(&tmphostport, "%s %s", hostname[i], port[i]); - /// TODO: FIX - //config_add_string(&mesh->config, "Address", tmphostport); - free(tmphostport); - // 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]); @@ -611,7 +612,7 @@ static bool finalize_join(meshlink_handle_t *mesh, const void *buf, uint16_t len } // Write host config files - while(count--) { + for(uint32_t i = 0; i < count; i++) { const void *data; uint32_t len = packmsg_get_bin_raw(&in, &data); @@ -654,11 +655,24 @@ static bool finalize_join(meshlink_handle_t *mesh, const void *buf, uint16_t len return false; } - node_add(mesh, n); + if(i == 0) { + /* The first host config file is of the inviter itself; + * remember the address we are currently using for the invitation connection. + */ + sockaddr_t sa; + socklen_t salen = sizeof(sa); - if(!config_write(mesh, "current", n->name, &config, mesh->config_key)) { + if(getpeername(mesh->sock, &sa.sa, &salen) == 0) { + node_add_recent_address(mesh, n, &sa); + } + } + + if(!node_write_config(mesh, n)) { + free_node(n); return false; } + + node_add(mesh, n); } /* Ensure the configuration directory metadata is on disk */ @@ -2372,7 +2386,7 @@ char *meshlink_invite_ex(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, c // Check validity of the new node's name if(!check_id(name)) { - logger(mesh, MESHLINK_DEBUG, "Invalid name for node.\n"); + logger(mesh, MESHLINK_ERROR, "Invalid name for node.\n"); meshlink_errno = MESHLINK_EINVAL; pthread_mutex_unlock(&mesh->mutex); return NULL; @@ -2380,7 +2394,7 @@ char *meshlink_invite_ex(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, c // Ensure no host configuration file with that name exists if(config_exists(mesh, "current", name)) { - logger(mesh, MESHLINK_DEBUG, "A host config file for %s already exists!\n", 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; @@ -2388,7 +2402,7 @@ char *meshlink_invite_ex(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, c // Ensure no other nodes know about this name if(meshlink_get_node(mesh, name)) { - logger(mesh, MESHLINK_DEBUG, "A node with name %s is already known!\n", 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; @@ -2398,7 +2412,7 @@ char *meshlink_invite_ex(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, c char *address = get_my_hostname(mesh, flags); if(!address) { - logger(mesh, MESHLINK_DEBUG, "No Address known for ourselves!\n"); + logger(mesh, MESHLINK_ERROR, "No Address known for ourselves!\n"); meshlink_errno = MESHLINK_ERESOLV; pthread_mutex_unlock(&mesh->mutex); return NULL; @@ -2410,6 +2424,15 @@ char *meshlink_invite_ex(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, c 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)) { + logger(mesh, MESHLINK_ERROR, "Could not write our own host conifg file!\n"); + pthread_mutex_unlock(&mesh->mutex); + return NULL; + } + } + char hash[64]; // Create a hash of the key. @@ -3784,6 +3807,22 @@ void meshlink_set_dev_class_timeouts(meshlink_handle_t *mesh, dev_class_t devcla pthread_mutex_unlock(&mesh->mutex); } +void meshlink_set_dev_class_fast_retry_period(meshlink_handle_t *mesh, dev_class_t devclass, int fast_retry_period) { + if(!mesh || devclass < 0 || devclass >= DEV_CLASS_COUNT) { + meshlink_errno = EINVAL; + return; + } + + if(fast_retry_period < 0) { + meshlink_errno = EINVAL; + return; + } + + pthread_mutex_lock(&mesh->mutex); + mesh->dev_class_traits[devclass].fast_retry_period = fast_retry_period; + pthread_mutex_unlock(&mesh->mutex); +} + void handle_network_change(meshlink_handle_t *mesh, bool online) { (void)online;