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