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