]> git.meshlink.io Git - meshlink/blobdiff - src/net_socket.c
Stop using the global variable mesh in most of the rest of the code.
[meshlink] / src / net_socket.c
index 6a859f153610aa4849d33c8cc450928994aab702..160195455b450a9e1f1dc158df064bcf5a8a013c 100644 (file)
@@ -23,6 +23,7 @@
 #include "connection.h"
 #include "list.h"
 #include "logger.h"
+#include "meshlink_internal.h"
 #include "meta.h"
 #include "net.h"
 #include "netutl.h"
 #endif
 
 int addressfamily = AF_UNSPEC;
-int maxtimeout = 900;
 int seconds_till_retry = 5;
 int max_connection_burst = 100;
 
-listen_socket_t listen_socket[MAXSOCKETS];
-int listen_sockets;
-list_t *outgoing_list = NULL;
-
 /* Setup sockets */
 
 static void configure_tcp(connection_t *c) {
@@ -74,11 +70,11 @@ static void configure_tcp(connection_t *c) {
 #endif
 }
 
-static bool bind_to_address(connection_t *c) {
+static bool bind_to_address(meshlink_handle_t *mesh, connection_t *c) {
        int s = -1;
 
-       for(int i = 0; i < listen_sockets && listen_socket[i].bindto; i++) {
-               if(listen_socket[i].sa.sa.sa_family != c->address.sa.sa_family)
+       for(int i = 0; i < mesh->listen_sockets && mesh->listen_socket[i].bindto; i++) {
+               if(mesh->listen_socket[i].sa.sa.sa_family != c->address.sa.sa_family)
                        continue;
                if(s >= 0)
                        return false;
@@ -88,7 +84,7 @@ static bool bind_to_address(connection_t *c) {
        if(s < 0)
                return false;
 
-       sockaddr_t sa = listen_socket[s].sa;
+       sockaddr_t sa = mesh->listen_socket[s].sa;
        if(sa.sa.sa_family == AF_INET)
                sa.in.sin_port = 0;
        else if(sa.sa.sa_family == AF_INET6)
@@ -129,25 +125,6 @@ int setup_listen_socket(const sockaddr_t *sa) {
                setsockopt(nfd, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
 #endif
 
-       if(get_config_string
-          (lookup_config(config_tree, "BindToInterface"), &iface)) {
-#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
-               struct ifreq ifr;
-
-               memset(&ifr, 0, sizeof ifr);
-               strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
-
-               if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof ifr)) {
-                       closesocket(nfd);
-                       logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface,
-                                  strerror(sockerrno));
-                       return -1;
-               }
-#else
-               logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform", "BindToInterface");
-#endif
-       }
-
        if(bind(nfd, &sa->sa, SALEN(sa->sa))) {
                closesocket(nfd);
                addrstr = sockaddr2hostname(sa);
@@ -165,7 +142,7 @@ int setup_listen_socket(const sockaddr_t *sa) {
        return nfd;
 }
 
-int setup_vpn_in_socket(const sockaddr_t *sa) {
+int setup_vpn_in_socket(meshlink_handle_t *mesh, const sockaddr_t *sa) {
        int nfd;
        char *addrstr;
        int option;
@@ -217,12 +194,12 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
 #endif
 
 #if defined(SOL_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
-       if(myself->options & OPTION_PMTU_DISCOVERY) {
+       if(mesh->self->options & OPTION_PMTU_DISCOVERY) {
                option = IP_PMTUDISC_DO;
                setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option));
        }
 #elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT)
-       if(myself->options & OPTION_PMTU_DISCOVERY) {
+       if(mesh->self->options & OPTION_PMTU_DISCOVERY) {
                option = 1;
                setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option));
        }
@@ -231,12 +208,12 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
 #endif
 
 #if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
-       if(myself->options & OPTION_PMTU_DISCOVERY) {
+       if(mesh->self->options & OPTION_PMTU_DISCOVERY) {
                option = IPV6_PMTUDISC_DO;
                setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option));
        }
 #elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG)
-       if(myself->options & OPTION_PMTU_DISCOVERY) {
+       if(mesh->self->options & OPTION_PMTU_DISCOVERY) {
                option = 1;
                setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option));
        }
@@ -255,31 +232,33 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
        return nfd;
 } /* int setup_vpn_in_socket */
 
-static void retry_outgoing_handler(void *data) {
-       setup_outgoing_connection(data);
+static void retry_outgoing_handler(event_loop_t *loop, void *data) {
+       meshlink_handle_t *mesh = loop->data;
+       outgoing_t *outgoing = data;
+       setup_outgoing_connection(mesh, outgoing);
 }
 
-void retry_outgoing(outgoing_t *outgoing) {
+void retry_outgoing(meshlink_handle_t *mesh, outgoing_t *outgoing) {
        outgoing->timeout += 5;
 
-       if(outgoing->timeout > maxtimeout)
-               outgoing->timeout = maxtimeout;
+       if(outgoing->timeout > mesh->maxtimeout)
+               outgoing->timeout = mesh->maxtimeout;
 
-       timeout_add(&outgoing->ev, retry_outgoing_handler, outgoing, &(struct timeval){outgoing->timeout, rand() % 100000});
+       timeout_add(&mesh->loop, &outgoing->ev, retry_outgoing_handler, outgoing, &(struct timeval){outgoing->timeout, rand() % 100000});
 
        logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Trying to re-establish outgoing connection in %d seconds", outgoing->timeout);
 }
 
-void finish_connecting(connection_t *c) {
+void finish_connecting(meshlink_handle_t *mesh, connection_t *c) {
        logger(DEBUG_CONNECTIONS, LOG_INFO, "Connected to %s (%s)", c->name, c->hostname);
 
-       c->last_ping_time = now.tv_sec;
+       c->last_ping_time = mesh->loop.now.tv_sec;
        c->status.connecting = false;
 
-       send_id(c);
+       send_id(mesh, c);
 }
 
-static void do_outgoing_pipe(connection_t *c, char *command) {
+static void do_outgoing_pipe(meshlink_handle_t *mesh, connection_t *c, char *command) {
 #ifndef HAVE_MINGW
        int fd[2];
 
@@ -311,7 +290,7 @@ static void do_outgoing_pipe(connection_t *c, char *command) {
        setenv("REMOTEADDRESS", host, true);
        setenv("REMOTEPORT", port, true);
        setenv("NODE", c->name, true);
-       setenv("NAME", myself->name, true);
+       setenv("NAME", mesh->self->name, true);
 
        int result = system(command);
        if(result < 0)
@@ -325,7 +304,7 @@ static void do_outgoing_pipe(connection_t *c, char *command) {
 #endif
 }
 
-static void handle_meta_write(connection_t *c) {
+static void handle_meta_write(meshlink_handle_t *mesh, connection_t *c) {
        if(c->outbuf.len <= c->outbuf.offset)
                return;
 
@@ -340,16 +319,17 @@ static void handle_meta_write(connection_t *c) {
                        logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not send %d bytes of data to %s (%s): %s", c->outbuf.len - c->outbuf.offset, c->name, c->hostname, strerror(errno));
                }
 
-               terminate_connection(c, c->status.active);
+               terminate_connection(mesh, c, c->status.active);
                return;
        }
 
        buffer_read(&c->outbuf, outlen);
        if(!c->outbuf.len)
-               io_set(&c->io, IO_READ);
+               io_set(&mesh->loop, &c->io, IO_READ);
 }
 
-static void handle_meta_io(void *data, int flags) {
+static void handle_meta_io(event_loop_t *loop, void *data, int flags) {
+       meshlink_handle_t *mesh = loop->data;
        connection_t *c = data;
 
        if(c->status.connecting) {
@@ -360,21 +340,21 @@ static void handle_meta_io(void *data, int flags) {
                getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&result, &len);
 
                if(!result)
-                       finish_connecting(c);
+                       finish_connecting(mesh, c);
                else {
                        logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Error while connecting to %s (%s): %s", c->name, c->hostname, sockstrerror(result));
-                       terminate_connection(c, false);
+                       terminate_connection(mesh, c, false);
                        return;
                }
        }
 
        if(flags & IO_WRITE)
-               handle_meta_write(c);
+               handle_meta_write(mesh, c);
        else
-               handle_meta_connection_data(c);
+               handle_meta_connection_data(mesh, c);
 }
 
-bool do_outgoing_connection(outgoing_t *outgoing) {
+bool do_outgoing_connection(meshlink_handle_t *mesh, outgoing_t *outgoing) {
        char *address, *port, *space;
        struct addrinfo *proxyai = NULL;
        int result;
@@ -383,7 +363,7 @@ begin:
        if(!outgoing->ai) {
                if(!outgoing->cfg) {
                        logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not set up a meta connection to %s", outgoing->name);
-                       retry_outgoing(outgoing);
+                       retry_outgoing(mesh, outgoing);
                        return false;
                }
 
@@ -394,6 +374,7 @@ begin:
                        port = xstrdup(space + 1);
                        *space = 0;
                } else {
+                       // TODO: Only allow Address statements?
                        if(!get_config_string(lookup_config(outgoing->config_tree, "Port"), &port))
                                port = xstrdup("655");
                }
@@ -423,18 +404,18 @@ begin:
 
        logger(DEBUG_CONNECTIONS, LOG_INFO, "Trying to connect to %s (%s)", outgoing->name, c->hostname);
 
-       if(!proxytype) {
+       if(!mesh->proxytype) {
                c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
                configure_tcp(c);
-       } else if(proxytype == PROXY_EXEC) {
-               do_outgoing_pipe(c, proxyhost);
+       } else if(mesh->proxytype == PROXY_EXEC) {
+               do_outgoing_pipe(mesh, c, mesh->proxyhost);
        } else {
-               proxyai = str2addrinfo(proxyhost, proxyport, SOCK_STREAM);
+               proxyai = str2addrinfo(mesh->proxyhost, mesh->proxyport, SOCK_STREAM);
                if(!proxyai) {
                        free_connection(c);
                        goto begin;
                }
-               logger(DEBUG_CONNECTIONS, LOG_INFO, "Using proxy at %s port %s", proxyhost, proxyport);
+               logger(DEBUG_CONNECTIONS, LOG_INFO, "Using proxy at %s port %s", mesh->proxyhost, mesh->proxyport);
                c->socket = socket(proxyai->ai_family, SOCK_STREAM, IPPROTO_TCP);
                configure_tcp(c);
        }
@@ -449,21 +430,21 @@ begin:
        fcntl(c->socket, F_SETFD, FD_CLOEXEC);
 #endif
 
-       if(proxytype != PROXY_EXEC) {
+       if(mesh->proxytype != PROXY_EXEC) {
 #if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
                int option = 1;
                if(c->address.sa.sa_family == AF_INET6)
                        setsockopt(c->socket, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
 #endif
 
-               bind_to_address(c);
+               bind_to_address(mesh, c);
        }
 
        /* Connect */
 
-       if(!proxytype) {
+       if(!mesh->proxytype) {
                result = connect(c->socket, &c->address.sa, SALEN(c->address.sa));
-       } else if(proxytype == PROXY_EXEC) {
+       } else if(mesh->proxytype == PROXY_EXEC) {
                result = 0;
        } else {
                result = connect(c->socket, proxyai->ai_addr, proxyai->ai_addrlen);
@@ -481,12 +462,12 @@ begin:
 
        c->status.connecting = true;
        c->name = xstrdup(outgoing->name);
-       c->outcompression = myself->connection->outcompression;
-       c->last_ping_time = now.tv_sec;
+       c->outcompression = mesh->self->connection->outcompression;
+       c->last_ping_time = mesh->loop.now.tv_sec;
 
-       connection_add(c);
+       connection_add(mesh, c);
 
-       io_add(&c->io, handle_meta_io, c, c->socket, IO_READ|IO_WRITE);
+       io_add(&mesh->loop, &c->io, handle_meta_io, c, c->socket, IO_READ|IO_WRITE);
 
        return true;
 }
@@ -524,10 +505,10 @@ static struct addrinfo *get_known_addresses(node_t *n) {
        return ai;
 }
 
-void setup_outgoing_connection(outgoing_t *outgoing) {
-       timeout_del(&outgoing->ev);
+void setup_outgoing_connection(meshlink_handle_t *mesh, outgoing_t *outgoing) {
+       timeout_del(&mesh->loop, &outgoing->ev);
 
-       node_t *n = lookup_node(outgoing->name);
+       node_t *n = lookup_node(mesh, outgoing->name);
 
        if(n && n->connection) {
                logger(DEBUG_CONNECTIONS, LOG_INFO, "Already connected to %s", outgoing->name);
@@ -537,7 +518,7 @@ void setup_outgoing_connection(outgoing_t *outgoing) {
        }
 
        init_configuration(&outgoing->config_tree);
-       read_host_config(outgoing->config_tree, outgoing->name);
+       read_host_config(mesh, outgoing->config_tree, outgoing->name);
        outgoing->cfg = lookup_config(outgoing->config_tree, "Address");
 
        if(!outgoing->cfg) {
@@ -549,14 +530,15 @@ void setup_outgoing_connection(outgoing_t *outgoing) {
                }
        }
 
-       do_outgoing_connection(outgoing);
+       do_outgoing_connection(mesh, outgoing);
 }
 
 /*
   accept a new tcp connect and create a
   new connection
 */
-void handle_new_meta_connection(void *data, int flags) {
+void handle_new_meta_connection(event_loop_t *loop, void *data, int flags) {
+       meshlink_handle_t *mesh = loop->data;
        listen_socket_t *l = data;
        connection_t *c;
        sockaddr_t sa;
@@ -586,12 +568,12 @@ void handle_new_meta_connection(void *data, int flags) {
                static int samehost_burst;
                static int samehost_burst_time;
 
-               if(now.tv_sec - samehost_burst_time > samehost_burst)
+               if(mesh->loop.now.tv_sec - samehost_burst_time > samehost_burst)
                        samehost_burst = 0;
                else
-                       samehost_burst -= now.tv_sec - samehost_burst_time;
+                       samehost_burst -= mesh->loop.now.tv_sec - samehost_burst_time;
 
-               samehost_burst_time = now.tv_sec;
+               samehost_burst_time = mesh->loop.now.tv_sec;
                samehost_burst++;
 
                if(samehost_burst > max_connection_burst) {
@@ -607,12 +589,12 @@ void handle_new_meta_connection(void *data, int flags) {
        static int connection_burst;
        static int connection_burst_time;
 
-       if(now.tv_sec - connection_burst_time > connection_burst)
+       if(mesh->loop.now.tv_sec - connection_burst_time > connection_burst)
                connection_burst = 0;
        else
-               connection_burst -= now.tv_sec - connection_burst_time;
+               connection_burst -= mesh->loop.now.tv_sec - connection_burst_time;
 
-       connection_burst_time = now.tv_sec;
+       connection_burst_time = mesh->loop.now.tv_sec;
        connection_burst++;
 
        if(connection_burst >= max_connection_burst) {
@@ -625,27 +607,27 @@ void handle_new_meta_connection(void *data, int flags) {
 
        c = new_connection();
        c->name = xstrdup("<unknown>");
-       c->outcompression = myself->connection->outcompression;
+       c->outcompression = mesh->self->connection->outcompression;
 
        c->address = sa;
        c->hostname = sockaddr2hostname(&sa);
        c->socket = fd;
-       c->last_ping_time = now.tv_sec;
+       c->last_ping_time = mesh->loop.now.tv_sec;
 
        logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection from %s", c->hostname);
 
-       io_add(&c->io, handle_meta_io, c, c->socket, IO_READ);
+       io_add(&mesh->loop, &c->io, handle_meta_io, c, c->socket, IO_READ);
 
        configure_tcp(c);
 
-       connection_add(c);
+       connection_add(mesh, c);
 
        c->allow_request = ID;
-       send_id(c);
+       send_id(mesh, c);
 }
 
-static void free_outgoing(outgoing_t *outgoing) {
-       timeout_del(&outgoing->ev);
+static void free_outgoing(meshlink_handle_t *mesh, outgoing_t *outgoing) {
+       timeout_del(&mesh->loop, &outgoing->ev);
 
        if(outgoing->ai)
                freeaddrinfo(outgoing->ai);
@@ -659,19 +641,20 @@ static void free_outgoing(outgoing_t *outgoing) {
        free(outgoing);
 }
 
-void try_outgoing_connections(void) {
+void try_outgoing_connections(meshlink_handle_t *mesh) {
        /* If there is no outgoing list yet, create one. Otherwise, mark all outgoings as deleted. */
 
-       if(!outgoing_list) {
-               outgoing_list = list_alloc((list_action_t)free_outgoing);
+       if(!mesh->outgoings) {
+               mesh->outgoings = list_alloc((list_action_t)free_outgoing);
        } else {
-               for list_each(outgoing_t, outgoing, outgoing_list)
+               for list_each(outgoing_t, outgoing, mesh->outgoings)
                        outgoing->timeout = -1;
        }
 
        /* Make sure there is one outgoing_t in the list for each ConnectTo. */
 
-       for(config_t *cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+       // TODO: Drop support for ConnectTo since AutoConnect is now always on?
+       for(config_t *cfg = lookup_config(mesh->config, "ConnectTo"); cfg; cfg = lookup_config_next(mesh->config, cfg)) {
                char *name;
                get_config_string(cfg, &name);
 
@@ -685,7 +668,7 @@ void try_outgoing_connections(void) {
 
                bool found = false;
 
-               for list_each(outgoing_t, outgoing, outgoing_list) {
+               for list_each(outgoing_t, outgoing, mesh->outgoings) {
                        if(!strcmp(outgoing->name, name)) {
                                found = true;
                                outgoing->timeout = 0;
@@ -696,24 +679,24 @@ void try_outgoing_connections(void) {
                if(!found) {
                        outgoing_t *outgoing = xzalloc(sizeof *outgoing);
                        outgoing->name = name;
-                       list_insert_tail(outgoing_list, outgoing);
-                       setup_outgoing_connection(outgoing);
+                       list_insert_tail(mesh->outgoings, outgoing);
+                       setup_outgoing_connection(mesh, outgoing);
                }
        }
 
        /* Terminate any connections whose outgoing_t is to be deleted. */
 
-       for list_each(connection_t, c, connection_list) {
+       for list_each(connection_t, c, mesh->connections) {
                if(c->outgoing && c->outgoing->timeout == -1) {
                        c->outgoing = NULL;
                        logger(DEBUG_CONNECTIONS, LOG_INFO, "No more outgoing connection to %s", c->name);
-                       terminate_connection(c, c->status.active);
+                       terminate_connection(mesh, c, c->status.active);
                }
        }
 
        /* Delete outgoing_ts for which there is no ConnectTo. */
 
-       for list_each(outgoing_t, outgoing, outgoing_list)
+       for list_each(outgoing_t, outgoing, mesh->outgoings)
                if(outgoing->timeout == -1)
-                       list_delete_node(outgoing_list, node);
+                       list_delete_node(mesh->outgoings, node);
 }