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