aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mesh/mesh_api_new.c351
-rw-r--r--src/mesh/test_mesh_api.c4
-rw-r--r--src/mesh/test_mesh_small.c2
3 files changed, 169 insertions, 188 deletions
diff --git a/src/mesh/mesh_api_new.c b/src/mesh/mesh_api_new.c
index 273d35b2d..23ade2379 100644
--- a/src/mesh/mesh_api_new.c
+++ b/src/mesh/mesh_api_new.c
@@ -1,17 +1,15 @@
1
1/* 2/*
2 This file is part of GNUnet. 3 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors) 4 (C) 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your 7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version. 8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but 9 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of 10 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details. 12 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License 13 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the 14 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330, 15 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
@@ -25,9 +23,6 @@
25 * 23 *
26 * TODO: 24 * TODO:
27 * - handle reconnect (service crash/disconnect) properly 25 * - handle reconnect (service crash/disconnect) properly
28 * - count only data for queue length; store current queue length
29 * with tunnel instead of counting each time
30 * (also count per tunnel instead of for the entire mesh handle?)
31 * - callbacks to client missing on certain events 26 * - callbacks to client missing on certain events
32 * - processing messages from service is incomplete 27 * - processing messages from service is incomplete
33 * 28 *
@@ -39,17 +34,16 @@
39 * - SEND FUNCTIONS 34 * - SEND FUNCTIONS
40 * - API CALL DEFINITIONS 35 * - API CALL DEFINITIONS
41 */ 36 */
42
43#ifdef __cplusplus 37#ifdef __cplusplus
44
45extern "C" 38extern "C"
46{ 39{
47#if 0 /* keep Emacsens' auto-indent happy */ 40#if 0 /* keep Emacsens' auto-indent happy */
48} 41}
49#endif 42#endif
50#endif 43 /*
51 44 */
52 45#endif /*
46 */
53#include "platform.h" 47#include "platform.h"
54#include "gnunet_common.h" 48#include "gnunet_common.h"
55#include "gnunet_client_lib.h" 49#include "gnunet_client_lib.h"
@@ -59,10 +53,6 @@ extern "C"
59#include "mesh.h" 53#include "mesh.h"
60#include "mesh_protocol.h" 54#include "mesh_protocol.h"
61 55
62/**
63 * TODO: replace with extra argument to mesh-connect.
64 */
65#define MESH_API_MAX_QUEUE 10
66 56
67/******************************************************************************/ 57/******************************************************************************/
68/************************ DATA STRUCTURES ****************************/ 58/************************ DATA STRUCTURES ****************************/
@@ -73,6 +63,7 @@ extern "C"
73 */ 63 */
74struct GNUNET_MESH_TransmitHandle 64struct GNUNET_MESH_TransmitHandle
75{ 65{
66
76 /** 67 /**
77 * Double Linked list 68 * Double Linked list
78 */ 69 */
@@ -84,58 +75,58 @@ struct GNUNET_MESH_TransmitHandle
84 struct GNUNET_MESH_TransmitHandle *prev; 75 struct GNUNET_MESH_TransmitHandle *prev;
85 76
86 /** 77 /**
78 * Tunnel this message is sent over (may be NULL for control messages).
79 */
80 struct GNUNET_MESH_Tunnel *tunnel;
81
82 /**
87 * Data itself, currently points to the end of this struct if 83 * Data itself, currently points to the end of this struct if
88 * we have a message already, NULL if the message is to be 84 * we have a message already, NULL if the message is to be
89 * obtained from the callback. 85 * obtained from the callback.
90 */ 86 */
91 const struct GNUNET_MessageHeader *data; 87 const struct GNUNET_MessageHeader *data;
92 88
93 /** 89 /**
94 * Tunnel this message is sent over (may be NULL for control messages). 90 * Callback to obtain the message to transmit, or NULL if we
95 */ 91 * got the message in 'data'. Notice that messages built
96 struct GNUNET_MESH_Tunnel *tunnel; 92 * by 'notify' need to be encapsulated with information about
97 93 * the 'target'.
98 /** 94 */
99 * Callback to obtain the message to transmit, or NULL if we
100 * got the message in 'data'. Notice that messages built
101 * by 'notify' need to be encapsulated with information about
102 * the 'target'.
103 */
104 GNUNET_CONNECTION_TransmitReadyNotify notify; 95 GNUNET_CONNECTION_TransmitReadyNotify notify;
105 96
106 /** 97 /**
107 * Closure for 'notify' 98 * Closure for 'notify'
108 */ 99 */
109 void *notify_cls; 100 void *notify_cls;
110 101
111 /** 102 /**
112 * How long is this message valid. Once the timeout has been 103 * How long is this message valid. Once the timeout has been
113 * reached, the message must no longer be sent. If this 104 * reached, the message must no longer be sent. If this
114 * is a message with a 'notify' callback set, the 'notify' 105 * is a message with a 'notify' callback set, the 'notify'
115 * function should be called with 'buf' NULL and size 0. 106 * function should be called with 'buf' NULL and size 0.
116 */ 107 */
117 struct GNUNET_TIME_Absolute timeout; 108 struct GNUNET_TIME_Absolute timeout;
118 109
119 /** 110 /**
120 * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER. 111 * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER.
121 */ 112 */
122 GNUNET_SCHEDULER_TaskIdentifier timeout_task; 113 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
123 114
124 /** 115 /**
125 * Priority of the message. The queue is sorted by priority, 116 * Priority of the message. The queue is sorted by priority,
126 * control messages have the maximum priority (UINT32_MAX). 117 * control messages have the maximum priority (UINT32_MAX).
127 */ 118 */
128 uint32_t priority; 119 uint32_t priority;
129 120
130 /** 121 /**
131 * Target of the message, 0 for broadcast. This field 122 * Target of the message, 0 for broadcast. This field
132 * is only valid if 'notify' is non-NULL. 123 * is only valid if 'notify' is non-NULL.
133 */ 124 */
134 GNUNET_PEER_Id target; 125 GNUNET_PEER_Id target;
135 126
136 /** 127 /**
137 * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL. 128 * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL.
138 */ 129 */
139 size_t size; 130 size_t size;
140}; 131};
141 132
@@ -145,6 +136,7 @@ struct GNUNET_MESH_TransmitHandle
145 */ 136 */
146struct GNUNET_MESH_Handle 137struct GNUNET_MESH_Handle
147{ 138{
139
148 /** 140 /**
149 * Handle to the server connection, to send messages later 141 * Handle to the server connection, to send messages later
150 */ 142 */
@@ -187,27 +179,30 @@ struct GNUNET_MESH_Handle
187 /** 179 /**
188 * Messages to send to the service 180 * Messages to send to the service
189 */ 181 */
190 struct GNUNET_MESH_TransmitHandle *queue_head; 182 struct GNUNET_MESH_TransmitHandle *th_head;
191 struct GNUNET_MESH_TransmitHandle *queue_tail; 183 struct GNUNET_MESH_TransmitHandle *th_tail;
192 184
193 /** 185 /**
194 * tid of the next tunnel to create (to avoid reusing IDs often) 186 * tid of the next tunnel to create (to avoid reusing IDs often)
195 */ 187 */
196 MESH_TunnelNumber next_tid; 188 MESH_TunnelNumber next_tid;
197
198 unsigned int n_handlers; 189 unsigned int n_handlers;
199
200 unsigned int n_applications; 190 unsigned int n_applications;
201
202 unsigned int max_queue_size; 191 unsigned int max_queue_size;
203 192
204 /** 193 /**
205 * Have we started the task to receive messages from the service 194 * Have we started the task to receive messages from the service
206 * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message. 195 * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message.
207 */ 196 */
208 int in_receive; 197 int in_receive;
198
199 /**
200 * Number of packets queued
201 */
202 unsigned int npackets;
209}; 203};
210 204
205
211/** 206/**
212 * Opaque handle to a tunnel. 207 * Opaque handle to a tunnel.
213 */ 208 */
@@ -256,9 +251,14 @@ struct GNUNET_MESH_Tunnel
256 GNUNET_PEER_Id owner; 251 GNUNET_PEER_Id owner;
257 252
258 /** 253 /**
259 * Number of peer added to the tunnel 254 * Number of peers added to the tunnel
260 */ 255 */
261 unsigned int npeers; 256 unsigned int npeers;
257
258 /**
259 * Number of packets queued in this tunnel
260 */
261 unsigned int npackets;
262}; 262};
263 263
264 264
@@ -287,20 +287,58 @@ retrieve_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
287 return NULL; 287 return NULL;
288} 288}
289 289
290
290/** 291/**
291 * Get the length of the transmission queue 292 * Notify client that the transmission has timed out
292 * @param h mesh handle whose queue is to be measured 293 * @param cls closure
294 * @param tc task context
293 */ 295 */
294static unsigned int 296static void
295get_queue_length (struct GNUNET_MESH_Handle *h) 297timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
296{ 298{
297 struct GNUNET_MESH_TransmitHandle *q; 299 struct GNUNET_MESH_TransmitHandle *th = cls;
298 unsigned int i; 300 struct GNUNET_MESH_Handle *mesh;
301
302 mesh = th->tunnel->mesh;
303 GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
304 if (th->notify != NULL)
305 th->notify (th->notify_cls, 0, NULL);
306 GNUNET_free (th);
307 if ((NULL == mesh->th_head) && (NULL != mesh->th))
308 {
309 /* queue empty, no point in asking for transmission */
310 GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
311 mesh->th = NULL;
312 }
313}
299 314
300 /* count */
301 for (q = h->queue_head, i = 0; NULL != q; q = q->next, i++) ;
302 315
303 return i; 316/**
317 * Add a transmit handle to the transmission queue by priority and set the
318 * timeout if needed.
319 *
320 * @param h mesh handle with the queue head and tail
321 * @param q handle to the packet to be transmitted
322 */
323static void
324add_to_queue (struct GNUNET_MESH_Handle *h,
325 struct GNUNET_MESH_TransmitHandle *th)
326{
327 struct GNUNET_MESH_TransmitHandle *p;
328
329 p = h->th_head;
330 while ((NULL != p) && (th->priority < p->priority))
331 p = p->next;
332 if (NULL == p)
333 p = h->th_tail;
334 else
335 p = p->prev;
336 GNUNET_CONTAINER_DLL_insert_after (h->th_head, h->th_tail, p, th);
337 if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value == th->timeout.abs_value)
338 return;
339 th->timeout_task =
340 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
341 (th->timeout), &timeout_transmission, th);
304} 342}
305 343
306 344
@@ -334,7 +372,6 @@ process_tunnel_create (struct GNUNET_MESH_Handle *h,
334 t->cls = h->cls; 372 t->cls = h->cls;
335 t->mesh = h; 373 t->mesh = h;
336 t->tid = tid; 374 t->tid = tid;
337
338 return; 375 return;
339} 376}
340 377
@@ -473,7 +510,6 @@ msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
473 // FIXME: service disconnect, handle! 510 // FIXME: service disconnect, handle!
474 return; 511 return;
475 } 512 }
476
477 switch (ntohs (msg->type)) 513 switch (ntohs (msg->type))
478 { 514 {
479 /* Notify of a new incoming tunnel */ 515 /* Notify of a new incoming tunnel */
@@ -497,7 +533,6 @@ msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
497 "MESH: unsolicited message form service (type %d)\n", 533 "MESH: unsolicited message form service (type %d)\n",
498 ntohs (msg->type)); 534 ntohs (msg->type));
499 } 535 }
500
501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: message processed\n"); 536 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: message processed\n");
502 GNUNET_CLIENT_receive (h->client, &msg_received, h, 537 GNUNET_CLIENT_receive (h->client, &msg_received, h,
503 GNUNET_TIME_UNIT_FOREVER_REL); 538 GNUNET_TIME_UNIT_FOREVER_REL);
@@ -522,7 +557,7 @@ static size_t
522send_raw (void *cls, size_t size, void *buf) 557send_raw (void *cls, size_t size, void *buf)
523{ 558{
524 struct GNUNET_MESH_Handle *h = cls; 559 struct GNUNET_MESH_Handle *h = cls;
525 struct GNUNET_MESH_TransmitHandle *q; 560 struct GNUNET_MESH_TransmitHandle *th;
526 char *cbuf = buf; 561 char *cbuf = buf;
527 size_t ret; 562 size_t ret;
528 size_t psize; 563 size_t psize;
@@ -536,29 +571,29 @@ send_raw (void *cls, size_t size, void *buf)
536 return 0; 571 return 0;
537 } 572 }
538 ret = 0; 573 ret = 0;
539 while ((NULL != (q = h->queue_head)) && (size >= q->size)) 574 while ((NULL != (th = h->th_head)) && (size >= th->size))
540 { 575 {
541 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "mesh-api", "type: %u\n", 576 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "mesh-api", "type: %u\n",
542 ntohs (q->data->type)); 577 ntohs (th->data->type));
543 if (NULL == q->data) 578 if (NULL == th->data)
544 { 579 {
545 GNUNET_assert (NULL != q->notify); 580 GNUNET_assert (NULL != th->notify);
546 if (q->target == 0) 581 if (th->target == 0)
547 { 582 {
548 /* multicast */ 583 /* multicast */
549 struct GNUNET_MESH_Multicast mc; 584 struct GNUNET_MESH_Multicast mc;
550 585
551 GNUNET_assert (size >= sizeof (mc) + q->size); 586 GNUNET_assert (size >= sizeof (mc) + th->size);
552 psize = 587 psize =
553 q->notify (q->notify_cls, size - sizeof (mc), &cbuf[sizeof (mc)]); 588 th->notify (th->notify_cls, size - sizeof (mc), &cbuf[sizeof (mc)]);
554 if (psize > 0) 589 if (psize > 0)
555 { 590 {
556 mc.header.size = htons (sizeof (mc) + q->size); 591 mc.header.size = htons (sizeof (mc) + th->size);
557 mc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST); 592 mc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
558 mc.tid = htonl (q->tunnel->tid); 593 mc.tid = htonl (th->tunnel->tid);
559 memset (&mc.oid, 0, sizeof (struct GNUNET_PeerIdentity)); /* myself */ 594 memset (&mc.oid, 0, sizeof (struct GNUNET_PeerIdentity)); /* myself */
560 memcpy (cbuf, &mc, sizeof (mc)); 595 memcpy (cbuf, &mc, sizeof (mc));
561 psize = q->size + sizeof (mc); 596 psize = th->size + sizeof (mc);
562 } 597 }
563 } 598 }
564 else 599 else
@@ -566,42 +601,40 @@ send_raw (void *cls, size_t size, void *buf)
566 /* unicast */ 601 /* unicast */
567 struct GNUNET_MESH_Unicast uc; 602 struct GNUNET_MESH_Unicast uc;
568 603
569 GNUNET_assert (size >= sizeof (uc) + q->size); 604 GNUNET_assert (size >= sizeof (uc) + th->size);
570 psize = 605 psize =
571 q->notify (q->notify_cls, size - sizeof (uc), &cbuf[sizeof (uc)]); 606 th->notify (th->notify_cls, size - sizeof (uc), &cbuf[sizeof (uc)]);
572 if (psize > 0) 607 if (psize > 0)
573 { 608 {
574 uc.header.size = htons (sizeof (uc) + q->size); 609 uc.header.size = htons (sizeof (uc) + th->size);
575 uc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST); 610 uc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
576 uc.tid = htonl (q->tunnel->tid); 611 uc.tid = htonl (th->tunnel->tid);
577 memset (&uc.oid, 0, sizeof (struct GNUNET_PeerIdentity)); /* myself */ 612 memset (&uc.oid, 0, sizeof (struct GNUNET_PeerIdentity)); /* myself */
578 GNUNET_PEER_resolve (q->target, &uc.destination); 613 GNUNET_PEER_resolve (th->target, &uc.destination);
579 memcpy (cbuf, &uc, sizeof (uc)); 614 memcpy (cbuf, &uc, sizeof (uc));
580 psize = q->size + sizeof (uc); 615 psize = th->size + sizeof (uc);
581 } 616 }
582 } 617 }
583 } 618 }
584 else 619 else
585 { 620 {
586 memcpy (cbuf, q->data, q->size); 621 memcpy (cbuf, th->data, th->size);
587 psize = q->size; 622 psize = th->size;
588 } 623 }
589 if (q->timeout_task != GNUNET_SCHEDULER_NO_TASK) 624 if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
590 GNUNET_SCHEDULER_cancel (q->timeout_task); 625 GNUNET_SCHEDULER_cancel (th->timeout_task);
591 GNUNET_CONTAINER_DLL_remove (h->queue_head, h->queue_tail, q); 626 GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
592 GNUNET_free (q); 627 GNUNET_free (th);
593 cbuf += psize; 628 cbuf += psize;
594 size -= psize; 629 size -= psize;
595 ret += psize; 630 ret += psize;
596 } 631 }
597
598 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: size: %u\n", ret); 632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: size: %u\n", ret);
599 633 if (NULL != (th = h->th_head))
600 if (NULL != (q = h->queue_head))
601 { 634 {
602 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: next size: %u\n", q->size); 635 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: next size: %u\n", th->size);
603 h->th = 636 h->th =
604 GNUNET_CLIENT_notify_transmit_ready (h->client, q->size, 637 GNUNET_CLIENT_notify_transmit_ready (h->client, th->size,
605 GNUNET_TIME_UNIT_FOREVER_REL, 638 GNUNET_TIME_UNIT_FOREVER_REL,
606 GNUNET_YES, &send_raw, h); 639 GNUNET_YES, &send_raw, h);
607 } 640 }
@@ -616,52 +649,8 @@ send_raw (void *cls, size_t size, void *buf)
616} 649}
617 650
618 651
619static void
620timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
621{
622 struct GNUNET_MESH_TransmitHandle *q = cls;
623 struct GNUNET_MESH_Handle *mesh;
624
625 mesh = q->tunnel->mesh;
626 GNUNET_CONTAINER_DLL_remove (mesh->queue_head, mesh->queue_tail, q);
627 if (q->notify != NULL)
628 q->notify (q->notify_cls, 0, NULL); /* signal timeout */
629 GNUNET_free (q);
630 if ((NULL == mesh->queue_head) && (NULL != mesh->th))
631 {
632 /* queue empty, no point in asking for transmission */
633 GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
634 mesh->th = NULL;
635 }
636}
637
638
639/** 652/**
640 * Add a transmit handle to the transmission queue (by priority). 653 * Auxiliary function to send an already constructed packet to the service.
641 * Also manage timeout.
642 *
643 * @param h mesh handle with the queue head and tail
644 * @param q handle to add
645 */
646static void
647queue_transmit_handle (struct GNUNET_MESH_Handle *h,
648 struct GNUNET_MESH_TransmitHandle *q)
649{
650 struct GNUNET_MESH_TransmitHandle *p;
651
652 p = h->queue_head;
653 while ((NULL != p) && (q->priority < p->priority))
654 p = p->next;
655 GNUNET_CONTAINER_DLL_insert_after (h->queue_head, h->queue_tail, p->prev, q);
656 if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value != q->timeout.abs_value)
657 q->timeout_task =
658 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
659 (q->timeout), &timeout_transmission, q);
660}
661
662
663/**
664 * Auxiliary function to send a packet to the service
665 * Takes care of creating a new queue element and calling the tmt_rdy function 654 * Takes care of creating a new queue element and calling the tmt_rdy function
666 * if necessary. 655 * if necessary.
667 * @param h mesh handle 656 * @param h mesh handle
@@ -671,17 +660,17 @@ static void
671send_packet (struct GNUNET_MESH_Handle *h, 660send_packet (struct GNUNET_MESH_Handle *h,
672 const struct GNUNET_MessageHeader *msg) 661 const struct GNUNET_MessageHeader *msg)
673{ 662{
674 struct GNUNET_MESH_TransmitHandle *q; 663 struct GNUNET_MESH_TransmitHandle *th;
675 size_t msize; 664 size_t msize;
676 665
677 msize = ntohs (msg->size); 666 msize = ntohs (msg->size);
678 q = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize); 667 th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize);
679 q->priority = UINT32_MAX; 668 th->priority = UINT32_MAX;
680 q->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; 669 th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
681 q->size = msize; 670 th->size = msize;
682 q->data = (void *) &q[1]; 671 th->data = (void *) &th[1];
683 memcpy (&q[1], msg, msize); 672 memcpy (&th[1], msg, msize);
684 queue_transmit_handle (h, q); 673 add_to_queue (h, th);
685 if (NULL != h->th) 674 if (NULL != h->th)
686 return; 675 return;
687 h->th = 676 h->th =
@@ -690,6 +679,7 @@ send_packet (struct GNUNET_MESH_Handle *h,
690 GNUNET_YES, &send_raw, h); 679 GNUNET_YES, &send_raw, h);
691} 680}
692 681
682
693/******************************************************************************/ 683/******************************************************************************/
694/********************** API CALL DEFINITIONS *************************/ 684/********************** API CALL DEFINITIONS *************************/
695/******************************************************************************/ 685/******************************************************************************/
@@ -700,6 +690,9 @@ send_packet (struct GNUNET_MESH_Handle *h,
700 * @param cfg configuration to use 690 * @param cfg configuration to use
701 * @param cls closure for the various callbacks that follow 691 * @param cls closure for the various callbacks that follow
702 * (including handlers in the handlers array) 692 * (including handlers in the handlers array)
693 * @param queue_size size of the data message queue, shared among all tunnels
694 * (each tunnel is guaranteed to accept at least one message,
695 * no matter what is the status of other tunnels)
703 * @param cleaner function called when an *inbound* tunnel is destroyed 696 * @param cleaner function called when an *inbound* tunnel is destroyed
704 * @param handlers callbacks for messages we care about, NULL-terminated 697 * @param handlers callbacks for messages we care about, NULL-terminated
705 * note that the mesh is allowed to drop notifications about 698 * note that the mesh is allowed to drop notifications about
@@ -710,7 +703,8 @@ send_packet (struct GNUNET_MESH_Handle *h,
710 * NULL on error (in this case, init is never called) 703 * NULL on error (in this case, init is never called)
711 */ 704 */
712struct GNUNET_MESH_Handle * 705struct GNUNET_MESH_Handle *
713GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, 706GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
707 unsigned int queue_size, void *cls,
714 GNUNET_MESH_TunnelEndHandler cleaner, 708 GNUNET_MESH_TunnelEndHandler cleaner,
715 const struct GNUNET_MESH_MessageHandler *handlers, 709 const struct GNUNET_MESH_MessageHandler *handlers,
716 const GNUNET_MESH_ApplicationType *stypes) 710 const GNUNET_MESH_ApplicationType *stypes)
@@ -725,7 +719,7 @@ GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
725 719
726 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: GNUNET_MESH_connect()\n"); 720 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: GNUNET_MESH_connect()\n");
727 h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle)); 721 h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
728 h->max_queue_size = MESH_API_MAX_QUEUE; /* FIXME: add to arguments to 'GNUNET_MESH_connect' */ 722 h->max_queue_size = queue_size;
729 h->cleaner = cleaner; 723 h->cleaner = cleaner;
730 h->client = GNUNET_CLIENT_connect ("mesh", cfg); 724 h->client = GNUNET_CLIENT_connect ("mesh", cfg);
731 if (h->client == NULL) 725 if (h->client == NULL)
@@ -734,20 +728,16 @@ GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
734 GNUNET_free (h); 728 GNUNET_free (h);
735 return NULL; 729 return NULL;
736 } 730 }
737
738 h->cls = cls; 731 h->cls = cls;
739 h->message_handlers = handlers; 732 h->message_handlers = handlers;
740 h->applications = stypes; 733 h->applications = stypes;
741 h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_MARK; 734 h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_MARK;
742
743 /* count handlers and apps, calculate size */ 735 /* count handlers and apps, calculate size */
744 for (h->n_handlers = 0; handlers[h->n_handlers].type; h->n_handlers++) ; 736 for (h->n_handlers = 0; handlers[h->n_handlers].type; h->n_handlers++) ;
745 for (h->n_applications = 0; stypes[h->n_applications]; h->n_applications++) ; 737 for (h->n_applications = 0; stypes[h->n_applications]; h->n_applications++) ;
746
747 size = sizeof (struct GNUNET_MESH_ClientConnect); 738 size = sizeof (struct GNUNET_MESH_ClientConnect);
748 size += h->n_handlers * sizeof (uint16_t); 739 size += h->n_handlers * sizeof (uint16_t);
749 size += h->n_applications * sizeof (GNUNET_MESH_ApplicationType); 740 size += h->n_applications * sizeof (GNUNET_MESH_ApplicationType);
750
751 { 741 {
752 char buf[size]; 742 char buf[size];
753 743
@@ -763,16 +753,12 @@ GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
763 apps[napps] = h->applications[napps]; 753 apps[napps] = h->applications[napps];
764 msg->applications = htons (napps); 754 msg->applications = htons (napps);
765 msg->types = htons (ntypes); 755 msg->types = htons (ntypes);
766
767 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
768 "mesh: Sending %lu bytes long message %d types and %d apps\n", 757 "mesh: Sending %lu bytes long message %d types and %d apps\n",
769 ntohs (msg->header.size), ntypes, napps); 758 ntohs (msg->header.size), ntypes, napps);
770
771 send_packet (h, &msg->header); 759 send_packet (h, &msg->header);
772 } 760 }
773
774 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: GNUNET_MESH_connect() END\n"); 761 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: GNUNET_MESH_connect() END\n");
775
776 return h; 762 return h;
777} 763}
778 764
@@ -817,14 +803,12 @@ GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h,
817 803
818 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: Creating new tunnel\n"); 804 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: Creating new tunnel\n");
819 t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel)); 805 t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel));
820
821 t->connect_handler = connect_handler; 806 t->connect_handler = connect_handler;
822 t->disconnect_handler = disconnect_handler; 807 t->disconnect_handler = disconnect_handler;
823 t->cls = handler_cls; 808 t->cls = handler_cls;
824 t->mesh = h; 809 t->mesh = h;
825 t->tid = h->next_tid++; 810 t->tid = h->next_tid++;
826 h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_MARK; // keep in range 811 h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_MARK; // keep in range
827
828 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); 812 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
829 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); 813 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
830 msg.tunnel_id = htonl (t->tid); 814 msg.tunnel_id = htonl (t->tid);
@@ -845,15 +829,12 @@ GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tun)
845 struct GNUNET_MESH_TunnelMessage *msg; 829 struct GNUNET_MESH_TunnelMessage *msg;
846 830
847 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: Destroying tunnel\n"); 831 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: Destroying tunnel\n");
848
849 h = tun->mesh; 832 h = tun->mesh;
850 msg = GNUNET_malloc (sizeof (struct GNUNET_MESH_TunnelMessage)); 833 msg = GNUNET_malloc (sizeof (struct GNUNET_MESH_TunnelMessage));
851 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); 834 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
852 msg->header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); 835 msg->header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
853 msg->tunnel_id = htonl (tun->tid); 836 msg->tunnel_id = htonl (tun->tid);
854
855 GNUNET_free (tun); 837 GNUNET_free (tun);
856
857 send_packet (h, &msg->header); 838 send_packet (h, &msg->header);
858} 839}
859 840
@@ -881,6 +862,7 @@ GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
881 if (tunnel->peers[i] == peer_id) 862 if (tunnel->peers[i] == peer_id)
882 { 863 {
883 GNUNET_PEER_change_rc (peer_id, -1); 864 GNUNET_PEER_change_rc (peer_id, -1);
865 /* FIXME: peer was already in the tunnel */
884 return; 866 return;
885 } 867 }
886 } 868 }
@@ -888,7 +870,6 @@ GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
888 tunnel->peers = 870 tunnel->peers =
889 GNUNET_realloc (tunnel->peers, tunnel->npeers * sizeof (GNUNET_PEER_Id)); 871 GNUNET_realloc (tunnel->peers, tunnel->npeers * sizeof (GNUNET_PEER_Id));
890 tunnel->peers[tunnel->npeers - 1] = peer_id; 872 tunnel->peers[tunnel->npeers - 1] = peer_id;
891
892 msg = GNUNET_malloc (sizeof (struct GNUNET_MESH_PeerControl)); 873 msg = GNUNET_malloc (sizeof (struct GNUNET_MESH_PeerControl));
893 msg->header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); 874 msg->header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
894 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD); 875 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD);
@@ -896,9 +877,7 @@ GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
896 msg->timeout = 877 msg->timeout =
897 GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (timeout)); 878 GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (timeout));
898 memcpy (&msg->peer, peer, sizeof (struct GNUNET_PeerIdentity)); 879 memcpy (&msg->peer, peer, sizeof (struct GNUNET_PeerIdentity));
899
900 send_packet (tunnel->mesh, &msg->header); 880 send_packet (tunnel->mesh, &msg->header);
901
902// tunnel->connect_handler (tunnel->cls, peer, NULL); FIXME call this later 881// tunnel->connect_handler (tunnel->cls, peer, NULL); FIXME call this later
903// TODO: remember timeout 882// TODO: remember timeout
904 return; 883 return;
@@ -1004,26 +983,28 @@ GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
1004 GNUNET_CONNECTION_TransmitReadyNotify notify, 983 GNUNET_CONNECTION_TransmitReadyNotify notify,
1005 void *notify_cls) 984 void *notify_cls)
1006{ 985{
1007 struct GNUNET_MESH_TransmitHandle *q; 986 struct GNUNET_MESH_TransmitHandle *th;
1008 size_t overhead; 987 size_t overhead;
1009 988
1010 if (get_queue_length (tunnel->mesh) >= tunnel->mesh->max_queue_size) 989 if (tunnel->mesh->npackets >= tunnel->mesh->max_queue_size &&
990 tunnel->npackets > 0)
1011 return NULL; /* queue full */ 991 return NULL; /* queue full */
1012 992 tunnel->npackets++;
1013 q = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle)); 993 tunnel->mesh->npackets++;
1014 q->tunnel = tunnel; 994 th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
1015 q->priority = priority; 995 th->tunnel = tunnel;
1016 q->timeout = GNUNET_TIME_relative_to_absolute (maxdelay); 996 th->priority = priority;
1017 q->target = GNUNET_PEER_intern (target); 997 th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
998 th->target = GNUNET_PEER_intern (target);
1018 overhead = 999 overhead =
1019 (NULL == 1000 (NULL ==
1020 target) ? sizeof (struct GNUNET_MESH_Multicast) : sizeof (struct 1001 target) ? sizeof (struct GNUNET_MESH_Multicast) : sizeof (struct
1021 GNUNET_MESH_Unicast); 1002 GNUNET_MESH_Unicast);
1022 q->size = notify_size + overhead; 1003 th->size = notify_size + overhead;
1023 q->notify = notify; 1004 th->notify = notify;
1024 q->notify_cls = notify_cls; 1005 th->notify_cls = notify_cls;
1025 queue_transmit_handle (tunnel->mesh, q); 1006 add_to_queue (tunnel->mesh, th);
1026 return q; 1007 return th;
1027} 1008}
1028 1009
1029 1010
@@ -1040,9 +1021,9 @@ GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th)
1040 mesh = th->tunnel->mesh; 1021 mesh = th->tunnel->mesh;
1041 if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK) 1022 if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1042 GNUNET_SCHEDULER_cancel (th->timeout_task); 1023 GNUNET_SCHEDULER_cancel (th->timeout_task);
1043 GNUNET_CONTAINER_DLL_remove (mesh->queue_head, mesh->queue_tail, th); 1024 GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
1044 GNUNET_free (th); 1025 GNUNET_free (th);
1045 if ((NULL == mesh->queue_head) && (NULL != mesh->th)) 1026 if ((NULL == mesh->th_head) && (NULL != mesh->th))
1046 { 1027 {
1047 /* queue empty, no point in asking for transmission */ 1028 /* queue empty, no point in asking for transmission */
1048 GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th); 1029 GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
diff --git a/src/mesh/test_mesh_api.c b/src/mesh/test_mesh_api.c
index c60b0314e..312e72375 100644
--- a/src/mesh/test_mesh_api.c
+++ b/src/mesh/test_mesh_api.c
@@ -104,7 +104,7 @@ test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
104 struct GNUNET_MESH_Tunnel *t; 104 struct GNUNET_MESH_Tunnel *t;
105 105
106 test_task = (GNUNET_SCHEDULER_TaskIdentifier) 0; 106 test_task = (GNUNET_SCHEDULER_TaskIdentifier) 0;
107 mesh = GNUNET_MESH_connect (cfg, NULL, NULL, handlers, app); 107 mesh = GNUNET_MESH_connect (cfg, 10, NULL, NULL, handlers, app);
108 if (NULL == mesh) 108 if (NULL == mesh)
109 { 109 {
110 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh :(\n"); 110 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh :(\n");
@@ -120,7 +120,7 @@ test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
120 GNUNET_MESH_tunnel_destroy (t); 120 GNUNET_MESH_tunnel_destroy (t);
121 121
122 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply 122 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
123 (GNUNET_TIME_UNIT_SECONDS, 5), &do_shutdown, 123 (GNUNET_TIME_UNIT_SECONDS, 1), &do_shutdown,
124 NULL); 124 NULL);
125} 125}
126 126
diff --git a/src/mesh/test_mesh_small.c b/src/mesh/test_mesh_small.c
index cea1bef56..53f00a24f 100644
--- a/src/mesh/test_mesh_small.c
+++ b/src/mesh/test_mesh_small.c
@@ -263,7 +263,7 @@ connect_mesh_service (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
264 "connecting to mesh service of peer %s\n", GNUNET_i2s (&d->id)); 264 "connecting to mesh service of peer %s\n", GNUNET_i2s (&d->id));
265#endif 265#endif
266 h = GNUNET_MESH_connect (d->cfg, NULL, &tunnel_cleaner, handlers, &app); 266 h = GNUNET_MESH_connect (d->cfg, 10, NULL, &tunnel_cleaner, handlers, &app);
267#if VERBOSE 267#if VERBOSE
268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connected to mesh service of peer %s\n", 268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connected to mesh service of peer %s\n",
269 GNUNET_i2s (&d->id)); 269 GNUNET_i2s (&d->id));