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