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