- partial change, broken build system on laptop
[oweals/gnunet.git] / src / mesh / mesh_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011 Christian Grothoff (and other contributing authors)
4      GNUnet is free software; you can redistribute it and/or modify
5      it under the terms of the GNU General Public License as published
6      by the Free Software Foundation; either version 3, or (at your
7      option) any later version.
8      GNUnet is distributed in the hope that it will be useful, but
9      WITHOUT ANY WARRANTY; without even the implied warranty of
10      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11      General Public License for more details.
12      You should have received a copy of the GNU General Public License
13      along with GNUnet; see the file COPYING.  If not, write to the
14      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15      Boston, MA 02111-1307, USA.
16 */
17
18 /**
19  * @file mesh/mesh_api.c
20  * @brief mesh api: client implementation of mesh service
21  * @author Bartlomiej Polot
22  *
23  * STRUCTURE:
24  * - CONSTANTS
25  * - DATA STRUCTURES
26  * - AUXILIARY FUNCTIONS
27  * - RECEIVE HANDLERS
28  * - SEND FUNCTIONS
29  * - API CALL DEFINITIONS
30  *
31  * TODO: add regex to reconnect
32  */
33 #include "platform.h"
34 #include "gnunet_common.h"
35 #include "gnunet_client_lib.h"
36 #include "gnunet_util_lib.h"
37 #include "gnunet_peer_lib.h"
38 #include "gnunet_mesh_service.h"
39 #include "mesh.h"
40 #include "mesh_protocol.h"
41
42 #define LOG(kind,...) GNUNET_log_from (kind, "mesh-api",__VA_ARGS__)
43
44
45 /******************************************************************************/
46 /************************      DATA STRUCTURES     ****************************/
47 /******************************************************************************/
48
49 /**
50  * Transmission queue to the service
51  */
52 struct GNUNET_MESH_TransmitHandle
53 {
54
55     /**
56      * Double Linked list
57      */
58   struct GNUNET_MESH_TransmitHandle *next;
59
60     /**
61      * Double Linked list
62      */
63   struct GNUNET_MESH_TransmitHandle *prev;
64
65     /**
66      * Tunnel this message is sent on / for (may be NULL for control messages).
67      */
68   struct GNUNET_MESH_Tunnel *tunnel;
69
70     /**
71      * Callback to obtain the message to transmit, or NULL if we
72      * got the message in 'data'.  Notice that messages built
73      * by 'notify' need to be encapsulated with information about
74      * the 'target'.
75      */
76   GNUNET_CONNECTION_TransmitReadyNotify notify;
77
78     /**
79      * Closure for 'notify'
80      */
81   void *notify_cls;
82
83     /**
84      * How long is this message valid.  Once the timeout has been
85      * reached, the message must no longer be sent.  If this
86      * is a message with a 'notify' callback set, the 'notify'
87      * function should be called with 'buf' NULL and size 0.
88      */
89   struct GNUNET_TIME_Absolute timeout;
90
91     /**
92      * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER.
93      */
94   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
95
96     /**
97      * Priority of the message.  The queue is sorted by priority,
98      * control messages have the maximum priority (UINT32_MAX).
99      */
100   uint32_t priority;
101
102     /**
103      * Target of the message, 0 for multicast.  This field
104      * is only valid if 'notify' is non-NULL.
105      */
106   GNUNET_PEER_Id target;
107
108     /**
109      * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL.
110      */
111   size_t size;
112 };
113
114
115 /**
116  * Opaque handle to the service.
117  */
118 struct GNUNET_MESH_Handle
119 {
120
121     /**
122      * Handle to the server connection, to send messages later
123      */
124   struct GNUNET_CLIENT_Connection *client;
125
126     /**
127      * Set of handlers used for processing incoming messages in the tunnels
128      */
129   const struct GNUNET_MESH_MessageHandler *message_handlers;
130
131     /**
132      * Set of applications that should be claimed to be offered at this node.
133      * Note that this is just informative, the appropiate handlers must be
134      * registered independently and the mapping is up to the developer of the
135      * client application.
136      */
137   const GNUNET_MESH_ApplicationType *applications;
138
139     /**
140      * Double linked list of the tunnels this client is connected to.
141      */
142   struct GNUNET_MESH_Tunnel *tunnels_head;
143   struct GNUNET_MESH_Tunnel *tunnels_tail;
144
145     /**
146      * Callback for inbound tunnel creation
147      */
148   GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
149
150     /**
151      * Callback for inbound tunnel disconnection
152      */
153   GNUNET_MESH_TunnelEndHandler *cleaner;
154
155     /**
156      * Handle to cancel pending transmissions in case of disconnection
157      */
158   struct GNUNET_CLIENT_TransmitHandle *th;
159
160     /**
161      * Closure for all the handlers given by the client
162      */
163   void *cls;
164
165     /**
166      * Messages to send to the service
167      */
168   struct GNUNET_MESH_TransmitHandle *th_head;
169   struct GNUNET_MESH_TransmitHandle *th_tail;
170
171     /**
172      * tid of the next tunnel to create (to avoid reusing IDs often)
173      */
174   MESH_TunnelNumber next_tid;
175   unsigned int n_handlers;
176   unsigned int n_applications;
177   unsigned int max_queue_size;
178
179     /**
180      * Have we started the task to receive messages from the service
181      * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message.
182      */
183   int in_receive;
184
185     /**
186      * Number of packets queued
187      */
188   unsigned int npackets;
189
190   /**
191    * Configuration given by the client, in case of reconnection
192    */
193   const struct GNUNET_CONFIGURATION_Handle *cfg;
194
195   /**
196    * Time to the next reconnect in case one reconnect fails
197    */
198   struct GNUNET_TIME_Relative reconnect_time;
199   
200   /**
201    * Task for trying to reconnect.
202    */
203   GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
204 };
205
206
207 /**
208  * Description of a peer
209  */
210 struct GNUNET_MESH_Peer
211 {
212     /**
213      * ID of the peer in short form
214      */
215   GNUNET_PEER_Id id;
216
217   /**
218    * Tunnel this peer belongs to
219    */
220   struct GNUNET_MESH_Tunnel *t;
221
222   /**
223    * Flag indicating whether service has informed about its connection
224    */
225   int connected;
226
227 };
228
229
230 /**
231  * Opaque handle to a tunnel.
232  */
233 struct GNUNET_MESH_Tunnel
234 {
235
236     /**
237      * DLL
238      */
239   struct GNUNET_MESH_Tunnel *next;
240   struct GNUNET_MESH_Tunnel *prev;
241
242     /**
243      * Callback to execute when peers connect to the tunnel
244      */
245   GNUNET_MESH_PeerConnectHandler connect_handler;
246
247     /**
248      * Callback to execute when peers disconnect from the tunnel
249      */
250   GNUNET_MESH_PeerDisconnectHandler disconnect_handler;
251
252     /**
253      * Closure for the connect/disconnect handlers
254      */
255   void *cls;
256
257     /**
258      * Handle to the mesh this tunnel belongs to
259      */
260   struct GNUNET_MESH_Handle *mesh;
261
262     /**
263      * Local ID of the tunnel
264      */
265   MESH_TunnelNumber tid;
266
267     /**
268      * Owner of the tunnel. 0 if the tunnel is the local client.
269      */
270   GNUNET_PEER_Id owner;
271
272     /**
273      * All peers added to the tunnel
274      */
275   struct GNUNET_MESH_Peer **peers;
276
277   /**
278    * List of application types that have been requested for this tunnel
279    */
280   GNUNET_MESH_ApplicationType *apps;
281
282   /**
283    * Any data the caller wants to put in here
284    */
285   void *ctx;
286
287   /**
288      * Number of peers added to the tunnel
289      */
290   unsigned int npeers;
291
292     /**
293      * Number of packets queued in this tunnel
294      */
295   unsigned int npackets;
296
297     /**
298      * Number of applications requested this tunnel
299      */
300   unsigned int napps;
301
302     /**
303      * Is the tunnel throttled to the slowest peer?
304      */
305   int speed_min;
306
307 };
308
309
310 /******************************************************************************/
311 /***********************     AUXILIARY FUNCTIONS      *************************/
312 /******************************************************************************/
313
314 /**
315  * Get the tunnel handler for the tunnel specified by id from the given handle
316  * @param h Mesh handle
317  * @param tid ID of the wanted tunnel
318  * @return handle to the required tunnel or NULL if not found
319  */
320 static struct GNUNET_MESH_Tunnel *
321 retrieve_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
322 {
323   struct GNUNET_MESH_Tunnel *t;
324
325   t = h->tunnels_head;
326   while (t != NULL)
327   {
328     if (t->tid == tid)
329       return t;
330     t = t->next;
331   }
332   return NULL;
333 }
334
335
336 /**
337  * Create a new tunnel and insert it in the tunnel list of the mesh handle
338  * @param h Mesh handle
339  * @param tid desired tid of the tunnel, 0 to assign one automatically
340  * @return handle to the created tunnel
341  */
342 static struct GNUNET_MESH_Tunnel *
343 create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
344 {
345   struct GNUNET_MESH_Tunnel *t;
346
347   t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel));
348   GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t);
349   t->mesh = h;
350   if (0 == tid)
351   {
352     t->tid = h->next_tid;
353     while (NULL != retrieve_tunnel (h, h->next_tid))
354     {
355       h->next_tid++;
356       h->next_tid &= ~GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
357       h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
358     }
359   }
360   else
361   {
362     t->tid = tid;
363   }
364   return t;
365 }
366
367
368 /**
369  * Destroy the specified tunnel.
370  * - Destroys all peers, calling the disconnect callback on each if needed
371  * - Cancels all outgoing traffic for that tunnel, calling respective notifys
372  * - Calls cleaner if tunnel was inbound
373  * - Frees all memory used
374  *
375  * @param t Pointer to the tunnel.
376  * @param call_cleaner Whether to call the cleaner handler.
377  *
378  * @return Handle to the required tunnel or NULL if not found.
379  */
380 static void
381 destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner)
382 {
383   struct GNUNET_MESH_Handle *h;
384   struct GNUNET_PeerIdentity pi;
385   struct GNUNET_MESH_TransmitHandle *th;
386   struct GNUNET_MESH_TransmitHandle *next;
387   unsigned int i;
388
389   LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid);
390
391   if (NULL == t)
392   {
393     GNUNET_break (0);
394     return;
395   }
396   h = t->mesh;
397
398   /* disconnect all peers */
399   GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t);
400   for (i = 0; i < t->npeers; i++)
401   {
402     if ( (NULL != t->disconnect_handler) && t->peers[i]->connected)
403     {
404       GNUNET_PEER_resolve (t->peers[i]->id, &pi);
405       t->disconnect_handler (t->cls, &pi);
406     }
407     GNUNET_PEER_change_rc (t->peers[i]->id, -1);
408     GNUNET_free (t->peers[i]);
409   }
410
411   /* signal tunnel destruction */
412   if ( (NULL != h->cleaner) && (0 != t->owner) && (GNUNET_YES == call_cleaner) )
413     h->cleaner (h->cls, t, t->ctx);
414
415   /* check that clients did not leave messages behind in the queue */
416   for (th = h->th_head; NULL != th; th = next)
417   {
418     next = th->next;
419     if (th->tunnel != t)
420       continue;
421     /* Clients should have aborted their requests already.
422      * Management traffic should be ok, as clients can't cancel that */
423     GNUNET_break (NULL == th->notify);
424     GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
425
426     /* clean up request */
427     if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
428       GNUNET_SCHEDULER_cancel (th->timeout_task);
429     GNUNET_free (th);    
430   }
431
432   /* if there are no more pending requests with mesh service, cancel active request */
433   /* Note: this should be unnecessary... */
434   if ( (NULL == h->th_head) && (NULL != h->th))
435   {
436     GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
437     h->th = NULL;
438   }
439
440
441   if (t->npeers > 0)
442     GNUNET_free (t->peers);
443   if (0 != t->owner)
444     GNUNET_PEER_change_rc (t->owner, -1);
445   if (0 != t->napps && t->apps)
446     GNUNET_free (t->apps);
447   GNUNET_free (t);
448   return;
449 }
450
451
452 /**
453  * Get the peer descriptor for the peer with id from the given tunnel
454  * @param t Tunnel handle
455  * @param id Short form ID of the wanted peer
456  * @return handle to the requested peer or NULL if not found
457  */
458 static struct GNUNET_MESH_Peer *
459 retrieve_peer (struct GNUNET_MESH_Tunnel *t, GNUNET_PEER_Id id)
460 {
461   unsigned int i;
462
463   for (i = 0; i < t->npeers; i++)
464     if (t->peers[i]->id == id)
465       return t->peers[i];
466   return NULL;
467 }
468
469
470 /**
471  * Add a peer into a tunnel
472  * @param t Tunnel handle
473  * @param pi Full ID of the new peer
474  * @return handle to the newly created peer
475  */
476 static struct GNUNET_MESH_Peer *
477 add_peer_to_tunnel (struct GNUNET_MESH_Tunnel *t,
478                     const struct GNUNET_PeerIdentity *pi)
479 {
480   struct GNUNET_MESH_Peer *p;
481   GNUNET_PEER_Id id;
482
483   if (0 != t->owner)
484   {
485     GNUNET_break (0);
486     return NULL;
487   }
488   id = GNUNET_PEER_intern (pi);
489
490   p = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
491   p->id = id;
492   p->t = t;
493   GNUNET_array_append (t->peers, t->npeers, p);
494   return p;
495 }
496
497
498 /**
499  * Remove a peer from a tunnel
500  * @param p Peer handle
501  */
502 static void
503 remove_peer_from_tunnel (struct GNUNET_MESH_Peer *p)
504 {
505   unsigned int i;
506
507   for (i = 0; i < p->t->npeers; i++)
508   {
509     if (p->t->peers[i] == p)
510       break;
511   }
512   if (i == p->t->npeers)
513   {
514     GNUNET_break (0);
515     return;
516   }
517   p->t->peers[i] = p->t->peers[p->t->npeers - 1];
518   GNUNET_array_grow (p->t->peers, p->t->npeers, p->t->npeers - 1);
519 }
520
521
522 /**
523  * Notify client that the transmission has timed out
524  * @param cls closure
525  * @param tc task context
526  */
527 static void
528 timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
529 {
530   struct GNUNET_MESH_TransmitHandle *th = cls;
531   struct GNUNET_MESH_Handle *mesh;
532
533   mesh = th->tunnel->mesh;
534   GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
535   if (th->notify != NULL)
536     th->notify (th->notify_cls, 0, NULL);
537   GNUNET_free (th);
538   if ((NULL == mesh->th_head) && (NULL != mesh->th))
539   {
540     /* queue empty, no point in asking for transmission */
541     GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
542     mesh->th = NULL;
543   }
544 }
545
546
547 /**
548  * Add a transmit handle to the transmission queue by priority and set the
549  * timeout if needed.
550  *
551  * @param h mesh handle with the queue head and tail
552  * @param th handle to the packet to be transmitted
553  */
554 static void
555 add_to_queue (struct GNUNET_MESH_Handle *h,
556               struct GNUNET_MESH_TransmitHandle *th)
557 {
558   struct GNUNET_MESH_TransmitHandle *p;
559
560   p = h->th_head;
561   while ((NULL != p) && (th->priority <= p->priority))
562     p = p->next;
563   if (NULL == p)
564     p = h->th_tail;
565   else
566     p = p->prev;
567   GNUNET_CONTAINER_DLL_insert_after (h->th_head, h->th_tail, p, th);
568   if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value == th->timeout.abs_value)
569     return;
570   th->timeout_task =
571       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
572                                     (th->timeout), &timeout_transmission, th);
573 }
574
575
576 /**
577  * Auxiliary function to send an already constructed packet to the service.
578  * Takes care of creating a new queue element, copying the message and
579  * calling the tmt_rdy function if necessary.
580  *
581  * @param h mesh handle
582  * @param msg message to transmit
583  * @param tunnel tunnel this send is related to (NULL if N/A)
584  */
585 static void
586 send_packet (struct GNUNET_MESH_Handle *h,
587              const struct GNUNET_MessageHeader *msg,
588              struct GNUNET_MESH_Tunnel *tunnel);
589
590
591 /**
592  * Reconnect callback: tries to reconnect again after a failer previous
593  * reconnecttion
594  * @param cls closure (mesh handle)
595  * @param tc task context
596  */
597 static void
598 reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
599
600
601 /**
602  * Send a connect packet to the service with the applications and types
603  * requested by the user.
604  *
605  * @param h The mesh handle.
606  *
607  */
608 static void
609 send_connect (struct GNUNET_MESH_Handle *h)
610 {
611   size_t size;
612
613   size = sizeof (struct GNUNET_MESH_ClientConnect);
614   size += h->n_applications * sizeof (GNUNET_MESH_ApplicationType);
615   size += h->n_handlers * sizeof (uint16_t);
616   {
617     char buf[size] GNUNET_ALIGN;
618     struct GNUNET_MESH_ClientConnect *msg;
619     GNUNET_MESH_ApplicationType *apps;
620     uint16_t napps;
621     uint16_t *types;
622     uint16_t ntypes;
623
624     /* build connection packet */
625     msg = (struct GNUNET_MESH_ClientConnect *) buf;
626     msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT);
627     msg->header.size = htons (size);
628     apps = (GNUNET_MESH_ApplicationType *) &msg[1];
629     for (napps = 0; napps < h->n_applications; napps++)
630     {
631       apps[napps] = htonl (h->applications[napps]);
632       LOG (GNUNET_ERROR_TYPE_DEBUG, " app %u\n", h->applications[napps]);
633     }
634     types = (uint16_t *) & apps[napps];
635     for (ntypes = 0; ntypes < h->n_handlers; ntypes++)
636       types[ntypes] = htons (h->message_handlers[ntypes].type);
637     msg->applications = htons (napps);
638     msg->types = htons (ntypes);
639     LOG (GNUNET_ERROR_TYPE_DEBUG,
640          "Sending %lu bytes long message %d types and %d apps\n",
641          ntohs (msg->header.size), ntypes, napps);
642     send_packet (h, &msg->header, NULL);
643   }
644 }
645
646
647 /**
648  * Reconnect to the service, retransmit all infomation to try to restore the
649  * original state.
650  *
651  * @param h handle to the mesh
652  *
653  * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
654  */
655 static int
656 do_reconnect (struct GNUNET_MESH_Handle *h)
657 {
658   struct GNUNET_MESH_Tunnel *t;
659   unsigned int i;
660
661   LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
662   LOG (GNUNET_ERROR_TYPE_DEBUG, "*******   RECONNECT   *******\n");
663   LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
664
665   h->in_receive = GNUNET_NO;
666   /* disconnect */
667   if (NULL != h->th)
668   {
669     GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
670     h->th = NULL;
671   }
672   if (NULL != h->client)
673   {
674     GNUNET_CLIENT_disconnect (h->client);
675   }
676
677   /* connect again */
678   h->client = GNUNET_CLIENT_connect ("mesh", h->cfg);
679   if (h->client == NULL)
680   {
681     h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
682                                                       &reconnect_cbk, h);
683     h->reconnect_time =
684         GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
685                                   GNUNET_TIME_relative_multiply
686                                   (h->reconnect_time, 2));
687     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Next retry in %sms\n",
688          GNUNET_TIME_relative_to_string (h->reconnect_time));
689     GNUNET_break (0);
690     return GNUNET_NO;
691   }
692   else
693   {
694     h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
695   }
696   send_connect (h);
697   /* Rebuild all tunnels */
698   for (t = h->tunnels_head; NULL != t; t = t->next)
699   {
700     struct GNUNET_MESH_TunnelMessage tmsg;
701     struct GNUNET_MESH_PeerControl pmsg;
702
703     if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
704     {
705       /* Tunnel was created by service (incoming tunnel) */
706       /* TODO: Notify service of missing tunnel, to request
707        * creator to recreate path (find a path to him via DHT?)
708        */
709       continue;
710     }
711     tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
712     tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
713     tmsg.tunnel_id = htonl (t->tid);
714     send_packet (h, &tmsg.header, t);
715
716     pmsg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
717     pmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
718     pmsg.tunnel_id = htonl (t->tid);
719
720     /* Reconnect all peers */
721     for (i = 0; i < t->npeers; i++)
722     {
723       GNUNET_PEER_resolve (t->peers[i]->id, &pmsg.peer);
724       if (NULL != t->disconnect_handler && t->peers[i]->connected)
725         t->disconnect_handler (t->cls, &pmsg.peer);
726       /* If the tunnel was "by type", dont connect individual peers */
727       if (0 == t->napps)
728         send_packet (t->mesh, &pmsg.header, t);
729     }
730     /* Reconnect all types, if any  */
731     for (i = 0; i < t->napps; i++)
732     {
733       struct GNUNET_MESH_ConnectPeerByType msg;
734
735       msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
736       msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
737       msg.tunnel_id = htonl (t->tid);
738       msg.type = htonl (t->apps[i]);
739       send_packet (t->mesh, &msg.header, t);
740     }
741   }
742   return GNUNET_YES;
743 }
744
745 /**
746  * Reconnect callback: tries to reconnect again after a failer previous
747  * reconnecttion
748  * @param cls closure (mesh handle)
749  * @param tc task context
750  */
751 static void
752 reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
753 {
754   struct GNUNET_MESH_Handle *h = cls;
755
756   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
757   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
758     return;
759   do_reconnect (h);
760 }
761
762
763 /**
764  * Reconnect to the service, retransmit all infomation to try to restore the
765  * original state.
766  *
767  * @param h handle to the mesh
768  *
769  * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
770  */
771 static void
772 reconnect (struct GNUNET_MESH_Handle *h)
773 {
774   LOG (GNUNET_ERROR_TYPE_DEBUG, "Requested RECONNECT\n");
775   if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task)
776     h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
777                                                       &reconnect_cbk, h);
778 }
779
780
781 /******************************************************************************/
782 /***********************      RECEIVE HANDLERS     ****************************/
783 /******************************************************************************/
784
785 /**
786  * Process the new tunnel notification and add it to the tunnels in the handle
787  *
788  * @param h     The mesh handle
789  * @param msg   A message with the details of the new incoming tunnel
790  */
791 static void
792 process_tunnel_created (struct GNUNET_MESH_Handle *h,
793                         const struct GNUNET_MESH_TunnelNotification *msg)
794 {
795   struct GNUNET_MESH_Tunnel *t;
796   MESH_TunnelNumber tid;
797
798   tid = ntohl (msg->tunnel_id);
799   if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
800   {
801     GNUNET_break (0);
802     return;
803   }
804   if (NULL != h->new_tunnel)
805   {
806     struct GNUNET_ATS_Information atsi;
807
808     t = create_tunnel (h, tid);
809     t->owner = GNUNET_PEER_intern (&msg->peer);
810     t->npeers = 1;
811     t->peers = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer *));
812     t->peers[0] = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
813     t->peers[0]->t = t;
814     t->peers[0]->connected = 1;
815     t->peers[0]->id = t->owner;
816     GNUNET_PEER_change_rc (t->owner, 1);
817     t->mesh = h;
818     t->tid = tid;
819     atsi.type = 0;
820     atsi.value = 0;
821     t->ctx = h->new_tunnel (h->cls, t, &msg->peer, &atsi);
822     LOG (GNUNET_ERROR_TYPE_DEBUG, "new incoming tunnel %X\n", t->tid);
823   }
824   else
825   {
826     struct GNUNET_MESH_TunnelMessage d_msg;
827
828     LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming tunnels\n");
829
830     d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
831     d_msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
832     d_msg.tunnel_id = msg->tunnel_id;
833
834     send_packet (h, &d_msg.header, NULL);
835   }
836   return;
837 }
838
839
840 /**
841  * Process the tunnel destroy notification and free associated resources
842  *
843  * @param h     The mesh handle
844  * @param msg   A message with the details of the tunnel being destroyed
845  */
846 static void
847 process_tunnel_destroy (struct GNUNET_MESH_Handle *h,
848                         const struct GNUNET_MESH_TunnelMessage *msg)
849 {
850   struct GNUNET_MESH_Tunnel *t;
851   MESH_TunnelNumber tid;
852
853   tid = ntohl (msg->tunnel_id);
854   t = retrieve_tunnel (h, tid);
855
856   if (NULL == t)
857   {
858     return;
859   }
860   if (0 == t->owner)
861   {
862     GNUNET_break (0);
863   }
864   LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid);
865   destroy_tunnel (t, GNUNET_YES);
866   return;
867 }
868
869
870 /**
871  * Process the new peer event and notify the upper level of it
872  *
873  * @param h     The mesh handle
874  * @param msg   A message with the details of the peer event
875  */
876 static void
877 process_peer_event (struct GNUNET_MESH_Handle *h,
878                     const struct GNUNET_MESH_PeerControl *msg)
879 {
880   struct GNUNET_MESH_Tunnel *t;
881   struct GNUNET_MESH_Peer *p;
882   struct GNUNET_ATS_Information atsi;
883   GNUNET_PEER_Id id;
884   uint16_t size;
885
886   LOG (GNUNET_ERROR_TYPE_DEBUG, "processig peer event\n");
887   size = ntohs (msg->header.size);
888   if (size != sizeof (struct GNUNET_MESH_PeerControl))
889   {
890     GNUNET_break (0);
891     return;
892   }
893   t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
894   if (NULL == t)
895   {
896     GNUNET_break (0);
897     return;
898   }
899   id = GNUNET_PEER_search (&msg->peer);
900   if ((p = retrieve_peer (t, id)) == NULL)
901     p = add_peer_to_tunnel (t, &msg->peer);
902   if (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD == ntohs (msg->header.type))
903   {
904     LOG (GNUNET_ERROR_TYPE_DEBUG, "adding peer\n");
905     if (NULL != t->connect_handler)
906     {
907       atsi.type = 0;
908       atsi.value = 0;
909       t->connect_handler (t->cls, &msg->peer, &atsi);
910     }
911     p->connected = 1;
912   }
913   else
914   {
915     LOG (GNUNET_ERROR_TYPE_DEBUG, "removing peer\n");
916     if (NULL != t->disconnect_handler && p->connected)
917     {
918       t->disconnect_handler (t->cls, &msg->peer);
919     }
920     remove_peer_from_tunnel (p);
921     GNUNET_free (p);
922   }
923   LOG (GNUNET_ERROR_TYPE_DEBUG, "processing peer event END\n");
924 }
925
926
927 /**
928  * Process the incoming data packets
929  *
930  * @param h         The mesh handle
931  * @param message   A message encapsulating the data
932  * 
933  * @return GNUNET_YES if everything went fine
934  *         GNUNET_NO if client closed connection (h no longer valid)
935  */
936 static int
937 process_incoming_data (struct GNUNET_MESH_Handle *h,
938                        const struct GNUNET_MessageHeader *message)
939 {
940   const struct GNUNET_MessageHeader *payload;
941   const struct GNUNET_MESH_MessageHandler *handler;
942   const struct GNUNET_PeerIdentity *peer;
943   struct GNUNET_MESH_Unicast *ucast;
944   struct GNUNET_MESH_Multicast *mcast;
945   struct GNUNET_MESH_ToOrigin *to_orig;
946   struct GNUNET_MESH_Tunnel *t;
947   unsigned int i;
948   uint16_t type;
949
950   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n");
951   type = ntohs (message->type);
952   switch (type)
953   {
954   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
955     ucast = (struct GNUNET_MESH_Unicast *) message;
956
957     t = retrieve_tunnel (h, ntohl (ucast->tid));
958     payload = (struct GNUNET_MessageHeader *) &ucast[1];
959     peer = &ucast->oid;
960     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ucast on tunnel %s [%X]\n",
961          GNUNET_i2s (peer), ntohl (ucast->tid));
962     break;
963   case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
964     mcast = (struct GNUNET_MESH_Multicast *) message;
965     t = retrieve_tunnel (h, ntohl (mcast->tid));
966     payload = (struct GNUNET_MessageHeader *) &mcast[1];
967     peer = &mcast->oid;
968     LOG (GNUNET_ERROR_TYPE_DEBUG, "  mcast on tunnel %s [%X]\n",
969          GNUNET_i2s (peer), ntohl (mcast->tid));
970     break;
971   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
972     to_orig = (struct GNUNET_MESH_ToOrigin *) message;
973     t = retrieve_tunnel (h, ntohl (to_orig->tid));
974     payload = (struct GNUNET_MessageHeader *) &to_orig[1];
975     peer = &to_orig->sender;
976     LOG (GNUNET_ERROR_TYPE_DEBUG, "  torig on tunnel %s [%X]\n",
977          GNUNET_i2s (peer), ntohl (to_orig->tid));
978     break;
979   default:
980     GNUNET_break (0);
981     return GNUNET_YES;
982   }
983   if (NULL == t)
984   {
985     /* Tunnel was ignored, probably service didn't get it yet */
986     return GNUNET_YES;
987   }
988   type = ntohs (payload->type);
989   for (i = 0; i < h->n_handlers; i++)
990   {
991     handler = &h->message_handlers[i];
992     if (handler->type == type)
993     {
994       struct GNUNET_ATS_Information atsi;
995
996       atsi.type = 0;
997       atsi.value = 0;
998       if (GNUNET_OK !=
999           handler->callback (h->cls, t, &t->ctx, peer, payload, &atsi))
1000       {
1001         LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH: callback caused disconnection\n");
1002         GNUNET_MESH_disconnect (h);
1003         return GNUNET_NO;
1004       }
1005       else
1006       {
1007         LOG (GNUNET_ERROR_TYPE_DEBUG,
1008              "MESH: callback completed successfully\n");
1009
1010       }
1011     }
1012   }
1013   return GNUNET_YES;
1014 }
1015
1016
1017 /**
1018  * Function to process all messages received from the service
1019  *
1020  * @param cls closure
1021  * @param msg message received, NULL on timeout or fatal error
1022  */
1023 static void
1024 msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
1025 {
1026   struct GNUNET_MESH_Handle *h = cls;
1027
1028   if (msg == NULL)
1029   {
1030     LOG (GNUNET_ERROR_TYPE_DEBUG, "Received NULL msg\n");
1031     reconnect (h);
1032     return;
1033   }
1034   LOG (GNUNET_ERROR_TYPE_DEBUG, "received a message type %hu from MESH\n",
1035        ntohs (msg->type));
1036   switch (ntohs (msg->type))
1037   {
1038     /* Notify of a new incoming tunnel */
1039   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE:
1040     process_tunnel_created (h, (struct GNUNET_MESH_TunnelNotification *) msg);
1041     break;
1042     /* Notify of a tunnel disconnection */
1043   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1044     process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg);
1045     break;
1046     /* Notify of a new peer or a peer disconnect in the tunnel */
1047   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD:
1048   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL:
1049     process_peer_event (h, (struct GNUNET_MESH_PeerControl *) msg);
1050     break;
1051     /* Notify of a new data packet in the tunnel */
1052   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1053   case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1054   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1055     if (GNUNET_NO == process_incoming_data (h, msg))
1056       return;
1057     break;
1058     /* We shouldn't get any other packages, log and ignore */
1059   default:
1060     LOG (GNUNET_ERROR_TYPE_WARNING,
1061          "MESH: unsolicited message form service (type %d)\n",
1062          ntohs (msg->type));
1063   }
1064   LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n");
1065   GNUNET_CLIENT_receive (h->client, &msg_received, h,
1066                          GNUNET_TIME_UNIT_FOREVER_REL);
1067 }
1068
1069
1070 /******************************************************************************/
1071 /************************       SEND FUNCTIONS     ****************************/
1072 /******************************************************************************/
1073
1074 /**
1075  * Function called to send a message to the service.
1076  * "buf" will be NULL and "size" zero if the socket was closed for writing in
1077  * the meantime.
1078  *
1079  * @param cls closure, the mesh handle
1080  * @param size number of bytes available in buf
1081  * @param buf where the callee should write the connect message
1082  * @return number of bytes written to buf
1083  */
1084 static size_t
1085 send_callback (void *cls, size_t size, void *buf)
1086 {
1087   struct GNUNET_MESH_Handle *h = cls;
1088   struct GNUNET_MESH_TransmitHandle *th;
1089   char *cbuf = buf;
1090   size_t tsize;
1091   size_t psize;
1092
1093   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() Buffer %u\n", size);
1094   h->th = NULL;
1095   if ((0 == size) || (NULL == buf))
1096   {
1097     LOG (GNUNET_ERROR_TYPE_DEBUG, "Received NULL callback\n");
1098     reconnect (h);
1099     return 0;
1100   }
1101   tsize = 0;
1102   while ((NULL != (th = h->th_head)) && (size >= th->size))
1103   {
1104     if (NULL != th->notify)
1105     {
1106       if (th->tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1107       {
1108         /* traffic to origin */
1109         struct GNUNET_MESH_ToOrigin to;
1110         struct GNUNET_MessageHeader *mh;
1111
1112         GNUNET_assert (size >= th->size);
1113         mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (to)];
1114         psize = th->notify (th->notify_cls, size - sizeof (to), mh);
1115         LOG (GNUNET_ERROR_TYPE_DEBUG, "  to origin, type %u\n",
1116              ntohs (mh->type));
1117         if (psize > 0)
1118         {
1119           psize += sizeof (to);
1120           GNUNET_assert (size >= psize);
1121           to.header.size = htons (psize);
1122           to.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
1123           to.tid = htonl (th->tunnel->tid);
1124           memset (&to.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1125           memset (&to.sender, 0, sizeof (struct GNUNET_PeerIdentity));
1126           memcpy (cbuf, &to, sizeof (to));
1127         }
1128       }
1129       else if (th->target == 0)
1130       {
1131         /* multicast */
1132         struct GNUNET_MESH_Multicast mc;
1133         struct GNUNET_MessageHeader *mh;
1134
1135         GNUNET_assert (size >= th->size);
1136         mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (mc)];
1137         psize = th->notify (th->notify_cls, size - sizeof (mc), mh);
1138         LOG (GNUNET_ERROR_TYPE_DEBUG, "  multicast, type %u\n",
1139              ntohs (mh->type));
1140         if (psize > 0)
1141         {
1142           psize += sizeof (mc);
1143           GNUNET_assert (size >= psize);
1144           mc.header.size = htons (psize);
1145           mc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
1146           mc.tid = htonl (th->tunnel->tid);
1147           mc.mid = 0;
1148           mc.ttl = 0;
1149           memset (&mc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1150           memcpy (cbuf, &mc, sizeof (mc));
1151         }
1152       }
1153       else
1154       {
1155         /* unicast */
1156         struct GNUNET_MESH_Unicast uc;
1157         struct GNUNET_MessageHeader *mh;
1158
1159         GNUNET_assert (size >= th->size);
1160         mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (uc)];
1161         psize = th->notify (th->notify_cls, size - sizeof (uc), mh);
1162         LOG (GNUNET_ERROR_TYPE_DEBUG, "  unicast, type %u\n",
1163              ntohs (mh->type));
1164         if (psize > 0)
1165         {
1166           psize += sizeof (uc);
1167           GNUNET_assert (size >= psize);
1168           uc.header.size = htons (psize);
1169           uc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
1170           uc.tid = htonl (th->tunnel->tid);
1171           memset (&uc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1172           GNUNET_PEER_resolve (th->target, &uc.destination);
1173           memcpy (cbuf, &uc, sizeof (uc));
1174         }
1175       }
1176     }
1177     else
1178     {
1179       struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1];
1180       LOG (GNUNET_ERROR_TYPE_DEBUG, "  mesh traffic, type %u\n",
1181              ntohs (mh->type));
1182       memcpy (cbuf, &th[1], th->size);
1183       psize = th->size;
1184     }
1185     if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1186       GNUNET_SCHEDULER_cancel (th->timeout_task);
1187     if (NULL != th->notify)
1188     {
1189       th->tunnel->mesh->npackets--;
1190       th->tunnel->npackets--;
1191     }
1192     GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1193     GNUNET_free (th);
1194     cbuf += psize;
1195     size -= psize;
1196     tsize += psize;
1197   }
1198   LOG (GNUNET_ERROR_TYPE_DEBUG, "  total size: %u\n", tsize);
1199   if (NULL != (th = h->th_head))
1200   {
1201     LOG (GNUNET_ERROR_TYPE_DEBUG, "  next size: %u\n", th->size);
1202     if (NULL == h->th)
1203       h->th =
1204           GNUNET_CLIENT_notify_transmit_ready (h->client, th->size,
1205                                                GNUNET_TIME_UNIT_FOREVER_REL,
1206                                                GNUNET_YES, &send_callback, h);
1207   }
1208   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() END\n");
1209   if (GNUNET_NO == h->in_receive)
1210   {
1211     h->in_receive = GNUNET_YES;
1212     GNUNET_CLIENT_receive (h->client, &msg_received, h,
1213                            GNUNET_TIME_UNIT_FOREVER_REL);
1214   }
1215   return tsize;
1216 }
1217
1218
1219 /**
1220  * Auxiliary function to send an already constructed packet to the service.
1221  * Takes care of creating a new queue element, copying the message and
1222  * calling the tmt_rdy function if necessary.
1223  * 
1224  * @param h mesh handle
1225  * @param msg message to transmit
1226  * @param tunnel tunnel this send is related to (NULL if N/A)
1227  */
1228 static void
1229 send_packet (struct GNUNET_MESH_Handle *h,
1230              const struct GNUNET_MessageHeader *msg,
1231              struct GNUNET_MESH_Tunnel *tunnel)
1232 {
1233   struct GNUNET_MESH_TransmitHandle *th;
1234   size_t msize;
1235
1236   msize = ntohs (msg->size);
1237   th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize);
1238   th->priority = UINT32_MAX;
1239   th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1240   th->size = msize;
1241   th->tunnel = tunnel;
1242   memcpy (&th[1], msg, msize);
1243   add_to_queue (h, th);
1244   if (NULL != h->th)
1245     return;
1246   h->th =
1247       GNUNET_CLIENT_notify_transmit_ready (h->client, msize,
1248                                            GNUNET_TIME_UNIT_FOREVER_REL,
1249                                            GNUNET_YES, &send_callback, h);
1250 }
1251
1252
1253 /******************************************************************************/
1254 /**********************      API CALL DEFINITIONS     *************************/
1255 /******************************************************************************/
1256
1257 /**
1258  * Connect to the mesh service.
1259  *
1260  * @param cfg configuration to use
1261  * @param queue_size size of the data message queue, shared among all tunnels
1262  *                   (each tunnel is guaranteed to accept at least one message,
1263  *                    no matter what is the status of other tunnels)
1264  * @param cls closure for the various callbacks that follow
1265  *            (including handlers in the handlers array)
1266  * @param new_tunnel function called when an *inbound* tunnel is created
1267  * @param cleaner function called when an *inbound* tunnel is destroyed by the
1268  *                remote peer, it is *not* called if GNUNET_MESH_tunnel_destroy
1269  *                is called on the tunnel
1270  * @param handlers callbacks for messages we care about, NULL-terminated
1271  *                note that the mesh is allowed to drop notifications about
1272  *                inbound messages if the client does not process them fast
1273  *                enough (for this notification type, a bounded queue is used)
1274  * @param stypes list of the applications that this client claims to provide
1275  * @return handle to the mesh service NULL on error
1276  *         (in this case, init is never called)
1277  */
1278 struct GNUNET_MESH_Handle *
1279 GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
1280                      unsigned int queue_size, void *cls,
1281                      GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
1282                      GNUNET_MESH_TunnelEndHandler cleaner,
1283                      const struct GNUNET_MESH_MessageHandler *handlers,
1284                      const GNUNET_MESH_ApplicationType *stypes)
1285 {
1286   struct GNUNET_MESH_Handle *h;
1287
1288   LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n");
1289   h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
1290   h->cfg = cfg;
1291   h->max_queue_size = queue_size;
1292   h->new_tunnel = new_tunnel;
1293   h->cleaner = cleaner;
1294   h->client = GNUNET_CLIENT_connect ("mesh", cfg);
1295   if (h->client == NULL)
1296   {
1297     GNUNET_break (0);
1298     GNUNET_free (h);
1299     return NULL;
1300   }
1301   h->cls = cls;
1302   /* FIXME memdup? */
1303   h->applications = stypes;
1304   h->message_handlers = handlers;
1305   h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
1306   h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
1307   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1308
1309   /* count handlers and apps, calculate size */
1310   for (h->n_applications = 0; stypes[h->n_applications]; h->n_applications++) ;
1311   for (h->n_handlers = 0; handlers[h->n_handlers].type; h->n_handlers++) ;
1312   send_connect (h);
1313   LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n");
1314   return h;
1315 }
1316
1317
1318 /**
1319  * Disconnect from the mesh service. All tunnels will be destroyed. All tunnel
1320  * disconnect callbacks will be called on any still connected peers, notifying
1321  * about their disconnection. The registered inbound tunnel cleaner will be
1322  * called should any inbound tunnels still exist.
1323  *
1324  * @param handle connection to mesh to disconnect
1325  */
1326 void
1327 GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
1328 {
1329   struct GNUNET_MESH_Tunnel *t;
1330   struct GNUNET_MESH_Tunnel *aux;
1331   struct GNUNET_MESH_TransmitHandle *th;
1332
1333   LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH DISCONNECT\n");
1334
1335   t = handle->tunnels_head;
1336   while (NULL != t)
1337   {
1338     aux = t->next;
1339     if (t->tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1340     {
1341       GNUNET_break (0);
1342       LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X not destroyed\n", t->tid);
1343     }
1344     destroy_tunnel (t, GNUNET_YES);
1345     t = aux;
1346   }
1347   while ( (th = handle->th_head) != NULL)
1348   {
1349     struct GNUNET_MessageHeader *msg;
1350
1351     /* Make sure it is an allowed packet (everything else should have been
1352      * already canceled).
1353      */
1354     GNUNET_break (UINT32_MAX == th->priority);
1355     GNUNET_break (NULL == th->notify);
1356     msg = (struct GNUNET_MessageHeader *) &th[1];
1357     switch (ntohs(msg->type))
1358     {
1359       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT:
1360       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1361         break;
1362       default:
1363         GNUNET_break (0);
1364         LOG (GNUNET_ERROR_TYPE_DEBUG, "unexpected msg %u\n",
1365              ntohs(msg->type));
1366     }
1367
1368     GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th);
1369     GNUNET_free (th);
1370   }
1371
1372   if (NULL != handle->th)
1373   {
1374     GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
1375     handle->th = NULL;
1376   }
1377   if (NULL != handle->client)
1378   {
1379     GNUNET_CLIENT_disconnect (handle->client);
1380     handle->client = NULL;
1381   }
1382   if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task)
1383   {
1384     GNUNET_SCHEDULER_cancel(handle->reconnect_task);
1385     handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1386   }
1387   GNUNET_free (handle);
1388 }
1389
1390
1391 /**
1392  * Announce to ther peer the availability of services described by the regex,
1393  * in order to be reachable to other peers via connect_by_string.
1394  * 
1395  * Note that the first 8 characters are considered to be part of a prefix,
1396  * (for instance 'gnunet://'). If you put a variable part in there (*, +. ()),
1397  * all matching strings will be stored in the DHT.
1398  *
1399  * @param h handle to mesh.
1400  * @param regex string with the regular expression describing local services.
1401  */
1402 void
1403 GNUNET_MESH_announce_regex (struct GNUNET_MESH_Handle *h,
1404                             const char *regex)
1405 {
1406   struct GNUNET_MessageHeader *msg;
1407   size_t len;
1408   size_t msgsize;
1409
1410   len = strlen (regex);
1411   msgsize = sizeof(struct GNUNET_MessageHeader) + len;
1412   GNUNET_assert (UINT16_MAX > msgsize);
1413
1414   msg = GNUNET_malloc (msgsize);
1415   msg->size = htons (msgsize);
1416   msg->type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ANNOUNCE_REGEX);
1417   memcpy (&msg[1], regex, len);
1418
1419   send_packet(h, msg, NULL);
1420 }
1421
1422 /**
1423  * Create a new tunnel (we're initiator and will be allowed to add/remove peers
1424  * and to broadcast).
1425  *
1426  * @param h mesh handle
1427  * @param tunnel_ctx client's tunnel context to associate with the tunnel
1428  * @param connect_handler function to call when peers are actually connected
1429  * @param disconnect_handler function to call when peers are disconnected
1430  * @param handler_cls closure for connect/disconnect handlers
1431  */
1432 struct GNUNET_MESH_Tunnel *
1433 GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, void *tunnel_ctx,
1434                            GNUNET_MESH_PeerConnectHandler connect_handler,
1435                            GNUNET_MESH_PeerDisconnectHandler disconnect_handler,
1436                            void *handler_cls)
1437 {
1438   struct GNUNET_MESH_Tunnel *t;
1439   struct GNUNET_MESH_TunnelMessage msg;
1440
1441   LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new tunnel\n");
1442   t = create_tunnel (h, 0);
1443   t->connect_handler = connect_handler;
1444   t->disconnect_handler = disconnect_handler;
1445   t->cls = handler_cls;
1446   t->ctx = tunnel_ctx;
1447   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
1448   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1449   msg.tunnel_id = htonl (t->tid);
1450   send_packet (h, &msg.header, t);
1451   return t;
1452 }
1453
1454
1455 /**
1456  * Destroy an existing tunnel. The existing callback for the tunnel will NOT
1457  * be called.
1458  *
1459  * @param tunnel tunnel handle
1460  */
1461 void
1462 GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel)
1463 {
1464   struct GNUNET_MESH_Handle *h;
1465   struct GNUNET_MESH_TunnelMessage msg;
1466   struct GNUNET_MESH_TransmitHandle *th;
1467
1468   LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying tunnel\n");
1469   h = tunnel->mesh;
1470
1471   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1472   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1473   msg.tunnel_id = htonl (tunnel->tid);
1474   th = h->th_head;
1475   while (th != NULL)
1476   {
1477     struct GNUNET_MESH_TransmitHandle *aux;
1478     if (th->tunnel == tunnel)
1479     {
1480       aux = th->next;
1481       /* FIXME call the handler? */
1482       if (NULL != th->notify)
1483         th->notify (th->notify_cls, 0, NULL);
1484       GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1485       GNUNET_free (th);
1486       th = aux;
1487     }
1488     else
1489       th = th->next;
1490   }
1491
1492   destroy_tunnel (tunnel, GNUNET_NO);
1493   send_packet (h, &msg.header, NULL);
1494 }
1495
1496 /**
1497  * Request that the tunnel data rate is limited to the speed of the slowest
1498  * receiver.
1499  *
1500  * @param tunnel Tunnel affected.
1501  */
1502 void
1503 GNUNET_MESH_tunnel_speed_min (struct GNUNET_MESH_Tunnel *tunnel)
1504 {
1505   struct GNUNET_MESH_TunnelMessage msg;
1506   struct GNUNET_MESH_Handle *h;
1507
1508   h = tunnel->mesh;
1509   tunnel->speed_min = GNUNET_YES;
1510
1511   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MIN);
1512   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1513   msg.tunnel_id = htonl (tunnel->tid);
1514
1515   send_packet (h, &msg.header, NULL);
1516 }
1517
1518
1519 /**
1520  * Request that the tunnel data rate is limited to the speed of the fastest
1521  * receiver. This is the default behavior.
1522  *
1523  * @param tunnel Tunnel affected.
1524  */
1525 void
1526 GNUNET_MESH_tunnel_speed_max (struct GNUNET_MESH_Tunnel *tunnel)
1527 {
1528   struct GNUNET_MESH_TunnelMessage msg;
1529   struct GNUNET_MESH_Handle *h;
1530
1531   h = tunnel->mesh;
1532   tunnel->speed_min = GNUNET_NO;
1533
1534   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MAX);
1535   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1536   msg.tunnel_id = htonl (tunnel->tid);
1537
1538   send_packet (h, &msg.header, NULL);
1539 }
1540
1541 /**
1542  * Request that a peer should be added to the tunnel.  The existing
1543  * connect handler will be called ONCE with either success or failure.
1544  * This function should NOT be called again with the same peer before the
1545  * connect handler is called.
1546  *
1547  * @param tunnel handle to existing tunnel
1548  * @param peer peer to add
1549  */
1550 void
1551 GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
1552                                       const struct GNUNET_PeerIdentity *peer)
1553 {
1554   struct GNUNET_MESH_PeerControl msg;
1555   GNUNET_PEER_Id peer_id;
1556   unsigned int i;
1557
1558   peer_id = GNUNET_PEER_intern (peer);
1559   for (i = 0; i < tunnel->npeers; i++)
1560   {
1561     if (tunnel->peers[i]->id == peer_id)
1562     {
1563       /* Peer already exists in tunnel */
1564       GNUNET_PEER_change_rc (peer_id, -1);
1565       GNUNET_break (0);
1566       return;
1567     }
1568   }
1569   if (NULL == add_peer_to_tunnel (tunnel, peer))
1570     return;
1571
1572   msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
1573   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
1574   msg.tunnel_id = htonl (tunnel->tid);
1575   msg.peer = *peer;
1576   send_packet (tunnel->mesh, &msg.header, tunnel);
1577
1578   return;
1579 }
1580
1581
1582 /**
1583  * Request that a peer should be removed from the tunnel.  The existing
1584  * disconnect handler will be called ONCE if we were connected.
1585  *
1586  * @param tunnel handle to existing tunnel
1587  * @param peer peer to remove
1588  */
1589 void
1590 GNUNET_MESH_peer_request_connect_del (struct GNUNET_MESH_Tunnel *tunnel,
1591                                       const struct GNUNET_PeerIdentity *peer)
1592 {
1593   struct GNUNET_MESH_PeerControl msg;
1594   GNUNET_PEER_Id peer_id;
1595   unsigned int i;
1596
1597   peer_id = GNUNET_PEER_search (peer);
1598   if (0 == peer_id)
1599   {
1600     GNUNET_break (0);
1601     return;
1602   }
1603   for (i = 0; i < tunnel->npeers; i++)
1604     if (tunnel->peers[i]->id == peer_id)
1605       break;
1606   if (i == tunnel->npeers)
1607   {
1608     GNUNET_break (0);
1609     return;
1610   }
1611   if (NULL != tunnel->disconnect_handler && tunnel->peers[i]->connected == 1)
1612     tunnel->disconnect_handler (tunnel->cls, peer);
1613   GNUNET_PEER_change_rc (peer_id, -1);
1614   GNUNET_free (tunnel->peers[i]);
1615   tunnel->peers[i] = tunnel->peers[tunnel->npeers - 1];
1616   GNUNET_array_grow (tunnel->peers, tunnel->npeers, tunnel->npeers - 1);
1617
1618   msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
1619   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
1620   msg.tunnel_id = htonl (tunnel->tid);
1621   memcpy (&msg.peer, peer, sizeof (struct GNUNET_PeerIdentity));
1622   send_packet (tunnel->mesh, &msg.header, tunnel);
1623 }
1624
1625
1626 /**
1627  * Request that the mesh should try to connect to a peer supporting the given
1628  * message type.
1629  *
1630  * @param tunnel handle to existing tunnel
1631  * @param app_type application type that must be supported by the peer (MESH
1632  *                 should discover peer in proximity handling this type)
1633  */
1634 void
1635 GNUNET_MESH_peer_request_connect_by_type (struct GNUNET_MESH_Tunnel *tunnel,
1636                                           GNUNET_MESH_ApplicationType app_type)
1637 {
1638   struct GNUNET_MESH_ConnectPeerByType msg;
1639
1640   GNUNET_array_append (tunnel->apps, tunnel->napps, app_type);
1641
1642   LOG (GNUNET_ERROR_TYPE_DEBUG, "* CONNECT BY TYPE *\n");
1643   msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
1644   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
1645   msg.tunnel_id = htonl (tunnel->tid);
1646   msg.type = htonl (app_type);
1647   send_packet (tunnel->mesh, &msg.header, tunnel);
1648 }
1649
1650
1651 /**
1652  * Request that the mesh should try to connect to a peer matching the
1653  * description given in the service string.
1654  *
1655  * @param tunnel handle to existing tunnel
1656  * @param description string describing the destination node requirements
1657  */
1658 void
1659 GNUNET_MESH_peer_request_connect_by_string (struct GNUNET_MESH_Tunnel *tunnel,
1660                                             const char *description)
1661 {
1662   struct GNUNET_MESH_ConnectPeerByString *msg;
1663   size_t len;
1664   size_t msgsize;
1665
1666   len = strlen(description);
1667   msgsize = sizeof(struct GNUNET_MESH_ConnectPeerByString) + len;
1668   GNUNET_assert (UINT16_MAX > msgsize);
1669   msg = GNUNET_malloc (msgsize);
1670   msg->header.size = htons (msgsize);
1671   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_STRING);
1672   msg->tunnel_id = htonl (tunnel->tid);
1673   memcpy(&msg[1], description, len);
1674
1675   send_packet (tunnel->mesh, &msg->header, tunnel);
1676 }
1677
1678
1679 /**
1680  * Request that the given peer isn't added to this tunnel in calls to
1681  * connect_by_* calls, (due to misbehaviour, bad performance, ...).
1682  *
1683  * @param tunnel handle to existing tunnel.
1684  * @param peer peer identity of the peer which should be blacklisted
1685  *                  for the tunnel.
1686  */
1687 void
1688 GNUNET_MESH_peer_blacklist (struct GNUNET_MESH_Tunnel *tunnel,
1689                             const struct GNUNET_PeerIdentity *peer)
1690 {
1691   struct GNUNET_MESH_PeerControl msg;
1692
1693   msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
1694   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_BLACKLIST);
1695   msg.tunnel_id = htonl (tunnel->tid);
1696   msg.peer = *peer;
1697   send_packet (tunnel->mesh, &msg.header, tunnel);
1698
1699   return;
1700 }
1701
1702
1703 /**
1704  * Request that the given peer isn't blacklisted anymore from this tunnel,
1705  * and therefore can be added in future calls to connect_by_*.
1706  * The peer must have been previously blacklisted for this tunnel.
1707  *
1708  * @param tunnel handle to existing tunnel.
1709  * @param peer peer identity of the peer which shouldn't be blacklisted
1710  *                  for the tunnel anymore.
1711  */
1712 void
1713 GNUNET_MESH_peer_unblacklist (struct GNUNET_MESH_Tunnel *tunnel,
1714                               const struct GNUNET_PeerIdentity *peer)
1715 {
1716   struct GNUNET_MESH_PeerControl msg;
1717
1718   msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
1719   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_UNBLACKLIST);
1720   msg.tunnel_id = htonl (tunnel->tid);
1721   msg.peer = *peer;
1722   send_packet (tunnel->mesh, &msg.header, tunnel);
1723
1724   return;
1725 }
1726
1727
1728 /**
1729  * Ask the mesh to call "notify" once it is ready to transmit the
1730  * given number of bytes to the specified "target".  If we are not yet
1731  * connected to the specified peer, a call to this function will cause
1732  * us to try to establish a connection.
1733  *
1734  * @param tunnel tunnel to use for transmission
1735  * @param cork is corking allowed for this transmission?
1736  * @param priority how important is the message?
1737  * @param maxdelay how long can the message wait?
1738  * @param target destination for the message,
1739  *               NULL for multicast to all tunnel targets
1740  * @param notify_size how many bytes of buffer space does notify want?
1741  * @param notify function to call when buffer space is available;
1742  *        will be called with NULL on timeout or if the overall queue
1743  *        for this peer is larger than queue_size and this is currently
1744  *        the message with the lowest priority
1745  * @param notify_cls closure for notify
1746  * @return non-NULL if the notify callback was queued,
1747  *         NULL if we can not even queue the request (insufficient
1748  *         memory); if NULL is returned, "notify" will NOT be called.
1749  */
1750 struct GNUNET_MESH_TransmitHandle *
1751 GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
1752                                    uint32_t priority,
1753                                    struct GNUNET_TIME_Relative maxdelay,
1754                                    const struct GNUNET_PeerIdentity *target,
1755                                    size_t notify_size,
1756                                    GNUNET_CONNECTION_TransmitReadyNotify notify,
1757                                    void *notify_cls)
1758 {
1759   struct GNUNET_MESH_TransmitHandle *th;
1760   struct GNUNET_MESH_TransmitHandle *least_priority_th;
1761   uint32_t least_priority;
1762   size_t overhead;
1763
1764   GNUNET_assert (NULL != tunnel);
1765   LOG (GNUNET_ERROR_TYPE_DEBUG, "mesh notify transmit ready called\n");
1766   if (NULL != target)
1767     LOG (GNUNET_ERROR_TYPE_DEBUG, "    target %s\n", GNUNET_i2s (target));
1768   else
1769     LOG (GNUNET_ERROR_TYPE_DEBUG, "    target multicast\n");
1770   GNUNET_assert (NULL != notify);
1771   if (tunnel->mesh->npackets >= tunnel->mesh->max_queue_size &&
1772       tunnel->npackets > 0)
1773   {
1774     /* queue full */
1775     if (0 == priority)
1776       return NULL;
1777     th = tunnel->mesh->th_tail;
1778     least_priority = priority;
1779     least_priority_th = NULL;
1780     while (NULL != th)
1781     {
1782       if (th->priority < least_priority && th->tunnel->npackets > 1)
1783       {
1784         least_priority_th = th;
1785         least_priority = th->priority;
1786       }
1787       th = th->prev;
1788     }
1789     if (NULL == least_priority_th)
1790       return NULL;
1791     /* Can't be a control message */
1792     GNUNET_assert (NULL != least_priority_th->notify);
1793     least_priority_th->notify (notify_cls, 0, NULL);
1794     least_priority_th->tunnel->npackets--;
1795     tunnel->mesh->npackets--;
1796     GNUNET_CONTAINER_DLL_remove (tunnel->mesh->th_head, tunnel->mesh->th_tail,
1797                                  least_priority_th);
1798     if (GNUNET_SCHEDULER_NO_TASK != least_priority_th->timeout_task)
1799       GNUNET_SCHEDULER_cancel (least_priority_th->timeout_task);
1800     GNUNET_free (least_priority_th);
1801   }
1802   tunnel->npackets++;
1803   tunnel->mesh->npackets++;
1804   th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
1805   th->tunnel = tunnel;
1806   th->priority = priority;
1807   th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
1808   th->target = GNUNET_PEER_intern (target);
1809   if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1810     overhead = sizeof (struct GNUNET_MESH_ToOrigin);
1811   else if (NULL == target)
1812     overhead = sizeof (struct GNUNET_MESH_Multicast);
1813   else
1814     overhead = sizeof (struct GNUNET_MESH_Unicast);
1815   th->size = notify_size + overhead;
1816   th->notify = notify;
1817   th->notify_cls = notify_cls;
1818   add_to_queue (tunnel->mesh, th);
1819   if (NULL != tunnel->mesh->th)
1820     return th;
1821   tunnel->mesh->th =
1822       GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size,
1823                                            GNUNET_TIME_UNIT_FOREVER_REL,
1824                                            GNUNET_YES, &send_callback,
1825                                            tunnel->mesh);
1826   return th;
1827 }
1828
1829
1830 /**
1831  * Cancel the specified transmission-ready notification.
1832  *
1833  * @param th handle that was returned by "notify_transmit_ready".
1834  */
1835 void
1836 GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th)
1837 {
1838   struct GNUNET_MESH_Handle *mesh;
1839
1840   mesh = th->tunnel->mesh;
1841   if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1842     GNUNET_SCHEDULER_cancel (th->timeout_task);
1843   GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
1844   GNUNET_free (th);
1845   if ((NULL == mesh->th_head) && (NULL != mesh->th))
1846   {
1847     /* queue empty, no point in asking for transmission */
1848     GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
1849     mesh->th = NULL;
1850   }
1851 }
1852
1853
1854 /**
1855  * Transition API for tunnel ctx management
1856  */
1857 void
1858 GNUNET_MESH_tunnel_set_data (struct GNUNET_MESH_Tunnel *tunnel, void *data)
1859 {
1860   tunnel->ctx = data;
1861 }
1862
1863 /**
1864  * Transition API for tunnel ctx management
1865  */
1866 void *
1867 GNUNET_MESH_tunnel_get_data (struct GNUNET_MESH_Tunnel *tunnel)
1868 {
1869   return tunnel->ctx;
1870 }
1871
1872