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