- local channel id better accounted for per-client
[oweals/gnunet.git] / src / mesh / gnunet-service-mesh_channel.c
1 /*
2      This file is part of GNUnet.
3      (C) 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 #include "platform.h"
23 #include "gnunet_util_lib.h"
24
25 #include "gnunet_statistics_service.h"
26
27 #include "mesh_enc.h"
28 #include "mesh_protocol_enc.h"
29
30 #include "gnunet-service-mesh_channel.h"
31 #include "gnunet-service-mesh_local.h"
32 #include "gnunet-service-mesh_tunnel.h"
33
34 #define LOG(level, ...) GNUNET_log_from(level,"mesh-chn",__VA_ARGS__)
35
36 #define MESH_RETRANSMIT_TIME    GNUNET_TIME_UNIT_SECONDS
37 #define MESH_RETRANSMIT_MARGIN  4
38
39
40 /**
41  * All the states a connection can be in.
42  */
43 enum MeshChannelState
44 {
45   /**
46    * Uninitialized status, should never appear in operation.
47    */
48   MESH_CHANNEL_NEW,
49
50   /**
51    * Connection create message sent, waiting for ACK.
52    */
53   MESH_CHANNEL_SENT,
54
55   /**
56    * Connection confirmed, ready to carry traffic..
57    */
58   MESH_CHANNEL_READY,
59 };
60
61
62
63 /**
64  * Info needed to retry a message in case it gets lost.
65  */
66 struct MeshReliableMessage
67 {
68     /**
69      * Double linked list, FIFO style
70      */
71   struct MeshReliableMessage    *next;
72   struct MeshReliableMessage    *prev;
73
74     /**
75      * Type of message (payload, channel management).
76      */
77   int16_t type;
78
79     /**
80      * Tunnel Reliability queue this message is in.
81      */
82   struct MeshChannelReliability  *rel;
83
84     /**
85      * ID of the message (ACK needed to free)
86      */
87   uint32_t                      mid;
88
89     /**
90      * When was this message issued (to calculate ACK delay)
91      */
92   struct GNUNET_TIME_Absolute   timestamp;
93
94   /* struct GNUNET_MESH_Data with payload */
95 };
96
97
98 /**
99  * Info about the traffic state for a client in a channel.
100  */
101 struct MeshChannelReliability
102 {
103     /**
104      * Channel this is about.
105      */
106   struct MeshChannel *ch;
107
108     /**
109      * DLL of messages sent and not yet ACK'd.
110      */
111   struct MeshReliableMessage        *head_sent;
112   struct MeshReliableMessage        *tail_sent;
113
114     /**
115      * Messages pending to send.
116      */
117   unsigned int                      n_sent;
118
119     /**
120      * DLL of messages received out of order.
121      */
122   struct MeshReliableMessage        *head_recv;
123   struct MeshReliableMessage        *tail_recv;
124
125     /**
126      * Messages received.
127      */
128   unsigned int                      n_recv;
129
130     /**
131      * Next MID to use for outgoing traffic.
132      */
133   uint32_t                          mid_send;
134
135     /**
136      * Next MID expected for incoming traffic.
137      */
138   uint32_t                          mid_recv;
139
140     /**
141      * Can we send data to the client?
142      */
143   int                               client_ready;
144
145     /**
146      * Task to resend/poll in case no ACK is received.
147      */
148   GNUNET_SCHEDULER_TaskIdentifier   retry_task;
149
150     /**
151      * Counter for exponential backoff.
152      */
153   struct GNUNET_TIME_Relative       retry_timer;
154
155     /**
156      * How long does it usually take to get an ACK.
157      */
158   struct GNUNET_TIME_Relative       expected_delay;
159 };
160
161
162 /**
163  * Struct containing all information regarding a channel to a remote client.
164  */
165 struct MeshChannel
166 {
167     /**
168      * Tunnel this channel is in.
169      */
170   struct MeshTunnel3 *t;
171
172     /**
173      * Destination port of the channel.
174      */
175   uint32_t port;
176
177     /**
178      * Global channel number ( < GNUNET_MESH_LOCAL_CHANNEL_ID_CLI)
179      */
180   MESH_ChannelNumber gid;
181
182     /**
183      * Local tunnel number for root (owner) client.
184      * ( >= GNUNET_MESH_LOCAL_CHANNEL_ID_CLI or 0 )
185      */
186   MESH_ChannelNumber lid_root;
187
188     /**
189      * Local tunnel number for local destination clients (incoming number)
190      * ( >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV or 0).
191      */
192   MESH_ChannelNumber lid_dest;
193
194     /**
195      * Channel state.
196      */
197   enum MeshChannelState state;
198
199     /**
200      * Is the tunnel bufferless (minimum latency)?
201      */
202   int nobuffer;
203
204     /**
205      * Is the tunnel reliable?
206      */
207   int reliable;
208
209     /**
210      * Last time the channel was used
211      */
212   struct GNUNET_TIME_Absolute timestamp;
213
214     /**
215      * Client owner of the tunnel, if any
216      */
217   struct MeshClient *root;
218
219     /**
220      * Client destination of the tunnel, if any.
221      */
222   struct MeshClient *dest;
223
224     /**
225      * Flag to signal the destruction of the channel.
226      * If this is set GNUNET_YES the channel will be destroyed
227      * when the queue is empty.
228      */
229   int destroy;
230
231     /**
232      * Total messages pending for this channel, payload or not.
233      */
234   unsigned int pending_messages;
235
236     /**
237      * Reliability data.
238      * Only present (non-NULL) at the owner of a tunnel.
239      */
240   struct MeshChannelReliability *root_rel;
241
242     /**
243      * Reliability data.
244      * Only present (non-NULL) at the destination of a tunnel.
245      */
246   struct MeshChannelReliability *dest_rel;
247
248 };
249
250
251 /******************************************************************************/
252 /*******************************   GLOBALS  ***********************************/
253 /******************************************************************************/
254
255 /**
256  * Global handle to the statistics service.
257  */
258 extern struct GNUNET_STATISTICS_Handle *stats;
259
260
261 /******************************************************************************/
262 /********************************   STATIC  ***********************************/
263 /******************************************************************************/
264
265 /**
266  * Destroy a reliable message after it has been acknowledged, either by
267  * direct mid ACK or bitfield. Updates the appropriate data structures and
268  * timers and frees all memory.
269  *
270  * @param copy Message that is no longer needed: remote peer got it.
271  */
272 static void
273 rel_message_free (struct MeshReliableMessage *copy);
274
275 /**
276  * We have received a message out of order, or the client is not ready.
277  * Buffer it until we receive an ACK from the client or the missing
278  * message from the channel.
279  *
280  * @param msg Message to buffer (MUST be of type MESH_DATA).
281  * @param rel Reliability data to the corresponding direction.
282  */
283 static void
284 add_buffered_data (const struct GNUNET_MESH_Data *msg,
285                    struct MeshChannelReliability *rel)
286 {
287   struct MeshReliableMessage *copy;
288   struct MeshReliableMessage *prev;
289   uint32_t mid;
290   uint16_t size;
291
292   size = ntohs (msg->header.size);
293   mid = ntohl (msg->mid);
294
295   LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data %u\n", mid);
296
297   copy = GNUNET_malloc (sizeof (*copy) + size);
298   copy->mid = mid;
299   copy->rel = rel;
300   memcpy (&copy[1], msg, size);
301
302   rel->n_recv++;
303
304   // FIXME do something better than O(n), although n < 64...
305   // FIXME start from the end (most messages are the latest ones)
306   for (prev = rel->head_recv; NULL != prev; prev = prev->next)
307   {
308     LOG (GNUNET_ERROR_TYPE_DEBUG, " prev %u\n", prev->mid);
309     if (GMC_is_pid_bigger (prev->mid, mid))
310     {
311       LOG (GNUNET_ERROR_TYPE_DEBUG, " bingo!\n");
312       GNUNET_CONTAINER_DLL_insert_before (rel->head_recv, rel->tail_recv,
313                                           prev, copy);
314       return;
315     }
316   }
317     LOG (GNUNET_ERROR_TYPE_DEBUG, " insert at tail!\n");
318     GNUNET_CONTAINER_DLL_insert_tail (rel->head_recv, rel->tail_recv, copy);
319     LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data END\n");
320 }
321
322
323 /**
324  * Send data to a client.
325  *
326  * If the client is ready, send directly, otherwise buffer while listening
327  * for a local ACK.
328  *
329  * @param ch Channel
330  * @param msg Message.
331  * @param fwd Is this a fwd (root->dest) message?
332  */
333 static void
334 send_client_data (struct MeshChannel *ch,
335                   const struct GNUNET_MESH_Data *msg,
336                   int fwd)
337 {
338   if (fwd)
339   {
340     if (ch->dest_rel->client_ready)
341       GML_send_data (ch, msg, ch->dest, ch->lid_dest);
342     else
343       add_buffered_data (msg, ch->dest_rel);
344   }
345   else
346   {
347     if (ch->root_rel->client_ready)
348       GML_send_data (ch, msg, ch->root, ch->lid_root);
349     else
350       add_buffered_data (msg, ch->root_rel);
351   }
352 }
353
354
355 /**
356  * Add a client to a channel, initializing all needed data structures.
357  *
358  * @param ch Channel to which add the client.
359  * @param c Client which to add to the channel.
360  */
361 void
362 GMCH_add_client (struct MeshChannel *ch, struct MeshClient *c)
363 {
364   struct MeshTunnel3 *t = ch->t;
365
366   if (NULL != ch->dest)
367   {
368     GNUNET_break (0);
369     return;
370   }
371
372   /* Assign local id as destination */
373   ch->lid_dest = GML_get_next_chid (c);
374
375   /* Store in client's hashmap */
376   GML_channel_add (c, ch->lid_dest, ch);
377
378   GNUNET_break (NULL == ch->dest_rel);
379   ch->dest_rel = GNUNET_new (struct MeshChannelReliability);
380   ch->dest_rel->ch = ch;
381   ch->dest_rel->expected_delay = MESH_RETRANSMIT_TIME;
382
383   ch->dest = c;
384 }
385
386
387 /**
388  * Destroy all reliable messages queued for a channel,
389  * during a channel destruction.
390  * Frees the reliability structure itself.
391  *
392  * @param rel Reliability data for a channel.
393  */
394 static void
395 channel_rel_free_all (struct MeshChannelReliability *rel)
396 {
397   struct MeshReliableMessage *copy;
398   struct MeshReliableMessage *next;
399
400   if (NULL == rel)
401     return;
402
403   for (copy = rel->head_recv; NULL != copy; copy = next)
404   {
405     next = copy->next;
406     GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy);
407     GNUNET_free (copy);
408   }
409   for (copy = rel->head_sent; NULL != copy; copy = next)
410   {
411     next = copy->next;
412     GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy);
413     GNUNET_free (copy);
414   }
415   if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task)
416     GNUNET_SCHEDULER_cancel (rel->retry_task);
417   GNUNET_free (rel);
418 }
419
420
421 /**
422  * Mark future messages as ACK'd.
423  *
424  * @param rel Reliability data.
425  * @param msg DataACK message with a bitfield of future ACK'd messages.
426  */
427 static void
428 channel_rel_free_sent (struct MeshChannelReliability *rel,
429                        const struct GNUNET_MESH_DataACK *msg)
430 {
431   struct MeshReliableMessage *copy;
432   struct MeshReliableMessage *next;
433   uint64_t bitfield;
434   uint64_t mask;
435   uint32_t mid;
436   uint32_t target;
437   unsigned int i;
438
439   bitfield = msg->futures;
440   mid = ntohl (msg->mid);
441   LOG (GNUNET_ERROR_TYPE_DEBUG,
442               "free_sent_reliable %u %llX\n",
443               mid, bitfield);
444   LOG (GNUNET_ERROR_TYPE_DEBUG,
445               " rel %p, head %p\n",
446               rel, rel->head_sent);
447   for (i = 0, copy = rel->head_sent;
448        i < 64 && NULL != copy && 0 != bitfield;
449        i++)
450   {
451     LOG (GNUNET_ERROR_TYPE_DEBUG,
452                 " trying bit %u (mid %u)\n",
453                 i, mid + i + 1);
454     mask = 0x1LL << i;
455     if (0 == (bitfield & mask))
456      continue;
457
458     LOG (GNUNET_ERROR_TYPE_DEBUG, " set!\n");
459     /* Bit was set, clear the bit from the bitfield */
460     bitfield &= ~mask;
461
462     /* The i-th bit was set. Do we have that copy? */
463     /* Skip copies with mid < target */
464     target = mid + i + 1;
465     LOG (GNUNET_ERROR_TYPE_DEBUG, " target %u\n", target);
466     while (NULL != copy && GMC_is_pid_bigger (target, copy->mid))
467      copy = copy->next;
468
469     /* Did we run out of copies? (previously freed, it's ok) */
470     if (NULL == copy)
471     {
472      LOG (GNUNET_ERROR_TYPE_DEBUG, "run out of copies...\n");
473      return;
474     }
475
476     /* Did we overshoot the target? (previously freed, it's ok) */
477     if (GMC_is_pid_bigger (copy->mid, target))
478     {
479      LOG (GNUNET_ERROR_TYPE_DEBUG, " next copy %u\n", copy->mid);
480      continue;
481     }
482
483     /* Now copy->mid == target, free it */
484     next = copy->next;
485     rel_message_free (copy);
486     copy = next;
487   }
488   LOG (GNUNET_ERROR_TYPE_DEBUG, "free_sent_reliable END\n");
489 }
490
491
492 /**
493  * We haven't received an ACK after a certain time: restransmit the message.
494  *
495  * @param cls Closure (MeshReliableMessage with the message to restransmit)
496  * @param tc TaskContext.
497  */
498 static void
499 channel_retransmit_message (void *cls,
500                             const struct GNUNET_SCHEDULER_TaskContext *tc)
501 {
502   struct MeshChannelReliability *rel = cls;
503   struct MeshReliableMessage *copy;
504   struct MeshPeerQueue *q;
505   struct MeshChannel *ch;
506   struct MeshConnection *c;
507   struct GNUNET_MESH_Data *payload;
508   struct MeshPeer *hop;
509   int fwd;
510
511   rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
512   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
513     return;
514
515   ch = rel->ch;
516   copy = rel->head_sent;
517   if (NULL == copy)
518   {
519     GNUNET_break (0);
520     return;
521   }
522
523   /* Search the message to be retransmitted in the outgoing queue.
524    * Check only the queue for the connection that is going to be used,
525    * if the message is stuck in some other connection's queue we shouldn't
526    * act upon it:
527    * - cancelling it and sending the new one doesn't guarantee it's delivery,
528    *   the old connection could be temporary stalled or the queue happened to
529    *   be long at time of insertion.
530    * - not sending the new one could cause terrible delays the old connection
531    *   is stalled.
532    */
533   payload = (struct GNUNET_MESH_Data *) &copy[1];
534   fwd = (rel == ch->root_rel);
535   c = GMT_get_connection (ch->t, fwd);
536   hop = connection_get_hop (c, fwd);
537   for (q = hop->queue_head; NULL != q; q = q->next)
538   {
539     if (ntohs (payload->header.type) == q->type && ch == q->ch)
540     {
541       struct GNUNET_MESH_Data *queued_data = q->cls;
542
543       if (queued_data->mid == payload->mid)
544         break;
545     }
546   }
547
548   /* Message not found in the queue that we are going to use. */
549   if (NULL == q)
550   {
551     LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RETRANSMIT %u\n", copy->mid);
552
553     GMCH_send_prebuilt_message (&payload->header, ch, fwd);
554     GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO);
555   }
556   else
557   {
558     LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! ALREADY IN QUEUE %u\n", copy->mid);
559   }
560
561   rel->retry_timer = GNUNET_TIME_STD_BACKOFF (rel->retry_timer);
562   rel->retry_task = GNUNET_SCHEDULER_add_delayed (rel->retry_timer,
563                                                   &channel_retransmit_message,
564                                                   cls);
565 }
566
567
568 /**
569  * Send ACK on one or more connections due to buffer space to the client.
570  *
571  * Iterates all connections of the tunnel and sends ACKs appropriately.
572  *
573  * @param ch Channel which has some free buffer space.
574  * @param fwd Is this in for FWD traffic? (ACK goes dest->root)
575  */
576 static void
577 channel_send_connections_ack (struct MeshChannel *ch,
578                               unsigned int buffer,
579                               int fwd)
580 {
581   struct MeshTunnel3 *t = ch->t;
582   struct MeshConnection *c;
583   uint32_t allowed;
584   uint32_t to_allow;
585   uint32_t allow_per_connection;
586   unsigned int cs;
587
588   LOG (GNUNET_ERROR_TYPE_DEBUG,
589               "Channel send connection %s ack on %s:%X\n",
590               fwd ? "FWD" : "BCK", peer2s (ch->t->peer), ch->gid);
591
592   /* Count connections, how many messages are already allowed */
593   cs = GMT_count_connections (t);
594   for (cs = 0, allowed = 0, c = t->connection_head; NULL != c; c = c->next)
595   {
596     fc = fwd ? &c->fwd_fc : &c->bck_fc;
597     if (GMC_is_pid_bigger (fc->last_pid_recv, fc->last_ack_sent))
598     {
599       GNUNET_break (0);
600       continue;
601     }
602     allowed += fc->last_ack_sent - fc->last_pid_recv;
603     cs++;
604   }
605
606   /* Make sure there is no overflow */
607   if (allowed > buffer)
608   {
609     GNUNET_break (0);
610     return;
611   }
612
613   /* Authorize connections to send more data */
614   to_allow = buffer - allowed;
615
616   for (c = t->connection_head; NULL != c && to_allow > 0; c = c->next)
617   {
618     allow_per_connection = to_allow/cs;
619     to_allow -= allow_per_connection;
620     cs--;
621     fc = fwd ? &c->fwd_fc : &c->bck_fc;
622     if (fc->last_ack_sent - fc->last_pid_recv > 64 / 3)
623     {
624       continue;
625     }
626     GMC_send_ack (c, allow_per_connection, fwd);
627   }
628
629   LOG (GNUNET_ERROR_TYPE_DEBUG,
630                 "Channel send connection %s ack on %s:%X\n",
631                 fwd ? "FWD" : "BCK", GMT_2s (ch->t), ch->gid);
632   GNUNET_break (to_allow == 0);
633 }
634
635
636 /**
637  * Destroy a reliable message after it has been acknowledged, either by
638  * direct mid ACK or bitfield. Updates the appropriate data structures and
639  * timers and frees all memory.
640  *
641  * @param copy Message that is no longer needed: remote peer got it.
642  */
643 static void
644 rel_message_free (struct MeshReliableMessage *copy)
645 {
646   struct MeshChannelReliability *rel;
647   struct GNUNET_TIME_Relative time;
648
649   rel = copy->rel;
650   time = GNUNET_TIME_absolute_get_duration (copy->timestamp);
651   rel->expected_delay.rel_value_us *= 7;
652   rel->expected_delay.rel_value_us += time.rel_value_us;
653   rel->expected_delay.rel_value_us /= 8;
654   rel->n_sent--;
655   LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Freeing %u\n", copy->mid);
656   LOG (GNUNET_ERROR_TYPE_DEBUG, "    n_sent %u\n", rel->n_sent);
657   LOG (GNUNET_ERROR_TYPE_DEBUG, "!!!  took %s\n",
658               GNUNET_STRINGS_relative_time_to_string (time, GNUNET_NO));
659   LOG (GNUNET_ERROR_TYPE_DEBUG, "!!!  new expected delay %s\n",
660               GNUNET_STRINGS_relative_time_to_string (rel->expected_delay,
661                                                       GNUNET_NO));
662   rel->retry_timer = rel->expected_delay;
663   GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy);
664   GNUNET_free (copy);
665 }
666
667
668
669 /**
670  * Channel was ACK'd by remote peer, mark as ready and cancel retransmission.
671  *
672  * @param ch Channel to mark as ready.
673  * @param fwd Was the CREATE message sent fwd?
674  */
675 static void
676 channel_confirm (struct MeshChannel *ch, int fwd)
677 {
678   struct MeshChannelReliability *rel;
679   struct MeshReliableMessage *copy;
680   struct MeshReliableMessage *next;
681
682   LOG (GNUNET_ERROR_TYPE_DEBUG,
683               "  channel confirm %s %s:%X\n",
684               fwd ? "FWD" : "BCK", GMT_2s (ch->t), ch->gid);
685   ch->state = MESH_CHANNEL_READY;
686
687   rel = fwd ? ch->root_rel : ch->dest_rel;
688   for (copy = rel->head_sent; NULL != copy; copy = next)
689   {
690     struct GNUNET_MessageHeader *msg;
691
692     next = copy->next;
693     msg = (struct GNUNET_MessageHeader *) &copy[1];
694     if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE)
695     {
696       rel_message_free (copy);
697       /* TODO return? */
698     }
699   }
700   send_ack (NULL, ch, fwd);
701 }
702
703
704 /**
705  * Save a copy to retransmit in case it gets lost.
706  *
707  * Initializes all needed callbacks and timers.
708  *
709  * @param ch Channel this message goes on.
710  * @param msg Message to copy.
711  * @param fwd Is this fwd traffic?
712  */
713 static void
714 channel_save_copy (struct MeshChannel *ch,
715                    const struct GNUNET_MessageHeader *msg,
716                    int fwd)
717 {
718   struct MeshChannelReliability *rel;
719   struct MeshReliableMessage *copy;
720   uint32_t mid;
721   uint16_t type;
722   uint16_t size;
723
724   rel = fwd ? ch->root_rel : ch->dest_rel;
725   mid = rel->mid_send;
726   type = ntohs (msg->type);
727   size = ntohs (msg->size);
728
729   LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SAVE %u\n", mid);
730   copy = GNUNET_malloc (sizeof (struct MeshReliableMessage) + size);
731   copy->mid = mid;
732   copy->timestamp = GNUNET_TIME_absolute_get ();
733   copy->rel = rel;
734   copy->type = type;
735   memcpy (&copy[1], msg, size);
736   rel->n_sent++;
737   LOG (GNUNET_ERROR_TYPE_DEBUG, " n_sent %u\n", rel->n_sent);
738   GNUNET_CONTAINER_DLL_insert_tail (rel->head_sent, rel->tail_sent, copy);
739   if (GNUNET_SCHEDULER_NO_TASK == rel->retry_task)
740   {
741     rel->retry_timer =
742         GNUNET_TIME_relative_multiply (rel->expected_delay,
743                                         MESH_RETRANSMIT_MARGIN);
744     rel->retry_task =
745         GNUNET_SCHEDULER_add_delayed (rel->retry_timer,
746                                       &channel_retransmit_message,
747                                       rel);
748   }
749 }
750
751
752
753 /**
754  * Send a buffered message to the client, for in order delivery or
755  * as result of client ACK.
756  *
757  * @param ch Channel on which to empty the message buffer.
758  * @param c Client to send to.
759  * @param rel Reliability structure to corresponding peer.
760  *            If rel == bck_rel, this is FWD data.
761  */
762 static void
763 send_client_buffered_data (struct MeshChannel *ch,
764                                    struct MeshClient *c,
765                                    int fwd)
766 {
767   struct MeshReliableMessage *copy;
768   struct MeshChannelReliability *rel;
769
770   LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data\n");
771   rel = fwd ? ch->dest_rel : ch->root_rel;
772   if (GNUNET_NO == rel->client_ready)
773   {
774     LOG (GNUNET_ERROR_TYPE_DEBUG, "client not ready\n");
775     return;
776   }
777
778   copy = rel->head_recv;
779   /* We never buffer channel management messages */
780   if (NULL != copy)
781   {
782     if (copy->mid == rel->mid_recv || GNUNET_NO == ch->reliable)
783     {
784       struct GNUNET_MESH_Data *msg = (struct GNUNET_MESH_Data *) &copy[1];
785
786       LOG (GNUNET_ERROR_TYPE_DEBUG,
787                   " have %u! now expecting %u\n",
788                   copy->mid, rel->mid_recv + 1);
789       send_client_data (ch, msg, fwd);
790       rel->n_recv--;
791       rel->mid_recv++;
792       GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy);
793       GNUNET_free (copy);
794     }
795     else
796     {
797       LOG (GNUNET_ERROR_TYPE_DEBUG,
798                   " reliable && don't have %u, next is %u\n",
799                   rel->mid_recv,
800                   copy->mid);
801       return;
802     }
803   }
804   LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data END\n");
805 }
806
807
808
809
810 /**
811  * Destroy a channel and free all resources.
812  *
813  * @param ch Channel to destroy.
814  */
815 static void
816 channel_destroy (struct MeshChannel *ch)
817 {
818   struct MeshClient *c;
819
820   if (NULL == ch)
821     return;
822
823   LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying channel %s:%u\n",
824               GMT_2s (ch->t), ch->gid);
825   GMCH_debug (ch);
826
827   c = ch->root;
828   if (NULL != c)
829   {
830     GML_channel_remove (c, ch->lid_root, ch);
831   }
832
833   c = ch->dest;
834   if (NULL != c)
835   {
836     GML_channel_remove (c, ch->lid_dest, ch);
837   }
838
839   channel_rel_free_all (ch->root_rel);
840   channel_rel_free_all (ch->dest_rel);
841
842   GMT_remove_channel (ch->t, ch);
843   GNUNET_STATISTICS_update (stats, "# channels", -1, GNUNET_NO);
844
845   GNUNET_free (ch);
846 }
847
848
849 /**
850  * Create a new channel.
851  *
852  * @param t Tunnel this channel is in.
853  * @param owner Client that owns the channel, NULL for foreign channels.
854  * @param lid_root Local ID for root client.
855  *
856  * @return A new initialized channel. NULL on error.
857  */
858 static struct MeshChannel *
859 channel_new (struct MeshTunnel3 *t,
860              struct MeshClient *owner, MESH_ChannelNumber lid_root)
861 {
862   struct MeshChannel *ch;
863
864   ch = GNUNET_new (struct MeshChannel);
865   ch->root = owner;
866   ch->lid_root = lid_root;
867   ch->t = t;
868
869   GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
870
871   if (NULL != owner)
872   {
873     ch->gid = GMT_get_next_chid (t);
874     GML_channel_add (owner, lid_root, ch);
875   }
876   GMT_add_channel (t, ch);
877
878   return ch;
879 }
880
881
882 /**
883  * Set options in a channel, extracted from a bit flag field
884  *
885  * @param ch Channel to set options to.
886  * @param options Bit array in host byte order.
887  */
888 static void
889 channel_set_options (struct MeshChannel *ch, uint32_t options)
890 {
891   ch->nobuffer = (options & GNUNET_MESH_OPTION_NOBUFFER) != 0 ?
892                  GNUNET_YES : GNUNET_NO;
893   ch->reliable = (options & GNUNET_MESH_OPTION_RELIABLE) != 0 ?
894                  GNUNET_YES : GNUNET_NO;
895 }
896
897
898
899 /**
900  * Confirm we got a channel create.
901  *
902  * @param ch The channel to confirm.
903  * @param fwd Should we send the ACK fwd?
904  */
905 static void
906 channel_send_ack (struct MeshChannel *ch, int fwd)
907 {
908   struct GNUNET_MESH_ChannelManage msg;
909
910   msg.header.size = htons (sizeof (msg));
911   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK);
912   LOG (GNUNET_ERROR_TYPE_DEBUG,
913               "  sending channel %s ack for channel %s:%X\n",
914               fwd ? "FWD" : "BCK", GMT_2s (ch->t),
915               ch->gid);
916
917   msg.chid = htonl (ch->gid);
918   GMCH_send_prebuilt_message (&msg.header, ch, !fwd);
919 }
920
921
922 /**
923  * Iterator for deleting each channel whose client endpoint disconnected.
924  *
925  * @param cls Closure (client that has disconnected).
926  * @param key The local channel id (used to access the hashmap).
927  * @param value The value stored at the key (channel to destroy).
928  *
929  * @return GNUNET_OK, keep iterating.
930  */
931 static int
932 channel_destroy_iterator (void *cls,
933                           uint32_t key,
934                           void *value)
935 {
936   struct MeshChannel *ch = value;
937   struct MeshClient *c = cls;
938   struct MeshTunnel3 *t;
939
940   LOG (GNUNET_ERROR_TYPE_DEBUG,
941               " Channel %X (%X / %X) destroy, due to client %s shutdown.\n",
942               ch->gid, ch->lid_root, ch->lid_dest, GML_2s (c));
943   GMCH_debug (ch);
944
945   if (c == ch->dest)
946   {
947     LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is destination.\n", GML_2s (c));
948   }
949   if (c == ch->root)
950   {
951     LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is owner.\n", GML_2s (c));
952   }
953
954   t = ch->t;
955   GMCH_send_destroy (ch);
956   channel_destroy (ch);
957   GMT_destroy_if_empty (t);
958
959   return GNUNET_OK;
960 }
961
962
963 /**
964  * Handle a loopback message: call the appropriate handler for the message type.
965  *
966  * @param ch Channel this message is on.
967  * @param msgh Message header.
968  * @param fwd Is this FWD traffic?
969  */
970 void
971 handle_loopback (struct MeshChannel *ch,
972                  struct GNUNET_MessageHeader *msgh,
973                  int fwd)
974 {
975   uint16_t type;
976
977   type = ntohs (msgh->type);
978   LOG (GNUNET_ERROR_TYPE_DEBUG,
979        "Loopback %s message!\n",
980        GNUNET_MESH_DEBUG_M2S (type));
981
982   switch (type)
983   {
984     case GNUNET_MESSAGE_TYPE_MESH_DATA:
985       /* Don't send hop ACK, wait for client to ACK */
986       GMCH_handle_data (ch, (struct GNUNET_MESH_Data *) msgh, fwd);
987       break;
988
989     case GNUNET_MESSAGE_TYPE_MESH_DATA_ACK:
990       GMCH_handle_data_ack (ch, (struct GNUNET_MESH_DataACK *) msgh, fwd);
991       break;
992
993     case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE:
994        // FIXME store channel in loopback tunnel?
995       GMCH_handle_create ((struct GNUNET_MESH_ChannelCreate *) msgh,
996                           fwd);
997       break;
998
999     case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK:
1000       GMCH_handle_ack (ch,
1001                        (struct GNUNET_MESH_ChannelManage *) msgh,
1002                        fwd);
1003       break;
1004
1005     case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY:
1006       GMCH_handle_destroy (ch,
1007                            (struct GNUNET_MESH_ChannelManage *) msgh,
1008                            fwd);
1009       break;
1010
1011     default:
1012       GNUNET_break_op (0);
1013       LOG (GNUNET_ERROR_TYPE_DEBUG,
1014            "end-to-end message not known (%u)\n",
1015            ntohs (msgh->type));
1016   }
1017 }
1018
1019
1020
1021 /******************************************************************************/
1022 /********************************    API    ***********************************/
1023 /******************************************************************************/
1024
1025 /**
1026  * Get channel ID.
1027  *
1028  * @param ch Channel.
1029  *
1030  * @return ID
1031  */
1032 MESH_ChannelNumber
1033 GMCH_get_id (const struct MeshChannel *ch)
1034 {
1035   return ch->gid;
1036 }
1037
1038
1039 /**
1040  * Get the channel tunnel.
1041  *
1042  * @param ch Channel to get the tunnel from.
1043  *
1044  * @return tunnel of the channel.
1045  */
1046 struct MeshTunnel3 *
1047 GMCH_get_tunnel (const struct MeshChannel *ch)
1048 {
1049   return ch->t;
1050 }
1051
1052
1053 /**
1054  * Get free buffer space towards the client on a specific channel.
1055  *
1056  * @param ch Channel.
1057  * @param fwd Is query about FWD traffic?
1058  *
1059  * @return Free buffer space [0 - 64]
1060  */
1061 unsigned int
1062 GMCH_get_buffer (struct MeshChannel *ch, int fwd)
1063 {
1064   struct MeshChannelReliability *rel;
1065
1066   rel = fwd ? ch->dest_rel : ch->root_rel;
1067
1068   /* If rel is NULL it means that the end is not yet created,
1069    * most probably is a loopback channel at the point of sending
1070    * the ChannelCreate to itself.
1071    */
1072   if (NULL == rel)
1073     return 64;
1074
1075   return (64 - rel->n_recv);
1076 }
1077
1078
1079 /**
1080  * Is the root client for this channel on this peer?
1081  *
1082  * @param ch Channel.
1083  * @param fwd Is this for fwd traffic?
1084  *
1085  * @return GNUNET_YES in case it is.
1086  */
1087 int
1088 GMCH_is_origin (struct MeshChannel *ch, int fwd)
1089 {
1090   struct MeshClient *c;
1091
1092   c = fwd ? ch->root : ch->dest;
1093   return NULL != c;
1094 }
1095
1096
1097 /**
1098  * Is the destination client for this channel on this peer?
1099  *
1100  * @param ch Channel.
1101  * @param fwd Is this for fwd traffic?
1102  *
1103  * @return GNUNET_YES in case it is.
1104  */
1105 int
1106 GMCH_is_terminal (struct MeshChannel *ch, int fwd)
1107 {
1108   struct MeshClient *c;
1109
1110   c = fwd ? ch->dest : ch->root;
1111   return NULL != c;
1112 }
1113
1114
1115 /**
1116  * Notify the destination client that a new incoming channel was created.
1117  *
1118  * @param ch Channel that was created.
1119  */
1120 void
1121 GMCH_send_create (struct MeshChannel *ch)
1122 {
1123   struct GNUNET_MESH_ChannelMessage msg;
1124   uint32_t opt;
1125
1126   if (NULL == ch->dest)
1127     return;
1128
1129   opt = 0;
1130   opt |= GNUNET_YES == ch->reliable ? GNUNET_MESH_OPTION_RELIABLE : 0;
1131   opt |= GNUNET_YES == ch->nobuffer ? GNUNET_MESH_OPTION_NOBUFFER : 0;
1132   GML_send_channel_create (ch->dest, ch->lid_dest, ch->port, opt,
1133                            GMT_get_destination (ch->t));
1134
1135 }
1136
1137 /**
1138  * Notify a client that the channel is no longer valid.
1139  * FIXME send on tunnel if some client == NULL?
1140  *
1141  * @param ch Channel that is destroyed.
1142  */
1143 void
1144 GMCH_send_destroy (struct MeshChannel *ch)
1145 {
1146   if (NULL != ch->root)
1147     GML_send_channel_destroy (ch->root, ch->lid_root);
1148
1149   if (NULL != ch->dest)
1150     GML_send_channel_destroy (ch->dest, ch->lid_dest);
1151 }
1152
1153
1154 /**
1155  * Send data on a channel.
1156  *
1157  * If the destination is local, send it to client, otherwise encrypt and
1158  * send to next hop.
1159  *
1160  * @param ch Channel
1161  * @param msg Message.
1162  * @param fwd Is this a fwd (root->dest) message?
1163  */
1164 void
1165 GMCH_send_data (struct MeshChannel *ch,
1166                 const struct GNUNET_MESH_Data *msg,
1167                 int fwd)
1168 {
1169 }
1170
1171
1172 /**
1173  * Send an end-to-end ACK message for the most recent in-sequence payload.
1174  *
1175  * If channel is not reliable, do nothing.
1176  *
1177  * @param ch Channel this is about.
1178  * @param fwd Is for FWD traffic? (ACK dest->owner)
1179  */
1180 void
1181 GMCH_send_ack (struct MeshChannel *ch, int fwd)
1182 {
1183   struct GNUNET_MESH_DataACK msg;
1184   struct MeshChannelReliability *rel;
1185   struct MeshReliableMessage *copy;
1186   unsigned int delta;
1187   uint64_t mask;
1188   uint16_t type;
1189
1190   if (GNUNET_NO == ch->reliable)
1191   {
1192     return;
1193   }
1194   rel = fwd ? ch->dest_rel : ch->root_rel;
1195   LOG (GNUNET_ERROR_TYPE_DEBUG,
1196               "send_data_ack for %u\n",
1197               rel->mid_recv - 1);
1198
1199   type = GNUNET_MESSAGE_TYPE_MESH_DATA_ACK;
1200   msg.header.type = htons (type);
1201   msg.header.size = htons (sizeof (msg));
1202   msg.chid = htonl (ch->gid);
1203   msg.mid = htonl (rel->mid_recv - 1);
1204   msg.futures = 0;
1205   for (copy = rel->head_recv; NULL != copy; copy = copy->next)
1206   {
1207     if (copy->type != type)
1208       continue;
1209     delta = copy->mid - rel->mid_recv;
1210     if (63 < delta)
1211       break;
1212     mask = 0x1LL << delta;
1213     msg.futures |= mask;
1214     LOG (GNUNET_ERROR_TYPE_DEBUG,
1215                 " setting bit for %u (delta %u) (%llX) -> %llX\n",
1216                 copy->mid, delta, mask, msg.futures);
1217   }
1218   LOG (GNUNET_ERROR_TYPE_DEBUG, " final futures %llX\n", msg.futures);
1219
1220   GMCH_send_prebuilt_message (&msg.header, ch, fwd);
1221   LOG (GNUNET_ERROR_TYPE_DEBUG, "send_data_ack END\n");
1222 }
1223
1224
1225 /**
1226  * Log channel info.
1227  *
1228  * @param ch Channel.
1229  */
1230 void
1231 GMCH_debug (struct MeshChannel *ch)
1232 {
1233   if (NULL == ch)
1234   {
1235     LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CHANNEL ***\n");
1236     return;
1237   }
1238   LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %s:%X (%p)\n",
1239               GMT_2s (ch->t), ch->gid, ch);
1240   LOG (GNUNET_ERROR_TYPE_DEBUG, "  root %p/%p\n",
1241               ch->root, ch->root_rel);
1242   if (NULL != ch->root)
1243   {
1244     LOG (GNUNET_ERROR_TYPE_DEBUG, "  cli %s\n", GML_2s (ch->root));
1245     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ready %s\n",
1246                 ch->root_rel->client_ready ? "YES" : "NO");
1247     LOG (GNUNET_ERROR_TYPE_DEBUG, "  id %X\n", ch->lid_root);
1248   }
1249   LOG (GNUNET_ERROR_TYPE_DEBUG, "  dest %p/%p\n",
1250               ch->dest, ch->dest_rel);
1251   if (NULL != ch->dest)
1252   {
1253     LOG (GNUNET_ERROR_TYPE_DEBUG, "  cli %s\n", GML_2s (ch->dest));
1254     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ready %s\n",
1255                 ch->dest_rel->client_ready ? "YES" : "NO");
1256     LOG (GNUNET_ERROR_TYPE_DEBUG, "  id %X\n", ch->lid_dest);
1257   }
1258 }
1259
1260
1261 /**
1262  * Handler for mesh network payload traffic.
1263  *
1264  * @param ch Channel for the message.
1265  * @param message Unencryted data message.
1266  * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1267  */
1268 void
1269 GMCH_handle_data (struct MeshChannel *ch,
1270                   const struct GNUNET_MESH_Data *msg,
1271                   int fwd)
1272 {
1273   struct MeshChannelReliability *rel;
1274   struct MeshClient *c;
1275   uint32_t mid;
1276   uint16_t type;
1277   size_t size;
1278
1279   /*  Initialize FWD/BCK data */
1280   c   = fwd ? ch->dest     : ch->root;
1281   rel = fwd ? ch->dest_rel : ch->root_rel;
1282
1283   if (NULL == c)
1284   {
1285     GNUNET_break (0);
1286     return;
1287   }
1288
1289   GNUNET_STATISTICS_update (stats, "# data received", 1, GNUNET_NO);
1290
1291   mid = ntohl (msg->mid);
1292   LOG (GNUNET_ERROR_TYPE_DEBUG, " mid %u\n", mid);
1293
1294   if (GNUNET_NO == ch->reliable ||
1295       ( !GMC_is_pid_bigger (rel->mid_recv, mid) &&
1296         GMC_is_pid_bigger (rel->mid_recv + 64, mid) ) )
1297   {
1298     LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RECV %u\n", mid);
1299     if (GNUNET_YES == ch->reliable)
1300     {
1301       /* Is this the exact next expected messasge? */
1302       if (mid == rel->mid_recv)
1303       {
1304         LOG (GNUNET_ERROR_TYPE_DEBUG, "as expected\n");
1305         rel->mid_recv++;
1306         send_client_data (ch, msg, fwd);
1307       }
1308       else
1309       {
1310         LOG (GNUNET_ERROR_TYPE_DEBUG, "save for later\n");
1311         add_buffered_data (msg, rel);
1312       }
1313     }
1314     else
1315     {
1316       /* Tunnel is unreliable: send to clients directly */
1317       /* FIXME: accept Out Of Order traffic */
1318       rel->mid_recv = mid + 1;
1319       send_client_data (ch, msg, fwd);
1320     }
1321   }
1322   else
1323   {
1324     GNUNET_break_op (0);
1325     LOG (GNUNET_ERROR_TYPE_DEBUG,
1326                 " MID %u not expected (%u - %u), dropping!\n",
1327                 mid, rel->mid_recv, rel->mid_recv + 64);
1328   }
1329
1330   GMCH_send_ack (ch, fwd);
1331 }
1332
1333
1334 /**
1335  * Handler for mesh network traffic end-to-end ACKs.
1336  *
1337  * @param t Tunnel on which we got this message.
1338  * @param message Data message.
1339  * @param fwd Is this a fwd ACK? (dest->orig)
1340  */
1341 void
1342 GMCH_handle_data_ack (struct MeshChannel *ch,
1343                       const struct GNUNET_MESH_DataACK *msg,
1344                       int fwd)
1345 {
1346   struct MeshChannelReliability *rel;
1347   struct MeshReliableMessage *copy;
1348   struct MeshReliableMessage *next;
1349   uint32_t ack;
1350   int work;
1351
1352   ack = ntohl (msg->mid);
1353   LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! %s ACK %u\n",
1354               (GNUNET_YES == fwd) ? "FWD" : "BCK", ack);
1355
1356   if (GNUNET_YES == fwd)
1357   {
1358     rel = ch->root_rel;
1359   }
1360   else
1361   {
1362     rel = ch->dest_rel;
1363   }
1364   if (NULL == rel)
1365   {
1366     GNUNET_break (0);
1367     return;
1368   }
1369
1370   for (work = GNUNET_NO, copy = rel->head_sent; copy != NULL; copy = next)
1371   {
1372     if (GMC_is_pid_bigger (copy->mid, ack))
1373     {
1374       LOG (GNUNET_ERROR_TYPE_DEBUG, "!!!  head %u, out!\n", copy->mid);
1375       channel_rel_free_sent (rel, msg);
1376       break;
1377     }
1378     work = GNUNET_YES;
1379     LOG (GNUNET_ERROR_TYPE_DEBUG, "!!!  id %u\n", copy->mid);
1380     next = copy->next;
1381     rel_message_free (copy);
1382   }
1383   /* ACK client if needed */
1384 //   channel_send_ack (t, type, GNUNET_MESSAGE_TYPE_MESH_UNICAST_ACK == type);
1385
1386   /* If some message was free'd, update the retransmission delay*/
1387   if (GNUNET_YES == work)
1388   {
1389     if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task)
1390     {
1391       GNUNET_SCHEDULER_cancel (rel->retry_task);
1392       if (NULL == rel->head_sent)
1393       {
1394         rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
1395       }
1396       else
1397       {
1398         struct GNUNET_TIME_Absolute new_target;
1399         struct GNUNET_TIME_Relative delay;
1400
1401         delay = GNUNET_TIME_relative_multiply (rel->retry_timer,
1402                                                MESH_RETRANSMIT_MARGIN);
1403         new_target = GNUNET_TIME_absolute_add (rel->head_sent->timestamp,
1404                                                delay);
1405         delay = GNUNET_TIME_absolute_get_remaining (new_target);
1406         rel->retry_task =
1407             GNUNET_SCHEDULER_add_delayed (delay,
1408                                           &channel_retransmit_message,
1409                                           rel);
1410       }
1411     }
1412     else
1413       GNUNET_break (0);
1414   }
1415 }
1416
1417
1418 /**
1419  * Handler for channel create messages.
1420  *
1421  * @param msg Message.
1422  * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1423  */
1424 struct MeshChannel *
1425 GMCH_handle_create (const struct GNUNET_MESH_ChannelCreate *msg,
1426                     int fwd)
1427 {
1428   MESH_ChannelNumber chid;
1429   struct MeshChannel *ch;
1430   struct MeshClient *c;
1431   uint32_t port;
1432
1433   chid = ntohl (msg->chid);
1434
1435   /* Create channel */
1436   ch = channel_new (NULL, NULL, 0); /* FIXME t */
1437   ch->gid = chid;
1438   channel_set_options (ch, ntohl (msg->opt));
1439
1440   /* Find a destination client */
1441   port = ntohl (msg->port);
1442   LOG (GNUNET_ERROR_TYPE_DEBUG, "   port %u\n", port);
1443   c = GML_client_get_by_port (port);
1444   if (NULL == c)
1445   {
1446     /* TODO send reject */
1447     LOG (GNUNET_ERROR_TYPE_DEBUG, "  no client has port registered\n");
1448     /* TODO free ch */
1449     return;
1450   }
1451
1452   channel_add_client (ch, c);
1453   if (GNUNET_YES == ch->reliable)
1454     LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Reliable\n");
1455
1456   GMCH_send_create (ch);
1457   GMCH_send_ack (ch, fwd);
1458   GML_send_ack (ch, !fwd);
1459
1460   return ch;
1461 }
1462
1463
1464 /**
1465  * Handler for channel ack messages.
1466  *
1467  * @param ch Channel.
1468  * @param msg Message.
1469  * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1470  */
1471 void
1472 GMCH_handle_ack (struct MeshChannel *ch,
1473                  const struct GNUNET_MESH_ChannelManage *msg,
1474                  int fwd)
1475 {
1476   channel_confirm (ch, !fwd);
1477 }
1478
1479
1480 /**
1481  * Handler for channel destroy messages.
1482  *
1483  * @param ch Channel to be destroyed of.
1484  * @param msg Message.
1485  * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1486  */
1487 void
1488 GMCH_handle_destroy (struct MeshChannel *ch,
1489                      const struct GNUNET_MESH_ChannelManage *msg,
1490                      int fwd)
1491 {
1492   MESH_ChannelNumber chid;
1493
1494   /* Check if channel exists */
1495   chid = ntohl (msg->chid);
1496   if ( (fwd && NULL == ch->dest) || (!fwd && NULL == ch->root) )
1497   {
1498     /* Not for us (don't destroy twice a half-open loopback channel) */
1499     return;
1500   }
1501
1502   GMCH_send_destroy (ch);
1503   channel_destroy (ch);
1504 }
1505
1506
1507 /**
1508  * Sends an already built message on a channel.
1509  *
1510  * @param message Message to send. Function makes a copy of it.
1511  * @param ch Channel on which this message is transmitted.
1512  * @param fwd Is this a fwd message?
1513  */
1514 void
1515 GMCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
1516                             struct MeshChannel *ch, int fwd)
1517 {
1518   size_t size = ntohs (message->size);
1519
1520   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send on Channel %s:%X %s\n",
1521        GMT_2s (ch->t), ch->gid, fwd ? "FWD" : "BCK");
1522   LOG (GNUNET_ERROR_TYPE_DEBUG, "  %s\n",
1523        GNUNET_MESH_DEBUG_M2S (ntohs (message->type)));
1524
1525   if (GMT_is_loopback (ch->t))
1526   {
1527     handle_loopback (ch->t, message, fwd);
1528     return;
1529   }
1530
1531   GMT_send_prebuilt_message (message, ch->t, ch, fwd);
1532 }