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