2 This file is part of GNUnet.
3 Copyright (C) 2010-2016, 2018 GNUnet e.V.
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.
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.
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/>.
19 * @file transport/gnunet-service-transport.c
20 * @brief main for gnunet-service-transport
21 * @author Christian Grothoff
24 #include "gnunet_util_lib.h"
25 #include "gnunet_statistics_service.h"
26 #include "gnunet_transport_service.h"
27 #include "gnunet_peerinfo_service.h"
28 #include "gnunet_ats_service.h"
29 #include "gnunet-service-transport.h"
30 #include "transport.h"
34 * How many messages can we have pending for a given client process
35 * before we start to drop incoming messages? We typically should
36 * have only one client and so this would be the primary buffer for
37 * messages, so the number should be chosen rather generously.
39 * The expectation here is that most of the time the queue is large
40 * enough so that a drop is virtually never required. Note that
41 * this value must be about as large as 'TOTAL_MSGS' in the
42 * 'test_transport_api_reliability.c', otherwise that testcase may
45 #define MAX_PENDING (128 * 1024)
49 * What type of client is the `struct TransportClient` about?
54 * We do not know yet (client is fresh).
59 * Is the CORE service, we need to forward traffic to it.
64 * It is a monitor, forward monitor data.
69 * It is a communicator, use for communication.
76 * Client connected to the transport service.
78 struct TransportClient;
82 * A neighbour that at least one communicator is connected to.
88 * List of available queues for a particular neighbour.
95 struct Queue *next_neighbour;
100 struct Queue *prev_neighbour;
105 struct Queue *prev_client;
110 struct Queue *next_client;
113 * Which neighbour is this queue for?
115 struct Neighbour *neighbour;
118 * Which communicator offers this queue?
120 struct TransportClient *tc;
123 * Unique identifier of this queue with the communicator.
128 * Network type offered by this queue.
130 enum GNUNET_ATS_Network_Type nt;
133 * Address served by the queue.
140 * A neighbour that at least one communicator is connected to.
146 * Which peer is this about?
148 struct GNUNET_PeerIdentity pid;
151 * Head of list of messages pending for this neighbour.
153 struct PendingMessage *pending_msg_head;
156 * Tail of list of messages pending for this neighbour.
158 struct PendingMessage *pending_msg_tail;
161 * Head of DLL of queues to this peer.
163 struct Queue *queue_head;
166 * Tail of DLL of queues to this peer.
168 struct Queue *queue_tail;
174 * Transmission request from CORE that is awaiting delivery.
176 struct PendingMessage
179 * Kept in a MDLL of messages for this @a target.
181 struct PendingMessage *next_neighbour;
184 * Kept in a MDLL of messages for this @a target.
186 struct PendingMessage *prev_neighbour;
189 * Kept in a MDLL of messages from this @a client.
191 struct PendingMessage *next_client;
194 * Kept in a MDLL of messages from this @a client.
196 struct PendingMessage *prev_client;
199 * Target of the request.
201 struct Neighbour *target;
204 * Client that issued the transmission request.
206 struct TransportClient *client;
209 * Size of the original message.
217 * Client connected to the transport service.
219 struct TransportClient
225 struct TransportClient *next;
230 struct TransportClient *prev;
233 * Handle to the client.
235 struct GNUNET_SERVICE_Client *client;
238 * Message queue to the client.
240 struct GNUNET_MQ_Handle *mq;
243 * What type of client is this?
245 enum ClientType type;
251 * Information for @e type #CT_CORE.
256 * Head of list of messages pending for this client.
258 struct PendingMessage *pending_msg_head;
261 * Tail of list of messages pending for this client.
263 struct PendingMessage *pending_msg_tail;
268 * Information for @e type #CT_MONITOR.
273 * Peer identity to monitor the addresses of.
274 * Zero to monitor all neighbours. Valid if
275 * @e type is #CT_MONITOR.
277 struct GNUNET_PeerIdentity peer;
280 * Is this a one-shot monitor?
288 * Information for @e type #CT_COMMUNICATOR.
292 * If @e type is #CT_COMMUNICATOR, this communicator
293 * supports communicating using these addresses.
295 char *address_prefix;
298 * Head of DLL of queues offered by this communicator.
300 struct Queue *queue_head;
303 * Tail of DLL of queues offered by this communicator.
305 struct Queue *queue_tail;
315 * Head of linked list of all clients to this service.
317 static struct TransportClient *clients_head;
320 * Tail of linked list of all clients to this service.
322 static struct TransportClient *clients_tail;
327 struct GNUNET_STATISTICS_Handle *GST_stats;
330 * Configuration handle.
332 const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
337 struct GNUNET_PeerIdentity GST_my_identity;
342 struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
345 * Map from PIDs to `struct Neighbour` entries. A peer is
346 * a neighbour if we have an MQ to it from some communicator.
348 static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
352 * Lookup neighbour record for peer @a pid.
354 * @param pid neighbour to look for
355 * @return NULL if we do not have this peer as a neighbour
357 static struct Neighbour *
358 lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
360 return GNUNET_CONTAINER_multipeermap_get (neighbours,
366 * Called whenever a client connects. Allocates our
367 * data structures associated with that client.
369 * @param cls closure, NULL
370 * @param client identification of the client
371 * @param mq message queue for the client
372 * @return our `struct TransportClient`
375 client_connect_cb (void *cls,
376 struct GNUNET_SERVICE_Client *client,
377 struct GNUNET_MQ_Handle *mq)
379 struct TransportClient *tc;
381 tc = GNUNET_new (struct TransportClient);
384 GNUNET_CONTAINER_DLL_insert (clients_head,
387 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
388 "Client %p connected\n",
395 * Called whenever a client is disconnected. Frees our
396 * resources associated with that client.
398 * @param cls closure, NULL
399 * @param client identification of the client
400 * @param app_ctx our `struct TransportClient`
403 client_disconnect_cb (void *cls,
404 struct GNUNET_SERVICE_Client *client,
407 struct TransportClient *tc = app_ctx;
409 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
410 "Client %p disconnected, cleaning up.\n",
412 GNUNET_CONTAINER_DLL_remove (clients_head,
421 struct PendingMessage *pm;
423 while (NULL != (pm = tc->details.core.pending_msg_head))
425 GNUNET_CONTAINER_MDLL_remove (client,
426 tc->details.core.pending_msg_head,
427 tc->details.core.pending_msg_tail,
435 case CT_COMMUNICATOR:
436 GNUNET_free (tc->details.communicator.address_prefix);
444 * Initialize a "CORE" client. We got a start message from this
445 * client, so add it to the list of clients for broadcasting of
448 * @param cls the client
449 * @param start the start message that was sent
452 handle_client_start (void *cls,
453 const struct StartMessage *start)
455 struct TransportClient *tc = cls;
458 options = ntohl (start->options);
459 if ( (0 != (1 & options)) &&
461 memcmp (&start->self,
463 sizeof (struct GNUNET_PeerIdentity)) ) )
465 /* client thinks this is a different peer, reject */
467 GNUNET_SERVICE_client_drop (tc->client);
470 if (CT_NONE != tc->type)
473 GNUNET_SERVICE_client_drop (tc->client);
477 GNUNET_SERVICE_client_continue (tc->client);
482 * Client asked for transmission to a peer. Process the request.
484 * @param cls the client
485 * @param obm the send message that was sent
488 check_client_send (void *cls,
489 const struct OutboundMessage *obm)
491 struct TransportClient *tc = cls;
493 const struct GNUNET_MessageHeader *obmm;
495 if (CT_CORE != tc->type)
498 return GNUNET_SYSERR;
500 size = ntohs (obm->header.size) - sizeof (struct OutboundMessage);
501 if (size < sizeof (struct GNUNET_MessageHeader))
504 return GNUNET_SYSERR;
506 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
507 if (size != ntohs (obmm->size))
510 return GNUNET_SYSERR;
517 * Send a response to the @a pm that we have processed a
518 * "send" request with status @a success. We
519 * transmitted @a bytes_physical on the actual wire.
520 * Sends a confirmation to the "core" client responsible
521 * for the original request and free's @a pm.
523 * @param pm handle to the original pending message
524 * @param success status code, #GNUNET_OK on success, #GNUNET_SYSERR
525 * for transmission failure
526 * @param bytes_physical amount of bandwidth consumed
529 client_send_response (struct PendingMessage *pm,
531 uint32_t bytes_physical)
533 struct TransportClient *tc = pm->client;
534 struct Neighbour *target = pm->target;
535 struct GNUNET_MQ_Envelope *env;
536 struct SendOkMessage *som;
540 env = GNUNET_MQ_msg (som,
541 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
542 som->success = htonl ((uint32_t) success);
543 som->bytes_msg = htonl (pm->bytes_msg);
544 som->bytes_physical = htonl (bytes_physical);
545 som->peer = target->pid;
546 GNUNET_MQ_send (tc->mq,
548 GNUNET_CONTAINER_MDLL_remove (client,
549 tc->details.core.pending_msg_head,
550 tc->details.core.pending_msg_tail,
553 GNUNET_CONTAINER_MDLL_remove (neighbour,
554 target->pending_msg_head,
555 target->pending_msg_tail,
562 * Client asked for transmission to a peer. Process the request.
564 * @param cls the client
565 * @param obm the send message that was sent
568 handle_client_send (void *cls,
569 const struct OutboundMessage *obm)
571 struct TransportClient *tc = cls;
572 struct PendingMessage *pm;
573 const struct GNUNET_MessageHeader *obmm;
574 struct Neighbour *target;
577 GNUNET_assert (CT_CORE == tc->type);
578 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
579 bytes_msg = ntohs (obmm->size);
580 target = lookup_neighbour (&obm->peer);
583 /* Failure: don't have this peer as a neighbour (anymore).
584 Might have gone down asynchronously, so this is NOT
585 a protocol violation by CORE. Still count the event,
586 as this should be rare. */
587 struct GNUNET_MQ_Envelope *env;
588 struct SendOkMessage *som;
590 env = GNUNET_MQ_msg (som,
591 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
592 som->success = htonl (GNUNET_SYSERR);
593 som->bytes_msg = htonl (bytes_msg);
594 som->bytes_physical = htonl (0);
595 som->peer = obm->peer;
596 GNUNET_MQ_send (tc->mq,
598 GNUNET_SERVICE_client_continue (tc->client);
599 GNUNET_STATISTICS_update (GST_stats,
600 "# messages dropped (neighbour unknown)",
605 pm = GNUNET_new (struct PendingMessage);
608 pm->bytes_msg = bytes_msg;
609 GNUNET_CONTAINER_MDLL_insert (neighbour,
610 target->pending_msg_head,
611 target->pending_msg_tail,
613 GNUNET_CONTAINER_MDLL_insert (client,
614 tc->details.core.pending_msg_head,
615 tc->details.core.pending_msg_tail,
617 // FIXME: do the work, continuation with:
618 client_send_response (pm,
625 * Communicator started. Test message is well-formed.
627 * @param cls the client
628 * @param cam the send message that was sent
631 check_communicator_available (void *cls,
632 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
634 struct TransportClient *tc = cls;
638 if (CT_NONE != tc->type)
641 return GNUNET_SYSERR;
643 tc->type = CT_COMMUNICATOR;
644 size = ntohs (cam->header.size) - sizeof (*cam);
646 return GNUNET_OK; /* receive-only communicator */
647 addr = (const char *) &cam[1];
648 if ('\0' != addr[size-1])
651 return GNUNET_SYSERR;
658 * Communicator started. Process the request.
660 * @param cls the client
661 * @param cam the send message that was sent
664 handle_communicator_available (void *cls,
665 const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
667 struct TransportClient *tc = cls;
670 size = ntohs (cam->header.size) - sizeof (*cam);
672 return; /* receive-only communicator */
673 tc->details.communicator.address_prefix = GNUNET_strdup ((const char *) &cam[1]);
674 GNUNET_SERVICE_client_continue (tc->client);
679 * Address of our peer added. Test message is well-formed.
681 * @param cls the client
682 * @param aam the send message that was sent
685 check_add_address (void *cls,
686 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
688 struct TransportClient *tc = cls;
692 if (CT_COMMUNICATOR != tc->type)
695 return GNUNET_SYSERR;
697 size = ntohs (aam->header.size) - sizeof (*aam);
701 return GNUNET_SYSERR;
703 addr = (const char *) &aam[1];
704 if ('\0' != addr[size-1])
707 return GNUNET_SYSERR;
714 * Address of our peer added. Process the request.
716 * @param cls the client
717 * @param aam the send message that was sent
720 handle_add_address (void *cls,
721 const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
723 struct TransportClient *tc = cls;
725 GNUNET_SERVICE_client_continue (tc->client);
730 * Address of our peer deleted. Process the request.
732 * @param cls the client
733 * @param dam the send message that was sent
736 handle_del_address (void *cls,
737 const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
739 struct TransportClient *tc = cls;
741 if (CT_COMMUNICATOR != tc->type)
744 GNUNET_SERVICE_client_drop (tc->client);
748 GNUNET_SERVICE_client_continue (tc->client);
753 * Client notified us about transmission from a peer. Process the request.
755 * @param cls the client
756 * @param obm the send message that was sent
759 check_incoming_msg (void *cls,
760 const struct GNUNET_TRANSPORT_IncomingMessage *im)
762 struct TransportClient *tc = cls;
764 const struct GNUNET_MessageHeader *obmm;
766 if (CT_COMMUNICATOR != tc->type)
769 return GNUNET_SYSERR;
771 size = ntohs (im->header.size) - sizeof (*im);
772 if (size < sizeof (struct GNUNET_MessageHeader))
775 return GNUNET_SYSERR;
777 obmm = (const struct GNUNET_MessageHeader *) &im[1];
778 if (size != ntohs (obmm->size))
781 return GNUNET_SYSERR;
788 * Incoming meessage. Process the request.
790 * @param cls the client
791 * @param im the send message that was received
794 handle_incoming_msg (void *cls,
795 const struct GNUNET_TRANSPORT_IncomingMessage *im)
797 struct TransportClient *tc = cls;
799 GNUNET_SERVICE_client_continue (tc->client);
804 * New queue became available. Check message.
806 * @param cls the client
807 * @param aqm the send message that was sent
810 check_add_queue_message (void *cls,
811 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
813 struct TransportClient *tc = cls;
817 if (CT_COMMUNICATOR != tc->type)
820 return GNUNET_SYSERR;
822 size = ntohs (aqm->header.size) - sizeof (*aqm);
826 return GNUNET_SYSERR;
828 addr = (const char *) &aqm[1];
829 if ('\0' != addr[size-1])
832 return GNUNET_SYSERR;
839 * New queue became available. Process the request.
841 * @param cls the client
842 * @param aqm the send message that was sent
845 handle_add_queue_message (void *cls,
846 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
848 struct TransportClient *tc = cls;
850 struct Neighbour *neighbour;
854 neighbour = lookup_neighbour (&aqm->receiver);
855 if (NULL == neighbour)
857 neighbour = GNUNET_new (struct Neighbour);
858 neighbour->pid = aqm->receiver;
859 GNUNET_assert (GNUNET_OK ==
860 GNUNET_CONTAINER_multipeermap_put (neighbours,
863 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
864 // FIXME: notify cores/monitors!
866 addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
867 addr = (const char *) &aqm[1];
869 queue = GNUNET_malloc (sizeof (struct Queue) + addr_len);
870 queue->qid = aqm->qid;
871 queue->nt = (enum GNUNET_ATS_Network_Type) ntohl (aqm->nt);
873 queue->neighbour = neighbour;
874 queue->address = (const char *) &queue[1];
878 GNUNET_CONTAINER_MDLL_insert (neighbour,
879 neighbour->queue_head,
880 neighbour->queue_tail,
882 GNUNET_CONTAINER_MDLL_insert (client,
883 tc->details.communicator.queue_head,
884 tc->details.communicator.queue_tail,
886 // FIXME: possibly transmit queued messages?
887 GNUNET_SERVICE_client_continue (tc->client);
892 * Release memory used by @a neighbour.
894 * @param neighbour neighbour entry to free
897 free_neighbour (struct Neighbour *neighbour)
899 GNUNET_assert (NULL == neighbour->queue_head);
900 GNUNET_assert (GNUNET_YES ==
901 GNUNET_CONTAINER_multipeermap_remove (neighbours,
904 GNUNET_free (neighbour);
909 * Queue to a peer went down. Process the request.
911 * @param cls the client
912 * @param dqm the send message that was sent
915 handle_del_queue_message (void *cls,
916 const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
918 struct TransportClient *tc = cls;
920 if (CT_COMMUNICATOR != tc->type)
923 GNUNET_SERVICE_client_drop (tc->client);
926 for (struct Queue *queue = tc->details.communicator.queue_head;
928 queue = queue->next_client)
930 struct Neighbour *neighbour = queue->neighbour;
932 if ( (dqm->qid != queue->qid) ||
933 (0 != memcmp (&dqm->receiver,
935 sizeof (struct GNUNET_PeerIdentity))) )
937 GNUNET_CONTAINER_MDLL_remove (neighbour,
938 neighbour->queue_head,
939 neighbour->queue_tail,
941 GNUNET_CONTAINER_MDLL_remove (client,
942 tc->details.communicator.queue_head,
943 tc->details.communicator.queue_tail,
946 if (NULL == neighbour->queue_head)
948 // FIXME: notify cores/monitors!
949 free_neighbour (neighbour);
951 GNUNET_SERVICE_client_continue (tc->client);
955 GNUNET_SERVICE_client_drop (tc->client);
960 * Message was transmitted. Process the request.
962 * @param cls the client
963 * @param sma the send message that was sent
966 handle_send_message_ack (void *cls,
967 const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
969 struct TransportClient *tc = cls;
971 if (CT_COMMUNICATOR != tc->type)
974 GNUNET_SERVICE_client_drop (tc->client);
977 GNUNET_SERVICE_client_continue (tc->client);
982 * Initialize a monitor client.
984 * @param cls the client
985 * @param start the start message that was sent
988 handle_monitor_start (void *cls,
989 const struct GNUNET_TRANSPORT_MonitorStart *start)
991 struct TransportClient *tc = cls;
993 if (CT_NONE != tc->type)
996 GNUNET_SERVICE_client_drop (tc->client);
999 tc->type = CT_MONITOR;
1000 tc->details.monitor.peer = start->peer;
1001 tc->details.monitor.one_shot = ntohl (start->one_shot);
1003 GNUNET_SERVICE_client_continue (tc->client);
1008 * Free neighbour entry.
1012 * @param value a `struct Neighbour`
1013 * @return #GNUNET_OK (always)
1016 free_neighbour_cb (void *cls,
1017 const struct GNUNET_PeerIdentity *pid,
1020 struct Neighbour *neighbour = value;
1024 GNUNET_break (0); // should this ever happen?
1025 free_neighbour (neighbour);
1032 * Function called when the service shuts down. Unloads our plugins
1033 * and cancels pending validations.
1035 * @param cls closure, unused
1038 do_shutdown (void *cls)
1042 if (NULL != GST_stats)
1044 GNUNET_STATISTICS_destroy (GST_stats,
1048 if (NULL != GST_my_private_key)
1050 GNUNET_free (GST_my_private_key);
1051 GST_my_private_key = NULL;
1053 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
1056 GNUNET_CONTAINER_multipeermap_destroy (neighbours);
1061 * Initiate transport service.
1063 * @param cls closure
1064 * @param c configuration to use
1065 * @param service the initialized service
1069 const struct GNUNET_CONFIGURATION_Handle *c,
1070 struct GNUNET_SERVICE_Handle *service)
1075 neighbours = GNUNET_CONTAINER_multipeermap_create (1024,
1077 GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
1078 if (NULL == GST_my_private_key)
1080 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1081 _("Transport service is lacking key configuration settings. Exiting.\n"));
1082 GNUNET_SCHEDULER_shutdown ();
1085 GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
1086 &GST_my_identity.public_key);
1087 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1088 "My identity is `%s'\n",
1089 GNUNET_i2s_full (&GST_my_identity));
1091 GST_stats = GNUNET_STATISTICS_create ("transport",
1093 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1095 /* start subsystems */
1100 * Define "main" method using service macro.
1104 GNUNET_SERVICE_OPTION_NONE,
1107 &client_disconnect_cb,
1109 /* communication with core */
1110 GNUNET_MQ_hd_fixed_size (client_start,
1111 GNUNET_MESSAGE_TYPE_TRANSPORT_START,
1112 struct StartMessage,
1114 GNUNET_MQ_hd_var_size (client_send,
1115 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
1116 struct OutboundMessage,
1118 /* communication with communicators */
1119 GNUNET_MQ_hd_var_size (communicator_available,
1120 GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
1121 struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
1123 GNUNET_MQ_hd_var_size (add_address,
1124 GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
1125 struct GNUNET_TRANSPORT_AddAddressMessage,
1127 GNUNET_MQ_hd_fixed_size (del_address,
1128 GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
1129 struct GNUNET_TRANSPORT_DelAddressMessage,
1131 GNUNET_MQ_hd_var_size (incoming_msg,
1132 GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
1133 struct GNUNET_TRANSPORT_IncomingMessage,
1135 GNUNET_MQ_hd_var_size (add_queue_message,
1136 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
1137 struct GNUNET_TRANSPORT_AddQueueMessage,
1139 GNUNET_MQ_hd_fixed_size (del_queue_message,
1140 GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
1141 struct GNUNET_TRANSPORT_DelQueueMessage,
1143 GNUNET_MQ_hd_fixed_size (send_message_ack,
1144 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
1145 struct GNUNET_TRANSPORT_SendMessageToAck,
1147 /* communication with monitors */
1148 GNUNET_MQ_hd_fixed_size (monitor_start,
1149 GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_START,
1150 struct GNUNET_TRANSPORT_MonitorStart,
1152 GNUNET_MQ_handler_end ());
1155 /* end of file gnunet-service-transport.c */