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