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