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