]> git.meshlink.io Git - meshlink/blobdiff - src/meshlink.c
Add functions to get the amount of bytes in chanenl send and receive buffers.
[meshlink] / src / meshlink.c
index d094452733712c2e1b02b3bbfaa09efce7e96cca..8ec207842c6732bee32b25914db502c1174863d5 100644 (file)
@@ -54,6 +54,8 @@ __thread meshlink_errno_t meshlink_errno;
 meshlink_log_cb_t global_log_cb;
 meshlink_log_level_t global_log_level;
 
+typedef bool (*search_node_by_condition_t)(const node_t *, const void *);
+
 //TODO: this can go away completely
 const var_t variables[] = {
        /* Server configuration */
@@ -624,23 +626,22 @@ static bool try_bind(int port) {
                return false;
        }
 
-       while(ai) {
-               int fd = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
+       //while(ai) {
+       for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
+               int fd = socket(aip->ai_family, SOCK_STREAM, IPPROTO_TCP);
 
                if(!fd) {
                        freeaddrinfo(ai);
                        return false;
                }
 
-               int result = bind(fd, ai->ai_addr, ai->ai_addrlen);
+               int result = bind(fd, aip->ai_addr, aip->ai_addrlen);
                closesocket(fd);
 
                if(result) {
                        freeaddrinfo(ai);
                        return false;
                }
-
-               ai = ai->ai_next;
        }
 
        freeaddrinfo(ai);
@@ -921,7 +922,7 @@ static bool invitation_receive(void *handle, uint8_t type, const void *msg, uint
                return finalize_join(mesh);
 
        case 2:
-               logger(mesh, MESHLINK_DEBUG, "Invitation succesfully accepted.\n");
+               logger(mesh, MESHLINK_DEBUG, "Invitation successfully accepted.\n");
                shutdown(mesh->sock, SHUT_RDWR);
                mesh->success = true;
                break;
@@ -1433,20 +1434,13 @@ meshlink_submesh_t *meshlink_submesh_open(meshlink_handle_t  *mesh, const char *
                return NULL;
        }
 
-       s = (meshlink_submesh_t *)lookup_submesh(mesh, submesh);
-
-       if(s) {
-               logger(NULL, MESHLINK_ERROR, "SubMesh Already exists!\n");
-               meshlink_errno = MESHLINK_EEXIST;
-               return NULL;
-       }
+       //lock mesh->nodes
+       pthread_mutex_lock(&(mesh->mesh_mutex));
 
-       s = (meshlink_submesh_t *)new_submesh();
-       s->name = xstrdup(submesh);
+       s = (meshlink_submesh_t *)create_submesh(mesh, submesh);
 
-       submesh_add(mesh, (submesh_t *)s);
+       pthread_mutex_unlock(&(mesh->mesh_mutex));
 
-       meshlink_errno = MESHLINK_OK;
        return s;
 }
 
@@ -1732,6 +1726,13 @@ bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const
                return false;
        }
 
+       node_t *n = (node_t *)destination;
+
+       if(n->status.blacklisted) {
+               logger(mesh, MESHLINK_ERROR, "Node %s blacklisted, dropping packet\n", n->name);
+               return false;
+       }
+
        // Prepare the packet
        vpn_packet_t *packet = malloc(sizeof(*packet));
 
@@ -1882,12 +1883,7 @@ meshlink_node_t **meshlink_get_all_nodes(meshlink_handle_t *mesh, meshlink_node_
        return result;
 }
 
-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 || ((int)devclass < 0) || (devclass > _DEV_CLASS_MAX) || !nmemb) {
-               meshlink_errno = MESHLINK_EINVAL;
-               return NULL;
-       }
-
+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;
 
        pthread_mutex_lock(&(mesh->mesh_mutex));
@@ -1895,7 +1891,7 @@ meshlink_node_t **meshlink_get_all_nodes_by_dev_class(meshlink_handle_t *mesh, d
        *nmemb = 0;
 
        for splay_each(node_t, n, mesh->nodes) {
-               if(n->devclass == devclass) {
+               if(true == search_node(n, condition)) {
                        *nmemb = *nmemb + 1;
                }
        }
@@ -1912,7 +1908,7 @@ meshlink_node_t **meshlink_get_all_nodes_by_dev_class(meshlink_handle_t *mesh, d
                meshlink_node_t **p = result;
 
                for splay_each(node_t, n, mesh->nodes) {
-                       if(n->devclass == devclass) {
+                       if(true == search_node(n, condition)) {
                                *p++ = (meshlink_node_t *)n;
                        }
                }
@@ -1927,6 +1923,42 @@ meshlink_node_t **meshlink_get_all_nodes_by_dev_class(meshlink_handle_t *mesh, d
        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 == 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;
+}
+
+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 || ((int)devclass < 0) || (devclass > _DEV_CLASS_MAX) || !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;
@@ -1944,6 +1976,21 @@ dev_class_t meshlink_get_node_dev_class(meshlink_handle_t *mesh, meshlink_node_t
        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_sign(meshlink_handle_t *mesh, const void *data, size_t len, void *signature, size_t *siglen) {
        if(!mesh || !data || !len || !signature || !siglen) {
                meshlink_errno = MESHLINK_EINVAL;
@@ -2267,6 +2314,8 @@ char *meshlink_invite_ex(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, c
                        meshlink_errno = MESHLINK_EINVAL;
                        return NULL;
                }
+       } else {
+               s = (meshlink_submesh_t *)mesh->self->submesh;
        }
 
        pthread_mutex_lock(&(mesh->mesh_mutex));
@@ -2773,6 +2822,20 @@ void meshlink_blacklist(meshlink_handle_t *mesh, meshlink_node_t *node) {
 
        node_t *n;
        n = (node_t *)node;
+
+       if(n == mesh->self) {
+               logger(mesh, MESHLINK_ERROR, "%s blacklisting itself?\n", node->name);
+               meshlink_errno = MESHLINK_EINVAL;
+               pthread_mutex_unlock(&(mesh->mesh_mutex));
+               return;
+       }
+
+       if(n->status.blacklisted) {
+               logger(mesh, MESHLINK_DEBUG, "Node %s already blacklisted\n", node->name);
+               pthread_mutex_unlock(&(mesh->mesh_mutex));
+               return;
+       }
+
        n->status.blacklisted = true;
        logger(mesh, MESHLINK_DEBUG, "Blacklisted %s.\n", node->name);
 
@@ -2786,6 +2849,18 @@ void meshlink_blacklist(meshlink_handle_t *mesh, meshlink_node_t *node) {
                }
        }
 
+       utcp_abort_all_connections(n->utcp);
+
+       n->mtu = 0;
+       n->minmtu = 0;
+       n->maxmtu = MTU;
+       n->mtuprobes = 0;
+       n->status.udp_confirmed = false;
+
+       if(n->status.reachable) {
+               update_node_status(mesh, n);
+       }
+
        pthread_mutex_unlock(&(mesh->mesh_mutex));
 }
 
@@ -2798,9 +2873,22 @@ void meshlink_whitelist(meshlink_handle_t *mesh, meshlink_node_t *node) {
        pthread_mutex_lock(&(mesh->mesh_mutex));
 
        node_t *n = (node_t *)node;
+
+       if(!n->status.blacklisted) {
+               logger(mesh, MESHLINK_DEBUG, "Node %s was already whitelisted\n", node->name);
+               meshlink_errno = MESHLINK_EINVAL;
+               pthread_mutex_unlock(&(mesh->mesh_mutex));
+               return;
+       }
+
        n->status.blacklisted = false;
 
-       //TODO: remove blacklisted = yes from the config file
+       if(n->status.reachable) {
+               update_node_status(mesh, n);
+       }
+
+       //Remove blacklisting from the config file
+       append_config_file(mesh, n->name, "blacklisted", NULL);
 
        pthread_mutex_unlock(&(mesh->mesh_mutex));
        return;
@@ -2989,6 +3077,11 @@ meshlink_channel_t *meshlink_channel_open_ex(meshlink_handle_t *mesh, meshlink_n
                }
        }
 
+       if(n->status.blacklisted) {
+               logger(mesh, MESHLINK_ERROR, "Cannot open a channel with blacklisted node\n");
+               return NULL;
+       }
+
        meshlink_channel_t *channel = xzalloc(sizeof(*channel));
        channel->node = n;
        channel->receive_cb = cb;
@@ -3043,7 +3136,7 @@ ssize_t meshlink_channel_send(meshlink_handle_t *mesh, meshlink_channel_t *chann
 
        // TODO: more finegrained locking.
        // Ideally we want to put the data into the UTCP connection's send buffer.
-       // Then, preferrably only if there is room in the receiver window,
+       // Then, preferably only if there is room in the receiver window,
        // kick the meshlink thread to go send packets.
 
        pthread_mutex_lock(&mesh->mesh_mutex);
@@ -3066,13 +3159,31 @@ uint32_t meshlink_channel_get_flags(meshlink_handle_t *mesh, meshlink_channel_t
        return channel->c->flags;
 }
 
+size_t meshlink_channel_get_sendq(meshlink_handle_t *mesh, meshlink_channel_t *channel) {
+       if(!mesh || !channel) {
+               meshlink_errno = MESHLINK_EINVAL;
+               return -1;
+       }
+
+       return utcp_get_sendq(channel->c);
+}
+
+size_t meshlink_channel_get_recvq(meshlink_handle_t *mesh, meshlink_channel_t *channel) {
+       if(!mesh || !channel) {
+               meshlink_errno = MESHLINK_EINVAL;
+               return -1;
+       }
+
+       return utcp_get_recvq(channel->c);
+}
+
 void update_node_status(meshlink_handle_t *mesh, node_t *n) {
        if(n->status.reachable && mesh->channel_accept_cb && !n->utcp) {
                n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
        }
 
        if(mesh->node_status_cb) {
-               mesh->node_status_cb(mesh, (meshlink_node_t *)n, n->status.reachable);
+               mesh->node_status_cb(mesh, (meshlink_node_t *)n, n->status.reachable && !n->status.blacklisted);
        }
 }