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