- remove deprecated tests
[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  * Send keepalive packets for a connection.
747  *
748  * @param c Connection to keep alive..
749  * @param fwd Is this a FWD keepalive? (owner -> dest).
750  */
751 static void
752 connection_keepalive (struct MeshConnection *c, int fwd)
753 {
754   struct GNUNET_MESH_ConnectionKeepAlive *msg;
755   size_t size = sizeof (struct GNUNET_MESH_ConnectionKeepAlive);
756   char cbuf[size];
757
758   LOG (GNUNET_ERROR_TYPE_DEBUG,
759        "sending %s keepalive for connection %s]\n",
760        GM_f2s (fwd), GMC_2s (c));
761
762   msg = (struct GNUNET_MESH_ConnectionKeepAlive *) cbuf;
763   msg->header.size = htons (size);
764   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE);
765   msg->cid = c->id;
766   msg->reserved = htonl (0);
767
768   GMC_send_prebuilt_message (&msg->header, c, fwd, NULL, NULL);
769 }
770
771
772 /**
773  * Send CONNECTION_{CREATE/ACK} packets for a connection.
774  *
775  * @param c Connection for which to send the message.
776  * @param fwd If #GNUNET_YES, send CREATE, otherwise send ACK.
777  */
778 static void
779 connection_recreate (struct MeshConnection *c, int fwd)
780 {
781   LOG (GNUNET_ERROR_TYPE_DEBUG, "sending connection recreate\n");
782   if (fwd)
783     GMC_send_create (c);
784   else
785     send_connection_ack (c, GNUNET_NO);
786 }
787
788
789 /**
790  * Generic connection timer management.
791  * Depending on the role of the peer in the connection will send the
792  * appropriate message (build or keepalive)
793  *
794  * @param c Conncetion to maintain.
795  * @param fwd Is FWD?
796  */
797 static void
798 connection_maintain (struct MeshConnection *c, int fwd)
799 {
800   if (MESH_TUNNEL3_SEARCHING == GMT_get_cstate (c->t))
801   {
802     /* TODO DHT GET with RO_BART */
803     return;
804   }
805   switch (c->state)
806   {
807     case MESH_CONNECTION_NEW:
808       GNUNET_break (0);
809       /* fall-through */
810     case MESH_CONNECTION_SENT:
811       connection_recreate (c, fwd);
812       break;
813     case MESH_CONNECTION_READY:
814       connection_keepalive (c, fwd);
815       break;
816     default:
817       break;
818   }
819 }
820
821
822 static void
823 connection_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
824 {
825   struct MeshConnection *c = cls;
826   struct GNUNET_TIME_Relative delay;
827
828   c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
829   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
830     return;
831
832   connection_maintain (c, GNUNET_YES);
833   delay = c->state == MESH_CONNECTION_READY ?
834           refresh_connection_time : create_connection_time;
835   c->fwd_maintenance_task = GNUNET_SCHEDULER_add_delayed (delay,
836                                                           &connection_fwd_keepalive,
837                                                           c);
838 }
839
840
841 static void
842 connection_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
843 {
844   struct MeshConnection *c = cls;
845   struct GNUNET_TIME_Relative delay;
846
847   c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
848   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
849     return;
850
851   connection_maintain (c, GNUNET_NO);
852   delay = c->state == MESH_CONNECTION_READY ?
853           refresh_connection_time : create_connection_time;
854   c->bck_maintenance_task = GNUNET_SCHEDULER_add_delayed (delay,
855                                                           &connection_bck_keepalive,
856                                                           c);
857 }
858
859
860 /**
861  * @brief Re-initiate traffic on this connection if necessary.
862  *
863  * Check if there is traffic queued towards this peer
864  * and the core transmit handle is NULL (traffic was stalled).
865  * If so, call core tmt rdy.
866  *
867  * @param c Connection on which initiate traffic.
868  * @param fwd Is this about fwd traffic?
869  */
870 static void
871 connection_unlock_queue (struct MeshConnection *c, int fwd)
872 {
873   struct MeshPeer *peer;
874
875   LOG (GNUNET_ERROR_TYPE_DEBUG,
876               "connection_unlock_queue %s on %s\n",
877               GM_f2s (fwd), GMC_2s (c));
878
879   if (GMC_is_terminal (c, fwd))
880   {
881     LOG (GNUNET_ERROR_TYPE_DEBUG, " is terminal!\n");
882     return;
883   }
884
885   peer = get_hop (c, fwd);
886   GMP_queue_unlock (peer, c);
887 }
888
889
890 /**
891  * Cancel all transmissions that belong to a certain connection.
892  *
893  * If the connection is scheduled for destruction and no more messages are left,
894  * the connection will be destroyed by the continuation call.
895  *
896  * @param c Connection which to cancel. Might be destroyed during this call.
897  * @param fwd Cancel fwd traffic?
898  */
899 static void
900 connection_cancel_queues (struct MeshConnection *c, int fwd)
901 {
902   struct MeshFlowControl *fc;
903   struct MeshPeer *peer;
904
905   LOG (GNUNET_ERROR_TYPE_DEBUG,
906        " *** Cancel %s queues for connection %s\n",
907        GM_f2s (fwd), GMC_2s (c));
908   if (NULL == c)
909   {
910     GNUNET_break (0);
911     return;
912   }
913
914   fc = fwd ? &c->fwd_fc : &c->bck_fc;
915   if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
916   {
917     GNUNET_SCHEDULER_cancel (fc->poll_task);
918     fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
919     LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Cancel POLL in ccq for fc %p\n", fc);
920   }
921   peer = get_hop (c, fwd);
922   GMP_queue_cancel (peer, c);
923 }
924
925
926 /**
927  * Function called if a connection has been stalled for a while,
928  * possibly due to a missed ACK. Poll the neighbor about its ACK status.
929  *
930  * @param cls Closure (poll ctx).
931  * @param tc TaskContext.
932  */
933 static void
934 connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
935
936
937 /**
938  * Callback called when a queued POLL message is sent.
939  *
940  * @param cls Closure (FC).
941  * @param c Connection this message was on.
942  * @param q Queue handler this call invalidates.
943  * @param type Type of message sent.
944  * @param fwd Was this a FWD going message?
945  * @param size Size of the message.
946  */
947 static void
948 poll_sent (void *cls,
949            struct MeshConnection *c,
950            struct MeshConnectionQueue *q,
951            uint16_t type, int fwd, size_t size)
952 {
953   struct MeshFlowControl *fc = cls;
954
955   if (2 == c->destroy)
956   {
957     LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL canceled on shutdown\n");
958     return;
959   }
960   LOG (GNUNET_ERROR_TYPE_DEBUG,
961        " *** POLL sent for , scheduling new one!\n");
962   fc->poll_msg = NULL;
963   fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
964   fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
965                                                 &connection_poll, fc);
966   LOG (GNUNET_ERROR_TYPE_DEBUG, " task %u\n", fc->poll_task);
967
968 }
969
970 /**
971  * Function called if a connection has been stalled for a while,
972  * possibly due to a missed ACK. Poll the neighbor about its ACK status.
973  *
974  * @param cls Closure (poll ctx).
975  * @param tc TaskContext.
976  */
977 static void
978 connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
979 {
980   struct MeshFlowControl *fc = cls;
981   struct GNUNET_MESH_Poll msg;
982   struct MeshConnection *c;
983
984   fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
985   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
986   {
987     return;
988   }
989
990   c = fc->c;
991   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Polling!\n");
992   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** connection [%s]\n", GMC_2s (c));
993   LOG (GNUNET_ERROR_TYPE_DEBUG, " ***   %s\n",
994        fc == &c->fwd_fc ? "FWD" : "BCK");
995
996   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL);
997   msg.header.size = htons (sizeof (msg));
998   msg.pid = htonl (fc->last_pid_sent);
999   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** last pid sent: %u!\n", fc->last_pid_sent);
1000   fc->poll_msg = GMC_send_prebuilt_message (&msg.header, c, fc == &c->fwd_fc,
1001                                             &poll_sent, fc);
1002 }
1003
1004
1005 /**
1006  * Timeout function due to lack of keepalive/traffic from the owner.
1007  * Destroys connection if called.
1008  *
1009  * @param cls Closure (connection to destroy).
1010  * @param tc TaskContext.
1011  */
1012 static void
1013 connection_fwd_timeout (void *cls,
1014                         const struct GNUNET_SCHEDULER_TaskContext *tc)
1015 {
1016   struct MeshConnection *c = cls;
1017
1018   c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
1019   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1020     return;
1021   LOG (GNUNET_ERROR_TYPE_DEBUG,
1022               "Connection %s[%X] FWD timed out. Destroying.\n",
1023               GMT_2s (c->t),
1024               c->id);
1025
1026   if (GMC_is_origin (c, GNUNET_YES)) /* If local, leave. */
1027     return;
1028
1029   GMC_destroy (c);
1030 }
1031
1032
1033 /**
1034  * Timeout function due to lack of keepalive/traffic from the destination.
1035  * Destroys connection if called.
1036  *
1037  * @param cls Closure (connection to destroy).
1038  * @param tc TaskContext
1039  */
1040 static void
1041 connection_bck_timeout (void *cls,
1042                         const struct GNUNET_SCHEDULER_TaskContext *tc)
1043 {
1044   struct MeshConnection *c = cls;
1045
1046   c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
1047   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1048     return;
1049
1050   LOG (GNUNET_ERROR_TYPE_DEBUG,
1051               "Connection %s[%X] FWD timed out. Destroying.\n",
1052               GMT_2s (c->t), c->id);
1053
1054   if (GMC_is_origin (c, GNUNET_NO)) /* If local, leave. */
1055     return;
1056
1057   GMC_destroy (c);
1058 }
1059
1060
1061 /**
1062  * Resets the connection timeout task, some other message has done the
1063  * task's job.
1064  * - For the first peer on the direction this means to send
1065  *   a keepalive or a path confirmation message (either create or ACK).
1066  * - For all other peers, this means to destroy the connection,
1067  *   due to lack of activity.
1068  * Starts the timeout if no timeout was running (connection just created).
1069  *
1070  * @param c Connection whose timeout to reset.
1071  * @param fwd Is this forward?
1072  *
1073  * TODO use heap to improve efficiency of scheduler.
1074  */
1075 static void
1076 connection_reset_timeout (struct MeshConnection *c, int fwd)
1077 {
1078   GNUNET_SCHEDULER_TaskIdentifier *ti;
1079   GNUNET_SCHEDULER_Task f;
1080
1081   ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task;
1082
1083   LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s reset timeout\n", GM_f2s (fwd));
1084
1085   if (GNUNET_SCHEDULER_NO_TASK != *ti)
1086     GNUNET_SCHEDULER_cancel (*ti);
1087
1088   if (GMC_is_origin (c, fwd)) /* Startpoint */
1089   {
1090     f  = fwd ? &connection_fwd_keepalive : &connection_bck_keepalive;
1091     *ti = GNUNET_SCHEDULER_add_delayed (refresh_connection_time, f, c);
1092   }
1093   else /* Relay, endpoint. */
1094   {
1095     struct GNUNET_TIME_Relative delay;
1096
1097     delay = GNUNET_TIME_relative_multiply (refresh_connection_time, 4);
1098     f  = fwd ? &connection_fwd_timeout : &connection_bck_timeout;
1099     *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c);
1100   }
1101 }
1102
1103
1104 /**
1105  * Add the connection to the list of both neighbors.
1106  *
1107  * @param c Connection.
1108  *
1109  * @return #GNUNET_OK if everything went fine
1110  *         #GNUNET_SYSERR if the was an error and @c c is malformed.
1111  */
1112 static int
1113 register_neighbors (struct MeshConnection *c)
1114 {
1115   struct MeshPeer *next_peer;
1116   struct MeshPeer *prev_peer;
1117
1118   next_peer = get_next_hop (c);
1119   prev_peer = get_prev_hop (c);
1120
1121   if (GNUNET_NO == GMP_is_neighbor (next_peer)
1122       || GNUNET_NO == GMP_is_neighbor (prev_peer))
1123     return GNUNET_SYSERR;
1124
1125   GMP_add_connection (next_peer, c);
1126   GMP_add_connection (prev_peer, c);
1127
1128   return GNUNET_OK;
1129 }
1130
1131
1132 /**
1133  * Remove the connection from the list of both neighbors.
1134  *
1135  * @param c Connection.
1136  */
1137 static void
1138 unregister_neighbors (struct MeshConnection *c)
1139 {
1140   struct MeshPeer *peer;
1141
1142   peer = get_next_hop (c);
1143   GMP_remove_connection (peer, c);
1144
1145   peer = get_prev_hop (c);
1146   GMP_remove_connection (peer, c);
1147
1148 }
1149
1150
1151 /**
1152  * Bind the connection to the peer and the tunnel to that peer.
1153  *
1154  * If the peer has no tunnel, create one. Update tunnel and connection
1155  * data structres to reflect new status.
1156  *
1157  * @param c Connection.
1158  * @param peer Peer.
1159  */
1160 static void
1161 add_to_peer (struct MeshConnection *c, struct MeshPeer *peer)
1162 {
1163   GMP_add_tunnel (peer);
1164   c->t = GMP_get_tunnel (peer);
1165   GMT_add_connection (c->t, c);
1166 }
1167
1168 /******************************************************************************/
1169 /********************************    API    ***********************************/
1170 /******************************************************************************/
1171
1172 /**
1173  * Core handler for connection creation.
1174  *
1175  * @param cls Closure (unused).
1176  * @param peer Sender (neighbor).
1177  * @param message Message.
1178  *
1179  * @return GNUNET_OK to keep the connection open,
1180  *         GNUNET_SYSERR to close it (signal serious error)
1181  */
1182 int
1183 GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
1184                    const struct GNUNET_MessageHeader *message)
1185 {
1186   struct GNUNET_MESH_ConnectionCreate *msg;
1187   struct GNUNET_PeerIdentity *id;
1188   struct GNUNET_HashCode *cid;
1189   struct MeshPeerPath *path;
1190   struct MeshPeer *dest_peer;
1191   struct MeshPeer *orig_peer;
1192   struct MeshConnection *c;
1193   unsigned int own_pos;
1194   uint16_t size;
1195   uint16_t i;
1196
1197   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1198   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a connection create msg\n");
1199
1200   /* Check size */
1201   size = ntohs (message->size);
1202   if (size < sizeof (struct GNUNET_MESH_ConnectionCreate))
1203   {
1204     GNUNET_break_op (0);
1205     return GNUNET_OK;
1206   }
1207
1208   /* Calculate hops */
1209   size -= sizeof (struct GNUNET_MESH_ConnectionCreate);
1210   if (size % sizeof (struct GNUNET_PeerIdentity))
1211   {
1212     GNUNET_break_op (0);
1213     return GNUNET_OK;
1214   }
1215   size /= sizeof (struct GNUNET_PeerIdentity);
1216   if (1 > size)
1217   {
1218     GNUNET_break_op (0);
1219     return GNUNET_OK;
1220   }
1221   LOG (GNUNET_ERROR_TYPE_DEBUG, "    path has %u hops.\n", size);
1222
1223   /* Get parameters */
1224   msg = (struct GNUNET_MESH_ConnectionCreate *) message;
1225   cid = &msg->cid;
1226   id = (struct GNUNET_PeerIdentity *) &msg[1];
1227   LOG (GNUNET_ERROR_TYPE_DEBUG,
1228               "    connection %s (%s).\n",
1229               GNUNET_h2s (cid), GNUNET_i2s (id));
1230
1231   /* Create connection */
1232   c = connection_get (cid);
1233   if (NULL == c)
1234   {
1235     /* Create path */
1236     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Creating path...\n");
1237     path = path_new (size);
1238     own_pos = 0;
1239     for (i = 0; i < size; i++)
1240     {
1241       LOG (GNUNET_ERROR_TYPE_DEBUG, "  ... adding %s\n",
1242                   GNUNET_i2s (&id[i]));
1243       path->peers[i] = GNUNET_PEER_intern (&id[i]);
1244       if (path->peers[i] == myid)
1245         own_pos = i;
1246     }
1247     if (own_pos == 0 && path->peers[own_pos] != myid)
1248     {
1249       /* create path: self not found in path through self */
1250       GNUNET_break_op (0);
1251       path_destroy (path);
1252       return GNUNET_OK;
1253     }
1254     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Own position: %u\n", own_pos);
1255     GMP_add_path_to_all (path, GNUNET_NO);
1256         LOG (GNUNET_ERROR_TYPE_DEBUG, "  Creating connection\n");
1257     c = GMC_new (cid, NULL, path_duplicate (path), own_pos);
1258     if (NULL == c)
1259     {
1260       path_destroy (path);
1261       return GNUNET_OK;
1262     }
1263     connection_reset_timeout (c, GNUNET_YES);
1264   }
1265   else
1266   {
1267     path = path_duplicate (c->path);
1268   }
1269   if (MESH_CONNECTION_NEW == c->state)
1270     connection_change_state (c, MESH_CONNECTION_SENT);
1271
1272   /* Remember peers */
1273   dest_peer = GMP_get (&id[size - 1]);
1274   orig_peer = GMP_get (&id[0]);
1275
1276   /* Is it a connection to us? */
1277   if (c->own_pos == size - 1)
1278   {
1279     LOG (GNUNET_ERROR_TYPE_DEBUG, "  It's for us!\n");
1280     GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_YES);
1281
1282     add_to_peer (c, orig_peer);
1283     if (MESH_TUNNEL3_NEW == GMT_get_cstate (c->t))
1284       GMT_change_cstate (c->t,  MESH_TUNNEL3_WAITING);
1285
1286     send_connection_ack (c, GNUNET_NO);
1287     if (MESH_CONNECTION_SENT == c->state)
1288       connection_change_state (c, MESH_CONNECTION_ACK);
1289
1290     /* Keep tunnel alive in direction dest->owner*/
1291     c->bck_maintenance_task =
1292       GNUNET_SCHEDULER_add_delayed (create_connection_time,
1293                                     &connection_bck_keepalive, c);
1294   }
1295   else
1296   {
1297     /* It's for somebody else! Retransmit. */
1298     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Retransmitting.\n");
1299     GMP_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
1300     GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_NO);
1301     GMC_send_prebuilt_message (message, c, GNUNET_YES, NULL, NULL);
1302   }
1303   path_destroy (path);
1304   return GNUNET_OK;
1305 }
1306
1307
1308 /**
1309  * Core handler for path confirmations.
1310  *
1311  * @param cls closure
1312  * @param message message
1313  * @param peer peer identity this notification is about
1314  *
1315  * @return GNUNET_OK to keep the connection open,
1316  *         GNUNET_SYSERR to close it (signal serious error)
1317  */
1318 int
1319 GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer,
1320                     const struct GNUNET_MessageHeader *message)
1321 {
1322   struct GNUNET_MESH_ConnectionACK *msg;
1323   struct MeshConnection *c;
1324   struct MeshPeerPath *p;
1325   struct MeshPeer *pi;
1326   enum MeshConnectionState oldstate;
1327   int fwd;
1328
1329   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1330   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a connection ACK msg\n");
1331   msg = (struct GNUNET_MESH_ConnectionACK *) message;
1332   LOG (GNUNET_ERROR_TYPE_DEBUG, "  on connection %s\n",
1333               GNUNET_h2s (&msg->cid));
1334   c = connection_get (&msg->cid);
1335   if (NULL == c)
1336   {
1337     GNUNET_STATISTICS_update (stats, "# control on unknown connection",
1338                               1, GNUNET_NO);
1339     LOG (GNUNET_ERROR_TYPE_DEBUG, "  don't know the connection!\n");
1340     return GNUNET_OK;
1341   }
1342
1343   oldstate = c->state;
1344   LOG (GNUNET_ERROR_TYPE_DEBUG, "  via peer %s\n", GNUNET_i2s (peer));
1345   pi = GMP_get (peer);
1346   if (get_next_hop (c) == pi)
1347   {
1348     LOG (GNUNET_ERROR_TYPE_DEBUG, "  SYNACK\n");
1349     fwd = GNUNET_NO;
1350     if (MESH_CONNECTION_SENT == oldstate)
1351       connection_change_state (c, MESH_CONNECTION_ACK);
1352   }
1353   else if (get_prev_hop (c) == pi)
1354   {
1355     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ACK\n");
1356     fwd = GNUNET_YES;
1357     connection_change_state (c, MESH_CONNECTION_READY);
1358   }
1359   else
1360   {
1361     GNUNET_break_op (0);
1362     return GNUNET_OK;
1363   }
1364
1365   connection_reset_timeout (c, fwd);
1366
1367   /* Add path to peers? */
1368   p = c->path;
1369   if (NULL != p)
1370   {
1371     GMP_add_path_to_all (p, GNUNET_YES);
1372   }
1373   else
1374   {
1375     GNUNET_break (0);
1376   }
1377
1378   /* Message for us as creator? */
1379   if (GMC_is_origin (c, GNUNET_YES))
1380   {
1381     if (GNUNET_NO != fwd)
1382     {
1383       GNUNET_break_op (0);
1384       return GNUNET_OK;
1385     }
1386     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Connection (SYN)ACK for us!\n");
1387
1388     /* If just created, cancel the short timeout and start a long one */
1389     if (MESH_CONNECTION_SENT == oldstate)
1390       connection_reset_timeout (c, GNUNET_YES);
1391
1392     /* Change connection state */
1393     connection_change_state (c, MESH_CONNECTION_READY);
1394     send_connection_ack (c, GNUNET_YES);
1395
1396     /* Change tunnel state, trigger KX */
1397     if (MESH_TUNNEL3_WAITING == GMT_get_cstate (c->t))
1398       GMT_change_cstate (c->t, MESH_TUNNEL3_READY);
1399
1400     return GNUNET_OK;
1401   }
1402
1403   /* Message for us as destination? */
1404   if (GMC_is_terminal (c, GNUNET_YES))
1405   {
1406     if (GNUNET_YES != fwd)
1407     {
1408       GNUNET_break_op (0);
1409       return GNUNET_OK;
1410     }
1411     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Connection ACK for us!\n");
1412
1413     /* If just created, cancel the short timeout and start a long one */
1414     if (MESH_CONNECTION_ACK == oldstate)
1415       connection_reset_timeout (c, GNUNET_NO);
1416
1417     /* Change tunnel state */
1418     if (MESH_TUNNEL3_WAITING == GMT_get_cstate (c->t))
1419       GMT_change_cstate (c->t, MESH_TUNNEL3_READY);
1420
1421     return GNUNET_OK;
1422   }
1423
1424   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
1425   GMC_send_prebuilt_message (message, c, fwd, NULL, NULL);
1426   return GNUNET_OK;
1427 }
1428
1429
1430 /**
1431  * Core handler for notifications of broken paths
1432  *
1433  * @param cls Closure (unused).
1434  * @param id Peer identity of sending neighbor.
1435  * @param message Message.
1436  *
1437  * @return GNUNET_OK to keep the connection open,
1438  *         GNUNET_SYSERR to close it (signal serious error)
1439  */
1440 int
1441 GMC_handle_broken (void* cls,
1442                    const struct GNUNET_PeerIdentity* id,
1443                    const struct GNUNET_MessageHeader* message)
1444 {
1445   struct GNUNET_MESH_ConnectionBroken *msg;
1446   struct MeshConnection *c;
1447   int fwd;
1448
1449   LOG (GNUNET_ERROR_TYPE_DEBUG,
1450               "Received a CONNECTION BROKEN msg from %s\n", GNUNET_i2s (id));
1451   msg = (struct GNUNET_MESH_ConnectionBroken *) message;
1452   LOG (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
1453               GNUNET_i2s (&msg->peer1));
1454   LOG (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
1455               GNUNET_i2s (&msg->peer2));
1456   c = connection_get (&msg->cid);
1457   if (NULL == c)
1458   {
1459     GNUNET_break_op (0);
1460     return GNUNET_OK;
1461   }
1462
1463   fwd = is_fwd (c, id);
1464   connection_cancel_queues (c, !fwd);
1465   if (GMC_is_terminal (c, fwd))
1466   {
1467     if (0 < c->pending_messages)
1468       c->destroy = GNUNET_YES;
1469     else
1470       GMC_destroy (c);
1471   }
1472   else
1473   {
1474     GMC_send_prebuilt_message (message, c, fwd, NULL, NULL);
1475     c->destroy = GNUNET_YES;
1476   }
1477
1478   return GNUNET_OK;
1479
1480 }
1481
1482
1483 /**
1484  * Core handler for tunnel destruction
1485  *
1486  * @param cls Closure (unused).
1487  * @param peer Peer identity of sending neighbor.
1488  * @param message Message.
1489  *
1490  * @return GNUNET_OK to keep the connection open,
1491  *         GNUNET_SYSERR to close it (signal serious error)
1492  */
1493 int
1494 GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
1495                     const struct GNUNET_MessageHeader *message)
1496 {
1497   struct GNUNET_MESH_ConnectionDestroy *msg;
1498   struct MeshConnection *c;
1499   int fwd;
1500
1501   msg = (struct GNUNET_MESH_ConnectionDestroy *) message;
1502   LOG (GNUNET_ERROR_TYPE_DEBUG,
1503               "Got a CONNECTION DESTROY message from %s\n",
1504               GNUNET_i2s (peer));
1505   LOG (GNUNET_ERROR_TYPE_DEBUG,
1506               "  for connection %s\n",
1507               GNUNET_h2s (&msg->cid));
1508   c = connection_get (&msg->cid);
1509   if (NULL == c)
1510   {
1511     /* Probably already got the message from another path,
1512      * destroyed the tunnel and retransmitted to children.
1513      * Safe to ignore.
1514      */
1515     GNUNET_STATISTICS_update (stats, "# control on unknown tunnel",
1516                               1, GNUNET_NO);
1517     LOG (GNUNET_ERROR_TYPE_DEBUG, "  connection unknown: already destroyed?\n");
1518     return GNUNET_OK;
1519   }
1520   fwd = is_fwd (c, peer);
1521   if (GNUNET_SYSERR == fwd)
1522   {
1523     GNUNET_break_op (0);
1524     return GNUNET_OK;
1525   }
1526   GMC_send_prebuilt_message (message, c, fwd, NULL, NULL);
1527   c->destroy = GNUNET_YES;
1528   c->state = MESH_CONNECTION_DESTROYED;
1529
1530   return GNUNET_OK;
1531 }
1532
1533 /**
1534  * Generic handler for mesh network encrypted traffic.
1535  *
1536  * @param peer Peer identity this notification is about.
1537  * @param msg Encrypted message.
1538  *
1539  * @return GNUNET_OK to keep the connection open,
1540  *         GNUNET_SYSERR to close it (signal serious error)
1541  */
1542 static int
1543 handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer,
1544                        const struct GNUNET_MESH_Encrypted *msg)
1545 {
1546   struct MeshConnection *c;
1547   struct MeshPeer *neighbor;
1548   struct MeshFlowControl *fc;
1549   GNUNET_PEER_Id peer_id;
1550   uint32_t pid;
1551   uint32_t ttl;
1552   uint16_t type;
1553   size_t size;
1554   int fwd;
1555
1556   /* Check size */
1557   size = ntohs (msg->header.size);
1558   if (size <
1559       sizeof (struct GNUNET_MESH_Encrypted) +
1560       sizeof (struct GNUNET_MessageHeader))
1561   {
1562     GNUNET_break_op (0);
1563     return GNUNET_OK;
1564   }
1565   type = ntohs (msg->header.type);
1566   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1567   LOG (GNUNET_ERROR_TYPE_DEBUG, "got a %s message (#%u) from %s\n",
1568        GM_m2s (type), ntohl (msg->pid), GNUNET_i2s (peer));
1569
1570   /* Check connection */
1571   c = connection_get (&msg->cid);
1572   if (NULL == c)
1573   {
1574     GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
1575     LOG (GNUNET_ERROR_TYPE_DEBUG,
1576          "WARNING connection %s unknown\n",
1577          GNUNET_h2s (&msg->cid));
1578     return GNUNET_OK;
1579   }
1580
1581   /* Check if origin is as expected */
1582   neighbor = get_prev_hop (c);
1583   peer_id = GNUNET_PEER_search (peer);
1584   if (peer_id == GMP_get_short_id (neighbor))
1585   {
1586     fwd = GNUNET_YES;
1587   }
1588   else
1589   {
1590     neighbor = get_next_hop (c);
1591     if (peer_id == GMP_get_short_id (neighbor))
1592     {
1593       fwd = GNUNET_NO;
1594     }
1595     else
1596     {
1597       /* Unexpected peer sending traffic on a connection. */
1598       GNUNET_break_op (0);
1599       return GNUNET_OK;
1600     }
1601   }
1602
1603   /* Check PID */
1604   fc = fwd ? &c->bck_fc : &c->fwd_fc;
1605   pid = ntohl (msg->pid);
1606   if (GM_is_pid_bigger (pid, fc->last_ack_sent))
1607   {
1608     GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
1609     LOG (GNUNET_ERROR_TYPE_DEBUG,
1610                 "WARNING Received PID %u, (prev %u), ACK %u\n",
1611                 pid, fc->last_pid_recv, fc->last_ack_sent);
1612     return GNUNET_OK;
1613   }
1614   if (GNUNET_NO == GM_is_pid_bigger (pid, fc->last_pid_recv))
1615   {
1616     GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO);
1617     LOG (GNUNET_ERROR_TYPE_DEBUG,
1618                 " Pid %u not expected (%u+), dropping!\n",
1619                 pid, fc->last_pid_recv + 1);
1620     return GNUNET_OK;
1621   }
1622   if (MESH_CONNECTION_SENT == c->state || MESH_CONNECTION_ACK == c->state)
1623     connection_change_state (c, MESH_CONNECTION_READY);
1624   connection_reset_timeout (c, fwd);
1625   fc->last_pid_recv = pid;
1626
1627   /* Is this message for us? */
1628   if (GMC_is_terminal (c, fwd))
1629   {
1630     /* TODO signature verification */
1631     LOG (GNUNET_ERROR_TYPE_DEBUG, "  message for us!\n");
1632     GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
1633
1634     if (NULL == c->t)
1635     {
1636       GNUNET_break (0);
1637       return GNUNET_OK;
1638     }
1639     fc->last_pid_recv = pid;
1640     GMT_handle_encrypted (c->t, msg);
1641     GMC_send_ack (c, fwd, GNUNET_NO);
1642     return GNUNET_OK;
1643   }
1644
1645   /* Message not for us: forward to next hop */
1646   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
1647   ttl = ntohl (msg->ttl);
1648   LOG (GNUNET_ERROR_TYPE_DEBUG, "   ttl: %u\n", ttl);
1649   if (ttl == 0)
1650   {
1651     GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
1652     LOG (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
1653     GMC_send_ack (c, fwd, GNUNET_NO);
1654     return GNUNET_OK;
1655   }
1656
1657   GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
1658   GMC_send_prebuilt_message (&msg->header, c, fwd, NULL, NULL);
1659
1660   return GNUNET_OK;
1661 }
1662
1663 /**
1664  * Generic handler for mesh network encrypted traffic.
1665  *
1666  * @param peer Peer identity this notification is about.
1667  * @param msg Encrypted message.
1668  *
1669  * @return GNUNET_OK to keep the connection open,
1670  *         GNUNET_SYSERR to close it (signal serious error)
1671  */
1672 static int
1673 handle_mesh_kx (const struct GNUNET_PeerIdentity *peer,
1674                 const struct GNUNET_MESH_KX *msg)
1675 {
1676   struct MeshConnection *c;
1677   struct MeshPeer *neighbor;
1678   GNUNET_PEER_Id peer_id;
1679   size_t size;
1680   uint16_t type;
1681   int fwd;
1682
1683   /* Check size */
1684   size = ntohs (msg->header.size);
1685   if (size <
1686       sizeof (struct GNUNET_MESH_Encrypted) +
1687       sizeof (struct GNUNET_MessageHeader))
1688   {
1689     GNUNET_break_op (0);
1690     return GNUNET_OK;
1691   }
1692   type = ntohs (msg->header.type);
1693   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1694   LOG (GNUNET_ERROR_TYPE_DEBUG, "got a %s message from %s\n",
1695               GM_m2s (type), GNUNET_i2s (peer));
1696
1697   /* Check connection */
1698   c = connection_get (&msg->cid);
1699   if (NULL == c)
1700   {
1701     GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
1702     LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING connection unknown\n");
1703     return GNUNET_OK;
1704   }
1705
1706   /* Check if origin is as expected */
1707   neighbor = get_prev_hop (c);
1708   peer_id = GNUNET_PEER_search (peer);
1709   if (peer_id == GMP_get_short_id (neighbor))
1710   {
1711     fwd = GNUNET_YES;
1712   }
1713   else
1714   {
1715     neighbor = get_next_hop (c);
1716     if (peer_id == GMP_get_short_id (neighbor))
1717     {
1718       fwd = GNUNET_NO;
1719     }
1720     else
1721     {
1722       /* Unexpected peer sending traffic on a connection. */
1723       GNUNET_break_op (0);
1724       return GNUNET_OK;
1725     }
1726   }
1727
1728   /* Count as connection confirmation. */
1729   if (MESH_CONNECTION_SENT == c->state || MESH_CONNECTION_ACK == c->state)
1730     connection_change_state (c, MESH_CONNECTION_READY);
1731   connection_reset_timeout (c, fwd);
1732   if (NULL != c->t)
1733   {
1734     if (MESH_TUNNEL3_WAITING == GMT_get_cstate (c->t))
1735       GMT_change_cstate (c->t, MESH_TUNNEL3_READY);
1736   }
1737
1738   /* Is this message for us? */
1739   if (GMC_is_terminal (c, fwd))
1740   {
1741     LOG (GNUNET_ERROR_TYPE_DEBUG, "  message for us!\n");
1742     GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
1743     if (NULL == c->t)
1744     {
1745       GNUNET_break (0);
1746       return GNUNET_OK;
1747     }
1748     GMT_handle_kx (c->t, &msg[1].header);
1749     return GNUNET_OK;
1750   }
1751
1752   /* Message not for us: forward to next hop */
1753   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
1754   GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
1755   GMC_send_prebuilt_message (&msg->header, c, fwd, NULL, NULL);
1756
1757   return GNUNET_OK;
1758 }
1759
1760
1761 /**
1762  * Core handler for encrypted mesh network traffic (channel mgmt, data).
1763  *
1764  * @param cls Closure (unused).
1765  * @param message Message received.
1766  * @param peer Peer who sent the message.
1767  *
1768  * @return GNUNET_OK to keep the connection open,
1769  *         GNUNET_SYSERR to close it (signal serious error)
1770  */
1771 int
1772 GMC_handle_encrypted (void *cls, const struct GNUNET_PeerIdentity *peer,
1773                       const struct GNUNET_MessageHeader *message)
1774 {
1775   return handle_mesh_encrypted (peer,
1776                                 (struct GNUNET_MESH_Encrypted *)message);
1777 }
1778
1779
1780 /**
1781  * Core handler for key exchange traffic (ephemeral key, ping, pong).
1782  *
1783  * @param cls Closure (unused).
1784  * @param message Message received.
1785  * @param peer Peer who sent the message.
1786  *
1787  * @return GNUNET_OK to keep the connection open,
1788  *         GNUNET_SYSERR to close it (signal serious error)
1789  */
1790 int
1791 GMC_handle_kx (void *cls, const struct GNUNET_PeerIdentity *peer,
1792                const struct GNUNET_MessageHeader *message)
1793 {
1794   return handle_mesh_kx (peer,
1795                          (struct GNUNET_MESH_KX *) message);
1796 }
1797
1798
1799 /**
1800  * Core handler for mesh network traffic point-to-point acks.
1801  *
1802  * @param cls closure
1803  * @param message message
1804  * @param peer peer identity this notification is about
1805  *
1806  * @return GNUNET_OK to keep the connection open,
1807  *         GNUNET_SYSERR to close it (signal serious error)
1808  */
1809 int
1810 GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
1811                 const struct GNUNET_MessageHeader *message)
1812 {
1813   struct GNUNET_MESH_ACK *msg;
1814   struct MeshConnection *c;
1815   struct MeshFlowControl *fc;
1816   GNUNET_PEER_Id id;
1817   uint32_t ack;
1818   int fwd;
1819
1820   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1821   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
1822               GNUNET_i2s (peer));
1823   msg = (struct GNUNET_MESH_ACK *) message;
1824
1825   c = connection_get (&msg->cid);
1826
1827   if (NULL == c)
1828   {
1829     GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1,
1830                               GNUNET_NO);
1831     return GNUNET_OK;
1832   }
1833
1834   /* Is this a forward or backward ACK? */
1835   id = GNUNET_PEER_search (peer);
1836   if (GMP_get_short_id (get_next_hop (c)) == id)
1837   {
1838     LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
1839     fc = &c->fwd_fc;
1840     fwd = GNUNET_YES;
1841   }
1842   else if (GMP_get_short_id (get_prev_hop (c)) == id)
1843   {
1844     LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK ACK\n");
1845     fc = &c->bck_fc;
1846     fwd = GNUNET_NO;
1847   }
1848   else
1849   {
1850     GNUNET_break_op (0);
1851     return GNUNET_OK;
1852   }
1853
1854   ack = ntohl (msg->ack);
1855   LOG (GNUNET_ERROR_TYPE_DEBUG, "  ACK %u (was %u)\n",
1856               ack, fc->last_ack_recv);
1857   if (GM_is_pid_bigger (ack, fc->last_ack_recv))
1858     fc->last_ack_recv = ack;
1859
1860   /* Cancel polling if the ACK is big enough. */
1861   if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task &&
1862       GM_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
1863   {
1864     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Cancel poll\n");
1865     GNUNET_SCHEDULER_cancel (fc->poll_task);
1866     fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
1867     fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
1868   }
1869
1870   connection_unlock_queue (c, fwd);
1871
1872   return GNUNET_OK;
1873 }
1874
1875
1876 /**
1877  * Core handler for mesh network traffic point-to-point ack polls.
1878  *
1879  * @param cls closure
1880  * @param message message
1881  * @param peer peer identity this notification is about
1882  *
1883  * @return GNUNET_OK to keep the connection open,
1884  *         GNUNET_SYSERR to close it (signal serious error)
1885  */
1886 int
1887 GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
1888                  const struct GNUNET_MessageHeader *message)
1889 {
1890   struct GNUNET_MESH_Poll *msg;
1891   struct MeshConnection *c;
1892   struct MeshFlowControl *fc;
1893   GNUNET_PEER_Id id;
1894   uint32_t pid;
1895   int fwd;
1896
1897   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1898   LOG (GNUNET_ERROR_TYPE_DEBUG,
1899        "Got a POLL packet from %s!\n",
1900        GNUNET_i2s (peer));
1901
1902   msg = (struct GNUNET_MESH_Poll *) message;
1903
1904   c = connection_get (&msg->cid);
1905
1906   if (NULL == c)
1907   {
1908     GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
1909                               GNUNET_NO);
1910     GNUNET_break_op (0);
1911     return GNUNET_OK;
1912   }
1913
1914   /* Is this a forward or backward ACK?
1915    * Note: a poll should never be needed in a loopback case,
1916    * since there is no possiblility of packet loss there, so
1917    * this way of discerining FWD/BCK should not be a problem.
1918    */
1919   id = GNUNET_PEER_search (peer);
1920   if (GMP_get_short_id (get_next_hop (c)) == id)
1921   {
1922     LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD FC\n");
1923     fc = &c->fwd_fc;
1924   }
1925   else if (GMP_get_short_id (get_prev_hop (c)) == id)
1926   {
1927     LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK FC\n");
1928     fc = &c->bck_fc;
1929   }
1930   else
1931   {
1932     GNUNET_break_op (0);
1933     return GNUNET_OK;
1934   }
1935
1936   pid = ntohl (msg->pid);
1937   LOG (GNUNET_ERROR_TYPE_DEBUG, "  PID %u, OLD %u\n", pid, fc->last_pid_recv);
1938   fc->last_pid_recv = pid;
1939   fwd = fc == &c->bck_fc;
1940   GMC_send_ack (c, fwd, GNUNET_YES);
1941
1942   return GNUNET_OK;
1943 }
1944
1945
1946 /**
1947  * Core handler for mesh keepalives.
1948  *
1949  * @param cls closure
1950  * @param message message
1951  * @param peer peer identity this notification is about
1952  * @return GNUNET_OK to keep the connection open,
1953  *         GNUNET_SYSERR to close it (signal serious error)
1954  *
1955  * TODO: Check who we got this from, to validate route.
1956  */
1957 int
1958 GMC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
1959                       const struct GNUNET_MessageHeader *message)
1960 {
1961   struct GNUNET_MESH_ConnectionKeepAlive *msg;
1962   struct MeshConnection *c;
1963   struct MeshPeer *neighbor;
1964   GNUNET_PEER_Id peer_id;
1965   int fwd;
1966
1967   msg = (struct GNUNET_MESH_ConnectionKeepAlive *) message;
1968   LOG (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
1969               GNUNET_i2s (peer));
1970
1971   c = connection_get (&msg->cid);
1972   if (NULL == c)
1973   {
1974     GNUNET_STATISTICS_update (stats, "# keepalive on unknown connection", 1,
1975                               GNUNET_NO);
1976     return GNUNET_OK;
1977   }
1978
1979   /* Check if origin is as expected TODO refactor and reuse */
1980   peer_id = GNUNET_PEER_search (peer);
1981   neighbor = get_prev_hop (c);
1982   if (peer_id == GMP_get_short_id (neighbor))
1983   {
1984     fwd = GNUNET_YES;
1985   }
1986   else
1987   {
1988     neighbor = get_next_hop (c);
1989     if (peer_id == GMP_get_short_id (neighbor))
1990     {
1991       fwd = GNUNET_NO;
1992     }
1993     else
1994     {
1995       GNUNET_break_op (0);
1996       return GNUNET_OK;
1997     }
1998   }
1999
2000   connection_change_state (c, MESH_CONNECTION_READY);
2001   connection_reset_timeout (c, fwd);
2002
2003   if (GMC_is_terminal (c, fwd))
2004     return GNUNET_OK;
2005
2006   GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
2007   GMC_send_prebuilt_message (message, c, fwd, NULL, NULL);
2008
2009   return GNUNET_OK;
2010 }
2011
2012
2013 /**
2014  * Send an ACK on the appropriate connection/channel, depending on
2015  * the direction and the position of the peer.
2016  *
2017  * @param c Which connection to send the hop-by-hop ACK.
2018  * @param fwd Is this a fwd ACK? (will go dest->root).
2019  * @param force Send the ACK even if suboptimal (e.g. requested by POLL).
2020  */
2021 void
2022 GMC_send_ack (struct MeshConnection *c, int fwd, int force)
2023 {
2024   unsigned int buffer;
2025
2026   LOG (GNUNET_ERROR_TYPE_DEBUG,
2027        "GMC send %s ACK on %s\n",
2028        GM_f2s (fwd), GMC_2s (c));
2029
2030   if (NULL == c)
2031   {
2032     GNUNET_break (0);
2033     return;
2034   }
2035
2036   if (GNUNET_NO != c->destroy)
2037   {
2038     LOG (GNUNET_ERROR_TYPE_DEBUG, "  being destroyed, why bother...\n");
2039     return;
2040   }
2041
2042   /* Get available buffer space */
2043   if (GMC_is_terminal (c, fwd))
2044   {
2045     LOG (GNUNET_ERROR_TYPE_DEBUG, "  getting from all channels\n");
2046     buffer = GMT_get_channels_buffer (c->t);
2047   }
2048   else
2049   {
2050     LOG (GNUNET_ERROR_TYPE_DEBUG, "  getting from one connection\n");
2051     buffer = GMC_get_buffer (c, fwd);
2052   }
2053   LOG (GNUNET_ERROR_TYPE_DEBUG, "  buffer available: %u\n", buffer);
2054   if (0 == buffer && GNUNET_NO == force)
2055     return;
2056
2057   /* Send available buffer space */
2058   if (GMC_is_origin (c, fwd))
2059   {
2060     GNUNET_assert (NULL != c->t);
2061     LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on channels...\n");
2062     GMT_unchoke_channels (c->t);
2063   }
2064   else
2065   {
2066     LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on connection\n");
2067     send_ack (c, buffer, fwd, force);
2068   }
2069 }
2070
2071
2072 /**
2073  * Initialize the connections subsystem
2074  *
2075  * @param c Configuration handle.
2076  */
2077 void
2078 GMC_init (const struct GNUNET_CONFIGURATION_Handle *c)
2079 {
2080   LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
2081   if (GNUNET_OK !=
2082       GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE",
2083                                              &max_msgs_queue))
2084   {
2085     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
2086                                "MESH", "MAX_MSGS_QUEUE", "MISSING");
2087     GNUNET_SCHEDULER_shutdown ();
2088     return;
2089   }
2090
2091   if (GNUNET_OK !=
2092       GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_CONNECTIONS",
2093                                              &max_connections))
2094   {
2095     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
2096                                "MESH", "MAX_CONNECTIONS", "MISSING");
2097     GNUNET_SCHEDULER_shutdown ();
2098     return;
2099   }
2100
2101   if (GNUNET_OK !=
2102       GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_CONNECTION_TIME",
2103                                            &refresh_connection_time))
2104   {
2105     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
2106                                "MESH", "REFRESH_CONNECTION_TIME", "MISSING");
2107     GNUNET_SCHEDULER_shutdown ();
2108     return;
2109   }
2110   create_connection_time = GNUNET_TIME_UNIT_SECONDS;
2111   connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES);
2112 }
2113
2114
2115 /**
2116  * Destroy each connection on shutdown.
2117  *
2118  * @param cls Closure (unused).
2119  * @param key Current key code (CID, unused).
2120  * @param value Value in the hash map (connection)
2121  *
2122  * @return #GNUNET_YES, because we should continue to iterate,
2123  */
2124 static int
2125 shutdown_iterator (void *cls,
2126                    const struct GNUNET_HashCode *key,
2127                    void *value)
2128 {
2129   struct MeshConnection *c = value;
2130
2131   GMC_destroy (c);
2132   return GNUNET_YES;
2133 }
2134
2135
2136 /**
2137  * Shut down the connections subsystem.
2138  */
2139 void
2140 GMC_shutdown (void)
2141 {
2142   GNUNET_CONTAINER_multihashmap_iterate (connections, &shutdown_iterator, NULL);
2143   GNUNET_CONTAINER_multihashmap_destroy (connections);
2144   connections = NULL;
2145 }
2146
2147
2148 struct MeshConnection *
2149 GMC_new (const struct GNUNET_HashCode *cid,
2150          struct MeshTunnel3 *t,
2151          struct MeshPeerPath *p,
2152          unsigned int own_pos)
2153 {
2154   struct MeshConnection *c;
2155
2156   c = GNUNET_new (struct MeshConnection);
2157   c->id = *cid;
2158   GNUNET_CONTAINER_multihashmap_put (connections, &c->id, c,
2159                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
2160   fc_init (&c->fwd_fc);
2161   fc_init (&c->bck_fc);
2162   c->fwd_fc.c = c;
2163   c->bck_fc.c = c;
2164
2165   c->t = t;
2166   if (own_pos > p->length - 1)
2167   {
2168     GNUNET_break (0);
2169     GMC_destroy (c);
2170     return NULL;
2171   }
2172   c->own_pos = own_pos;
2173   c->path = p;
2174
2175   if (0 == own_pos)
2176   {
2177     c->fwd_maintenance_task =
2178       GNUNET_SCHEDULER_add_delayed (create_connection_time,
2179                                     &connection_fwd_keepalive, c);
2180   }
2181   if (GNUNET_OK != register_neighbors (c))
2182   {
2183     GMC_destroy (c);
2184     return NULL;
2185   }
2186
2187   return c;
2188 }
2189
2190
2191 void
2192 GMC_destroy (struct MeshConnection *c)
2193 {
2194   if (NULL == c)
2195     return;
2196
2197   if (2 == c->destroy) /* cancel queues -> GMP_queue_cancel -> q_destroy -> */
2198     return;            /* -> message_sent -> GMC_destroy. Don't loop. */
2199   c->destroy = 2;
2200
2201   LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s\n", GMC_2s (c));
2202   LOG (GNUNET_ERROR_TYPE_DEBUG, " fc's f: %p, b: %p\n",
2203        &c->fwd_fc, &c->bck_fc);
2204   LOG (GNUNET_ERROR_TYPE_DEBUG, " fc tasks f: %u, b: %u\n",
2205        c->fwd_fc.poll_task, c->bck_fc.poll_task);
2206
2207   /* Cancel all traffic */
2208   connection_cancel_queues (c, GNUNET_YES);
2209   connection_cancel_queues (c, GNUNET_NO);
2210
2211   LOG (GNUNET_ERROR_TYPE_DEBUG, " fc tasks f: %u, b: %u\n",
2212        c->fwd_fc.poll_task, c->bck_fc.poll_task);
2213
2214   /* Cancel maintainance task (keepalive/timeout) */
2215   if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task)
2216     GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
2217   if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task)
2218     GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
2219   if (GNUNET_SCHEDULER_NO_TASK != c->fwd_fc.poll_task)
2220   {
2221     GNUNET_SCHEDULER_cancel (c->fwd_fc.poll_task);
2222     LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL FWD canceled\n");
2223   }
2224   if (GNUNET_SCHEDULER_NO_TASK != c->bck_fc.poll_task)
2225   {
2226     GNUNET_SCHEDULER_cancel (c->bck_fc.poll_task);
2227     LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL BCK canceled\n");
2228   }
2229   if (NULL != c->fwd_fc.poll_msg)
2230   {
2231     GMC_cancel (c->fwd_fc.poll_msg);
2232     LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL msg FWD canceled\n");
2233   }
2234   if (NULL != c->bck_fc.poll_msg)
2235   {
2236     GMC_cancel (c->bck_fc.poll_msg);
2237     LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL msg BCK canceled\n");
2238   }
2239
2240   /* Unregister from neighbors */
2241   unregister_neighbors (c);
2242
2243   /* Delete */
2244   GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO);
2245   if (NULL != c->t)
2246     GMT_remove_connection (c->t, c);
2247
2248   if (GNUNET_NO == GMC_is_origin (c, GNUNET_YES))
2249     path_destroy (c->path);
2250
2251   GNUNET_break (GNUNET_YES ==
2252                 GNUNET_CONTAINER_multihashmap_remove (connections, &c->id, c));
2253
2254   GNUNET_free (c);
2255 }
2256
2257 /**
2258  * Get the connection ID.
2259  *
2260  * @param c Connection to get the ID from.
2261  *
2262  * @return ID of the connection.
2263  */
2264 const struct GNUNET_HashCode *
2265 GMC_get_id (const struct MeshConnection *c)
2266 {
2267   return &c->id;
2268 }
2269
2270
2271 /**
2272  * Get the connection path.
2273  *
2274  * @param c Connection to get the path from.
2275  *
2276  * @return path used by the connection.
2277  */
2278 const struct MeshPeerPath *
2279 GMC_get_path (const struct MeshConnection *c)
2280 {
2281   if (GNUNET_NO == c->destroy)
2282     return c->path;
2283   return NULL;
2284 }
2285
2286
2287 /**
2288  * Get the connection state.
2289  *
2290  * @param c Connection to get the state from.
2291  *
2292  * @return state of the connection.
2293  */
2294 enum MeshConnectionState
2295 GMC_get_state (const struct MeshConnection *c)
2296 {
2297   return c->state;
2298 }
2299
2300 /**
2301  * Get the connection tunnel.
2302  *
2303  * @param c Connection to get the tunnel from.
2304  *
2305  * @return tunnel of the connection.
2306  */
2307 struct MeshTunnel3 *
2308 GMC_get_tunnel (const struct MeshConnection *c)
2309 {
2310   return c->t;
2311 }
2312
2313
2314 /**
2315  * Get free buffer space in a connection.
2316  *
2317  * @param c Connection.
2318  * @param fwd Is query about FWD traffic?
2319  *
2320  * @return Free buffer space [0 - max_msgs_queue/max_connections]
2321  */
2322 unsigned int
2323 GMC_get_buffer (struct MeshConnection *c, int fwd)
2324 {
2325   struct MeshFlowControl *fc;
2326
2327   fc = fwd ? &c->fwd_fc : &c->bck_fc;
2328
2329   return (fc->queue_max - fc->queue_n);
2330 }
2331
2332 /**
2333  * Get how many messages have we allowed to send to us from a direction.
2334  *
2335  * @param c Connection.
2336  * @param fwd Are we asking about traffic from FWD (BCK messages)?
2337  *
2338  * @return last_ack_sent - last_pid_recv
2339  */
2340 unsigned int
2341 GMC_get_allowed (struct MeshConnection *c, int fwd)
2342 {
2343   struct MeshFlowControl *fc;
2344
2345   fc = fwd ? &c->fwd_fc : &c->bck_fc;
2346   if (GM_is_pid_bigger(fc->last_pid_recv, fc->last_ack_sent))
2347   {
2348     return 0;
2349   }
2350   return (fc->last_ack_sent - fc->last_pid_recv);
2351 }
2352
2353 /**
2354  * Get messages queued in a connection.
2355  *
2356  * @param c Connection.
2357  * @param fwd Is query about FWD traffic?
2358  *
2359  * @return Number of messages queued.
2360  */
2361 unsigned int
2362 GMC_get_qn (struct MeshConnection *c, int fwd)
2363 {
2364   struct MeshFlowControl *fc;
2365
2366   fc = fwd ? &c->fwd_fc : &c->bck_fc;
2367
2368   return fc->queue_n;
2369 }
2370
2371
2372 /**
2373  * Allow the connection to advertise a buffer of the given size.
2374  *
2375  * The connection will send an @c fwd ACK message (so: in direction !fwd)
2376  * allowing up to last_pid_recv + buffer.
2377  *
2378  * @param c Connection.
2379  * @param buffer How many more messages the connection can accept.
2380  * @param fwd Is this about FWD traffic? (The ack will go dest->root).
2381  */
2382 void
2383 GMC_allow (struct MeshConnection *c, unsigned int buffer, int fwd)
2384 {
2385   send_ack (c, buffer, fwd, GNUNET_NO);
2386 }
2387
2388
2389 /**
2390  * Notify other peers on a connection of a broken link. Mark connections
2391  * to destroy after all traffic has been sent.
2392  *
2393  * @param c Connection on which there has been a disconnection.
2394  * @param peer Peer that disconnected.
2395  */
2396 void
2397 GMC_notify_broken (struct MeshConnection *c,
2398                    struct MeshPeer *peer)
2399 {
2400   int fwd;
2401
2402   LOG (GNUNET_ERROR_TYPE_DEBUG,
2403        " notify broken on %s due to %s disconnect\n",
2404        GMC_2s (c), GMP_2s (peer));
2405
2406   fwd = peer == get_prev_hop (c);
2407
2408   if (GNUNET_YES == GMC_is_terminal (c, fwd))
2409   {
2410     /* Local shutdown, no one to notify about this. */
2411     GMC_destroy (c);
2412     return;
2413   }
2414   if (GNUNET_NO == c->destroy)
2415     send_broken (c, &my_full_id, GMP_get_id (peer), fwd);
2416
2417   /* Connection will have at least one pending message
2418    * (the one we just scheduled), so no point in checking whether to
2419    * destroy immediately. */
2420   c->destroy = GNUNET_YES;
2421   c->state = MESH_CONNECTION_DESTROYED;
2422
2423   /**
2424    * Cancel all queues, if no message is left, connection will be destroyed.
2425    */
2426   connection_cancel_queues (c, !fwd);
2427
2428   return;
2429 }
2430
2431
2432 /**
2433  * Is this peer the first one on the connection?
2434  *
2435  * @param c Connection.
2436  * @param fwd Is this about fwd traffic?
2437  *
2438  * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal.
2439  */
2440 int
2441 GMC_is_origin (struct MeshConnection *c, int fwd)
2442 {
2443   if (!fwd && c->path->length - 1 == c->own_pos )
2444     return GNUNET_YES;
2445   if (fwd && 0 == c->own_pos)
2446     return GNUNET_YES;
2447   return GNUNET_NO;
2448 }
2449
2450
2451 /**
2452  * Is this peer the last one on the connection?
2453  *
2454  * @param c Connection.
2455  * @param fwd Is this about fwd traffic?
2456  *            Note that the ROOT is the terminal for BCK traffic!
2457  *
2458  * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin.
2459  */
2460 int
2461 GMC_is_terminal (struct MeshConnection *c, int fwd)
2462 {
2463   return GMC_is_origin (c, !fwd);
2464 }
2465
2466
2467 /**
2468  * See if we are allowed to send by the next hop in the given direction.
2469  *
2470  * @param c Connection.
2471  * @param fwd Is this about fwd traffic?
2472  *
2473  * @return #GNUNET_YES in case it's OK to send.
2474  */
2475 int
2476 GMC_is_sendable (struct MeshConnection *c, int fwd)
2477 {
2478   struct MeshFlowControl *fc;
2479
2480   fc = fwd ? &c->fwd_fc : &c->bck_fc;
2481   if (GM_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
2482     return GNUNET_YES;
2483   return GNUNET_NO;
2484 }
2485
2486 /**
2487  * Sends an already built message on a connection, properly registering
2488  * all used resources.
2489  *
2490  * @param message Message to send. Function makes a copy of it.
2491  *                If message is not hop-by-hop, decrements TTL of copy.
2492  * @param c Connection on which this message is transmitted.
2493  * @param fwd Is this a fwd message?
2494  * @param cont Continuation called once message is sent. Can be NULL.
2495  * @param cont_cls Closure for @c cont.
2496  *
2497  * @return Handle to cancel the message before it's sent.
2498  *         NULL on error or if @c cont is NULL.
2499  *         Invalid on @c cont call.
2500  */
2501 struct MeshConnectionQueue *
2502 GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2503                            struct MeshConnection *c, int fwd,
2504                            GMC_sent cont, void *cont_cls)
2505 {
2506   struct MeshFlowControl *fc;
2507   struct MeshConnectionQueue *q;
2508   void *data;
2509   size_t size;
2510   uint16_t type;
2511   int droppable;
2512
2513   size = ntohs (message->size);
2514   data = GNUNET_malloc (size);
2515   memcpy (data, message, size);
2516   type = ntohs (message->type);
2517   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send %s (%u bytes) on connection %s\n",
2518               GM_m2s (type), size, GMC_2s (c));
2519
2520   fc = fwd ? &c->fwd_fc : &c->bck_fc;
2521   droppable = GNUNET_YES;
2522   switch (type)
2523   {
2524     struct GNUNET_MESH_Encrypted *emsg;
2525     struct GNUNET_MESH_KX        *kmsg;
2526     struct GNUNET_MESH_ACK       *amsg;
2527     struct GNUNET_MESH_Poll      *pmsg;
2528     struct GNUNET_MESH_ConnectionDestroy *dmsg;
2529     struct GNUNET_MESH_ConnectionBroken  *bmsg;
2530     uint32_t ttl;
2531
2532     case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED:
2533       emsg = (struct GNUNET_MESH_Encrypted *) data;
2534       ttl = ntohl (emsg->ttl);
2535       if (0 == ttl)
2536       {
2537         GNUNET_break_op (0);
2538         GNUNET_free (data);
2539         return NULL;
2540       }
2541       emsg->cid = c->id;
2542       emsg->ttl = htonl (ttl - 1);
2543       emsg->pid = htonl (fc->next_pid++);
2544       LOG (GNUNET_ERROR_TYPE_DEBUG, "  Q_N+ %p %u\n", fc, fc->queue_n);
2545       fc->queue_n++;
2546       LOG (GNUNET_ERROR_TYPE_DEBUG, "pid %u\n", ntohl (emsg->pid));
2547       LOG (GNUNET_ERROR_TYPE_DEBUG, "last pid sent %u\n", fc->last_pid_sent);
2548       LOG (GNUNET_ERROR_TYPE_DEBUG, "     ack recv %u\n", fc->last_ack_recv);
2549       if (GM_is_pid_bigger (fc->last_pid_sent + 1, fc->last_ack_recv))
2550       {
2551         GMC_start_poll (c, fwd);
2552       }
2553       break;
2554
2555     case GNUNET_MESSAGE_TYPE_MESH_KX:
2556       kmsg = (struct GNUNET_MESH_KX *) data;
2557       kmsg->cid = c->id;
2558       break;
2559
2560     case GNUNET_MESSAGE_TYPE_MESH_ACK:
2561       amsg = (struct GNUNET_MESH_ACK *) data;
2562       amsg->cid = c->id;
2563       LOG (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ntohl (amsg->ack));
2564       droppable = GNUNET_NO;
2565       break;
2566
2567     case GNUNET_MESSAGE_TYPE_MESH_POLL:
2568       pmsg = (struct GNUNET_MESH_Poll *) data;
2569       pmsg->cid = c->id;
2570       LOG (GNUNET_ERROR_TYPE_DEBUG, " poll %u\n", ntohl (pmsg->pid));
2571       droppable = GNUNET_NO;
2572       break;
2573
2574     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY:
2575       dmsg = (struct GNUNET_MESH_ConnectionDestroy *) data;
2576       dmsg->cid = c->id;
2577       dmsg->reserved = 0;
2578       break;
2579
2580     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
2581       bmsg = (struct GNUNET_MESH_ConnectionBroken *) data;
2582       bmsg->cid = c->id;
2583       bmsg->reserved = 0;
2584       break;
2585
2586     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
2587     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
2588     case GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE:
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 }