- add peer's tunnel setter
[oweals/gnunet.git] / src / mesh / gnunet-service-mesh_connection.c
1 /*
2      This file is part of GNUnet.
3      (C) 2001-2013 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file mesh/gnunet-service-mesh_connection.c
23  * @brief GNUnet MESH service connection handling
24  * @author Bartlomiej Polot
25  */
26
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29
30 #include "gnunet-service-mesh_connection.h"
31 #include "gnunet-service-mesh_peer.h"
32 #include "mesh_protocol_enc.h"
33 #include "mesh_path.h"
34
35
36 #define MESH_MAX_POLL_TIME      GNUNET_TIME_relative_multiply (\
37                                   GNUNET_TIME_UNIT_MINUTES,\
38                                   10)
39 #define MESH_RETRANSMIT_TIME    GNUNET_TIME_UNIT_SECONDS
40 #define MESH_RETRANSMIT_MARGIN  4
41
42 #define LOG(level, ...) GNUNET_log_from (level,"mesh-con",__VA_ARGS__)
43
44 /**
45  * All the states a connection can be in.
46  */
47 enum MeshConnectionState
48 {
49   /**
50    * Uninitialized status, should never appear in operation.
51    */
52   MESH_CONNECTION_NEW,
53
54   /**
55    * Connection create message sent, waiting for ACK.
56    */
57   MESH_CONNECTION_SENT,
58
59   /**
60    * Connection ACK sent, waiting for ACK.
61    */
62   MESH_CONNECTION_ACK,
63
64   /**
65    * Connection confirmed, ready to carry traffic.
66    */
67   MESH_CONNECTION_READY,
68 };
69
70
71
72 /**
73  * Struct containing info about a queued transmission to this peer
74  */
75 struct MeshPeerQueue
76 {
77     /**
78       * DLL next
79       */
80   struct MeshPeerQueue *next;
81
82     /**
83       * DLL previous
84       */
85   struct MeshPeerQueue *prev;
86
87     /**
88      * Peer this transmission is directed to.
89      */
90   struct MeshPeer *peer;
91
92     /**
93      * Connection this message belongs to.
94      */
95   struct MeshConnection *c;
96
97     /**
98      * Is FWD in c?
99      */
100   int fwd;
101
102     /**
103      * Channel this message belongs to, if known.
104      */
105   struct MeshChannel *ch;
106
107     /**
108      * Pointer to info stucture used as cls.
109      */
110   void *cls;
111
112     /**
113      * Type of message
114      */
115   uint16_t type;
116
117     /**
118      * Size of the message
119      */
120   size_t size;
121 };
122
123
124 /**
125  * Struct to encapsulate all the Flow Control information to a peer to which
126  * we are directly connected (on a core level).
127  */
128 struct MeshFlowControl
129 {
130   /**
131    * Connection this controls.
132    */
133   struct MeshConnection *c;
134
135   /**
136    * How many messages are in the queue on this connection.
137    */
138   unsigned int queue_n;
139
140   /**
141    * How many messages do we accept in the queue.
142    */
143   unsigned int queue_max;
144
145   /**
146    * Next ID to use.
147    */
148   uint32_t next_pid;
149
150   /**
151    * ID of the last packet sent towards the peer.
152    */
153   uint32_t last_pid_sent;
154
155   /**
156    * ID of the last packet received from the peer.
157    */
158   uint32_t last_pid_recv;
159
160   /**
161    * Last ACK sent to the peer (peer can't send more than this PID).
162    */
163   uint32_t last_ack_sent;
164
165   /**
166    * Last ACK sent towards the origin (for traffic towards leaf node).
167    */
168   uint32_t last_ack_recv;
169
170   /**
171    * Task to poll the peer in case of a lost ACK causes stall.
172    */
173   GNUNET_SCHEDULER_TaskIdentifier poll_task;
174
175   /**
176    * How frequently to poll for ACKs.
177    */
178   struct GNUNET_TIME_Relative poll_time;
179 };
180
181
182 /**
183  * Struct containing all information regarding a connection to a peer.
184  */
185 struct MeshConnection
186 {
187   /**
188    * DLL
189    */
190   struct MeshConnection *next;
191   struct MeshConnection *prev;
192
193   /**
194    * Tunnel this connection is part of.
195    */
196   struct MeshTunnel2 *t;
197
198   /**
199    * Flow control information for traffic fwd.
200    */
201   struct MeshFlowControl fwd_fc;
202
203   /**
204    * Flow control information for traffic bck.
205    */
206   struct MeshFlowControl bck_fc;
207
208   /**
209    * ID of the connection.
210    */
211   struct GNUNET_HashCode id;
212
213   /**
214    * State of the connection.
215    */
216   enum MeshConnectionState state;
217
218   /**
219    * Path being used for the tunnel.
220    */
221   struct MeshPeerPath *path;
222
223   /**
224    * Position of the local peer in the path.
225    */
226   unsigned int own_pos;
227
228   /**
229    * Task to keep the used paths alive at the owner,
230    * time tunnel out on all the other peers.
231    */
232   GNUNET_SCHEDULER_TaskIdentifier fwd_maintenance_task;
233
234   /**
235    * Task to keep the used paths alive at the destination,
236    * time tunnel out on all the other peers.
237    */
238   GNUNET_SCHEDULER_TaskIdentifier bck_maintenance_task;
239
240   /**
241    * Pending message count.
242    */
243   int pending_messages;
244
245   /**
246    * Destroy flag: if true, destroy on last message.
247    */
248   int destroy;
249 };
250
251
252 /**
253  * Connections known, indexed by cid (MeshConnection).
254  */
255 static struct GNUNET_CONTAINER_MultiHashMap *connections;
256
257 /**
258  * How many connections are we willing to maintain.
259  * Local connections are always allowed, even if there are more connections than max.
260  */
261 static unsigned long long max_connections;
262
263 /**
264  * How many messages *in total* are we willing to queue, divide by number of
265  * connections to get connection queue size.
266  */
267 static unsigned long long max_msgs_queue;
268
269 /**
270  * How often to send path keepalives. Paths timeout after 4 missed.
271  */
272 static struct GNUNET_TIME_Relative refresh_connection_time;
273
274
275 #if 0 // avoid compiler warning for unused static function
276 static void
277 fc_debug (struct MeshFlowControl *fc)
278 {
279   LOG (GNUNET_ERROR_TYPE_DEBUG, "    IN: %u/%u\n",
280               fc->last_pid_recv, fc->last_ack_sent);
281   LOG (GNUNET_ERROR_TYPE_DEBUG, "    OUT: %u/%u\n",
282               fc->last_pid_sent, fc->last_ack_recv);
283   LOG (GNUNET_ERROR_TYPE_DEBUG, "    QUEUE: %u/%u\n",
284               fc->queue_n, fc->queue_max);
285 }
286
287 static void
288 connection_debug (struct MeshConnection *c)
289 {
290   if (NULL == c)
291   {
292     LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n");
293     return;
294   }
295   LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
296               peer2s (c->t->peer), GNUNET_h2s (&c->id));
297   LOG (GNUNET_ERROR_TYPE_DEBUG, "  state: %u, pending msgs: %u\n",
298               c->state, c->pending_messages);
299   LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD FC\n");
300   fc_debug (&c->fwd_fc);
301   LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK FC\n");
302   fc_debug (&c->bck_fc);
303 }
304 #endif
305
306 /**
307  * Get string description for tunnel state.
308  *
309  * @param s Tunnel state.
310  *
311  * @return String representation.
312  */
313 static const char *
314 GMC_DEBUG_state2s (enum MeshTunnelState s)
315 {
316   switch (s)
317   {
318     case MESH_CONNECTION_NEW:
319       return "MESH_CONNECTION_NEW";
320     case MESH_CONNECTION_SENT:
321       return "MESH_CONNECTION_SENT";
322     case MESH_CONNECTION_ACK:
323       return "MESH_CONNECTION_ACK";
324     case MESH_CONNECTION_READY:
325       return "MESH_CONNECTION_READY";
326     default:
327       return "MESH_CONNECTION_STATE_ERROR";
328   }
329 }
330
331
332
333 /**
334  * Initialize a Flow Control structure to the initial state.
335  *
336  * @param fc Flow Control structure to initialize.
337  */
338 static void
339 fc_init (struct MeshFlowControl *fc)
340 {
341   fc->next_pid = 0;
342   fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */
343   fc->last_pid_recv = (uint32_t) -1;
344   fc->last_ack_sent = (uint32_t) 0;
345   fc->last_ack_recv = (uint32_t) 0;
346   fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
347   fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
348   fc->queue_n = 0;
349   fc->queue_max = (max_msgs_queue / max_connections) + 1;
350 }
351
352
353 /**
354  * Find a connection.
355  *
356  * @param cid Connection ID.
357  */
358 static struct MeshConnection *
359 connection_get (const struct GNUNET_HashCode *cid)
360 {
361   return GNUNET_CONTAINER_multihashmap_get (connections, cid);
362 }
363
364
365 /**
366  * Send an ACK informing the predecessor about the available buffer space.
367  *
368  * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
369  * the ACK itself goes "back" (dest->root).
370  *
371  * @param c Connection on which to send the ACK.
372  * @param buffer How much space free to advertise?
373  * @param fwd Is this FWD ACK? (Going dest->owner)
374  */
375 static void
376 connection_send_ack (struct MeshConnection *c, unsigned int buffer, int fwd)
377 {
378   struct MeshFlowControl *next_fc;
379   struct MeshFlowControl *prev_fc;
380   struct GNUNET_MESH_ACK msg;
381   uint32_t ack;
382   int delta;
383
384   next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
385   prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
386
387   LOG (GNUNET_ERROR_TYPE_DEBUG,
388               "connection send %s ack on %s\n",
389               fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
390
391   /* Check if we need to transmit the ACK */
392   if (prev_fc->last_ack_sent - prev_fc->last_pid_recv > 3)
393   {
394     LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n");
395     LOG (GNUNET_ERROR_TYPE_DEBUG,
396                 "  last pid recv: %u, last ack sent: %u\n",
397                 prev_fc->last_pid_recv, prev_fc->last_ack_sent);
398     return;
399   }
400
401   /* Ok, ACK might be necessary, what PID to ACK? */
402   delta = next_fc->queue_max - next_fc->queue_n;
403   ack = prev_fc->last_pid_recv + delta;
404   LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
405   LOG (GNUNET_ERROR_TYPE_DEBUG,
406               " last pid %u, last ack %u, qmax %u, q %u\n",
407               prev_fc->last_pid_recv, prev_fc->last_ack_sent,
408               next_fc->queue_max, next_fc->queue_n);
409   if (ack == prev_fc->last_ack_sent)
410   {
411     LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
412     return;
413   }
414
415   prev_fc->last_ack_sent = ack;
416
417   /* Build ACK message and send on connection */
418   msg.header.size = htons (sizeof (msg));
419   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
420   msg.ack = htonl (ack);
421   msg.cid = c->id;
422
423   send_prebuilt_message_connection (&msg.header, c, NULL, !fwd);
424 }
425
426
427 /**
428  * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
429  * directed to us.
430  *
431  * @param connection Connection to confirm.
432  * @param fwd Is this a fwd ACK? (First is bck (SYNACK), second is fwd (ACK))
433  */
434 static void
435 send_connection_ack (struct MeshConnection *connection, int fwd)
436 {
437   struct MeshTunnel2 *t;
438
439   t = connection->t;
440   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send connection ack\n");
441   queue_add (NULL,
442              GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
443              sizeof (struct GNUNET_MESH_ConnectionACK),
444              connection,
445              NULL,
446              fwd);
447   if (MESH_TUNNEL_NEW == t->state)
448     tunnel_change_state (t, MESH_TUNNEL_WAITING);
449   if (MESH_CONNECTION_READY != connection->state)
450     connection_change_state (connection, MESH_CONNECTION_SENT);
451 }
452
453
454 /**
455  * Sends a CREATE CONNECTION message for a path to a peer.
456  * Changes the connection and tunnel states if necessary.
457  *
458  * @param connection Connection to create.
459  */
460 static void
461 send_connection_create (struct MeshConnection *connection)
462 {
463   struct MeshTunnel2 *t;
464
465   t = connection->t;
466   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send connection create\n");
467   queue_add (NULL,
468              GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
469              sizeof (struct GNUNET_MESH_ConnectionCreate) +
470                 (connection->path->length *
471                  sizeof (struct GNUNET_PeerIdentity)),
472              connection,
473              NULL,
474              GNUNET_YES);
475   if (NULL != t &&
476       (MESH_TUNNEL_SEARCHING == t->state || MESH_TUNNEL_NEW == t->state))
477     tunnel_change_state (t, MESH_TUNNEL_WAITING);
478   if (MESH_CONNECTION_NEW == connection->state)
479     connection_change_state (connection, MESH_CONNECTION_SENT);
480 }
481
482
483 static void
484 connection_change_state (struct MeshConnection* c,
485                          enum MeshConnectionState state)
486 {
487   LOG (GNUNET_ERROR_TYPE_DEBUG,
488               "Connection %s state was %s\n",
489               GNUNET_h2s (&c->id), GNUNET_MESH_DEBUG_CS2S (c->state));
490   LOG (GNUNET_ERROR_TYPE_DEBUG,
491               "Connection %s state is now %s\n",
492               GNUNET_h2s (&c->id), GNUNET_MESH_DEBUG_CS2S (state));
493   c->state = state;
494 }
495
496
497
498 /**
499  * Send keepalive packets for a connection.
500  *
501  * @param c Connection to keep alive..
502  * @param fwd Is this a FWD keepalive? (owner -> dest).
503  */
504 static void
505 connection_keepalive (struct MeshConnection *c, int fwd)
506 {
507   struct GNUNET_MESH_ConnectionKeepAlive *msg;
508   size_t size = sizeof (struct GNUNET_MESH_ConnectionKeepAlive);
509   char cbuf[size];
510   uint16_t type;
511
512   type = fwd ? GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE :
513                GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE;
514
515   LOG (GNUNET_ERROR_TYPE_DEBUG,
516               "sending %s keepalive for connection %s[%d]\n",
517               fwd ? "FWD" : "BCK",
518               peer2s (c->t->peer),
519               c->id);
520
521   msg = (struct GNUNET_MESH_ConnectionKeepAlive *) cbuf;
522   msg->header.size = htons (size);
523   msg->header.type = htons (type);
524   msg->cid = c->id;
525
526   send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
527 }
528
529
530 /**
531  * Send CONNECTION_{CREATE/ACK} packets for a connection.
532  *
533  * @param c Connection for which to send the message.
534  * @param fwd If GNUNET_YES, send CREATE, otherwise send ACK.
535  */
536 static void
537 connection_recreate (struct MeshConnection *c, int fwd)
538 {
539   LOG (GNUNET_ERROR_TYPE_DEBUG, "sending connection recreate\n");
540   if (fwd)
541     send_connection_create (c);
542   else
543     send_connection_ack (c, GNUNET_NO);
544 }
545
546
547 /**
548  * Generic connection timer management.
549  * Depending on the role of the peer in the connection will send the
550  * appropriate message (build or keepalive)
551  *
552  * @param c Conncetion to maintain.
553  * @param fwd Is FWD?
554  */
555 static void
556 connection_maintain (struct MeshConnection *c, int fwd)
557 {
558   if (MESH_TUNNEL_SEARCHING == c->t->state)
559   {
560     /* TODO DHT GET with RO_BART */
561     return;
562   }
563   switch (c->state)
564   {
565     case MESH_CONNECTION_NEW:
566       GNUNET_break (0);
567     case MESH_CONNECTION_SENT:
568       connection_recreate (c, fwd);
569       break;
570     case MESH_CONNECTION_READY:
571       connection_keepalive (c, fwd);
572       break;
573     default:
574       break;
575   }
576 }
577
578
579 static void
580 connection_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
581 {
582   struct MeshConnection *c = cls;
583
584   c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
585   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
586     return;
587
588   connection_maintain (c, GNUNET_YES);
589   c->fwd_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
590                                                           &connection_fwd_keepalive,
591                                                           c);
592 }
593
594
595 static void
596 connection_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
597 {
598   struct MeshConnection *c = cls;
599
600   c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
601   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
602     return;
603
604   connection_maintain (c, GNUNET_NO);
605   c->bck_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
606                                                           &connection_bck_keepalive,
607                                                           c);
608 }
609
610
611 /**
612  * Send a message to all peers in this connection that the connection
613  * is no longer valid.
614  *
615  * If some peer should not receive the message, it should be zero'ed out
616  * before calling this function.
617  *
618  * @param c The connection whose peers to notify.
619  */
620 static void
621 connection_send_destroy (struct MeshConnection *c)
622 {
623   struct GNUNET_MESH_ConnectionDestroy msg;
624
625   msg.header.size = htons (sizeof (msg));
626   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY);;
627   msg.cid = c->id;
628   LOG (GNUNET_ERROR_TYPE_DEBUG,
629               "  sending connection destroy for connection %s[%X]\n",
630               peer2s (c->t->peer),
631               c->id);
632
633   if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES))
634     send_prebuilt_message_connection (&msg.header, c, NULL, GNUNET_YES);
635   if (GNUNET_NO == GMC_is_terminal (c, GNUNET_NO))
636     send_prebuilt_message_connection (&msg.header, c, NULL, GNUNET_NO);
637   c->destroy = GNUNET_YES;
638 }
639
640
641 /**
642  * Get free buffer space in a connection.
643  *
644  * @param c Connection.
645  * @param fwd Is query about FWD traffic?
646  *
647  * @return Free buffer space [0 - max_msgs_queue/max_connections]
648  */
649 static unsigned int
650 connection_get_buffer (struct MeshConnection *c, int fwd)
651 {
652   struct MeshFlowControl *fc;
653
654   fc = fwd ? &c->fwd_fc : &c->bck_fc;
655
656   return (fc->queue_max - fc->queue_n);
657 }
658
659
660 /**
661  * Get the first transmittable message for a connection.
662  *
663  * @param c Connection.
664  * @param fwd Is this FWD?
665  *
666  * @return First transmittable message.
667  */
668 static struct MeshPeerQueue *
669 connection_get_first_message (struct MeshConnection *c, int fwd)
670 {
671   struct MeshPeerQueue *q;
672   struct MeshPeer *p;
673
674   p = connection_get_hop (c, fwd);
675
676   for (q = p->queue_head; NULL != q; q = q->next)
677   {
678     if (q->c != c)
679       continue;
680     if (queue_is_sendable (q))
681       return q;
682   }
683
684   return NULL;
685 }
686
687
688 /**
689  * @brief Re-initiate traffic on this connection if necessary.
690  *
691  * Check if there is traffic queued towards this peer
692  * and the core transmit handle is NULL (traffic was stalled).
693  * If so, call core tmt rdy.
694  *
695  * @param c Connection on which initiate traffic.
696  * @param fwd Is this about fwd traffic?
697  */
698 static void
699 connection_unlock_queue (struct MeshConnection *c, int fwd)
700 {
701   struct MeshPeer *peer;
702   struct MeshPeerQueue *q;
703   size_t size;
704
705   LOG (GNUNET_ERROR_TYPE_DEBUG,
706               "connection_unlock_queue %s on %s\n",
707               fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
708
709   if (GMC_is_terminal (c, fwd))
710   {
711     LOG (GNUNET_ERROR_TYPE_DEBUG, " is terminal!\n");
712     return;
713   }
714
715   peer = connection_get_hop (c, fwd);
716
717   if (NULL != peer->core_transmit)
718   {
719     LOG (GNUNET_ERROR_TYPE_DEBUG, "  already unlocked!\n");
720     return; /* Already unlocked */
721   }
722
723   q = connection_get_first_message (c, fwd);
724   if (NULL == q)
725   {
726     LOG (GNUNET_ERROR_TYPE_DEBUG, "  queue empty!\n");
727     return; /* Nothing to transmit */
728   }
729
730   size = q->size;
731   peer->core_transmit =
732       GNUNET_CORE_notify_transmit_ready (core_handle,
733                                          GNUNET_NO,
734                                          0,
735                                          GNUNET_TIME_UNIT_FOREVER_REL,
736                                          GNUNET_PEER_resolve2 (peer->id),
737                                          size,
738                                          &queue_send,
739                                          peer);
740 }
741
742
743 /**
744  * Cancel all transmissions that belong to a certain connection.
745  *
746  * @param c Connection which to cancel.
747  * @param fwd Cancel fwd traffic?
748  */
749 static void
750 connection_cancel_queues (struct MeshConnection *c, int fwd)
751 {
752   struct MeshPeerQueue *q;
753   struct MeshPeerQueue *next;
754   struct MeshFlowControl *fc;
755   struct MeshPeer *peer;
756
757   if (NULL == c)
758   {
759     GNUNET_break (0);
760     return;
761   }
762   fc = fwd ? &c->fwd_fc : &c->bck_fc;
763   peer = connection_get_hop (c, fwd);
764
765   for (q = peer->queue_head; NULL != q; q = next)
766   {
767     next = q->next;
768     if (q->c == c)
769     {
770       LOG (GNUNET_ERROR_TYPE_DEBUG,
771                   "connection_cancel_queue %s\n",
772                   GNUNET_MESH_DEBUG_M2S (q->type));
773       queue_destroy (q, GNUNET_YES);
774     }
775   }
776   if (NULL == peer->queue_head)
777   {
778     if (NULL != peer->core_transmit)
779     {
780       GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
781       peer->core_transmit = NULL;
782     }
783     if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
784     {
785       GNUNET_SCHEDULER_cancel (fc->poll_task);
786       fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
787     }
788   }
789 }
790
791
792
793
794 /**
795  * Function called if a connection has been stalled for a while,
796  * possibly due to a missed ACK. Poll the neighbor about its ACK status.
797  *
798  * @param cls Closure (poll ctx).
799  * @param tc TaskContext.
800  */
801 static void
802 connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
803 {
804   struct MeshFlowControl *fc = cls;
805   struct GNUNET_MESH_Poll msg;
806   struct MeshConnection *c;
807
808   fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
809   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
810   {
811     return;
812   }
813
814   c = fc->c;
815   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Polling!\n");
816   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** connection [%X]\n",
817               GNUNET_h2s (&c->id));
818   LOG (GNUNET_ERROR_TYPE_DEBUG, " ***   %s\n",
819               fc == &c->fwd_fc ? "FWD" : "BCK");
820
821   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL);
822   msg.header.size = htons (sizeof (msg));
823   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** pid (%u)!\n", fc->last_pid_sent);
824   send_prebuilt_message_connection (&msg.header, c, NULL, fc == &c->fwd_fc);
825   fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
826   fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
827                                                 &connection_poll, fc);
828 }
829
830
831
832
833 /**
834  * Get the previous hop in a connection
835  *
836  * @param c Connection.
837  *
838  * @return Previous peer in the connection.
839  */
840 static struct MeshPeer *
841 connection_get_prev_hop (struct MeshConnection *c)
842 {
843   GNUNET_PEER_Id id;
844
845   if (0 == c->own_pos || c->path->length < 2)
846     id = c->path->peers[0];
847   else
848     id = c->path->peers[c->own_pos - 1];
849
850   return peer_get_short (id);
851 }
852
853
854 /**
855  * Get the next hop in a connection
856  *
857  * @param c Connection.
858  *
859  * @return Next peer in the connection.
860  */
861 static struct MeshPeer *
862 connection_get_next_hop (struct MeshConnection *c)
863 {
864   GNUNET_PEER_Id id;
865
866   if ((c->path->length - 1) == c->own_pos || c->path->length < 2)
867     id = c->path->peers[c->path->length - 1];
868   else
869     id = c->path->peers[c->own_pos + 1];
870
871   return peer_get_short (id);
872 }
873
874
875 /**
876  * Get the hop in a connection.
877  *
878  * @param c Connection.
879  * @param fwd Next hop?
880  *
881  * @return Next peer in the connection.
882  */
883 static struct MeshPeer *
884 connection_get_hop (struct MeshConnection *c, int fwd)
885 {
886   if (fwd)
887     return connection_get_next_hop (c);
888   return connection_get_prev_hop (c);
889 }
890
891
892
893
894 /**
895  * Timeout function due to lack of keepalive/traffic from the owner.
896  * Destroys connection if called.
897  *
898  * @param cls Closure (connection to destroy).
899  * @param tc TaskContext.
900  */
901 static void
902 connection_fwd_timeout (void *cls,
903                         const struct GNUNET_SCHEDULER_TaskContext *tc)
904 {
905   struct MeshConnection *c = cls;
906
907   c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
908   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
909     return;
910   LOG (GNUNET_ERROR_TYPE_DEBUG,
911               "Connection %s[%X] FWD timed out. Destroying.\n",
912               peer2s (c->t->peer),
913               c->id);
914
915   if (GMC_is_origin (c, GNUNET_YES)) /* If local, leave. */
916     return;
917
918   GMC_destroy (c);
919 }
920
921
922 /**
923  * Timeout function due to lack of keepalive/traffic from the destination.
924  * Destroys connection if called.
925  *
926  * @param cls Closure (connection to destroy).
927  * @param tc TaskContext
928  */
929 static void
930 connection_bck_timeout (void *cls,
931                         const struct GNUNET_SCHEDULER_TaskContext *tc)
932 {
933   struct MeshConnection *c = cls;
934
935   c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
936   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
937     return;
938
939   LOG (GNUNET_ERROR_TYPE_DEBUG,
940               "Connection %s[%X] FWD timed out. Destroying.\n",
941               peer2s (c->t->peer),
942               c->id);
943
944   if (GMC_is_origin (c, GNUNET_NO)) /* If local, leave. */
945     return;
946
947   GMC_destroy (c);
948 }
949
950
951 /**
952  * Resets the connection timeout task, some other message has done the
953  * task's job.
954  * - For the first peer on the direction this means to send
955  *   a keepalive or a path confirmation message (either create or ACK).
956  * - For all other peers, this means to destroy the connection,
957  *   due to lack of activity.
958  * Starts the tiemout if no timeout was running (connection just created).
959  *
960  * @param c Connection whose timeout to reset.
961  * @param fwd Is this forward?
962  *
963  * TODO use heap to improve efficiency of scheduler.
964  */
965 static void
966 connection_reset_timeout (struct MeshConnection *c, int fwd)
967 {
968   GNUNET_SCHEDULER_TaskIdentifier *ti;
969   GNUNET_SCHEDULER_Task f;
970
971   ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task;
972
973   if (GNUNET_SCHEDULER_NO_TASK != *ti)
974     GNUNET_SCHEDULER_cancel (*ti);
975
976   if (GMC_is_origin (c, fwd)) /* Endpoint */
977   {
978     f  = fwd ? &connection_fwd_keepalive : &connection_bck_keepalive;
979     *ti = GNUNET_SCHEDULER_add_delayed (refresh_connection_time, f, c);
980   }
981   else /* Relay */
982   {
983     struct GNUNET_TIME_Relative delay;
984
985     delay = GNUNET_TIME_relative_multiply (refresh_connection_time, 4);
986     f  = fwd ? &connection_fwd_timeout : &connection_bck_timeout;
987     *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c);
988   }
989 }
990
991
992 /**
993  * 
994  */
995 static void
996 register_neighbors (struct MeshConnection *c)
997 {
998   struct MeshPeer *peer;
999
1000   peer = connection_get_next_hop (c);
1001   if (GNUNET_NO == GMP_is_neighbor (peer))
1002   {
1003     GMC_destroy (c);
1004     return NULL;
1005   }
1006   GMP_add_connection (peer, c);
1007   peer = connection_get_prev_hop (c);
1008   if (GNUNET_NO == GMP_is_neighbor (peer))
1009   {
1010     GMC_destroy (c);
1011     return NULL;
1012   }
1013   GMP_add_connection (peer, c);
1014 }
1015
1016
1017 /**
1018  * Core handler for connection creation.
1019  *
1020  * @param cls Closure (unused).
1021  * @param peer Sender (neighbor).
1022  * @param message Message.
1023  *
1024  * @return GNUNET_OK to keep the connection open,
1025  *         GNUNET_SYSERR to close it (signal serious error)
1026  */
1027 int
1028 GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
1029                    const struct GNUNET_MessageHeader *message)
1030 {
1031   struct GNUNET_MESH_ConnectionCreate *msg;
1032   struct GNUNET_PeerIdentity *id;
1033   struct GNUNET_HashCode *cid;
1034   struct MeshPeerPath *path;
1035   struct MeshPeer *dest_peer;
1036   struct MeshPeer *orig_peer;
1037   struct MeshConnection *c;
1038   unsigned int own_pos;
1039   uint16_t size;
1040   uint16_t i;
1041
1042   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1043   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a connection create msg\n");
1044
1045   /* Check size */
1046   size = ntohs (message->size);
1047   if (size < sizeof (struct GNUNET_MESH_ConnectionCreate))
1048   {
1049     GNUNET_break_op (0);
1050     return GNUNET_OK;
1051   }
1052
1053   /* Calculate hops */
1054   size -= sizeof (struct GNUNET_MESH_ConnectionCreate);
1055   if (size % sizeof (struct GNUNET_PeerIdentity))
1056   {
1057     GNUNET_break_op (0);
1058     return GNUNET_OK;
1059   }
1060   size /= sizeof (struct GNUNET_PeerIdentity);
1061   if (1 > size)
1062   {
1063     GNUNET_break_op (0);
1064     return GNUNET_OK;
1065   }
1066   LOG (GNUNET_ERROR_TYPE_DEBUG, "    path has %u hops.\n", size);
1067
1068   /* Get parameters */
1069   msg = (struct GNUNET_MESH_ConnectionCreate *) message;
1070   cid = &msg->cid;
1071   id = (struct GNUNET_PeerIdentity *) &msg[1];
1072   LOG (GNUNET_ERROR_TYPE_DEBUG,
1073               "    connection %s (%s).\n",
1074               GNUNET_h2s (cid), GNUNET_i2s (id));
1075
1076   /* Create connection */
1077   c = connection_get (cid);
1078   if (NULL == c)
1079   {
1080     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Creating connection\n");
1081     c = connection_new (cid);
1082     if (NULL == c)
1083       return GNUNET_OK;
1084     connection_reset_timeout (c, GNUNET_YES);
1085
1086     /* Create path */
1087     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Creating path...\n");
1088     path = path_new (size);
1089     own_pos = 0;
1090     for (i = 0; i < size; i++)
1091     {
1092       LOG (GNUNET_ERROR_TYPE_DEBUG, "  ... adding %s\n",
1093                   GNUNET_i2s (&id[i]));
1094       path->peers[i] = GNUNET_PEER_intern (&id[i]);
1095       if (path->peers[i] == myid)
1096         own_pos = i;
1097     }
1098     if (own_pos == 0 && path->peers[own_pos] != myid)
1099     {
1100       /* create path: self not found in path through self */
1101       GNUNET_break_op (0);
1102       path_destroy (path);
1103       connection_destroy (c);
1104       return GNUNET_OK;
1105     }
1106     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Own position: %u\n", own_pos);
1107     path_add_to_peers (path, GNUNET_NO);
1108     c->path = path_duplicate (path);
1109     c->own_pos = own_pos;
1110   }
1111   else
1112   {
1113     path = NULL;
1114   }
1115   if (MESH_CONNECTION_NEW == c->state)
1116     connection_change_state (c, MESH_CONNECTION_SENT);
1117
1118   /* Remember peers */
1119   dest_peer = peer_get (&id[size - 1]);
1120   orig_peer = peer_get (&id[0]);
1121
1122   /* Is it a connection to us? */
1123   if (c->own_pos == size - 1)
1124   {
1125     LOG (GNUNET_ERROR_TYPE_DEBUG, "  It's for us!\n");
1126     peer_add_path_to_origin (orig_peer, path, GNUNET_YES);
1127
1128     if (NULL == orig_peer->tunnel)
1129     {
1130       orig_peer->tunnel = tunnel_new ();
1131       orig_peer->tunnel->peer = orig_peer;
1132     }
1133     tunnel_add_connection (orig_peer->tunnel, c);
1134     if (MESH_TUNNEL_NEW == c->t->state)
1135       tunnel_change_state (c->t,  MESH_TUNNEL_WAITING);
1136
1137     send_connection_ack (c, GNUNET_NO);
1138     if (MESH_CONNECTION_SENT == c->state)
1139       connection_change_state (c, MESH_CONNECTION_ACK);
1140
1141     /* Keep tunnel alive in direction dest->owner*/
1142     connection_reset_timeout (c, GNUNET_NO);
1143   }
1144   else
1145   {
1146     /* It's for somebody else! Retransmit. */
1147     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Retransmitting.\n");
1148     peer_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
1149     peer_add_path_to_origin (orig_peer, path, GNUNET_NO);
1150     send_prebuilt_message_connection (message, c, NULL, GNUNET_YES);
1151   }
1152   return GNUNET_OK;
1153 }
1154
1155
1156 /**
1157  * Core handler for path confirmations.
1158  *
1159  * @param cls closure
1160  * @param message message
1161  * @param peer peer identity this notification is about
1162  *
1163  * @return GNUNET_OK to keep the connection open,
1164  *         GNUNET_SYSERR to close it (signal serious error)
1165  */
1166 int
1167 GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer,
1168                     const struct GNUNET_MessageHeader *message)
1169 {
1170   struct GNUNET_MESH_ConnectionACK *msg;
1171   struct MeshConnection *c;
1172   struct MeshPeerPath *p;
1173   struct MeshPeer *pi;
1174   int fwd;
1175
1176   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1177   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a connection ACK msg\n");
1178   msg = (struct GNUNET_MESH_ConnectionACK *) message;
1179   LOG (GNUNET_ERROR_TYPE_DEBUG, "  on connection %s\n",
1180               GNUNET_h2s (&msg->cid));
1181   c = connection_get (&msg->cid);
1182   if (NULL == c)
1183   {
1184     GNUNET_STATISTICS_update (stats, "# control on unknown connection",
1185                               1, GNUNET_NO);
1186     LOG (GNUNET_ERROR_TYPE_DEBUG, "  don't know the connection!\n");
1187     return GNUNET_OK;
1188   }
1189
1190
1191   LOG (GNUNET_ERROR_TYPE_DEBUG, "  via peer %s\n",
1192               GNUNET_i2s (peer));
1193   pi = peer_get (peer);
1194   if (connection_get_next_hop (c) == pi)
1195   {
1196     LOG (GNUNET_ERROR_TYPE_DEBUG, "  SYNACK\n");
1197     fwd = GNUNET_NO;
1198     if (MESH_CONNECTION_SENT == c->state)
1199       connection_change_state (c, MESH_CONNECTION_ACK);
1200   }
1201   else if (connection_get_prev_hop (c) == pi)
1202   {
1203     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ACK\n");
1204     fwd = GNUNET_YES;
1205     connection_change_state (c, MESH_CONNECTION_READY);
1206   }
1207   else
1208   {
1209     GNUNET_break_op (0);
1210     return GNUNET_OK;
1211   }
1212   connection_reset_timeout (c, fwd);
1213
1214   /* Add path to peers? */
1215   p = c->path;
1216   if (NULL != p)
1217   {
1218     path_add_to_peers (p, GNUNET_YES);
1219   }
1220   else
1221   {
1222     GNUNET_break (0);
1223   }
1224
1225   /* Message for us as creator? */
1226   if (connection_is_origin (c, GNUNET_YES))
1227   {
1228     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Connection (SYN)ACK for us!\n");
1229     connection_change_state (c, MESH_CONNECTION_READY);
1230     if (MESH_TUNNEL_READY != c->t->state)
1231       tunnel_change_state (c->t, MESH_TUNNEL_READY);
1232     send_connection_ack (c, GNUNET_YES);
1233     tunnel_send_queued_data (c->t, GNUNET_YES);
1234     if (3 <= tunnel_count_connections (c->t) && NULL != c->t->peer->dhtget)
1235     {
1236       GNUNET_DHT_get_stop (c->t->peer->dhtget);
1237       c->t->peer->dhtget = NULL;
1238     }
1239     return GNUNET_OK;
1240   }
1241
1242   /* Message for us as destination? */
1243   if (GMC_is_terminal (c, GNUNET_YES))
1244   {
1245     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Connection ACK for us!\n");
1246     if (MESH_TUNNEL_READY != c->t->state)
1247       tunnel_change_state (c->t, MESH_TUNNEL_READY);
1248     connection_change_state (c, MESH_CONNECTION_READY);
1249     tunnel_send_queued_data (c->t, GNUNET_NO);
1250     return GNUNET_OK;
1251   }
1252
1253   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
1254   send_prebuilt_message_connection (message, c, NULL, fwd);
1255   return GNUNET_OK;
1256 }
1257
1258
1259 /**
1260  * Core handler for notifications of broken paths
1261  *
1262  * @param cls Closure (unused).
1263  * @param peer Peer identity of sending neighbor.
1264  * @param message Message.
1265  *
1266  * @return GNUNET_OK to keep the connection open,
1267  *         GNUNET_SYSERR to close it (signal serious error)
1268  */
1269 int
1270 GMC_handle_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
1271                    const struct GNUNET_MessageHeader *message)
1272 {
1273   struct GNUNET_MESH_ConnectionBroken *msg;
1274   struct MeshConnection *c;
1275
1276   LOG (GNUNET_ERROR_TYPE_DEBUG,
1277               "Received a CONNECTION BROKEN msg from %s\n", GNUNET_i2s (peer));
1278   msg = (struct GNUNET_MESH_ConnectionBroken *) message;
1279   LOG (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
1280               GNUNET_i2s (&msg->peer1));
1281   LOG (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
1282               GNUNET_i2s (&msg->peer2));
1283   c = connection_get (&msg->cid);
1284   if (NULL == c)
1285   {
1286     GNUNET_break_op (0);
1287     return GNUNET_OK;
1288   }
1289   tunnel_notify_connection_broken (c->t, GNUNET_PEER_search (&msg->peer1),
1290                                    GNUNET_PEER_search (&msg->peer2));
1291   return GNUNET_OK;
1292
1293 }
1294
1295
1296 /**
1297  * Core handler for tunnel destruction
1298  *
1299  * @param cls Closure (unused).
1300  * @param peer Peer identity of sending neighbor.
1301  * @param message Message.
1302  *
1303  * @return GNUNET_OK to keep the connection open,
1304  *         GNUNET_SYSERR to close it (signal serious error)
1305  */
1306 int
1307 GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
1308                     const struct GNUNET_MessageHeader *message)
1309 {
1310   struct GNUNET_MESH_ConnectionDestroy *msg;
1311   struct MeshConnection *c;
1312   GNUNET_PEER_Id id;
1313   int fwd;
1314
1315   msg = (struct GNUNET_MESH_ConnectionDestroy *) message;
1316   LOG (GNUNET_ERROR_TYPE_DEBUG,
1317               "Got a CONNECTION DESTROY message from %s\n",
1318               GNUNET_i2s (peer));
1319   LOG (GNUNET_ERROR_TYPE_DEBUG,
1320               "  for connection %s\n",
1321               GNUNET_h2s (&msg->cid));
1322   c = connection_get (&msg->cid);
1323   if (NULL == c)
1324   {
1325     /* Probably already got the message from another path,
1326      * destroyed the tunnel and retransmitted to children.
1327      * Safe to ignore.
1328      */
1329     GNUNET_STATISTICS_update (stats, "# control on unknown tunnel",
1330                               1, GNUNET_NO);
1331     return GNUNET_OK;
1332   }
1333   id = GNUNET_PEER_search (peer);
1334   if (id == connection_get_prev_hop (c)->id)
1335     fwd = GNUNET_YES;
1336   else if (id == connection_get_next_hop (c)->id)
1337     fwd = GNUNET_NO;
1338   else
1339   {
1340     GNUNET_break_op (0);
1341     return GNUNET_OK;
1342   }
1343   send_prebuilt_message_connection (message, c, NULL, fwd);
1344   c->destroy = GNUNET_YES;
1345
1346   return GNUNET_OK;
1347 }
1348
1349 /**
1350  * Generic handler for mesh network encrypted traffic.
1351  *
1352  * @param peer Peer identity this notification is about.
1353  * @param message Encrypted message.
1354  * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1355  *
1356  * @return GNUNET_OK to keep the connection open,
1357  *         GNUNET_SYSERR to close it (signal serious error)
1358  */
1359 static int
1360 handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer,
1361                        const struct GNUNET_MESH_Encrypted *msg,
1362                        int fwd)
1363 {
1364   struct MeshConnection *c;
1365   struct MeshTunnel2 *t;
1366   struct MeshPeer *neighbor;
1367   struct MeshFlowControl *fc;
1368   uint32_t pid;
1369   uint32_t ttl;
1370   uint16_t type;
1371   size_t size;
1372
1373   /* Check size */
1374   size = ntohs (msg->header.size);
1375   if (size <
1376       sizeof (struct GNUNET_MESH_Encrypted) +
1377       sizeof (struct GNUNET_MessageHeader))
1378   {
1379     GNUNET_break_op (0);
1380     return GNUNET_OK;
1381   }
1382   type = ntohs (msg->header.type);
1383   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1384   LOG (GNUNET_ERROR_TYPE_DEBUG, "got a %s message from %s\n",
1385               GNUNET_MESH_DEBUG_M2S (type), GNUNET_i2s (peer));
1386
1387   /* Check connection */
1388   c = connection_get (&msg->cid);
1389   if (NULL == c)
1390   {
1391     GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
1392     LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING connection unknown\n");
1393     return GNUNET_OK;
1394   }
1395   t = c->t;
1396   fc = fwd ? &c->bck_fc : &c->fwd_fc;
1397
1398   /* Check if origin is as expected */
1399   neighbor = connection_get_hop (c, !fwd);
1400   if (peer_get (peer)->id != neighbor->id)
1401   {
1402     GNUNET_break_op (0);
1403     return GNUNET_OK;
1404   }
1405
1406   /* Check PID */
1407   pid = ntohl (msg->pid);
1408   if (GMC_is_pid_bigger (pid, fc->last_ack_sent))
1409   {
1410     GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
1411     LOG (GNUNET_ERROR_TYPE_DEBUG,
1412                 "WARNING Received PID %u, (prev %u), ACK %u\n",
1413                 pid, fc->last_pid_recv, fc->last_ack_sent);
1414     return GNUNET_OK;
1415   }
1416   if (GNUNET_NO == GMC_is_pid_bigger (pid, fc->last_pid_recv))
1417   {
1418     GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO);
1419     LOG (GNUNET_ERROR_TYPE_DEBUG,
1420                 " Pid %u not expected (%u+), dropping!\n",
1421                 pid, fc->last_pid_recv + 1);
1422     return GNUNET_OK;
1423   }
1424   if (MESH_CONNECTION_SENT == c->state)
1425     connection_change_state (c, MESH_CONNECTION_READY);
1426   connection_reset_timeout (c, fwd);
1427   fc->last_pid_recv = pid;
1428
1429   /* Is this message for us? */
1430   if (GMC_is_terminal (c, fwd))
1431   {
1432     size_t dsize = size - sizeof (struct GNUNET_MESH_Encrypted);
1433     char cbuf[dsize];
1434     struct GNUNET_MessageHeader *msgh;
1435     unsigned int off;
1436
1437     /* TODO signature verification */
1438     LOG (GNUNET_ERROR_TYPE_DEBUG, "  message for us!\n");
1439     GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
1440
1441     fc->last_pid_recv = pid;
1442     tunnel_decrypt (t, cbuf, &msg[1], dsize, msg->iv, fwd);
1443     off = 0;
1444     while (off < dsize)
1445     {
1446       msgh = (struct GNUNET_MessageHeader *) &cbuf[off];
1447       handle_decrypted (t, msgh, fwd);
1448       off += ntohs (msgh->size);
1449     }
1450     send_ack (c, NULL, fwd);
1451     return GNUNET_OK;
1452   }
1453
1454   /* Message not for us: forward to next hop */
1455   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
1456   ttl = ntohl (msg->ttl);
1457   LOG (GNUNET_ERROR_TYPE_DEBUG, "   ttl: %u\n", ttl);
1458   if (ttl == 0)
1459   {
1460     GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
1461     LOG (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
1462     send_ack (c, NULL, fwd);
1463     return GNUNET_OK;
1464   }
1465   GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
1466
1467   send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
1468
1469   return GNUNET_OK;
1470 }
1471
1472
1473 /**
1474  * Core handler for mesh network traffic going orig->dest.
1475  *
1476  * @param cls Closure (unused).
1477  * @param message Message received.
1478  * @param peer Peer who sent the message.
1479  *
1480  * @return GNUNET_OK to keep the connection open,
1481  *         GNUNET_SYSERR to close it (signal serious error)
1482  */
1483 int
1484 GMC_handle_fwd (void *cls, const struct GNUNET_PeerIdentity *peer,
1485                 const struct GNUNET_MessageHeader *message)
1486 {
1487   return handle_mesh_encrypted (peer,
1488                                 (struct GNUNET_MESH_Encrypted *)message,
1489                                 GNUNET_YES);
1490 }
1491
1492 /**
1493  * Core handler for mesh network traffic going dest->orig.
1494  *
1495  * @param cls Closure (unused).
1496  * @param message Message received.
1497  * @param peer Peer who sent the message.
1498  *
1499  * @return GNUNET_OK to keep the connection open,
1500  *         GNUNET_SYSERR to close it (signal serious error)
1501  */
1502 int
1503 GMC_handle_bck (void *cls, const struct GNUNET_PeerIdentity *peer,
1504                 const struct GNUNET_MessageHeader *message)
1505 {
1506   return handle_mesh_encrypted (peer,
1507                                 (struct GNUNET_MESH_Encrypted *)message,
1508                                 GNUNET_NO);
1509 }
1510
1511
1512 /**
1513  * Core handler for mesh network traffic point-to-point acks.
1514  *
1515  * @param cls closure
1516  * @param message message
1517  * @param peer peer identity this notification is about
1518  *
1519  * @return GNUNET_OK to keep the connection open,
1520  *         GNUNET_SYSERR to close it (signal serious error)
1521  */
1522 int
1523 GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
1524                 const struct GNUNET_MessageHeader *message)
1525 {
1526   struct GNUNET_MESH_ACK *msg;
1527   struct MeshConnection *c;
1528   struct MeshFlowControl *fc;
1529   GNUNET_PEER_Id id;
1530   uint32_t ack;
1531   int fwd;
1532
1533   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1534   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
1535               GNUNET_i2s (peer));
1536   msg = (struct GNUNET_MESH_ACK *) message;
1537
1538   c = connection_get (&msg->cid);
1539
1540   if (NULL == c)
1541   {
1542     GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1,
1543                               GNUNET_NO);
1544     return GNUNET_OK;
1545   }
1546
1547   /* Is this a forward or backward ACK? */
1548   id = GNUNET_PEER_search (peer);
1549   if (connection_get_next_hop (c)->id == id)
1550   {
1551     LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
1552     fc = &c->fwd_fc;
1553     fwd = GNUNET_YES;
1554   }
1555   else if (connection_get_prev_hop (c)->id == id)
1556   {
1557     LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK ACK\n");
1558     fc = &c->bck_fc;
1559     fwd = GNUNET_NO;
1560   }
1561   else
1562   {
1563     GNUNET_break_op (0);
1564     return GNUNET_OK;
1565   }
1566
1567   ack = ntohl (msg->ack);
1568   LOG (GNUNET_ERROR_TYPE_DEBUG, "  ACK %u (was %u)\n",
1569               ack, fc->last_ack_recv);
1570   if (GMC_is_pid_bigger (ack, fc->last_ack_recv))
1571     fc->last_ack_recv = ack;
1572
1573   /* Cancel polling if the ACK is big enough. */
1574   if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task &&
1575       GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
1576   {
1577     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Cancel poll\n");
1578     GNUNET_SCHEDULER_cancel (fc->poll_task);
1579     fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
1580     fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
1581   }
1582
1583   connection_unlock_queue (c, fwd);
1584
1585   return GNUNET_OK;
1586 }
1587
1588
1589 /**
1590  * Core handler for mesh network traffic point-to-point ack polls.
1591  *
1592  * @param cls closure
1593  * @param message message
1594  * @param peer peer identity this notification is about
1595  *
1596  * @return GNUNET_OK to keep the connection open,
1597  *         GNUNET_SYSERR to close it (signal serious error)
1598  */
1599 int
1600 GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
1601                  const struct GNUNET_MessageHeader *message)
1602 {
1603   struct GNUNET_MESH_Poll *msg;
1604   struct MeshConnection *c;
1605   struct MeshFlowControl *fc;
1606   GNUNET_PEER_Id id;
1607   uint32_t pid;
1608   int fwd;
1609
1610   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1611   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a POLL packet from %s!\n",
1612               GNUNET_i2s (peer));
1613
1614   msg = (struct GNUNET_MESH_Poll *) message;
1615
1616   c = connection_get (&msg->cid);
1617
1618   if (NULL == c)
1619   {
1620     GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
1621                               GNUNET_NO);
1622     GNUNET_break_op (0);
1623     return GNUNET_OK;
1624   }
1625
1626   /* Is this a forward or backward ACK?
1627    * Note: a poll should never be needed in a loopback case,
1628    * since there is no possiblility of packet loss there, so
1629    * this way of discerining FWD/BCK should not be a problem.
1630    */
1631   id = GNUNET_PEER_search (peer);
1632   if (connection_get_next_hop (c)->id == id)
1633   {
1634     LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
1635     fc = &c->fwd_fc;
1636   }
1637   else if (connection_get_prev_hop (c)->id == id)
1638   {
1639     LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK ACK\n");
1640     fc = &c->bck_fc;
1641   }
1642   else
1643   {
1644     GNUNET_break_op (0);
1645     return GNUNET_OK;
1646   }
1647
1648   pid = ntohl (msg->pid);
1649   LOG (GNUNET_ERROR_TYPE_DEBUG, "  PID %u, OLD %u\n",
1650               pid, fc->last_pid_recv);
1651   fc->last_pid_recv = pid;
1652   fwd = fc == &c->fwd_fc;
1653   send_ack (c, NULL, fwd);
1654
1655   return GNUNET_OK;
1656 }
1657
1658
1659 /**
1660  * Core handler for mesh keepalives.
1661  *
1662  * @param cls closure
1663  * @param message message
1664  * @param peer peer identity this notification is about
1665  * @return GNUNET_OK to keep the connection open,
1666  *         GNUNET_SYSERR to close it (signal serious error)
1667  *
1668  * TODO: Check who we got this from, to validate route.
1669  */
1670 int
1671 GMC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
1672                     const struct GNUNET_MessageHeader *message)
1673 {
1674   struct GNUNET_MESH_ConnectionKeepAlive *msg;
1675   struct MeshConnection *c;
1676   struct MeshPeer *neighbor;
1677   int fwd;
1678
1679   msg = (struct GNUNET_MESH_ConnectionKeepAlive *) message;
1680   LOG (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
1681               GNUNET_i2s (peer));
1682
1683   c = connection_get (&msg->cid);
1684   if (NULL == c)
1685   {
1686     GNUNET_STATISTICS_update (stats, "# keepalive on unknown connection", 1,
1687                               GNUNET_NO);
1688     return GNUNET_OK;
1689   }
1690
1691   fwd = GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE == ntohs (message->type) ?
1692         GNUNET_YES : GNUNET_NO;
1693
1694   /* Check if origin is as expected */
1695   neighbor = connection_get_hop (c, fwd);
1696   if (peer_get (peer)->id != neighbor->id)
1697   {
1698     GNUNET_break_op (0);
1699     return GNUNET_OK;
1700   }
1701
1702   connection_change_state (c, MESH_CONNECTION_READY);
1703   connection_reset_timeout (c, fwd);
1704
1705   if (GMC_is_terminal (c, fwd))
1706     return GNUNET_OK;
1707
1708   GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
1709   send_prebuilt_message_connection (message, c, NULL, fwd);
1710
1711   return GNUNET_OK;
1712 }
1713
1714
1715 /**
1716  * Send an ACK on the appropriate connection/channel, depending on
1717  * the direction and the position of the peer.
1718  *
1719  * @param c Which connection to send the hop-by-hop ACK.
1720  * @param ch Channel, if any.
1721  * @param fwd Is this a fwd ACK? (will go dest->root)
1722  */
1723 static void
1724 send_ack (struct MeshConnection *c, struct MeshChannel *ch, int fwd)
1725 {
1726   unsigned int buffer;
1727
1728   LOG (GNUNET_ERROR_TYPE_DEBUG,
1729               "send ack %s on %p %p\n",
1730               fwd ? "FWD" : "BCK", c, ch);
1731   if (NULL == c || GMC_is_terminal (c, fwd))
1732   {
1733     LOG (GNUNET_ERROR_TYPE_DEBUG, "  getting from all connections\n");
1734     buffer = tunnel_get_buffer (NULL == c ? ch->t : c->t, fwd);
1735   }
1736   else
1737   {
1738     LOG (GNUNET_ERROR_TYPE_DEBUG, "  getting from one connection\n");
1739     buffer = connection_get_buffer (c, fwd);
1740   }
1741   LOG (GNUNET_ERROR_TYPE_DEBUG, "  buffer available: %u\n", buffer);
1742
1743   if ( (NULL != ch && channel_is_origin (ch, fwd)) ||
1744        (NULL != c && connection_is_origin (c, fwd)) )
1745   {
1746     LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on channel...\n");
1747     if (0 < buffer)
1748     {
1749       GNUNET_assert (NULL != ch);
1750       LOG (GNUNET_ERROR_TYPE_DEBUG, "  really sending!\n");
1751       send_local_ack (ch, fwd);
1752     }
1753   }
1754   else if (NULL == c)
1755   {
1756     LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on all connections\n");
1757     GNUNET_assert (NULL != ch);
1758     channel_send_connections_ack (ch, buffer, fwd);
1759   }
1760   else
1761   {
1762     LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on connection\n");
1763     connection_send_ack (c, buffer, fwd);
1764   }
1765 }
1766
1767
1768
1769 /**
1770  * Initialize the connections subsystem
1771  *
1772  * @param c Configuration handle.
1773  */
1774 void
1775 GMC_init (const struct GNUNET_CONFIGURATION_Handle *c)
1776 {
1777   if (GNUNET_OK !=
1778       GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE",
1779                                              &max_msgs_queue))
1780   {
1781     LOG_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1782                                "MESH", "MAX_MSGS_QUEUE", "MISSING");
1783     GNUNET_SCHEDULER_shutdown ();
1784     return;
1785   }
1786
1787   if (GNUNET_OK !=
1788       GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_CONNECTIONS",
1789                                              &max_connections))
1790   {
1791     LOG_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1792                                "MESH", "MAX_CONNECTIONS", "MISSING");
1793     GNUNET_SCHEDULER_shutdown ();
1794     return;
1795   }
1796
1797   if (GNUNET_OK !=
1798       GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_CONNECTION_TIME",
1799                                            &refresh_connection_time))
1800   {
1801     LOG_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1802                                "MESH", "REFRESH_CONNECTION_TIME", "MISSING");
1803     GNUNET_SCHEDULER_shutdown ();
1804     return;
1805   }
1806   connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES);
1807 }
1808
1809 /**
1810  * Shut down the connections subsystem.
1811  */
1812 void
1813 GMC_shutdown (void)
1814 {
1815 }
1816
1817
1818 struct MeshConnection *
1819 GMC_new (const struct GNUNET_HashCode *cid,
1820          struct MeshTunnel2 *t,
1821          struct MeshPeerPath *p,
1822          unsigned int own_pos)
1823 {
1824   struct MeshConnection *c;
1825   unsigned int own_pos;
1826
1827   c = GNUNET_new (struct MeshConnection);
1828   c->id = *cid;
1829   GNUNET_CONTAINER_multihashmap_put (connections, &c->id, c,
1830                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1831   fc_init (&c->fwd_fc);
1832   fc_init (&c->bck_fc);
1833   c->fwd_fc.c = c;
1834   c->bck_fc.c = c;
1835
1836   c->t = t;
1837   if (own_pos > p->length - 1)
1838   {
1839     GNUNET_break (0);
1840     GMC_destroy (c);
1841     return NULL;
1842   }
1843   c->own_pos = own_pos;
1844   c->path = p;
1845
1846   if (0 == own_pos)
1847   {
1848     c->fwd_maintenance_task =
1849             GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
1850                                           &connection_fwd_keepalive, c);
1851   }
1852   register_neighbors (c);
1853   return c;
1854 }
1855
1856
1857 static void
1858 GMC_destroy (struct MeshConnection *c)
1859 {
1860   struct MeshPeer *peer;
1861
1862   if (NULL == c)
1863     return;
1864
1865   LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s[%X]\n",
1866               peer2s (c->t->peer),
1867               c->id);
1868
1869   /* Cancel all traffic */
1870   connection_cancel_queues (c, GNUNET_YES);
1871   connection_cancel_queues (c, GNUNET_NO);
1872
1873   /* Cancel maintainance task (keepalive/timeout) */
1874   if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task)
1875     GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
1876   if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task)
1877     GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
1878
1879   /* Deregister from neighbors */
1880   peer = connection_get_next_hop (c);
1881   if (NULL != peer && NULL != peer->connections)
1882     GNUNET_CONTAINER_multihashmap_remove (peer->connections, &c->id, c);
1883   peer = connection_get_prev_hop (c);
1884   if (NULL != peer && NULL != peer->connections)
1885     GNUNET_CONTAINER_multihashmap_remove (peer->connections, &c->id, c);
1886
1887   /* Delete */
1888   GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO);
1889   GNUNET_CONTAINER_DLL_remove (c->t->connection_head, c->t->connection_tail, c);
1890   GNUNET_free (c);
1891 }
1892
1893
1894 /**
1895  * Get the connection ID.
1896  *
1897  * @param c Connection to get the ID from.
1898  *
1899  * @return ID of the connection.
1900  */
1901 const struct GNUNET_HashCode *
1902 GMC_get_id (const struct MeshConnection *c)
1903 {
1904   return &c->id;
1905 }
1906
1907 /**
1908  * Notify other peers on a connection of a broken link. Mark connections
1909  * to destroy after all traffic has been sent.
1910  *
1911  * @param c Connection on which there has been a disconnection.
1912  * @param peer Peer that disconnected.
1913  * @param my_full_id My ID (to send to other peers).
1914  */
1915 void
1916 GMC_notify_broken (struct MeshConnection *c,
1917                    struct MeshPeer *peer,
1918                    struct GNUNET_PeerIdentity *my_full_id)
1919 {
1920   struct MeshConnection *c = value;
1921   struct GNUNET_MESH_ConnectionBroken msg;
1922   int fwd;
1923
1924   fwd = peer == connection_get_prev_hop (c);
1925
1926   connection_cancel_queues (c, !fwd);
1927   if (GMC_is_terminal (c, fwd))
1928   {
1929     /* Local shutdown, no one to notify about this. */
1930     GMC_destroy (c);
1931     return GNUNET_YES;
1932   }
1933
1934   msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectionBroken));
1935   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN);
1936   msg.cid = c->id;
1937   msg.peer1 = *my_full_id;
1938   msg.peer2 = *GNUNET_PEER_resolve2 (peer->id);
1939   GMC_send_prebuilt_message (&msg.header, c, NULL, fwd);
1940   c->destroy = GNUNET_YES;
1941
1942   return GNUNET_YES;
1943 }
1944
1945
1946 /**
1947  * Is this peer the first one on the connection?
1948  *
1949  * @param c Connection.
1950  * @param fwd Is this about fwd traffic?
1951  *
1952  * @return GNUNET_YES if origin, GNUNET_NO if relay/terminal.
1953  */
1954 int
1955 GMC_is_origin (struct MeshConnection *c, int fwd)
1956 {
1957   if (!fwd && c->path->length - 1 == c->own_pos )
1958     return GNUNET_YES;
1959   if (fwd && 0 == c->own_pos)
1960     return GNUNET_YES;
1961   return GNUNET_NO;
1962 }
1963
1964
1965 /**
1966  * Is this peer the last one on the connection?
1967  *
1968  * @param c Connection.
1969  * @param fwd Is this about fwd traffic?
1970  *            Note that the ROOT is the terminal for BCK traffic!
1971  *
1972  * @return GNUNET_YES if terminal, GNUNET_NO if relay/origin.
1973  */
1974 int
1975 GMC_is_terminal (struct MeshConnection *c, int fwd)
1976 {
1977   return GMC_is_origin (c, !fwd);
1978 }
1979
1980
1981 /**
1982  * Count connections in a DLL.
1983  * 
1984  * @param head Head of the DLL.
1985  */
1986 unsigned int
1987 GMC_count (const struct MeshConnection *head)
1988 {
1989   unsigned int count;
1990   struct MeshConnection *iter;
1991
1992   for (count = 0, iter = head; NULL != iter; iter = iter->next, count++);
1993
1994   return count;
1995 }
1996
1997
1998 /**
1999  * Sends an already built message on a connection, properly registering
2000  * all used resources.
2001  *
2002  * @param message Message to send. Function makes a copy of it.
2003  *                If message is not hop-by-hop, decrements TTL of copy.
2004  * @param c Connection on which this message is transmitted.
2005  * @param ch Channel on which this message is transmitted, or NULL.
2006  * @param fwd Is this a fwd message?
2007  */
2008 void
2009 GMC_send_prebuilt_message (    const struct GNUNET_MessageHeader *message,
2010                            struct MeshConnection *c,
2011                            struct MeshChannel *ch,
2012                            int fwd)
2013 {
2014   void *data;
2015   size_t size;
2016   uint16_t type;
2017
2018   size = ntohs (message->size);
2019   data = GNUNET_malloc (size);
2020   memcpy (data, message, size);
2021   type = ntohs (message->type);
2022   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send %s (%u) on connection %s\n",
2023               GNUNET_MESH_DEBUG_M2S (type), size, GNUNET_h2s (&c->id));
2024
2025   switch (type)
2026   {
2027     struct GNUNET_MESH_Encrypted *emsg;
2028     struct GNUNET_MESH_ACK       *amsg;
2029     struct GNUNET_MESH_Poll      *pmsg;
2030     struct GNUNET_MESH_ConnectionDestroy *dmsg;
2031     struct GNUNET_MESH_ConnectionBroken  *bmsg;
2032     uint32_t ttl;
2033
2034     case GNUNET_MESSAGE_TYPE_MESH_FWD:
2035     case GNUNET_MESSAGE_TYPE_MESH_BCK:
2036       emsg = (struct GNUNET_MESH_Encrypted *) data;
2037       ttl = ntohl (emsg->ttl);
2038       if (0 == ttl)
2039       {
2040         GNUNET_break_op (0);
2041         return;
2042       }
2043       emsg->cid = c->id;
2044       emsg->ttl = htonl (ttl - 1);
2045       emsg->pid = htonl (fwd ? c->fwd_fc.next_pid++ : c->bck_fc.next_pid++);
2046       LOG (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", ntohl (emsg->pid));
2047       break;
2048
2049     case GNUNET_MESSAGE_TYPE_MESH_ACK:
2050       amsg = (struct GNUNET_MESH_ACK *) data;
2051       amsg->cid = c->id;
2052       LOG (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ntohl (amsg->ack));
2053       break;
2054
2055     case GNUNET_MESSAGE_TYPE_MESH_POLL:
2056       pmsg = (struct GNUNET_MESH_Poll *) data;
2057       pmsg->cid = c->id;
2058       pmsg->pid = htonl (fwd ? c->fwd_fc.last_pid_sent : c->bck_fc.last_pid_sent);
2059       LOG (GNUNET_ERROR_TYPE_DEBUG, " poll %u\n", ntohl (pmsg->pid));
2060       break;
2061
2062     case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
2063       dmsg = (struct GNUNET_MESH_ConnectionDestroy *) data;
2064       dmsg->cid = c->id;
2065       dmsg->reserved = 0;
2066       break;
2067
2068     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
2069       bmsg = (struct GNUNET_MESH_ConnectionBroken *) data;
2070       bmsg->cid = c->id;
2071       bmsg->reserved = 0;
2072       break;
2073
2074     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
2075     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
2076       break;
2077
2078     default:
2079       GNUNET_break (0);
2080   }
2081
2082   GMP_queue_add (data,
2083                  type,
2084                  size,
2085                  c,
2086                  ch,
2087                  fwd);
2088 }