- fix
[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  * - DATA STRUCTURES
25  * - DECLARATIONS
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 #define DEBUG_ACK GNUNET_YES
45
46 /******************************************************************************/
47 /************************      DATA STRUCTURES     ****************************/
48 /******************************************************************************/
49
50 /**
51  * Transmission queue to the service
52  */
53 struct GNUNET_MESH_TransmitHandle
54 {
55
56     /**
57      * Double Linked list
58      */
59   struct GNUNET_MESH_TransmitHandle *next;
60
61     /**
62      * Double Linked list
63      */
64   struct GNUNET_MESH_TransmitHandle *prev;
65
66     /**
67      * Tunnel this message is sent on / for (may be NULL for control messages).
68      */
69   struct GNUNET_MESH_Tunnel *tunnel;
70
71     /**
72      * Callback to obtain the message to transmit, or NULL if we
73      * got the message in 'data'.  Notice that messages built
74      * by 'notify' need to be encapsulated with information about
75      * the 'target'.
76      */
77   GNUNET_CONNECTION_TransmitReadyNotify notify;
78
79     /**
80      * Closure for 'notify'
81      */
82   void *notify_cls;
83
84     /**
85      * How long is this message valid.  Once the timeout has been
86      * reached, the message must no longer be sent.  If this
87      * is a message with a 'notify' callback set, the 'notify'
88      * function should be called with 'buf' NULL and size 0.
89      */
90   struct GNUNET_TIME_Absolute timeout;
91
92     /**
93      * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER.
94      */
95   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
96
97     /**
98      * Target of the message, 0 for multicast.  This field
99      * is only valid if 'notify' is non-NULL.
100      */
101   GNUNET_PEER_Id target;
102
103     /**
104      * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL.
105      */
106   size_t size;
107 };
108
109
110 /**
111  * Opaque handle to the service.
112  */
113 struct GNUNET_MESH_Handle
114 {
115
116     /**
117      * Handle to the server connection, to send messages later
118      */
119   struct GNUNET_CLIENT_Connection *client;
120
121     /**
122      * Set of handlers used for processing incoming messages in the tunnels
123      */
124   const struct GNUNET_MESH_MessageHandler *message_handlers;
125
126     /**
127      * Set of applications that should be claimed to be offered at this node.
128      * Note that this is just informative, the appropiate handlers must be
129      * registered independently and the mapping is up to the developer of the
130      * client application.
131      */
132   const GNUNET_MESH_ApplicationType *applications;
133
134     /**
135      * Double linked list of the tunnels this client is connected to, head.
136      */
137   struct GNUNET_MESH_Tunnel *tunnels_head;
138
139     /**
140      * Double linked list of the tunnels this client is connected to, tail.
141      */
142   struct GNUNET_MESH_Tunnel *tunnels_tail;
143
144     /**
145      * Callback for inbound tunnel creation
146      */
147   GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
148
149     /**
150      * Callback for inbound tunnel disconnection
151      */
152   GNUNET_MESH_TunnelEndHandler *cleaner;
153
154     /**
155      * Handle to cancel pending transmissions in case of disconnection
156      */
157   struct GNUNET_CLIENT_TransmitHandle *th;
158
159     /**
160      * Closure for all the handlers given by the client
161      */
162   void *cls;
163
164     /**
165      * Messages to send to the service, head.
166      */
167   struct GNUNET_MESH_TransmitHandle *th_head;
168
169     /**
170      * Messages to send to the service, tail.
171      */
172   struct GNUNET_MESH_TransmitHandle *th_tail;
173
174     /**
175      * tid of the next tunnel to create (to avoid reusing IDs often)
176      */
177   MESH_TunnelNumber next_tid;
178
179     /**
180      * Number of handlers in the handlers array.
181      */
182   unsigned int n_handlers;
183
184     /**
185      * Number of applications in the applications array.
186      */
187   unsigned int n_applications;
188
189     /**
190      * Have we started the task to receive messages from the service
191      * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message.
192      */
193   int in_receive;
194
195   /**
196    * Configuration given by the client, in case of reconnection
197    */
198   const struct GNUNET_CONFIGURATION_Handle *cfg;
199
200   /**
201    * Time to the next reconnect in case one reconnect fails
202    */
203   struct GNUNET_TIME_Relative reconnect_time;
204   
205   /**
206    * Task for trying to reconnect.
207    */
208   GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
209
210   /**
211    * Monitor callback
212    */
213   GNUNET_MESH_TunnelsCB tunnels_cb;
214
215   /**
216    * Monitor callback closure.
217    */
218   void *tunnels_cls;
219
220   /**
221    * Tunnel callback.
222    */
223   GNUNET_MESH_TunnelCB tunnel_cb;
224
225   /**
226    * Tunnel callback closure.
227    */
228   void *tunnel_cls;
229
230 #if DEBUG_ACK
231   unsigned int acks_sent;
232   unsigned int acks_recv;
233 #endif
234 };
235
236
237 /**
238  * Description of a peer
239  */
240 struct GNUNET_MESH_Peer
241 {
242     /**
243      * ID of the peer in short form
244      */
245   GNUNET_PEER_Id id;
246
247   /**
248    * Tunnel this peer belongs to
249    */
250   struct GNUNET_MESH_Tunnel *t;
251
252   /**
253    * Flag indicating whether service has informed about its connection
254    */
255   int connected;
256
257 };
258
259
260 /**
261  * Opaque handle to a tunnel.
262  */
263 struct GNUNET_MESH_Tunnel
264 {
265
266     /**
267      * DLL next
268      */
269   struct GNUNET_MESH_Tunnel *next;
270
271     /**
272      * DLL prev
273      */
274   struct GNUNET_MESH_Tunnel *prev;
275
276     /**
277      * Callback to execute when peers connect to the tunnel
278      */
279   GNUNET_MESH_PeerConnectHandler connect_handler;
280
281     /**
282      * Callback to execute when peers disconnect from the tunnel
283      */
284   GNUNET_MESH_PeerDisconnectHandler disconnect_handler;
285
286     /**
287      * Closure for the connect/disconnect handlers
288      */
289   void *cls;
290
291     /**
292      * Handle to the mesh this tunnel belongs to
293      */
294   struct GNUNET_MESH_Handle *mesh;
295
296     /**
297      * Local ID of the tunnel
298      */
299   MESH_TunnelNumber tid;
300
301     /**
302      * Owner of the tunnel. 0 if the tunnel is the local client.
303      */
304   GNUNET_PEER_Id owner;
305
306     /**
307      * All peers added to the tunnel
308      */
309   struct GNUNET_MESH_Peer **peers;
310
311   /**
312    * List of application types that have been requested for this tunnel
313    */
314   GNUNET_MESH_ApplicationType *apps;
315
316   /**
317    * Any data the caller wants to put in here
318    */
319   void *ctx;
320
321   /**
322      * Number of peers added to the tunnel
323      */
324   unsigned int npeers;
325
326     /**
327      * Size of packet queued in this tunnel
328      */
329   unsigned int packet_size;
330
331     /**
332      * Number of applications requested this tunnel
333      */
334   unsigned int napps;
335
336     /**
337      * Is the tunnel throttled to the slowest peer?
338      */
339   int speed_min;
340
341     /**
342      * Is the tunnel allowed to buffer?
343      */
344   int buffering;
345
346     /**
347      * Next packet ID to send.
348      */
349   uint32_t next_send_pid;
350
351     /**
352      * Maximum allowed PID to send (ACK recevied).
353      */
354   uint32_t max_send_pid;
355
356     /**
357      * Last pid received from the service.
358      */
359   uint32_t last_recv_pid;
360
361   /**
362    * Which ACK value have we last sent to the service?
363    */
364   uint32_t max_recv_pid;
365 };
366
367
368 /******************************************************************************/
369 /***********************         DECLARATIONS         *************************/
370 /******************************************************************************/
371
372 /**
373  * Function called to send a message to the service.
374  * "buf" will be NULL and "size" zero if the socket was closed for writing in
375  * the meantime.
376  *
377  * @param cls closure, the mesh handle
378  * @param size number of bytes available in buf
379  * @param buf where the callee should write the connect message
380  * @return number of bytes written to buf
381  */
382 static size_t
383 send_callback (void *cls, size_t size, void *buf);
384
385
386 /******************************************************************************/
387 /***********************     AUXILIARY FUNCTIONS      *************************/
388 /******************************************************************************/
389
390 /**
391  * Check if transmission is a payload packet.
392  *
393  * @param th Transmission handle.
394  *
395  * @return GNUNET_YES if it is a payload packet,
396  *         GNUNET_NO if it is a mesh management packet.
397  */
398 static int
399 th_is_payload (struct GNUNET_MESH_TransmitHandle *th)
400 {
401   return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO;
402 }
403
404
405 /**
406  * Check whether there is any message ready in the queue and find the size.
407  * 
408  * @param h Mesh handle.
409  * 
410  * @return The size of the first ready message in the queue,
411  *         0 if there is none.
412  */
413 static size_t
414 message_ready_size (struct GNUNET_MESH_Handle *h)
415 {
416   struct GNUNET_MESH_TransmitHandle *th;
417   struct GNUNET_MESH_Tunnel *t;
418
419   for (th = h->th_head; NULL != th; th = th->next)
420   {
421     t = th->tunnel;
422     if (GNUNET_NO == th_is_payload (th))
423     {
424       LOG (GNUNET_ERROR_TYPE_DEBUG, "  message internal\n");
425       return th->size;
426     }
427     if (GNUNET_NO == GMC_is_pid_bigger(t->next_send_pid, t->max_send_pid))
428     {
429       LOG (GNUNET_ERROR_TYPE_DEBUG, "  message payload ok (%u <= %u)\n",
430            t->next_send_pid, t->max_send_pid);
431       return th->size;
432     }
433   }
434   return 0;
435 }
436
437
438 /**
439  * Get the tunnel handler for the tunnel specified by id from the given handle
440  * @param h Mesh handle
441  * @param tid ID of the wanted tunnel
442  * @return handle to the required tunnel or NULL if not found
443  */
444 static struct GNUNET_MESH_Tunnel *
445 retrieve_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
446 {
447   struct GNUNET_MESH_Tunnel *t;
448
449   t = h->tunnels_head;
450   while (t != NULL)
451   {
452     if (t->tid == tid)
453       return t;
454     t = t->next;
455   }
456   return NULL;
457 }
458
459
460 /**
461  * Create a new tunnel and insert it in the tunnel list of the mesh handle
462  * @param h Mesh handle
463  * @param tid desired tid of the tunnel, 0 to assign one automatically
464  * @return handle to the created tunnel
465  */
466 static struct GNUNET_MESH_Tunnel *
467 create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
468 {
469   struct GNUNET_MESH_Tunnel *t;
470
471   t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel));
472   GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t);
473   t->mesh = h;
474   if (0 == tid)
475   {
476     t->tid = h->next_tid;
477     while (NULL != retrieve_tunnel (h, h->next_tid))
478     {
479       h->next_tid++;
480       h->next_tid &= ~GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
481       h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
482     }
483   }
484   else
485   {
486     t->tid = tid;
487   }
488   t->max_send_pid = INITIAL_WINDOW_SIZE - 1;
489   t->last_recv_pid = (uint32_t) -1;
490   t->buffering = GNUNET_YES;
491   return t;
492 }
493
494
495 /**
496  * Destroy the specified tunnel.
497  * - Destroys all peers, calling the disconnect callback on each if needed
498  * - Cancels all outgoing traffic for that tunnel, calling respective notifys
499  * - Calls cleaner if tunnel was inbound
500  * - Frees all memory used
501  *
502  * @param t Pointer to the tunnel.
503  * @param call_cleaner Whether to call the cleaner handler.
504  *
505  * @return Handle to the required tunnel or NULL if not found.
506  */
507 static void
508 destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner)
509 {
510   struct GNUNET_MESH_Handle *h;
511   struct GNUNET_PeerIdentity pi;
512   struct GNUNET_MESH_TransmitHandle *th;
513   struct GNUNET_MESH_TransmitHandle *next;
514   unsigned int i;
515
516   LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid);
517
518   if (NULL == t)
519   {
520     GNUNET_break (0);
521     return;
522   }
523   h = t->mesh;
524
525   /* disconnect all peers */
526   GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t);
527   for (i = 0; i < t->npeers; i++)
528   {
529     if ( (NULL != t->disconnect_handler) && t->peers[i]->connected)
530     {
531       GNUNET_PEER_resolve (t->peers[i]->id, &pi);
532       t->disconnect_handler (t->cls, &pi);
533     }
534     GNUNET_PEER_change_rc (t->peers[i]->id, -1);
535     GNUNET_free (t->peers[i]);
536   }
537
538   /* signal tunnel destruction */
539   if ( (NULL != h->cleaner) && (0 != t->owner) && (GNUNET_YES == call_cleaner) )
540     h->cleaner (h->cls, t, t->ctx);
541
542   /* check that clients did not leave messages behind in the queue */
543   for (th = h->th_head; NULL != th; th = next)
544   {
545     next = th->next;
546     if (th->tunnel != t)
547       continue;
548     /* Clients should have aborted their requests already.
549      * Management traffic should be ok, as clients can't cancel that */
550     GNUNET_break (GNUNET_NO == th_is_payload(th));
551     GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
552
553     /* clean up request */
554     if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
555       GNUNET_SCHEDULER_cancel (th->timeout_task);
556     GNUNET_free (th);    
557   }
558
559   /* if there are no more pending requests with mesh service, cancel active request */
560   /* Note: this should be unnecessary... */
561   if ((0 == message_ready_size (h)) && (NULL != h->th))
562   {
563     GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
564     h->th = NULL;
565   }
566
567
568   if (t->npeers > 0)
569     GNUNET_free (t->peers);
570   if (0 != t->owner)
571     GNUNET_PEER_change_rc (t->owner, -1);
572   if (0 != t->napps && t->apps)
573     GNUNET_free (t->apps);
574   GNUNET_free (t);
575   return;
576 }
577
578
579 /**
580  * Get the peer descriptor for the peer with id from the given tunnel
581  * @param t Tunnel handle
582  * @param id Short form ID of the wanted peer
583  * @return handle to the requested peer or NULL if not found
584  */
585 static struct GNUNET_MESH_Peer *
586 retrieve_peer (struct GNUNET_MESH_Tunnel *t, GNUNET_PEER_Id id)
587 {
588   unsigned int i;
589
590   for (i = 0; i < t->npeers; i++)
591     if (t->peers[i]->id == id)
592       return t->peers[i];
593   return NULL;
594 }
595
596
597 /**
598  * Add a peer into a tunnel
599  * @param t Tunnel handle
600  * @param pi Full ID of the new peer
601  * @return handle to the newly created peer
602  */
603 static struct GNUNET_MESH_Peer *
604 add_peer_to_tunnel (struct GNUNET_MESH_Tunnel *t,
605                     const struct GNUNET_PeerIdentity *pi)
606 {
607   struct GNUNET_MESH_Peer *p;
608   GNUNET_PEER_Id id;
609
610   if (0 != t->owner)
611   {
612     GNUNET_break (0);
613     return NULL;
614   }
615   id = GNUNET_PEER_intern (pi);
616
617   p = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
618   p->id = id;
619   p->t = t;
620   GNUNET_array_append (t->peers, t->npeers, p);
621   return p;
622 }
623
624
625 /**
626  * Remove a peer from a tunnel
627  * @param p Peer handle
628  */
629 static void
630 remove_peer_from_tunnel (struct GNUNET_MESH_Peer *p)
631 {
632   unsigned int i;
633
634   for (i = 0; i < p->t->npeers; i++)
635   {
636     if (p->t->peers[i] == p)
637       break;
638   }
639   if (i == p->t->npeers)
640   {
641     GNUNET_break (0);
642     return;
643   }
644   p->t->peers[i] = p->t->peers[p->t->npeers - 1];
645   GNUNET_array_grow (p->t->peers, p->t->npeers, p->t->npeers - 1);
646 }
647
648
649 /**
650  * Notify client that the transmission has timed out
651  * 
652  * @param cls closure
653  * @param tc task context
654  */
655 static void
656 timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
657 {
658   struct GNUNET_MESH_TransmitHandle *th = cls;
659   struct GNUNET_MESH_Handle *mesh;
660
661   mesh = th->tunnel->mesh;
662   GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
663   th->tunnel->packet_size = 0;
664   if (GNUNET_YES == th_is_payload (th))
665     th->notify (th->notify_cls, 0, NULL);
666   GNUNET_free (th);
667   if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
668   {
669     /* nothing ready to transmit, no point in asking for transmission */
670     GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
671     mesh->th = NULL;
672   }
673 }
674
675
676 /**
677  * Add a transmit handle to the transmission queue and set the
678  * timeout if needed.
679  *
680  * @param h mesh handle with the queue head and tail
681  * @param th handle to the packet to be transmitted
682  */
683 static void
684 add_to_queue (struct GNUNET_MESH_Handle *h,
685               struct GNUNET_MESH_TransmitHandle *th)
686 {
687   GNUNET_CONTAINER_DLL_insert_tail (h->th_head, h->th_tail, th);
688   if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value == th->timeout.abs_value)
689     return;
690   th->timeout_task =
691       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
692                                     (th->timeout), &timeout_transmission, th);
693 }
694
695
696 /**
697  * Auxiliary function to send an already constructed packet to the service.
698  * Takes care of creating a new queue element, copying the message and
699  * calling the tmt_rdy function if necessary.
700  *
701  * @param h mesh handle
702  * @param msg message to transmit
703  * @param tunnel tunnel this send is related to (NULL if N/A)
704  */
705 static void
706 send_packet (struct GNUNET_MESH_Handle *h,
707              const struct GNUNET_MessageHeader *msg,
708              struct GNUNET_MESH_Tunnel *tunnel);
709
710
711 /**
712  * Send an ack on the tunnel to confirm the processing of a message.
713  * 
714  * @param h Mesh handle.
715  * @param t Tunnel on which to send the ACK.
716  */
717 static void
718 send_ack (struct GNUNET_MESH_Handle *h, struct GNUNET_MESH_Tunnel *t)
719 {
720   struct GNUNET_MESH_LocalAck msg;
721   uint32_t delta;
722
723   delta = t->max_recv_pid - t->last_recv_pid;
724   if (delta > ACK_THRESHOLD)
725   {
726     LOG (GNUNET_ERROR_TYPE_DEBUG,
727          "Not sending ACK on tunnel %X: ACK: %u, PID: %u, buffer %u\n",
728          t->tid, t->max_recv_pid, t->last_recv_pid, delta);
729     return;
730   }
731   if (GNUNET_YES == t->buffering)
732     t->max_recv_pid = t->last_recv_pid + INITIAL_WINDOW_SIZE;
733   else
734     t->max_recv_pid = t->last_recv_pid + 1;
735   LOG (GNUNET_ERROR_TYPE_DEBUG,
736        "Sending ACK on tunnel %X: %u\n",
737        t->tid, t->max_recv_pid);
738   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
739   msg.header.size = htons (sizeof (msg));
740   msg.tunnel_id = htonl (t->tid);
741   msg.max_pid = htonl (t->max_recv_pid);
742
743 #if DEBUG_ACK
744   t->mesh->acks_sent++;
745 #endif
746
747   send_packet (h, &msg.header, t);
748   return;
749 }
750
751
752
753 /**
754  * Reconnect callback: tries to reconnect again after a failer previous
755  * reconnecttion
756  * @param cls closure (mesh handle)
757  * @param tc task context
758  */
759 static void
760 reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
761
762
763 /**
764  * Send a connect packet to the service with the applications and types
765  * requested by the user.
766  *
767  * @param h The mesh handle.
768  *
769  */
770 static void
771 send_connect (struct GNUNET_MESH_Handle *h)
772 {
773   size_t size;
774
775   size = sizeof (struct GNUNET_MESH_ClientConnect);
776   size += h->n_applications * sizeof (GNUNET_MESH_ApplicationType);
777   size += h->n_handlers * sizeof (uint16_t);
778   {
779     char buf[size] GNUNET_ALIGN;
780     struct GNUNET_MESH_ClientConnect *msg;
781     GNUNET_MESH_ApplicationType *apps;
782     uint16_t napps;
783     uint16_t *types;
784     uint16_t ntypes;
785
786     /* build connection packet */
787     msg = (struct GNUNET_MESH_ClientConnect *) buf;
788     msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT);
789     msg->header.size = htons (size);
790     apps = (GNUNET_MESH_ApplicationType *) &msg[1];
791     for (napps = 0; napps < h->n_applications; napps++)
792     {
793       apps[napps] = htonl (h->applications[napps]);
794       LOG (GNUNET_ERROR_TYPE_DEBUG, " app %u\n",
795            h->applications[napps]);
796     }
797     types = (uint16_t *) & apps[napps];
798     for (ntypes = 0; ntypes < h->n_handlers; ntypes++)
799     {
800       types[ntypes] = htons (h->message_handlers[ntypes].type);
801       LOG (GNUNET_ERROR_TYPE_DEBUG, " type %u\n",
802            h->message_handlers[ntypes].type);
803     }
804     msg->applications = htons (napps);
805     msg->types = htons (ntypes);
806     LOG (GNUNET_ERROR_TYPE_DEBUG,
807          "Sending %lu bytes long message %d types and %d apps\n",
808          ntohs (msg->header.size), ntypes, napps);
809     send_packet (h, &msg->header, NULL);
810   }
811 }
812
813
814 /**
815  * Reconnect to the service, retransmit all infomation to try to restore the
816  * original state.
817  *
818  * @param h handle to the mesh
819  *
820  * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
821  */
822 static int
823 do_reconnect (struct GNUNET_MESH_Handle *h)
824 {
825   struct GNUNET_MESH_Tunnel *t;
826   unsigned int i;
827
828   LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
829   LOG (GNUNET_ERROR_TYPE_DEBUG, "*******   RECONNECT   *******\n");
830   LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
831   LOG (GNUNET_ERROR_TYPE_DEBUG, "******** on %p *******\n", h);
832   LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
833
834   /* disconnect */
835   if (NULL != h->th)
836   {
837     GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
838     h->th = NULL;
839   }
840   if (NULL != h->client)
841   {
842     GNUNET_CLIENT_disconnect (h->client);
843   }
844
845   /* connect again */
846   h->client = GNUNET_CLIENT_connect ("mesh", h->cfg);
847   if (h->client == NULL)
848   {
849     h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
850                                                       &reconnect_cbk, h);
851     h->reconnect_time =
852         GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
853                                   GNUNET_TIME_relative_multiply
854                                   (h->reconnect_time, 2));
855     LOG (GNUNET_ERROR_TYPE_DEBUG, 
856          "Next retry in %s\n",
857          GNUNET_STRINGS_relative_time_to_string (h->reconnect_time,
858                                                  GNUNET_NO));
859     GNUNET_break (0);
860     return GNUNET_NO;
861   }
862   else
863   {
864     h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
865   }
866   send_connect (h);
867   /* Rebuild all tunnels */
868   for (t = h->tunnels_head; NULL != t; t = t->next)
869   {
870     struct GNUNET_MESH_TunnelMessage tmsg;
871     struct GNUNET_MESH_PeerControl pmsg;
872
873     if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
874     {
875       /* Tunnel was created by service (incoming tunnel) */
876       /* TODO: Notify service of missing tunnel, to request
877        * creator to recreate path (find a path to him via DHT?)
878        */
879       continue;
880     }
881     t->next_send_pid = 0;
882     t->max_send_pid = INITIAL_WINDOW_SIZE - 1;
883     t->last_recv_pid = (uint32_t) -1;
884     tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
885     tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
886     tmsg.tunnel_id = htonl (t->tid);
887     send_packet (h, &tmsg.header, t);
888
889     pmsg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
890     pmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
891     pmsg.tunnel_id = htonl (t->tid);
892
893     /* Reconnect all peers */
894     /* If the tunnel was "by type", dont connect individual peers */
895     for (i = 0; i < t->npeers && 0 == t->napps; i++)
896     {
897       GNUNET_PEER_resolve (t->peers[i]->id, &pmsg.peer);
898       if (NULL != t->disconnect_handler && t->peers[i]->connected)
899         t->disconnect_handler (t->cls, &pmsg.peer);
900       send_packet (t->mesh, &pmsg.header, t);
901     }
902     /* Reconnect all types, if any  */
903     for (i = 0; i < t->napps; i++)
904     {
905       struct GNUNET_MESH_ConnectPeerByType msg;
906
907       msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
908       msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
909       msg.tunnel_id = htonl (t->tid);
910       msg.type = htonl (t->apps[i]);
911       send_packet (t->mesh, &msg.header, t);
912     }
913     if (GNUNET_NO == t->buffering)
914       GNUNET_MESH_tunnel_buffer (t, GNUNET_NO);
915     if (GNUNET_YES == t->speed_min)
916       GNUNET_MESH_tunnel_speed_min (t);
917   }
918   return GNUNET_YES;
919 }
920
921 /**
922  * Reconnect callback: tries to reconnect again after a failer previous
923  * reconnecttion
924  * @param cls closure (mesh handle)
925  * @param tc task context
926  */
927 static void
928 reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
929 {
930   struct GNUNET_MESH_Handle *h = cls;
931
932   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
933   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
934     return;
935   do_reconnect (h);
936 }
937
938
939 /**
940  * Reconnect to the service, retransmit all infomation to try to restore the
941  * original state.
942  *
943  * @param h handle to the mesh
944  *
945  * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
946  */
947 static void
948 reconnect (struct GNUNET_MESH_Handle *h)
949 {
950   LOG (GNUNET_ERROR_TYPE_DEBUG, "Requested RECONNECT\n");
951   h->in_receive = GNUNET_NO;
952   if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task)
953     h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
954                                                       &reconnect_cbk, h);
955 }
956
957
958 /******************************************************************************/
959 /***********************      RECEIVE HANDLERS     ****************************/
960 /******************************************************************************/
961
962 /**
963  * Process the new tunnel notification and add it to the tunnels in the handle
964  *
965  * @param h     The mesh handle
966  * @param msg   A message with the details of the new incoming tunnel
967  */
968 static void
969 process_tunnel_created (struct GNUNET_MESH_Handle *h,
970                         const struct GNUNET_MESH_TunnelNotification *msg)
971 {
972   struct GNUNET_MESH_Tunnel *t;
973   MESH_TunnelNumber tid;
974
975   tid = ntohl (msg->tunnel_id);
976   LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming tunnel %X\n", tid);
977   if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
978   {
979     GNUNET_break (0);
980     return;
981   }
982   if (NULL != h->new_tunnel)
983   {
984     struct GNUNET_ATS_Information atsi;
985
986     t = create_tunnel (h, tid);
987     t->owner = GNUNET_PEER_intern (&msg->peer);
988     t->npeers = 1;
989     t->peers = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer *));
990     t->peers[0] = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
991     t->peers[0]->t = t;
992     t->peers[0]->connected = 1;
993     t->peers[0]->id = t->owner;
994     GNUNET_PEER_change_rc (t->owner, 1);
995     t->mesh = h;
996     t->tid = tid;
997     if ((msg->opt & MESH_TUNNEL_OPT_NOBUFFER) != 0)
998       t->buffering = GNUNET_NO;
999     else
1000       t->buffering = GNUNET_YES;
1001     if ((msg->opt & MESH_TUNNEL_OPT_SPEED_MIN) != 0)
1002       t->speed_min = GNUNET_YES;
1003     atsi.type = 0;
1004     atsi.value = 0;
1005     LOG (GNUNET_ERROR_TYPE_DEBUG, "  created tunnel %p\n", t);
1006     t->ctx = h->new_tunnel (h->cls, t, &msg->peer, &atsi);
1007     LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n");
1008   }
1009   else
1010   {
1011     struct GNUNET_MESH_TunnelMessage d_msg;
1012
1013     LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming tunnels\n");
1014
1015     d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1016     d_msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1017     d_msg.tunnel_id = msg->tunnel_id;
1018
1019     send_packet (h, &d_msg.header, NULL);
1020   }
1021   return;
1022 }
1023
1024
1025 /**
1026  * Process the tunnel destroy notification and free associated resources
1027  *
1028  * @param h     The mesh handle
1029  * @param msg   A message with the details of the tunnel being destroyed
1030  */
1031 static void
1032 process_tunnel_destroy (struct GNUNET_MESH_Handle *h,
1033                         const struct GNUNET_MESH_TunnelMessage *msg)
1034 {
1035   struct GNUNET_MESH_Tunnel *t;
1036   MESH_TunnelNumber tid;
1037
1038   tid = ntohl (msg->tunnel_id);
1039   t = retrieve_tunnel (h, tid);
1040
1041   if (NULL == t)
1042   {
1043     return;
1044   }
1045   if (0 == t->owner)
1046   {
1047     GNUNET_break (0);
1048   }
1049   LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid);
1050   destroy_tunnel (t, GNUNET_YES);
1051   return;
1052 }
1053
1054
1055 /**
1056  * Process the new peer event and notify the upper level of it
1057  *
1058  * @param h     The mesh handle
1059  * @param msg   A message with the details of the peer event
1060  */
1061 static void
1062 process_peer_event (struct GNUNET_MESH_Handle *h,
1063                     const struct GNUNET_MESH_PeerControl *msg)
1064 {
1065   struct GNUNET_MESH_Tunnel *t;
1066   struct GNUNET_MESH_Peer *p;
1067   struct GNUNET_ATS_Information atsi;
1068   GNUNET_PEER_Id id;
1069   uint16_t size;
1070
1071   LOG (GNUNET_ERROR_TYPE_DEBUG, "processig peer event\n");
1072   size = ntohs (msg->header.size);
1073   if (size != sizeof (struct GNUNET_MESH_PeerControl))
1074   {
1075     GNUNET_break (0);
1076     return;
1077   }
1078   t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
1079   if (NULL == t)
1080   {
1081     GNUNET_break (0);
1082     return;
1083   }
1084   id = GNUNET_PEER_search (&msg->peer);
1085   if ((p = retrieve_peer (t, id)) == NULL)
1086     p = add_peer_to_tunnel (t, &msg->peer);
1087   if (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD == ntohs (msg->header.type))
1088   {
1089     LOG (GNUNET_ERROR_TYPE_DEBUG, "adding peer\n");
1090     if (NULL != t->connect_handler)
1091     {
1092       atsi.type = 0;
1093       atsi.value = 0;
1094       t->connect_handler (t->cls, &msg->peer, &atsi);
1095     }
1096     p->connected = 1;
1097   }
1098   else
1099   {
1100     LOG (GNUNET_ERROR_TYPE_DEBUG, "removing peer\n");
1101     if (NULL != t->disconnect_handler && p->connected)
1102     {
1103       t->disconnect_handler (t->cls, &msg->peer);
1104     }
1105     remove_peer_from_tunnel (p);
1106     GNUNET_free (p);
1107   }
1108   LOG (GNUNET_ERROR_TYPE_DEBUG, "processing peer event END\n");
1109 }
1110
1111
1112 /**
1113  * Process the incoming data packets
1114  *
1115  * @param h         The mesh handle
1116  * @param message   A message encapsulating the data
1117  * 
1118  * @return GNUNET_YES if everything went fine
1119  *         GNUNET_NO if client closed connection (h no longer valid)
1120  */
1121 static int
1122 process_incoming_data (struct GNUNET_MESH_Handle *h,
1123                        const struct GNUNET_MessageHeader *message)
1124 {
1125   const struct GNUNET_MessageHeader *payload;
1126   const struct GNUNET_MESH_MessageHandler *handler;
1127   const struct GNUNET_PeerIdentity *peer;
1128   struct GNUNET_MESH_Unicast *ucast;
1129   struct GNUNET_MESH_Multicast *mcast;
1130   struct GNUNET_MESH_ToOrigin *to_orig;
1131   struct GNUNET_MESH_Tunnel *t;
1132   unsigned int i;
1133   uint32_t pid;
1134   uint16_t type;
1135
1136   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n");
1137   type = ntohs (message->type);
1138   switch (type)
1139   {
1140   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1141     ucast = (struct GNUNET_MESH_Unicast *) message;
1142
1143     t = retrieve_tunnel (h, ntohl (ucast->tid));
1144     payload = (struct GNUNET_MessageHeader *) &ucast[1];
1145     peer = &ucast->oid;
1146     pid = ntohl (ucast->pid);
1147     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ucast on tunnel %s [%X]\n",
1148          GNUNET_i2s (peer), ntohl (ucast->tid));
1149     break;
1150   case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1151     mcast = (struct GNUNET_MESH_Multicast *) message;
1152     t = retrieve_tunnel (h, ntohl (mcast->tid));
1153     payload = (struct GNUNET_MessageHeader *) &mcast[1];
1154     peer = &mcast->oid;
1155     pid = ntohl (mcast->pid);
1156     LOG (GNUNET_ERROR_TYPE_DEBUG, "  mcast on tunnel %s [%X]\n",
1157          GNUNET_i2s (peer), ntohl (mcast->tid));
1158     break;
1159   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1160     to_orig = (struct GNUNET_MESH_ToOrigin *) message;
1161     t = retrieve_tunnel (h, ntohl (to_orig->tid));
1162     payload = (struct GNUNET_MessageHeader *) &to_orig[1];
1163     peer = &to_orig->sender;
1164     pid = ntohl (to_orig->pid);
1165     LOG (GNUNET_ERROR_TYPE_DEBUG, "  torig on tunnel %s [%X]\n",
1166          GNUNET_i2s (peer), ntohl (to_orig->tid));
1167     break;
1168   default:
1169     GNUNET_break (0);
1170     return GNUNET_YES;
1171   }
1172   LOG (GNUNET_ERROR_TYPE_DEBUG, "  pid %u\n", pid);
1173   if (NULL == t)
1174   {
1175     /* Tunnel was ignored/destroyed, probably service didn't get it yet */
1176     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ignored!\n");
1177     return GNUNET_YES;
1178   }
1179   if (GNUNET_YES ==
1180       GMC_is_pid_bigger(pid, t->max_recv_pid))
1181   {
1182     GNUNET_break (0);
1183     LOG (GNUNET_ERROR_TYPE_WARNING,
1184          "  unauthorized message! (%u, max %u)\n",
1185          pid, t->max_recv_pid);
1186     // FIXME fc what now? accept? reject?
1187     return GNUNET_YES;
1188   }
1189   t->last_recv_pid = pid;
1190   type = ntohs (payload->type);
1191   send_ack (h, t);
1192   for (i = 0; i < h->n_handlers; i++)
1193   {
1194     handler = &h->message_handlers[i];
1195     if (handler->type == type)
1196     {
1197       struct GNUNET_ATS_Information atsi;
1198
1199       atsi.type = 0;
1200       atsi.value = 0;
1201       if (GNUNET_OK !=
1202           handler->callback (h->cls, t, &t->ctx, peer, payload, &atsi))
1203       {
1204         LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n");
1205         GNUNET_MESH_disconnect (h);
1206         return GNUNET_NO;
1207       }
1208       else
1209       {
1210         LOG (GNUNET_ERROR_TYPE_DEBUG,
1211              "callback completed successfully\n");
1212       }
1213     }
1214   }
1215   return GNUNET_YES;
1216 }
1217
1218
1219 /**
1220  * Process a local ACK message, enabling the client to send
1221  * more data to the service.
1222  * 
1223  * @param h Mesh handle.
1224  * @param message Message itself.
1225  */
1226 static void
1227 process_ack (struct GNUNET_MESH_Handle *h,
1228              const struct GNUNET_MessageHeader *message)
1229 {
1230   struct GNUNET_MESH_LocalAck *msg;
1231   struct GNUNET_MESH_Tunnel *t;
1232   uint32_t ack;
1233
1234   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n");
1235   h->acks_recv++;
1236   msg = (struct GNUNET_MESH_LocalAck *) message;
1237
1238   t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
1239
1240   if (NULL == t)
1241   {
1242     LOG (GNUNET_ERROR_TYPE_WARNING,
1243          "ACK on unknown tunnel %X\n",
1244          ntohl (msg->tunnel_id));
1245     return;
1246   }
1247   ack = ntohl (msg->max_pid);
1248   LOG (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X, ack %u!\n", t->tid, ack);
1249   if (GNUNET_YES == GMC_is_pid_bigger(ack, t->max_send_pid))
1250     t->max_send_pid = ack;
1251   else
1252     return;
1253   if (NULL == h->th && 0 < t->packet_size)
1254   {
1255     LOG (GNUNET_ERROR_TYPE_DEBUG, "  tmt rdy was NULL, requesting!\n", t->tid, ack);
1256     h->th =
1257         GNUNET_CLIENT_notify_transmit_ready (h->client, t->packet_size,
1258                                              GNUNET_TIME_UNIT_FOREVER_REL,
1259                                              GNUNET_YES, &send_callback, h);
1260   }
1261 }
1262
1263
1264 /**
1265  * Process a local monitor reply, pass info to the user.
1266  *
1267  * @param h Mesh handle.
1268  * @param message Message itself.
1269  */
1270 static void
1271 process_monitor (struct GNUNET_MESH_Handle *h,
1272                  const struct GNUNET_MessageHeader *message)
1273 {
1274   struct GNUNET_MESH_LocalMonitor *msg;
1275   uint32_t npeers;
1276
1277   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Monitor messasge received\n");
1278
1279   if (NULL == h->tunnels_cb)
1280   {
1281     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
1282     return;
1283   }
1284
1285   msg = (struct GNUNET_MESH_LocalMonitor *) message;
1286   npeers = ntohl (msg->npeers);
1287   if (ntohs (message->size)  !=
1288       (sizeof (struct GNUNET_MESH_LocalMonitor) +
1289        npeers * sizeof (struct GNUNET_PeerIdentity)))
1290   {
1291     GNUNET_break_op (0);
1292     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1293                 "Monitor message: size %hu - expected %u (%u peers)\n",
1294                 ntohs (message->size),
1295                 sizeof (struct GNUNET_MESH_LocalMonitor) +
1296                 npeers * sizeof (struct GNUNET_PeerIdentity),
1297                 npeers);
1298     return;
1299   }
1300   h->tunnels_cb (h->tunnels_cls,
1301                  &msg->owner,
1302                  ntohl (msg->tunnel_id),
1303                  (struct GNUNET_PeerIdentity *) &msg[1],
1304                  npeers);
1305 }
1306
1307
1308
1309 /**
1310  * Process a local monitor_tunnel reply, pass info to the user.
1311  *
1312  * @param h Mesh handle.
1313  * @param message Message itself.
1314  */
1315 static void
1316 process_monitor_tunnel (struct GNUNET_MESH_Handle *h,
1317                         const struct GNUNET_MessageHeader *message)
1318 {
1319 }
1320
1321
1322 /**
1323  * Function to process all messages received from the service
1324  *
1325  * @param cls closure
1326  * @param msg message received, NULL on timeout or fatal error
1327  */
1328 static void
1329 msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
1330 {
1331   struct GNUNET_MESH_Handle *h = cls;
1332
1333   if (msg == NULL)
1334   {
1335     LOG (GNUNET_ERROR_TYPE_DEBUG, 
1336          "Mesh service disconnected, reconnecting\n", h);
1337     reconnect (h);
1338     return;
1339   }
1340   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n",
1341        GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1342   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n",
1343        GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1344   switch (ntohs (msg->type))
1345   {
1346     /* Notify of a new incoming tunnel */
1347   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE:
1348     process_tunnel_created (h, (struct GNUNET_MESH_TunnelNotification *) msg);
1349     break;
1350     /* Notify of a tunnel disconnection */
1351   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1352     process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg);
1353     break;
1354     /* Notify of a new peer or a peer disconnect in the tunnel */
1355   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD:
1356   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL:
1357     process_peer_event (h, (struct GNUNET_MESH_PeerControl *) msg);
1358     break;
1359     /* Notify of a new data packet in the tunnel */
1360   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1361   case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1362   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1363     if (GNUNET_NO == process_incoming_data (h, msg))
1364       return;
1365     break;
1366   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
1367     process_ack (h, msg);
1368     break;
1369   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR:
1370     process_monitor (h, msg);
1371     break;
1372   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR_TUNNEL:
1373     process_monitor_tunnel (h, msg);
1374     break;
1375   default:
1376     /* We shouldn't get any other packages, log and ignore */
1377     LOG (GNUNET_ERROR_TYPE_WARNING,
1378          "unsolicited message form service (type %s)\n",
1379          GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1380   }
1381   LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n");
1382   if (GNUNET_YES == h->in_receive)
1383   {
1384     GNUNET_CLIENT_receive (h->client, &msg_received, h,
1385                            GNUNET_TIME_UNIT_FOREVER_REL);
1386   }
1387   else
1388   {
1389     LOG (GNUNET_ERROR_TYPE_DEBUG,
1390          "in receive off, not calling CLIENT_receive\n");
1391   }
1392 }
1393
1394
1395 /******************************************************************************/
1396 /************************       SEND FUNCTIONS     ****************************/
1397 /******************************************************************************/
1398
1399 /**
1400  * Function called to send a message to the service.
1401  * "buf" will be NULL and "size" zero if the socket was closed for writing in
1402  * the meantime.
1403  *
1404  * @param cls closure, the mesh handle
1405  * @param size number of bytes available in buf
1406  * @param buf where the callee should write the connect message
1407  * @return number of bytes written to buf
1408  */
1409 static size_t
1410 send_callback (void *cls, size_t size, void *buf)
1411 {
1412   struct GNUNET_MESH_Handle *h = cls;
1413   struct GNUNET_MESH_TransmitHandle *th;
1414   struct GNUNET_MESH_TransmitHandle *next;
1415   struct GNUNET_MESH_Tunnel *t;
1416   char *cbuf = buf;
1417   size_t tsize;
1418   size_t psize;
1419   size_t nsize;
1420
1421   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
1422   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() Buffer %u\n", size);
1423   if ((0 == size) || (NULL == buf))
1424   {
1425     LOG (GNUNET_ERROR_TYPE_DEBUG, "Received NULL send callback on %p\n", h);
1426     reconnect (h);
1427     h->th = NULL;
1428     return 0;
1429   }
1430   tsize = 0;
1431   next = h->th_head;
1432   nsize = message_ready_size (h);
1433   while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize))
1434   {
1435     t = th->tunnel;
1436     if (GNUNET_YES == th_is_payload (th))
1437     {
1438       LOG (GNUNET_ERROR_TYPE_DEBUG, " payload\n");
1439       if (GNUNET_YES == GMC_is_pid_bigger(t->next_send_pid, t->max_send_pid))
1440       {
1441         /* This tunnel is not ready to transmit yet, try next message */
1442         next = th->next;
1443         continue;
1444       }
1445       t->packet_size = 0;
1446       if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1447       {
1448         /* traffic to origin */
1449         struct GNUNET_MESH_ToOrigin to;
1450         struct GNUNET_MessageHeader *mh;
1451
1452         GNUNET_assert (size >= th->size);
1453         mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (to)];
1454         psize = th->notify (th->notify_cls, size - sizeof (to), mh);
1455         LOG (GNUNET_ERROR_TYPE_DEBUG, "  to origin, type %s\n",
1456              GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1457         if (psize > 0)
1458         {
1459           psize += sizeof (to);
1460           GNUNET_assert (size >= psize);
1461           to.header.size = htons (psize);
1462           to.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
1463           to.tid = htonl (t->tid);
1464           to.pid = htonl (t->next_send_pid);
1465           to.ttl = 0;
1466           memset (&to.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1467           memset (&to.sender, 0, sizeof (struct GNUNET_PeerIdentity));
1468           memcpy (cbuf, &to, sizeof (to));
1469         }
1470       }
1471       else if (th->target == 0)
1472       {
1473         /* multicast */
1474         struct GNUNET_MESH_Multicast mc;
1475         struct GNUNET_MessageHeader *mh;
1476
1477         GNUNET_assert (size >= th->size);
1478         mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (mc)];
1479         psize = th->notify (th->notify_cls, size - sizeof (mc), mh);
1480         LOG (GNUNET_ERROR_TYPE_DEBUG, "  multicast, type %s\n",
1481              GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1482         if (psize > 0)
1483         {
1484           psize += sizeof (mc);
1485           GNUNET_assert (size >= psize);
1486           mc.header.size = htons (psize);
1487           mc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
1488           mc.tid = htonl (t->tid);
1489           mc.pid = htonl (t->next_send_pid);
1490           mc.ttl = 0;
1491           memset (&mc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1492           memcpy (cbuf, &mc, sizeof (mc));
1493         }
1494       }
1495       else
1496       {
1497         /* unicast */
1498         struct GNUNET_MESH_Unicast uc;
1499         struct GNUNET_MessageHeader *mh;
1500
1501         GNUNET_assert (size >= th->size);
1502         mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (uc)];
1503         psize = th->notify (th->notify_cls, size - sizeof (uc), mh);
1504         LOG (GNUNET_ERROR_TYPE_DEBUG, "  unicast, type %s\n",
1505              GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1506         if (psize > 0)
1507         {
1508           psize += sizeof (uc);
1509           GNUNET_assert (size >= psize);
1510           uc.header.size = htons (psize);
1511           uc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
1512           uc.tid = htonl (t->tid);
1513           uc.pid = htonl (t->next_send_pid);
1514           uc.ttl = 0;
1515           memset (&uc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1516           GNUNET_PEER_resolve (th->target, &uc.destination);
1517           memcpy (cbuf, &uc, sizeof (uc));
1518         }
1519       }
1520       t->next_send_pid++;
1521     }
1522     else
1523     {
1524       struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1];
1525
1526       LOG (GNUNET_ERROR_TYPE_DEBUG, "  mesh traffic, type %s\n",
1527            GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1528       memcpy (cbuf, &th[1], th->size);
1529       psize = th->size;
1530     }
1531     if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1532       GNUNET_SCHEDULER_cancel (th->timeout_task);
1533     GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1534     GNUNET_free (th);
1535     next = h->th_head;
1536     nsize = message_ready_size (h);
1537     cbuf += psize;
1538     size -= psize;
1539     tsize += psize;
1540   }
1541   LOG (GNUNET_ERROR_TYPE_DEBUG, "  total size: %u\n", tsize);
1542   h->th = NULL;
1543   size = message_ready_size (h);
1544   if (0 != size)
1545   {
1546     LOG (GNUNET_ERROR_TYPE_DEBUG, "  next size: %u\n", size);
1547     h->th =
1548         GNUNET_CLIENT_notify_transmit_ready (h->client, size,
1549                                              GNUNET_TIME_UNIT_FOREVER_REL,
1550                                              GNUNET_YES, &send_callback, h);
1551   }
1552   else
1553   {
1554     if (NULL != h->th_head)
1555       LOG (GNUNET_ERROR_TYPE_DEBUG, "  can't transmit any more\n");
1556     else
1557       LOG (GNUNET_ERROR_TYPE_DEBUG, "  nothing left to transmit\n");
1558   }
1559   if (GNUNET_NO == h->in_receive)
1560   {
1561     LOG (GNUNET_ERROR_TYPE_DEBUG, " start receiving from service\n");
1562     h->in_receive = GNUNET_YES;
1563     GNUNET_CLIENT_receive (h->client, &msg_received, h,
1564                            GNUNET_TIME_UNIT_FOREVER_REL);
1565   }
1566   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() END\n");
1567   return tsize;
1568 }
1569
1570
1571 /**
1572  * Auxiliary function to send an already constructed packet to the service.
1573  * Takes care of creating a new queue element, copying the message and
1574  * calling the tmt_rdy function if necessary.
1575  * 
1576  * @param h mesh handle
1577  * @param msg message to transmit
1578  * @param tunnel tunnel this send is related to (NULL if N/A)
1579  */
1580 static void
1581 send_packet (struct GNUNET_MESH_Handle *h,
1582              const struct GNUNET_MessageHeader *msg,
1583              struct GNUNET_MESH_Tunnel *tunnel)
1584 {
1585   struct GNUNET_MESH_TransmitHandle *th;
1586   size_t msize;
1587
1588   LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n",
1589        GNUNET_MESH_DEBUG_M2S(ntohs(msg->type)));
1590   msize = ntohs (msg->size);
1591   th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize);
1592   th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1593   th->size = msize;
1594   th->tunnel = tunnel;
1595   memcpy (&th[1], msg, msize);
1596   add_to_queue (h, th);
1597   LOG (GNUNET_ERROR_TYPE_DEBUG, "  queued\n");
1598   if (NULL != h->th)
1599     return;
1600   LOG (GNUNET_ERROR_TYPE_DEBUG, "  calling ntfy tmt rdy for %u bytes\n", msize);
1601   h->th =
1602       GNUNET_CLIENT_notify_transmit_ready (h->client, msize,
1603                                            GNUNET_TIME_UNIT_FOREVER_REL,
1604                                            GNUNET_YES, &send_callback, h);
1605 }
1606
1607
1608 /******************************************************************************/
1609 /**********************      API CALL DEFINITIONS     *************************/
1610 /******************************************************************************/
1611
1612 /**
1613  * Connect to the mesh service.
1614  *
1615  * @param cfg configuration to use
1616  * @param cls closure for the various callbacks that follow
1617  *            (including handlers in the handlers array)
1618  * @param new_tunnel function called when an *inbound* tunnel is created
1619  * @param cleaner function called when an *inbound* tunnel is destroyed by the
1620  *                remote peer, it is *not* called if GNUNET_MESH_tunnel_destroy
1621  *                is called on the tunnel
1622  * @param handlers callbacks for messages we care about, NULL-terminated
1623  *                note that the mesh is allowed to drop notifications about
1624  *                inbound messages if the client does not process them fast
1625  *                enough (for this notification type, a bounded queue is used)
1626  * @param stypes list of the applications that this client claims to provide
1627  * @return handle to the mesh service NULL on error
1628  *         (in this case, init is never called)
1629  */
1630 struct GNUNET_MESH_Handle *
1631 GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
1632                      GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
1633                      GNUNET_MESH_TunnelEndHandler cleaner,
1634                      const struct GNUNET_MESH_MessageHandler *handlers,
1635                      const GNUNET_MESH_ApplicationType *stypes)
1636 {
1637   struct GNUNET_MESH_Handle *h;
1638
1639   LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n");
1640   h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
1641   LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h);
1642   h->cfg = cfg;
1643   h->new_tunnel = new_tunnel;
1644   h->cleaner = cleaner;
1645   h->client = GNUNET_CLIENT_connect ("mesh", cfg);
1646   if (h->client == NULL)
1647   {
1648     GNUNET_break (0);
1649     GNUNET_free (h);
1650     return NULL;
1651   }
1652   h->cls = cls;
1653   /* FIXME memdup? */
1654   h->applications = stypes;
1655   h->message_handlers = handlers;
1656   h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
1657   h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
1658   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1659
1660   /* count handlers and apps, calculate size */
1661   for (h->n_applications = 0; stypes[h->n_applications]; h->n_applications++) ;
1662   for (h->n_handlers = 0; handlers[h->n_handlers].type; h->n_handlers++) ;
1663   send_connect (h);
1664   LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n");
1665   return h;
1666 }
1667
1668
1669 /**
1670  * Disconnect from the mesh service. All tunnels will be destroyed. All tunnel
1671  * disconnect callbacks will be called on any still connected peers, notifying
1672  * about their disconnection. The registered inbound tunnel cleaner will be
1673  * called should any inbound tunnels still exist.
1674  *
1675  * @param handle connection to mesh to disconnect
1676  */
1677 void
1678 GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
1679 {
1680   struct GNUNET_MESH_Tunnel *t;
1681   struct GNUNET_MESH_Tunnel *aux;
1682   struct GNUNET_MESH_TransmitHandle *th;
1683
1684   LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH DISCONNECT\n");
1685
1686 #if DEBUG_ACK
1687   LOG (GNUNET_ERROR_TYPE_INFO, "Sent %d ACKs\n", handle->acks_sent);
1688   LOG (GNUNET_ERROR_TYPE_INFO, "Recv %d ACKs\n\n", handle->acks_recv);
1689 #endif
1690
1691   t = handle->tunnels_head;
1692   while (NULL != t)
1693   {
1694     aux = t->next;
1695     if (t->tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1696     {
1697       GNUNET_break (0);
1698       LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X not destroyed\n", t->tid);
1699     }
1700     destroy_tunnel (t, GNUNET_YES);
1701     t = aux;
1702   }
1703   while ( (th = handle->th_head) != NULL)
1704   {
1705     struct GNUNET_MessageHeader *msg;
1706
1707     /* Make sure it is an allowed packet (everything else should have been
1708      * already canceled).
1709      */
1710     GNUNET_break (GNUNET_NO == th_is_payload (th));
1711     msg = (struct GNUNET_MessageHeader *) &th[1];
1712     switch (ntohs(msg->type))
1713     {
1714       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT:
1715       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1716       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR:
1717         break;
1718       default:
1719         GNUNET_break (0);
1720         LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n",
1721              ntohs(msg->type));
1722     }
1723
1724     GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th);
1725     GNUNET_free (th);
1726   }
1727
1728   if (NULL != handle->th)
1729   {
1730     GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
1731     handle->th = NULL;
1732   }
1733   if (NULL != handle->client)
1734   {
1735     GNUNET_CLIENT_disconnect (handle->client);
1736     handle->client = NULL;
1737   }
1738   if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task)
1739   {
1740     GNUNET_SCHEDULER_cancel(handle->reconnect_task);
1741     handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1742   }
1743   GNUNET_free (handle);
1744 }
1745
1746
1747 /**
1748  * Announce to ther peer the availability of services described by the regex,
1749  * in order to be reachable to other peers via connect_by_string.
1750  * 
1751  * Note that the first 8 characters are considered to be part of a prefix,
1752  * (for instance 'gnunet://'). If you put a variable part in there (*, +. ()),
1753  * all matching strings will be stored in the DHT.
1754  *
1755  * @param h Handle to mesh.
1756  * @param regex String with the regular expression describing local services.
1757  * @param compression_characters How many characters can be assigned to one
1758  *                               edge of the graph. The bigger the variability
1759  *                               of the data, the smaller this parameter should
1760  *                               be (down to 1).
1761  *                               For maximum compression, use strlen (regex)
1762  *                               or 0 (special value). Use with care!
1763  */
1764 void
1765 GNUNET_MESH_announce_regex (struct GNUNET_MESH_Handle *h,
1766                             const char *regex,
1767                             unsigned int compression_characters)
1768 {
1769   struct GNUNET_MESH_RegexAnnounce *msg;
1770   size_t len;
1771   size_t msgsize;
1772
1773   len = strlen (regex);
1774   msgsize = sizeof(struct GNUNET_MESH_RegexAnnounce) + len;
1775   GNUNET_assert (UINT16_MAX > msgsize);
1776
1777   {
1778     char buffer[msgsize];
1779
1780     msg = (struct GNUNET_MESH_RegexAnnounce *) buffer;
1781     msg->header.size = htons (msgsize);
1782     msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ANNOUNCE_REGEX);
1783     msg->compression_characters = htons (compression_characters);
1784     memcpy (&msg[1], regex, len);
1785
1786     send_packet(h, &msg->header, NULL);
1787   }
1788 }
1789
1790 /**
1791  * Create a new tunnel (we're initiator and will be allowed to add/remove peers
1792  * and to broadcast).
1793  *
1794  * @param h mesh handle
1795  * @param tunnel_ctx client's tunnel context to associate with the tunnel
1796  * @param connect_handler function to call when peers are actually connected
1797  * @param disconnect_handler function to call when peers are disconnected
1798  * @param handler_cls closure for connect/disconnect handlers
1799  */
1800 struct GNUNET_MESH_Tunnel *
1801 GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, void *tunnel_ctx,
1802                            GNUNET_MESH_PeerConnectHandler connect_handler,
1803                            GNUNET_MESH_PeerDisconnectHandler disconnect_handler,
1804                            void *handler_cls)
1805 {
1806   struct GNUNET_MESH_Tunnel *t;
1807   struct GNUNET_MESH_TunnelMessage msg;
1808
1809   LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new tunnel\n");
1810   t = create_tunnel (h, 0);
1811   LOG (GNUNET_ERROR_TYPE_DEBUG, "  at %p\n", t);
1812   LOG (GNUNET_ERROR_TYPE_DEBUG, "  number %X\n", t->tid);
1813   t->connect_handler = connect_handler;
1814   t->disconnect_handler = disconnect_handler;
1815   t->cls = handler_cls;
1816   t->ctx = tunnel_ctx;
1817   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
1818   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1819   msg.tunnel_id = htonl (t->tid);
1820   send_packet (h, &msg.header, t);
1821   return t;
1822 }
1823
1824
1825 /**
1826  * Destroy an existing tunnel. The existing callback for the tunnel will NOT
1827  * be called.
1828  *
1829  * @param tunnel tunnel handle
1830  */
1831 void
1832 GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel)
1833 {
1834   struct GNUNET_MESH_Handle *h;
1835   struct GNUNET_MESH_TunnelMessage msg;
1836   struct GNUNET_MESH_TransmitHandle *th;
1837
1838   LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying tunnel\n");
1839   h = tunnel->mesh;
1840
1841   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1842   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1843   msg.tunnel_id = htonl (tunnel->tid);
1844   th = h->th_head;
1845   while (th != NULL)
1846   {
1847     struct GNUNET_MESH_TransmitHandle *aux;
1848     if (th->tunnel == tunnel)
1849     {
1850       aux = th->next;
1851       /* FIXME call the handler? */
1852       if (GNUNET_YES == th_is_payload (th))
1853         th->notify (th->notify_cls, 0, NULL);
1854       GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1855       GNUNET_free (th);
1856       th = aux;
1857     }
1858     else
1859       th = th->next;
1860   }
1861
1862   destroy_tunnel (tunnel, GNUNET_NO);
1863   send_packet (h, &msg.header, NULL);
1864 }
1865
1866 /**
1867  * Request that the tunnel data rate is limited to the speed of the slowest
1868  * receiver.
1869  *
1870  * @param tunnel Tunnel affected.
1871  */
1872 void
1873 GNUNET_MESH_tunnel_speed_min (struct GNUNET_MESH_Tunnel *tunnel)
1874 {
1875   struct GNUNET_MESH_TunnelMessage msg;
1876   struct GNUNET_MESH_Handle *h;
1877
1878   h = tunnel->mesh;
1879   tunnel->speed_min = GNUNET_YES;
1880
1881   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MIN);
1882   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1883   msg.tunnel_id = htonl (tunnel->tid);
1884
1885   send_packet (h, &msg.header, NULL);
1886 }
1887
1888
1889 /**
1890  * Request that the tunnel data rate is limited to the speed of the fastest
1891  * receiver. This is the default behavior.
1892  *
1893  * @param tunnel Tunnel affected.
1894  */
1895 void
1896 GNUNET_MESH_tunnel_speed_max (struct GNUNET_MESH_Tunnel *tunnel)
1897 {
1898   struct GNUNET_MESH_TunnelMessage msg;
1899   struct GNUNET_MESH_Handle *h;
1900
1901   h = tunnel->mesh;
1902   tunnel->speed_min = GNUNET_NO;
1903
1904   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MAX);
1905   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1906   msg.tunnel_id = htonl (tunnel->tid);
1907
1908   send_packet (h, &msg.header, NULL);
1909 }
1910
1911 /**
1912  * Turn on/off the buffering status of the tunnel.
1913  * 
1914  * @param tunnel Tunnel affected.
1915  * @param buffer GNUNET_YES to turn buffering on (default),
1916  *               GNUNET_NO otherwise.
1917  */
1918 void
1919 GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer)
1920 {
1921   struct GNUNET_MESH_TunnelMessage msg;
1922   struct GNUNET_MESH_Handle *h;
1923
1924   h = tunnel->mesh;
1925   tunnel->buffering = buffer;
1926   tunnel->max_send_pid = tunnel->next_send_pid;
1927
1928   if (GNUNET_YES == buffer)
1929     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER);
1930   else
1931     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER);
1932   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1933   msg.tunnel_id = htonl (tunnel->tid);
1934
1935   send_packet (h, &msg.header, NULL);
1936 }
1937
1938 /**
1939  * Request that a peer should be added to the tunnel.  The existing
1940  * connect handler will be called ONCE with either success or failure.
1941  * This function should NOT be called again with the same peer before the
1942  * connect handler is called.
1943  *
1944  * @param tunnel handle to existing tunnel
1945  * @param peer peer to add
1946  */
1947 void
1948 GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
1949                                       const struct GNUNET_PeerIdentity *peer)
1950 {
1951   struct GNUNET_MESH_PeerControl msg;
1952   GNUNET_PEER_Id peer_id;
1953   unsigned int i;
1954
1955   peer_id = GNUNET_PEER_intern (peer);
1956   for (i = 0; i < tunnel->npeers; i++)
1957   {
1958     if (tunnel->peers[i]->id == peer_id)
1959     {
1960       /* Peer already exists in tunnel */
1961       GNUNET_PEER_change_rc (peer_id, -1);
1962       GNUNET_break (0);
1963       return;
1964     }
1965   }
1966   if (NULL == add_peer_to_tunnel (tunnel, peer))
1967     return;
1968
1969   msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
1970   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
1971   msg.tunnel_id = htonl (tunnel->tid);
1972   msg.peer = *peer;
1973   send_packet (tunnel->mesh, &msg.header, tunnel);
1974
1975   return;
1976 }
1977
1978
1979 /**
1980  * Request that a peer should be removed from the tunnel.  The existing
1981  * disconnect handler will be called ONCE if we were connected.
1982  *
1983  * @param tunnel handle to existing tunnel
1984  * @param peer peer to remove
1985  */
1986 void
1987 GNUNET_MESH_peer_request_connect_del (struct GNUNET_MESH_Tunnel *tunnel,
1988                                       const struct GNUNET_PeerIdentity *peer)
1989 {
1990   struct GNUNET_MESH_PeerControl msg;
1991   GNUNET_PEER_Id peer_id;
1992   unsigned int i;
1993
1994   peer_id = GNUNET_PEER_search (peer);
1995   if (0 == peer_id)
1996   {
1997     GNUNET_break (0);
1998     return;
1999   }
2000   for (i = 0; i < tunnel->npeers; i++)
2001     if (tunnel->peers[i]->id == peer_id)
2002       break;
2003   if (i == tunnel->npeers)
2004   {
2005     GNUNET_break (0);
2006     return;
2007   }
2008   if (NULL != tunnel->disconnect_handler && tunnel->peers[i]->connected == 1)
2009     tunnel->disconnect_handler (tunnel->cls, peer);
2010   GNUNET_PEER_change_rc (peer_id, -1);
2011   GNUNET_free (tunnel->peers[i]);
2012   tunnel->peers[i] = tunnel->peers[tunnel->npeers - 1];
2013   GNUNET_array_grow (tunnel->peers, tunnel->npeers, tunnel->npeers - 1);
2014
2015   msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2016   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
2017   msg.tunnel_id = htonl (tunnel->tid);
2018   memcpy (&msg.peer, peer, sizeof (struct GNUNET_PeerIdentity));
2019   send_packet (tunnel->mesh, &msg.header, tunnel);
2020 }
2021
2022
2023 /**
2024  * Request that the mesh should try to connect to a peer supporting the given
2025  * message type.
2026  *
2027  * @param tunnel handle to existing tunnel
2028  * @param app_type application type that must be supported by the peer (MESH
2029  *                 should discover peer in proximity handling this type)
2030  */
2031 void
2032 GNUNET_MESH_peer_request_connect_by_type (struct GNUNET_MESH_Tunnel *tunnel,
2033                                           GNUNET_MESH_ApplicationType app_type)
2034 {
2035   struct GNUNET_MESH_ConnectPeerByType msg;
2036
2037   GNUNET_array_append (tunnel->apps, tunnel->napps, app_type);
2038
2039   LOG (GNUNET_ERROR_TYPE_DEBUG, "* CONNECT BY TYPE *\n");
2040   msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
2041   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
2042   msg.tunnel_id = htonl (tunnel->tid);
2043   msg.type = htonl (app_type);
2044   send_packet (tunnel->mesh, &msg.header, tunnel);
2045 }
2046
2047
2048 /**
2049  * Request that the mesh should try to connect to a peer matching the
2050  * description given in the service string.
2051  * 
2052  * FIXME: allow multiple? how to deal with reconnect?
2053  *
2054  * @param tunnel handle to existing tunnel
2055  * @param description string describing the destination node requirements
2056  */
2057 void
2058 GNUNET_MESH_peer_request_connect_by_string (struct GNUNET_MESH_Tunnel *tunnel,
2059                                             const char *description)
2060 {
2061   struct GNUNET_MESH_ConnectPeerByString *m;
2062   size_t len;
2063   size_t msgsize;
2064
2065   len = strlen (description);
2066   msgsize = sizeof(struct GNUNET_MESH_ConnectPeerByString) + len;
2067   GNUNET_assert (UINT16_MAX > msgsize);
2068   {
2069     char buffer[msgsize];
2070
2071     m = (struct GNUNET_MESH_ConnectPeerByString *) buffer;
2072     m->header.size = htons (msgsize);
2073     m->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_STRING);
2074     m->tunnel_id = htonl (tunnel->tid);
2075     memcpy(&m[1], description, len);
2076
2077     send_packet (tunnel->mesh, &m->header, tunnel);
2078   }
2079 }
2080
2081
2082 /**
2083  * Request that the given peer isn't added to this tunnel in calls to
2084  * connect_by_* calls, (due to misbehaviour, bad performance, ...).
2085  *
2086  * @param tunnel handle to existing tunnel.
2087  * @param peer peer identity of the peer which should be blacklisted
2088  *                  for the tunnel.
2089  */
2090 void
2091 GNUNET_MESH_peer_blacklist (struct GNUNET_MESH_Tunnel *tunnel,
2092                             const struct GNUNET_PeerIdentity *peer)
2093 {
2094   struct GNUNET_MESH_PeerControl msg;
2095
2096   msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2097   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_BLACKLIST);
2098   msg.tunnel_id = htonl (tunnel->tid);
2099   msg.peer = *peer;
2100   send_packet (tunnel->mesh, &msg.header, tunnel);
2101
2102   return;
2103 }
2104
2105
2106 /**
2107  * Request that the given peer isn't blacklisted anymore from this tunnel,
2108  * and therefore can be added in future calls to connect_by_*.
2109  * The peer must have been previously blacklisted for this tunnel.
2110  *
2111  * @param tunnel handle to existing tunnel.
2112  * @param peer peer identity of the peer which shouldn't be blacklisted
2113  *                  for the tunnel anymore.
2114  */
2115 void
2116 GNUNET_MESH_peer_unblacklist (struct GNUNET_MESH_Tunnel *tunnel,
2117                               const struct GNUNET_PeerIdentity *peer)
2118 {
2119   struct GNUNET_MESH_PeerControl msg;
2120
2121   msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2122   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_UNBLACKLIST);
2123   msg.tunnel_id = htonl (tunnel->tid);
2124   msg.peer = *peer;
2125   send_packet (tunnel->mesh, &msg.header, tunnel);
2126
2127   return;
2128 }
2129
2130
2131 /**
2132  * Ask the mesh to call "notify" once it is ready to transmit the
2133  * given number of bytes to the specified tunnel or target.
2134  * Only one call can be active at any time, to issue another request,
2135  * wait for the callback or cancel the current request.
2136  *
2137  * @param tunnel tunnel to use for transmission
2138  * @param cork is corking allowed for this transmission?
2139  * @param maxdelay how long can the message wait?
2140  * @param target destination for the message
2141  *               NULL for multicast to all tunnel targets
2142  * @param notify_size how many bytes of buffer space does notify want?
2143  * @param notify function to call when buffer space is available;
2144  *        will be called with NULL on timeout or if the overall queue
2145  *        for this peer is larger than queue_size and this is currently
2146  *        the message with the lowest priority
2147  * @param notify_cls closure for notify
2148  * @return non-NULL if the notify callback was queued,
2149  *         NULL if we can not even queue the request (insufficient
2150  *         memory); if NULL is returned, "notify" will NOT be called.
2151  */
2152 struct GNUNET_MESH_TransmitHandle *
2153 GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
2154                                    struct GNUNET_TIME_Relative maxdelay,
2155                                    const struct GNUNET_PeerIdentity *target,
2156                                    size_t notify_size,
2157                                    GNUNET_CONNECTION_TransmitReadyNotify notify,
2158                                    void *notify_cls)
2159 {
2160   struct GNUNET_MESH_TransmitHandle *th;
2161   size_t overhead;
2162
2163   GNUNET_assert (NULL != tunnel);
2164   LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n");
2165   LOG (GNUNET_ERROR_TYPE_DEBUG, "    on tunnel %X\n", tunnel->tid);
2166   if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
2167     LOG (GNUNET_ERROR_TYPE_DEBUG, "    to origin\n");
2168   else if (NULL != target)
2169     LOG (GNUNET_ERROR_TYPE_DEBUG, "    target %s\n", GNUNET_i2s (target));
2170   else
2171     LOG (GNUNET_ERROR_TYPE_DEBUG, "    target multicast\n");
2172   LOG (GNUNET_ERROR_TYPE_DEBUG, "    payload size %u\n", notify_size);
2173   GNUNET_assert (NULL != notify);
2174   GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed
2175   th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
2176   th->tunnel = tunnel;
2177   th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
2178   th->target = GNUNET_PEER_intern (target);
2179   if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
2180     overhead = sizeof (struct GNUNET_MESH_ToOrigin);
2181   else if (NULL == target)
2182     overhead = sizeof (struct GNUNET_MESH_Multicast);
2183   else
2184     overhead = sizeof (struct GNUNET_MESH_Unicast);
2185   tunnel->packet_size = th->size = notify_size + overhead;
2186   LOG (GNUNET_ERROR_TYPE_DEBUG, "    total size %u\n", th->size);
2187   th->notify = notify;
2188   th->notify_cls = notify_cls;
2189   add_to_queue (tunnel->mesh, th);
2190   if (NULL != tunnel->mesh->th)
2191     return th;
2192   if (GMC_is_pid_bigger(tunnel->next_send_pid, tunnel->max_send_pid))
2193     return th;
2194   LOG (GNUNET_ERROR_TYPE_DEBUG, "    call notify tmt rdy\n");
2195   tunnel->mesh->th =
2196       GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size,
2197                                            GNUNET_TIME_UNIT_FOREVER_REL,
2198                                            GNUNET_YES, &send_callback,
2199                                            tunnel->mesh);
2200   LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY END\n");
2201   return th;
2202 }
2203
2204
2205 /**
2206  * Cancel the specified transmission-ready notification.
2207  *
2208  * @param th handle that was returned by "notify_transmit_ready".
2209  */
2210 void
2211 GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th)
2212 {
2213   struct GNUNET_MESH_Handle *mesh;
2214
2215   th->tunnel->packet_size = 0;
2216   mesh = th->tunnel->mesh;
2217   if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2218     GNUNET_SCHEDULER_cancel (th->timeout_task);
2219   GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
2220   GNUNET_free (th);
2221   if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
2222   {
2223     /* queue empty, no point in asking for transmission */
2224     GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
2225     mesh->th = NULL;
2226   }
2227 }
2228
2229
2230 /**
2231  * Request information about the running mesh peer.
2232  * The callback will be called for every tunnel known to the service,
2233  * listing all active peers that blong to the tunnel.
2234  *
2235  * If called again on the same handle, it will overwrite the previous
2236  * callback and cls. To retrieve the cls, monitor_cancel must be
2237  * called first.
2238  *
2239  * WARNING: unstable API, likely to change in the future!
2240  *
2241  * @param h Handle to the mesh peer.
2242  * @param callback Function to call with the requested data.
2243  * @param callback_cls Closure for @c callback.
2244  */
2245 void
2246 GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h,
2247                          GNUNET_MESH_TunnelsCB callback,
2248                          void *callback_cls)
2249 {
2250   struct GNUNET_MessageHeader msg;
2251
2252   msg.size = htons (sizeof (msg));
2253   msg.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR);
2254   send_packet (h, &msg, NULL);
2255   h->tunnels_cb = callback;
2256   h->tunnels_cls = callback_cls;
2257
2258   return;
2259 }
2260
2261
2262 /**
2263  * Cancel a monitor request. The monitor callback will not be called.
2264  *
2265  * @param h Mesh handle.
2266  *
2267  * @return Closure given to GNUNET_MESH_monitor, if any.
2268  */
2269 void *
2270 GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h)
2271 {
2272   void *cls;
2273
2274   cls = h->tunnels_cls;
2275   h->tunnels_cb = NULL;
2276   h->tunnels_cls = NULL;
2277   return cls;
2278 }
2279
2280
2281 /**
2282  * Request information about a specific tunnel of the running mesh peer.
2283  *
2284  * WARNING: unstable API, likely to change in the future!
2285  *
2286  * @param h Handle to the mesh peer.
2287  * @param initiator ID of the owner of the tunnel.
2288  * @param tunnel_number Tunnel number.
2289  * @param callback Function to call with the requested data.
2290  * @param callback_cls Closure for @c callback.
2291  */
2292 void
2293 GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h,
2294                          struct GNUNET_PeerIdentity *initiator,
2295                          unsigned int tunnel_number,
2296                          GNUNET_MESH_TunnelCB callback,
2297                          void *callback_cls)
2298 {
2299   struct GNUNET_MESH_LocalMonitor msg;
2300
2301   msg.header.size = htons (sizeof (msg));
2302   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR_TUNNEL);
2303   msg.npeers = htonl (0);
2304   msg.owner = *initiator;
2305   msg.tunnel_id = htonl (tunnel_number);
2306   msg.reserved = 0;
2307   send_packet (h, &msg.header, NULL);
2308   h->tunnel_cb = callback;
2309   h->tunnel_cls = callback_cls;
2310
2311   return;
2312 }
2313
2314
2315 /**
2316  * Transition API for tunnel ctx management
2317  */
2318 void
2319 GNUNET_MESH_tunnel_set_data (struct GNUNET_MESH_Tunnel *tunnel, void *data)
2320 {
2321   tunnel->ctx = data;
2322 }
2323
2324 /**
2325  * Transition API for tunnel ctx management
2326  */
2327 void *
2328 GNUNET_MESH_tunnel_get_data (struct GNUNET_MESH_Tunnel *tunnel)
2329 {
2330   return tunnel->ctx;
2331 }
2332
2333