finish (?) libgnunetatstransport for now
[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   uint16_t size;
1082
1083   if (CT_NONE != tc->type)
1084   {
1085     GNUNET_break (0);
1086     return GNUNET_SYSERR;
1087   }
1088   tc->type = CT_COMMUNICATOR;
1089   size = ntohs (cam->header.size) - sizeof (*cam);
1090   if (0 == size)
1091     return GNUNET_OK; /* receive-only communicator */
1092   GNUNET_MQ_check_zero_termination (cam);
1093   return GNUNET_OK;
1094 }
1095
1096
1097 /**
1098  * Communicator started.  Process the request.
1099  *
1100  * @param cls the client
1101  * @param cam the send message that was sent
1102  */
1103 static void
1104 handle_communicator_available (void *cls,
1105                                const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
1106 {
1107   struct TransportClient *tc = cls;
1108   uint16_t size;
1109
1110   size = ntohs (cam->header.size) - sizeof (*cam);
1111   if (0 == size)
1112     return; /* receive-only communicator */
1113   tc->details.communicator.address_prefix
1114     = GNUNET_strdup ((const char *) &cam[1]);
1115   tc->details.communicator.cc
1116     = (enum GNUNET_TRANSPORT_CommunicatorCharacteristics) ntohl (cam->cc);
1117   GNUNET_SERVICE_client_continue (tc->client);
1118 }
1119
1120
1121 /**
1122  * Address of our peer added.  Test message is well-formed.
1123  *
1124  * @param cls the client
1125  * @param aam the send message that was sent
1126  */
1127 static int
1128 check_add_address (void *cls,
1129                    const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1130 {
1131   struct TransportClient *tc = cls;
1132
1133   if (CT_COMMUNICATOR != tc->type)
1134   {
1135     GNUNET_break (0);
1136     return GNUNET_SYSERR;
1137   }
1138   GNUNET_MQ_check_zero_termination (aam);
1139   return GNUNET_OK;
1140 }
1141
1142
1143 /**
1144  * Ask peerstore to store our address.
1145  *
1146  * @param cls an `struct AddressListEntry *`
1147  */
1148 static void
1149 store_pi (void *cls);
1150
1151
1152 /**
1153  * Function called when peerstore is done storing our address.
1154  */
1155 static void
1156 peerstore_store_cb (void *cls,
1157                     int success)
1158 {
1159   struct AddressListEntry *ale = cls;
1160
1161   ale->sc = NULL;
1162   if (GNUNET_YES != success)
1163     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1164                 "Failed to store our own address `%s' in peerstore!\n",
1165                 ale->address);
1166   /* refresh period is 1/4 of expiration time, that should be plenty
1167      without being excessive. */
1168   ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (ale->expiration,
1169                                                                        4ULL),
1170                                           &store_pi,
1171                                           ale);
1172 }
1173
1174
1175 /**
1176  * Ask peerstore to store our address.
1177  *
1178  * @param cls an `struct AddressListEntry *`
1179  */
1180 static void
1181 store_pi (void *cls)
1182 {
1183   struct AddressListEntry *ale = cls;
1184   void *addr;
1185   size_t addr_len;
1186   struct GNUNET_TIME_Absolute expiration;
1187
1188   ale->st = NULL;
1189   expiration = GNUNET_TIME_relative_to_absolute (ale->expiration);
1190   GNUNET_HELLO_sign_address (ale->address,
1191                              ale->nt,
1192                              expiration,
1193                              GST_my_private_key,
1194                              &addr,
1195                              &addr_len);
1196   ale->sc = GNUNET_PEERSTORE_store (peerstore,
1197                                     "transport",
1198                                     &GST_my_identity,
1199                                     "hello",
1200                                     addr,
1201                                     addr_len,
1202                                     expiration,
1203                                     GNUNET_PEERSTORE_STOREOPTION_MULTIPLE,
1204                                     &peerstore_store_cb,
1205                                     ale);
1206   GNUNET_free (addr);
1207   if (NULL == ale->sc)
1208   {
1209     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1210                 "Failed to store our address `%s' with peerstore\n",
1211                 ale->address);
1212     ale->st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
1213                                             &store_pi,
1214                                             ale);
1215   }
1216 }
1217
1218
1219 /**
1220  * Address of our peer added.  Process the request.
1221  *
1222  * @param cls the client
1223  * @param aam the send message that was sent
1224  */
1225 static void
1226 handle_add_address (void *cls,
1227                     const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
1228 {
1229   struct TransportClient *tc = cls;
1230   struct AddressListEntry *ale;
1231   size_t slen;
1232
1233   slen = ntohs (aam->header.size) - sizeof (*aam);
1234   ale = GNUNET_malloc (sizeof (struct AddressListEntry) + slen);
1235   ale->tc = tc;
1236   ale->address = (const char *) &ale[1];
1237   ale->expiration = GNUNET_TIME_relative_ntoh (aam->expiration);
1238   ale->aid = aam->aid;
1239   ale->nt = (enum GNUNET_NetworkType) ntohl (aam->nt);
1240   memcpy (&ale[1],
1241           &aam[1],
1242           slen);
1243   GNUNET_CONTAINER_DLL_insert (tc->details.communicator.addr_head,
1244                                tc->details.communicator.addr_tail,
1245                                ale);
1246   ale->st = GNUNET_SCHEDULER_add_now (&store_pi,
1247                                       ale);
1248   GNUNET_SERVICE_client_continue (tc->client);
1249 }
1250
1251
1252 /**
1253  * Address of our peer deleted.  Process the request.
1254  *
1255  * @param cls the client
1256  * @param dam the send message that was sent
1257  */
1258 static void
1259 handle_del_address (void *cls,
1260                     const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
1261 {
1262   struct TransportClient *tc = cls;
1263
1264   if (CT_COMMUNICATOR != tc->type)
1265   {
1266     GNUNET_break (0);
1267     GNUNET_SERVICE_client_drop (tc->client);
1268     return;
1269   }
1270   for (struct AddressListEntry *ale = tc->details.communicator.addr_head;
1271        NULL != ale;
1272        ale = ale->next)
1273   {
1274     if (dam->aid != ale->aid)
1275       continue;
1276     GNUNET_assert (ale->tc == tc);
1277     free_address_list_entry (ale);
1278     GNUNET_SERVICE_client_continue (tc->client);
1279   }
1280   GNUNET_break (0);
1281   GNUNET_SERVICE_client_drop (tc->client);
1282 }
1283
1284
1285 /**
1286  * Client notified us about transmission from a peer.  Process the request.
1287  *
1288  * @param cls the client
1289  * @param obm the send message that was sent
1290  */
1291 static int
1292 check_incoming_msg (void *cls,
1293                     const struct GNUNET_TRANSPORT_IncomingMessage *im)
1294 {
1295   struct TransportClient *tc = cls;
1296   uint16_t size;
1297   const struct GNUNET_MessageHeader *obmm;
1298
1299   if (CT_COMMUNICATOR != tc->type)
1300   {
1301     GNUNET_break (0);
1302     return GNUNET_SYSERR;
1303   }
1304   size = ntohs (im->header.size) - sizeof (*im);
1305   if (size < sizeof (struct GNUNET_MessageHeader))
1306   {
1307     GNUNET_break (0);
1308     return GNUNET_SYSERR;
1309   }
1310   obmm = (const struct GNUNET_MessageHeader *) &im[1];
1311   if (size != ntohs (obmm->size))
1312   {
1313     GNUNET_break (0);
1314     return GNUNET_SYSERR;
1315   }
1316   return GNUNET_OK;
1317 }
1318
1319
1320 /**
1321  * Incoming meessage.  Process the request.
1322  *
1323  * @param cls the client
1324  * @param im the send message that was received
1325  */
1326 static void
1327 handle_incoming_msg (void *cls,
1328                      const struct GNUNET_TRANSPORT_IncomingMessage *im)
1329 {
1330   struct TransportClient *tc = cls;
1331
1332   GNUNET_SERVICE_client_continue (tc->client);
1333 }
1334
1335
1336 /**
1337  * New queue became available.  Check message.
1338  *
1339  * @param cls the client
1340  * @param aqm the send message that was sent
1341  */
1342 static int
1343 check_add_queue_message (void *cls,
1344                          const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1345 {
1346   struct TransportClient *tc = cls;
1347
1348   if (CT_COMMUNICATOR != tc->type)
1349   {
1350     GNUNET_break (0);
1351     return GNUNET_SYSERR;
1352   }
1353   GNUNET_MQ_check_zero_termination (aqm);
1354   return GNUNET_OK;
1355 }
1356
1357
1358 /**
1359  * New queue became available.  Process the request.
1360  *
1361  * @param cls the client
1362  * @param aqm the send message that was sent
1363  */
1364 static void
1365 handle_add_queue_message (void *cls,
1366                           const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
1367 {
1368   struct TransportClient *tc = cls;
1369   struct Queue *queue;
1370   struct Neighbour *neighbour;
1371   const char *addr;
1372   uint16_t addr_len;
1373
1374   neighbour = lookup_neighbour (&aqm->receiver);
1375   if (NULL == neighbour)
1376   {
1377     neighbour = GNUNET_new (struct Neighbour);
1378     neighbour->pid = aqm->receiver;
1379     GNUNET_assert (GNUNET_OK ==
1380                    GNUNET_CONTAINER_multipeermap_put (neighbours,
1381                                                       &neighbour->pid,
1382                                                       neighbour,
1383                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1384     cores_send_connect_info (&neighbour->pid,
1385                              GNUNET_BANDWIDTH_ZERO);
1386     // FIXME: notify ATS!
1387   }
1388   addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
1389   addr = (const char *) &aqm[1];
1390
1391   queue = GNUNET_malloc (sizeof (struct Queue) + addr_len);
1392   queue->tc = tc;
1393   queue->address = (const char *) &queue[1];
1394   queue->rtt = GNUNET_TIME_UNIT_FOREVER_REL;
1395   queue->qid = aqm->qid;
1396   queue->mtu = ntohl (aqm->mtu);
1397   queue->distance = ntohl (aqm->distance);
1398   queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
1399   queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
1400   queue->neighbour = neighbour;
1401   memcpy (&queue[1],
1402           addr,
1403           addr_len);
1404   /* notify monitors about new queue */
1405   {
1406     struct MonitorEvent me = {
1407       .rtt = queue->rtt,
1408       .cs = queue->cs
1409     };
1410
1411     notify_monitors (&neighbour->pid,
1412                      queue->address,
1413                      queue->nt,
1414                      &me);
1415   }
1416   GNUNET_CONTAINER_MDLL_insert (neighbour,
1417                                 neighbour->queue_head,
1418                                 neighbour->queue_tail,
1419                                 queue);
1420   GNUNET_CONTAINER_MDLL_insert (client,
1421                                 tc->details.communicator.queue_head,
1422                                 tc->details.communicator.queue_tail,
1423                                 queue);
1424   // FIXME: possibly transmit queued messages?
1425   GNUNET_SERVICE_client_continue (tc->client);
1426 }
1427
1428
1429 /**
1430  * Queue to a peer went down.  Process the request.
1431  *
1432  * @param cls the client
1433  * @param dqm the send message that was sent
1434  */
1435 static void
1436 handle_del_queue_message (void *cls,
1437                           const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
1438 {
1439   struct TransportClient *tc = cls;
1440
1441   if (CT_COMMUNICATOR != tc->type)
1442   {
1443     GNUNET_break (0);
1444     GNUNET_SERVICE_client_drop (tc->client);
1445     return;
1446   }
1447   for (struct Queue *queue = tc->details.communicator.queue_head;
1448        NULL != queue;
1449        queue = queue->next_client)
1450   {
1451     struct Neighbour *neighbour = queue->neighbour;
1452
1453     if ( (dqm->qid != queue->qid) ||
1454          (0 != memcmp (&dqm->receiver,
1455                        &neighbour->pid,
1456                        sizeof (struct GNUNET_PeerIdentity))) )
1457       continue;
1458     free_queue (queue);
1459     GNUNET_SERVICE_client_continue (tc->client);
1460     return;
1461   }
1462   GNUNET_break (0);
1463   GNUNET_SERVICE_client_drop (tc->client);
1464 }
1465
1466
1467 /**
1468  * Message was transmitted.  Process the request.
1469  *
1470  * @param cls the client
1471  * @param sma the send message that was sent
1472  */
1473 static void
1474 handle_send_message_ack (void *cls,
1475                          const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
1476 {
1477   struct TransportClient *tc = cls;
1478
1479   if (CT_COMMUNICATOR != tc->type)
1480   {
1481     GNUNET_break (0);
1482     GNUNET_SERVICE_client_drop (tc->client);
1483     return;
1484   }
1485   GNUNET_SERVICE_client_continue (tc->client);
1486 }
1487
1488
1489 /**
1490  * Iterator telling new MONITOR client about all existing
1491  * queues to peers.
1492  *
1493  * @param cls the new `struct TransportClient`
1494  * @param pid a connected peer
1495  * @param value the `struct Neighbour` with more information
1496  * @return #GNUNET_OK (continue to iterate)
1497  */
1498 static int
1499 notify_client_queues (void *cls,
1500                       const struct GNUNET_PeerIdentity *pid,
1501                       void *value)
1502 {
1503   struct TransportClient *tc = cls;
1504   struct Neighbour *neighbour = value;
1505
1506   GNUNET_assert (CT_MONITOR == tc->type);
1507   for (struct Queue *q = neighbour->queue_head;
1508        NULL != q;
1509        q = q->next_neighbour)
1510   {
1511     struct MonitorEvent me = {
1512       .rtt = q->rtt,
1513       .cs = q->cs,
1514       .num_msg_pending = q->num_msg_pending,
1515       .num_bytes_pending = q->num_bytes_pending
1516     };
1517
1518     notify_monitor (tc,
1519                     pid,
1520                     q->address,
1521                     q->nt,
1522                     &me);
1523   }
1524   return GNUNET_OK;
1525 }
1526
1527
1528 /**
1529  * Initialize a monitor client.
1530  *
1531  * @param cls the client
1532  * @param start the start message that was sent
1533  */
1534 static void
1535 handle_monitor_start (void *cls,
1536                       const struct GNUNET_TRANSPORT_MonitorStart *start)
1537 {
1538   struct TransportClient *tc = cls;
1539
1540   if (CT_NONE != tc->type)
1541   {
1542     GNUNET_break (0);
1543     GNUNET_SERVICE_client_drop (tc->client);
1544     return;
1545   }
1546   tc->type = CT_MONITOR;
1547   tc->details.monitor.peer = start->peer;
1548   tc->details.monitor.one_shot = ntohl (start->one_shot);
1549   GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1550                                          &notify_client_queues,
1551                                          tc);
1552   GNUNET_SERVICE_client_mark_monitor (tc->client);
1553   GNUNET_SERVICE_client_continue (tc->client);
1554 }
1555
1556
1557 /**
1558  * Free neighbour entry.
1559  *
1560  * @param cls NULL
1561  * @param pid unused
1562  * @param value a `struct Neighbour`
1563  * @return #GNUNET_OK (always)
1564  */
1565 static int
1566 free_neighbour_cb (void *cls,
1567                    const struct GNUNET_PeerIdentity *pid,
1568                    void *value)
1569 {
1570   struct Neighbour *neighbour = value;
1571
1572   (void) cls;
1573   (void) pid;
1574   GNUNET_break (0); // should this ever happen?
1575   free_neighbour (neighbour);
1576
1577   return GNUNET_OK;
1578 }
1579
1580
1581 /**
1582  * Function called when the service shuts down.  Unloads our plugins
1583  * and cancels pending validations.
1584  *
1585  * @param cls closure, unused
1586  */
1587 static void
1588 do_shutdown (void *cls)
1589 {
1590   (void) cls;
1591
1592   GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1593                                          &free_neighbour_cb,
1594                                          NULL);
1595   if (NULL != peerstore)
1596   {
1597     GNUNET_PEERSTORE_disconnect (peerstore,
1598                                  GNUNET_NO);
1599     peerstore = NULL;
1600   }
1601   if (NULL != GST_stats)
1602   {
1603     GNUNET_STATISTICS_destroy (GST_stats,
1604                                GNUNET_NO);
1605     GST_stats = NULL;
1606   }
1607   if (NULL != GST_my_private_key)
1608   {
1609     GNUNET_free (GST_my_private_key);
1610     GST_my_private_key = NULL;
1611   }
1612   GNUNET_CONTAINER_multipeermap_destroy (neighbours);
1613 }
1614
1615
1616 /**
1617  * Initiate transport service.
1618  *
1619  * @param cls closure
1620  * @param c configuration to use
1621  * @param service the initialized service
1622  */
1623 static void
1624 run (void *cls,
1625      const struct GNUNET_CONFIGURATION_Handle *c,
1626      struct GNUNET_SERVICE_Handle *service)
1627 {
1628   (void) cls;
1629   /* setup globals */
1630   GST_cfg = c;
1631   neighbours = GNUNET_CONTAINER_multipeermap_create (1024,
1632                                                      GNUNET_YES);
1633   GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
1634   if (NULL == GST_my_private_key)
1635   {
1636     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1637                 _("Transport service is lacking key configuration settings. Exiting.\n"));
1638     GNUNET_SCHEDULER_shutdown ();
1639     return;
1640   }
1641   GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
1642                                       &GST_my_identity.public_key);
1643   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1644              "My identity is `%s'\n",
1645              GNUNET_i2s_full (&GST_my_identity));
1646
1647   GST_stats = GNUNET_STATISTICS_create ("transport",
1648                                         GST_cfg);
1649   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1650                                  NULL);
1651   peerstore = GNUNET_PEERSTORE_connect (GST_cfg);
1652   if (NULL == peerstore)
1653     {
1654       GNUNET_break (0);
1655       GNUNET_SCHEDULER_shutdown ();
1656       return;
1657     }
1658   /* start subsystems */
1659 }
1660
1661
1662 /**
1663  * Define "main" method using service macro.
1664  */
1665 GNUNET_SERVICE_MAIN
1666 ("transport",
1667  GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN,
1668  &run,
1669  &client_connect_cb,
1670  &client_disconnect_cb,
1671  NULL,
1672  /* communication with core */
1673  GNUNET_MQ_hd_fixed_size (client_start,
1674                           GNUNET_MESSAGE_TYPE_TRANSPORT_START,
1675                           struct StartMessage,
1676                           NULL),
1677  GNUNET_MQ_hd_var_size (client_send,
1678                         GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
1679                         struct OutboundMessage,
1680                         NULL),
1681  /* communication with communicators */
1682  GNUNET_MQ_hd_var_size (communicator_available,
1683                         GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
1684                         struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
1685                         NULL),
1686  GNUNET_MQ_hd_var_size (add_address,
1687                         GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
1688                         struct GNUNET_TRANSPORT_AddAddressMessage,
1689                         NULL),
1690  GNUNET_MQ_hd_fixed_size (del_address,
1691                           GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
1692                           struct GNUNET_TRANSPORT_DelAddressMessage,
1693                           NULL),
1694  GNUNET_MQ_hd_var_size (incoming_msg,
1695                         GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
1696                         struct GNUNET_TRANSPORT_IncomingMessage,
1697                         NULL),
1698  GNUNET_MQ_hd_var_size (add_queue_message,
1699                         GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
1700                         struct GNUNET_TRANSPORT_AddQueueMessage,
1701                         NULL),
1702  GNUNET_MQ_hd_fixed_size (del_queue_message,
1703                           GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
1704                           struct GNUNET_TRANSPORT_DelQueueMessage,
1705                           NULL),
1706  GNUNET_MQ_hd_fixed_size (send_message_ack,
1707                           GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
1708                           struct GNUNET_TRANSPORT_SendMessageToAck,
1709                           NULL),
1710  /* communication with monitors */
1711  GNUNET_MQ_hd_fixed_size (monitor_start,
1712                           GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
1713                           struct GNUNET_TRANSPORT_MonitorStart,
1714                           NULL),
1715  GNUNET_MQ_handler_end ());
1716
1717
1718 /* end of file gnunet-service-transport.c */