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