- remove old include
[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 "mesh_path.h"
33 #include "mesh_protocol_enc.h"
34 #include "mesh_enc.h"
35
36 #include "gnunet-service-mesh_connection.h"
37 #include "gnunet-service-mesh_peer.h"
38 #include "gnunet-service-mesh_tunnel.h"
39 #include "gnunet-service-mesh_channel.h"
40
41
42 #define LOG(level, ...) GNUNET_log_from (level,"mesh-con",__VA_ARGS__)
43
44 #define MESH_MAX_POLL_TIME      GNUNET_TIME_relative_multiply (\
45                                   GNUNET_TIME_UNIT_MINUTES,\
46                                   10)
47 #define AVG_MSGS                32
48
49
50 /******************************************************************************/
51 /********************************   STRUCTS  **********************************/
52 /******************************************************************************/
53
54 /**
55  * Struct to encapsulate all the Flow Control information to a peer to which
56  * we are directly connected (on a core level).
57  */
58 struct MeshFlowControl
59 {
60   /**
61    * Connection this controls.
62    */
63   struct MeshConnection *c;
64
65   /**
66    * How many messages are in the queue on this connection.
67    */
68   unsigned int queue_n;
69
70   /**
71    * How many messages do we accept in the queue.
72    */
73   unsigned int queue_max;
74
75   /**
76    * Next ID to use.
77    */
78   uint32_t next_pid;
79
80   /**
81    * ID of the last packet sent towards the peer.
82    */
83   uint32_t last_pid_sent;
84
85   /**
86    * ID of the last packet received from the peer.
87    */
88   uint32_t last_pid_recv;
89
90   /**
91    * Last ACK sent to the peer (peer can't send more than this PID).
92    */
93   uint32_t last_ack_sent;
94
95   /**
96    * Last ACK sent towards the origin (for traffic towards leaf node).
97    */
98   uint32_t last_ack_recv;
99
100   /**
101    * Task to poll the peer in case of a lost ACK causes stall.
102    */
103   GNUNET_SCHEDULER_TaskIdentifier poll_task;
104
105   /**
106    * How frequently to poll for ACKs.
107    */
108   struct GNUNET_TIME_Relative poll_time;
109 };
110
111 /**
112  * Keep a record of the last messages sent on this connection.
113  */
114 struct MeshConnectionPerformance
115 {
116   /**
117    * Circular buffer for storing measurements.
118    */
119   double usecsperbyte[AVG_MSGS];
120
121   /**
122    * Running average of @c usecsperbyte.
123    */
124   double avg;
125
126   /**
127    * How many values of @c usecsperbyte are valid.
128    */
129   uint16_t size;
130
131   /**
132    * Index of the next "free" position in @c usecsperbyte.
133    */
134   uint16_t idx;
135 };
136
137
138 /**
139  * Struct containing all information regarding a connection to a peer.
140  */
141 struct MeshConnection
142 {
143   /**
144    * Tunnel this connection is part of.
145    */
146   struct MeshTunnel3 *t;
147
148   /**
149    * Flow control information for traffic fwd.
150    */
151   struct MeshFlowControl fwd_fc;
152
153   /**
154    * Flow control information for traffic bck.
155    */
156   struct MeshFlowControl bck_fc;
157
158   /**
159    * Measure connection performance on the endpoint.
160    */
161   struct MeshConnectionPerformance *perf;
162
163   /**
164    * ID of the connection.
165    */
166   struct GNUNET_HashCode id;
167
168   /**
169    * State of the connection.
170    */
171   enum MeshConnectionState state;
172
173   /**
174    * Path being used for the tunnel.
175    */
176   struct MeshPeerPath *path;
177
178   /**
179    * Position of the local peer in the path.
180    */
181   unsigned int own_pos;
182
183   /**
184    * Task to keep the used paths alive at the owner,
185    * time tunnel out on all the other peers.
186    */
187   GNUNET_SCHEDULER_TaskIdentifier fwd_maintenance_task;
188
189   /**
190    * Task to keep the used paths alive at the destination,
191    * time tunnel out on all the other peers.
192    */
193   GNUNET_SCHEDULER_TaskIdentifier bck_maintenance_task;
194
195   /**
196    * Pending message count.
197    */
198   int pending_messages;
199
200   /**
201    * Destroy flag: if true, destroy on last message.
202    */
203   int destroy;
204 };
205
206 /******************************************************************************/
207 /*******************************   GLOBALS  ***********************************/
208 /******************************************************************************/
209
210 /**
211  * Global handle to the statistics service.
212  */
213 extern struct GNUNET_STATISTICS_Handle *stats;
214
215 /**
216  * Connections known, indexed by cid (MeshConnection).
217  */
218 static struct GNUNET_CONTAINER_MultiHashMap *connections;
219
220 /**
221  * How many connections are we willing to maintain.
222  * Local connections are always allowed, even if there are more connections than max.
223  */
224 static unsigned long long max_connections;
225
226 /**
227  * How many messages *in total* are we willing to queue, divide by number of
228  * connections to get connection queue size.
229  */
230 static unsigned long long max_msgs_queue;
231
232 /**
233  * How often to send path keepalives. Paths timeout after 4 missed.
234  */
235 static struct GNUNET_TIME_Relative refresh_connection_time;
236
237
238 /******************************************************************************/
239 /********************************   STATIC  ***********************************/
240 /******************************************************************************/
241
242 #if 0 // avoid compiler warning for unused static function
243 static void
244 fc_debug (struct MeshFlowControl *fc)
245 {
246   LOG (GNUNET_ERROR_TYPE_DEBUG, "    IN: %u/%u\n",
247               fc->last_pid_recv, fc->last_ack_sent);
248   LOG (GNUNET_ERROR_TYPE_DEBUG, "    OUT: %u/%u\n",
249               fc->last_pid_sent, fc->last_ack_recv);
250   LOG (GNUNET_ERROR_TYPE_DEBUG, "    QUEUE: %u/%u\n",
251               fc->queue_n, fc->queue_max);
252 }
253
254 static void
255 connection_debug (struct MeshConnection *c)
256 {
257   if (NULL == c)
258   {
259     LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n");
260     return;
261   }
262   LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
263               peer2s (c->t->peer), GNUNET_h2s (&c->id));
264   LOG (GNUNET_ERROR_TYPE_DEBUG, "  state: %u, pending msgs: %u\n",
265               c->state, c->pending_messages);
266   LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD FC\n");
267   fc_debug (&c->fwd_fc);
268   LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK FC\n");
269   fc_debug (&c->bck_fc);
270 }
271 #endif
272
273 /**
274  * Get string description for tunnel state.
275  *
276  * @param s Tunnel state.
277  *
278  * @return String representation.
279  */
280 static const char *
281 GMC_state2s (enum MeshConnectionState s)
282 {
283   switch (s)
284   {
285     case MESH_CONNECTION_NEW:
286       return "MESH_CONNECTION_NEW";
287     case MESH_CONNECTION_SENT:
288       return "MESH_CONNECTION_SENT";
289     case MESH_CONNECTION_ACK:
290       return "MESH_CONNECTION_ACK";
291     case MESH_CONNECTION_READY:
292       return "MESH_CONNECTION_READY";
293     default:
294       return "MESH_CONNECTION_STATE_ERROR";
295   }
296 }
297
298
299 /**
300  * Initialize a Flow Control structure to the initial state.
301  *
302  * @param fc Flow Control structure to initialize.
303  */
304 static void
305 fc_init (struct MeshFlowControl *fc)
306 {
307   fc->next_pid = 0;
308   fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */
309   fc->last_pid_recv = (uint32_t) -1;
310   fc->last_ack_sent = (uint32_t) 0;
311   fc->last_ack_recv = (uint32_t) 0;
312   fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
313   fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
314   fc->queue_n = 0;
315   fc->queue_max = (max_msgs_queue / max_connections) + 1;
316 }
317
318
319 /**
320  * Find a connection.
321  *
322  * @param cid Connection ID.
323  */
324 static struct MeshConnection *
325 connection_get (const struct GNUNET_HashCode *cid)
326 {
327   return GNUNET_CONTAINER_multihashmap_get (connections, cid);
328 }
329
330
331 static void
332 connection_change_state (struct MeshConnection* c,
333                          enum MeshConnectionState state)
334 {
335   LOG (GNUNET_ERROR_TYPE_DEBUG,
336               "Connection %s state was %s\n",
337               GNUNET_h2s (&c->id), GMC_state2s (c->state));
338   LOG (GNUNET_ERROR_TYPE_DEBUG,
339               "Connection %s state is now %s\n",
340               GNUNET_h2s (&c->id), GMC_state2s (state));
341   c->state = state;
342 }
343
344
345 /**
346  * Callback called when a queued message is sent.
347  *
348  * Calculates the average time 
349  *
350  * @param cls Closure.
351  * @param c Connection this message was on.
352  * @param wait Time spent waiting for core (only the time for THIS message)
353  */
354 static void 
355 message_sent (void *cls,
356               struct MeshConnection *c,
357               struct GNUNET_TIME_Relative wait)
358 {
359   struct MeshConnectionPerformance *p;
360   size_t size = (size_t) cls;
361   double usecsperbyte;
362
363   if (NULL == c->perf)
364     return; /* Only endpoints are interested in this. */
365
366   p = c->perf;
367   usecsperbyte = ((double) wait.rel_value_us) / size;
368   if (p->size == AVG_MSGS)
369   {
370     /* Array is full. Substract oldest value, add new one and store. */
371     p->avg -= (p->usecsperbyte[p->idx] / AVG_MSGS);
372     p->usecsperbyte[p->idx] = usecsperbyte;
373     p->avg += (p->usecsperbyte[p->idx] / AVG_MSGS);
374   }
375   else
376   {
377     /* Array not yet full. Add current value to avg and store. */
378     p->usecsperbyte[p->idx] = usecsperbyte;
379     p->avg *= p->size;
380     p->avg += p->usecsperbyte[p->idx];
381     p->size++;
382     p->avg /= p->size;
383   }
384   p->idx = (p->idx + 1) % AVG_MSGS;
385 }
386
387
388
389 /**
390  * Send an ACK informing the predecessor about the available buffer space.
391  *
392  * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
393  * the ACK itself goes "back" (dest->root).
394  *
395  * @param c Connection on which to send the ACK.
396  * @param buffer How much space free to advertise?
397  * @param fwd Is this FWD ACK? (Going dest->owner)
398  */
399 static void
400 connection_send_ack (struct MeshConnection *c, unsigned int buffer, int fwd)
401 {
402   struct MeshFlowControl *next_fc;
403   struct MeshFlowControl *prev_fc;
404   struct GNUNET_MESH_ACK msg;
405   uint32_t ack;
406   int delta;
407
408   next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
409   prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
410
411   LOG (GNUNET_ERROR_TYPE_DEBUG,
412               "connection send %s ack on %s\n",
413               fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
414
415   /* Check if we need to transmit the ACK */
416   if (prev_fc->last_ack_sent - prev_fc->last_pid_recv > 3)
417   {
418     LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n");
419     LOG (GNUNET_ERROR_TYPE_DEBUG,
420                 "  last pid recv: %u, last ack sent: %u\n",
421                 prev_fc->last_pid_recv, prev_fc->last_ack_sent);
422     return;
423   }
424
425   /* Ok, ACK might be necessary, what PID to ACK? */
426   delta = next_fc->queue_max - next_fc->queue_n;
427   ack = prev_fc->last_pid_recv + delta;
428   LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
429   LOG (GNUNET_ERROR_TYPE_DEBUG,
430               " last pid %u, last ack %u, qmax %u, q %u\n",
431               prev_fc->last_pid_recv, prev_fc->last_ack_sent,
432               next_fc->queue_max, next_fc->queue_n);
433   if (ack == prev_fc->last_ack_sent)
434   {
435     LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
436     return;
437   }
438
439   prev_fc->last_ack_sent = ack;
440
441   /* Build ACK message and send on connection */
442   msg.header.size = htons (sizeof (msg));
443   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
444   msg.ack = htonl (ack);
445   msg.cid = c->id;
446
447   GMC_send_prebuilt_message (&msg.header, c, NULL, !fwd);
448 }
449
450
451 /**
452  * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
453  * or a first CONNECTION_ACK directed to us.
454  *
455  * @param connection Connection to confirm.
456  * @param fwd Is this a fwd ACK? (First is bck (SYNACK), second is fwd (ACK))
457  */
458 static void
459 send_connection_ack (struct MeshConnection *connection, int fwd)
460 {
461   struct MeshTunnel3 *t;
462
463   t = connection->t;
464   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send connection ack\n");
465   GMP_queue_add (NULL,
466                  GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
467                  sizeof (struct GNUNET_MESH_ConnectionACK),
468                  connection, NULL, fwd,
469                  &message_sent, sizeof (struct GNUNET_MESH_ConnectionACK));
470   if (MESH_TUNNEL3_NEW == GMT_get_state (t))
471     GMT_change_state (t, MESH_TUNNEL3_WAITING);
472   if (MESH_CONNECTION_READY != connection->state)
473     GMC_change_state (connection, MESH_CONNECTION_SENT);
474 }
475
476
477 /**
478  * Sends a CREATE CONNECTION message for a path to a peer.
479  * Changes the connection and tunnel states if necessary.
480  *
481  * @param connection Connection to create.
482  */
483 static void
484 send_connection_create (struct MeshConnection *connection)
485 {
486 enum MeshTunnel3State state;
487   size_t size;
488
489   size = sizeof (struct GNUNET_MESH_ConnectionCreate);
490   size += connection->path->length * sizeof (struct GNUNET_PeerIdentity);
491   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send connection create\n");
492   GMP_queue_add (NULL,
493                  GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
494                  size,
495                  connection,
496                  NULL,
497                  GNUNET_YES, &message_sent, size);
498   state = GMT_get_state (connection->t);
499   if (MESH_TUNNEL3_SEARCHING == state || MESH_TUNNEL3_NEW == state)
500     GMT_change_state (connection->t, MESH_TUNNEL3_WAITING);
501   if (MESH_CONNECTION_NEW == connection->state)
502     connection_change_state (connection, MESH_CONNECTION_SENT);
503 }
504
505
506 /**
507  * Send keepalive packets for a connection.
508  *
509  * @param c Connection to keep alive..
510  * @param fwd Is this a FWD keepalive? (owner -> dest).
511  */
512 static void
513 connection_keepalive (struct MeshConnection *c, int fwd)
514 {
515   struct GNUNET_MESH_ConnectionKeepAlive *msg;
516   size_t size = sizeof (struct GNUNET_MESH_ConnectionKeepAlive);
517   char cbuf[size];
518   uint16_t type;
519
520   type = fwd ? GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE :
521                GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE;
522
523   LOG (GNUNET_ERROR_TYPE_DEBUG,
524        "sending %s keepalive for connection %s[%d]\n",
525        fwd ? "FWD" : "BCK", GMT_2s (c->t), c->id);
526
527   msg = (struct GNUNET_MESH_ConnectionKeepAlive *) cbuf;
528   msg->header.size = htons (size);
529   msg->header.type = htons (type);
530   msg->cid = c->id;
531
532   GMC_send_prebuilt_message (&msg->header, c, NULL, fwd);
533 }
534
535
536 /**
537  * Send CONNECTION_{CREATE/ACK} packets for a connection.
538  *
539  * @param c Connection for which to send the message.
540  * @param fwd If GNUNET_YES, send CREATE, otherwise send ACK.
541  */
542 static void
543 connection_recreate (struct MeshConnection *c, int fwd)
544 {
545   LOG (GNUNET_ERROR_TYPE_DEBUG, "sending connection recreate\n");
546   if (fwd)
547     send_connection_create (c);
548   else
549     send_connection_ack (c, GNUNET_NO);
550 }
551
552
553 /**
554  * Generic connection timer management.
555  * Depending on the role of the peer in the connection will send the
556  * appropriate message (build or keepalive)
557  *
558  * @param c Conncetion to maintain.
559  * @param fwd Is FWD?
560  */
561 static void
562 connection_maintain (struct MeshConnection *c, int fwd)
563 {
564   if (MESH_TUNNEL3_SEARCHING == GMT_get_state (c->t))
565   {
566     /* TODO DHT GET with RO_BART */
567     return;
568   }
569   switch (c->state)
570   {
571     case MESH_CONNECTION_NEW:
572       GNUNET_break (0);
573     case MESH_CONNECTION_SENT:
574       connection_recreate (c, fwd);
575       break;
576     case MESH_CONNECTION_READY:
577       connection_keepalive (c, fwd);
578       break;
579     default:
580       break;
581   }
582 }
583
584
585 static void
586 connection_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
587 {
588   struct MeshConnection *c = cls;
589
590   c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
591   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
592     return;
593
594   connection_maintain (c, GNUNET_YES);
595   c->fwd_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
596                                                           &connection_fwd_keepalive,
597                                                           c);
598 }
599
600
601 static void
602 connection_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
603 {
604   struct MeshConnection *c = cls;
605
606   c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
607   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
608     return;
609
610   connection_maintain (c, GNUNET_NO);
611   c->bck_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
612                                                           &connection_bck_keepalive,
613                                                           c);
614 }
615
616
617
618 /**
619  * Get the previous hop in a connection
620  *
621  * @param c Connection.
622  *
623  * @return Previous peer in the connection.
624  */
625 static struct MeshPeer *
626 connection_get_prev_hop (struct MeshConnection *c)
627 {
628   GNUNET_PEER_Id id;
629
630   if (0 == c->own_pos || c->path->length < 2)
631     id = c->path->peers[0];
632   else
633     id = c->path->peers[c->own_pos - 1];
634
635   return peer_get_short (id);
636 }
637
638
639 /**
640  * Get the next hop in a connection
641  *
642  * @param c Connection.
643  *
644  * @return Next peer in the connection.
645  */
646 static struct MeshPeer *
647 connection_get_next_hop (struct MeshConnection *c)
648 {
649   GNUNET_PEER_Id id;
650
651   if ((c->path->length - 1) == c->own_pos || c->path->length < 2)
652     id = c->path->peers[c->path->length - 1];
653   else
654     id = c->path->peers[c->own_pos + 1];
655
656   return peer_get_short (id);
657 }
658
659
660 /**
661  * Get the hop in a connection.
662  *
663  * @param c Connection.
664  * @param fwd Next hop?
665  *
666  * @return Next peer in the connection.
667  */
668 static struct MeshPeer *
669 connection_get_hop (struct MeshConnection *c, int fwd)
670 {
671   if (fwd)
672     return connection_get_next_hop (c);
673   return connection_get_prev_hop (c);
674 }
675
676
677 /**
678  * Get the first transmittable message for a connection.
679  *
680  * @param c Connection.
681  * @param fwd Is this FWD?
682  *
683  * @return First transmittable message.
684  */
685 static struct MeshPeerQueue *
686 connection_get_first_message (struct MeshConnection *c, int fwd)
687 {
688   struct MeshPeerQueue *q;
689   struct MeshPeer *p;
690
691   p = connection_get_hop (c, fwd);
692
693   for (q = p->queue_head; NULL != q; q = q->next)
694   {
695     if (q->c != c)
696       continue;
697     if (queue_is_sendable (q))
698       return q;
699   }
700
701   return NULL;
702 }
703
704
705 /**
706  * @brief Re-initiate traffic on this connection if necessary.
707  *
708  * Check if there is traffic queued towards this peer
709  * and the core transmit handle is NULL (traffic was stalled).
710  * If so, call core tmt rdy.
711  *
712  * @param c Connection on which initiate traffic.
713  * @param fwd Is this about fwd traffic?
714  */
715 static void
716 connection_unlock_queue (struct MeshConnection *c, int fwd)
717 {
718   struct MeshPeer *peer;
719   struct MeshPeerQueue *q;
720   size_t size;
721
722   LOG (GNUNET_ERROR_TYPE_DEBUG,
723               "connection_unlock_queue %s on %s\n",
724               fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
725
726   if (GMC_is_terminal (c, fwd))
727   {
728     LOG (GNUNET_ERROR_TYPE_DEBUG, " is terminal!\n");
729     return;
730   }
731
732   peer = connection_get_hop (c, fwd);
733
734   if (NULL != peer->core_transmit)
735   {
736     LOG (GNUNET_ERROR_TYPE_DEBUG, "  already unlocked!\n");
737     return; /* Already unlocked */
738   }
739
740   q = connection_get_first_message (c, fwd);
741   if (NULL == q)
742   {
743     LOG (GNUNET_ERROR_TYPE_DEBUG, "  queue empty!\n");
744     return; /* Nothing to transmit */
745   }
746
747   size = q->size;
748   peer->core_transmit =
749       GNUNET_CORE_notify_transmit_ready (core_handle,
750                                          GNUNET_NO,
751                                          0,
752                                          GNUNET_TIME_UNIT_FOREVER_REL,
753                                          GNUNET_PEER_resolve2 (peer->id),
754                                          size,
755                                          &queue_send,
756                                          peer);
757 }
758
759
760 /**
761  * Cancel all transmissions that belong to a certain connection.
762  *
763  * @param c Connection which to cancel.
764  * @param fwd Cancel fwd traffic?
765  */
766 static void
767 connection_cancel_queues (struct MeshConnection *c, int fwd)
768 {
769
770   struct MeshFlowControl *fc;
771   struct MeshPeer *peer;
772
773   if (NULL == c)
774   {
775     GNUNET_break (0);
776     return;
777   }
778
779   peer = connection_get_hop (c, fwd);
780   GMP_queue_cancel (peer, c);
781
782   fc = fwd ? &c->fwd_fc : &c->bck_fc;
783   if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
784   {
785     GNUNET_SCHEDULER_cancel (fc->poll_task);
786     fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
787   }
788 }
789
790
791 /**
792  * Function called if a connection has been stalled for a while,
793  * possibly due to a missed ACK. Poll the neighbor about its ACK status.
794  *
795  * @param cls Closure (poll ctx).
796  * @param tc TaskContext.
797  */
798 static void
799 connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
800 {
801   struct MeshFlowControl *fc = cls;
802   struct GNUNET_MESH_Poll msg;
803   struct MeshConnection *c;
804
805   fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
806   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
807   {
808     return;
809   }
810
811   c = fc->c;
812   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Polling!\n");
813   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** connection [%X]\n",
814               GNUNET_h2s (&c->id));
815   LOG (GNUNET_ERROR_TYPE_DEBUG, " ***   %s\n",
816               fc == &c->fwd_fc ? "FWD" : "BCK");
817
818   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL);
819   msg.header.size = htons (sizeof (msg));
820   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** pid (%u)!\n", fc->last_pid_sent);
821   send_prebuilt_message_connection (&msg.header, c, NULL, fc == &c->fwd_fc);
822   fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
823   fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
824                                                 &connection_poll, fc);
825 }
826
827
828 /**
829  * Timeout function due to lack of keepalive/traffic from the owner.
830  * Destroys connection if called.
831  *
832  * @param cls Closure (connection to destroy).
833  * @param tc TaskContext.
834  */
835 static void
836 connection_fwd_timeout (void *cls,
837                         const struct GNUNET_SCHEDULER_TaskContext *tc)
838 {
839   struct MeshConnection *c = cls;
840
841   c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
842   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
843     return;
844   LOG (GNUNET_ERROR_TYPE_DEBUG,
845               "Connection %s[%X] FWD timed out. Destroying.\n",
846               GMT_2s (c->t),
847               c->id);
848
849   if (GMC_is_origin (c, GNUNET_YES)) /* If local, leave. */
850     return;
851
852   GMC_destroy (c);
853 }
854
855
856 /**
857  * Timeout function due to lack of keepalive/traffic from the destination.
858  * Destroys connection if called.
859  *
860  * @param cls Closure (connection to destroy).
861  * @param tc TaskContext
862  */
863 static void
864 connection_bck_timeout (void *cls,
865                         const struct GNUNET_SCHEDULER_TaskContext *tc)
866 {
867   struct MeshConnection *c = cls;
868
869   c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
870   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
871     return;
872
873   LOG (GNUNET_ERROR_TYPE_DEBUG,
874               "Connection %s[%X] FWD timed out. Destroying.\n",
875               GMT_2s (c->t), c->id);
876
877   if (GMC_is_origin (c, GNUNET_NO)) /* If local, leave. */
878     return;
879
880   GMC_destroy (c);
881 }
882
883
884 /**
885  * Resets the connection timeout task, some other message has done the
886  * task's job.
887  * - For the first peer on the direction this means to send
888  *   a keepalive or a path confirmation message (either create or ACK).
889  * - For all other peers, this means to destroy the connection,
890  *   due to lack of activity.
891  * Starts the tiemout if no timeout was running (connection just created).
892  *
893  * @param c Connection whose timeout to reset.
894  * @param fwd Is this forward?
895  *
896  * TODO use heap to improve efficiency of scheduler.
897  */
898 static void
899 connection_reset_timeout (struct MeshConnection *c, int fwd)
900 {
901   GNUNET_SCHEDULER_TaskIdentifier *ti;
902   GNUNET_SCHEDULER_Task f;
903
904   ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task;
905
906   if (GNUNET_SCHEDULER_NO_TASK != *ti)
907     GNUNET_SCHEDULER_cancel (*ti);
908
909   if (GMC_is_origin (c, fwd)) /* Endpoint */
910   {
911     f  = fwd ? &connection_fwd_keepalive : &connection_bck_keepalive;
912     *ti = GNUNET_SCHEDULER_add_delayed (refresh_connection_time, f, c);
913   }
914   else /* Relay */
915   {
916     struct GNUNET_TIME_Relative delay;
917
918     delay = GNUNET_TIME_relative_multiply (refresh_connection_time, 4);
919     f  = fwd ? &connection_fwd_timeout : &connection_bck_timeout;
920     *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c);
921   }
922 }
923
924
925 /**
926  * Add the connection to the list of both neighbors.
927  *
928  * @param c Connection.
929  */
930 static void
931 register_neighbors (struct MeshConnection *c)
932 {
933   struct MeshPeer *peer;
934
935   peer = connection_get_next_hop (c);
936   if (GNUNET_NO == GMP_is_neighbor (peer))
937   {
938     GMC_destroy (c);
939     return NULL;
940   }
941   GMP_add_connection (peer, c);
942   peer = connection_get_prev_hop (c);
943   if (GNUNET_NO == GMP_is_neighbor (peer))
944   {
945     GMC_destroy (c);
946     return NULL;
947   }
948   GMP_add_connection (peer, c);
949 }
950
951
952 /**
953  * Remove the connection from the list of both neighbors.
954  *
955  * @param c Connection.
956  */
957 static void
958 unregister_neighbors (struct MeshConnection *c)
959 {
960   struct MeshPeer *peer;
961
962   peer = connection_get_next_hop (c);
963   GMP_remove_connection (peer, c);
964
965   peer = connection_get_prev_hop (c);
966   GMP_remove_connection (peer, c);
967
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_TUNNEL3_NEW == GMT_get_state (c->t))
1090       GMT_change_state (c->t,  MESH_TUNNEL3_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_TUNNEL3_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_TUNNEL3_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 }