- queue is internal: channel -> tunnel -> connection -> peer, no clean way to access...
[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 //   FIXME access to queue elements is limited
534 //   payload = (struct GNUNET_MESH_Data *) &copy[1];
535 //   fwd = (rel == ch->root_rel);
536 //   c = GMT_get_connection (ch->t, fwd);
537 //   hop = connection_get_hop (c, fwd);
538 //   for (q = hop->queue_head; NULL != q; q = q->next)
539 //   {
540 //     if (ntohs (payload->header.type) == q->type && ch == q->ch)
541 //     {
542 //       struct GNUNET_MESH_Data *queued_data = q->cls;
543 // 
544 //       if (queued_data->mid == payload->mid)
545 //         break;
546 //     }
547 //   }
548
549   /* Message not found in the queue that we are going to use. */
550 //   if (NULL == q)
551 //   {
552     LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RETRANSMIT %u\n", copy->mid);
553
554     GMCH_send_prebuilt_message (&payload->header, ch, fwd);
555     GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO);
556 //   }
557 //   else
558 //   {
559 //     LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! ALREADY IN QUEUE %u\n", copy->mid);
560 //   }
561
562   rel->retry_timer = GNUNET_TIME_STD_BACKOFF (rel->retry_timer);
563   rel->retry_task = GNUNET_SCHEDULER_add_delayed (rel->retry_timer,
564                                                   &channel_retransmit_message,
565                                                   cls);
566 }
567
568
569 /**
570  * Send ACK on one or more connections due to buffer space to the client.
571  *
572  * Iterates all connections of the tunnel and sends ACKs appropriately.
573  *
574  * @param ch Channel which has some free buffer space.
575  * @param fwd Is this in for FWD traffic? (ACK goes dest->root)
576  */
577 static void
578 channel_send_connections_ack (struct MeshChannel *ch,
579                               unsigned int buffer,
580                               int fwd)
581 {
582   struct MeshTunnel3 *t = ch->t;
583   struct MeshConnection *c;
584   uint32_t allowed;
585   uint32_t to_allow;
586   uint32_t allow_per_connection;
587   unsigned int cs;
588
589   LOG (GNUNET_ERROR_TYPE_DEBUG,
590               "Channel send connection %s ack on %s:%X\n",
591               fwd ? "FWD" : "BCK", peer2s (ch->t->peer), ch->gid);
592
593   /* Count connections, how many messages are already allowed */
594   cs = GMT_count_connections (t);
595   for (cs = 0, allowed = 0, c = t->connection_head; NULL != c; c = c->next)
596   {
597     fc = fwd ? &c->fwd_fc : &c->bck_fc;
598     if (GMC_is_pid_bigger (fc->last_pid_recv, fc->last_ack_sent))
599     {
600       GNUNET_break (0);
601       continue;
602     }
603     allowed += fc->last_ack_sent - fc->last_pid_recv;
604     cs++;
605   }
606
607   /* Make sure there is no overflow */
608   if (allowed > buffer)
609   {
610     GNUNET_break (0);
611     return;
612   }
613
614   /* Authorize connections to send more data */
615   to_allow = buffer - allowed;
616
617   for (c = t->connection_head; NULL != c && to_allow > 0; c = c->next)
618   {
619     allow_per_connection = to_allow/cs;
620     to_allow -= allow_per_connection;
621     cs--;
622     fc = fwd ? &c->fwd_fc : &c->bck_fc;
623     if (fc->last_ack_sent - fc->last_pid_recv > 64 / 3)
624     {
625       continue;
626     }
627     GMC_send_ack (c, allow_per_connection, fwd);
628   }
629
630   LOG (GNUNET_ERROR_TYPE_DEBUG,
631                 "Channel send connection %s ack on %s:%X\n",
632                 fwd ? "FWD" : "BCK", GMT_2s (ch->t), ch->gid);
633   GNUNET_break (to_allow == 0);
634 }
635
636
637 /**
638  * Destroy a reliable message after it has been acknowledged, either by
639  * direct mid ACK or bitfield. Updates the appropriate data structures and
640  * timers and frees all memory.
641  *
642  * @param copy Message that is no longer needed: remote peer got it.
643  */
644 static void
645 rel_message_free (struct MeshReliableMessage *copy)
646 {
647   struct MeshChannelReliability *rel;
648   struct GNUNET_TIME_Relative time;
649
650   rel = copy->rel;
651   time = GNUNET_TIME_absolute_get_duration (copy->timestamp);
652   rel->expected_delay.rel_value_us *= 7;
653   rel->expected_delay.rel_value_us += time.rel_value_us;
654   rel->expected_delay.rel_value_us /= 8;
655   rel->n_sent--;
656   LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Freeing %u\n", copy->mid);
657   LOG (GNUNET_ERROR_TYPE_DEBUG, "    n_sent %u\n", rel->n_sent);
658   LOG (GNUNET_ERROR_TYPE_DEBUG, "!!!  took %s\n",
659               GNUNET_STRINGS_relative_time_to_string (time, GNUNET_NO));
660   LOG (GNUNET_ERROR_TYPE_DEBUG, "!!!  new expected delay %s\n",
661               GNUNET_STRINGS_relative_time_to_string (rel->expected_delay,
662                                                       GNUNET_NO));
663   rel->retry_timer = rel->expected_delay;
664   GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy);
665   GNUNET_free (copy);
666 }
667
668
669
670 /**
671  * Channel was ACK'd by remote peer, mark as ready and cancel retransmission.
672  *
673  * @param ch Channel to mark as ready.
674  * @param fwd Was the CREATE message sent fwd?
675  */
676 static void
677 channel_confirm (struct MeshChannel *ch, int fwd)
678 {
679   struct MeshChannelReliability *rel;
680   struct MeshReliableMessage *copy;
681   struct MeshReliableMessage *next;
682
683   LOG (GNUNET_ERROR_TYPE_DEBUG,
684               "  channel confirm %s %s:%X\n",
685               fwd ? "FWD" : "BCK", GMT_2s (ch->t), ch->gid);
686   ch->state = MESH_CHANNEL_READY;
687
688   rel = fwd ? ch->root_rel : ch->dest_rel;
689   for (copy = rel->head_sent; NULL != copy; copy = next)
690   {
691     struct GNUNET_MessageHeader *msg;
692
693     next = copy->next;
694     msg = (struct GNUNET_MessageHeader *) &copy[1];
695     if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE)
696     {
697       rel_message_free (copy);
698       /* TODO return? */
699     }
700   }
701   send_ack (NULL, ch, fwd);
702 }
703
704
705 /**
706  * Save a copy to retransmit in case it gets lost.
707  *
708  * Initializes all needed callbacks and timers.
709  *
710  * @param ch Channel this message goes on.
711  * @param msg Message to copy.
712  * @param fwd Is this fwd traffic?
713  */
714 static void
715 channel_save_copy (struct MeshChannel *ch,
716                    const struct GNUNET_MessageHeader *msg,
717                    int fwd)
718 {
719   struct MeshChannelReliability *rel;
720   struct MeshReliableMessage *copy;
721   uint32_t mid;
722   uint16_t type;
723   uint16_t size;
724
725   rel = fwd ? ch->root_rel : ch->dest_rel;
726   mid = rel->mid_send;
727   type = ntohs (msg->type);
728   size = ntohs (msg->size);
729
730   LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SAVE %u\n", mid);
731   copy = GNUNET_malloc (sizeof (struct MeshReliableMessage) + size);
732   copy->mid = mid;
733   copy->timestamp = GNUNET_TIME_absolute_get ();
734   copy->rel = rel;
735   copy->type = type;
736   memcpy (&copy[1], msg, size);
737   rel->n_sent++;
738   LOG (GNUNET_ERROR_TYPE_DEBUG, " n_sent %u\n", rel->n_sent);
739   GNUNET_CONTAINER_DLL_insert_tail (rel->head_sent, rel->tail_sent, copy);
740   if (GNUNET_SCHEDULER_NO_TASK == rel->retry_task)
741   {
742     rel->retry_timer =
743         GNUNET_TIME_relative_multiply (rel->expected_delay,
744                                         MESH_RETRANSMIT_MARGIN);
745     rel->retry_task =
746         GNUNET_SCHEDULER_add_delayed (rel->retry_timer,
747                                       &channel_retransmit_message,
748                                       rel);
749   }
750 }
751
752
753
754 /**
755  * Send a buffered message to the client, for in order delivery or
756  * as result of client ACK.
757  *
758  * @param ch Channel on which to empty the message buffer.
759  * @param c Client to send to.
760  * @param rel Reliability structure to corresponding peer.
761  *            If rel == bck_rel, this is FWD data.
762  */
763 static void
764 send_client_buffered_data (struct MeshChannel *ch,
765                                    struct MeshClient *c,
766                                    int fwd)
767 {
768   struct MeshReliableMessage *copy;
769   struct MeshChannelReliability *rel;
770
771   LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data\n");
772   rel = fwd ? ch->dest_rel : ch->root_rel;
773   if (GNUNET_NO == rel->client_ready)
774   {
775     LOG (GNUNET_ERROR_TYPE_DEBUG, "client not ready\n");
776     return;
777   }
778
779   copy = rel->head_recv;
780   /* We never buffer channel management messages */
781   if (NULL != copy)
782   {
783     if (copy->mid == rel->mid_recv || GNUNET_NO == ch->reliable)
784     {
785       struct GNUNET_MESH_Data *msg = (struct GNUNET_MESH_Data *) &copy[1];
786
787       LOG (GNUNET_ERROR_TYPE_DEBUG,
788                   " have %u! now expecting %u\n",
789                   copy->mid, rel->mid_recv + 1);
790       send_client_data (ch, msg, fwd);
791       rel->n_recv--;
792       rel->mid_recv++;
793       GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy);
794       GNUNET_free (copy);
795     }
796     else
797     {
798       LOG (GNUNET_ERROR_TYPE_DEBUG,
799                   " reliable && don't have %u, next is %u\n",
800                   rel->mid_recv,
801                   copy->mid);
802       return;
803     }
804   }
805   LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data END\n");
806 }
807
808
809
810
811 /**
812  * Destroy a channel and free all resources.
813  *
814  * @param ch Channel to destroy.
815  */
816 static void
817 channel_destroy (struct MeshChannel *ch)
818 {
819   struct MeshClient *c;
820
821   if (NULL == ch)
822     return;
823
824   LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying channel %s:%u\n",
825               GMT_2s (ch->t), ch->gid);
826   GMCH_debug (ch);
827
828   c = ch->root;
829   if (NULL != c)
830   {
831     GML_channel_remove (c, ch->lid_root, ch);
832   }
833
834   c = ch->dest;
835   if (NULL != c)
836   {
837     GML_channel_remove (c, ch->lid_dest, ch);
838   }
839
840   channel_rel_free_all (ch->root_rel);
841   channel_rel_free_all (ch->dest_rel);
842
843   GMT_remove_channel (ch->t, ch);
844   GNUNET_STATISTICS_update (stats, "# channels", -1, GNUNET_NO);
845
846   GNUNET_free (ch);
847 }
848
849
850 /**
851  * Create a new channel.
852  *
853  * @param t Tunnel this channel is in.
854  * @param owner Client that owns the channel, NULL for foreign channels.
855  * @param lid_root Local ID for root client.
856  *
857  * @return A new initialized channel. NULL on error.
858  */
859 static struct MeshChannel *
860 channel_new (struct MeshTunnel3 *t,
861              struct MeshClient *owner, MESH_ChannelNumber lid_root)
862 {
863   struct MeshChannel *ch;
864
865   ch = GNUNET_new (struct MeshChannel);
866   ch->root = owner;
867   ch->lid_root = lid_root;
868   ch->t = t;
869
870   GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
871
872   if (NULL != owner)
873   {
874     ch->gid = GMT_get_next_chid (t);
875     GML_channel_add (owner, lid_root, ch);
876   }
877   GMT_add_channel (t, ch);
878
879   return ch;
880 }
881
882
883 /**
884  * Set options in a channel, extracted from a bit flag field
885  *
886  * @param ch Channel to set options to.
887  * @param options Bit array in host byte order.
888  */
889 static void
890 channel_set_options (struct MeshChannel *ch, uint32_t options)
891 {
892   ch->nobuffer = (options & GNUNET_MESH_OPTION_NOBUFFER) != 0 ?
893                  GNUNET_YES : GNUNET_NO;
894   ch->reliable = (options & GNUNET_MESH_OPTION_RELIABLE) != 0 ?
895                  GNUNET_YES : GNUNET_NO;
896 }
897
898
899
900 /**
901  * Confirm we got a channel create.
902  *
903  * @param ch The channel to confirm.
904  * @param fwd Should we send the ACK fwd?
905  */
906 static void
907 channel_send_ack (struct MeshChannel *ch, int fwd)
908 {
909   struct GNUNET_MESH_ChannelManage msg;
910
911   msg.header.size = htons (sizeof (msg));
912   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK);
913   LOG (GNUNET_ERROR_TYPE_DEBUG,
914               "  sending channel %s ack for channel %s:%X\n",
915               fwd ? "FWD" : "BCK", GMT_2s (ch->t),
916               ch->gid);
917
918   msg.chid = htonl (ch->gid);
919   GMCH_send_prebuilt_message (&msg.header, ch, !fwd);
920 }
921
922
923 /**
924  * Iterator for deleting each channel whose client endpoint disconnected.
925  *
926  * @param cls Closure (client that has disconnected).
927  * @param key The local channel id (used to access the hashmap).
928  * @param value The value stored at the key (channel to destroy).
929  *
930  * @return GNUNET_OK, keep iterating.
931  */
932 static int
933 channel_destroy_iterator (void *cls,
934                           uint32_t key,
935                           void *value)
936 {
937   struct MeshChannel *ch = value;
938   struct MeshClient *c = cls;
939   struct MeshTunnel3 *t;
940
941   LOG (GNUNET_ERROR_TYPE_DEBUG,
942               " Channel %X (%X / %X) destroy, due to client %s shutdown.\n",
943               ch->gid, ch->lid_root, ch->lid_dest, GML_2s (c));
944   GMCH_debug (ch);
945
946   if (c == ch->dest)
947   {
948     LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is destination.\n", GML_2s (c));
949   }
950   if (c == ch->root)
951   {
952     LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is owner.\n", GML_2s (c));
953   }
954
955   t = ch->t;
956   GMCH_send_destroy (ch);
957   channel_destroy (ch);
958   GMT_destroy_if_empty (t);
959
960   return GNUNET_OK;
961 }
962
963
964 /**
965  * Handle a loopback message: call the appropriate handler for the message type.
966  *
967  * @param ch Channel this message is on.
968  * @param msgh Message header.
969  * @param fwd Is this FWD traffic?
970  */
971 void
972 handle_loopback (struct MeshChannel *ch,
973                  struct GNUNET_MessageHeader *msgh,
974                  int fwd)
975 {
976   uint16_t type;
977
978   type = ntohs (msgh->type);
979   LOG (GNUNET_ERROR_TYPE_DEBUG,
980        "Loopback %s message!\n",
981        GNUNET_MESH_DEBUG_M2S (type));
982
983   switch (type)
984   {
985     case GNUNET_MESSAGE_TYPE_MESH_DATA:
986       /* Don't send hop ACK, wait for client to ACK */
987       GMCH_handle_data (ch, (struct GNUNET_MESH_Data *) msgh, fwd);
988       break;
989
990     case GNUNET_MESSAGE_TYPE_MESH_DATA_ACK:
991       GMCH_handle_data_ack (ch, (struct GNUNET_MESH_DataACK *) msgh, fwd);
992       break;
993
994     case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE:
995        // FIXME store channel in loopback tunnel?
996       GMCH_handle_create ((struct GNUNET_MESH_ChannelCreate *) msgh,
997                           fwd);
998       break;
999
1000     case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK:
1001       GMCH_handle_ack (ch,
1002                        (struct GNUNET_MESH_ChannelManage *) msgh,
1003                        fwd);
1004       break;
1005
1006     case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY:
1007       GMCH_handle_destroy (ch,
1008                            (struct GNUNET_MESH_ChannelManage *) msgh,
1009                            fwd);
1010       break;
1011
1012     default:
1013       GNUNET_break_op (0);
1014       LOG (GNUNET_ERROR_TYPE_DEBUG,
1015            "end-to-end message not known (%u)\n",
1016            ntohs (msgh->type));
1017   }
1018 }
1019
1020
1021
1022 /******************************************************************************/
1023 /********************************    API    ***********************************/
1024 /******************************************************************************/
1025
1026 /**
1027  * Get channel ID.
1028  *
1029  * @param ch Channel.
1030  *
1031  * @return ID
1032  */
1033 MESH_ChannelNumber
1034 GMCH_get_id (const struct MeshChannel *ch)
1035 {
1036   return ch->gid;
1037 }
1038
1039
1040 /**
1041  * Get the channel tunnel.
1042  *
1043  * @param ch Channel to get the tunnel from.
1044  *
1045  * @return tunnel of the channel.
1046  */
1047 struct MeshTunnel3 *
1048 GMCH_get_tunnel (const struct MeshChannel *ch)
1049 {
1050   return ch->t;
1051 }
1052
1053
1054 /**
1055  * Get free buffer space towards the client on a specific channel.
1056  *
1057  * @param ch Channel.
1058  * @param fwd Is query about FWD traffic?
1059  *
1060  * @return Free buffer space [0 - 64]
1061  */
1062 unsigned int
1063 GMCH_get_buffer (struct MeshChannel *ch, int fwd)
1064 {
1065   struct MeshChannelReliability *rel;
1066
1067   rel = fwd ? ch->dest_rel : ch->root_rel;
1068
1069   /* If rel is NULL it means that the end is not yet created,
1070    * most probably is a loopback channel at the point of sending
1071    * the ChannelCreate to itself.
1072    */
1073   if (NULL == rel)
1074     return 64;
1075
1076   return (64 - rel->n_recv);
1077 }
1078
1079
1080 /**
1081  * Is the root client for this channel on this peer?
1082  *
1083  * @param ch Channel.
1084  * @param fwd Is this for fwd traffic?
1085  *
1086  * @return GNUNET_YES in case it is.
1087  */
1088 int
1089 GMCH_is_origin (struct MeshChannel *ch, int fwd)
1090 {
1091   struct MeshClient *c;
1092
1093   c = fwd ? ch->root : ch->dest;
1094   return NULL != c;
1095 }
1096
1097
1098 /**
1099  * Is the destination client for this channel on this peer?
1100  *
1101  * @param ch Channel.
1102  * @param fwd Is this for fwd traffic?
1103  *
1104  * @return GNUNET_YES in case it is.
1105  */
1106 int
1107 GMCH_is_terminal (struct MeshChannel *ch, int fwd)
1108 {
1109   struct MeshClient *c;
1110
1111   c = fwd ? ch->dest : ch->root;
1112   return NULL != c;
1113 }
1114
1115
1116 /**
1117  * Notify the destination client that a new incoming channel was created.
1118  *
1119  * @param ch Channel that was created.
1120  */
1121 void
1122 GMCH_send_create (struct MeshChannel *ch)
1123 {
1124   struct GNUNET_MESH_ChannelMessage msg;
1125   uint32_t opt;
1126
1127   if (NULL == ch->dest)
1128     return;
1129
1130   opt = 0;
1131   opt |= GNUNET_YES == ch->reliable ? GNUNET_MESH_OPTION_RELIABLE : 0;
1132   opt |= GNUNET_YES == ch->nobuffer ? GNUNET_MESH_OPTION_NOBUFFER : 0;
1133   GML_send_channel_create (ch->dest, ch->lid_dest, ch->port, opt,
1134                            GMT_get_destination (ch->t));
1135
1136 }
1137
1138 /**
1139  * Notify a client that the channel is no longer valid.
1140  * FIXME send on tunnel if some client == NULL?
1141  *
1142  * @param ch Channel that is destroyed.
1143  */
1144 void
1145 GMCH_send_destroy (struct MeshChannel *ch)
1146 {
1147   if (NULL != ch->root)
1148     GML_send_channel_destroy (ch->root, ch->lid_root);
1149
1150   if (NULL != ch->dest)
1151     GML_send_channel_destroy (ch->dest, ch->lid_dest);
1152 }
1153
1154
1155 /**
1156  * Send data on a channel.
1157  *
1158  * If the destination is local, send it to client, otherwise encrypt and
1159  * send to next hop.
1160  *
1161  * @param ch Channel
1162  * @param msg Message.
1163  * @param fwd Is this a fwd (root->dest) message?
1164  */
1165 void
1166 GMCH_send_data (struct MeshChannel *ch,
1167                 const struct GNUNET_MESH_Data *msg,
1168                 int fwd)
1169 {
1170 }
1171
1172
1173 /**
1174  * Send an end-to-end ACK message for the most recent in-sequence payload.
1175  *
1176  * If channel is not reliable, do nothing.
1177  *
1178  * @param ch Channel this is about.
1179  * @param fwd Is for FWD traffic? (ACK dest->owner)
1180  */
1181 void
1182 GMCH_send_ack (struct MeshChannel *ch, int fwd)
1183 {
1184   struct GNUNET_MESH_DataACK msg;
1185   struct MeshChannelReliability *rel;
1186   struct MeshReliableMessage *copy;
1187   unsigned int delta;
1188   uint64_t mask;
1189   uint16_t type;
1190
1191   if (GNUNET_NO == ch->reliable)
1192   {
1193     return;
1194   }
1195   rel = fwd ? ch->dest_rel : ch->root_rel;
1196   LOG (GNUNET_ERROR_TYPE_DEBUG,
1197               "send_data_ack for %u\n",
1198               rel->mid_recv - 1);
1199
1200   type = GNUNET_MESSAGE_TYPE_MESH_DATA_ACK;
1201   msg.header.type = htons (type);
1202   msg.header.size = htons (sizeof (msg));
1203   msg.chid = htonl (ch->gid);
1204   msg.mid = htonl (rel->mid_recv - 1);
1205   msg.futures = 0;
1206   for (copy = rel->head_recv; NULL != copy; copy = copy->next)
1207   {
1208     if (copy->type != type)
1209       continue;
1210     delta = copy->mid - rel->mid_recv;
1211     if (63 < delta)
1212       break;
1213     mask = 0x1LL << delta;
1214     msg.futures |= mask;
1215     LOG (GNUNET_ERROR_TYPE_DEBUG,
1216                 " setting bit for %u (delta %u) (%llX) -> %llX\n",
1217                 copy->mid, delta, mask, msg.futures);
1218   }
1219   LOG (GNUNET_ERROR_TYPE_DEBUG, " final futures %llX\n", msg.futures);
1220
1221   GMCH_send_prebuilt_message (&msg.header, ch, fwd);
1222   LOG (GNUNET_ERROR_TYPE_DEBUG, "send_data_ack END\n");
1223 }
1224
1225
1226 /**
1227  * Log channel info.
1228  *
1229  * @param ch Channel.
1230  */
1231 void
1232 GMCH_debug (struct MeshChannel *ch)
1233 {
1234   if (NULL == ch)
1235   {
1236     LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CHANNEL ***\n");
1237     return;
1238   }
1239   LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %s:%X (%p)\n",
1240               GMT_2s (ch->t), ch->gid, ch);
1241   LOG (GNUNET_ERROR_TYPE_DEBUG, "  root %p/%p\n",
1242               ch->root, ch->root_rel);
1243   if (NULL != ch->root)
1244   {
1245     LOG (GNUNET_ERROR_TYPE_DEBUG, "  cli %s\n", GML_2s (ch->root));
1246     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ready %s\n",
1247                 ch->root_rel->client_ready ? "YES" : "NO");
1248     LOG (GNUNET_ERROR_TYPE_DEBUG, "  id %X\n", ch->lid_root);
1249   }
1250   LOG (GNUNET_ERROR_TYPE_DEBUG, "  dest %p/%p\n",
1251               ch->dest, ch->dest_rel);
1252   if (NULL != ch->dest)
1253   {
1254     LOG (GNUNET_ERROR_TYPE_DEBUG, "  cli %s\n", GML_2s (ch->dest));
1255     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ready %s\n",
1256                 ch->dest_rel->client_ready ? "YES" : "NO");
1257     LOG (GNUNET_ERROR_TYPE_DEBUG, "  id %X\n", ch->lid_dest);
1258   }
1259 }
1260
1261
1262 /**
1263  * Handler for mesh network payload traffic.
1264  *
1265  * @param ch Channel for the message.
1266  * @param message Unencryted data message.
1267  * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1268  */
1269 void
1270 GMCH_handle_data (struct MeshChannel *ch,
1271                   const struct GNUNET_MESH_Data *msg,
1272                   int fwd)
1273 {
1274   struct MeshChannelReliability *rel;
1275   struct MeshClient *c;
1276   uint32_t mid;
1277   uint16_t type;
1278   size_t size;
1279
1280   /*  Initialize FWD/BCK data */
1281   c   = fwd ? ch->dest     : ch->root;
1282   rel = fwd ? ch->dest_rel : ch->root_rel;
1283
1284   if (NULL == c)
1285   {
1286     GNUNET_break (0);
1287     return;
1288   }
1289
1290   GNUNET_STATISTICS_update (stats, "# data received", 1, GNUNET_NO);
1291
1292   mid = ntohl (msg->mid);
1293   LOG (GNUNET_ERROR_TYPE_DEBUG, " mid %u\n", mid);
1294
1295   if (GNUNET_NO == ch->reliable ||
1296       ( !GMC_is_pid_bigger (rel->mid_recv, mid) &&
1297         GMC_is_pid_bigger (rel->mid_recv + 64, mid) ) )
1298   {
1299     LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RECV %u\n", mid);
1300     if (GNUNET_YES == ch->reliable)
1301     {
1302       /* Is this the exact next expected messasge? */
1303       if (mid == rel->mid_recv)
1304       {
1305         LOG (GNUNET_ERROR_TYPE_DEBUG, "as expected\n");
1306         rel->mid_recv++;
1307         send_client_data (ch, msg, fwd);
1308       }
1309       else
1310       {
1311         LOG (GNUNET_ERROR_TYPE_DEBUG, "save for later\n");
1312         add_buffered_data (msg, rel);
1313       }
1314     }
1315     else
1316     {
1317       /* Tunnel is unreliable: send to clients directly */
1318       /* FIXME: accept Out Of Order traffic */
1319       rel->mid_recv = mid + 1;
1320       send_client_data (ch, msg, fwd);
1321     }
1322   }
1323   else
1324   {
1325     GNUNET_break_op (0);
1326     LOG (GNUNET_ERROR_TYPE_DEBUG,
1327                 " MID %u not expected (%u - %u), dropping!\n",
1328                 mid, rel->mid_recv, rel->mid_recv + 64);
1329   }
1330
1331   GMCH_send_ack (ch, fwd);
1332 }
1333
1334
1335 /**
1336  * Handler for mesh network traffic end-to-end ACKs.
1337  *
1338  * @param t Tunnel on which we got this message.
1339  * @param message Data message.
1340  * @param fwd Is this a fwd ACK? (dest->orig)
1341  */
1342 void
1343 GMCH_handle_data_ack (struct MeshChannel *ch,
1344                       const struct GNUNET_MESH_DataACK *msg,
1345                       int fwd)
1346 {
1347   struct MeshChannelReliability *rel;
1348   struct MeshReliableMessage *copy;
1349   struct MeshReliableMessage *next;
1350   uint32_t ack;
1351   int work;
1352
1353   ack = ntohl (msg->mid);
1354   LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! %s ACK %u\n",
1355               (GNUNET_YES == fwd) ? "FWD" : "BCK", ack);
1356
1357   if (GNUNET_YES == fwd)
1358   {
1359     rel = ch->root_rel;
1360   }
1361   else
1362   {
1363     rel = ch->dest_rel;
1364   }
1365   if (NULL == rel)
1366   {
1367     GNUNET_break (0);
1368     return;
1369   }
1370
1371   for (work = GNUNET_NO, copy = rel->head_sent; copy != NULL; copy = next)
1372   {
1373     if (GMC_is_pid_bigger (copy->mid, ack))
1374     {
1375       LOG (GNUNET_ERROR_TYPE_DEBUG, "!!!  head %u, out!\n", copy->mid);
1376       channel_rel_free_sent (rel, msg);
1377       break;
1378     }
1379     work = GNUNET_YES;
1380     LOG (GNUNET_ERROR_TYPE_DEBUG, "!!!  id %u\n", copy->mid);
1381     next = copy->next;
1382     rel_message_free (copy);
1383   }
1384   /* ACK client if needed */
1385 //   channel_send_ack (t, type, GNUNET_MESSAGE_TYPE_MESH_UNICAST_ACK == type);
1386
1387   /* If some message was free'd, update the retransmission delay*/
1388   if (GNUNET_YES == work)
1389   {
1390     if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task)
1391     {
1392       GNUNET_SCHEDULER_cancel (rel->retry_task);
1393       if (NULL == rel->head_sent)
1394       {
1395         rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
1396       }
1397       else
1398       {
1399         struct GNUNET_TIME_Absolute new_target;
1400         struct GNUNET_TIME_Relative delay;
1401
1402         delay = GNUNET_TIME_relative_multiply (rel->retry_timer,
1403                                                MESH_RETRANSMIT_MARGIN);
1404         new_target = GNUNET_TIME_absolute_add (rel->head_sent->timestamp,
1405                                                delay);
1406         delay = GNUNET_TIME_absolute_get_remaining (new_target);
1407         rel->retry_task =
1408             GNUNET_SCHEDULER_add_delayed (delay,
1409                                           &channel_retransmit_message,
1410                                           rel);
1411       }
1412     }
1413     else
1414       GNUNET_break (0);
1415   }
1416 }
1417
1418
1419 /**
1420  * Handler for channel create messages.
1421  *
1422  * @param msg Message.
1423  * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1424  */
1425 struct MeshChannel *
1426 GMCH_handle_create (const struct GNUNET_MESH_ChannelCreate *msg,
1427                     int fwd)
1428 {
1429   MESH_ChannelNumber chid;
1430   struct MeshChannel *ch;
1431   struct MeshClient *c;
1432   uint32_t port;
1433
1434   chid = ntohl (msg->chid);
1435
1436   /* Create channel */
1437   ch = channel_new (NULL, NULL, 0); /* FIXME t */
1438   ch->gid = chid;
1439   channel_set_options (ch, ntohl (msg->opt));
1440
1441   /* Find a destination client */
1442   port = ntohl (msg->port);
1443   LOG (GNUNET_ERROR_TYPE_DEBUG, "   port %u\n", port);
1444   c = GML_client_get_by_port (port);
1445   if (NULL == c)
1446   {
1447     /* TODO send reject */
1448     LOG (GNUNET_ERROR_TYPE_DEBUG, "  no client has port registered\n");
1449     /* TODO free ch */
1450     return;
1451   }
1452
1453   channel_add_client (ch, c);
1454   if (GNUNET_YES == ch->reliable)
1455     LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Reliable\n");
1456
1457   GMCH_send_create (ch);
1458   GMCH_send_ack (ch, fwd);
1459   GML_send_ack (ch, !fwd);
1460
1461   return ch;
1462 }
1463
1464
1465 /**
1466  * Handler for channel ack messages.
1467  *
1468  * @param ch Channel.
1469  * @param msg Message.
1470  * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1471  */
1472 void
1473 GMCH_handle_ack (struct MeshChannel *ch,
1474                  const struct GNUNET_MESH_ChannelManage *msg,
1475                  int fwd)
1476 {
1477   channel_confirm (ch, !fwd);
1478 }
1479
1480
1481 /**
1482  * Handler for channel destroy messages.
1483  *
1484  * @param ch Channel to be destroyed of.
1485  * @param msg Message.
1486  * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1487  */
1488 void
1489 GMCH_handle_destroy (struct MeshChannel *ch,
1490                      const struct GNUNET_MESH_ChannelManage *msg,
1491                      int fwd)
1492 {
1493   MESH_ChannelNumber chid;
1494
1495   /* Check if channel exists */
1496   chid = ntohl (msg->chid);
1497   if ( (fwd && NULL == ch->dest) || (!fwd && NULL == ch->root) )
1498   {
1499     /* Not for us (don't destroy twice a half-open loopback channel) */
1500     return;
1501   }
1502
1503   GMCH_send_destroy (ch);
1504   channel_destroy (ch);
1505 }
1506
1507
1508 /**
1509  * Sends an already built message on a channel.
1510  *
1511  * @param message Message to send. Function makes a copy of it.
1512  * @param ch Channel on which this message is transmitted.
1513  * @param fwd Is this a fwd message?
1514  */
1515 void
1516 GMCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
1517                             struct MeshChannel *ch, int fwd)
1518 {
1519   size_t size = ntohs (message->size);
1520
1521   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send on Channel %s:%X %s\n",
1522        GMT_2s (ch->t), ch->gid, fwd ? "FWD" : "BCK");
1523   LOG (GNUNET_ERROR_TYPE_DEBUG, "  %s\n",
1524        GNUNET_MESH_DEBUG_M2S (ntohs (message->type)));
1525
1526   if (GMT_is_loopback (ch->t))
1527   {
1528     handle_loopback (ch->t, message, fwd);
1529     return;
1530   }
1531
1532   GMT_send_prebuilt_message (message, ch->t, ch, fwd);
1533 }