- typos, indent
[oweals/gnunet.git] / src / mesh / gnunet-service-mesh_connection.c
1 /*
2      This file is part of GNUnet.
3      (C) 2001-2013 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file mesh/gnunet-service-mesh_connection.c
23  * @brief GNUnet MESH service connection handling
24  * @author Bartlomiej Polot
25  */
26
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29
30 #include "gnunet_statistics_service.h"
31
32 #include "mesh_path.h"
33 #include "mesh_protocol.h"
34 #include "mesh.h"
35 #include "gnunet-service-mesh_connection.h"
36 #include "gnunet-service-mesh_peer.h"
37 #include "gnunet-service-mesh_tunnel.h"
38
39
40 #define LOG(level, ...) GNUNET_log_from (level,"mesh-con",__VA_ARGS__)
41
42 #define MESH_MAX_POLL_TIME      GNUNET_TIME_relative_multiply (\
43                                   GNUNET_TIME_UNIT_MINUTES,\
44                                   10)
45 #define AVG_MSGS                32
46
47
48 /******************************************************************************/
49 /********************************   STRUCTS  **********************************/
50 /******************************************************************************/
51
52 /**
53  * Struct to encapsulate all the Flow Control information to a peer to which
54  * we are directly connected (on a core level).
55  */
56 struct MeshFlowControl
57 {
58   /**
59    * Connection this controls.
60    */
61   struct MeshConnection *c;
62
63   /**
64    * How many messages are in the queue on this connection.
65    */
66   unsigned int queue_n;
67
68   /**
69    * How many messages do we accept in the queue.
70    */
71   unsigned int queue_max;
72
73   /**
74    * Next ID to use.
75    */
76   uint32_t next_pid;
77
78   /**
79    * ID of the last packet sent towards the peer.
80    */
81   uint32_t last_pid_sent;
82
83   /**
84    * ID of the last packet received from the peer.
85    */
86   uint32_t last_pid_recv;
87
88   /**
89    * Last ACK sent to the peer (peer can't send more than this PID).
90    */
91   uint32_t last_ack_sent;
92
93   /**
94    * Last ACK sent towards the origin (for traffic towards leaf node).
95    */
96   uint32_t last_ack_recv;
97
98   /**
99    * Task to poll the peer in case of a lost ACK causes stall.
100    */
101   GNUNET_SCHEDULER_TaskIdentifier poll_task;
102
103   /**
104    * How frequently to poll for ACKs.
105    */
106   struct GNUNET_TIME_Relative poll_time;
107
108   /**
109    * Queued poll message, to cancel if not necessary anymore (got ACK).
110    */
111   struct MeshConnectionQueue *poll_msg;
112
113   /**
114    * Queued poll message, to cancel if not necessary anymore (got ACK).
115    */
116   struct MeshConnectionQueue *ack_msg;
117 };
118
119 /**
120  * Keep a record of the last messages sent on this connection.
121  */
122 struct MeshConnectionPerformance
123 {
124   /**
125    * Circular buffer for storing measurements.
126    */
127   double usecsperbyte[AVG_MSGS];
128
129   /**
130    * Running average of @c usecsperbyte.
131    */
132   double avg;
133
134   /**
135    * How many values of @c usecsperbyte are valid.
136    */
137   uint16_t size;
138
139   /**
140    * Index of the next "free" position in @c usecsperbyte.
141    */
142   uint16_t idx;
143 };
144
145
146 /**
147  * Struct containing all information regarding a connection to a peer.
148  */
149 struct MeshConnection
150 {
151   /**
152    * Tunnel this connection is part of.
153    */
154   struct MeshTunnel3 *t;
155
156   /**
157    * Flow control information for traffic fwd.
158    */
159   struct MeshFlowControl fwd_fc;
160
161   /**
162    * Flow control information for traffic bck.
163    */
164   struct MeshFlowControl bck_fc;
165
166   /**
167    * Measure connection performance on the endpoint.
168    */
169   struct MeshConnectionPerformance *perf;
170
171   /**
172    * ID of the connection.
173    */
174   struct GNUNET_HashCode id;
175
176   /**
177    * State of the connection.
178    */
179   enum MeshConnectionState state;
180
181   /**
182    * Path being used for the tunnel.
183    */
184   struct MeshPeerPath *path;
185
186   /**
187    * Position of the local peer in the path.
188    */
189   unsigned int own_pos;
190
191   /**
192    * Task to keep the used paths alive at the owner,
193    * time tunnel out on all the other peers.
194    */
195   GNUNET_SCHEDULER_TaskIdentifier fwd_maintenance_task;
196
197   /**
198    * Task to keep the used paths alive at the destination,
199    * time tunnel out on all the other peers.
200    */
201   GNUNET_SCHEDULER_TaskIdentifier bck_maintenance_task;
202
203   /**
204    * Pending message count.
205    */
206   int pending_messages;
207
208   /**
209    * Destroy flag: if true, destroy on last message.
210    */
211   int destroy;
212 };
213
214 /**
215  * Handle for messages queued but not yet sent.
216  */
217 struct MeshConnectionQueue
218 {
219   /**
220    * Peer queue handle, to cancel if necessary.
221    */
222   struct MeshPeerQueue *q;
223
224   /**
225    * Continuation to call once sent.
226    */
227   GMC_sent cont;
228
229   /**
230    * Closure for @c cont.
231    */
232   void *cont_cls;
233 };
234
235 /******************************************************************************/
236 /*******************************   GLOBALS  ***********************************/
237 /******************************************************************************/
238
239 /**
240  * Global handle to the statistics service.
241  */
242 extern struct GNUNET_STATISTICS_Handle *stats;
243
244 /**
245  * Local peer own ID (memory efficient handle).
246  */
247 extern GNUNET_PEER_Id myid;
248
249 /**
250  * Local peer own ID (full value).
251  */
252 extern struct GNUNET_PeerIdentity my_full_id;
253
254 /**
255  * Connections known, indexed by cid (MeshConnection).
256  */
257 static struct GNUNET_CONTAINER_MultiHashMap *connections;
258
259 /**
260  * How many connections are we willing to maintain.
261  * Local connections are always allowed, even if there are more connections than max.
262  */
263 static unsigned long long max_connections;
264
265 /**
266  * How many messages *in total* are we willing to queue, divide by number of
267  * connections to get connection queue size.
268  */
269 static unsigned long long max_msgs_queue;
270
271 /**
272  * How often to send path keepalives. Paths timeout after 4 missed.
273  */
274 static struct GNUNET_TIME_Relative refresh_connection_time;
275
276 /**
277  * How often to send path create / ACKs.
278  */
279 static struct GNUNET_TIME_Relative create_connection_time;
280
281
282 /******************************************************************************/
283 /********************************   STATIC  ***********************************/
284 /******************************************************************************/
285
286 #if 0 // avoid compiler warning for unused static function
287 static void
288 fc_debug (struct MeshFlowControl *fc)
289 {
290   LOG (GNUNET_ERROR_TYPE_DEBUG, "    IN: %u/%u\n",
291               fc->last_pid_recv, fc->last_ack_sent);
292   LOG (GNUNET_ERROR_TYPE_DEBUG, "    OUT: %u/%u\n",
293               fc->last_pid_sent, fc->last_ack_recv);
294   LOG (GNUNET_ERROR_TYPE_DEBUG, "    QUEUE: %u/%u\n",
295               fc->queue_n, fc->queue_max);
296 }
297
298 static void
299 connection_debug (struct MeshConnection *c)
300 {
301   if (NULL == c)
302   {
303     LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n");
304     return;
305   }
306   LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
307               peer2s (c->t->peer), GMC_2s (c));
308   LOG (GNUNET_ERROR_TYPE_DEBUG, "  state: %u, pending msgs: %u\n",
309               c->state, c->pending_messages);
310   LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD FC\n");
311   fc_debug (&c->fwd_fc);
312   LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK FC\n");
313   fc_debug (&c->bck_fc);
314 }
315 #endif
316
317 /**
318  * Get string description for tunnel state.
319  *
320  * @param s Tunnel state.
321  *
322  * @return String representation.
323  */
324 static const char *
325 GMC_state2s (enum MeshConnectionState s)
326 {
327   switch (s)
328   {
329     case MESH_CONNECTION_NEW:
330       return "MESH_CONNECTION_NEW";
331     case MESH_CONNECTION_SENT:
332       return "MESH_CONNECTION_SENT";
333     case MESH_CONNECTION_ACK:
334       return "MESH_CONNECTION_ACK";
335     case MESH_CONNECTION_READY:
336       return "MESH_CONNECTION_READY";
337     case MESH_CONNECTION_DESTROYED:
338       return "MESH_CONNECTION_DESTROYED";
339     default:
340       return "MESH_CONNECTION_STATE_ERROR";
341   }
342 }
343
344
345 /**
346  * Initialize a Flow Control structure to the initial state.
347  *
348  * @param fc Flow Control structure to initialize.
349  */
350 static void
351 fc_init (struct MeshFlowControl *fc)
352 {
353   fc->next_pid = 0;
354   fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */
355   fc->last_pid_recv = (uint32_t) -1;
356   fc->last_ack_sent = (uint32_t) 0;
357   fc->last_ack_recv = (uint32_t) 0;
358   fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
359   fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
360   fc->queue_n = 0;
361   fc->queue_max = (max_msgs_queue / max_connections) + 1;
362 }
363
364
365 /**
366  * Find a connection.
367  *
368  * @param cid Connection ID.
369  */
370 static struct MeshConnection *
371 connection_get (const struct GNUNET_HashCode *cid)
372 {
373   return GNUNET_CONTAINER_multihashmap_get (connections, cid);
374 }
375
376
377 static void
378 connection_change_state (struct MeshConnection* c,
379                          enum MeshConnectionState state)
380 {
381   LOG (GNUNET_ERROR_TYPE_DEBUG,
382               "Connection %s state was %s\n",
383               GMC_2s (c), GMC_state2s (c->state));
384   if (MESH_CONNECTION_DESTROYED == c->state)
385   {
386     LOG (GNUNET_ERROR_TYPE_DEBUG, "state not changing anymore\n");
387     return;
388   }
389   LOG (GNUNET_ERROR_TYPE_DEBUG,
390               "Connection %s state is now %s\n",
391               GMC_2s (c), GMC_state2s (state));
392   c->state = state;
393 }
394
395
396 /**
397  * Callback called when a queued ACK message is sent.
398  *
399  * @param cls Closure (FC).
400  * @param c Connection this message was on.
401  * @param q Queue handler this call invalidates.
402  * @param type Type of message sent.
403  * @param fwd Was this a FWD going message?
404  * @param size Size of the message.
405  */
406 static void
407 ack_sent (void *cls,
408           struct MeshConnection *c,
409           struct MeshConnectionQueue *q,
410           uint16_t type, int fwd, size_t size)
411 {
412   struct MeshFlowControl *fc = cls;
413
414   fc->ack_msg = NULL;
415 }
416
417
418 /**
419  * Send an ACK on the connection, informing the predecessor about
420  * the available buffer space. Should not be called in case the peer
421  * is origin (no predecessor) in the @c fwd direction.
422  *
423  * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
424  * the ACK itself goes "back" (dest->root).
425  *
426  * @param c Connection on which to send the ACK.
427  * @param buffer How much space free to advertise?
428  * @param fwd Is this FWD ACK? (Going dest -> root)
429  * @param force Don't optimize out.
430  */
431 static void
432 send_ack (struct MeshConnection *c, unsigned int buffer, int fwd, int force)
433 {
434   struct MeshFlowControl *next_fc;
435   struct MeshFlowControl *prev_fc;
436   struct GNUNET_MESH_ACK msg;
437   uint32_t ack;
438   int delta;
439
440   /* If origin, there is no connection to send ACKs. Wrong function! */
441   if (GMC_is_origin (c, fwd))
442   {
443     GNUNET_break (0);
444     return;
445   }
446
447   next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
448   prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
449
450   LOG (GNUNET_ERROR_TYPE_DEBUG,
451               "connection send %s ack on %s\n",
452               GM_f2s (fwd), GMC_2s (c));
453
454   /* Check if we need to transmit the ACK. */
455   delta = prev_fc->last_ack_sent - prev_fc->last_pid_recv;
456   if (3 < delta && buffer < delta && GNUNET_NO == force)
457   {
458     LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n");
459     LOG (GNUNET_ERROR_TYPE_DEBUG,
460          "  last pid recv: %u, last ack sent: %u\n",
461          prev_fc->last_pid_recv, prev_fc->last_ack_sent);
462     return;
463   }
464
465   /* Ok, ACK might be necessary, what PID to ACK? */
466   ack = prev_fc->last_pid_recv + buffer;
467   LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
468   LOG (GNUNET_ERROR_TYPE_DEBUG,
469        " last pid %u, last ack %u, qmax %u, q %u\n",
470        prev_fc->last_pid_recv, prev_fc->last_ack_sent,
471        next_fc->queue_max, next_fc->queue_n);
472   if (ack == prev_fc->last_ack_sent && GNUNET_NO == force)
473   {
474     LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
475     return;
476   }
477
478   /* Check if message is already in queue */
479   if (NULL != prev_fc->ack_msg)
480   {
481     if (GM_is_pid_bigger (ack, prev_fc->last_ack_sent))
482     {
483       LOG (GNUNET_ERROR_TYPE_DEBUG, " canceling old ACK\n");
484       GMC_cancel (prev_fc->ack_msg);
485       /* GMC_cancel triggers ack_sent(), which clears fc->ack_msg */
486     }
487     else
488     {
489       LOG (GNUNET_ERROR_TYPE_DEBUG, " same ACK already in queue\n");
490       return;
491     }
492   }
493
494   prev_fc->last_ack_sent = ack;
495
496   /* Build ACK message and send on connection */
497   msg.header.size = htons (sizeof (msg));
498   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
499   msg.ack = htonl (ack);
500   msg.cid = c->id;
501
502   prev_fc->ack_msg = GMC_send_prebuilt_message (&msg.header, c, !fwd,
503                                                 &ack_sent, prev_fc);
504 }
505
506
507 /**
508  * Callback called when a queued message is sent.
509  *
510  * Calculates the average time and connection packet tracking.
511  *
512  * @param cls Closure (ConnectionQueue Handle).
513  * @param c Connection this message was on.
514  * @param type Type of message sent.
515  * @param fwd Was this a FWD going message?
516  * @param size Size of the message.
517  * @param wait Time spent waiting for core (only the time for THIS message)
518  */
519 static void
520 message_sent (void *cls,
521               struct MeshConnection *c, uint16_t type,
522               int fwd, size_t size,
523               struct GNUNET_TIME_Relative wait)
524 {
525   struct MeshConnectionPerformance *p;
526   struct MeshFlowControl *fc;
527   struct MeshConnectionQueue *q = cls;
528   double usecsperbyte;
529
530   fc = fwd ? &c->fwd_fc : &c->bck_fc;
531   LOG (GNUNET_ERROR_TYPE_DEBUG,
532        "!  sent %s %s\n",
533        GM_f2s (fwd),
534        GM_m2s (type));
535   LOG (GNUNET_ERROR_TYPE_DEBUG, "!  C_P- %p %u\n", c, c->pending_messages);
536   if (NULL != q)
537   {
538     if (NULL != q->cont)
539     {
540       LOG (GNUNET_ERROR_TYPE_DEBUG, "!  calling cont\n");
541       q->cont (q->cont_cls, c, q, type, fwd, size);
542     }
543     GNUNET_free (q);
544   }
545   c->pending_messages--;
546   if (GNUNET_YES == c->destroy && 0 == c->pending_messages)
547   {
548     LOG (GNUNET_ERROR_TYPE_DEBUG, "!  destroying connection!\n");
549     GMC_destroy (c);
550     return;
551   }
552   /* Send ACK if needed, after accounting for sent ID in fc->queue_n */
553   switch (type)
554   {
555     case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED:
556       fc->last_pid_sent++;
557       LOG (GNUNET_ERROR_TYPE_DEBUG, "!  Q_N- %p %u\n", fc, fc->queue_n);
558       fc->queue_n--;
559       LOG (GNUNET_ERROR_TYPE_DEBUG,
560            "!   accounting pid %u\n",
561            fc->last_pid_sent);
562       GMC_send_ack (c, fwd, GNUNET_NO);
563       break;
564
565     case GNUNET_MESSAGE_TYPE_MESH_POLL:
566       fc->poll_msg = NULL;
567       break;
568
569     case GNUNET_MESSAGE_TYPE_MESH_ACK:
570       fc->ack_msg = NULL;
571       break;
572
573     default:
574       break;
575   }
576   LOG (GNUNET_ERROR_TYPE_DEBUG, "!  message sent!\n");
577
578   if (NULL == c->perf)
579     return; /* Only endpoints are interested in timing. */
580
581   p = c->perf;
582   usecsperbyte = ((double) wait.rel_value_us) / size;
583   if (p->size == AVG_MSGS)
584   {
585     /* Array is full. Substract oldest value, add new one and store. */
586     p->avg -= (p->usecsperbyte[p->idx] / AVG_MSGS);
587     p->usecsperbyte[p->idx] = usecsperbyte;
588     p->avg += (p->usecsperbyte[p->idx] / AVG_MSGS);
589   }
590   else
591   {
592     /* Array not yet full. Add current value to avg and store. */
593     p->usecsperbyte[p->idx] = usecsperbyte;
594     p->avg *= p->size;
595     p->avg += p->usecsperbyte[p->idx];
596     p->size++;
597     p->avg /= p->size;
598   }
599   p->idx = (p->idx + 1) % AVG_MSGS;
600 }
601
602
603 /**
604  * Get the previous hop in a connection
605  *
606  * @param c Connection.
607  *
608  * @return Previous peer in the connection.
609  */
610 static struct MeshPeer *
611 get_prev_hop (const struct MeshConnection *c)
612 {
613   GNUNET_PEER_Id id;
614
615   LOG (GNUNET_ERROR_TYPE_DEBUG, "Get prev hop, own pos %u\n", c->own_pos);
616   if (0 == c->own_pos || c->path->length < 2)
617     id = c->path->peers[0];
618   else
619     id = c->path->peers[c->own_pos - 1];
620
621   return GMP_get_short (id);
622 }
623
624
625 /**
626  * Get the next hop in a connection
627  *
628  * @param c Connection.
629  *
630  * @return Next peer in the connection.
631  */
632 static struct MeshPeer *
633 get_next_hop (const struct MeshConnection *c)
634 {
635   GNUNET_PEER_Id id;
636
637   if ((c->path->length - 1) == c->own_pos || c->path->length < 2)
638     id = c->path->peers[c->path->length - 1];
639   else
640     id = c->path->peers[c->own_pos + 1];
641
642   return GMP_get_short (id);
643 }
644
645
646 /**
647  * Get the hop in a connection.
648  *
649  * @param c Connection.
650  * @param fwd Next hop?
651  *
652  * @return Next peer in the connection.
653  */
654 static struct MeshPeer *
655 get_hop (struct MeshConnection *c, int fwd)
656 {
657   if (fwd)
658     return get_next_hop (c);
659   return get_prev_hop (c);
660 }
661
662
663 /**
664  * Is traffic coming from this sender 'FWD' traffic?
665  *
666  * @param c Connection to check.
667  * @param sender Peer identity of neighbor.
668  *
669  * @return #GNUNET_YES in case the sender is the 'prev' hop and therefore
670  *         the traffic is 'FWD'.
671  *         #GNUNET_NO for BCK.
672  *         #GNUNET_SYSERR for errors.
673  */
674 static int
675 is_fwd (const struct MeshConnection *c,
676         const struct GNUNET_PeerIdentity *sender)
677 {
678   GNUNET_PEER_Id id;
679
680   id = GNUNET_PEER_search (sender);
681   if (GMP_get_short_id (get_prev_hop (c)) == id)
682     return GNUNET_YES;
683
684   if (GMP_get_short_id (get_next_hop (c)) == id)
685     return GNUNET_NO;
686
687   GNUNET_break (0);
688   return GNUNET_SYSERR;
689 }
690
691
692 /**
693  * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
694  * or a first CONNECTION_ACK directed to us.
695  *
696  * @param connection Connection to confirm.
697  * @param fwd Should we send it FWD? (root->dest)
698  *            (First (~SYNACK) goes BCK, second (~ACK) goes FWD)
699  */
700 static void
701 send_connection_ack (struct MeshConnection *connection, int fwd)
702 {
703   struct MeshTunnel3 *t;
704
705   t = connection->t;
706   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send connection %s ACK\n",
707        !GM_f2s (fwd));
708   GMP_queue_add (get_hop (connection, fwd), NULL,
709                  GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
710                  sizeof (struct GNUNET_MESH_ConnectionACK),
711                  connection, fwd, &message_sent, NULL);
712   connection->pending_messages++;
713   if (MESH_TUNNEL3_NEW == GMT_get_cstate (t))
714     GMT_change_cstate (t, MESH_TUNNEL3_WAITING);
715   if (MESH_CONNECTION_READY != connection->state)
716     connection_change_state (connection, MESH_CONNECTION_SENT);
717 }
718
719
720 /**
721  * Send a notification that a connection is broken.
722  *
723  * @param c Connection that is broken.
724  * @param id1 Peer that has disconnected.
725  * @param id2 Peer that has disconnected.
726  * @param fwd Direction towards which to send it.
727  */
728 static void
729 send_broken (struct MeshConnection *c,
730              const struct GNUNET_PeerIdentity *id1,
731              const struct GNUNET_PeerIdentity *id2,
732              int fwd)
733 {
734   struct GNUNET_MESH_ConnectionBroken msg;
735
736   msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectionBroken));
737   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN);
738   msg.cid = c->id;
739   msg.peer1 = *id1;
740   msg.peer2 = *id2;
741   GMC_send_prebuilt_message (&msg.header, c, fwd, NULL, NULL);
742 }
743
744
745
746 /**
747  * Send keepalive packets for a connection.
748  *
749  * @param c Connection to keep alive..
750  * @param fwd Is this a FWD keepalive? (owner -> dest).
751  *
752  * FIXME register in GMC_send_prebuilt_message()
753  */
754 static void
755 connection_keepalive (struct MeshConnection *c, int fwd)
756 {
757   struct GNUNET_MESH_ConnectionKeepAlive *msg;
758   size_t size = sizeof (struct GNUNET_MESH_ConnectionKeepAlive);
759   char cbuf[size];
760
761   LOG (GNUNET_ERROR_TYPE_DEBUG,
762        "sending %s keepalive for connection %s]\n",
763        GM_f2s (fwd), GMC_2s (c));
764
765   msg = (struct GNUNET_MESH_ConnectionKeepAlive *) cbuf;
766   msg->header.size = htons (size);
767   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE);
768   msg->cid = c->id;
769
770   GMC_send_prebuilt_message (&msg->header, c, fwd, NULL, NULL);
771 }
772
773
774 /**
775  * Send CONNECTION_{CREATE/ACK} packets for a connection.
776  *
777  * @param c Connection for which to send the message.
778  * @param fwd If #GNUNET_YES, send CREATE, otherwise send ACK.
779  */
780 static void
781 connection_recreate (struct MeshConnection *c, int fwd)
782 {
783   LOG (GNUNET_ERROR_TYPE_DEBUG, "sending connection recreate\n");
784   if (fwd)
785     GMC_send_create (c);
786   else
787     send_connection_ack (c, GNUNET_NO);
788 }
789
790
791 /**
792  * Generic connection timer management.
793  * Depending on the role of the peer in the connection will send the
794  * appropriate message (build or keepalive)
795  *
796  * @param c Conncetion to maintain.
797  * @param fwd Is FWD?
798  */
799 static void
800 connection_maintain (struct MeshConnection *c, int fwd)
801 {
802   if (MESH_TUNNEL3_SEARCHING == GMT_get_cstate (c->t))
803   {
804     /* TODO DHT GET with RO_BART */
805     return;
806   }
807   switch (c->state)
808   {
809     case MESH_CONNECTION_NEW:
810       GNUNET_break (0);
811       /* fall-through */
812     case MESH_CONNECTION_SENT:
813       connection_recreate (c, fwd);
814       break;
815     case MESH_CONNECTION_READY:
816       connection_keepalive (c, fwd);
817       break;
818     default:
819       break;
820   }
821 }
822
823
824 static void
825 connection_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
826 {
827   struct MeshConnection *c = cls;
828   struct GNUNET_TIME_Relative delay;
829
830   c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
831   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
832     return;
833
834   connection_maintain (c, GNUNET_YES);
835   delay = c->state == MESH_CONNECTION_READY ?
836           refresh_connection_time : create_connection_time;
837   c->fwd_maintenance_task = GNUNET_SCHEDULER_add_delayed (delay,
838                                                           &connection_fwd_keepalive,
839                                                           c);
840 }
841
842
843 static void
844 connection_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
845 {
846   struct MeshConnection *c = cls;
847   struct GNUNET_TIME_Relative delay;
848
849   c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
850   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
851     return;
852
853   connection_maintain (c, GNUNET_NO);
854   delay = c->state == MESH_CONNECTION_READY ?
855           refresh_connection_time : create_connection_time;
856   c->bck_maintenance_task = GNUNET_SCHEDULER_add_delayed (delay,
857                                                           &connection_bck_keepalive,
858                                                           c);
859 }
860
861
862 /**
863  * @brief Re-initiate traffic on this connection if necessary.
864  *
865  * Check if there is traffic queued towards this peer
866  * and the core transmit handle is NULL (traffic was stalled).
867  * If so, call core tmt rdy.
868  *
869  * @param c Connection on which initiate traffic.
870  * @param fwd Is this about fwd traffic?
871  */
872 static void
873 connection_unlock_queue (struct MeshConnection *c, int fwd)
874 {
875   struct MeshPeer *peer;
876
877   LOG (GNUNET_ERROR_TYPE_DEBUG,
878               "connection_unlock_queue %s on %s\n",
879               GM_f2s (fwd), GMC_2s (c));
880
881   if (GMC_is_terminal (c, fwd))
882   {
883     LOG (GNUNET_ERROR_TYPE_DEBUG, " is terminal!\n");
884     return;
885   }
886
887   peer = get_hop (c, fwd);
888   GMP_queue_unlock (peer, c);
889 }
890
891
892 /**
893  * Cancel all transmissions that belong to a certain connection.
894  *
895  * If the connection is scheduled for destruction and no more messages are left,
896  * the connection will be destroyed by the continuation call.
897  *
898  * @param c Connection which to cancel. Might be destroyed during this call.
899  * @param fwd Cancel fwd traffic?
900  */
901 static void
902 connection_cancel_queues (struct MeshConnection *c, int fwd)
903 {
904   struct MeshFlowControl *fc;
905   struct MeshPeer *peer;
906
907   LOG (GNUNET_ERROR_TYPE_DEBUG,
908        " *** Cancel %s queues for connection %s\n",
909        GM_f2s (fwd), GMC_2s (c));
910   if (NULL == c)
911   {
912     GNUNET_break (0);
913     return;
914   }
915
916   fc = fwd ? &c->fwd_fc : &c->bck_fc;
917   if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
918   {
919     GNUNET_SCHEDULER_cancel (fc->poll_task);
920     fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
921     LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Cancel POLL in ccq for fc %p\n", fc);
922   }
923   peer = get_hop (c, fwd);
924   GMP_queue_cancel (peer, c);
925 }
926
927
928 /**
929  * Function called if a connection has been stalled for a while,
930  * possibly due to a missed ACK. Poll the neighbor about its ACK status.
931  *
932  * @param cls Closure (poll ctx).
933  * @param tc TaskContext.
934  */
935 static void
936 connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
937
938
939 /**
940  * Callback called when a queued POLL message is sent.
941  *
942  * @param cls Closure (FC).
943  * @param c Connection this message was on.
944  * @param q Queue handler this call invalidates.
945  * @param type Type of message sent.
946  * @param fwd Was this a FWD going message?
947  * @param size Size of the message.
948  */
949 static void
950 poll_sent (void *cls,
951            struct MeshConnection *c,
952            struct MeshConnectionQueue *q,
953            uint16_t type, int fwd, size_t size)
954 {
955   struct MeshFlowControl *fc = cls;
956
957   if (2 == c->destroy)
958   {
959     LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL canceled on shutdown\n");
960     return;
961   }
962   LOG (GNUNET_ERROR_TYPE_DEBUG,
963        " *** POLL sent for , scheduling new one!\n");
964   fc->poll_msg = NULL;
965   fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
966   fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
967                                                 &connection_poll, fc);
968   LOG (GNUNET_ERROR_TYPE_DEBUG, " task %u\n", fc->poll_task);
969
970 }
971
972 /**
973  * Function called if a connection has been stalled for a while,
974  * possibly due to a missed ACK. Poll the neighbor about its ACK status.
975  *
976  * @param cls Closure (poll ctx).
977  * @param tc TaskContext.
978  */
979 static void
980 connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
981 {
982   struct MeshFlowControl *fc = cls;
983   struct GNUNET_MESH_Poll msg;
984   struct MeshConnection *c;
985
986   fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
987   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
988   {
989     return;
990   }
991
992   c = fc->c;
993   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Polling!\n");
994   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** connection [%s]\n", GMC_2s (c));
995   LOG (GNUNET_ERROR_TYPE_DEBUG, " ***   %s\n",
996        fc == &c->fwd_fc ? "FWD" : "BCK");
997
998   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL);
999   msg.header.size = htons (sizeof (msg));
1000   msg.pid = htonl (fc->last_pid_sent);
1001   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** last pid sent: %u!\n", fc->last_pid_sent);
1002   fc->poll_msg = GMC_send_prebuilt_message (&msg.header, c, fc == &c->fwd_fc,
1003                                             &poll_sent, fc);
1004 }
1005
1006
1007 /**
1008  * Timeout function due to lack of keepalive/traffic from the owner.
1009  * Destroys connection if called.
1010  *
1011  * @param cls Closure (connection to destroy).
1012  * @param tc TaskContext.
1013  */
1014 static void
1015 connection_fwd_timeout (void *cls,
1016                         const struct GNUNET_SCHEDULER_TaskContext *tc)
1017 {
1018   struct MeshConnection *c = cls;
1019
1020   c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
1021   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1022     return;
1023   LOG (GNUNET_ERROR_TYPE_DEBUG,
1024               "Connection %s[%X] FWD timed out. Destroying.\n",
1025               GMT_2s (c->t),
1026               c->id);
1027
1028   if (GMC_is_origin (c, GNUNET_YES)) /* If local, leave. */
1029     return;
1030
1031   GMC_destroy (c);
1032 }
1033
1034
1035 /**
1036  * Timeout function due to lack of keepalive/traffic from the destination.
1037  * Destroys connection if called.
1038  *
1039  * @param cls Closure (connection to destroy).
1040  * @param tc TaskContext
1041  */
1042 static void
1043 connection_bck_timeout (void *cls,
1044                         const struct GNUNET_SCHEDULER_TaskContext *tc)
1045 {
1046   struct MeshConnection *c = cls;
1047
1048   c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
1049   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1050     return;
1051
1052   LOG (GNUNET_ERROR_TYPE_DEBUG,
1053               "Connection %s[%X] FWD timed out. Destroying.\n",
1054               GMT_2s (c->t), c->id);
1055
1056   if (GMC_is_origin (c, GNUNET_NO)) /* If local, leave. */
1057     return;
1058
1059   GMC_destroy (c);
1060 }
1061
1062
1063 /**
1064  * Resets the connection timeout task, some other message has done the
1065  * task's job.
1066  * - For the first peer on the direction this means to send
1067  *   a keepalive or a path confirmation message (either create or ACK).
1068  * - For all other peers, this means to destroy the connection,
1069  *   due to lack of activity.
1070  * Starts the timeout if no timeout was running (connection just created).
1071  *
1072  * @param c Connection whose timeout to reset.
1073  * @param fwd Is this forward?
1074  *
1075  * TODO use heap to improve efficiency of scheduler.
1076  */
1077 static void
1078 connection_reset_timeout (struct MeshConnection *c, int fwd)
1079 {
1080   GNUNET_SCHEDULER_TaskIdentifier *ti;
1081   GNUNET_SCHEDULER_Task f;
1082
1083   ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task;
1084
1085   LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s reset timeout\n", GM_f2s (fwd));
1086
1087   if (GNUNET_SCHEDULER_NO_TASK != *ti)
1088     GNUNET_SCHEDULER_cancel (*ti);
1089
1090   if (GMC_is_origin (c, fwd)) /* Startpoint */
1091   {
1092     f  = fwd ? &connection_fwd_keepalive : &connection_bck_keepalive;
1093     *ti = GNUNET_SCHEDULER_add_delayed (refresh_connection_time, f, c);
1094   }
1095   else /* Relay, endpoint. */
1096   {
1097     struct GNUNET_TIME_Relative delay;
1098
1099     delay = GNUNET_TIME_relative_multiply (refresh_connection_time, 4);
1100     f  = fwd ? &connection_fwd_timeout : &connection_bck_timeout;
1101     *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c);
1102   }
1103 }
1104
1105
1106 /**
1107  * Add the connection to the list of both neighbors.
1108  *
1109  * @param c Connection.
1110  *
1111  * @return #GNUNET_OK if everything went fine
1112  *         #GNUNET_SYSERR if the was an error and @c c is malformed.
1113  */
1114 static int
1115 register_neighbors (struct MeshConnection *c)
1116 {
1117   struct MeshPeer *next_peer;
1118   struct MeshPeer *prev_peer;
1119
1120   next_peer = get_next_hop (c);
1121   prev_peer = get_prev_hop (c);
1122
1123   if (GNUNET_NO == GMP_is_neighbor (next_peer)
1124       || GNUNET_NO == GMP_is_neighbor (prev_peer))
1125     return GNUNET_SYSERR;
1126
1127   GMP_add_connection (next_peer, c);
1128   GMP_add_connection (prev_peer, c);
1129
1130   return GNUNET_OK;
1131 }
1132
1133
1134 /**
1135  * Remove the connection from the list of both neighbors.
1136  *
1137  * @param c Connection.
1138  */
1139 static void
1140 unregister_neighbors (struct MeshConnection *c)
1141 {
1142   struct MeshPeer *peer;
1143
1144   peer = get_next_hop (c);
1145   GMP_remove_connection (peer, c);
1146
1147   peer = get_prev_hop (c);
1148   GMP_remove_connection (peer, c);
1149
1150 }
1151
1152
1153 /**
1154  * Bind the connection to the peer and the tunnel to that peer.
1155  *
1156  * If the peer has no tunnel, create one. Update tunnel and connection
1157  * data structres to reflect new status.
1158  *
1159  * @param c Connection.
1160  * @param peer Peer.
1161  */
1162 static void
1163 add_to_peer (struct MeshConnection *c, struct MeshPeer *peer)
1164 {
1165   GMP_add_tunnel (peer);
1166   c->t = GMP_get_tunnel (peer);
1167   GMT_add_connection (c->t, c);
1168 }
1169
1170 /******************************************************************************/
1171 /********************************    API    ***********************************/
1172 /******************************************************************************/
1173
1174 /**
1175  * Core handler for connection creation.
1176  *
1177  * @param cls Closure (unused).
1178  * @param peer Sender (neighbor).
1179  * @param message Message.
1180  *
1181  * @return GNUNET_OK to keep the connection open,
1182  *         GNUNET_SYSERR to close it (signal serious error)
1183  */
1184 int
1185 GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
1186                    const struct GNUNET_MessageHeader *message)
1187 {
1188   struct GNUNET_MESH_ConnectionCreate *msg;
1189   struct GNUNET_PeerIdentity *id;
1190   struct GNUNET_HashCode *cid;
1191   struct MeshPeerPath *path;
1192   struct MeshPeer *dest_peer;
1193   struct MeshPeer *orig_peer;
1194   struct MeshConnection *c;
1195   unsigned int own_pos;
1196   uint16_t size;
1197   uint16_t i;
1198
1199   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1200   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a connection create msg\n");
1201
1202   /* Check size */
1203   size = ntohs (message->size);
1204   if (size < sizeof (struct GNUNET_MESH_ConnectionCreate))
1205   {
1206     GNUNET_break_op (0);
1207     return GNUNET_OK;
1208   }
1209
1210   /* Calculate hops */
1211   size -= sizeof (struct GNUNET_MESH_ConnectionCreate);
1212   if (size % sizeof (struct GNUNET_PeerIdentity))
1213   {
1214     GNUNET_break_op (0);
1215     return GNUNET_OK;
1216   }
1217   size /= sizeof (struct GNUNET_PeerIdentity);
1218   if (1 > size)
1219   {
1220     GNUNET_break_op (0);
1221     return GNUNET_OK;
1222   }
1223   LOG (GNUNET_ERROR_TYPE_DEBUG, "    path has %u hops.\n", size);
1224
1225   /* Get parameters */
1226   msg = (struct GNUNET_MESH_ConnectionCreate *) message;
1227   cid = &msg->cid;
1228   id = (struct GNUNET_PeerIdentity *) &msg[1];
1229   LOG (GNUNET_ERROR_TYPE_DEBUG,
1230               "    connection %s (%s).\n",
1231               GNUNET_h2s (cid), GNUNET_i2s (id));
1232
1233   /* Create connection */
1234   c = connection_get (cid);
1235   if (NULL == c)
1236   {
1237     /* Create path */
1238     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Creating path...\n");
1239     path = path_new (size);
1240     own_pos = 0;
1241     for (i = 0; i < size; i++)
1242     {
1243       LOG (GNUNET_ERROR_TYPE_DEBUG, "  ... adding %s\n",
1244                   GNUNET_i2s (&id[i]));
1245       path->peers[i] = GNUNET_PEER_intern (&id[i]);
1246       if (path->peers[i] == myid)
1247         own_pos = i;
1248     }
1249     if (own_pos == 0 && path->peers[own_pos] != myid)
1250     {
1251       /* create path: self not found in path through self */
1252       GNUNET_break_op (0);
1253       path_destroy (path);
1254       return GNUNET_OK;
1255     }
1256     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Own position: %u\n", own_pos);
1257     GMP_add_path_to_all (path, GNUNET_NO);
1258         LOG (GNUNET_ERROR_TYPE_DEBUG, "  Creating connection\n");
1259     c = GMC_new (cid, NULL, path_duplicate (path), own_pos);
1260     if (NULL == c)
1261     {
1262       path_destroy (path);
1263       return GNUNET_OK;
1264     }
1265     connection_reset_timeout (c, GNUNET_YES);
1266   }
1267   else
1268   {
1269     path = path_duplicate (c->path);
1270   }
1271   if (MESH_CONNECTION_NEW == c->state)
1272     connection_change_state (c, MESH_CONNECTION_SENT);
1273
1274   /* Remember peers */
1275   dest_peer = GMP_get (&id[size - 1]);
1276   orig_peer = GMP_get (&id[0]);
1277
1278   /* Is it a connection to us? */
1279   if (c->own_pos == size - 1)
1280   {
1281     LOG (GNUNET_ERROR_TYPE_DEBUG, "  It's for us!\n");
1282     GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_YES);
1283
1284     add_to_peer (c, orig_peer);
1285     if (MESH_TUNNEL3_NEW == GMT_get_cstate (c->t))
1286       GMT_change_cstate (c->t,  MESH_TUNNEL3_WAITING);
1287
1288     send_connection_ack (c, GNUNET_NO);
1289     if (MESH_CONNECTION_SENT == c->state)
1290       connection_change_state (c, MESH_CONNECTION_ACK);
1291
1292     /* Keep tunnel alive in direction dest->owner*/
1293     c->bck_maintenance_task =
1294       GNUNET_SCHEDULER_add_delayed (create_connection_time,
1295                                     &connection_bck_keepalive, c);
1296   }
1297   else
1298   {
1299     /* It's for somebody else! Retransmit. */
1300     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Retransmitting.\n");
1301     GMP_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
1302     GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_NO);
1303     GMC_send_prebuilt_message (message, c, GNUNET_YES, NULL, NULL);
1304   }
1305   path_destroy (path);
1306   return GNUNET_OK;
1307 }
1308
1309
1310 /**
1311  * Core handler for path confirmations.
1312  *
1313  * @param cls closure
1314  * @param message message
1315  * @param peer peer identity this notification is about
1316  *
1317  * @return GNUNET_OK to keep the connection open,
1318  *         GNUNET_SYSERR to close it (signal serious error)
1319  */
1320 int
1321 GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer,
1322                     const struct GNUNET_MessageHeader *message)
1323 {
1324   struct GNUNET_MESH_ConnectionACK *msg;
1325   struct MeshConnection *c;
1326   struct MeshPeerPath *p;
1327   struct MeshPeer *pi;
1328   enum MeshConnectionState oldstate;
1329   int fwd;
1330
1331   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1332   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a connection ACK msg\n");
1333   msg = (struct GNUNET_MESH_ConnectionACK *) message;
1334   LOG (GNUNET_ERROR_TYPE_DEBUG, "  on connection %s\n",
1335               GNUNET_h2s (&msg->cid));
1336   c = connection_get (&msg->cid);
1337   if (NULL == c)
1338   {
1339     GNUNET_STATISTICS_update (stats, "# control on unknown connection",
1340                               1, GNUNET_NO);
1341     LOG (GNUNET_ERROR_TYPE_DEBUG, "  don't know the connection!\n");
1342     return GNUNET_OK;
1343   }
1344
1345   oldstate = c->state;
1346   LOG (GNUNET_ERROR_TYPE_DEBUG, "  via peer %s\n", GNUNET_i2s (peer));
1347   pi = GMP_get (peer);
1348   if (get_next_hop (c) == pi)
1349   {
1350     LOG (GNUNET_ERROR_TYPE_DEBUG, "  SYNACK\n");
1351     fwd = GNUNET_NO;
1352     if (MESH_CONNECTION_SENT == oldstate)
1353       connection_change_state (c, MESH_CONNECTION_ACK);
1354   }
1355   else if (get_prev_hop (c) == pi)
1356   {
1357     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ACK\n");
1358     fwd = GNUNET_YES;
1359     connection_change_state (c, MESH_CONNECTION_READY);
1360   }
1361   else
1362   {
1363     GNUNET_break_op (0);
1364     return GNUNET_OK;
1365   }
1366
1367   connection_reset_timeout (c, fwd);
1368
1369   /* Add path to peers? */
1370   p = c->path;
1371   if (NULL != p)
1372   {
1373     GMP_add_path_to_all (p, GNUNET_YES);
1374   }
1375   else
1376   {
1377     GNUNET_break (0);
1378   }
1379
1380   /* Message for us as creator? */
1381   if (GMC_is_origin (c, GNUNET_YES))
1382   {
1383     if (GNUNET_NO != fwd)
1384     {
1385       GNUNET_break_op (0);
1386       return GNUNET_OK;
1387     }
1388     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Connection (SYN)ACK for us!\n");
1389
1390     /* If just created, cancel the short timeout and start a long one */
1391     if (MESH_CONNECTION_SENT == oldstate)
1392       connection_reset_timeout (c, GNUNET_YES);
1393
1394     /* Change connection and tunnel state */
1395     connection_change_state (c, MESH_CONNECTION_READY);
1396     if (MESH_TUNNEL3_WAITING == GMT_get_cstate (c->t))
1397       GMT_change_cstate (c->t, MESH_TUNNEL3_READY);
1398
1399     /* Send ACK (~TCP ACK)*/
1400     send_connection_ack (c, GNUNET_YES);
1401     return GNUNET_OK;
1402   }
1403
1404   /* Message for us as destination? */
1405   if (GMC_is_terminal (c, GNUNET_YES))
1406   {
1407     if (GNUNET_YES != fwd)
1408     {
1409       GNUNET_break_op (0);
1410       return GNUNET_OK;
1411     }
1412     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Connection ACK for us!\n");
1413
1414     /* If just created, cancel the short timeout and start a long one */
1415     if (MESH_CONNECTION_ACK == oldstate)
1416       connection_reset_timeout (c, GNUNET_NO);
1417
1418     /* Change tunnel state */
1419     if (MESH_TUNNEL3_WAITING == GMT_get_cstate (c->t))
1420       GMT_change_cstate (c->t, MESH_TUNNEL3_READY);
1421
1422     return GNUNET_OK;
1423   }
1424
1425   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
1426   GMC_send_prebuilt_message (message, c, fwd, NULL, NULL);
1427   return GNUNET_OK;
1428 }
1429
1430
1431 /**
1432  * Core handler for notifications of broken paths
1433  *
1434  * @param cls Closure (unused).
1435  * @param id Peer identity of sending neighbor.
1436  * @param message Message.
1437  *
1438  * @return GNUNET_OK to keep the connection open,
1439  *         GNUNET_SYSERR to close it (signal serious error)
1440  */
1441 int
1442 GMC_handle_broken (void* cls,
1443                    const struct GNUNET_PeerIdentity* id,
1444                    const struct GNUNET_MessageHeader* message)
1445 {
1446   struct GNUNET_MESH_ConnectionBroken *msg;
1447   struct MeshConnection *c;
1448   int fwd;
1449
1450   LOG (GNUNET_ERROR_TYPE_DEBUG,
1451               "Received a CONNECTION BROKEN msg from %s\n", GNUNET_i2s (id));
1452   msg = (struct GNUNET_MESH_ConnectionBroken *) message;
1453   LOG (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
1454               GNUNET_i2s (&msg->peer1));
1455   LOG (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
1456               GNUNET_i2s (&msg->peer2));
1457   c = connection_get (&msg->cid);
1458   if (NULL == c)
1459   {
1460     GNUNET_break_op (0);
1461     return GNUNET_OK;
1462   }
1463
1464   fwd = is_fwd (c, id);
1465   connection_cancel_queues (c, !fwd);
1466   if (GMC_is_terminal (c, fwd))
1467   {
1468     if (0 < c->pending_messages)
1469       c->destroy = GNUNET_YES;
1470     else
1471       GMC_destroy (c);
1472   }
1473   else
1474   {
1475     GMC_send_prebuilt_message (message, c, fwd, NULL, NULL);
1476     c->destroy = GNUNET_YES;
1477   }
1478
1479   return GNUNET_OK;
1480
1481 }
1482
1483
1484 /**
1485  * Core handler for tunnel destruction
1486  *
1487  * @param cls Closure (unused).
1488  * @param peer Peer identity of sending neighbor.
1489  * @param message Message.
1490  *
1491  * @return GNUNET_OK to keep the connection open,
1492  *         GNUNET_SYSERR to close it (signal serious error)
1493  */
1494 int
1495 GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
1496                     const struct GNUNET_MessageHeader *message)
1497 {
1498   struct GNUNET_MESH_ConnectionDestroy *msg;
1499   struct MeshConnection *c;
1500   int fwd;
1501
1502   msg = (struct GNUNET_MESH_ConnectionDestroy *) message;
1503   LOG (GNUNET_ERROR_TYPE_DEBUG,
1504               "Got a CONNECTION DESTROY message from %s\n",
1505               GNUNET_i2s (peer));
1506   LOG (GNUNET_ERROR_TYPE_DEBUG,
1507               "  for connection %s\n",
1508               GNUNET_h2s (&msg->cid));
1509   c = connection_get (&msg->cid);
1510   if (NULL == c)
1511   {
1512     /* Probably already got the message from another path,
1513      * destroyed the tunnel and retransmitted to children.
1514      * Safe to ignore.
1515      */
1516     GNUNET_STATISTICS_update (stats, "# control on unknown tunnel",
1517                               1, GNUNET_NO);
1518     LOG (GNUNET_ERROR_TYPE_DEBUG, "  connection unknown: already destroyed?\n");
1519     return GNUNET_OK;
1520   }
1521   fwd = is_fwd (c, peer);
1522   if (GNUNET_SYSERR == fwd)
1523   {
1524     GNUNET_break_op (0);
1525     return GNUNET_OK;
1526   }
1527   GMC_send_prebuilt_message (message, c, fwd, NULL, NULL);
1528   c->destroy = GNUNET_YES;
1529   c->state = MESH_CONNECTION_DESTROYED;
1530
1531   return GNUNET_OK;
1532 }
1533
1534 /**
1535  * Generic handler for mesh network encrypted traffic.
1536  *
1537  * @param peer Peer identity this notification is about.
1538  * @param msg Encrypted message.
1539  *
1540  * @return GNUNET_OK to keep the connection open,
1541  *         GNUNET_SYSERR to close it (signal serious error)
1542  */
1543 static int
1544 handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer,
1545                        const struct GNUNET_MESH_Encrypted *msg)
1546 {
1547   struct MeshConnection *c;
1548   struct MeshPeer *neighbor;
1549   struct MeshFlowControl *fc;
1550   GNUNET_PEER_Id peer_id;
1551   uint32_t pid;
1552   uint32_t ttl;
1553   uint16_t type;
1554   size_t size;
1555   int fwd;
1556
1557   /* Check size */
1558   size = ntohs (msg->header.size);
1559   if (size <
1560       sizeof (struct GNUNET_MESH_Encrypted) +
1561       sizeof (struct GNUNET_MessageHeader))
1562   {
1563     GNUNET_break_op (0);
1564     return GNUNET_OK;
1565   }
1566   type = ntohs (msg->header.type);
1567   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1568   LOG (GNUNET_ERROR_TYPE_DEBUG, "got a %s message (#%u) from %s\n",
1569        GM_m2s (type), ntohl (msg->pid), GNUNET_i2s (peer));
1570
1571   /* Check connection */
1572   c = connection_get (&msg->cid);
1573   if (NULL == c)
1574   {
1575     GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
1576     LOG (GNUNET_ERROR_TYPE_DEBUG,
1577          "WARNING connection %s unknown\n",
1578          GNUNET_h2s (&msg->cid));
1579     return GNUNET_OK;
1580   }
1581
1582   /* Check if origin is as expected */
1583   neighbor = get_prev_hop (c);
1584   peer_id = GNUNET_PEER_search (peer);
1585   if (peer_id == GMP_get_short_id (neighbor))
1586   {
1587     fwd = GNUNET_YES;
1588   }
1589   else
1590   {
1591     neighbor = get_next_hop (c);
1592     if (peer_id == GMP_get_short_id (neighbor))
1593     {
1594       fwd = GNUNET_NO;
1595     }
1596     else
1597     {
1598       /* Unexpected peer sending traffic on a connection. */
1599       GNUNET_break_op (0);
1600       return GNUNET_OK;
1601     }
1602   }
1603
1604   /* Check PID */
1605   fc = fwd ? &c->bck_fc : &c->fwd_fc;
1606   pid = ntohl (msg->pid);
1607   if (GM_is_pid_bigger (pid, fc->last_ack_sent))
1608   {
1609     GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
1610     LOG (GNUNET_ERROR_TYPE_DEBUG,
1611                 "WARNING Received PID %u, (prev %u), ACK %u\n",
1612                 pid, fc->last_pid_recv, fc->last_ack_sent);
1613     return GNUNET_OK;
1614   }
1615   if (GNUNET_NO == GM_is_pid_bigger (pid, fc->last_pid_recv))
1616   {
1617     GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO);
1618     LOG (GNUNET_ERROR_TYPE_DEBUG,
1619                 " Pid %u not expected (%u+), dropping!\n",
1620                 pid, fc->last_pid_recv + 1);
1621     return GNUNET_OK;
1622   }
1623   if (MESH_CONNECTION_SENT == c->state || MESH_CONNECTION_ACK == c->state)
1624     connection_change_state (c, MESH_CONNECTION_READY);
1625   connection_reset_timeout (c, fwd);
1626   fc->last_pid_recv = pid;
1627
1628   /* Is this message for us? */
1629   if (GMC_is_terminal (c, fwd))
1630   {
1631     /* TODO signature verification */
1632     LOG (GNUNET_ERROR_TYPE_DEBUG, "  message for us!\n");
1633     GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
1634
1635     if (NULL == c->t)
1636     {
1637       GNUNET_break (0);
1638       return GNUNET_OK;
1639     }
1640     fc->last_pid_recv = pid;
1641     GMT_handle_encrypted (c->t, msg);
1642     GMC_send_ack (c, fwd, GNUNET_NO);
1643     return GNUNET_OK;
1644   }
1645
1646   /* Message not for us: forward to next hop */
1647   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
1648   ttl = ntohl (msg->ttl);
1649   LOG (GNUNET_ERROR_TYPE_DEBUG, "   ttl: %u\n", ttl);
1650   if (ttl == 0)
1651   {
1652     GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
1653     LOG (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
1654     GMC_send_ack (c, fwd, GNUNET_NO);
1655     return GNUNET_OK;
1656   }
1657
1658   GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
1659   GMC_send_prebuilt_message (&msg->header, c, fwd, NULL, NULL);
1660
1661   return GNUNET_OK;
1662 }
1663
1664 /**
1665  * Generic handler for mesh network encrypted traffic.
1666  *
1667  * @param peer Peer identity this notification is about.
1668  * @param msg Encrypted message.
1669  *
1670  * @return GNUNET_OK to keep the connection open,
1671  *         GNUNET_SYSERR to close it (signal serious error)
1672  */
1673 static int
1674 handle_mesh_kx (const struct GNUNET_PeerIdentity *peer,
1675                 const struct GNUNET_MESH_KX *msg)
1676 {
1677   struct MeshConnection *c;
1678   struct MeshPeer *neighbor;
1679   GNUNET_PEER_Id peer_id;
1680   size_t size;
1681   uint16_t type;
1682   int fwd;
1683
1684   /* Check size */
1685   size = ntohs (msg->header.size);
1686   if (size <
1687       sizeof (struct GNUNET_MESH_Encrypted) +
1688       sizeof (struct GNUNET_MessageHeader))
1689   {
1690     GNUNET_break_op (0);
1691     return GNUNET_OK;
1692   }
1693   type = ntohs (msg->header.type);
1694   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1695   LOG (GNUNET_ERROR_TYPE_DEBUG, "got a %s message from %s\n",
1696               GM_m2s (type), GNUNET_i2s (peer));
1697
1698   /* Check connection */
1699   c = connection_get (&msg->cid);
1700   if (NULL == c)
1701   {
1702     GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
1703     LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING connection unknown\n");
1704     return GNUNET_OK;
1705   }
1706
1707   /* Check if origin is as expected */
1708   neighbor = get_prev_hop (c);
1709   peer_id = GNUNET_PEER_search (peer);
1710   if (peer_id == GMP_get_short_id (neighbor))
1711   {
1712     fwd = GNUNET_YES;
1713   }
1714   else
1715   {
1716     neighbor = get_next_hop (c);
1717     if (peer_id == GMP_get_short_id (neighbor))
1718     {
1719       fwd = GNUNET_NO;
1720     }
1721     else
1722     {
1723       /* Unexpected peer sending traffic on a connection. */
1724       GNUNET_break_op (0);
1725       return GNUNET_OK;
1726     }
1727   }
1728
1729   /* Count as connection confirmation. */
1730   if (MESH_CONNECTION_SENT == c->state || MESH_CONNECTION_ACK == c->state)
1731     connection_change_state (c, MESH_CONNECTION_READY);
1732   connection_reset_timeout (c, fwd);
1733   if (NULL != c->t)
1734   {
1735     if (MESH_TUNNEL3_WAITING == GMT_get_cstate (c->t))
1736       GMT_change_cstate (c->t, MESH_TUNNEL3_READY);
1737   }
1738
1739   /* Is this message for us? */
1740   if (GMC_is_terminal (c, fwd))
1741   {
1742     LOG (GNUNET_ERROR_TYPE_DEBUG, "  message for us!\n");
1743     GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
1744     if (NULL == c->t)
1745     {
1746       GNUNET_break (0);
1747       return GNUNET_OK;
1748     }
1749     GMT_handle_kx (c->t, &msg[1].header);
1750     return GNUNET_OK;
1751   }
1752
1753   /* Message not for us: forward to next hop */
1754   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
1755   GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
1756   GMC_send_prebuilt_message (&msg->header, c, fwd, NULL, NULL);
1757
1758   return GNUNET_OK;
1759 }
1760
1761
1762 /**
1763  * Core handler for encrypted mesh network traffic (channel mgmt, data).
1764  *
1765  * @param cls Closure (unused).
1766  * @param message Message received.
1767  * @param peer Peer who sent the message.
1768  *
1769  * @return GNUNET_OK to keep the connection open,
1770  *         GNUNET_SYSERR to close it (signal serious error)
1771  */
1772 int
1773 GMC_handle_encrypted (void *cls, const struct GNUNET_PeerIdentity *peer,
1774                       const struct GNUNET_MessageHeader *message)
1775 {
1776   return handle_mesh_encrypted (peer,
1777                                 (struct GNUNET_MESH_Encrypted *)message);
1778 }
1779
1780
1781 /**
1782  * Core handler for key exchange traffic (ephemeral key, ping, pong).
1783  *
1784  * @param cls Closure (unused).
1785  * @param message Message received.
1786  * @param peer Peer who sent the message.
1787  *
1788  * @return GNUNET_OK to keep the connection open,
1789  *         GNUNET_SYSERR to close it (signal serious error)
1790  */
1791 int
1792 GMC_handle_kx (void *cls, const struct GNUNET_PeerIdentity *peer,
1793                const struct GNUNET_MessageHeader *message)
1794 {
1795   return handle_mesh_kx (peer,
1796                          (struct GNUNET_MESH_KX *) message);
1797 }
1798
1799
1800 /**
1801  * Core handler for mesh network traffic point-to-point acks.
1802  *
1803  * @param cls closure
1804  * @param message message
1805  * @param peer peer identity this notification is about
1806  *
1807  * @return GNUNET_OK to keep the connection open,
1808  *         GNUNET_SYSERR to close it (signal serious error)
1809  */
1810 int
1811 GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
1812                 const struct GNUNET_MessageHeader *message)
1813 {
1814   struct GNUNET_MESH_ACK *msg;
1815   struct MeshConnection *c;
1816   struct MeshFlowControl *fc;
1817   GNUNET_PEER_Id id;
1818   uint32_t ack;
1819   int fwd;
1820
1821   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1822   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
1823               GNUNET_i2s (peer));
1824   msg = (struct GNUNET_MESH_ACK *) message;
1825
1826   c = connection_get (&msg->cid);
1827
1828   if (NULL == c)
1829   {
1830     GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1,
1831                               GNUNET_NO);
1832     return GNUNET_OK;
1833   }
1834
1835   /* Is this a forward or backward ACK? */
1836   id = GNUNET_PEER_search (peer);
1837   if (GMP_get_short_id (get_next_hop (c)) == id)
1838   {
1839     LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
1840     fc = &c->fwd_fc;
1841     fwd = GNUNET_YES;
1842   }
1843   else if (GMP_get_short_id (get_prev_hop (c)) == id)
1844   {
1845     LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK ACK\n");
1846     fc = &c->bck_fc;
1847     fwd = GNUNET_NO;
1848   }
1849   else
1850   {
1851     GNUNET_break_op (0);
1852     return GNUNET_OK;
1853   }
1854
1855   ack = ntohl (msg->ack);
1856   LOG (GNUNET_ERROR_TYPE_DEBUG, "  ACK %u (was %u)\n",
1857               ack, fc->last_ack_recv);
1858   if (GM_is_pid_bigger (ack, fc->last_ack_recv))
1859     fc->last_ack_recv = ack;
1860
1861   /* Cancel polling if the ACK is big enough. */
1862   if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task &&
1863       GM_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
1864   {
1865     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Cancel poll\n");
1866     GNUNET_SCHEDULER_cancel (fc->poll_task);
1867     fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
1868     fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
1869   }
1870
1871   connection_unlock_queue (c, fwd);
1872
1873   return GNUNET_OK;
1874 }
1875
1876
1877 /**
1878  * Core handler for mesh network traffic point-to-point ack polls.
1879  *
1880  * @param cls closure
1881  * @param message message
1882  * @param peer peer identity this notification is about
1883  *
1884  * @return GNUNET_OK to keep the connection open,
1885  *         GNUNET_SYSERR to close it (signal serious error)
1886  */
1887 int
1888 GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
1889                  const struct GNUNET_MessageHeader *message)
1890 {
1891   struct GNUNET_MESH_Poll *msg;
1892   struct MeshConnection *c;
1893   struct MeshFlowControl *fc;
1894   GNUNET_PEER_Id id;
1895   uint32_t pid;
1896   int fwd;
1897
1898   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1899   LOG (GNUNET_ERROR_TYPE_DEBUG,
1900        "Got a POLL packet from %s!\n",
1901        GNUNET_i2s (peer));
1902
1903   msg = (struct GNUNET_MESH_Poll *) message;
1904
1905   c = connection_get (&msg->cid);
1906
1907   if (NULL == c)
1908   {
1909     GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
1910                               GNUNET_NO);
1911     GNUNET_break_op (0);
1912     return GNUNET_OK;
1913   }
1914
1915   /* Is this a forward or backward ACK?
1916    * Note: a poll should never be needed in a loopback case,
1917    * since there is no possiblility of packet loss there, so
1918    * this way of discerining FWD/BCK should not be a problem.
1919    */
1920   id = GNUNET_PEER_search (peer);
1921   if (GMP_get_short_id (get_next_hop (c)) == id)
1922   {
1923     LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD FC\n");
1924     fc = &c->fwd_fc;
1925   }
1926   else if (GMP_get_short_id (get_prev_hop (c)) == id)
1927   {
1928     LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK FC\n");
1929     fc = &c->bck_fc;
1930   }
1931   else
1932   {
1933     GNUNET_break_op (0);
1934     return GNUNET_OK;
1935   }
1936
1937   pid = ntohl (msg->pid);
1938   LOG (GNUNET_ERROR_TYPE_DEBUG, "  PID %u, OLD %u\n", pid, fc->last_pid_recv);
1939   fc->last_pid_recv = pid;
1940   fwd = fc == &c->bck_fc;
1941   GMC_send_ack (c, fwd, GNUNET_YES);
1942
1943   return GNUNET_OK;
1944 }
1945
1946
1947 /**
1948  * Core handler for mesh keepalives.
1949  *
1950  * @param cls closure
1951  * @param message message
1952  * @param peer peer identity this notification is about
1953  * @return GNUNET_OK to keep the connection open,
1954  *         GNUNET_SYSERR to close it (signal serious error)
1955  *
1956  * TODO: Check who we got this from, to validate route.
1957  */
1958 int
1959 GMC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
1960                       const struct GNUNET_MessageHeader *message)
1961 {
1962   struct GNUNET_MESH_ConnectionKeepAlive *msg;
1963   struct MeshConnection *c;
1964   struct MeshPeer *neighbor;
1965   GNUNET_PEER_Id peer_id;
1966   int fwd;
1967
1968   msg = (struct GNUNET_MESH_ConnectionKeepAlive *) message;
1969   LOG (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
1970               GNUNET_i2s (peer));
1971
1972   c = connection_get (&msg->cid);
1973   if (NULL == c)
1974   {
1975     GNUNET_STATISTICS_update (stats, "# keepalive on unknown connection", 1,
1976                               GNUNET_NO);
1977     return GNUNET_OK;
1978   }
1979
1980   /* Check if origin is as expected TODO refactor and reuse */
1981   peer_id = GNUNET_PEER_search (peer);
1982   neighbor = get_prev_hop (c);
1983   if (peer_id == GMP_get_short_id (neighbor))
1984   {
1985     fwd = GNUNET_YES;
1986   }
1987   else
1988   {
1989     neighbor = get_next_hop (c);
1990     if (peer_id == GMP_get_short_id (neighbor))
1991     {
1992       fwd = GNUNET_NO;
1993     }
1994     else
1995     {
1996       GNUNET_break_op (0);
1997       return GNUNET_OK;
1998     }
1999   }
2000
2001   connection_change_state (c, MESH_CONNECTION_READY);
2002   connection_reset_timeout (c, fwd);
2003
2004   if (GMC_is_terminal (c, fwd))
2005     return GNUNET_OK;
2006
2007   GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
2008   GMC_send_prebuilt_message (message, c, fwd, NULL, NULL);
2009
2010   return GNUNET_OK;
2011 }
2012
2013
2014 /**
2015  * Send an ACK on the appropriate connection/channel, depending on
2016  * the direction and the position of the peer.
2017  *
2018  * @param c Which connection to send the hop-by-hop ACK.
2019  * @param fwd Is this a fwd ACK? (will go dest->root).
2020  * @param force Send the ACK even if suboptimal (e.g. requested by POLL).
2021  */
2022 void
2023 GMC_send_ack (struct MeshConnection *c, int fwd, int force)
2024 {
2025   unsigned int buffer;
2026
2027   LOG (GNUNET_ERROR_TYPE_DEBUG,
2028        "GMC send %s ACK on %s\n",
2029        GM_f2s (fwd), GMC_2s (c));
2030
2031   if (NULL == c)
2032   {
2033     GNUNET_break (0);
2034     return;
2035   }
2036
2037   if (GNUNET_NO != c->destroy)
2038   {
2039     LOG (GNUNET_ERROR_TYPE_DEBUG, "  being destroyed, why bother...\n");
2040     return;
2041   }
2042
2043   /* Get available buffer space */
2044   if (GMC_is_terminal (c, fwd))
2045   {
2046     LOG (GNUNET_ERROR_TYPE_DEBUG, "  getting from all channels\n");
2047     buffer = GMT_get_channels_buffer (c->t);
2048   }
2049   else
2050   {
2051     LOG (GNUNET_ERROR_TYPE_DEBUG, "  getting from one connection\n");
2052     buffer = GMC_get_buffer (c, fwd);
2053   }
2054   LOG (GNUNET_ERROR_TYPE_DEBUG, "  buffer available: %u\n", buffer);
2055   if (0 == buffer && GNUNET_NO == force)
2056     return;
2057
2058   /* Send available buffer space */
2059   if (GMC_is_origin (c, fwd))
2060   {
2061     GNUNET_assert (NULL != c->t);
2062     LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on channels...\n");
2063     GMT_unchoke_channels (c->t);
2064   }
2065   else
2066   {
2067     LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on connection\n");
2068     send_ack (c, buffer, fwd, force);
2069   }
2070 }
2071
2072
2073 /**
2074  * Initialize the connections subsystem
2075  *
2076  * @param c Configuration handle.
2077  */
2078 void
2079 GMC_init (const struct GNUNET_CONFIGURATION_Handle *c)
2080 {
2081   LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
2082   if (GNUNET_OK !=
2083       GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE",
2084                                              &max_msgs_queue))
2085   {
2086     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
2087                                "MESH", "MAX_MSGS_QUEUE", "MISSING");
2088     GNUNET_SCHEDULER_shutdown ();
2089     return;
2090   }
2091
2092   if (GNUNET_OK !=
2093       GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_CONNECTIONS",
2094                                              &max_connections))
2095   {
2096     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
2097                                "MESH", "MAX_CONNECTIONS", "MISSING");
2098     GNUNET_SCHEDULER_shutdown ();
2099     return;
2100   }
2101
2102   if (GNUNET_OK !=
2103       GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_CONNECTION_TIME",
2104                                            &refresh_connection_time))
2105   {
2106     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
2107                                "MESH", "REFRESH_CONNECTION_TIME", "MISSING");
2108     GNUNET_SCHEDULER_shutdown ();
2109     return;
2110   }
2111   create_connection_time = GNUNET_TIME_UNIT_SECONDS;
2112   connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES);
2113 }
2114
2115
2116 /**
2117  * Destroy each connection on shutdown.
2118  *
2119  * @param cls Closure (unused).
2120  * @param key Current key code (CID, unused).
2121  * @param value Value in the hash map (connection)
2122  *
2123  * @return #GNUNET_YES, because we should continue to iterate,
2124  */
2125 static int
2126 shutdown_iterator (void *cls,
2127                    const struct GNUNET_HashCode *key,
2128                    void *value)
2129 {
2130   struct MeshConnection *c = value;
2131
2132   GMC_destroy (c);
2133   return GNUNET_YES;
2134 }
2135
2136
2137 /**
2138  * Shut down the connections subsystem.
2139  */
2140 void
2141 GMC_shutdown (void)
2142 {
2143   GNUNET_CONTAINER_multihashmap_iterate (connections, &shutdown_iterator, NULL);
2144   GNUNET_CONTAINER_multihashmap_destroy (connections);
2145   connections = NULL;
2146 }
2147
2148
2149 struct MeshConnection *
2150 GMC_new (const struct GNUNET_HashCode *cid,
2151          struct MeshTunnel3 *t,
2152          struct MeshPeerPath *p,
2153          unsigned int own_pos)
2154 {
2155   struct MeshConnection *c;
2156
2157   c = GNUNET_new (struct MeshConnection);
2158   c->id = *cid;
2159   GNUNET_CONTAINER_multihashmap_put (connections, &c->id, c,
2160                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
2161   fc_init (&c->fwd_fc);
2162   fc_init (&c->bck_fc);
2163   c->fwd_fc.c = c;
2164   c->bck_fc.c = c;
2165
2166   c->t = t;
2167   if (own_pos > p->length - 1)
2168   {
2169     GNUNET_break (0);
2170     GMC_destroy (c);
2171     return NULL;
2172   }
2173   c->own_pos = own_pos;
2174   c->path = p;
2175
2176   if (0 == own_pos)
2177   {
2178     c->fwd_maintenance_task =
2179       GNUNET_SCHEDULER_add_delayed (create_connection_time,
2180                                     &connection_fwd_keepalive, c);
2181   }
2182   if (GNUNET_OK != register_neighbors (c))
2183   {
2184     GMC_destroy (c);
2185     return NULL;
2186   }
2187
2188   return c;
2189 }
2190
2191
2192 void
2193 GMC_destroy (struct MeshConnection *c)
2194 {
2195   if (NULL == c)
2196     return;
2197
2198   if (2 == c->destroy) /* cancel queues -> GMP_queue_cancel -> q_destroy -> */
2199     return;            /* -> message_sent -> GMC_destroy. Don't loop. */
2200   c->destroy = 2;
2201
2202   LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s\n", GMC_2s (c));
2203   LOG (GNUNET_ERROR_TYPE_DEBUG, " fc's f: %p, b: %p\n",
2204        &c->fwd_fc, &c->bck_fc);
2205   LOG (GNUNET_ERROR_TYPE_DEBUG, " fc tasks f: %u, b: %u\n",
2206        c->fwd_fc.poll_task, c->bck_fc.poll_task);
2207
2208   /* Cancel all traffic */
2209   connection_cancel_queues (c, GNUNET_YES);
2210   connection_cancel_queues (c, GNUNET_NO);
2211
2212   LOG (GNUNET_ERROR_TYPE_DEBUG, " fc tasks f: %u, b: %u\n",
2213        c->fwd_fc.poll_task, c->bck_fc.poll_task);
2214
2215   /* Cancel maintainance task (keepalive/timeout) */
2216   if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task)
2217     GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
2218   if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task)
2219     GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
2220   if (GNUNET_SCHEDULER_NO_TASK != c->fwd_fc.poll_task)
2221   {
2222     GNUNET_SCHEDULER_cancel (c->fwd_fc.poll_task);
2223     LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL FWD canceled\n");
2224   }
2225   if (GNUNET_SCHEDULER_NO_TASK != c->bck_fc.poll_task)
2226   {
2227     GNUNET_SCHEDULER_cancel (c->bck_fc.poll_task);
2228     LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL BCK canceled\n");
2229   }
2230   if (NULL != c->fwd_fc.poll_msg)
2231   {
2232     GMC_cancel (c->fwd_fc.poll_msg);
2233     LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL msg FWD canceled\n");
2234   }
2235   if (NULL != c->bck_fc.poll_msg)
2236   {
2237     GMC_cancel (c->bck_fc.poll_msg);
2238     LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL msg BCK canceled\n");
2239   }
2240
2241   /* Unregister from neighbors */
2242   unregister_neighbors (c);
2243
2244   /* Delete */
2245   GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO);
2246   if (NULL != c->t)
2247     GMT_remove_connection (c->t, c);
2248
2249   if (GNUNET_NO == GMC_is_origin (c, GNUNET_YES))
2250     path_destroy (c->path);
2251
2252   GNUNET_break (GNUNET_YES ==
2253                 GNUNET_CONTAINER_multihashmap_remove (connections, &c->id, c));
2254
2255   GNUNET_free (c);
2256 }
2257
2258 /**
2259  * Get the connection ID.
2260  *
2261  * @param c Connection to get the ID from.
2262  *
2263  * @return ID of the connection.
2264  */
2265 const struct GNUNET_HashCode *
2266 GMC_get_id (const struct MeshConnection *c)
2267 {
2268   return &c->id;
2269 }
2270
2271
2272 /**
2273  * Get the connection path.
2274  *
2275  * @param c Connection to get the path from.
2276  *
2277  * @return path used by the connection.
2278  */
2279 const struct MeshPeerPath *
2280 GMC_get_path (const struct MeshConnection *c)
2281 {
2282   if (GNUNET_NO == c->destroy)
2283     return c->path;
2284   return NULL;
2285 }
2286
2287
2288 /**
2289  * Get the connection state.
2290  *
2291  * @param c Connection to get the state from.
2292  *
2293  * @return state of the connection.
2294  */
2295 enum MeshConnectionState
2296 GMC_get_state (const struct MeshConnection *c)
2297 {
2298   return c->state;
2299 }
2300
2301 /**
2302  * Get the connection tunnel.
2303  *
2304  * @param c Connection to get the tunnel from.
2305  *
2306  * @return tunnel of the connection.
2307  */
2308 struct MeshTunnel3 *
2309 GMC_get_tunnel (const struct MeshConnection *c)
2310 {
2311   return c->t;
2312 }
2313
2314
2315 /**
2316  * Get free buffer space in a connection.
2317  *
2318  * @param c Connection.
2319  * @param fwd Is query about FWD traffic?
2320  *
2321  * @return Free buffer space [0 - max_msgs_queue/max_connections]
2322  */
2323 unsigned int
2324 GMC_get_buffer (struct MeshConnection *c, int fwd)
2325 {
2326   struct MeshFlowControl *fc;
2327
2328   fc = fwd ? &c->fwd_fc : &c->bck_fc;
2329
2330   return (fc->queue_max - fc->queue_n);
2331 }
2332
2333 /**
2334  * Get how many messages have we allowed to send to us from a direction.
2335  *
2336  * @param c Connection.
2337  * @param fwd Are we asking about traffic from FWD (BCK messages)?
2338  *
2339  * @return last_ack_sent - last_pid_recv
2340  */
2341 unsigned int
2342 GMC_get_allowed (struct MeshConnection *c, int fwd)
2343 {
2344   struct MeshFlowControl *fc;
2345
2346   fc = fwd ? &c->fwd_fc : &c->bck_fc;
2347   if (GM_is_pid_bigger(fc->last_pid_recv, fc->last_ack_sent))
2348   {
2349     return 0;
2350   }
2351   return (fc->last_ack_sent - fc->last_pid_recv);
2352 }
2353
2354 /**
2355  * Get messages queued in a connection.
2356  *
2357  * @param c Connection.
2358  * @param fwd Is query about FWD traffic?
2359  *
2360  * @return Number of messages queued.
2361  */
2362 unsigned int
2363 GMC_get_qn (struct MeshConnection *c, int fwd)
2364 {
2365   struct MeshFlowControl *fc;
2366
2367   fc = fwd ? &c->fwd_fc : &c->bck_fc;
2368
2369   return fc->queue_n;
2370 }
2371
2372
2373 /**
2374  * Allow the connection to advertise a buffer of the given size.
2375  *
2376  * The connection will send an @c fwd ACK message (so: in direction !fwd)
2377  * allowing up to last_pid_recv + buffer.
2378  *
2379  * @param c Connection.
2380  * @param buffer How many more messages the connection can accept.
2381  * @param fwd Is this about FWD traffic? (The ack will go dest->root).
2382  */
2383 void
2384 GMC_allow (struct MeshConnection *c, unsigned int buffer, int fwd)
2385 {
2386   send_ack (c, buffer, fwd, GNUNET_NO);
2387 }
2388
2389
2390 /**
2391  * Notify other peers on a connection of a broken link. Mark connections
2392  * to destroy after all traffic has been sent.
2393  *
2394  * @param c Connection on which there has been a disconnection.
2395  * @param peer Peer that disconnected.
2396  */
2397 void
2398 GMC_notify_broken (struct MeshConnection *c,
2399                    struct MeshPeer *peer)
2400 {
2401   int fwd;
2402
2403   LOG (GNUNET_ERROR_TYPE_DEBUG,
2404        " notify broken on %s due to %s disconnect\n",
2405        GMC_2s (c), GMP_2s (peer));
2406
2407   fwd = peer == get_prev_hop (c);
2408
2409   if (GNUNET_YES == GMC_is_terminal (c, fwd))
2410   {
2411     /* Local shutdown, no one to notify about this. */
2412     GMC_destroy (c);
2413     return;
2414   }
2415   if (GNUNET_NO == c->destroy)
2416     send_broken (c, &my_full_id, GMP_get_id (peer), fwd);
2417
2418   /* Connection will have at least one pending message
2419    * (the one we just scheduled), so no point in checking whether to
2420    * destroy immediately. */
2421   c->destroy = GNUNET_YES;
2422   c->state = MESH_CONNECTION_DESTROYED;
2423
2424   /**
2425    * Cancel all queues, if no message is left, connection will be destroyed.
2426    */
2427   connection_cancel_queues (c, !fwd);
2428
2429   return;
2430 }
2431
2432
2433 /**
2434  * Is this peer the first one on the connection?
2435  *
2436  * @param c Connection.
2437  * @param fwd Is this about fwd traffic?
2438  *
2439  * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal.
2440  */
2441 int
2442 GMC_is_origin (struct MeshConnection *c, int fwd)
2443 {
2444   if (!fwd && c->path->length - 1 == c->own_pos )
2445     return GNUNET_YES;
2446   if (fwd && 0 == c->own_pos)
2447     return GNUNET_YES;
2448   return GNUNET_NO;
2449 }
2450
2451
2452 /**
2453  * Is this peer the last one on the connection?
2454  *
2455  * @param c Connection.
2456  * @param fwd Is this about fwd traffic?
2457  *            Note that the ROOT is the terminal for BCK traffic!
2458  *
2459  * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin.
2460  */
2461 int
2462 GMC_is_terminal (struct MeshConnection *c, int fwd)
2463 {
2464   return GMC_is_origin (c, !fwd);
2465 }
2466
2467
2468 /**
2469  * See if we are allowed to send by the next hop in the given direction.
2470  *
2471  * @param c Connection.
2472  * @param fwd Is this about fwd traffic?
2473  *
2474  * @return #GNUNET_YES in case it's OK to send.
2475  */
2476 int
2477 GMC_is_sendable (struct MeshConnection *c, int fwd)
2478 {
2479   struct MeshFlowControl *fc;
2480
2481   fc = fwd ? &c->fwd_fc : &c->bck_fc;
2482   if (GM_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
2483     return GNUNET_YES;
2484   return GNUNET_NO;
2485 }
2486
2487 /**
2488  * Sends an already built message on a connection, properly registering
2489  * all used resources.
2490  *
2491  * @param message Message to send. Function makes a copy of it.
2492  *                If message is not hop-by-hop, decrements TTL of copy.
2493  * @param c Connection on which this message is transmitted.
2494  * @param fwd Is this a fwd message?
2495  * @param cont Continuation called once message is sent. Can be NULL.
2496  * @param cont_cls Closure for @c cont.
2497  *
2498  * @return Handle to cancel the message before it's sent.
2499  *         NULL on error or if @c cont is NULL.
2500  *         Invalid on @c cont call.
2501  */
2502 struct MeshConnectionQueue *
2503 GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2504                            struct MeshConnection *c, int fwd,
2505                            GMC_sent cont, void *cont_cls)
2506 {
2507   struct MeshFlowControl *fc;
2508   struct MeshConnectionQueue *q;
2509   void *data;
2510   size_t size;
2511   uint16_t type;
2512   int droppable;
2513
2514   size = ntohs (message->size);
2515   data = GNUNET_malloc (size);
2516   memcpy (data, message, size);
2517   type = ntohs (message->type);
2518   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send %s (%u bytes) on connection %s\n",
2519               GM_m2s (type), size, GMC_2s (c));
2520
2521   fc = fwd ? &c->fwd_fc : &c->bck_fc;
2522   droppable = GNUNET_YES;
2523   switch (type)
2524   {
2525     struct GNUNET_MESH_Encrypted *emsg;
2526     struct GNUNET_MESH_KX        *kmsg;
2527     struct GNUNET_MESH_ACK       *amsg;
2528     struct GNUNET_MESH_Poll      *pmsg;
2529     struct GNUNET_MESH_ConnectionDestroy *dmsg;
2530     struct GNUNET_MESH_ConnectionBroken  *bmsg;
2531     uint32_t ttl;
2532
2533     case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED:
2534       emsg = (struct GNUNET_MESH_Encrypted *) data;
2535       ttl = ntohl (emsg->ttl);
2536       if (0 == ttl)
2537       {
2538         GNUNET_break_op (0);
2539         GNUNET_free (data);
2540         return NULL;
2541       }
2542       emsg->cid = c->id;
2543       emsg->ttl = htonl (ttl - 1);
2544       emsg->pid = htonl (fc->next_pid++);
2545       LOG (GNUNET_ERROR_TYPE_DEBUG, "  Q_N+ %p %u\n", fc, fc->queue_n);
2546       fc->queue_n++;
2547       LOG (GNUNET_ERROR_TYPE_DEBUG, "pid %u\n", ntohl (emsg->pid));
2548       LOG (GNUNET_ERROR_TYPE_DEBUG, "last pid sent %u\n", fc->last_pid_sent);
2549       LOG (GNUNET_ERROR_TYPE_DEBUG, "     ack recv %u\n", fc->last_ack_recv);
2550       if (GM_is_pid_bigger (fc->last_pid_sent + 1, fc->last_ack_recv))
2551       {
2552         GMC_start_poll (c, fwd);
2553       }
2554       break;
2555
2556     case GNUNET_MESSAGE_TYPE_MESH_KX:
2557       kmsg = (struct GNUNET_MESH_KX *) data;
2558       kmsg->cid = c->id;
2559       break;
2560
2561     case GNUNET_MESSAGE_TYPE_MESH_ACK:
2562       amsg = (struct GNUNET_MESH_ACK *) data;
2563       amsg->cid = c->id;
2564       LOG (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ntohl (amsg->ack));
2565       droppable = GNUNET_NO;
2566       break;
2567
2568     case GNUNET_MESSAGE_TYPE_MESH_POLL:
2569       pmsg = (struct GNUNET_MESH_Poll *) data;
2570       pmsg->cid = c->id;
2571       LOG (GNUNET_ERROR_TYPE_DEBUG, " poll %u\n", ntohl (pmsg->pid));
2572       droppable = GNUNET_NO;
2573       break;
2574
2575     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY:
2576       dmsg = (struct GNUNET_MESH_ConnectionDestroy *) data;
2577       dmsg->cid = c->id;
2578       dmsg->reserved = 0;
2579       break;
2580
2581     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
2582       bmsg = (struct GNUNET_MESH_ConnectionBroken *) data;
2583       bmsg->cid = c->id;
2584       bmsg->reserved = 0;
2585       break;
2586
2587     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
2588     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
2589       break;
2590
2591     default:
2592       GNUNET_break (0);
2593       GNUNET_free (data);
2594       return NULL;
2595   }
2596
2597   if (fc->queue_n > fc->queue_max && droppable)
2598   {
2599     GNUNET_STATISTICS_update (stats, "# messages dropped (buffer full)",
2600                               1, GNUNET_NO);
2601     GNUNET_break (0);
2602     LOG (GNUNET_ERROR_TYPE_DEBUG,
2603                 "queue full: %u/%u\n",
2604                 fc->queue_n, fc->queue_max);
2605     if (GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED == type)
2606     {
2607       fc->queue_n--;
2608       fc->next_pid--;
2609     }
2610     GNUNET_free (data);
2611     return NULL; /* Drop this message */
2612   }
2613
2614   LOG (GNUNET_ERROR_TYPE_DEBUG, "  C_P+ %p %u\n", c, c->pending_messages);
2615   c->pending_messages++;
2616
2617   if (NULL == cont)
2618   {
2619     (void) GMP_queue_add (get_hop (c, fwd), data, type, size, c, fwd,
2620                           &message_sent, NULL);
2621     return NULL;
2622   }
2623
2624   q = GNUNET_new (struct MeshConnectionQueue);
2625   q->q = GMP_queue_add (get_hop (c, fwd), data, type, size, c, fwd,
2626                         &message_sent, q);
2627   if (NULL == q->q)
2628   {
2629     GNUNET_break (0);
2630     GNUNET_free (data);
2631     GNUNET_free (q);
2632     return NULL;
2633   }
2634   q->cont = cont;
2635   q->cont_cls = cont_cls;
2636   return q;
2637 }
2638
2639
2640 /**
2641  * Cancel a previously sent message while it's in the queue.
2642  *
2643  * ONLY can be called before the continuation given to the send function
2644  * is called. Once the continuation is called, the message is no longer in the
2645  * queue.
2646  *
2647  * @param q Handle to the queue.
2648  */
2649 void
2650 GMC_cancel (struct MeshConnectionQueue *q)
2651 {
2652   LOG (GNUNET_ERROR_TYPE_DEBUG, "!  GMC cancel message\n");
2653
2654   /* queue destroy calls message_sent, which calls q->cont and frees q */
2655   GMP_queue_destroy (q->q, GNUNET_YES);
2656 }
2657
2658
2659 /**
2660  * Sends a CREATE CONNECTION message for a path to a peer.
2661  * Changes the connection and tunnel states if necessary.
2662  *
2663  * @param connection Connection to create.
2664  */
2665 void
2666 GMC_send_create (struct MeshConnection *connection)
2667 {
2668   enum MeshTunnel3CState state;
2669   size_t size;
2670
2671   size = sizeof (struct GNUNET_MESH_ConnectionCreate);
2672   size += connection->path->length * sizeof (struct GNUNET_PeerIdentity);
2673   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send connection create\n");
2674   GMP_queue_add (get_next_hop (connection), NULL,
2675                  GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
2676                  size, connection, GNUNET_YES, &message_sent, NULL);
2677   LOG (GNUNET_ERROR_TYPE_DEBUG, "  C_P+ %p %u (create)\n",
2678        connection, connection->pending_messages);
2679   connection->pending_messages++;
2680   state = GMT_get_cstate (connection->t);
2681   if (MESH_TUNNEL3_SEARCHING == state || MESH_TUNNEL3_NEW == state)
2682     GMT_change_cstate (connection->t, MESH_TUNNEL3_WAITING);
2683   if (MESH_CONNECTION_NEW == connection->state)
2684     connection_change_state (connection, MESH_CONNECTION_SENT);
2685 }
2686
2687
2688 /**
2689  * Send a message to all peers in this connection that the connection
2690  * is no longer valid.
2691  *
2692  * If some peer should not receive the message, it should be zero'ed out
2693  * before calling this function.
2694  *
2695  * @param c The connection whose peers to notify.
2696  */
2697 void
2698 GMC_send_destroy (struct MeshConnection *c)
2699 {
2700   struct GNUNET_MESH_ConnectionDestroy msg;
2701
2702   if (GNUNET_YES == c->destroy)
2703     return;
2704
2705   msg.header.size = htons (sizeof (msg));
2706   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY);;
2707   msg.cid = c->id;
2708   LOG (GNUNET_ERROR_TYPE_DEBUG,
2709               "  sending connection destroy for connection %s\n",
2710               GMC_2s (c));
2711
2712   if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES))
2713     GMC_send_prebuilt_message (&msg.header, c, GNUNET_YES, NULL, NULL);
2714   if (GNUNET_NO == GMC_is_terminal (c, GNUNET_NO))
2715     GMC_send_prebuilt_message (&msg.header, c, GNUNET_NO, NULL, NULL);
2716   c->destroy = GNUNET_YES;
2717   c->state = MESH_CONNECTION_DESTROYED;
2718 }
2719
2720
2721 /**
2722  * @brief Start a polling timer for the connection.
2723  *
2724  * When a neighbor does not accept more traffic on the connection it could be
2725  * caused by a simple congestion or by a lost ACK. Polling enables to check
2726  * for the lastest ACK status for a connection.
2727  *
2728  * @param c Connection.
2729  * @param fwd Should we poll in the FWD direction?
2730  */
2731 void
2732 GMC_start_poll (struct MeshConnection *c, int fwd)
2733 {
2734   struct MeshFlowControl *fc;
2735
2736   fc = fwd ? &c->fwd_fc : &c->bck_fc;
2737   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL %s requested\n",
2738        GM_f2s (fwd));
2739   if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task || NULL != fc->poll_msg)
2740   {
2741     LOG (GNUNET_ERROR_TYPE_DEBUG, " ***   not needed (%u, %p)\n",
2742          fc->poll_task, fc->poll_msg);
2743     return;
2744   }
2745   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL started on request\n");
2746   fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
2747                                                 &connection_poll,
2748                                                 fc);
2749 }
2750
2751
2752 /**
2753  * @brief Stop polling a connection for ACKs.
2754  *
2755  * Once we have enough ACKs for future traffic, polls are no longer necessary.
2756  *
2757  * @param c Connection.
2758  * @param fwd Should we stop the poll in the FWD direction?
2759  */
2760 void
2761 GMC_stop_poll (struct MeshConnection *c, int fwd)
2762 {
2763   struct MeshFlowControl *fc;
2764
2765   fc = fwd ? &c->fwd_fc : &c->bck_fc;
2766   if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
2767   {
2768     GNUNET_SCHEDULER_cancel (fc->poll_task);
2769     fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
2770   }
2771 }
2772
2773 /**
2774  * Get a (static) string for a connection.
2775  *
2776  * @param c Connection.
2777  */
2778 const char *
2779 GMC_2s (struct MeshConnection *c)
2780 {
2781   if (NULL == c)
2782     return "NULL";
2783
2784   if (NULL != c->t)
2785   {
2786     static char buf[128];
2787
2788     sprintf (buf, "%s (->%s)", GNUNET_h2s (&c->id), GMT_2s (c->t));
2789     return buf;
2790   }
2791   return GNUNET_h2s (&c->id);
2792 }