- fixes
[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 = peer_get (&id[size - 1]);
1027   orig_peer = peer_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     if (NULL == orig_peer->tunnel)
1036     {
1037       orig_peer->tunnel = GMT_new ();
1038       orig_peer->tunnel->peer = orig_peer;
1039     }
1040     GMT_add_connection (orig_peer->tunnel, c);
1041     if (MESH_TUNNEL3_NEW == GMT_get_state (c->t))
1042       GMT_change_state (c->t,  MESH_TUNNEL3_WAITING);
1043
1044     send_connection_ack (c, GNUNET_NO);
1045     if (MESH_CONNECTION_SENT == c->state)
1046       connection_change_state (c, MESH_CONNECTION_ACK);
1047
1048     /* Keep tunnel alive in direction dest->owner*/
1049     connection_reset_timeout (c, GNUNET_NO);
1050   }
1051   else
1052   {
1053     /* It's for somebody else! Retransmit. */
1054     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Retransmitting.\n");
1055     GMP_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
1056     GMP_add_path_to_origin (orig_peer, path, GNUNET_NO);
1057     GMC_send_prebuilt_message (message, c, NULL, GNUNET_YES);
1058   }
1059   return GNUNET_OK;
1060 }
1061
1062
1063 /**
1064  * Core handler for path confirmations.
1065  *
1066  * @param cls closure
1067  * @param message message
1068  * @param peer peer identity this notification is about
1069  *
1070  * @return GNUNET_OK to keep the connection open,
1071  *         GNUNET_SYSERR to close it (signal serious error)
1072  */
1073 int
1074 GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer,
1075                     const struct GNUNET_MessageHeader *message)
1076 {
1077   struct GNUNET_MESH_ConnectionACK *msg;
1078   struct MeshConnection *c;
1079   struct MeshPeerPath *p;
1080   struct MeshPeer *pi;
1081   int fwd;
1082
1083   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1084   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a connection ACK msg\n");
1085   msg = (struct GNUNET_MESH_ConnectionACK *) message;
1086   LOG (GNUNET_ERROR_TYPE_DEBUG, "  on connection %s\n",
1087               GNUNET_h2s (&msg->cid));
1088   c = connection_get (&msg->cid);
1089   if (NULL == c)
1090   {
1091     GNUNET_STATISTICS_update (stats, "# control on unknown connection",
1092                               1, GNUNET_NO);
1093     LOG (GNUNET_ERROR_TYPE_DEBUG, "  don't know the connection!\n");
1094     return GNUNET_OK;
1095   }
1096
1097
1098   LOG (GNUNET_ERROR_TYPE_DEBUG, "  via peer %s\n",
1099               GNUNET_i2s (peer));
1100   pi = peer_get (peer);
1101   if (connection_get_next_hop (c) == pi)
1102   {
1103     LOG (GNUNET_ERROR_TYPE_DEBUG, "  SYNACK\n");
1104     fwd = GNUNET_NO;
1105     if (MESH_CONNECTION_SENT == c->state)
1106       connection_change_state (c, MESH_CONNECTION_ACK);
1107   }
1108   else if (connection_get_prev_hop (c) == pi)
1109   {
1110     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ACK\n");
1111     fwd = GNUNET_YES;
1112     connection_change_state (c, MESH_CONNECTION_READY);
1113   }
1114   else
1115   {
1116     GNUNET_break_op (0);
1117     return GNUNET_OK;
1118   }
1119   connection_reset_timeout (c, fwd);
1120
1121   /* Add path to peers? */
1122   p = c->path;
1123   if (NULL != p)
1124   {
1125     path_add_to_peers (p, GNUNET_YES);
1126   }
1127   else
1128   {
1129     GNUNET_break (0);
1130   }
1131
1132   /* Message for us as creator? */
1133   if (GMC_is_origin (c, GNUNET_YES))
1134   {
1135     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Connection (SYN)ACK for us!\n");
1136     connection_change_state (c, MESH_CONNECTION_READY);
1137     GMT_change_state (c->t, MESH_TUNNEL3_READY);
1138     send_connection_ack (c, GNUNET_YES);
1139     GMT_send_queued_data (c->t, GNUNET_YES);
1140     return GNUNET_OK;
1141   }
1142
1143   /* Message for us as destination? */
1144   if (GMC_is_terminal (c, GNUNET_YES))
1145   {
1146     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Connection ACK for us!\n");
1147     GMC_change_state (c, MESH_CONNECTION_READY);
1148     GMT_change_state (c->t, MESH_TUNNEL3_READY);
1149     GMT_send_queued_data (c->t, GNUNET_NO);
1150     return GNUNET_OK;
1151   }
1152
1153   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
1154   GMC_send_prebuilt_message (message, c, NULL, fwd);
1155   return GNUNET_OK;
1156 }
1157
1158
1159 /**
1160  * Core handler for notifications of broken paths
1161  *
1162  * @param cls Closure (unused).
1163  * @param peer Peer identity of sending neighbor.
1164  * @param message Message.
1165  *
1166  * @return GNUNET_OK to keep the connection open,
1167  *         GNUNET_SYSERR to close it (signal serious error)
1168  */
1169 int
1170 GMC_handle_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
1171                    const struct GNUNET_MessageHeader *message)
1172 {
1173   struct GNUNET_MESH_ConnectionBroken *msg;
1174   struct MeshConnection *c;
1175
1176   LOG (GNUNET_ERROR_TYPE_DEBUG,
1177               "Received a CONNECTION BROKEN msg from %s\n", GNUNET_i2s (peer));
1178   msg = (struct GNUNET_MESH_ConnectionBroken *) message;
1179   LOG (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
1180               GNUNET_i2s (&msg->peer1));
1181   LOG (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
1182               GNUNET_i2s (&msg->peer2));
1183   c = connection_get (&msg->cid);
1184   if (NULL == c)
1185   {
1186     GNUNET_break_op (0);
1187     return GNUNET_OK;
1188   }
1189   tunnel_notify_connection_broken (c->t, GNUNET_PEER_search (&msg->peer1),
1190                                    GNUNET_PEER_search (&msg->peer2));
1191   return GNUNET_OK;
1192
1193 }
1194
1195
1196 /**
1197  * Core handler for tunnel destruction
1198  *
1199  * @param cls Closure (unused).
1200  * @param peer Peer identity of sending neighbor.
1201  * @param message Message.
1202  *
1203  * @return GNUNET_OK to keep the connection open,
1204  *         GNUNET_SYSERR to close it (signal serious error)
1205  */
1206 int
1207 GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
1208                     const struct GNUNET_MessageHeader *message)
1209 {
1210   struct GNUNET_MESH_ConnectionDestroy *msg;
1211   struct MeshConnection *c;
1212   GNUNET_PEER_Id id;
1213   int fwd;
1214
1215   msg = (struct GNUNET_MESH_ConnectionDestroy *) message;
1216   LOG (GNUNET_ERROR_TYPE_DEBUG,
1217               "Got a CONNECTION DESTROY message from %s\n",
1218               GNUNET_i2s (peer));
1219   LOG (GNUNET_ERROR_TYPE_DEBUG,
1220               "  for connection %s\n",
1221               GNUNET_h2s (&msg->cid));
1222   c = connection_get (&msg->cid);
1223   if (NULL == c)
1224   {
1225     /* Probably already got the message from another path,
1226      * destroyed the tunnel and retransmitted to children.
1227      * Safe to ignore.
1228      */
1229     GNUNET_STATISTICS_update (stats, "# control on unknown tunnel",
1230                               1, GNUNET_NO);
1231     return GNUNET_OK;
1232   }
1233   id = GNUNET_PEER_search (peer);
1234   if (id == GMP_get_short_id (connection_get_prev_hop (c)))
1235     fwd = GNUNET_YES;
1236   else if (id == GMP_get_short_id (connection_get_next_hop (c)))
1237     fwd = GNUNET_NO;
1238   else
1239   {
1240     GNUNET_break_op (0);
1241     return GNUNET_OK;
1242   }
1243   GMC_send_prebuilt_message (message, c, NULL, fwd);
1244   c->destroy = GNUNET_YES;
1245
1246   return GNUNET_OK;
1247 }
1248
1249 /**
1250  * Generic handler for mesh network encrypted traffic.
1251  *
1252  * @param peer Peer identity this notification is about.
1253  * @param message Encrypted message.
1254  * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1255  *
1256  * @return GNUNET_OK to keep the connection open,
1257  *         GNUNET_SYSERR to close it (signal serious error)
1258  */
1259 static int
1260 handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer,
1261                        const struct GNUNET_MESH_Encrypted *msg,
1262                        int fwd)
1263 {
1264   struct MeshConnection *c;
1265   struct MeshTunnel3 *t;
1266   struct MeshPeer *neighbor;
1267   struct MeshFlowControl *fc;
1268   uint32_t pid;
1269   uint32_t ttl;
1270   uint16_t type;
1271   size_t size;
1272
1273   /* Check size */
1274   size = ntohs (msg->header.size);
1275   if (size <
1276       sizeof (struct GNUNET_MESH_Encrypted) +
1277       sizeof (struct GNUNET_MessageHeader))
1278   {
1279     GNUNET_break_op (0);
1280     return GNUNET_OK;
1281   }
1282   type = ntohs (msg->header.type);
1283   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1284   LOG (GNUNET_ERROR_TYPE_DEBUG, "got a %s message from %s\n",
1285               GNUNET_MESH_DEBUG_M2S (type), GNUNET_i2s (peer));
1286
1287   /* Check connection */
1288   c = connection_get (&msg->cid);
1289   if (NULL == c)
1290   {
1291     GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
1292     LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING connection unknown\n");
1293     return GNUNET_OK;
1294   }
1295   t = c->t;
1296   fc = fwd ? &c->bck_fc : &c->fwd_fc;
1297
1298   /* Check if origin is as expected */
1299   neighbor = connection_get_hop (c, !fwd);
1300   if (GNUNET_PEER_search (peer) != GMP_get_short_id (neighbor))
1301   {
1302     GNUNET_break_op (0);
1303     return GNUNET_OK;
1304   }
1305
1306   /* Check PID */
1307   pid = ntohl (msg->pid);
1308   if (GMC_is_pid_bigger (pid, fc->last_ack_sent))
1309   {
1310     GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
1311     LOG (GNUNET_ERROR_TYPE_DEBUG,
1312                 "WARNING Received PID %u, (prev %u), ACK %u\n",
1313                 pid, fc->last_pid_recv, fc->last_ack_sent);
1314     return GNUNET_OK;
1315   }
1316   if (GNUNET_NO == GMC_is_pid_bigger (pid, fc->last_pid_recv))
1317   {
1318     GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO);
1319     LOG (GNUNET_ERROR_TYPE_DEBUG,
1320                 " Pid %u not expected (%u+), dropping!\n",
1321                 pid, fc->last_pid_recv + 1);
1322     return GNUNET_OK;
1323   }
1324   if (MESH_CONNECTION_SENT == c->state)
1325     connection_change_state (c, MESH_CONNECTION_READY);
1326   connection_reset_timeout (c, fwd);
1327   fc->last_pid_recv = pid;
1328
1329   /* Is this message for us? */
1330   if (GMC_is_terminal (c, fwd))
1331   {
1332     size_t dsize = size - sizeof (struct GNUNET_MESH_Encrypted);
1333     char cbuf[dsize];
1334     struct GNUNET_MessageHeader *msgh;
1335     unsigned int off;
1336
1337     /* TODO signature verification */
1338     LOG (GNUNET_ERROR_TYPE_DEBUG, "  message for us!\n");
1339     GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
1340
1341     fc->last_pid_recv = pid;
1342     tunnel_decrypt (t, cbuf, &msg[1], dsize, msg->iv, fwd);
1343     off = 0;
1344     while (off < dsize)
1345     {
1346       msgh = (struct GNUNET_MessageHeader *) &cbuf[off];
1347       handle_decrypted (t, msgh, fwd);
1348       off += ntohs (msgh->size);
1349     }
1350     send_ack (c, NULL, fwd);
1351     return GNUNET_OK;
1352   }
1353
1354   /* Message not for us: forward to next hop */
1355   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
1356   ttl = ntohl (msg->ttl);
1357   LOG (GNUNET_ERROR_TYPE_DEBUG, "   ttl: %u\n", ttl);
1358   if (ttl == 0)
1359   {
1360     GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
1361     LOG (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
1362     send_ack (c, NULL, fwd);
1363     return GNUNET_OK;
1364   }
1365   GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
1366
1367   send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
1368
1369   return GNUNET_OK;
1370 }
1371
1372
1373 /**
1374  * Core handler for mesh network traffic going orig->dest.
1375  *
1376  * @param cls Closure (unused).
1377  * @param message Message received.
1378  * @param peer Peer who sent the message.
1379  *
1380  * @return GNUNET_OK to keep the connection open,
1381  *         GNUNET_SYSERR to close it (signal serious error)
1382  */
1383 int
1384 GMC_handle_fwd (void *cls, const struct GNUNET_PeerIdentity *peer,
1385                 const struct GNUNET_MessageHeader *message)
1386 {
1387   return handle_mesh_encrypted (peer,
1388                                 (struct GNUNET_MESH_Encrypted *)message,
1389                                 GNUNET_YES);
1390 }
1391
1392 /**
1393  * Core handler for mesh network traffic going dest->orig.
1394  *
1395  * @param cls Closure (unused).
1396  * @param message Message received.
1397  * @param peer Peer who sent the message.
1398  *
1399  * @return GNUNET_OK to keep the connection open,
1400  *         GNUNET_SYSERR to close it (signal serious error)
1401  */
1402 int
1403 GMC_handle_bck (void *cls, const struct GNUNET_PeerIdentity *peer,
1404                 const struct GNUNET_MessageHeader *message)
1405 {
1406   return handle_mesh_encrypted (peer,
1407                                 (struct GNUNET_MESH_Encrypted *)message,
1408                                 GNUNET_NO);
1409 }
1410
1411
1412 /**
1413  * Core handler for mesh network traffic point-to-point acks.
1414  *
1415  * @param cls closure
1416  * @param message message
1417  * @param peer peer identity this notification is about
1418  *
1419  * @return GNUNET_OK to keep the connection open,
1420  *         GNUNET_SYSERR to close it (signal serious error)
1421  */
1422 int
1423 GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
1424                 const struct GNUNET_MessageHeader *message)
1425 {
1426   struct GNUNET_MESH_ACK *msg;
1427   struct MeshConnection *c;
1428   struct MeshFlowControl *fc;
1429   GNUNET_PEER_Id id;
1430   uint32_t ack;
1431   int fwd;
1432
1433   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1434   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
1435               GNUNET_i2s (peer));
1436   msg = (struct GNUNET_MESH_ACK *) message;
1437
1438   c = connection_get (&msg->cid);
1439
1440   if (NULL == c)
1441   {
1442     GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1,
1443                               GNUNET_NO);
1444     return GNUNET_OK;
1445   }
1446
1447   /* Is this a forward or backward ACK? */
1448   id = GNUNET_PEER_search (peer);
1449   if (GMP_get_short_id (connection_get_next_hop (c)) == id)
1450   {
1451     LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
1452     fc = &c->fwd_fc;
1453     fwd = GNUNET_YES;
1454   }
1455   else if (GMP_get_short_id (connection_get_prev_hop (c)) == id)
1456   {
1457     LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK ACK\n");
1458     fc = &c->bck_fc;
1459     fwd = GNUNET_NO;
1460   }
1461   else
1462   {
1463     GNUNET_break_op (0);
1464     return GNUNET_OK;
1465   }
1466
1467   ack = ntohl (msg->ack);
1468   LOG (GNUNET_ERROR_TYPE_DEBUG, "  ACK %u (was %u)\n",
1469               ack, fc->last_ack_recv);
1470   if (GMC_is_pid_bigger (ack, fc->last_ack_recv))
1471     fc->last_ack_recv = ack;
1472
1473   /* Cancel polling if the ACK is big enough. */
1474   if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task &&
1475       GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
1476   {
1477     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Cancel poll\n");
1478     GNUNET_SCHEDULER_cancel (fc->poll_task);
1479     fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
1480     fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
1481   }
1482
1483   connection_unlock_queue (c, fwd);
1484
1485   return GNUNET_OK;
1486 }
1487
1488
1489 /**
1490  * Core handler for mesh network traffic point-to-point ack polls.
1491  *
1492  * @param cls closure
1493  * @param message message
1494  * @param peer peer identity this notification is about
1495  *
1496  * @return GNUNET_OK to keep the connection open,
1497  *         GNUNET_SYSERR to close it (signal serious error)
1498  */
1499 int
1500 GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
1501                  const struct GNUNET_MessageHeader *message)
1502 {
1503   struct GNUNET_MESH_Poll *msg;
1504   struct MeshConnection *c;
1505   struct MeshFlowControl *fc;
1506   GNUNET_PEER_Id id;
1507   uint32_t pid;
1508   int fwd;
1509
1510   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1511   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a POLL packet from %s!\n",
1512               GNUNET_i2s (peer));
1513
1514   msg = (struct GNUNET_MESH_Poll *) message;
1515
1516   c = connection_get (&msg->cid);
1517
1518   if (NULL == c)
1519   {
1520     GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
1521                               GNUNET_NO);
1522     GNUNET_break_op (0);
1523     return GNUNET_OK;
1524   }
1525
1526   /* Is this a forward or backward ACK?
1527    * Note: a poll should never be needed in a loopback case,
1528    * since there is no possiblility of packet loss there, so
1529    * this way of discerining FWD/BCK should not be a problem.
1530    */
1531   id = GNUNET_PEER_search (peer);
1532   if (GMP_get_short_id (connection_get_next_hop (c)) == id)
1533   {
1534     LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
1535     fc = &c->fwd_fc;
1536   }
1537   else if (GMP_get_short_id (connection_get_prev_hop (c)) == id)
1538   {
1539     LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK ACK\n");
1540     fc = &c->bck_fc;
1541   }
1542   else
1543   {
1544     GNUNET_break_op (0);
1545     return GNUNET_OK;
1546   }
1547
1548   pid = ntohl (msg->pid);
1549   LOG (GNUNET_ERROR_TYPE_DEBUG, "  PID %u, OLD %u\n",
1550               pid, fc->last_pid_recv);
1551   fc->last_pid_recv = pid;
1552   fwd = fc == &c->fwd_fc;
1553   send_ack (c, NULL, fwd);
1554
1555   return GNUNET_OK;
1556 }
1557
1558
1559 /**
1560  * Core handler for mesh keepalives.
1561  *
1562  * @param cls closure
1563  * @param message message
1564  * @param peer peer identity this notification is about
1565  * @return GNUNET_OK to keep the connection open,
1566  *         GNUNET_SYSERR to close it (signal serious error)
1567  *
1568  * TODO: Check who we got this from, to validate route.
1569  */
1570 int
1571 GMC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
1572                       const struct GNUNET_MessageHeader *message)
1573 {
1574   struct GNUNET_MESH_ConnectionKeepAlive *msg;
1575   struct MeshConnection *c;
1576   struct MeshPeer *neighbor;
1577   int fwd;
1578
1579   msg = (struct GNUNET_MESH_ConnectionKeepAlive *) message;
1580   LOG (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
1581               GNUNET_i2s (peer));
1582
1583   c = connection_get (&msg->cid);
1584   if (NULL == c)
1585   {
1586     GNUNET_STATISTICS_update (stats, "# keepalive on unknown connection", 1,
1587                               GNUNET_NO);
1588     return GNUNET_OK;
1589   }
1590
1591   fwd = GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE == ntohs (message->type) ?
1592         GNUNET_YES : GNUNET_NO;
1593
1594   /* Check if origin is as expected */
1595   neighbor = connection_get_hop (c, fwd);
1596   if (GNUNET_PEER_search (peer) != GMP_get_short_id (neighbor))
1597   {
1598     GNUNET_break_op (0);
1599     return GNUNET_OK;
1600   }
1601
1602   connection_change_state (c, MESH_CONNECTION_READY);
1603   connection_reset_timeout (c, fwd);
1604
1605   if (GMC_is_terminal (c, fwd))
1606     return GNUNET_OK;
1607
1608   GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
1609   GMC_send_prebuilt_message (message, c, NULL, fwd);
1610
1611   return GNUNET_OK;
1612 }
1613
1614
1615 /**
1616  * Send an ACK on the appropriate connection/channel, depending on
1617  * the direction and the position of the peer.
1618  *
1619  * @param c Which connection to send the hop-by-hop ACK.
1620  * @param ch Channel, if any.
1621  * @param fwd Is this a fwd ACK? (will go dest->root)
1622  */
1623 void
1624 GMC_send_ack (struct MeshConnection *c, struct MeshChannel *ch, int fwd)
1625 {
1626   unsigned int buffer;
1627
1628   LOG (GNUNET_ERROR_TYPE_DEBUG,
1629               "send ack %s on %p %p\n",
1630               fwd ? "FWD" : "BCK", c, ch);
1631   if (NULL == c || GMC_is_terminal (c, fwd))
1632   {
1633     struct MeshTunnel3 *t;
1634     LOG (GNUNET_ERROR_TYPE_DEBUG, "  getting from all connections\n");
1635     t = (NULL == c) ? GMCH_get_tunnel (ch) : GMC_get_tunnel (c);
1636     buffer = GMT_get_buffer (t, fwd);
1637   }
1638   else
1639   {
1640     LOG (GNUNET_ERROR_TYPE_DEBUG, "  getting from one connection\n");
1641     buffer = GMC_get_buffer (c, fwd);
1642   }
1643   LOG (GNUNET_ERROR_TYPE_DEBUG, "  buffer available: %u\n", buffer);
1644
1645   if ( (NULL != ch && GMCH_is_origin (ch, fwd)) ||
1646        (NULL != c && GMC_is_origin (c, fwd)) )
1647   {
1648     LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on channel...\n");
1649     if (0 < buffer)
1650     {
1651       GNUNET_assert (NULL != ch);
1652       LOG (GNUNET_ERROR_TYPE_DEBUG, "  really sending!\n");
1653       send_local_ack (ch, fwd);
1654     }
1655   }
1656   else if (NULL == c)
1657   {
1658     LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on all connections\n");
1659     GNUNET_assert (NULL != ch);
1660     channel_send_connections_ack (ch, buffer, fwd);
1661   }
1662   else
1663   {
1664     LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on connection\n");
1665     connection_send_ack (c, buffer, fwd);
1666   }
1667 }
1668
1669
1670 /**
1671  * Initialize the connections subsystem
1672  *
1673  * @param c Configuration handle.
1674  */
1675 void
1676 GMC_init (const struct GNUNET_CONFIGURATION_Handle *c)
1677 {
1678   if (GNUNET_OK !=
1679       GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE",
1680                                              &max_msgs_queue))
1681   {
1682     LOG_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1683                                "MESH", "MAX_MSGS_QUEUE", "MISSING");
1684     GNUNET_SCHEDULER_shutdown ();
1685     return;
1686   }
1687
1688   if (GNUNET_OK !=
1689       GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_CONNECTIONS",
1690                                              &max_connections))
1691   {
1692     LOG_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1693                                "MESH", "MAX_CONNECTIONS", "MISSING");
1694     GNUNET_SCHEDULER_shutdown ();
1695     return;
1696   }
1697
1698   if (GNUNET_OK !=
1699       GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_CONNECTION_TIME",
1700                                            &refresh_connection_time))
1701   {
1702     LOG_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1703                                "MESH", "REFRESH_CONNECTION_TIME", "MISSING");
1704     GNUNET_SCHEDULER_shutdown ();
1705     return;
1706   }
1707   connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES);
1708 }
1709
1710 /**
1711  * Shut down the connections subsystem.
1712  */
1713 void
1714 GMC_shutdown (void)
1715 {
1716 }
1717
1718
1719 struct MeshConnection *
1720 GMC_new (const struct GNUNET_HashCode *cid,
1721          struct MeshTunnel3 *t,
1722          struct MeshPeerPath *p,
1723          unsigned int own_pos)
1724 {
1725   struct MeshConnection *c;
1726
1727   c = GNUNET_new (struct MeshConnection);
1728   c->id = *cid;
1729   GNUNET_CONTAINER_multihashmap_put (connections, &c->id, c,
1730                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1731   fc_init (&c->fwd_fc);
1732   fc_init (&c->bck_fc);
1733   c->fwd_fc.c = c;
1734   c->bck_fc.c = c;
1735
1736   c->t = t;
1737   if (own_pos > p->length - 1)
1738   {
1739     GNUNET_break (0);
1740     GMC_destroy (c);
1741     return NULL;
1742   }
1743   c->own_pos = own_pos;
1744   c->path = p;
1745
1746   if (0 == own_pos)
1747   {
1748     c->fwd_maintenance_task =
1749             GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
1750                                           &connection_fwd_keepalive, c);
1751   }
1752   register_neighbors (c);
1753   return c;
1754 }
1755
1756
1757 void
1758 GMC_destroy (struct MeshConnection *c)
1759 {
1760   if (NULL == c)
1761     return;
1762
1763   LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s\n",
1764        GNUNET_h2s (&c->id));
1765
1766   /* Cancel all traffic */
1767   connection_cancel_queues (c, GNUNET_YES);
1768   connection_cancel_queues (c, GNUNET_NO);
1769
1770   /* Cancel maintainance task (keepalive/timeout) */
1771   if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task)
1772     GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
1773   if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task)
1774     GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
1775
1776   /* Unregister from neighbors */
1777   unregister_neighbors (c);
1778
1779   /* Delete */
1780   GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO);
1781   GMT_remove_connection (c->t, c);
1782   GNUNET_free (c);
1783 }
1784
1785 /**
1786  * Get the connection ID.
1787  *
1788  * @param c Connection to get the ID from.
1789  *
1790  * @return ID of the connection.
1791  */
1792 const struct GNUNET_HashCode *
1793 GMC_get_id (const struct MeshConnection *c)
1794 {
1795   return &c->id;
1796 }
1797
1798
1799 /**
1800  * Get the connection state.
1801  *
1802  * @param c Connection to get the state from.
1803  *
1804  * @return state of the connection.
1805  */
1806 enum MeshConnectionState
1807 GMC_get_state (const struct MeshConnection *c)
1808 {
1809   return c->state;
1810 }
1811
1812 /**
1813  * Get the connection tunnel.
1814  *
1815  * @param c Connection to get the tunnel from.
1816  *
1817  * @return tunnel of the connection.
1818  */
1819 struct MeshTunnel3 *
1820 GMC_get_tunnel (const struct MeshConnection *c)
1821 {
1822   return c->t;
1823 }
1824
1825
1826 /**
1827  * Get free buffer space in a connection.
1828  *
1829  * @param c Connection.
1830  * @param fwd Is query about FWD traffic?
1831  *
1832  * @return Free buffer space [0 - max_msgs_queue/max_connections]
1833  */
1834 unsigned int
1835 GMC_get_buffer (struct MeshConnection *c, int fwd)
1836 {
1837   struct MeshFlowControl *fc;
1838
1839   fc = fwd ? &c->fwd_fc : &c->bck_fc;
1840
1841   return (fc->queue_max - fc->queue_n);
1842 }
1843
1844 /**
1845  * Get messages queued in a connection.
1846  *
1847  * @param c Connection.
1848  * @param fwd Is query about FWD traffic?
1849  *
1850  * @return Number of messages queued.
1851  */
1852 unsigned int
1853 GMC_get_qn (struct MeshConnection *c, int fwd)
1854 {
1855   struct MeshFlowControl *fc;
1856
1857   fc = fwd ? &c->fwd_fc : &c->bck_fc;
1858
1859   return fc->queue_n;
1860 }
1861
1862
1863 /**
1864  * Notify other peers on a connection of a broken link. Mark connections
1865  * to destroy after all traffic has been sent.
1866  *
1867  * @param c Connection on which there has been a disconnection.
1868  * @param peer Peer that disconnected.
1869  * @param my_full_id My ID (to send to other peers).
1870  */
1871 void
1872 GMC_notify_broken (struct MeshConnection *c,
1873                    struct MeshPeer *peer,
1874                    struct GNUNET_PeerIdentity *my_full_id)
1875 {
1876   struct GNUNET_MESH_ConnectionBroken msg;
1877   int fwd;
1878
1879   fwd = peer == connection_get_prev_hop (c);
1880
1881   connection_cancel_queues (c, !fwd);
1882   if (GMC_is_terminal (c, fwd))
1883   {
1884     /* Local shutdown, no one to notify about this. */
1885     GMC_destroy (c);
1886     return;
1887   }
1888
1889   msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectionBroken));
1890   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN);
1891   msg.cid = c->id;
1892   msg.peer1 = *my_full_id;
1893   msg.peer2 = *GMP_get_id (peer);
1894   GMC_send_prebuilt_message (&msg.header, c, NULL, fwd);
1895   c->destroy = GNUNET_YES;
1896
1897   return;
1898 }
1899
1900
1901 /**
1902  * Is this peer the first one on the connection?
1903  *
1904  * @param c Connection.
1905  * @param fwd Is this about fwd traffic?
1906  *
1907  * @return GNUNET_YES if origin, GNUNET_NO if relay/terminal.
1908  */
1909 int
1910 GMC_is_origin (struct MeshConnection *c, int fwd)
1911 {
1912   if (!fwd && c->path->length - 1 == c->own_pos )
1913     return GNUNET_YES;
1914   if (fwd && 0 == c->own_pos)
1915     return GNUNET_YES;
1916   return GNUNET_NO;
1917 }
1918
1919
1920 /**
1921  * Is this peer the last one on the connection?
1922  *
1923  * @param c Connection.
1924  * @param fwd Is this about fwd traffic?
1925  *            Note that the ROOT is the terminal for BCK traffic!
1926  *
1927  * @return GNUNET_YES if terminal, GNUNET_NO if relay/origin.
1928  */
1929 int
1930 GMC_is_terminal (struct MeshConnection *c, int fwd)
1931 {
1932   return GMC_is_origin (c, !fwd);
1933 }
1934
1935
1936 /**
1937  * See if we are allowed to send by the next hop in the given direction.
1938  *
1939  * @param c Connection.
1940  * @param fwd Is this about fwd traffic?
1941  *
1942  * @return GNUNET_YES in case it's OK.
1943  */
1944 int
1945 GMC_is_sendable (struct MeshConnection *c, int fwd)
1946 {
1947   struct MeshFlowControl *fc;
1948
1949   fc = fwd ? &c->fwd_fc : &c->bck_fc;
1950   if (GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
1951     return GNUNET_YES;
1952   return GNUNET_NO;
1953 }
1954
1955 /**
1956  * Sends an already built message on a connection, properly registering
1957  * all used resources.
1958  *
1959  * @param message Message to send. Function makes a copy of it.
1960  *                If message is not hop-by-hop, decrements TTL of copy.
1961  * @param c Connection on which this message is transmitted.
1962  * @param ch Channel on which this message is transmitted, or NULL.
1963  * @param fwd Is this a fwd message?
1964  */
1965 void
1966 GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
1967                            struct MeshConnection *c,
1968                            struct MeshChannel *ch,
1969                            int fwd)
1970 {
1971   void *data;
1972   size_t size;
1973   uint16_t type;
1974
1975   size = ntohs (message->size);
1976   data = GNUNET_malloc (size);
1977   memcpy (data, message, size);
1978   type = ntohs (message->type);
1979   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send %s (%u) on connection %s\n",
1980               GNUNET_MESH_DEBUG_M2S (type), size, GNUNET_h2s (&c->id));
1981
1982   switch (type)
1983   {
1984     struct GNUNET_MESH_Encrypted *emsg;
1985     struct GNUNET_MESH_ACK       *amsg;
1986     struct GNUNET_MESH_Poll      *pmsg;
1987     struct GNUNET_MESH_ConnectionDestroy *dmsg;
1988     struct GNUNET_MESH_ConnectionBroken  *bmsg;
1989     uint32_t ttl;
1990
1991     case GNUNET_MESSAGE_TYPE_MESH_FWD:
1992     case GNUNET_MESSAGE_TYPE_MESH_BCK:
1993       emsg = (struct GNUNET_MESH_Encrypted *) data;
1994       ttl = ntohl (emsg->ttl);
1995       if (0 == ttl)
1996       {
1997         GNUNET_break_op (0);
1998         return;
1999       }
2000       emsg->cid = c->id;
2001       emsg->ttl = htonl (ttl - 1);
2002       emsg->pid = htonl (fwd ? c->fwd_fc.next_pid++ : c->bck_fc.next_pid++);
2003       LOG (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", ntohl (emsg->pid));
2004       break;
2005
2006     case GNUNET_MESSAGE_TYPE_MESH_ACK:
2007       amsg = (struct GNUNET_MESH_ACK *) data;
2008       amsg->cid = c->id;
2009       LOG (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ntohl (amsg->ack));
2010       break;
2011
2012     case GNUNET_MESSAGE_TYPE_MESH_POLL:
2013       pmsg = (struct GNUNET_MESH_Poll *) data;
2014       pmsg->cid = c->id;
2015       pmsg->pid = htonl (fwd ? c->fwd_fc.last_pid_sent : c->bck_fc.last_pid_sent);
2016       LOG (GNUNET_ERROR_TYPE_DEBUG, " poll %u\n", ntohl (pmsg->pid));
2017       break;
2018
2019     case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
2020       dmsg = (struct GNUNET_MESH_ConnectionDestroy *) data;
2021       dmsg->cid = c->id;
2022       dmsg->reserved = 0;
2023       break;
2024
2025     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
2026       bmsg = (struct GNUNET_MESH_ConnectionBroken *) data;
2027       bmsg->cid = c->id;
2028       bmsg->reserved = 0;
2029       break;
2030
2031     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
2032     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
2033       break;
2034
2035     default:
2036       GNUNET_break (0);
2037   }
2038
2039   GMP_queue_add (data, type, size, c, ch, fwd, &message_sent, (void *) size);
2040 }
2041
2042
2043 /**
2044  * Send a message to all peers in this connection that the connection
2045  * is no longer valid.
2046  *
2047  * If some peer should not receive the message, it should be zero'ed out
2048  * before calling this function.
2049  *
2050  * @param c The connection whose peers to notify.
2051  */
2052 void
2053 GMC_send_destroy (struct MeshConnection *c)
2054 {
2055   struct GNUNET_MESH_ConnectionDestroy msg;
2056
2057   if (GNUNET_YES == c->destroy)
2058     return;
2059
2060   msg.header.size = htons (sizeof (msg));
2061   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY);;
2062   msg.cid = c->id;
2063   LOG (GNUNET_ERROR_TYPE_DEBUG,
2064               "  sending connection destroy for connection %s\n",
2065               GNUNET_h2s (&c->id));
2066
2067   if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES))
2068     GMC_send_prebuilt_message (&msg.header, c, NULL, GNUNET_YES);
2069   if (GNUNET_NO == GMC_is_terminal (c, GNUNET_NO))
2070     GMC_send_prebuilt_message (&msg.header, c, NULL, GNUNET_NO);
2071   c->destroy = GNUNET_YES;
2072 }