]> git.meshlink.io Git - meshlink/commitdiff
Fix queue handling in meshlink_send().
authorGuus Sliepen <guus@meshlink.io>
Sat, 13 Sep 2014 14:09:11 +0000 (16:09 +0200)
committerGuus Sliepen <guus@meshlink.io>
Sat, 13 Sep 2014 14:09:11 +0000 (16:09 +0200)
We need to copy the data from the application *here*. To avoid multiple copies, prepare the
whole vpn_packet_t in meshlink_send(), so meshlink_send_from_queue() only has to dequeue
and call route(). We also don't need to take the mesh_mutex, since the only information we
use is the name of ourself and the destination node, which is guaranteed to be stable.

src/meshlink.c
src/meshlink_internal.h
src/route.c

index ef02580ea93d641059eb203c7e3a8a17b14c1ab9..e59170a9f220b50f992e0b07be376923f8ac1018 100644 (file)
@@ -1010,7 +1010,10 @@ void meshlink_set_log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, me
 }
 
 bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len) {
-       if(!mesh || !destination) {
+       meshlink_packethdr_t *hdr;
+
+       // Validate arguments
+       if(!mesh || !destination || len >= MAXSIZE - sizeof *hdr) {
                meshlink_errno = MESHLINK_EINVAL;
                return false;
        }
@@ -1023,59 +1026,45 @@ bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const
                return false;
        }
 
-       pthread_mutex_lock(&(mesh->mesh_mutex));
+       // Prepare the packet
+       vpn_packet_t *packet = malloc(sizeof *packet);
+       if(!packet) {
+               meshlink_errno = MESHLINK_ENOMEM;
+               return false;
+       }
 
-       //add packet to the queue
-       outpacketqueue_t *packet_in_queue = xzalloc(sizeof *packet_in_queue);
-       packet_in_queue->destination=destination;
-       packet_in_queue->data=data;
-       packet_in_queue->len=len;
-       if(!meshlink_queue_push(&mesh->outpacketqueue, packet_in_queue)) {
-               free(packet_in_queue);
-               pthread_mutex_unlock(&(mesh->mesh_mutex));
+       packet->probe = false;
+       packet->tcp = false;
+       packet->len = len + sizeof *hdr;
+
+       hdr = (meshlink_packethdr_t *)packet->data;
+       memset(hdr, 0, sizeof *hdr);
+       memcpy(hdr->destination, destination->name, sizeof hdr->destination);
+       memcpy(hdr->source, mesh->self->name, sizeof hdr->source);
+
+       memcpy(packet->data + sizeof *hdr, data, len);
+
+       // Queue it
+       if(!meshlink_queue_push(&mesh->outpacketqueue, packet)) {
+               free(packet);
+               meshlink_errno = MESHLINK_ENOMEM;
                return false;
        }
 
-       //notify event loop
+       // Notify event loop
        signal_trigger(&(mesh->loop),&(mesh->datafromapp));
        
-       pthread_mutex_unlock(&(mesh->mesh_mutex));
        return true;
 }
 
-void meshlink_send_from_queue(event_loop_t* el,meshlink_handle_t *mesh) {
-       pthread_mutex_lock(&(mesh->mesh_mutex));
-       
-       vpn_packet_t packet;
-       meshlink_packethdr_t *hdr = (meshlink_packethdr_t *)packet.data;
-
-       outpacketqueue_t* p = meshlink_queue_pop(&mesh->outpacketqueue);
-       if(!p)
-       {
-               pthread_mutex_unlock(&(mesh->mesh_mutex));
-               return;
-       }
-
-       if (sizeof(meshlink_packethdr_t) + p->len > MAXSIZE) {
-               pthread_mutex_unlock(&(mesh->mesh_mutex));
-               //log something
+void meshlink_send_from_queue(event_loop_t *loop, meshlink_handle_t *mesh) {
+       vpn_packet_t *packet = meshlink_queue_pop(&mesh->outpacketqueue);
+       if(!packet)
                return;
-       }
-
-       packet.probe = false;
-       memset(hdr, 0, sizeof *hdr);
-       memcpy(hdr->destination, p->destination->name, sizeof hdr->destination);
-       memcpy(hdr->source, mesh->self->name, sizeof hdr->source);
 
-       packet.len = sizeof *hdr + p->len;
-       memcpy(packet.data + sizeof *hdr, p->data, p->len);
-
-        mesh->self->in_packets++;
-        mesh->self->in_bytes += packet.len;
-        route(mesh, mesh->self, &packet);
-       
-       pthread_mutex_unlock(&(mesh->mesh_mutex));
-       return ;
+       mesh->self->in_packets++;
+       mesh->self->in_bytes += packet->len;
+       route(mesh, mesh->self, packet);
 }
 
 ssize_t meshlink_get_pmtu(meshlink_handle_t *mesh, meshlink_node_t *destination) {
index a58ab440ee5ca25f3011354b85364ee2305afa75..6c7ac7bdf717e12e13d7c927a7aaf19237ce2cb1 100644 (file)
@@ -54,12 +54,6 @@ typedef enum proxytype_t {
        PROXY_EXEC,
 } proxytype_t;
 
-typedef struct outpacketqueue {
-       meshlink_node_t *destination;
-       const void *data;
-       unsigned int len;
-} outpacketqueue_t;
-
 /// A handle for an instance of MeshLink.
 struct meshlink_handle {
        char *name;
index f451d8e35ebb8229d987746b970b17de4d55049c..1cb60d87ddf0f98c997c161943f0ad18a9140bbb 100644 (file)
@@ -45,7 +45,7 @@ void route(meshlink_handle_t *mesh, node_t *source, vpn_packet_t *packet) {
        logger(mesh, MESHLINK_DEBUG, "Routing packet from \"%s\" to \"%s\"\n", hdr->source, hdr->destination);
 
        //Check Lenght
-       if(!checklength(source, packet, (sizeof(meshlink_packethdr_t))))
+       if(!checklength(source, packet, sizeof *hdr))
                return;
 
        if(owner == NULL) {