X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fmeshlink.c;h=19d9fdca9d32f31c9acd92ea330ce51a3686968f;hb=664466227602b6aabd4f601cf57183bbfa45bc08;hp=9bfaa22b854b7333281c5d14f930aa6235a72ce4;hpb=e58fbbcfd73213995ead721db3efbc22808430d3;p=meshlink-tiny diff --git a/src/meshlink.c b/src/meshlink.c index 9bfaa22..19d9fdc 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -27,7 +27,6 @@ #include "net.h" #include "netutl.h" #include "node.h" -#include "submesh.h" #include "packmsg.h" #include "prf.h" #include "protocol.h" @@ -149,342 +148,6 @@ static int socket_in_netns(int domain, int type, int protocol, int netns) { } -// Find out what local address a socket would use if we connect to the given address. -// We do this using connect() on a UDP socket, so the kernel has to resolve the address -// of both endpoints, but this will actually not send any UDP packet. -static bool getlocaladdr(const char *destaddr, sockaddr_t *sa, socklen_t *salen, int netns) { - struct addrinfo *rai = NULL; - const struct addrinfo hint = { - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_DGRAM, - .ai_protocol = IPPROTO_UDP, - .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV, - }; - - if(getaddrinfo(destaddr, "80", &hint, &rai) || !rai) { - return false; - } - - int sock = socket_in_netns(rai->ai_family, rai->ai_socktype, rai->ai_protocol, netns); - - if(sock == -1) { - freeaddrinfo(rai); - return false; - } - - if(connect(sock, rai->ai_addr, rai->ai_addrlen) && !sockwouldblock(errno)) { - closesocket(sock); - freeaddrinfo(rai); - return false; - } - - freeaddrinfo(rai); - - if(getsockname(sock, &sa->sa, salen)) { - closesocket(sock); - return false; - } - - closesocket(sock); - return true; -} - -static bool getlocaladdrname(const char *destaddr, char *host, socklen_t hostlen, int netns) { - sockaddr_t sa; - socklen_t salen = sizeof(sa); - - if(!getlocaladdr(destaddr, &sa, &salen, netns)) { - return false; - } - - if(getnameinfo(&sa.sa, salen, host, hostlen, NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV)) { - return false; - } - - return true; -} - -char *meshlink_get_external_address(meshlink_handle_t *mesh) { - return meshlink_get_external_address_for_family(mesh, AF_UNSPEC); -} - -char *meshlink_get_external_address_for_family(meshlink_handle_t *mesh, int family) { - logger(mesh, MESHLINK_DEBUG, "meshlink_get_external_address_for_family(%d)", family); - const char *url = mesh->external_address_url; - - if(!url) { - url = "http://meshlink.io/host.cgi"; - } - - /* Find the hostname part between the slashes */ - if(strncmp(url, "http://", 7)) { - abort(); - meshlink_errno = MESHLINK_EINTERNAL; - return NULL; - } - - const char *begin = url + 7; - - const char *end = strchr(begin, '/'); - - if(!end) { - end = begin + strlen(begin); - } - - /* Make a copy */ - char host[end - begin + 1]; - strncpy(host, begin, end - begin); - host[end - begin] = 0; - - char *port = strchr(host, ':'); - - if(port) { - *port++ = 0; - } - - logger(mesh, MESHLINK_DEBUG, "Trying to discover externally visible hostname...\n"); - struct addrinfo *ai = str2addrinfo(host, port ? port : "80", SOCK_STREAM); - char line[256]; - char *hostname = NULL; - - for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) { - if(family != AF_UNSPEC && aip->ai_family != family) { - continue; - } - - int s = socket_in_netns(aip->ai_family, aip->ai_socktype, aip->ai_protocol, mesh->netns); - -#ifdef SO_NOSIGPIPE - int nosigpipe = 1; - setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe)); -#endif - - if(s >= 0) { - set_timeout(s, 5000); - - if(connect(s, aip->ai_addr, aip->ai_addrlen)) { - closesocket(s); - s = -1; - } - } - - if(s >= 0) { - send(s, "GET ", 4, 0); - send(s, url, strlen(url), 0); - send(s, " HTTP/1.0\r\n\r\n", 13, 0); - int len = recv(s, line, sizeof(line) - 1, MSG_WAITALL); - - if(len > 0) { - line[len] = 0; - - if(line[len - 1] == '\n') { - line[--len] = 0; - } - - char *p = strrchr(line, '\n'); - - if(p && p[1]) { - hostname = xstrdup(p + 1); - } - } - - closesocket(s); - - if(hostname) { - break; - } - } - } - - if(ai) { - freeaddrinfo(ai); - } - - // Check that the hostname is reasonable - if(hostname && !is_valid_hostname(hostname)) { - free(hostname); - hostname = NULL; - } - - if(!hostname) { - meshlink_errno = MESHLINK_ERESOLV; - } - - return hostname; -} - -static bool is_localaddr(sockaddr_t *sa) { - switch(sa->sa.sa_family) { - case AF_INET: - return *(uint8_t *)(&sa->in.sin_addr.s_addr) == 127; - - case AF_INET6: { - uint16_t first = sa->in6.sin6_addr.s6_addr[0] << 8 | sa->in6.sin6_addr.s6_addr[1]; - return first == 0 || (first & 0xffc0) == 0xfe80; - } - - default: - return false; - } -} - -#ifdef HAVE_GETIFADDRS -struct getifaddrs_in_netns_params { - struct ifaddrs **ifa; - int netns; -}; - -#ifdef HAVE_SETNS -static void *getifaddrs_in_netns_thread(void *arg) { - struct getifaddrs_in_netns_params *params = arg; - - if(setns(params->netns, CLONE_NEWNET) == -1) { - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - if(getifaddrs(params->ifa) != 0) { - *params->ifa = NULL; - } - - return NULL; -} -#endif // HAVE_SETNS - -static int getifaddrs_in_netns(struct ifaddrs **ifa, int netns) { - if(netns == -1) { - return getifaddrs(ifa); - } - -#ifdef HAVE_SETNS - struct getifaddrs_in_netns_params params = {ifa, netns}; - pthread_t thr; - - if(pthread_create(&thr, NULL, getifaddrs_in_netns_thread, ¶ms) == 0) { - if(pthread_join(thr, NULL) != 0) { - abort(); - } - } - - return *params.ifa ? 0 : -1; -#else - return -1; -#endif // HAVE_SETNS - -} -#endif - -char *meshlink_get_local_address_for_family(meshlink_handle_t *mesh, int family) { - logger(mesh, MESHLINK_DEBUG, "meshlink_get_local_address_for_family(%d)", family); - - if(!mesh) { - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - // Determine address of the local interface used for outgoing connections. - char localaddr[NI_MAXHOST]; - bool success = false; - - if(family == AF_INET) { - success = getlocaladdrname("93.184.216.34", localaddr, sizeof(localaddr), mesh->netns); - } else if(family == AF_INET6) { - success = getlocaladdrname("2606:2800:220:1:248:1893:25c8:1946", localaddr, sizeof(localaddr), mesh->netns); - } - -#ifdef HAVE_GETIFADDRS - - if(!success) { - struct ifaddrs *ifa = NULL; - getifaddrs_in_netns(&ifa, mesh->netns); - - for(struct ifaddrs *ifap = ifa; ifap; ifap = ifap->ifa_next) { - sockaddr_t *sa = (sockaddr_t *)ifap->ifa_addr; - - if(!sa || sa->sa.sa_family != family) { - continue; - } - - if(is_localaddr(sa)) { - continue; - } - - if(!getnameinfo(&sa->sa, SALEN(sa->sa), localaddr, sizeof(localaddr), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV)) { - success = true; - break; - } - } - - freeifaddrs(ifa); - } - -#endif - - if(!success) { - meshlink_errno = MESHLINK_ENETWORK; - return NULL; - } - - return xstrdup(localaddr); -} - -static bool try_bind(meshlink_handle_t *mesh, int port) { - struct addrinfo *ai = NULL; - struct addrinfo hint = { - .ai_flags = AI_PASSIVE, - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_STREAM, - .ai_protocol = IPPROTO_TCP, - }; - - char portstr[16]; - snprintf(portstr, sizeof(portstr), "%d", port); - - if(getaddrinfo(NULL, portstr, &hint, &ai) || !ai) { - return false; - } - - bool success = false; - - for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) { - /* Try to bind to TCP. */ - - int tcp_fd = setup_tcp_listen_socket(mesh, aip); - - if(tcp_fd == -1) { - if(errno == EADDRINUSE) { - /* If this port is in use for any address family, avoid it. */ - success = false; - break; - } else { - continue; - } - } - - closesocket(tcp_fd); - success = true; - } - - freeaddrinfo(ai); - return success; -} - -int check_port(meshlink_handle_t *mesh) { - for(int i = 0; i < 1000; i++) { - int port = 0x1000 + prng(mesh, 0x8000); - - if(try_bind(mesh, port)) { - free(mesh->myport); - xasprintf(&mesh->myport, "%d", port); - return port; - } - } - - meshlink_errno = MESHLINK_ENETWORK; - logger(mesh, MESHLINK_DEBUG, "Could not find any available network port.\n"); - return 0; -} - static bool write_main_config_files(meshlink_handle_t *mesh) { if(!mesh->confbase) { return true; @@ -544,28 +207,19 @@ static bool finalize_join(join_state_t *state, const void *buf, uint16_t len) { } char *name = packmsg_get_str_dup(&in); - char *submesh_name = packmsg_get_str_dup(&in); + packmsg_skip_element(&in); // submesh_name dev_class_t devclass = packmsg_get_int32(&in); uint32_t count = packmsg_get_array(&in); if(!name || !check_id(name)) { logger(mesh, MESHLINK_DEBUG, "No valid Name found in invitation!\n"); free(name); - free(submesh_name); - return false; - } - - if(!submesh_name || (strcmp(submesh_name, CORE_MESH) && !check_id(submesh_name))) { - logger(mesh, MESHLINK_DEBUG, "No valid Submesh found in invitation!\n"); - free(name); - free(submesh_name); return false; } if(!count) { logger(mesh, MESHLINK_ERROR, "Incomplete invitation file!\n"); free(name); - free(submesh_name); return false; } @@ -573,8 +227,6 @@ static bool finalize_join(join_state_t *state, const void *buf, uint16_t len) { free(mesh->self->name); mesh->name = name; mesh->self->name = xstrdup(name); - mesh->self->submesh = strcmp(submesh_name, CORE_MESH) ? lookup_or_create_submesh(mesh, submesh_name) : NULL; - free(submesh_name); mesh->self->devclass = devclass == DEV_CLASS_UNKNOWN ? mesh->devclass : devclass; // Initialize configuration directory @@ -836,54 +488,16 @@ static bool ecdsa_keygen(meshlink_handle_t *mesh) { return true; } -static bool timespec_lt(const struct timespec *a, const struct timespec *b) { - if(a->tv_sec == b->tv_sec) { - return a->tv_nsec < b->tv_nsec; - } else { - return a->tv_sec < b->tv_sec; - } -} - static struct timespec idle(event_loop_t *loop, void *data) { (void)loop; meshlink_handle_t *mesh = data; - struct timespec t, tmin = {3600, 0}; - - for splay_each(node_t, n, mesh->nodes) { - if(!n->utcp) { - continue; - } - - t = utcp_timeout(n->utcp); - - if(timespec_lt(&t, &tmin)) { - tmin = t; - } - } - - return tmin; -} -// Get our local address(es) by simulating connecting to an Internet host. -static void add_local_addresses(meshlink_handle_t *mesh) { - sockaddr_t sa; - sa.storage.ss_family = AF_UNKNOWN; - socklen_t salen = sizeof(sa); - - // IPv4 example.org - - if(getlocaladdr("93.184.216.34", &sa, &salen, mesh->netns)) { - sa.in.sin_port = ntohs(atoi(mesh->myport)); - node_add_recent_address(mesh, mesh->self, &sa); - } - - // IPv6 example.org - - salen = sizeof(sa); - - if(getlocaladdr("2606:2800:220:1:248:1893:25c8:1946", &sa, &salen, mesh->netns)) { - sa.in6.sin6_port = ntohs(atoi(mesh->myport)); - node_add_recent_address(mesh, mesh->self, &sa); + if(mesh->peer && mesh->peer->utcp) { + return utcp_timeout(mesh->peer->utcp); + } else { + return (struct timespec) { + 3600, 0 + }; } } @@ -911,10 +525,7 @@ static bool meshlink_setup(meshlink_handle_t *mesh) { return false; } - if(check_port(mesh) == 0) { - meshlink_errno = MESHLINK_ENETWORK; - return false; - } + mesh->myport = xstrdup("0"); /* Create a node for ourself */ @@ -1352,7 +963,6 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) { mesh->appname = xstrdup(params->appname); mesh->devclass = params->devclass; mesh->netns = params->netns; - mesh->submeshes = NULL; mesh->log_cb = global_log_cb; mesh->log_level = global_log_level; mesh->packet = xmalloc(sizeof(vpn_packet_t)); @@ -1465,8 +1075,6 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) { return NULL; } - add_local_addresses(mesh); - if(!node_write_config(mesh, mesh->self, new_configuration)) { logger(NULL, MESHLINK_ERROR, "Cannot update configuration\n"); return NULL; @@ -1478,35 +1086,6 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) { return mesh; } -meshlink_submesh_t *meshlink_submesh_open(meshlink_handle_t *mesh, const char *submesh) { - logger(NULL, MESHLINK_DEBUG, "meshlink_submesh_open(%s)", submesh); - - meshlink_submesh_t *s = NULL; - - if(!mesh) { - logger(NULL, MESHLINK_ERROR, "No mesh handle given!\n"); - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - if(!submesh || !*submesh) { - logger(NULL, MESHLINK_ERROR, "No submesh name given!\n"); - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - //lock mesh->nodes - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - s = (meshlink_submesh_t *)create_submesh(mesh, submesh); - - pthread_mutex_unlock(&mesh->mutex); - - return s; -} - static void *meshlink_main_loop(void *arg) { meshlink_handle_t *mesh = arg; @@ -1561,19 +1140,11 @@ bool meshlink_start(meshlink_handle_t *mesh) { return true; } - if(mesh->listen_socket[0].tcp.fd < 0) { - logger(mesh, MESHLINK_ERROR, "Listening socket not open\n"); - meshlink_errno = MESHLINK_ENETWORK; - return false; - } - // Reset node connection timers - for splay_each(node_t, n, mesh->nodes) { - n->last_connect_try = 0; + if(mesh->peer) { + mesh->peer->last_connect_try = 0; } - // TODO: open listening sockets first - //Check that a valid name is set if(!mesh->name) { logger(mesh, MESHLINK_ERROR, "No name given!\n"); @@ -1642,25 +1213,17 @@ void meshlink_stop(meshlink_handle_t *mesh) { } // Close all metaconnections - if(mesh->connections) { - for(list_node_t *node = mesh->connections->head, *next; node; node = next) { - next = node->next; - connection_t *c = node->data; - c->outgoing = NULL; - terminate_connection(mesh, c, false); - } + if(mesh->connection) { + mesh->connection->outgoing = NULL; + terminate_connection(mesh, mesh->connection, false); } exit_outgoings(mesh); // Try to write out any changed node config files, ignore errors at this point. - if(mesh->nodes) { - for splay_each(node_t, n, mesh->nodes) { - if(n->status.dirty) { - if(!node_write_config(mesh, n, false)) { - // ignore - } - } + if(mesh->peer && mesh->peer->status.dirty) { + if(!node_write_config(mesh, mesh->peer, false)) { + // ignore } } @@ -2116,202 +1679,6 @@ meshlink_node_t *meshlink_get_node(meshlink_handle_t *mesh, const char *name) { return (meshlink_node_t *)n; } -meshlink_submesh_t *meshlink_get_submesh(meshlink_handle_t *mesh, const char *name) { - if(!mesh || !name) { - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - meshlink_submesh_t *submesh = NULL; - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - submesh = (meshlink_submesh_t *)lookup_submesh(mesh, name); - pthread_mutex_unlock(&mesh->mutex); - - if(!submesh) { - meshlink_errno = MESHLINK_ENOENT; - } - - return submesh; -} - -meshlink_node_t **meshlink_get_all_nodes(meshlink_handle_t *mesh, meshlink_node_t **nodes, size_t *nmemb) { - if(!mesh || !nmemb || (*nmemb && !nodes)) { - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - meshlink_node_t **result; - - //lock mesh->nodes - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - *nmemb = mesh->nodes->count; - result = realloc(nodes, *nmemb * sizeof(*nodes)); - - if(result) { - meshlink_node_t **p = result; - - for splay_each(node_t, n, mesh->nodes) { - *p++ = (meshlink_node_t *)n; - } - } else { - *nmemb = 0; - free(nodes); - meshlink_errno = MESHLINK_ENOMEM; - } - - pthread_mutex_unlock(&mesh->mutex); - - return result; -} - -static meshlink_node_t **meshlink_get_all_nodes_by_condition(meshlink_handle_t *mesh, const void *condition, meshlink_node_t **nodes, size_t *nmemb, search_node_by_condition_t search_node) { - meshlink_node_t **result; - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - *nmemb = 0; - - for splay_each(node_t, n, mesh->nodes) { - if(search_node(n, condition)) { - ++*nmemb; - } - } - - if(*nmemb == 0) { - free(nodes); - pthread_mutex_unlock(&mesh->mutex); - return NULL; - } - - result = realloc(nodes, *nmemb * sizeof(*nodes)); - - if(result) { - meshlink_node_t **p = result; - - for splay_each(node_t, n, mesh->nodes) { - if(search_node(n, condition)) { - *p++ = (meshlink_node_t *)n; - } - } - } else { - *nmemb = 0; - free(nodes); - meshlink_errno = MESHLINK_ENOMEM; - } - - pthread_mutex_unlock(&mesh->mutex); - - return result; -} - -static bool search_node_by_dev_class(const node_t *node, const void *condition) { - dev_class_t *devclass = (dev_class_t *)condition; - - if(*devclass == (dev_class_t)node->devclass) { - return true; - } - - return false; -} - -static bool search_node_by_submesh(const node_t *node, const void *condition) { - if(condition == node->submesh) { - return true; - } - - return false; -} - -struct time_range { - time_t start; - time_t end; -}; - -meshlink_node_t **meshlink_get_all_nodes_by_dev_class(meshlink_handle_t *mesh, dev_class_t devclass, meshlink_node_t **nodes, size_t *nmemb) { - if(!mesh || devclass < 0 || devclass >= DEV_CLASS_COUNT || !nmemb) { - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - return meshlink_get_all_nodes_by_condition(mesh, &devclass, nodes, nmemb, search_node_by_dev_class); -} - -meshlink_node_t **meshlink_get_all_nodes_by_submesh(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, meshlink_node_t **nodes, size_t *nmemb) { - if(!mesh || !submesh || !nmemb) { - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - return meshlink_get_all_nodes_by_condition(mesh, submesh, nodes, nmemb, search_node_by_submesh); -} - -dev_class_t meshlink_get_node_dev_class(meshlink_handle_t *mesh, meshlink_node_t *node) { - if(!mesh || !node) { - meshlink_errno = MESHLINK_EINVAL; - return -1; - } - - dev_class_t devclass; - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - devclass = ((node_t *)node)->devclass; - - pthread_mutex_unlock(&mesh->mutex); - - return devclass; -} - -meshlink_submesh_t *meshlink_get_node_submesh(meshlink_handle_t *mesh, meshlink_node_t *node) { - if(!mesh || !node) { - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - node_t *n = (node_t *)node; - - meshlink_submesh_t *s; - - s = (meshlink_submesh_t *)n->submesh; - - return s; -} - -bool meshlink_get_node_reachability(struct meshlink_handle *mesh, struct meshlink_node *node, time_t *last_reachable, time_t *last_unreachable) { - if(!mesh || !node) { - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - node_t *n = (node_t *)node; - bool reachable; - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - reachable = n->status.reachable && !n->status.blacklisted; - - // TODO: handle reachable times? - (void)last_reachable; - (void)last_unreachable; - - pthread_mutex_unlock(&mesh->mutex); - - return reachable; -} - bool meshlink_sign(meshlink_handle_t *mesh, const void *data, size_t len, void *signature, size_t *siglen) { logger(mesh, MESHLINK_DEBUG, "meshlink_sign(%p, %zu, %p, %p)", data, len, signature, (void *)siglen); @@ -2447,124 +1814,6 @@ bool meshlink_clear_canonical_address(meshlink_handle_t *mesh, meshlink_node_t * return config_sync(mesh, "current"); } -bool meshlink_add_address(meshlink_handle_t *mesh, const char *address) { - logger(mesh, MESHLINK_DEBUG, "meshlink_add_address(%s)", address ? address : "(null)"); - - return meshlink_set_canonical_address(mesh, (meshlink_node_t *)mesh->self, address, NULL); -} - -bool meshlink_add_external_address(meshlink_handle_t *mesh) { - logger(mesh, MESHLINK_DEBUG, "meshlink_add_external_address()"); - - if(!mesh) { - meshlink_errno = MESHLINK_EINVAL; - return false; - } - - char *address = meshlink_get_external_address(mesh); - - if(!address) { - return false; - } - - bool rval = meshlink_set_canonical_address(mesh, (meshlink_node_t *)mesh->self, address, NULL); - free(address); - - return rval; -} - -int meshlink_get_port(meshlink_handle_t *mesh) { - if(!mesh) { - meshlink_errno = MESHLINK_EINVAL; - return -1; - } - - if(!mesh->myport) { - meshlink_errno = MESHLINK_EINTERNAL; - return -1; - } - - int port; - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - port = atoi(mesh->myport); - pthread_mutex_unlock(&mesh->mutex); - - return port; -} - -bool meshlink_set_port(meshlink_handle_t *mesh, int port) { - logger(mesh, MESHLINK_DEBUG, "meshlink_set_port(%d)", port); - - if(!mesh || port < 0 || port >= 65536 || mesh->threadstarted) { - meshlink_errno = MESHLINK_EINVAL; - return false; - } - - if(mesh->myport && port == atoi(mesh->myport)) { - return true; - } - - if(!try_bind(mesh, port)) { - meshlink_errno = MESHLINK_ENETWORK; - return false; - } - - devtool_trybind_probe(); - - bool rval = false; - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - if(mesh->threadstarted) { - meshlink_errno = MESHLINK_EINVAL; - goto done; - } - - free(mesh->myport); - xasprintf(&mesh->myport, "%d", port); - - /* Close down the network. This also deletes mesh->self. */ - close_network_connections(mesh); - - /* Recreate mesh->self. */ - mesh->self = new_node(); - mesh->self->name = xstrdup(mesh->name); - mesh->self->devclass = mesh->devclass; - mesh->self->session_id = mesh->session_id; - xasprintf(&mesh->myport, "%d", port); - - if(!node_read_public_key(mesh, mesh->self)) { - logger(NULL, MESHLINK_ERROR, "Could not read our host configuration file!"); - meshlink_errno = MESHLINK_ESTORAGE; - free_node(mesh->self); - mesh->self = NULL; - goto done; - } else if(!setup_network(mesh)) { - meshlink_errno = MESHLINK_ENETWORK; - goto done; - } - - /* Rebuild our own list of recent addresses */ - memset(mesh->self->recent, 0, sizeof(mesh->self->recent)); - add_local_addresses(mesh); - - /* Write meshlink.conf with the updated port number */ - write_main_config_files(mesh); - - rval = config_sync(mesh, "current"); - -done: - pthread_mutex_unlock(&mesh->mutex); - - return rval && meshlink_get_port(mesh) == port; -} - bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { logger(mesh, MESHLINK_DEBUG, "meshlink_join(%s)", invitation ? invitation : "(null)"); @@ -2601,7 +1850,7 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { } // 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) { + if(mesh->peer) { logger(mesh, MESHLINK_ERROR, "Already part of an existing mesh\n"); meshlink_errno = MESHLINK_EINVAL; goto exit; @@ -3013,66 +2262,6 @@ bool meshlink_import(meshlink_handle_t *mesh, const char *data) { return true; } -bool meshlink_forget_node(meshlink_handle_t *mesh, meshlink_node_t *node) { - logger(mesh, MESHLINK_DEBUG, "meshlink_forget_node(%s)", node ? node->name : "(null)"); - - if(!mesh || !node) { - meshlink_errno = MESHLINK_EINVAL; - return false; - } - - node_t *n = (node_t *)node; - - if(pthread_mutex_lock(&mesh->mutex) != 0) { - abort(); - } - - /* Check that the node is not reachable */ - if(n->status.reachable || n->connection) { - pthread_mutex_unlock(&mesh->mutex); - logger(mesh, MESHLINK_WARNING, "Could not forget %s: still reachable", n->name); - return false; - } - - /* Check that we don't have any active UTCP connections */ - if(n->utcp && utcp_is_active(n->utcp)) { - pthread_mutex_unlock(&mesh->mutex); - logger(mesh, MESHLINK_WARNING, "Could not forget %s: active UTCP connections", n->name); - return false; - } - - /* Check that we have no active connections to this node */ - for list_each(connection_t, c, mesh->connections) { - if(c->node == n) { - pthread_mutex_unlock(&mesh->mutex); - logger(mesh, MESHLINK_WARNING, "Could not forget %s: active connection", n->name); - return false; - } - } - - /* Remove any pending outgoings to this node */ - if(mesh->outgoings) { - for list_each(outgoing_t, outgoing, mesh->outgoings) { - if(outgoing->node == n) { - list_delete_node(mesh->outgoings, list_node); - } - } - } - - /* Delete the config file for this node */ - if(!config_delete(mesh, "current", n->name)) { - pthread_mutex_unlock(&mesh->mutex); - return false; - } - - /* Delete the node struct and any remaining edges referencing this node */ - node_del(mesh, n); - - pthread_mutex_unlock(&mesh->mutex); - - return config_sync(mesh, "current"); -} - /* Hint that a hostname may be found at an address * See header file for detailed comment. */ @@ -3447,12 +2636,10 @@ void meshlink_set_channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_ac mesh->channel_accept_cb = cb; mesh->receive_cb = channel_receive; - for splay_each(node_t, n, mesh->nodes) { - if(!n->utcp && n != mesh->self) { - n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n); - utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t)); - utcp_set_retransmit_cb(n->utcp, channel_retransmit); - } + if(mesh->peer) { + mesh->peer->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, mesh->peer); + utcp_set_mtu(mesh->peer->utcp, mesh->peer->mtu - sizeof(meshlink_packethdr_t)); + utcp_set_retransmit_cb(mesh->peer->utcp, channel_retransmit); } pthread_mutex_unlock(&mesh->mutex); @@ -4098,7 +3285,7 @@ void meshlink_set_storage_policy(struct meshlink_handle *mesh, meshlink_storage_ void handle_network_change(meshlink_handle_t *mesh, bool online) { (void)online; - if(!mesh->connections || !mesh->loop.running) { + if(!mesh->loop.running) { return; }