more work on TNG
[oweals/gnunet.git] / src / transport / gnunet-service-tng.c
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2010-2016, 2018 GNUnet e.V.
4
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your 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  Affero General Public License for more details.
14
15  You should have received a copy of the GNU Affero General Public License
16  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 /**
19  * @file transport/gnunet-service-transport.c
20  * @brief main for gnunet-service-transport
21  * @author Christian Grothoff
22  *
23  * TODO:
24  * - monitor start: iterate to inform monitor about all existing queues!
25  * - manage fragmentation/defragmentation, retransmission, track RTT, loss, etc.
26  * - inform ATS about RTT, goodput/loss, overheads, etc.
27  * - ask ATS about bandwidth allocation!
28  * -
29  */
30 #include "platform.h"
31 #include "gnunet_util_lib.h"
32 #include "gnunet_statistics_service.h"
33 #include "gnunet_transport_service.h"
34 #include "gnunet_transport_monitor_service.h"
35 #include "gnunet_peerstore_service.h"
36 #include "gnunet_ats_service.h"
37 #include "gnunet-service-transport.h"
38 #include "transport.h"
39
40
41 /**
42  * How many messages can we have pending for a given client process
43  * before we start to drop incoming messages?  We typically should
44  * have only one client and so this would be the primary buffer for
45  * messages, so the number should be chosen rather generously.
46  *
47  * The expectation here is that most of the time the queue is large
48  * enough so that a drop is virtually never required.  Note that
49  * this value must be about as large as 'TOTAL_MSGS' in the
50  * 'test_transport_api_reliability.c', otherwise that testcase may
51  * fail.
52  */
53 #define MAX_PENDING (128 * 1024)
54
55
56 /**
57  * What type of client is the `struct TransportClient` about?
58  */
59 enum ClientType
60 {
61   /**
62    * We do not know yet (client is fresh).
63    */
64   CT_NONE = 0,
65
66   /**
67    * Is the CORE service, we need to forward traffic to it.
68    */
69   CT_CORE = 1,
70
71   /**
72    * It is a monitor, forward monitor data.
73    */
74   CT_MONITOR = 2,
75
76   /**
77    * It is a communicator, use for communication.
78    */
79   CT_COMMUNICATOR = 3
80 };
81
82
83 /**
84  * Client connected to the transport service.
85  */
86 struct TransportClient;
87
88
89 /**
90  * A neighbour that at least one communicator is connected to.
91  */
92 struct Neighbour;
93
94
95 /**
96  * List of available queues for a particular neighbour.
97  */
98 struct Queue
99 {
100   /**
101    * Kept in a MDLL.
102    */
103   struct Queue *next_neighbour;
104
105   /**
106    * Kept in a MDLL.
107    */
108   struct Queue *prev_neighbour;
109
110   /**
111    * Kept in a MDLL.
112    */
113   struct Queue *prev_client;
114
115   /**
116    * Kept in a MDLL.
117    */
118   struct Queue *next_client;
119
120   /**
121    * Which neighbour is this queue for?
122    */
123   struct Neighbour *neighbour;
124
125   /**
126    * Which communicator offers this queue?
127    */
128   struct TransportClient *tc;
129
130   /**
131    * Address served by the queue.
132    */
133   const char *address;
134
135   /**
136    * Unique identifier of this queue with the communicator.
137    */
138   uint32_t qid;
139
140   /**
141    * Maximum transmission unit supported by this queue.
142    */
143   uint32_t mtu;
144   
145   /**
146    * Network type offered by this queue.
147    */
148   enum GNUNET_ATS_Network_Type nt;
149
150   // FIXME: add ATS-specific fields here!
151 };
152
153
154 /**
155  * A neighbour that at least one communicator is connected to.
156  */
157 struct Neighbour
158 {
159
160   /**
161    * Which peer is this about?
162    */
163   struct GNUNET_PeerIdentity pid;
164
165   /**
166    * Head of list of messages pending for this neighbour.
167    */
168   struct PendingMessage *pending_msg_head;
169
170   /**
171    * Tail of list of messages pending for this neighbour.
172    */
173   struct PendingMessage *pending_msg_tail;
174
175   /**
176    * Head of DLL of queues to this peer.
177    */
178   struct Queue *queue_head;
179
180   /**
181    * Tail of DLL of queues to this peer.
182    */
183   struct Queue *queue_tail;
184
185   /**
186    * Quota at which CORE is allowed to transmit to this peer
187    * according to ATS.
188    *
189    * FIXME: not yet used, tricky to get right given multiple queues!
190    *        (=> Idea: let ATS set a quota per queue and we add them up here?)
191    * FIXME: how do we set this value initially when we tell CORE?
192    *    Options: start at a minimum value or at literally zero (before ATS?)
193    *         (=> Current thought: clean would be zero!)
194    */
195   struct GNUNET_BANDWIDTH_Value32NBO quota_out;
196
197 };
198
199
200 /**
201  * Transmission request from CORE that is awaiting delivery.
202  */
203 struct PendingMessage
204 {
205   /**
206    * Kept in a MDLL of messages for this @a target.
207    */
208   struct PendingMessage *next_neighbour;
209
210   /**
211    * Kept in a MDLL of messages for this @a target.
212    */
213   struct PendingMessage *prev_neighbour;
214
215   /**
216    * Kept in a MDLL of messages from this @a client.
217    */
218   struct PendingMessage *next_client;
219
220   /**
221    * Kept in a MDLL of messages from this @a client.
222    */
223   struct PendingMessage *prev_client;
224
225   /**
226    * Target of the request.
227    */
228   struct Neighbour *target;
229
230   /**
231    * Client that issued the transmission request.
232    */
233   struct TransportClient *client;
234
235   /**
236    * Size of the original message.
237    */
238   uint32_t bytes_msg;
239
240 };
241
242
243 /**
244  * One of the addresses of this peer.
245  */
246 struct AddressListEntry
247 {
248
249   /**
250    * Kept in a DLL.
251    */
252   struct AddressListEntry *next;
253
254   /**
255    * Kept in a DLL.
256    */
257   struct AddressListEntry *prev;
258
259   /**
260    * Which communicator provides this address?
261    */
262   struct TransportClient *tc;
263
264   /**
265    * The actual address.
266    */
267   const char *address;
268
269   /**
270    * Current context for storing this address in the peerstore.
271    */
272   struct GNUNET_PEERSTORE_StoreContext *sc;
273
274   /**
275    * Task to periodically do @e st operation.
276    */
277   struct GNUNET_SCHEDULER_Task *st;
278
279   /**
280    * What is a typical lifetime the communicator expects this
281    * address to have? (Always from now.)
282    */
283   struct GNUNET_TIME_Relative expiration;
284
285   /**
286    * Address identifier used by the communicator.
287    */
288   uint32_t aid;
289
290   /**
291    * Network type offered by this address.
292    */
293   enum GNUNET_ATS_Network_Type nt;
294
295 };
296
297
298 /**
299  * Client connected to the transport service.
300  */
301 struct TransportClient
302 {
303
304   /**
305    * Kept in a DLL.
306    */
307   struct TransportClient *next;
308
309   /**
310    * Kept in a DLL.
311    */
312   struct TransportClient *prev;
313
314   /**
315    * Handle to the client.
316    */
317   struct GNUNET_SERVICE_Client *client;
318
319   /**
320    * Message queue to the client.
321    */
322   struct GNUNET_MQ_Handle *mq;
323
324   /**
325    * What type of client is this?
326    */
327   enum ClientType type;
328
329   union
330   {
331
332     /**
333      * Information for @e type #CT_CORE.
334      */
335     struct {
336
337       /**
338        * Head of list of messages pending for this client.
339        */
340       struct PendingMessage *pending_msg_head;
341
342       /**
343        * Tail of list of messages pending for this client.
344        */
345       struct PendingMessage *pending_msg_tail;
346
347     } core;
348
349     /**
350      * Information for @e type #CT_MONITOR.
351      */
352     struct {
353
354       /**
355        * Peer identity to monitor the addresses of.
356        * Zero to monitor all neighbours.  Valid if
357        * @e type is #CT_MONITOR.
358        */
359       struct GNUNET_PeerIdentity peer;
360
361       /**
362        * Is this a one-shot monitor?
363        */
364       int one_shot;
365
366     } monitor;
367
368
369     /**
370      * Information for @e type #CT_COMMUNICATOR.
371      */
372     struct {
373       /**
374        * If @e type is #CT_COMMUNICATOR, this communicator
375        * supports communicating using these addresses.
376        */
377       char *address_prefix;
378
379       /**
380        * Head of DLL of queues offered by this communicator.
381        */
382       struct Queue *queue_head;
383
384       /**
385        * Tail of DLL of queues offered by this communicator.
386        */
387       struct Queue *queue_tail;
388
389       /**
390        * Head of list of the addresses of this peer offered by this communicator.
391        */
392       struct AddressListEntry *addr_head;
393
394       /**
395        * Tail of list of the addresses of this peer offered by this communicator.
396        */
397       struct AddressListEntry *addr_tail;
398
399     } communicator;
400
401   } details;
402
403 };
404
405
406 /**
407  * Head of linked list of all clients to this service.
408  */
409 static struct TransportClient *clients_head;
410
411 /**
412  * Tail of linked list of all clients to this service.
413  */
414 static struct TransportClient *clients_tail;
415
416 /**
417  * Statistics handle.
418  */
419 struct GNUNET_STATISTICS_Handle *GST_stats;
420
421 /**
422  * Configuration handle.
423  */
424 const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
425
426 /**
427  * Our public key.
428  */
429 struct GNUNET_PeerIdentity GST_my_identity;
430
431 /**
432  * Our private key.
433  */
434 struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
435
436 /**
437  * Map from PIDs to `struct Neighbour` entries.  A peer is
438  * a neighbour if we have an MQ to it from some communicator.
439  */
440 static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
441
442 /**
443  * Database for peer's HELLOs.
444  */
445 static struct GNUNET_PEERSTORE_Handle *peerstore;
446
447
448 /**
449  * Lookup neighbour record for peer @a pid.
450  *
451  * @param pid neighbour to look for
452  * @return NULL if we do not have this peer as a neighbour
453  */
454 static struct Neighbour *
455 lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
456 {
457   return GNUNET_CONTAINER_multipeermap_get (neighbours,
458                                             pid);
459 }
460
461
462 /**
463  * Details about what to notify monitors about.
464  */
465 struct MonitorEvent
466 {
467   /**
468    * @deprecated To be discussed if we keep these...
469    */
470   struct GNUNET_TIME_Absolute last_validation;
471   struct GNUNET_TIME_Absolute valid_until;
472   struct GNUNET_TIME_Absolute next_validation;
473
474   /**
475    * Current round-trip time estimate.
476    */
477   struct GNUNET_TIME_Relative rtt;
478
479   /**
480    * Connection status.
481    */
482   enum GNUNET_TRANSPORT_ConnectionStatus cs;
483
484   /**
485    * Messages pending.
486    */
487   uint32_t num_msg_pending;
488
489   /**
490    * Bytes pending.
491    */
492   uint32_t num_bytes_pending;
493
494
495 };
496
497
498 /**
499  * Notify monitor @a tc about an event.  That @a tc
500  * cares about the event has already been checked.
501  *
502  * Send @a tc information in @a me about a @a peer's status with
503  * respect to some @a address to all monitors that care.
504  *
505  * @param tc monitor to inform
506  * @param peer peer the information is about
507  * @param address address the information is about
508  * @param nt network type associated with @a address
509  * @param me detailed information to transmit
510  */
511 static void
512 notify_monitor (struct TransportClient *tc,
513                 const struct GNUNET_PeerIdentity *peer,
514                 const char *address,
515                 enum GNUNET_ATS_Network_Type nt,
516                 const struct MonitorEvent *me)
517 {
518   struct GNUNET_MQ_Envelope *env;
519   struct GNUNET_TRANSPORT_MonitorData *md;   
520   size_t addr_len = strlen (address) + 1;
521
522   env = GNUNET_MQ_msg_extra (md,
523                              addr_len,
524                              GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_DATA);
525   md->nt = htonl ((uint32_t) nt);
526   md->peer = *peer;
527   md->last_validation = GNUNET_TIME_absolute_hton (me->last_validation);
528   md->valid_until = GNUNET_TIME_absolute_hton (me->valid_until);
529   md->next_validation = GNUNET_TIME_absolute_hton (me->next_validation);
530   md->rtt = GNUNET_TIME_relative_hton (me->rtt);
531   md->cs = htonl ((uint32_t) me->cs);
532   md->num_msg_pending = htonl (me->num_msg_pending);
533   md->num_bytes_pending = htonl (me->num_bytes_pending);
534   memcpy (&md[1],
535           address,
536           addr_len);
537   GNUNET_MQ_send (tc->mq,
538                   env);
539 }
540
541
542 /**
543  * Send information in @a me about a @a peer's status with respect
544  * to some @a address to all monitors that care.
545  *
546  * @param peer peer the information is about
547  * @param address address the information is about
548  * @param nt network type associated with @a address
549  * @param me detailed information to transmit
550  */
551 static void
552 notify_monitors (const struct GNUNET_PeerIdentity *peer,
553                  const char *address,
554                  enum GNUNET_ATS_Network_Type nt,
555                  const struct MonitorEvent *me)
556 {
557   static struct GNUNET_PeerIdentity zero;
558
559   for (struct TransportClient *tc = clients_head;
560        NULL != tc;
561        tc = tc->next)
562   {
563     if (CT_MONITOR != tc->type)
564       continue;
565     if (tc->details.monitor.one_shot)
566       continue;
567     if ( (0 != memcmp (&tc->details.monitor.peer,
568                        &zero,
569                        sizeof (zero))) &&
570          (0 != memcmp (&tc->details.monitor.peer,
571                        peer,
572                        sizeof (*peer))) )
573       continue;
574     notify_monitor (tc,
575                     peer,
576                     address,
577                     nt,
578                     me);
579   }
580
581
582
583 /**
584  * Called whenever a client connects.  Allocates our
585  * data structures associated with that client.
586  *
587  * @param cls closure, NULL
588  * @param client identification of the client
589  * @param mq message queue for the client
590  * @return our `struct TransportClient`
591  */
592 static void *
593 client_connect_cb (void *cls,
594                    struct GNUNET_SERVICE_Client *client,
595                    struct GNUNET_MQ_Handle *mq)
596 {
597   struct TransportClient *tc;
598
599   tc = GNUNET_new (struct TransportClient);
600   tc->client = client;
601   tc->mq = mq;
602   GNUNET_CONTAINER_DLL_insert (clients_head,
603                                clients_tail,
604                                tc);
605   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
606               "Client %p connected\n",
607               tc);
608   return tc;
609 }
610
611
612 /**
613  * Release memory used by @a neighbour.
614  *
615  * @param neighbour neighbour entry to free
616  */
617 static void
618 free_neighbour (struct Neighbour *neighbour)
619 {
620   GNUNET_assert (NULL == neighbour->queue_head);
621   GNUNET_assert (GNUNET_YES ==
622                  GNUNET_CONTAINER_multipeermap_remove (neighbours,
623                                                        &neighbour->pid,
624                                                        neighbour));
625   GNUNET_free (neighbour);
626 }
627
628
629 /**
630  * Send message to CORE clients that we lost a connection.
631  *
632  * @param tc client to inform (must be CORE client)
633  * @param pid peer the connection is for
634  * @param quota_out current quota for the peer
635  */
636 static void
637 core_send_connect_info (struct TransportClient *tc,
638                         const struct GNUNET_PeerIdentity *pid,
639                         struct GNUNET_BANDWIDTH_Value32NBO quota_out)
640 {
641   struct GNUNET_MQ_Envelope *env;
642   struct ConnectInfoMessage *cim;
643     
644   GNUNET_assert (CT_CORE == tc->type);
645   env = GNUNET_MQ_msg (cim,
646                        GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
647   cim->quota_out = quota_out;
648   cim->id = *pid;
649   GNUNET_MQ_send (tc->mq,
650                   env);
651 }
652
653
654 /**
655  * Send message to CORE clients that we gained a connection
656  *
657  * @param pid peer the queue was for
658  * @param quota_out current quota for the peer
659  */
660 static void
661 cores_send_connect_info (const struct GNUNET_PeerIdentity *pid,
662                          struct GNUNET_BANDWIDTH_Value32NBO quota_out)
663 {
664   for (struct TransportClient *tc = clients_head;
665        NULL != tc;
666        tc = tc->next)
667   {    
668     if (CT_CORE != tc->type)
669       continue;
670     core_send_connect_info (tc,
671                             pid,
672                             quota_out);
673   }
674 }
675
676
677 /**
678  * Send message to CORE clients that we lost a connection.
679  *
680  * @param pid peer the connection was for
681  */
682 static void
683 cores_send_disconnect_info (const struct GNUNET_PeerIdentity *pid)
684 {
685   for (struct TransportClient *tc = clients_head;
686        NULL != tc;
687        tc = tc->next)
688   {
689     struct GNUNET_MQ_Envelope *env;
690     struct DisconnectInfoMessage *dim;
691     
692     if (CT_CORE != tc->type)
693       continue;
694     env = GNUNET_MQ_msg (dim,
695                          GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
696     dim->peer = *pid;
697     GNUNET_MQ_send (tc->mq,
698                     env);
699   }
700 }
701
702
703 /**
704  * Free @a queue.
705  *
706  * @param queue the queue to free
707  */
708 static void
709 free_queue (struct Queue *queue)
710 {
711   struct Neighbour *neighbour = queue->neighbour;
712   struct TransportClient *tc = queue->tc;
713   struct MonitorEvent me = {
714     .cs = GNUNET_TRANSPORT_CS_DOWN,
715     .rtt = GNUNET_TIME_UNIT_FOREVER_REL
716   };
717
718   GNUNET_CONTAINER_MDLL_remove (neighbour,
719                                 neighbour->queue_head,
720                                 neighbour->queue_tail,
721                                 queue);
722   GNUNET_CONTAINER_MDLL_remove (client,
723                                 tc->details.communicator.queue_head,
724                                 tc->details.communicator.queue_tail,
725                                 queue);
726
727   notify_monitors (&neighbour->pid,
728                    queue->address,
729                    queue->nt,
730                    &me);
731   GNUNET_free (queue);
732   if (NULL == neighbour->queue_head)
733     {
734       cores_send_disconnect_info (&neighbour->pid);
735       free_neighbour (neighbour);
736     }
737 }
738
739
740 /**
741  * Free @a ale
742  * 
743  * @param ale address list entry to free
744  */
745 static void
746 free_address_list_entry (struct AddressListEntry *ale)
747 {
748   struct TransportClient *tc = ale->tc;
749   
750   GNUNET_CONTAINER_DLL_remove (tc->details.communicator.addr_head,
751                                tc->details.communicator.addr_tail,
752                                ale);
753   if (NULL != ale->sc)
754   {
755     GNUNET_PEERSTORE_store_cancel (ale->sc);
756     ale->sc = NULL;
757   }
758   if (NULL != ale->st)
759   {
760     GNUNET_SCHEDULER_cancel (ale->st);
761     ale->st = NULL;
762   }
763   GNUNET_free (ale);
764 }
765
766
767 /**
768  * Called whenever a client is disconnected.  Frees our
769  * resources associated with that client.
770  *
771  * @param cls closure, NULL
772  * @param client identification of the client
773  * @param app_ctx our `struct TransportClient`
774  */
775 static void
776 client_disconnect_cb (void *cls,
777                       struct GNUNET_SERVICE_Client *client,
778                       void *app_ctx)
779 {
780   struct TransportClient *tc = app_ctx;
781
782   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
783               "Client %p disconnected, cleaning up.\n",
784               tc);
785   GNUNET_CONTAINER_DLL_remove (clients_head,
786                                clients_tail,
787                                tc);
788   switch (tc->type)
789   {
790   case CT_NONE:
791     break;
792   case CT_CORE:
793     {
794       struct PendingMessage *pm;
795
796       while (NULL != (pm = tc->details.core.pending_msg_head))
797       {
798         GNUNET_CONTAINER_MDLL_remove (client,
799                                       tc->details.core.pending_msg_head,
800                                       tc->details.core.pending_msg_tail,
801                                       pm);
802         pm->client = NULL;
803       }
804     }
805     break;
806   case CT_MONITOR:
807     break;
808   case CT_COMMUNICATOR:
809     {
810       struct Queue *q;
811       struct AddressListEntry *ale;
812
813       while (NULL != (q = tc->details.communicator.queue_head))
814         free_queue (q);
815       while (NULL != (ale = tc->details.communicator.addr_head))
816         free_address_list_entry (ale);
817       GNUNET_free (tc->details.communicator.address_prefix);
818     }
819     break;
820   }
821   GNUNET_free (tc);
822 }
823
824
825 /**
826  * Iterator telling new CORE client about all existing
827  * connections to peers.
828  *
829  * @param cls the new `struct TransportClient`
830  * @param pid a connected peer
831  * @param value the `struct Neighbour` with more information
832  * @return #GNUNET_OK (continue to iterate)
833  */
834 static int
835 notify_client_connect_info (void *cls,
836                             const struct GNUNET_PeerIdentity *pid,
837                             void *value)
838 {
839   struct TransportClient *tc = cls;
840   struct Neighbour *neighbour = value;
841   
842   core_send_connect_info (tc,
843                           pid,
844                           neighbour->quota_out);
845   return GNUNET_OK;
846 }
847
848
849 /**
850  * Initialize a "CORE" client.  We got a start message from this
851  * client, so add it to the list of clients for broadcasting of
852  * inbound messages.
853  *
854  * @param cls the client
855  * @param start the start message that was sent
856  */
857 static void
858 handle_client_start (void *cls,
859                      const struct StartMessage *start)
860 {
861   struct TransportClient *tc = cls;
862   uint32_t options;
863
864   options = ntohl (start->options);
865   if ( (0 != (1 & options)) &&
866        (0 !=
867         memcmp (&start->self,
868                 &GST_my_identity,
869                 sizeof (struct GNUNET_PeerIdentity)) ) )
870   {
871     /* client thinks this is a different peer, reject */
872     GNUNET_break (0);
873     GNUNET_SERVICE_client_drop (tc->client);
874     return;
875   }
876   if (CT_NONE != tc->type)
877   {
878     GNUNET_break (0);
879     GNUNET_SERVICE_client_drop (tc->client);
880     return;
881   }
882   tc->type = CT_CORE;
883   GNUNET_CONTAINER_multipeermap_iterate (neighbours,
884                                          &notify_client_connect_info,
885                                          tc);
886   GNUNET_SERVICE_client_continue (tc->client);
887 }
888
889
890 /**
891  * Client asked for transmission to a peer.  Process the request.
892  *
893  * @param cls the client
894  * @param obm the send message that was sent
895  */
896 static int
897 check_client_send (void *cls,
898                    const struct OutboundMessage *obm)
899 {
900   struct TransportClient *tc = cls;
901   uint16_t size;
902   const struct GNUNET_MessageHeader *obmm;
903
904   if (CT_CORE != tc->type)
905   {
906     GNUNET_break (0);
907     return GNUNET_SYSERR;
908   }
909   size = ntohs (obm->header.size) - sizeof (struct OutboundMessage);
910   if (size < sizeof (struct GNUNET_MessageHeader))
911   {
912     GNUNET_break (0);
913     return GNUNET_SYSERR;
914   }
915   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
916   if (size != ntohs (obmm->size))
917   {
918     GNUNET_break (0);
919     return GNUNET_SYSERR;
920   }
921   return GNUNET_OK;
922 }
923
924
925 /**
926  * Send a response to the @a pm that we have processed a
927  * "send" request with status @a success. We
928  * transmitted @a bytes_physical on the actual wire.
929  * Sends a confirmation to the "core" client responsible
930  * for the original request and free's @a pm.
931  *
932  * @param pm handle to the original pending message
933  * @param success status code, #GNUNET_OK on success, #GNUNET_SYSERR
934  *          for transmission failure
935  * @param bytes_physical amount of bandwidth consumed
936  */
937 static void
938 client_send_response (struct PendingMessage *pm,
939                       int success,
940                       uint32_t bytes_physical)
941 {
942   struct TransportClient *tc = pm->client;
943   struct Neighbour *target = pm->target;
944   struct GNUNET_MQ_Envelope *env;
945   struct SendOkMessage *som;
946
947   if (NULL != tc)
948   {
949     env = GNUNET_MQ_msg (som,
950                          GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
951     som->success = htonl ((uint32_t) success);
952     som->bytes_msg = htonl (pm->bytes_msg);
953     som->bytes_physical = htonl (bytes_physical);
954     som->peer = target->pid;
955     GNUNET_MQ_send (tc->mq,
956                     env);
957     GNUNET_CONTAINER_MDLL_remove (client,
958                                   tc->details.core.pending_msg_head,
959                                   tc->details.core.pending_msg_tail,
960                                   pm);
961   }
962   GNUNET_CONTAINER_MDLL_remove (neighbour,
963                                 target->pending_msg_head,
964                                 target->pending_msg_tail,
965                                 pm);
966   GNUNET_free (pm);
967 }
968
969
970 /**
971  * Client asked for transmission to a peer.  Process the request.
972  *
973  * @param cls the client
974  * @param obm the send message that was sent
975  */
976 static void
977 handle_client_send (void *cls,
978                     const struct OutboundMessage *obm)
979 {
980   struct TransportClient *tc = cls;
981   struct PendingMessage *pm;
982   const struct GNUNET_MessageHeader *obmm;
983   struct Neighbour *target;
984   uint32_t bytes_msg;
985
986   GNUNET_assert (CT_CORE == tc->type);
987   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
988   bytes_msg = ntohs (obmm->size);
989   target = lookup_neighbour (&obm->peer);
990   if (NULL == target)
991   {
992     /* Failure: don't have this peer as a neighbour (anymore).
993        Might have gone down asynchronously, so this is NOT
994        a protocol violation by CORE. Still count the event,
995        as this should be rare. */
996     struct GNUNET_MQ_Envelope *env;
997     struct SendOkMessage *som;
998
999     env = GNUNET_MQ_msg (som,
1000                          GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
1001     som->success = htonl (GNUNET_SYSERR);
1002     som->bytes_msg = htonl (bytes_msg);
1003     som->bytes_physical = htonl (0);
1004     som->peer = obm->peer;
1005     GNUNET_MQ_send (tc->mq,
1006                     env);
1007     GNUNET_SERVICE_client_continue (tc->client);
1008     GNUNET_STATISTICS_update (GST_stats,
1009                               "# messages dropped (neighbour unknown)",
1010                               1,
1011                               GNUNET_NO);
1012     return;
1013   }
1014   pm = GNUNET_new (struct PendingMessage);
1015   pm->client = tc;
1016   pm->target = target;
1017   pm->bytes_msg = bytes_msg;
1018   GNUNET_CONTAINER_MDLL_insert (neighbour,
1019                                 target->pending_msg_head,
1020                                 target->pending_msg_tail,
1021                                 pm);
1022   GNUNET_CONTAINER_MDLL_insert (client,
1023                                 tc->details.core.pending_msg_head,
1024                                 tc->details.core.pending_msg_tail,
1025                                 pm);
1026   // FIXME: do the work, final continuation with call to:
1027   client_send_response (pm,
1028                         GNUNET_NO,
1029                         0);
1030 }
1031
1032
1033 /**
1034  * Communicator started.  Test message is well-formed.
1035  *
1036  * @param cls the client
1037  * @param cam the send message that was sent
1038  */
1039 static int
1040 check_communicator_available (void *cls,
1041                               const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1042 {
1043   struct TransportClient *tc = cls;
1044   const char *addr;
1045   uint16_t size;
1046
1047   if (CT_NONE != tc->type)
1048   {
1049     GNUNET_break (0);
1050     return GNUNET_SYSERR;
1051   }
1052   tc->type = CT_COMMUNICATOR;
1053   size = ntohs (cam->header.size) - sizeof (*cam);
1054   if (0 == size)
1055     return GNUNET_OK; /* receive-only communicator */
1056   addr = (const char *) &cam[1];
1057   if ('\0' != addr[size-1])
1058   {
1059     GNUNET_break (0);
1060     return GNUNET_SYSERR;
1061   }
1062   return GNUNET_OK;
1063 }
1064
1065
1066 /**
1067  * Communicator started.  Process the request.
1068  *
1069  * @param cls the client
1070  * @param cam the send message that was sent
1071  */
1072 static void
1073 handle_communicator_available (void *cls,
1074                                const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1075 {
1076   struct TransportClient *tc = cls;
1077   uint16_t size;
1078
1079   size = ntohs (cam->header.size) - sizeof (*cam);
1080   if (0 == size)
1081     return; /* receive-only communicator */
1082   tc->details.communicator.address_prefix = GNUNET_strdup ((const char *) &cam[1]);
1083   GNUNET_SERVICE_client_continue (tc->client);
1084 }
1085
1086
1087 /**
1088  * Address of our peer added.  Test message is well-formed.
1089  *
1090  * @param cls the client
1091  * @param aam the send message that was sent
1092  */
1093 static int
1094 check_add_address (void *cls,
1095                    const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1096 {
1097   struct TransportClient *tc = cls;
1098   const char *addr;
1099   uint16_t size;
1100
1101   if (CT_COMMUNICATOR != tc->type)
1102   {
1103     GNUNET_break (0);
1104     return GNUNET_SYSERR;
1105   }
1106   size = ntohs (aam->header.size) - sizeof (*aam);
1107   if (0 == size)
1108   {
1109     GNUNET_break (0);
1110     return GNUNET_SYSERR;
1111   }
1112   addr = (const char *) &aam[1];
1113   if ('\0' != addr[size-1])
1114   {
1115     GNUNET_break (0);
1116     return GNUNET_SYSERR;
1117   }
1118   return GNUNET_OK;
1119 }
1120
1121
1122 /**
1123  * Ask peerstore to store our address.
1124  *
1125  * @param cls an `struct AddressListEntry *`
1126  */
1127 static void
1128 store_pi (void *cls);
1129
1130
1131 /**
1132  * Function called when peerstore is done storing our address.
1133  */
1134 static void
1135 peerstore_store_cb (void *cls,
1136                     int success)
1137 {
1138   struct AddressListEntry *ale = cls;
1139
1140   ale->sc = NULL;
1141   if (GNUNET_YES != success)
1142     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1143                 "Failed to store our own address `%s' in peerstore!\n",
1144                 ale->address);
1145   /* refresh period is 1/4 of expiration time, that should be plenty 
1146      without being excessive. */
1147   ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (ale->expiration,
1148                                                                        4ULL),
1149                                           &store_pi,
1150                                           ale);
1151 }
1152
1153
1154 /**
1155  * Ask peerstore to store our address.
1156  *
1157  * @param cls an `struct AddressListEntry *`
1158  */
1159 static void
1160 store_pi (void *cls)
1161 {
1162   struct AddressListEntry *ale = cls;
1163   void *addr;
1164   size_t addr_len;
1165   struct GNUNET_TIME_Absolute expiration;
1166   
1167   ale->st = NULL;
1168   expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
1169   GNUNET_HELLO_sign_address (ale->address,
1170                              ale->nt,
1171                              expiration,
1172                              GST_my_private_key,
1173                              &addr,
1174                              &addr_len);  
1175   ale->sc = GNUNET_PEERSTORE_store (peerstore,
1176                                     "transport",
1177                                     &GST_my_identity,
1178                                     "hello",
1179                                     addr,
1180                                     addr_len,
1181                                     expiration,
1182                                     GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
1183                                     &peerstore_store_cb,
1184                                     ale);
1185   GNUNET_free (addr);
1186   if (NULL == ale->sc)
1187   {
1188     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1189                 "Failed to store our address `%s' with peerstore\n",
1190                 ale->address);
1191     ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
1192                                             &store_pi,
1193                                             ale);
1194   }
1195 }
1196
1197
1198 /**
1199  * Address of our peer added.  Process the request.
1200  *
1201  * @param cls the client
1202  * @param aam the send message that was sent
1203  */
1204 static void
1205 handle_add_address (void *cls,
1206                     const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1207 {
1208   struct TransportClient *tc = cls;
1209   struct AddressListEntry *ale;
1210   size_t slen;
1211
1212   slen = ntohs (aam->header.size) - sizeof (*aam);
1213   ale = GNUNET_malloc (sizeof (struct AddressListEntry) + slen);
1214   ale->tc = tc;
1215   ale->address = (const char *) &ale[1];
1216   ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
1217   ale->aid = aam->aid;
1218   ale->nt = (enum GNUNET_ATS_Network_Type) ntohl (aam->nt);
1219   memcpy (&ale[1],
1220           &aam[1],
1221           slen);
1222   GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
1223                                tc->details.communicator.addr_tail,
1224                                ale);
1225   ale->st = GNUNET_SCHEDULER_add_now (&store_pi,
1226                                       ale);
1227   GNUNET_SERVICE_client_continue (tc->client);
1228 }
1229
1230
1231 /**
1232  * Address of our peer deleted.  Process the request.
1233  *
1234  * @param cls the client
1235  * @param dam the send message that was sent
1236  */
1237 static void
1238 handle_del_address (void *cls,
1239                     const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
1240 {
1241   struct TransportClient *tc = cls;
1242
1243   if (CT_COMMUNICATOR != tc->type)
1244   {
1245     GNUNET_break (0);
1246     GNUNET_SERVICE_client_drop (tc->client);
1247     return;
1248   }
1249   for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
1250        NULL != ale;
1251        ale = ale->next)
1252   {
1253     if (dam->aid != ale->aid)
1254       continue;
1255     GNUNET_assert (ale->tc == tc);
1256     free_address_list_entry (ale);
1257     GNUNET_SERVICE_client_continue (tc->client);
1258   }
1259   GNUNET_break (0);
1260   GNUNET_SERVICE_client_drop (tc->client);
1261 }
1262
1263
1264 /**
1265  * Client notified us about transmission from a peer.  Process the request.
1266  *
1267  * @param cls the client
1268  * @param obm the send message that was sent
1269  */
1270 static int
1271 check_incoming_msg (void *cls,
1272                     const struct GNUNET_TRANSPORT_IncomingMessage *im)
1273 {
1274   struct TransportClient *tc = cls;
1275   uint16_t size;
1276   const struct GNUNET_MessageHeader *obmm;
1277
1278   if (CT_COMMUNICATOR != tc->type)
1279   {
1280     GNUNET_break (0);
1281     return GNUNET_SYSERR;
1282   }
1283   size = ntohs (im->header.size) - sizeof (*im);
1284   if (size < sizeof (struct GNUNET_MessageHeader))
1285   {
1286     GNUNET_break (0);
1287     return GNUNET_SYSERR;
1288   }
1289   obmm = (const struct GNUNET_MessageHeader *) &im[1];
1290   if (size != ntohs (obmm->size))
1291   {
1292     GNUNET_break (0);
1293     return GNUNET_SYSERR;
1294   }
1295   return GNUNET_OK;
1296 }
1297
1298
1299 /**
1300  * Incoming meessage.  Process the request.
1301  *
1302  * @param cls the client
1303  * @param im the send message that was received
1304  */
1305 static void
1306 handle_incoming_msg (void *cls,
1307                      const struct GNUNET_TRANSPORT_IncomingMessage *im)
1308 {
1309   struct TransportClient *tc = cls;
1310
1311   GNUNET_SERVICE_client_continue (tc->client);
1312 }
1313
1314
1315 /**
1316  * New queue became available.  Check message.
1317  *
1318  * @param cls the client
1319  * @param aqm the send message that was sent
1320  */
1321 static int
1322 check_add_queue_message (void *cls,
1323                          const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1324 {
1325   struct TransportClient *tc = cls;
1326   const char *addr;
1327   uint16_t size;
1328
1329   if (CT_COMMUNICATOR != tc->type)
1330   {
1331     GNUNET_break (0);
1332     return GNUNET_SYSERR;
1333   }
1334   size = ntohs (aqm->header.size) - sizeof (*aqm);
1335   if (0 == size)
1336   {
1337     GNUNET_break (0);
1338     return GNUNET_SYSERR;
1339   }
1340   addr = (const char *) &aqm[1];
1341   if ('\0' != addr[size-1])
1342   {
1343     GNUNET_break (0);
1344     return GNUNET_SYSERR;
1345   }
1346   return GNUNET_OK;
1347 }
1348
1349
1350 /**
1351  * New queue became available.  Process the request.
1352  *
1353  * @param cls the client
1354  * @param aqm the send message that was sent
1355  */
1356 static void
1357 handle_add_queue_message (void *cls,
1358                           const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1359 {
1360   struct TransportClient *tc = cls;
1361   struct Queue *queue;
1362   struct Neighbour *neighbour;
1363   const char *addr;
1364   uint16_t addr_len;                 
1365
1366   neighbour = lookup_neighbour (&aqm->receiver);
1367   if (NULL == neighbour)
1368   {
1369     neighbour = GNUNET_new (struct Neighbour);
1370     neighbour->pid = aqm->receiver;
1371     GNUNET_assert (GNUNET_OK ==
1372                    GNUNET_CONTAINER_multipeermap_put (neighbours,
1373                                                       &neighbour->pid,
1374                                                       neighbour,
1375                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1376     cores_send_connect_info (&neighbour->pid,
1377                              GNUNET_BANDWIDTH_ZERO);
1378     // FIXME: notify ATS!
1379   }
1380   addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
1381   addr = (const char *) &aqm[1];
1382
1383   queue = GNUNET_malloc (sizeof (struct Queue) + addr_len);
1384   queue->mtu = ntohl (aqm->mtu);
1385   queue->qid = aqm->qid;
1386   queue->nt = (enum GNUNET_ATS_Network_Type) ntohl (aqm->nt);
1387   queue->tc = tc;
1388   queue->neighbour = neighbour;
1389   queue->address = (const char *) &queue[1];
1390   memcpy (&queue[1],
1391           addr,
1392           addr_len);
1393   /* notify monitors about new queue */
1394   {
1395     struct MonitorEvent me = {
1396       .cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs)
1397     };
1398     
1399     notify_monitors (&neighbour->pid,
1400                      queue->address,
1401                      queue->nt,
1402                      &me);
1403   }
1404   GNUNET_CONTAINER_MDLL_insert (neighbour,
1405                                 neighbour->queue_head,
1406                                 neighbour->queue_tail,
1407                                 queue);
1408   GNUNET_CONTAINER_MDLL_insert (client,
1409                                 tc->details.communicator.queue_head,
1410                                 tc->details.communicator.queue_tail,
1411                                 queue);
1412   // FIXME: possibly transmit queued messages?
1413   GNUNET_SERVICE_client_continue (tc->client);
1414 }
1415
1416
1417 /**
1418  * Queue to a peer went down.  Process the request.
1419  *
1420  * @param cls the client
1421  * @param dqm the send message that was sent
1422  */
1423 static void
1424 handle_del_queue_message (void *cls,
1425                           const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
1426 {
1427   struct TransportClient *tc = cls;
1428
1429   if (CT_COMMUNICATOR != tc->type)
1430   {
1431     GNUNET_break (0);
1432     GNUNET_SERVICE_client_drop (tc->client);
1433     return;
1434   }
1435   for (struct Queue *queue = tc->details.communicator.queue_head;
1436        NULL != queue;
1437        queue = queue->next_client)
1438   {
1439     struct Neighbour *neighbour = queue->neighbour;
1440
1441     if ( (dqm->qid != queue->qid) ||
1442          (0 != memcmp (&dqm->receiver,
1443                        &neighbour->pid,
1444                        sizeof (struct GNUNET_PeerIdentity))) )
1445       continue;
1446     free_queue (queue);
1447     GNUNET_SERVICE_client_continue (tc->client);
1448     return;
1449   }
1450   GNUNET_break (0);
1451   GNUNET_SERVICE_client_drop (tc->client);
1452 }
1453
1454
1455 /**
1456  * Message was transmitted.  Process the request.
1457  *
1458  * @param cls the client
1459  * @param sma the send message that was sent
1460  */
1461 static void
1462 handle_send_message_ack (void *cls,
1463                          const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
1464 {
1465   struct TransportClient *tc = cls;
1466
1467   if (CT_COMMUNICATOR != tc->type)
1468   {
1469     GNUNET_break (0);
1470     GNUNET_SERVICE_client_drop (tc->client);
1471     return;
1472   }
1473   GNUNET_SERVICE_client_continue (tc->client);
1474 }
1475
1476
1477 /**
1478  * Initialize a monitor client.
1479  *
1480  * @param cls the client
1481  * @param start the start message that was sent
1482  */
1483 static void
1484 handle_monitor_start (void *cls,
1485                       const struct GNUNET_TRANSPORT_MonitorStart *start)
1486 {
1487   struct TransportClient *tc = cls;
1488
1489   if (CT_NONE != tc->type)
1490   {
1491     GNUNET_break (0);
1492     GNUNET_SERVICE_client_drop (tc->client);
1493     return;
1494   }
1495   tc->type = CT_MONITOR;
1496   tc->details.monitor.peer = start->peer;
1497   tc->details.monitor.one_shot = ntohl (start->one_shot);
1498   // FIXME: do work!
1499
1500   GNUNET_SERVICE_client_mark_monitor (tc->client);
1501   GNUNET_SERVICE_client_continue (tc->client);
1502 }
1503
1504
1505 /**
1506  * Free neighbour entry.
1507  *
1508  * @param cls NULL
1509  * @param pid unused
1510  * @param value a `struct Neighbour`
1511  * @return #GNUNET_OK (always)
1512  */
1513 static int
1514 free_neighbour_cb (void *cls,
1515                    const struct GNUNET_PeerIdentity *pid,
1516                    void *value)
1517 {
1518   struct Neighbour *neighbour = value;
1519
1520   (void) cls;
1521   (void) pid;
1522   GNUNET_break (0); // should this ever happen?
1523   free_neighbour (neighbour);
1524
1525   return GNUNET_OK;
1526 }
1527
1528
1529 /**
1530  * Function called when the service shuts down.  Unloads our plugins
1531  * and cancels pending validations.
1532  *
1533  * @param cls closure, unused
1534  */
1535 static void
1536 do_shutdown (void *cls)
1537 {
1538   (void) cls;
1539
1540   GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1541                                          &free_neighbour_cb,
1542                                          NULL);
1543   if (NULL != peerstore)
1544   {
1545     GNUNET_PEERSTORE_disconnect (peerstore,
1546                                  GNUNET_NO);
1547     peerstore = NULL;
1548   }
1549   if (NULL != GST_stats)
1550   {
1551     GNUNET_STATISTICS_destroy (GST_stats,
1552                                GNUNET_NO);
1553     GST_stats = NULL;
1554   }  
1555   if (NULL != GST_my_private_key)
1556   {
1557     GNUNET_free (GST_my_private_key);
1558     GST_my_private_key = NULL;
1559   }
1560   GNUNET_CONTAINER_multipeermap_destroy (neighbours);
1561 }
1562
1563
1564 /**
1565  * Initiate transport service.
1566  *
1567  * @param cls closure
1568  * @param c configuration to use
1569  * @param service the initialized service
1570  */
1571 static void
1572 run (void *cls,
1573      const struct GNUNET_CONFIGURATION_Handle *c,
1574      struct GNUNET_SERVICE_Handle *service)
1575 {
1576   (void) cls;
1577   /* setup globals */
1578   GST_cfg = c;
1579   neighbours = GNUNET_CONTAINER_multipeermap_create (1024,
1580                                                      GNUNET_YES);
1581   GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
1582   if (NULL == GST_my_private_key)
1583   {
1584     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1585                 _("Transport service is lacking key configuration settings. Exiting.\n"));
1586     GNUNET_SCHEDULER_shutdown ();
1587     return;
1588   }
1589   GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
1590                                       &GST_my_identity.public_key);
1591   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1592              "My identity is `%s'\n",
1593              GNUNET_i2s_full (&GST_my_identity));
1594
1595   GST_stats = GNUNET_STATISTICS_create ("transport",
1596                                         GST_cfg);
1597   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1598                                  NULL);
1599   peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
1600   if (NULL == peerstore)
1601     {
1602       GNUNET_break (0);
1603       GNUNET_SCHEDULER_shutdown ();
1604       return;
1605     }
1606   /* start subsystems */
1607 }
1608
1609
1610 /**
1611  * Define "main" method using service macro.
1612  */
1613 GNUNET_SERVICE_MAIN
1614 ("transport",
1615  GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
1616  &run,
1617  &client_connect_cb,
1618  &client_disconnect_cb,
1619  NULL,
1620  /* communication with core */
1621  GNUNET_MQ_hd_fixed_size (client_start,
1622                           GNUNET_MESSAGE_TYPE_TRANSPORT_START,
1623                           struct StartMessage,
1624                           NULL),
1625  GNUNET_MQ_hd_var_size (client_send,
1626                         GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
1627                         struct OutboundMessage,
1628                         NULL),
1629  /* communication with communicators */
1630  GNUNET_MQ_hd_var_size (communicator_available,
1631                         GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
1632                         struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
1633                         NULL),
1634  GNUNET_MQ_hd_var_size (add_address,
1635                         GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
1636                         struct GNUNET_TRANSPORT_AddAddressMessage,
1637                         NULL),
1638  GNUNET_MQ_hd_fixed_size (del_address,
1639                           GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
1640                           struct GNUNET_TRANSPORT_DelAddressMessage,
1641                           NULL),
1642  GNUNET_MQ_hd_var_size (incoming_msg,
1643                         GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
1644                         struct GNUNET_TRANSPORT_IncomingMessage,
1645                         NULL),
1646  GNUNET_MQ_hd_var_size (add_queue_message,
1647                         GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
1648                         struct GNUNET_TRANSPORT_AddQueueMessage,
1649                         NULL),
1650  GNUNET_MQ_hd_fixed_size (del_queue_message,
1651                           GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
1652                           struct GNUNET_TRANSPORT_DelQueueMessage,
1653                           NULL),
1654  GNUNET_MQ_hd_fixed_size (send_message_ack,
1655                           GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
1656                           struct GNUNET_TRANSPORT_SendMessageToAck,
1657                           NULL),
1658  /* communication with monitors */
1659  GNUNET_MQ_hd_fixed_size (monitor_start,
1660                           GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
1661                           struct GNUNET_TRANSPORT_MonitorStart,
1662                           NULL),
1663  GNUNET_MQ_handler_end ());
1664
1665
1666 /* end of file gnunet-service-transport.c */