- connection fixing
[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 "gnunet-service-mesh_connection.h"
33 #include "gnunet-service-mesh_peer.h"
34 #include "gnunet-service-mesh_tunnel.h"
35 #include "gnunet-service-mesh_channel.h"
36 #include "mesh_protocol_enc.h"
37 #include "mesh_path.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 /**
110  * Keep a record of the last messages sent on this connection.
111  */
112 struct MeshConnectionPerformance
113 {
114   /**
115    * Circular buffer for storing measurements.
116    */
117   double usecsperbyte[AVG_MSGS];
118
119   /**
120    * Running average of @c usecsperbyte.
121    */
122   double avg;
123
124   /**
125    * How many values of @c usecsperbyte are valid.
126    */
127   uint16_t size;
128
129   /**
130    * Index of the next "free" position in @c usecsperbyte.
131    */
132   uint16_t idx;
133 };
134
135
136 /**
137  * Struct containing all information regarding a connection to a peer.
138  */
139 struct MeshConnection
140 {
141   /**
142    * Tunnel this connection is part of.
143    */
144   struct MeshTunnel3 *t;
145
146   /**
147    * Flow control information for traffic fwd.
148    */
149   struct MeshFlowControl fwd_fc;
150
151   /**
152    * Flow control information for traffic bck.
153    */
154   struct MeshFlowControl bck_fc;
155
156   /**
157    * Measure connection performance on the endpoint.
158    */
159   struct MeshConnectionPerformance *perf;
160
161   /**
162    * ID of the connection.
163    */
164   struct GNUNET_HashCode id;
165
166   /**
167    * State of the connection.
168    */
169   enum MeshConnectionState state;
170
171   /**
172    * Path being used for the tunnel.
173    */
174   struct MeshPeerPath *path;
175
176   /**
177    * Position of the local peer in the path.
178    */
179   unsigned int own_pos;
180
181   /**
182    * Task to keep the used paths alive at the owner,
183    * time tunnel out on all the other peers.
184    */
185   GNUNET_SCHEDULER_TaskIdentifier fwd_maintenance_task;
186
187   /**
188    * Task to keep the used paths alive at the destination,
189    * time tunnel out on all the other peers.
190    */
191   GNUNET_SCHEDULER_TaskIdentifier bck_maintenance_task;
192
193   /**
194    * Pending message count.
195    */
196   int pending_messages;
197
198   /**
199    * Destroy flag: if true, destroy on last message.
200    */
201   int destroy;
202 };
203
204 /******************************************************************************/
205 /*******************************   GLOBALS  ***********************************/
206 /******************************************************************************/
207
208 /**
209  * Global handle to the statistics service.
210  */
211 extern struct GNUNET_STATISTICS_Handle *stats;
212
213 /**
214  * Connections known, indexed by cid (MeshConnection).
215  */
216 static struct GNUNET_CONTAINER_MultiHashMap *connections;
217
218 /**
219  * How many connections are we willing to maintain.
220  * Local connections are always allowed, even if there are more connections than max.
221  */
222 static unsigned long long max_connections;
223
224 /**
225  * How many messages *in total* are we willing to queue, divide by number of
226  * connections to get connection queue size.
227  */
228 static unsigned long long max_msgs_queue;
229
230 /**
231  * How often to send path keepalives. Paths timeout after 4 missed.
232  */
233 static struct GNUNET_TIME_Relative refresh_connection_time;
234
235
236 /******************************************************************************/
237 /********************************   STATIC  ***********************************/
238 /******************************************************************************/
239
240 #if 0 // avoid compiler warning for unused static function
241 static void
242 fc_debug (struct MeshFlowControl *fc)
243 {
244   LOG (GNUNET_ERROR_TYPE_DEBUG, "    IN: %u/%u\n",
245               fc->last_pid_recv, fc->last_ack_sent);
246   LOG (GNUNET_ERROR_TYPE_DEBUG, "    OUT: %u/%u\n",
247               fc->last_pid_sent, fc->last_ack_recv);
248   LOG (GNUNET_ERROR_TYPE_DEBUG, "    QUEUE: %u/%u\n",
249               fc->queue_n, fc->queue_max);
250 }
251
252 static void
253 connection_debug (struct MeshConnection *c)
254 {
255   if (NULL == c)
256   {
257     LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n");
258     return;
259   }
260   LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
261               peer2s (c->t->peer), GNUNET_h2s (&c->id));
262   LOG (GNUNET_ERROR_TYPE_DEBUG, "  state: %u, pending msgs: %u\n",
263               c->state, c->pending_messages);
264   LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD FC\n");
265   fc_debug (&c->fwd_fc);
266   LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK FC\n");
267   fc_debug (&c->bck_fc);
268 }
269 #endif
270
271 /**
272  * Get string description for tunnel state.
273  *
274  * @param s Tunnel state.
275  *
276  * @return String representation.
277  */
278 static const char *
279 GMC_state2s (enum MeshConnectionState s)
280 {
281   switch (s)
282   {
283     case MESH_CONNECTION_NEW:
284       return "MESH_CONNECTION_NEW";
285     case MESH_CONNECTION_SENT:
286       return "MESH_CONNECTION_SENT";
287     case MESH_CONNECTION_ACK:
288       return "MESH_CONNECTION_ACK";
289     case MESH_CONNECTION_READY:
290       return "MESH_CONNECTION_READY";
291     default:
292       return "MESH_CONNECTION_STATE_ERROR";
293   }
294 }
295
296
297 /**
298  * Initialize a Flow Control structure to the initial state.
299  *
300  * @param fc Flow Control structure to initialize.
301  */
302 static void
303 fc_init (struct MeshFlowControl *fc)
304 {
305   fc->next_pid = 0;
306   fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */
307   fc->last_pid_recv = (uint32_t) -1;
308   fc->last_ack_sent = (uint32_t) 0;
309   fc->last_ack_recv = (uint32_t) 0;
310   fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
311   fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
312   fc->queue_n = 0;
313   fc->queue_max = (max_msgs_queue / max_connections) + 1;
314 }
315
316
317 /**
318  * Find a connection.
319  *
320  * @param cid Connection ID.
321  */
322 static struct MeshConnection *
323 connection_get (const struct GNUNET_HashCode *cid)
324 {
325   return GNUNET_CONTAINER_multihashmap_get (connections, cid);
326 }
327
328
329 /**
330  * Send an ACK informing the predecessor about the available buffer space.
331  *
332  * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
333  * the ACK itself goes "back" (dest->root).
334  *
335  * @param c Connection on which to send the ACK.
336  * @param buffer How much space free to advertise?
337  * @param fwd Is this FWD ACK? (Going dest->owner)
338  */
339 static void
340 connection_send_ack (struct MeshConnection *c, unsigned int buffer, int fwd)
341 {
342   struct MeshFlowControl *next_fc;
343   struct MeshFlowControl *prev_fc;
344   struct GNUNET_MESH_ACK msg;
345   uint32_t ack;
346   int delta;
347
348   next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
349   prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
350
351   LOG (GNUNET_ERROR_TYPE_DEBUG,
352               "connection send %s ack on %s\n",
353               fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
354
355   /* Check if we need to transmit the ACK */
356   if (prev_fc->last_ack_sent - prev_fc->last_pid_recv > 3)
357   {
358     LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n");
359     LOG (GNUNET_ERROR_TYPE_DEBUG,
360                 "  last pid recv: %u, last ack sent: %u\n",
361                 prev_fc->last_pid_recv, prev_fc->last_ack_sent);
362     return;
363   }
364
365   /* Ok, ACK might be necessary, what PID to ACK? */
366   delta = next_fc->queue_max - next_fc->queue_n;
367   ack = prev_fc->last_pid_recv + delta;
368   LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
369   LOG (GNUNET_ERROR_TYPE_DEBUG,
370               " last pid %u, last ack %u, qmax %u, q %u\n",
371               prev_fc->last_pid_recv, prev_fc->last_ack_sent,
372               next_fc->queue_max, next_fc->queue_n);
373   if (ack == prev_fc->last_ack_sent)
374   {
375     LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
376     return;
377   }
378
379   prev_fc->last_ack_sent = ack;
380
381   /* Build ACK message and send on connection */
382   msg.header.size = htons (sizeof (msg));
383   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
384   msg.ack = htonl (ack);
385   msg.cid = c->id;
386
387   GMC_send_prebuilt_message (&msg.header, c, NULL, !fwd);
388 }
389
390
391 /**
392  * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
393  * or a first CONNECTION_ACK directed to us.
394  *
395  * @param connection Connection to confirm.
396  * @param fwd Is this a fwd ACK? (First is bck (SYNACK), second is fwd (ACK))
397  */
398 static void
399 send_connection_ack (struct MeshConnection *connection, int fwd)
400 {
401   struct MeshTunnel3 *t;
402
403   t = connection->t;
404   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send connection ack\n");
405   GMP_queue_add (NULL,
406                  GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
407                  sizeof (struct GNUNET_MESH_ConnectionACK),
408                  connection, NULL, fwd,
409                  &message_sent, sizeof (struct GNUNET_MESH_ConnectionACK));
410   if (MESH_TUNNEL_NEW == t->state)
411     GMT_change_state (t, MESH_TUNNEL_WAITING);
412   if (MESH_CONNECTION_READY != connection->state)
413     GMC_change_state (connection, MESH_CONNECTION_SENT);
414 }
415
416
417 /**
418  * Sends a CREATE CONNECTION message for a path to a peer.
419  * Changes the connection and tunnel states if necessary.
420  *
421  * @param connection Connection to create.
422  */
423 static void
424 send_connection_create (struct MeshConnection *connection)
425 {
426   struct MeshTunnel3 *t;
427
428   t = connection->t;
429   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send connection create\n");
430   queue_add (NULL,
431              GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
432              sizeof (struct GNUNET_MESH_ConnectionCreate) +
433                 (connection->path->length *
434                  sizeof (struct GNUNET_PeerIdentity)),
435              connection,
436              NULL,
437              GNUNET_YES);
438   if (NULL != t &&
439       (MESH_TUNNEL_SEARCHING == t->state || MESH_TUNNEL_NEW == t->state))
440     tunnel_change_state (t, MESH_TUNNEL_WAITING);
441   if (MESH_CONNECTION_NEW == connection->state)
442     connection_change_state (connection, MESH_CONNECTION_SENT);
443 }
444
445
446 static void
447 connection_change_state (struct MeshConnection* c,
448                          enum MeshConnectionState state)
449 {
450   LOG (GNUNET_ERROR_TYPE_DEBUG,
451               "Connection %s state was %s\n",
452               GNUNET_h2s (&c->id), GMC_state2s (c->state));
453   LOG (GNUNET_ERROR_TYPE_DEBUG,
454               "Connection %s state is now %s\n",
455               GNUNET_h2s (&c->id), GMC_state2s (state));
456   c->state = state;
457 }
458
459
460
461 /**
462  * Send keepalive packets for a connection.
463  *
464  * @param c Connection to keep alive..
465  * @param fwd Is this a FWD keepalive? (owner -> dest).
466  */
467 static void
468 connection_keepalive (struct MeshConnection *c, int fwd)
469 {
470   struct GNUNET_MESH_ConnectionKeepAlive *msg;
471   size_t size = sizeof (struct GNUNET_MESH_ConnectionKeepAlive);
472   char cbuf[size];
473   uint16_t type;
474
475   type = fwd ? GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE :
476                GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE;
477
478   LOG (GNUNET_ERROR_TYPE_DEBUG,
479               "sending %s keepalive for connection %s[%d]\n",
480               fwd ? "FWD" : "BCK",
481               peer2s (c->t->peer),
482               c->id);
483
484   msg = (struct GNUNET_MESH_ConnectionKeepAlive *) cbuf;
485   msg->header.size = htons (size);
486   msg->header.type = htons (type);
487   msg->cid = c->id;
488
489   send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
490 }
491
492
493 /**
494  * Send CONNECTION_{CREATE/ACK} packets for a connection.
495  *
496  * @param c Connection for which to send the message.
497  * @param fwd If GNUNET_YES, send CREATE, otherwise send ACK.
498  */
499 static void
500 connection_recreate (struct MeshConnection *c, int fwd)
501 {
502   LOG (GNUNET_ERROR_TYPE_DEBUG, "sending connection recreate\n");
503   if (fwd)
504     send_connection_create (c);
505   else
506     send_connection_ack (c, GNUNET_NO);
507 }
508
509
510 /**
511  * Generic connection timer management.
512  * Depending on the role of the peer in the connection will send the
513  * appropriate message (build or keepalive)
514  *
515  * @param c Conncetion to maintain.
516  * @param fwd Is FWD?
517  */
518 static void
519 connection_maintain (struct MeshConnection *c, int fwd)
520 {
521   if (MESH_TUNNEL_SEARCHING == c->t->state)
522   {
523     /* TODO DHT GET with RO_BART */
524     return;
525   }
526   switch (c->state)
527   {
528     case MESH_CONNECTION_NEW:
529       GNUNET_break (0);
530     case MESH_CONNECTION_SENT:
531       connection_recreate (c, fwd);
532       break;
533     case MESH_CONNECTION_READY:
534       connection_keepalive (c, fwd);
535       break;
536     default:
537       break;
538   }
539 }
540
541
542 static void
543 connection_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
544 {
545   struct MeshConnection *c = cls;
546
547   c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
548   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
549     return;
550
551   connection_maintain (c, GNUNET_YES);
552   c->fwd_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
553                                                           &connection_fwd_keepalive,
554                                                           c);
555 }
556
557
558 static void
559 connection_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
560 {
561   struct MeshConnection *c = cls;
562
563   c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
564   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
565     return;
566
567   connection_maintain (c, GNUNET_NO);
568   c->bck_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
569                                                           &connection_bck_keepalive,
570                                                           c);
571 }
572
573
574
575 /**
576  * Get the previous hop in a connection
577  *
578  * @param c Connection.
579  *
580  * @return Previous peer in the connection.
581  */
582 static struct MeshPeer *
583 connection_get_prev_hop (struct MeshConnection *c)
584 {
585   GNUNET_PEER_Id id;
586
587   if (0 == c->own_pos || c->path->length < 2)
588     id = c->path->peers[0];
589   else
590     id = c->path->peers[c->own_pos - 1];
591
592   return peer_get_short (id);
593 }
594
595
596 /**
597  * Get the next hop in a connection
598  *
599  * @param c Connection.
600  *
601  * @return Next peer in the connection.
602  */
603 static struct MeshPeer *
604 connection_get_next_hop (struct MeshConnection *c)
605 {
606   GNUNET_PEER_Id id;
607
608   if ((c->path->length - 1) == c->own_pos || c->path->length < 2)
609     id = c->path->peers[c->path->length - 1];
610   else
611     id = c->path->peers[c->own_pos + 1];
612
613   return peer_get_short (id);
614 }
615
616
617 /**
618  * Get the hop in a connection.
619  *
620  * @param c Connection.
621  * @param fwd Next hop?
622  *
623  * @return Next peer in the connection.
624  */
625 static struct MeshPeer *
626 connection_get_hop (struct MeshConnection *c, int fwd)
627 {
628   if (fwd)
629     return connection_get_next_hop (c);
630   return connection_get_prev_hop (c);
631 }
632
633
634 /**
635  * Get the first transmittable message for a connection.
636  *
637  * @param c Connection.
638  * @param fwd Is this FWD?
639  *
640  * @return First transmittable message.
641  */
642 static struct MeshPeerQueue *
643 connection_get_first_message (struct MeshConnection *c, int fwd)
644 {
645   struct MeshPeerQueue *q;
646   struct MeshPeer *p;
647
648   p = connection_get_hop (c, fwd);
649
650   for (q = p->queue_head; NULL != q; q = q->next)
651   {
652     if (q->c != c)
653       continue;
654     if (queue_is_sendable (q))
655       return q;
656   }
657
658   return NULL;
659 }
660
661
662 /**
663  * @brief Re-initiate traffic on this connection if necessary.
664  *
665  * Check if there is traffic queued towards this peer
666  * and the core transmit handle is NULL (traffic was stalled).
667  * If so, call core tmt rdy.
668  *
669  * @param c Connection on which initiate traffic.
670  * @param fwd Is this about fwd traffic?
671  */
672 static void
673 connection_unlock_queue (struct MeshConnection *c, int fwd)
674 {
675   struct MeshPeer *peer;
676   struct MeshPeerQueue *q;
677   size_t size;
678
679   LOG (GNUNET_ERROR_TYPE_DEBUG,
680               "connection_unlock_queue %s on %s\n",
681               fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
682
683   if (GMC_is_terminal (c, fwd))
684   {
685     LOG (GNUNET_ERROR_TYPE_DEBUG, " is terminal!\n");
686     return;
687   }
688
689   peer = connection_get_hop (c, fwd);
690
691   if (NULL != peer->core_transmit)
692   {
693     LOG (GNUNET_ERROR_TYPE_DEBUG, "  already unlocked!\n");
694     return; /* Already unlocked */
695   }
696
697   q = connection_get_first_message (c, fwd);
698   if (NULL == q)
699   {
700     LOG (GNUNET_ERROR_TYPE_DEBUG, "  queue empty!\n");
701     return; /* Nothing to transmit */
702   }
703
704   size = q->size;
705   peer->core_transmit =
706       GNUNET_CORE_notify_transmit_ready (core_handle,
707                                          GNUNET_NO,
708                                          0,
709                                          GNUNET_TIME_UNIT_FOREVER_REL,
710                                          GNUNET_PEER_resolve2 (peer->id),
711                                          size,
712                                          &queue_send,
713                                          peer);
714 }
715
716
717 /**
718  * Cancel all transmissions that belong to a certain connection.
719  *
720  * @param c Connection which to cancel.
721  * @param fwd Cancel fwd traffic?
722  */
723 static void
724 connection_cancel_queues (struct MeshConnection *c, int fwd)
725 {
726   struct MeshPeerQueue *q;
727   struct MeshPeerQueue *next;
728   struct MeshFlowControl *fc;
729   struct MeshPeer *peer;
730
731   if (NULL == c)
732   {
733     GNUNET_break (0);
734     return;
735   }
736   fc = fwd ? &c->fwd_fc : &c->bck_fc;
737   peer = connection_get_hop (c, fwd);
738
739   for (q = peer->queue_head; NULL != q; q = next)
740   {
741     next = q->next;
742     if (q->c == c)
743     {
744       LOG (GNUNET_ERROR_TYPE_DEBUG,
745                   "connection_cancel_queue %s\n",
746                   GNUNET_MESH_DEBUG_M2S (q->type));
747       queue_destroy (q, GNUNET_YES);
748     }
749   }
750   if (NULL == peer->queue_head)
751   {
752     if (NULL != peer->core_transmit)
753     {
754       GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
755       peer->core_transmit = NULL;
756     }
757     if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
758     {
759       GNUNET_SCHEDULER_cancel (fc->poll_task);
760       fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
761     }
762   }
763 }
764
765
766 /**
767  * Function called if a connection has been stalled for a while,
768  * possibly due to a missed ACK. Poll the neighbor about its ACK status.
769  *
770  * @param cls Closure (poll ctx).
771  * @param tc TaskContext.
772  */
773 static void
774 connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
775 {
776   struct MeshFlowControl *fc = cls;
777   struct GNUNET_MESH_Poll msg;
778   struct MeshConnection *c;
779
780   fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
781   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
782   {
783     return;
784   }
785
786   c = fc->c;
787   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Polling!\n");
788   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** connection [%X]\n",
789               GNUNET_h2s (&c->id));
790   LOG (GNUNET_ERROR_TYPE_DEBUG, " ***   %s\n",
791               fc == &c->fwd_fc ? "FWD" : "BCK");
792
793   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL);
794   msg.header.size = htons (sizeof (msg));
795   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** pid (%u)!\n", fc->last_pid_sent);
796   send_prebuilt_message_connection (&msg.header, c, NULL, fc == &c->fwd_fc);
797   fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
798   fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
799                                                 &connection_poll, fc);
800 }
801
802
803 /**
804  * Timeout function due to lack of keepalive/traffic from the owner.
805  * Destroys connection if called.
806  *
807  * @param cls Closure (connection to destroy).
808  * @param tc TaskContext.
809  */
810 static void
811 connection_fwd_timeout (void *cls,
812                         const struct GNUNET_SCHEDULER_TaskContext *tc)
813 {
814   struct MeshConnection *c = cls;
815
816   c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
817   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
818     return;
819   LOG (GNUNET_ERROR_TYPE_DEBUG,
820               "Connection %s[%X] FWD timed out. Destroying.\n",
821               GMT_2s (c->t),
822               c->id);
823
824   if (GMC_is_origin (c, GNUNET_YES)) /* If local, leave. */
825     return;
826
827   GMC_destroy (c);
828 }
829
830
831 /**
832  * Timeout function due to lack of keepalive/traffic from the destination.
833  * Destroys connection if called.
834  *
835  * @param cls Closure (connection to destroy).
836  * @param tc TaskContext
837  */
838 static void
839 connection_bck_timeout (void *cls,
840                         const struct GNUNET_SCHEDULER_TaskContext *tc)
841 {
842   struct MeshConnection *c = cls;
843
844   c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
845   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
846     return;
847
848   LOG (GNUNET_ERROR_TYPE_DEBUG,
849               "Connection %s[%X] FWD timed out. Destroying.\n",
850               GMT_2s (c->t), c->id);
851
852   if (GMC_is_origin (c, GNUNET_NO)) /* If local, leave. */
853     return;
854
855   GMC_destroy (c);
856 }
857
858
859 /**
860  * Resets the connection timeout task, some other message has done the
861  * task's job.
862  * - For the first peer on the direction this means to send
863  *   a keepalive or a path confirmation message (either create or ACK).
864  * - For all other peers, this means to destroy the connection,
865  *   due to lack of activity.
866  * Starts the tiemout if no timeout was running (connection just created).
867  *
868  * @param c Connection whose timeout to reset.
869  * @param fwd Is this forward?
870  *
871  * TODO use heap to improve efficiency of scheduler.
872  */
873 static void
874 connection_reset_timeout (struct MeshConnection *c, int fwd)
875 {
876   GNUNET_SCHEDULER_TaskIdentifier *ti;
877   GNUNET_SCHEDULER_Task f;
878
879   ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task;
880
881   if (GNUNET_SCHEDULER_NO_TASK != *ti)
882     GNUNET_SCHEDULER_cancel (*ti);
883
884   if (GMC_is_origin (c, fwd)) /* Endpoint */
885   {
886     f  = fwd ? &connection_fwd_keepalive : &connection_bck_keepalive;
887     *ti = GNUNET_SCHEDULER_add_delayed (refresh_connection_time, f, c);
888   }
889   else /* Relay */
890   {
891     struct GNUNET_TIME_Relative delay;
892
893     delay = GNUNET_TIME_relative_multiply (refresh_connection_time, 4);
894     f  = fwd ? &connection_fwd_timeout : &connection_bck_timeout;
895     *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c);
896   }
897 }
898
899
900 /**
901  * Add the connection to the list of both neighbors.
902  *
903  * @param c Connection.
904  */
905 static void
906 register_neighbors (struct MeshConnection *c)
907 {
908   struct MeshPeer *peer;
909
910   peer = connection_get_next_hop (c);
911   if (GNUNET_NO == GMP_is_neighbor (peer))
912   {
913     GMC_destroy (c);
914     return NULL;
915   }
916   GMP_add_connection (peer, c);
917   peer = connection_get_prev_hop (c);
918   if (GNUNET_NO == GMP_is_neighbor (peer))
919   {
920     GMC_destroy (c);
921     return NULL;
922   }
923   GMP_add_connection (peer, c);
924 }
925
926
927 /**
928  * Remove the connection from the list of both neighbors.
929  *
930  * @param c Connection.
931  */
932 static void
933 unregister_neighbors (struct MeshConnection *c)
934 {
935   struct MeshPeer *peer;
936
937   peer = connection_get_next_hop (c);
938   GMP_remove_connection (peer, c);
939
940   peer = connection_get_prev_hop (c);
941   GMP_remove_connection (peer, c);
942
943 }
944
945
946 /**
947  * Callback called when a queued message is sent.
948  *
949  * Calculates the average time 
950  *
951  * @param cls Closure.
952  * @param c Connection this message was on.
953  * @param wait Time spent waiting for core (only the time for THIS message)
954  */
955 static void 
956 message_sent (void *cls,
957               struct MeshConnection *c,
958               struct GNUNET_TIME_Relative wait)
959 {
960   struct MeshConnectionPerformance *p;
961   size_t size = (size_t) cls;
962   double usecsperbyte;
963
964   if (NULL == c->perf)
965     return; /* Only endpoints are interested in this. */
966
967   p = c->perf;
968   usecsperbyte = ((double) wait.rel_value_us) / size;
969   if (p->size == AVG_MSGS)
970   {
971     /* Array is full. Substract oldest value, add new one and store. */
972     p->avg -= (p->usecsperbyte[p->idx] / AVG_MSGS);
973     p->usecsperbyte[p->idx] = usecsperbyte;
974     p->avg += (p->usecsperbyte[p->idx] / AVG_MSGS);
975   }
976   else
977   {
978     /* Array not yet full. Add current value to avg and store. */
979     p->usecsperbyte[p->idx] = usecsperbyte;
980     p->avg *= p->size;
981     p->avg += p->usecsperbyte[p->idx];
982     p->size++;
983     p->avg /= p->size;
984   }
985   p->idx = (p->idx + 1) % AVG_MSGS;
986 }
987
988
989 /******************************************************************************/
990 /********************************    API    ***********************************/
991 /******************************************************************************/
992
993 /**
994  * Core handler for connection creation.
995  *
996  * @param cls Closure (unused).
997  * @param peer Sender (neighbor).
998  * @param message Message.
999  *
1000  * @return GNUNET_OK to keep the connection open,
1001  *         GNUNET_SYSERR to close it (signal serious error)
1002  */
1003 int
1004 GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
1005                    const struct GNUNET_MessageHeader *message)
1006 {
1007   struct GNUNET_MESH_ConnectionCreate *msg;
1008   struct GNUNET_PeerIdentity *id;
1009   struct GNUNET_HashCode *cid;
1010   struct MeshPeerPath *path;
1011   struct MeshPeer *dest_peer;
1012   struct MeshPeer *orig_peer;
1013   struct MeshConnection *c;
1014   unsigned int own_pos;
1015   uint16_t size;
1016   uint16_t i;
1017
1018   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1019   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a connection create msg\n");
1020
1021   /* Check size */
1022   size = ntohs (message->size);
1023   if (size < sizeof (struct GNUNET_MESH_ConnectionCreate))
1024   {
1025     GNUNET_break_op (0);
1026     return GNUNET_OK;
1027   }
1028
1029   /* Calculate hops */
1030   size -= sizeof (struct GNUNET_MESH_ConnectionCreate);
1031   if (size % sizeof (struct GNUNET_PeerIdentity))
1032   {
1033     GNUNET_break_op (0);
1034     return GNUNET_OK;
1035   }
1036   size /= sizeof (struct GNUNET_PeerIdentity);
1037   if (1 > size)
1038   {
1039     GNUNET_break_op (0);
1040     return GNUNET_OK;
1041   }
1042   LOG (GNUNET_ERROR_TYPE_DEBUG, "    path has %u hops.\n", size);
1043
1044   /* Get parameters */
1045   msg = (struct GNUNET_MESH_ConnectionCreate *) message;
1046   cid = &msg->cid;
1047   id = (struct GNUNET_PeerIdentity *) &msg[1];
1048   LOG (GNUNET_ERROR_TYPE_DEBUG,
1049               "    connection %s (%s).\n",
1050               GNUNET_h2s (cid), GNUNET_i2s (id));
1051
1052   /* Create connection */
1053   c = connection_get (cid);
1054   if (NULL == c)
1055   {
1056     /* Create path */
1057     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Creating path...\n");
1058     path = path_new (size);
1059     own_pos = 0;
1060     for (i = 0; i < size; i++)
1061     {
1062       LOG (GNUNET_ERROR_TYPE_DEBUG, "  ... adding %s\n",
1063                   GNUNET_i2s (&id[i]));
1064       path->peers[i] = GNUNET_PEER_intern (&id[i]);
1065       if (path->peers[i] == my_short_id)
1066         own_pos = i;
1067     }
1068     if (own_pos == 0 && path->peers[own_pos] != myid)
1069     {
1070       /* create path: self not found in path through self */
1071       GNUNET_break_op (0);
1072       path_destroy (path);
1073       GMC_destroy (c);
1074       return GNUNET_OK;
1075     }
1076     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Own position: %u\n", own_pos);
1077     path_add_to_peers (path, GNUNET_NO);
1078         LOG (GNUNET_ERROR_TYPE_DEBUG, "  Creating connection\n");
1079     c = GMC_new (cid, NULL, path_duplicate (path), own_pos);
1080     if (NULL == c)
1081       return GNUNET_OK;
1082     connection_reset_timeout (c, GNUNET_YES);
1083   }
1084   else
1085   {
1086     path = NULL;
1087   }
1088   if (MESH_CONNECTION_NEW == c->state)
1089     connection_change_state (c, MESH_CONNECTION_SENT);
1090
1091   /* Remember peers */
1092   dest_peer = peer_get (&id[size - 1]);
1093   orig_peer = peer_get (&id[0]);
1094
1095   /* Is it a connection to us? */
1096   if (c->own_pos == size - 1)
1097   {
1098     LOG (GNUNET_ERROR_TYPE_DEBUG, "  It's for us!\n");
1099     peer_add_path_to_origin (orig_peer, path, GNUNET_YES);
1100
1101     if (NULL == orig_peer->tunnel)
1102     {
1103       orig_peer->tunnel = tunnel_new ();
1104       orig_peer->tunnel->peer = orig_peer;
1105     }
1106     GMT_add_connection (orig_peer->tunnel, c);
1107     if (MESH_TUNNEL_NEW == GMT_get_state (c->t))
1108       GMT_change_state (c->t,  MESH_TUNNEL_WAITING);
1109
1110     send_connection_ack (c, GNUNET_NO);
1111     if (MESH_CONNECTION_SENT == c->state)
1112       connection_change_state (c, MESH_CONNECTION_ACK);
1113
1114     /* Keep tunnel alive in direction dest->owner*/
1115     connection_reset_timeout (c, GNUNET_NO);
1116   }
1117   else
1118   {
1119     /* It's for somebody else! Retransmit. */
1120     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Retransmitting.\n");
1121     peer_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
1122     peer_add_path_to_origin (orig_peer, path, GNUNET_NO);
1123     GMC_send_prebuilt_message (message, c, NULL, GNUNET_YES);
1124   }
1125   return GNUNET_OK;
1126 }
1127
1128
1129 /**
1130  * Core handler for path confirmations.
1131  *
1132  * @param cls closure
1133  * @param message message
1134  * @param peer peer identity this notification is about
1135  *
1136  * @return GNUNET_OK to keep the connection open,
1137  *         GNUNET_SYSERR to close it (signal serious error)
1138  */
1139 int
1140 GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer,
1141                     const struct GNUNET_MessageHeader *message)
1142 {
1143   struct GNUNET_MESH_ConnectionACK *msg;
1144   struct MeshConnection *c;
1145   struct MeshPeerPath *p;
1146   struct MeshPeer *pi;
1147   int fwd;
1148
1149   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1150   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a connection ACK msg\n");
1151   msg = (struct GNUNET_MESH_ConnectionACK *) message;
1152   LOG (GNUNET_ERROR_TYPE_DEBUG, "  on connection %s\n",
1153               GNUNET_h2s (&msg->cid));
1154   c = connection_get (&msg->cid);
1155   if (NULL == c)
1156   {
1157     GNUNET_STATISTICS_update (stats, "# control on unknown connection",
1158                               1, GNUNET_NO);
1159     LOG (GNUNET_ERROR_TYPE_DEBUG, "  don't know the connection!\n");
1160     return GNUNET_OK;
1161   }
1162
1163
1164   LOG (GNUNET_ERROR_TYPE_DEBUG, "  via peer %s\n",
1165               GNUNET_i2s (peer));
1166   pi = peer_get (peer);
1167   if (connection_get_next_hop (c) == pi)
1168   {
1169     LOG (GNUNET_ERROR_TYPE_DEBUG, "  SYNACK\n");
1170     fwd = GNUNET_NO;
1171     if (MESH_CONNECTION_SENT == c->state)
1172       connection_change_state (c, MESH_CONNECTION_ACK);
1173   }
1174   else if (connection_get_prev_hop (c) == pi)
1175   {
1176     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ACK\n");
1177     fwd = GNUNET_YES;
1178     connection_change_state (c, MESH_CONNECTION_READY);
1179   }
1180   else
1181   {
1182     GNUNET_break_op (0);
1183     return GNUNET_OK;
1184   }
1185   connection_reset_timeout (c, fwd);
1186
1187   /* Add path to peers? */
1188   p = c->path;
1189   if (NULL != p)
1190   {
1191     path_add_to_peers (p, GNUNET_YES);
1192   }
1193   else
1194   {
1195     GNUNET_break (0);
1196   }
1197
1198   /* Message for us as creator? */
1199   if (GMC_is_origin (c, GNUNET_YES))
1200   {
1201     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Connection (SYN)ACK for us!\n");
1202     connection_change_state (c, MESH_CONNECTION_READY);
1203     GMT_change_state (c->t, MESH_TUNNEL_READY);
1204     send_connection_ack (c, GNUNET_YES);
1205     GMT_send_queued_data (c->t, GNUNET_YES);
1206     return GNUNET_OK;
1207   }
1208
1209   /* Message for us as destination? */
1210   if (GMC_is_terminal (c, GNUNET_YES))
1211   {
1212     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Connection ACK for us!\n");
1213     GMC_change_state (c, MESH_CONNECTION_READY);
1214     GMT_change_state (c->t, MESH_TUNNEL_READY);
1215     GMT_send_queued_data (c->t, GNUNET_NO);
1216     return GNUNET_OK;
1217   }
1218
1219   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
1220   GMC_send_prebuilt_message (message, c, NULL, fwd);
1221   return GNUNET_OK;
1222 }
1223
1224
1225 /**
1226  * Core handler for notifications of broken paths
1227  *
1228  * @param cls Closure (unused).
1229  * @param peer Peer identity of sending neighbor.
1230  * @param message Message.
1231  *
1232  * @return GNUNET_OK to keep the connection open,
1233  *         GNUNET_SYSERR to close it (signal serious error)
1234  */
1235 int
1236 GMC_handle_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
1237                    const struct GNUNET_MessageHeader *message)
1238 {
1239   struct GNUNET_MESH_ConnectionBroken *msg;
1240   struct MeshConnection *c;
1241
1242   LOG (GNUNET_ERROR_TYPE_DEBUG,
1243               "Received a CONNECTION BROKEN msg from %s\n", GNUNET_i2s (peer));
1244   msg = (struct GNUNET_MESH_ConnectionBroken *) message;
1245   LOG (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
1246               GNUNET_i2s (&msg->peer1));
1247   LOG (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
1248               GNUNET_i2s (&msg->peer2));
1249   c = connection_get (&msg->cid);
1250   if (NULL == c)
1251   {
1252     GNUNET_break_op (0);
1253     return GNUNET_OK;
1254   }
1255   tunnel_notify_connection_broken (c->t, GNUNET_PEER_search (&msg->peer1),
1256                                    GNUNET_PEER_search (&msg->peer2));
1257   return GNUNET_OK;
1258
1259 }
1260
1261
1262 /**
1263  * Core handler for tunnel destruction
1264  *
1265  * @param cls Closure (unused).
1266  * @param peer Peer identity of sending neighbor.
1267  * @param message Message.
1268  *
1269  * @return GNUNET_OK to keep the connection open,
1270  *         GNUNET_SYSERR to close it (signal serious error)
1271  */
1272 int
1273 GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
1274                     const struct GNUNET_MessageHeader *message)
1275 {
1276   struct GNUNET_MESH_ConnectionDestroy *msg;
1277   struct MeshConnection *c;
1278   GNUNET_PEER_Id id;
1279   int fwd;
1280
1281   msg = (struct GNUNET_MESH_ConnectionDestroy *) message;
1282   LOG (GNUNET_ERROR_TYPE_DEBUG,
1283               "Got a CONNECTION DESTROY message from %s\n",
1284               GNUNET_i2s (peer));
1285   LOG (GNUNET_ERROR_TYPE_DEBUG,
1286               "  for connection %s\n",
1287               GNUNET_h2s (&msg->cid));
1288   c = connection_get (&msg->cid);
1289   if (NULL == c)
1290   {
1291     /* Probably already got the message from another path,
1292      * destroyed the tunnel and retransmitted to children.
1293      * Safe to ignore.
1294      */
1295     GNUNET_STATISTICS_update (stats, "# control on unknown tunnel",
1296                               1, GNUNET_NO);
1297     return GNUNET_OK;
1298   }
1299   id = GNUNET_PEER_search (peer);
1300   if (id == GMP_get_short_id (connection_get_prev_hop (c)))
1301     fwd = GNUNET_YES;
1302   else if (id == GMP_get_short_id (connection_get_next_hop (c)))
1303     fwd = GNUNET_NO;
1304   else
1305   {
1306     GNUNET_break_op (0);
1307     return GNUNET_OK;
1308   }
1309   GMC_send_prebuilt_message (message, c, NULL, fwd);
1310   c->destroy = GNUNET_YES;
1311
1312   return GNUNET_OK;
1313 }
1314
1315 /**
1316  * Generic handler for mesh network encrypted traffic.
1317  *
1318  * @param peer Peer identity this notification is about.
1319  * @param message Encrypted message.
1320  * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1321  *
1322  * @return GNUNET_OK to keep the connection open,
1323  *         GNUNET_SYSERR to close it (signal serious error)
1324  */
1325 static int
1326 handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer,
1327                        const struct GNUNET_MESH_Encrypted *msg,
1328                        int fwd)
1329 {
1330   struct MeshConnection *c;
1331   struct MeshTunnel3 *t;
1332   struct MeshPeer *neighbor;
1333   struct MeshFlowControl *fc;
1334   uint32_t pid;
1335   uint32_t ttl;
1336   uint16_t type;
1337   size_t size;
1338
1339   /* Check size */
1340   size = ntohs (msg->header.size);
1341   if (size <
1342       sizeof (struct GNUNET_MESH_Encrypted) +
1343       sizeof (struct GNUNET_MessageHeader))
1344   {
1345     GNUNET_break_op (0);
1346     return GNUNET_OK;
1347   }
1348   type = ntohs (msg->header.type);
1349   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1350   LOG (GNUNET_ERROR_TYPE_DEBUG, "got a %s message from %s\n",
1351               GNUNET_MESH_DEBUG_M2S (type), GNUNET_i2s (peer));
1352
1353   /* Check connection */
1354   c = connection_get (&msg->cid);
1355   if (NULL == c)
1356   {
1357     GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
1358     LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING connection unknown\n");
1359     return GNUNET_OK;
1360   }
1361   t = c->t;
1362   fc = fwd ? &c->bck_fc : &c->fwd_fc;
1363
1364   /* Check if origin is as expected */
1365   neighbor = connection_get_hop (c, !fwd);
1366   if (GNUNET_PEER_search (peer) != GMP_get_short_id (neighbor))
1367   {
1368     GNUNET_break_op (0);
1369     return GNUNET_OK;
1370   }
1371
1372   /* Check PID */
1373   pid = ntohl (msg->pid);
1374   if (GMC_is_pid_bigger (pid, fc->last_ack_sent))
1375   {
1376     GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
1377     LOG (GNUNET_ERROR_TYPE_DEBUG,
1378                 "WARNING Received PID %u, (prev %u), ACK %u\n",
1379                 pid, fc->last_pid_recv, fc->last_ack_sent);
1380     return GNUNET_OK;
1381   }
1382   if (GNUNET_NO == GMC_is_pid_bigger (pid, fc->last_pid_recv))
1383   {
1384     GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO);
1385     LOG (GNUNET_ERROR_TYPE_DEBUG,
1386                 " Pid %u not expected (%u+), dropping!\n",
1387                 pid, fc->last_pid_recv + 1);
1388     return GNUNET_OK;
1389   }
1390   if (MESH_CONNECTION_SENT == c->state)
1391     connection_change_state (c, MESH_CONNECTION_READY);
1392   connection_reset_timeout (c, fwd);
1393   fc->last_pid_recv = pid;
1394
1395   /* Is this message for us? */
1396   if (GMC_is_terminal (c, fwd))
1397   {
1398     size_t dsize = size - sizeof (struct GNUNET_MESH_Encrypted);
1399     char cbuf[dsize];
1400     struct GNUNET_MessageHeader *msgh;
1401     unsigned int off;
1402
1403     /* TODO signature verification */
1404     LOG (GNUNET_ERROR_TYPE_DEBUG, "  message for us!\n");
1405     GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
1406
1407     fc->last_pid_recv = pid;
1408     tunnel_decrypt (t, cbuf, &msg[1], dsize, msg->iv, fwd);
1409     off = 0;
1410     while (off < dsize)
1411     {
1412       msgh = (struct GNUNET_MessageHeader *) &cbuf[off];
1413       handle_decrypted (t, msgh, fwd);
1414       off += ntohs (msgh->size);
1415     }
1416     send_ack (c, NULL, fwd);
1417     return GNUNET_OK;
1418   }
1419
1420   /* Message not for us: forward to next hop */
1421   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
1422   ttl = ntohl (msg->ttl);
1423   LOG (GNUNET_ERROR_TYPE_DEBUG, "   ttl: %u\n", ttl);
1424   if (ttl == 0)
1425   {
1426     GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
1427     LOG (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
1428     send_ack (c, NULL, fwd);
1429     return GNUNET_OK;
1430   }
1431   GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
1432
1433   send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
1434
1435   return GNUNET_OK;
1436 }
1437
1438
1439 /**
1440  * Core handler for mesh network traffic going orig->dest.
1441  *
1442  * @param cls Closure (unused).
1443  * @param message Message received.
1444  * @param peer Peer who sent the message.
1445  *
1446  * @return GNUNET_OK to keep the connection open,
1447  *         GNUNET_SYSERR to close it (signal serious error)
1448  */
1449 int
1450 GMC_handle_fwd (void *cls, const struct GNUNET_PeerIdentity *peer,
1451                 const struct GNUNET_MessageHeader *message)
1452 {
1453   return handle_mesh_encrypted (peer,
1454                                 (struct GNUNET_MESH_Encrypted *)message,
1455                                 GNUNET_YES);
1456 }
1457
1458 /**
1459  * Core handler for mesh network traffic going dest->orig.
1460  *
1461  * @param cls Closure (unused).
1462  * @param message Message received.
1463  * @param peer Peer who sent the message.
1464  *
1465  * @return GNUNET_OK to keep the connection open,
1466  *         GNUNET_SYSERR to close it (signal serious error)
1467  */
1468 int
1469 GMC_handle_bck (void *cls, const struct GNUNET_PeerIdentity *peer,
1470                 const struct GNUNET_MessageHeader *message)
1471 {
1472   return handle_mesh_encrypted (peer,
1473                                 (struct GNUNET_MESH_Encrypted *)message,
1474                                 GNUNET_NO);
1475 }
1476
1477
1478 /**
1479  * Core handler for mesh network traffic point-to-point acks.
1480  *
1481  * @param cls closure
1482  * @param message message
1483  * @param peer peer identity this notification is about
1484  *
1485  * @return GNUNET_OK to keep the connection open,
1486  *         GNUNET_SYSERR to close it (signal serious error)
1487  */
1488 int
1489 GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
1490                 const struct GNUNET_MessageHeader *message)
1491 {
1492   struct GNUNET_MESH_ACK *msg;
1493   struct MeshConnection *c;
1494   struct MeshFlowControl *fc;
1495   GNUNET_PEER_Id id;
1496   uint32_t ack;
1497   int fwd;
1498
1499   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1500   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
1501               GNUNET_i2s (peer));
1502   msg = (struct GNUNET_MESH_ACK *) message;
1503
1504   c = connection_get (&msg->cid);
1505
1506   if (NULL == c)
1507   {
1508     GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1,
1509                               GNUNET_NO);
1510     return GNUNET_OK;
1511   }
1512
1513   /* Is this a forward or backward ACK? */
1514   id = GNUNET_PEER_search (peer);
1515   if (GMP_get_short_id (connection_get_next_hop (c)) == id)
1516   {
1517     LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
1518     fc = &c->fwd_fc;
1519     fwd = GNUNET_YES;
1520   }
1521   else if (GMP_get_short_id (connection_get_prev_hop (c)) == id)
1522   {
1523     LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK ACK\n");
1524     fc = &c->bck_fc;
1525     fwd = GNUNET_NO;
1526   }
1527   else
1528   {
1529     GNUNET_break_op (0);
1530     return GNUNET_OK;
1531   }
1532
1533   ack = ntohl (msg->ack);
1534   LOG (GNUNET_ERROR_TYPE_DEBUG, "  ACK %u (was %u)\n",
1535               ack, fc->last_ack_recv);
1536   if (GMC_is_pid_bigger (ack, fc->last_ack_recv))
1537     fc->last_ack_recv = ack;
1538
1539   /* Cancel polling if the ACK is big enough. */
1540   if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task &&
1541       GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
1542   {
1543     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Cancel poll\n");
1544     GNUNET_SCHEDULER_cancel (fc->poll_task);
1545     fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
1546     fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
1547   }
1548
1549   connection_unlock_queue (c, fwd);
1550
1551   return GNUNET_OK;
1552 }
1553
1554
1555 /**
1556  * Core handler for mesh network traffic point-to-point ack polls.
1557  *
1558  * @param cls closure
1559  * @param message message
1560  * @param peer peer identity this notification is about
1561  *
1562  * @return GNUNET_OK to keep the connection open,
1563  *         GNUNET_SYSERR to close it (signal serious error)
1564  */
1565 int
1566 GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
1567                  const struct GNUNET_MessageHeader *message)
1568 {
1569   struct GNUNET_MESH_Poll *msg;
1570   struct MeshConnection *c;
1571   struct MeshFlowControl *fc;
1572   GNUNET_PEER_Id id;
1573   uint32_t pid;
1574   int fwd;
1575
1576   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1577   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a POLL packet from %s!\n",
1578               GNUNET_i2s (peer));
1579
1580   msg = (struct GNUNET_MESH_Poll *) message;
1581
1582   c = connection_get (&msg->cid);
1583
1584   if (NULL == c)
1585   {
1586     GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
1587                               GNUNET_NO);
1588     GNUNET_break_op (0);
1589     return GNUNET_OK;
1590   }
1591
1592   /* Is this a forward or backward ACK?
1593    * Note: a poll should never be needed in a loopback case,
1594    * since there is no possiblility of packet loss there, so
1595    * this way of discerining FWD/BCK should not be a problem.
1596    */
1597   id = GNUNET_PEER_search (peer);
1598   if (GMP_get_short_id (connection_get_next_hop (c)) == id)
1599   {
1600     LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
1601     fc = &c->fwd_fc;
1602   }
1603   else if (GMP_get_short_id (connection_get_prev_hop (c)) == id)
1604   {
1605     LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK ACK\n");
1606     fc = &c->bck_fc;
1607   }
1608   else
1609   {
1610     GNUNET_break_op (0);
1611     return GNUNET_OK;
1612   }
1613
1614   pid = ntohl (msg->pid);
1615   LOG (GNUNET_ERROR_TYPE_DEBUG, "  PID %u, OLD %u\n",
1616               pid, fc->last_pid_recv);
1617   fc->last_pid_recv = pid;
1618   fwd = fc == &c->fwd_fc;
1619   send_ack (c, NULL, fwd);
1620
1621   return GNUNET_OK;
1622 }
1623
1624
1625 /**
1626  * Core handler for mesh keepalives.
1627  *
1628  * @param cls closure
1629  * @param message message
1630  * @param peer peer identity this notification is about
1631  * @return GNUNET_OK to keep the connection open,
1632  *         GNUNET_SYSERR to close it (signal serious error)
1633  *
1634  * TODO: Check who we got this from, to validate route.
1635  */
1636 int
1637 GMC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
1638                       const struct GNUNET_MessageHeader *message)
1639 {
1640   struct GNUNET_MESH_ConnectionKeepAlive *msg;
1641   struct MeshConnection *c;
1642   struct MeshPeer *neighbor;
1643   int fwd;
1644
1645   msg = (struct GNUNET_MESH_ConnectionKeepAlive *) message;
1646   LOG (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
1647               GNUNET_i2s (peer));
1648
1649   c = connection_get (&msg->cid);
1650   if (NULL == c)
1651   {
1652     GNUNET_STATISTICS_update (stats, "# keepalive on unknown connection", 1,
1653                               GNUNET_NO);
1654     return GNUNET_OK;
1655   }
1656
1657   fwd = GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE == ntohs (message->type) ?
1658         GNUNET_YES : GNUNET_NO;
1659
1660   /* Check if origin is as expected */
1661   neighbor = connection_get_hop (c, fwd);
1662   if (GNUNET_PEER_search (peer) != GMP_get_short_id (neighbor))
1663   {
1664     GNUNET_break_op (0);
1665     return GNUNET_OK;
1666   }
1667
1668   connection_change_state (c, MESH_CONNECTION_READY);
1669   connection_reset_timeout (c, fwd);
1670
1671   if (GMC_is_terminal (c, fwd))
1672     return GNUNET_OK;
1673
1674   GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
1675   GMC_send_prebuilt_message (message, c, NULL, fwd);
1676
1677   return GNUNET_OK;
1678 }
1679
1680
1681 /**
1682  * Send an ACK on the appropriate connection/channel, depending on
1683  * the direction and the position of the peer.
1684  *
1685  * @param c Which connection to send the hop-by-hop ACK.
1686  * @param ch Channel, if any.
1687  * @param fwd Is this a fwd ACK? (will go dest->root)
1688  */
1689 void
1690 GMC_send_ack (struct MeshConnection *c, struct MeshChannel *ch, int fwd)
1691 {
1692   unsigned int buffer;
1693
1694   LOG (GNUNET_ERROR_TYPE_DEBUG,
1695               "send ack %s on %p %p\n",
1696               fwd ? "FWD" : "BCK", c, ch);
1697   if (NULL == c || GMC_is_terminal (c, fwd))
1698   {
1699     struct MeshTunnel3 *t;
1700     LOG (GNUNET_ERROR_TYPE_DEBUG, "  getting from all connections\n");
1701     t = (NULL == c) ? GMCH_get_tunnel (ch) : GMC_get_tunnel (c);
1702     buffer = GMT_get_buffer (t, fwd);
1703   }
1704   else
1705   {
1706     LOG (GNUNET_ERROR_TYPE_DEBUG, "  getting from one connection\n");
1707     buffer = GMC_get_buffer (c, fwd);
1708   }
1709   LOG (GNUNET_ERROR_TYPE_DEBUG, "  buffer available: %u\n", buffer);
1710
1711   if ( (NULL != ch && GMCH_is_origin (ch, fwd)) ||
1712        (NULL != c && GMC_is_origin (c, fwd)) )
1713   {
1714     LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on channel...\n");
1715     if (0 < buffer)
1716     {
1717       GNUNET_assert (NULL != ch);
1718       LOG (GNUNET_ERROR_TYPE_DEBUG, "  really sending!\n");
1719       send_local_ack (ch, fwd);
1720     }
1721   }
1722   else if (NULL == c)
1723   {
1724     LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on all connections\n");
1725     GNUNET_assert (NULL != ch);
1726     channel_send_connections_ack (ch, buffer, fwd);
1727   }
1728   else
1729   {
1730     LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on connection\n");
1731     connection_send_ack (c, buffer, fwd);
1732   }
1733 }
1734
1735
1736 /**
1737  * Initialize the connections subsystem
1738  *
1739  * @param c Configuration handle.
1740  */
1741 void
1742 GMC_init (const struct GNUNET_CONFIGURATION_Handle *c)
1743 {
1744   if (GNUNET_OK !=
1745       GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE",
1746                                              &max_msgs_queue))
1747   {
1748     LOG_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1749                                "MESH", "MAX_MSGS_QUEUE", "MISSING");
1750     GNUNET_SCHEDULER_shutdown ();
1751     return;
1752   }
1753
1754   if (GNUNET_OK !=
1755       GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_CONNECTIONS",
1756                                              &max_connections))
1757   {
1758     LOG_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1759                                "MESH", "MAX_CONNECTIONS", "MISSING");
1760     GNUNET_SCHEDULER_shutdown ();
1761     return;
1762   }
1763
1764   if (GNUNET_OK !=
1765       GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_CONNECTION_TIME",
1766                                            &refresh_connection_time))
1767   {
1768     LOG_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1769                                "MESH", "REFRESH_CONNECTION_TIME", "MISSING");
1770     GNUNET_SCHEDULER_shutdown ();
1771     return;
1772   }
1773   connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES);
1774 }
1775
1776 /**
1777  * Shut down the connections subsystem.
1778  */
1779 void
1780 GMC_shutdown (void)
1781 {
1782 }
1783
1784
1785 struct MeshConnection *
1786 GMC_new (const struct GNUNET_HashCode *cid,
1787          struct MeshTunnel3 *t,
1788          struct MeshPeerPath *p,
1789          unsigned int own_pos)
1790 {
1791   struct MeshConnection *c;
1792
1793   c = GNUNET_new (struct MeshConnection);
1794   c->id = *cid;
1795   GNUNET_CONTAINER_multihashmap_put (connections, &c->id, c,
1796                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1797   fc_init (&c->fwd_fc);
1798   fc_init (&c->bck_fc);
1799   c->fwd_fc.c = c;
1800   c->bck_fc.c = c;
1801
1802   c->t = t;
1803   if (own_pos > p->length - 1)
1804   {
1805     GNUNET_break (0);
1806     GMC_destroy (c);
1807     return NULL;
1808   }
1809   c->own_pos = own_pos;
1810   c->path = p;
1811
1812   if (0 == own_pos)
1813   {
1814     c->fwd_maintenance_task =
1815             GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
1816                                           &connection_fwd_keepalive, c);
1817   }
1818   register_neighbors (c);
1819   return c;
1820 }
1821
1822
1823 void
1824 GMC_destroy (struct MeshConnection *c)
1825 {
1826   struct MeshPeer *peer;
1827
1828   if (NULL == c)
1829     return;
1830
1831   LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s\n",
1832        GNUNET_h2s (&c->id));
1833
1834   /* Cancel all traffic */
1835   connection_cancel_queues (c, GNUNET_YES);
1836   connection_cancel_queues (c, GNUNET_NO);
1837
1838   /* Cancel maintainance task (keepalive/timeout) */
1839   if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task)
1840     GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
1841   if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task)
1842     GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
1843
1844   /* Unregister from neighbors */
1845   unregister_neighbors (c);
1846
1847   /* Delete */
1848   GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO);
1849   GMT_remove_connection (c->t, c);
1850   GNUNET_free (c);
1851 }
1852
1853 /**
1854  * Get the connection ID.
1855  *
1856  * @param c Connection to get the ID from.
1857  *
1858  * @return ID of the connection.
1859  */
1860 const struct GNUNET_HashCode *
1861 GMC_get_id (const struct MeshConnection *c)
1862 {
1863   return &c->id;
1864 }
1865
1866
1867 /**
1868  * Get the connection state.
1869  *
1870  * @param c Connection to get the state from.
1871  *
1872  * @return state of the connection.
1873  */
1874 enum MeshConnectionState
1875 GMC_get_state (const struct MeshConnection *c)
1876 {
1877   return c->state;
1878 }
1879
1880 /**
1881  * Get the connection tunnel.
1882  *
1883  * @param c Connection to get the tunnel from.
1884  *
1885  * @return tunnel of the connection.
1886  */
1887 struct MeshTunnel3 *
1888 GMC_get_tunnel (const struct MeshConnection *c)
1889 {
1890   return c->t;
1891 }
1892
1893
1894 /**
1895  * Get free buffer space in a connection.
1896  *
1897  * @param c Connection.
1898  * @param fwd Is query about FWD traffic?
1899  *
1900  * @return Free buffer space [0 - max_msgs_queue/max_connections]
1901  */
1902 unsigned int
1903 GMC_get_buffer (struct MeshConnection *c, int fwd)
1904 {
1905   struct MeshFlowControl *fc;
1906
1907   fc = fwd ? &c->fwd_fc : &c->bck_fc;
1908
1909   return (fc->queue_max - fc->queue_n);
1910 }
1911
1912 /**
1913  * Get messages queued in a connection.
1914  *
1915  * @param c Connection.
1916  * @param fwd Is query about FWD traffic?
1917  *
1918  * @return Number of messages queued.
1919  */
1920 unsigned int
1921 GMC_get_qn (struct MeshConnection *c, int fwd)
1922 {
1923   struct MeshFlowControl *fc;
1924
1925   fc = fwd ? &c->fwd_fc : &c->bck_fc;
1926
1927   return fc->queue_n;
1928 }
1929
1930
1931 /**
1932  * Notify other peers on a connection of a broken link. Mark connections
1933  * to destroy after all traffic has been sent.
1934  *
1935  * @param c Connection on which there has been a disconnection.
1936  * @param peer Peer that disconnected.
1937  * @param my_full_id My ID (to send to other peers).
1938  */
1939 void
1940 GMC_notify_broken (struct MeshConnection *c,
1941                    struct MeshPeer *peer,
1942                    struct GNUNET_PeerIdentity *my_full_id)
1943 {
1944   struct GNUNET_MESH_ConnectionBroken msg;
1945   int fwd;
1946
1947   fwd = peer == connection_get_prev_hop (c);
1948
1949   connection_cancel_queues (c, !fwd);
1950   if (GMC_is_terminal (c, fwd))
1951   {
1952     /* Local shutdown, no one to notify about this. */
1953     GMC_destroy (c);
1954     return;
1955   }
1956
1957   msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectionBroken));
1958   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN);
1959   msg.cid = c->id;
1960   msg.peer1 = *my_full_id;
1961   msg.peer2 = *GMP_get_id (peer);
1962   GMC_send_prebuilt_message (&msg.header, c, NULL, fwd);
1963   c->destroy = GNUNET_YES;
1964
1965   return;
1966 }
1967
1968
1969 /**
1970  * Is this peer the first one on the connection?
1971  *
1972  * @param c Connection.
1973  * @param fwd Is this about fwd traffic?
1974  *
1975  * @return GNUNET_YES if origin, GNUNET_NO if relay/terminal.
1976  */
1977 int
1978 GMC_is_origin (struct MeshConnection *c, int fwd)
1979 {
1980   if (!fwd && c->path->length - 1 == c->own_pos )
1981     return GNUNET_YES;
1982   if (fwd && 0 == c->own_pos)
1983     return GNUNET_YES;
1984   return GNUNET_NO;
1985 }
1986
1987
1988 /**
1989  * Is this peer the last one on the connection?
1990  *
1991  * @param c Connection.
1992  * @param fwd Is this about fwd traffic?
1993  *            Note that the ROOT is the terminal for BCK traffic!
1994  *
1995  * @return GNUNET_YES if terminal, GNUNET_NO if relay/origin.
1996  */
1997 int
1998 GMC_is_terminal (struct MeshConnection *c, int fwd)
1999 {
2000   return GMC_is_origin (c, !fwd);
2001 }
2002
2003
2004 /**
2005  * Sends an already built message on a connection, properly registering
2006  * all used resources.
2007  *
2008  * @param message Message to send. Function makes a copy of it.
2009  *                If message is not hop-by-hop, decrements TTL of copy.
2010  * @param c Connection on which this message is transmitted.
2011  * @param ch Channel on which this message is transmitted, or NULL.
2012  * @param fwd Is this a fwd message?
2013  */
2014 void
2015 GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2016                            struct MeshConnection *c,
2017                            struct MeshChannel *ch,
2018                            int fwd)
2019 {
2020   void *data;
2021   size_t size;
2022   uint16_t type;
2023
2024   size = ntohs (message->size);
2025   data = GNUNET_malloc (size);
2026   memcpy (data, message, size);
2027   type = ntohs (message->type);
2028   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send %s (%u) on connection %s\n",
2029               GNUNET_MESH_DEBUG_M2S (type), size, GNUNET_h2s (&c->id));
2030
2031   switch (type)
2032   {
2033     struct GNUNET_MESH_Encrypted *emsg;
2034     struct GNUNET_MESH_ACK       *amsg;
2035     struct GNUNET_MESH_Poll      *pmsg;
2036     struct GNUNET_MESH_ConnectionDestroy *dmsg;
2037     struct GNUNET_MESH_ConnectionBroken  *bmsg;
2038     uint32_t ttl;
2039
2040     case GNUNET_MESSAGE_TYPE_MESH_FWD:
2041     case GNUNET_MESSAGE_TYPE_MESH_BCK:
2042       emsg = (struct GNUNET_MESH_Encrypted *) data;
2043       ttl = ntohl (emsg->ttl);
2044       if (0 == ttl)
2045       {
2046         GNUNET_break_op (0);
2047         return;
2048       }
2049       emsg->cid = c->id;
2050       emsg->ttl = htonl (ttl - 1);
2051       emsg->pid = htonl (fwd ? c->fwd_fc.next_pid++ : c->bck_fc.next_pid++);
2052       LOG (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", ntohl (emsg->pid));
2053       break;
2054
2055     case GNUNET_MESSAGE_TYPE_MESH_ACK:
2056       amsg = (struct GNUNET_MESH_ACK *) data;
2057       amsg->cid = c->id;
2058       LOG (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ntohl (amsg->ack));
2059       break;
2060
2061     case GNUNET_MESSAGE_TYPE_MESH_POLL:
2062       pmsg = (struct GNUNET_MESH_Poll *) data;
2063       pmsg->cid = c->id;
2064       pmsg->pid = htonl (fwd ? c->fwd_fc.last_pid_sent : c->bck_fc.last_pid_sent);
2065       LOG (GNUNET_ERROR_TYPE_DEBUG, " poll %u\n", ntohl (pmsg->pid));
2066       break;
2067
2068     case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
2069       dmsg = (struct GNUNET_MESH_ConnectionDestroy *) data;
2070       dmsg->cid = c->id;
2071       dmsg->reserved = 0;
2072       break;
2073
2074     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
2075       bmsg = (struct GNUNET_MESH_ConnectionBroken *) data;
2076       bmsg->cid = c->id;
2077       bmsg->reserved = 0;
2078       break;
2079
2080     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
2081     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
2082       break;
2083
2084     default:
2085       GNUNET_break (0);
2086   }
2087
2088   GMP_queue_add (data, type, size, c, ch, fwd, &message_sent, (void *) size);
2089 }
2090
2091
2092 /**
2093  * Send a message to all peers in this connection that the connection
2094  * is no longer valid.
2095  *
2096  * If some peer should not receive the message, it should be zero'ed out
2097  * before calling this function.
2098  *
2099  * @param c The connection whose peers to notify.
2100  */
2101 void
2102 GMC_send_destroy (struct MeshConnection *c)
2103 {
2104   struct GNUNET_MESH_ConnectionDestroy msg;
2105
2106   if (GNUNET_YES == c->destroy)
2107     return;
2108
2109   msg.header.size = htons (sizeof (msg));
2110   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY);;
2111   msg.cid = c->id;
2112   LOG (GNUNET_ERROR_TYPE_DEBUG,
2113               "  sending connection destroy for connection %s\n",
2114               GNUNET_h2s (&c->id));
2115
2116   if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES))
2117     GMC_send_prebuilt_message (&msg.header, c, NULL, GNUNET_YES);
2118   if (GNUNET_NO == GMC_is_terminal (c, GNUNET_NO))
2119     GMC_send_prebuilt_message (&msg.header, c, NULL, GNUNET_NO);
2120   c->destroy = GNUNET_YES;
2121 }