Merge branch 'master' of gnunet.org:gnunet
[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 #include "platform.h"
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"
31
32
33 /**
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.
38  *
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
43  * fail.
44  */
45 #define MAX_PENDING (128 * 1024)
46
47
48 /**
49  * What type of client is the `struct TransportClient` about?
50  */
51 enum ClientType
52 {
53   /**
54    * We do not know yet (client is fresh).
55    */
56   CT_NONE = 0,
57
58   /**
59    * Is the CORE service, we need to forward traffic to it.
60    */
61   CT_CORE = 1,
62
63   /**
64    * It is a monitor, forward monitor data.
65    */
66   CT_MONITOR = 2,
67
68   /**
69    * It is a communicator, use for communication.
70    */
71   CT_COMMUNICATOR = 3
72 };
73
74
75 /**
76  * Client connected to the transport service.
77  */
78 struct TransportClient
79 {
80
81   /**
82    * Kept in a DLL.
83    */
84   struct TransportClient *next;
85
86   /**
87    * Kept in a DLL.
88    */
89   struct TransportClient *prev;
90
91   /**
92    * Handle to the client.
93    */
94   struct GNUNET_SERVICE_Client *client;
95
96   /**
97    * Message queue to the client.
98    */
99   struct GNUNET_MQ_Handle *mq;
100
101   /**
102    * What type of client is this?
103    */
104   enum ClientType type;
105
106   union
107   {
108
109     /**
110      * Peer identity to monitor the addresses of.
111      * Zero to monitor all neighbours.  Valid if
112      * @e type is #CT_MONITOR.
113      */
114     struct GNUNET_PeerIdentity monitor_peer;
115
116     /**
117      * If @e type is #CT_COMMUNICATOR, this communicator
118      * supports communicating using these addresses.
119      */
120     const char *address_prefix;
121
122   } details;
123
124 };
125
126
127 /**
128  * Head of linked list of all clients to this service.
129  */
130 static struct TransportClient *clients_head;
131
132 /**
133  * Tail of linked list of all clients to this service.
134  */
135 static struct TransportClient *clients_tail;
136
137 /**
138  * Statistics handle.
139  */
140 struct GNUNET_STATISTICS_Handle *GST_stats;
141
142 /**
143  * Configuration handle.
144  */
145 const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
146
147 /**
148  * Configuration handle.
149  */
150 struct GNUNET_PeerIdentity GST_my_identity;
151
152 /**
153  * Handle to peerinfo service.
154  */
155 struct GNUNET_PEERINFO_Handle *GST_peerinfo;
156
157 /**
158  * Our private key.
159  */
160 struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key;
161
162
163 /**
164  * Called whenever a client connects.  Allocates our
165  * data structures associated with that client.
166  *
167  * @param cls closure, NULL
168  * @param client identification of the client
169  * @param mq message queue for the client
170  * @return our `struct TransportClient`
171  */
172 static void *
173 client_connect_cb (void *cls,
174                    struct GNUNET_SERVICE_Client *client,
175                    struct GNUNET_MQ_Handle *mq)
176 {
177   struct TransportClient *tc;
178
179   tc = GNUNET_new (struct TransportClient);
180   tc->client = client;
181   tc->mq = mq;
182   GNUNET_CONTAINER_DLL_insert (clients_head,
183                                clients_tail,
184                                tc);
185   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
186               "Client %p connected\n",
187               tc);
188   return tc;
189 }
190
191
192 /**
193  * Called whenever a client is disconnected.  Frees our
194  * resources associated with that client.
195  *
196  * @param cls closure, NULL
197  * @param client identification of the client
198  * @param app_ctx our `struct TransportClient`
199  */
200 static void
201 client_disconnect_cb (void *cls,
202                       struct GNUNET_SERVICE_Client *client,
203                       void *app_ctx)
204 {
205   struct TransportClient *tc = app_ctx;
206
207   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
208               "Client %p disconnected, cleaning up.\n",
209               tc);
210   GNUNET_CONTAINER_DLL_remove (clients_head,
211                                clients_tail,
212                                tc);
213   switch (tc->type)
214   {
215   case CT_NONE:
216     break;
217   case CT_CORE:
218     break;
219   case CT_MONITOR:
220     break;
221   case CT_COMMUNICATOR:
222     break;
223   }
224   GNUNET_free (tc);
225 }
226
227
228 /**
229  * Initialize a "CORE" client.  We got a start message from this
230  * client, so add it to the list of clients for broadcasting of
231  * inbound messages.
232  *
233  * @param cls the client
234  * @param start the start message that was sent
235  */
236 static void
237 handle_client_start (void *cls,
238                      const struct StartMessage *start)
239 {
240   struct TransportClient *tc = cls;
241   const struct GNUNET_MessageHeader *hello;
242   uint32_t options;
243
244   options = ntohl (start->options);
245   if ( (0 != (1 & options)) &&
246        (0 !=
247         memcmp (&start->self,
248                 &GST_my_identity,
249                 sizeof (struct GNUNET_PeerIdentity)) ) )
250   {
251     /* client thinks this is a different peer, reject */
252     GNUNET_break (0);
253     GNUNET_SERVICE_client_drop (tc->client);
254     return;
255   }
256   if (CT_NONE != tc->type)
257   {
258     GNUNET_break (0);
259     GNUNET_SERVICE_client_drop (tc->client);
260     return;
261   }
262   tc->type = CT_CORE;
263 #if 0
264   hello = GST_hello_get ();
265   if (NULL != hello)
266     unicast (tc,
267              hello,
268              GNUNET_NO);
269 #endif
270   GNUNET_SERVICE_client_continue (tc->client);
271 }
272
273
274 /**
275  * Client sent us a HELLO.  Check the request.
276  *
277  * @param cls the client
278  * @param message the HELLO message
279  */
280 static int
281 check_client_hello (void *cls,
282                     const struct GNUNET_MessageHeader *message)
283 {
284   (void) cls;
285   return GNUNET_OK; /* FIXME: check here? */
286 }
287
288
289 /**
290  * Client sent us a HELLO.  Process the request.
291  *
292  * @param cls the client
293  * @param message the HELLO message
294  */
295 static void
296 handle_client_hello (void *cls,
297                      const struct GNUNET_MessageHeader *message)
298 {
299   struct TransportClient *tc = cls;
300
301   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
302               "Received HELLO message\n");
303   GNUNET_SERVICE_client_continue (tc->client);
304 }
305
306
307 /**
308  * Client asked for transmission to a peer.  Process the request.
309  *
310  * @param cls the client
311  * @param obm the send message that was sent
312  */
313 static int
314 check_client_send (void *cls,
315                    const struct OutboundMessage *obm)
316 {
317   uint16_t size;
318   const struct GNUNET_MessageHeader *obmm;
319
320   (void) cls;
321   size = ntohs (obm->header.size) - sizeof (struct OutboundMessage);
322   if (size < sizeof (struct GNUNET_MessageHeader))
323   {
324     GNUNET_break (0);
325     return GNUNET_SYSERR;
326   }
327   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
328   if (size != ntohs (obmm->size))
329   {
330     GNUNET_break (0);
331     return GNUNET_SYSERR;
332   }
333   return GNUNET_OK;
334 }
335
336
337 /**
338  * Client asked for transmission to a peer.  Process the request.
339  *
340  * @param cls the client
341  * @param obm the send message that was sent
342  */
343 static void
344 handle_client_send (void *cls,
345                     const struct OutboundMessage *obm)
346 {
347   struct TransportClient *tc = cls;
348   const struct GNUNET_MessageHeader *obmm;
349
350   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
351 }
352
353
354 /**
355  * Communicator started.  Test message is well-formed.
356  *
357  * @param cls the client
358  * @param cam the send message that was sent
359  */
360 static int
361 check_communicator_available (void *cls,
362                               const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
363 {
364   const char *addr;
365   uint16_t size;
366
367   (void) cls;
368   size = ntohs (cam->header.size) - sizeof (*cam);
369   if (0 == size)
370     return GNUNET_OK; /* receive-only communicator */
371   addr = (const char *) &cam[1];
372   if ('\0' != addr[size-1])
373   {
374     GNUNET_break (0);
375     return GNUNET_SYSERR;
376   }
377   return GNUNET_OK;
378 }
379
380
381 /**
382  * Communicator started.  Process the request.
383  *
384  * @param cls the client
385  * @param cam the send message that was sent
386  */
387 static void
388 handle_communicator_available (void *cls,
389                                const struct GNUNET_TRANSPORT_CommunicatorAvailableMessage *cam)
390 {
391   struct TransportClient *tc = cls;
392   uint16_t size;
393
394   if (CT_NONE != tc->type)
395   {
396     GNUNET_break (0);
397     GNUNET_SERVICE_client_drop (tc->client);
398     return;
399   }
400   tc->type = CT_COMMUNICATOR;
401   size = ntohs (cam->header.size) - sizeof (*cam);
402   if (0 == size)
403     return GNUNET_OK; /* receive-only communicator */
404   tc->details.address_prefix = GNUNET_strdup ((const char *) &cam[1]);
405   GNUNET_SERVICE_client_continue (tc->client);
406 }
407
408
409 /**
410  * Address of our peer added.  Test message is well-formed.
411  *
412  * @param cls the client
413  * @param aam the send message that was sent
414  */
415 static int
416 check_add_address (void *cls,
417                    const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
418 {
419   const char *addr;
420   uint16_t size;
421
422   (void) cls;
423   size = ntohs (aam->header.size) - sizeof (*aam);
424   if (0 == size)
425   {
426     GNUNET_break (0);
427     return GNUNET_SYSERR;
428   }
429   addr = (const char *) &cam[1];
430   if ('\0' != addr[size-1])
431   {
432     GNUNET_break (0);
433     return GNUNET_SYSERR;
434   }
435   return GNUNET_OK;
436 }
437
438
439 /**
440  * Address of our peer added.  Process the request.
441  *
442  * @param cls the client
443  * @param aam the send message that was sent
444  */
445 static void
446 handle_add_address (void *cls,
447                     const struct GNUNET_TRANSPORT_AddAddressMessage *aam)
448 {
449   struct TransportClient *tc = cls;
450
451   GNUNET_SERVICE_client_continue (tc->client);
452 }
453
454
455 /**
456  * Address of our peer deleted.  Process the request.
457  *
458  * @param cls the client
459  * @param dam the send message that was sent
460  */
461 static void
462 handle_del_address (void *cls,
463                     const struct GNUNET_TRANSPORT_DelAddressMessage *dam)
464 {
465   struct TransportClient *tc = cls;
466
467   GNUNET_SERVICE_client_continue (tc->client);
468 }
469
470
471 /**
472  * Client asked for transmission to a peer.  Process the request.
473  *
474  * @param cls the client
475  * @param obm the send message that was sent
476  */
477 static int
478 check_incoming_msg (void *cls,
479                     const struct GNUNET_TRANSPORT_IncomingMessage *im)
480 {
481   uint16_t size;
482   const struct GNUNET_MessageHeader *obmm;
483
484   (void) cls;
485   size = ntohs (im->header.size) - sizeof (*im);
486   if (size < sizeof (struct GNUNET_MessageHeader))
487   {
488     GNUNET_break (0);
489     return GNUNET_SYSERR;
490   }
491   obmm = (const struct GNUNET_MessageHeader *) &im[1];
492   if (size != ntohs (obmm->size))
493   {
494     GNUNET_break (0);
495     return GNUNET_SYSERR;
496   }
497   return GNUNET_OK;
498 }
499
500
501 /**
502  * Incoming meessage.  Process the request.
503  *
504  * @param cls the client
505  * @param im the send message that was received
506  */
507 static void
508 handle_incoming_msg (void *cls,
509                      const struct GNUNET_TRANSPORT_IncomingMessage *im)
510 {
511   struct TransportClient *tc = cls;
512
513   GNUNET_SERVICE_client_continue (tc->client);
514 }
515
516
517 /**
518  * New queue became available.  Check message.
519  *
520  * @param cls the client
521  * @param aqm the send message that was sent
522  */
523 static int
524 check_add_queue_message (void *cls,
525                          const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
526 {
527   const char *addr;
528   uint16_t size;
529
530   (void) cls;
531   size = ntohs (aqm->header.size) - sizeof (*aqm);
532   if (0 == size)
533   {
534     GNUNET_break (0);
535     return GNUNET_SYSERR;
536   }
537   addr = (const char *) &aqm[1];
538   if ('\0' != addr[size-1])
539   {
540     GNUNET_break (0);
541     return GNUNET_SYSERR;
542   }
543   return GNUNET_OK;
544 }
545
546
547 /**
548  * New queue became available.  Process the request.
549  *
550  * @param cls the client
551  * @param aqm the send message that was sent
552  */
553 static void
554 handle_add_queue_message (void *cls,
555                           const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
556 {
557   struct TransportClient *tc = cls;
558
559   GNUNET_SERVICE_client_continue (tc->client);
560 }
561
562
563 /**
564  * Queue to a peer went down.  Process the request.
565  *
566  * @param cls the client
567  * @param dqm the send message that was sent
568  */
569 static void
570 handle_del_queue_message (void *cls,
571                           const struct GNUNET_TRANSPORT_DelQueueMessage *dqm)
572 {
573   struct TransportClient *tc = cls;
574
575   GNUNET_SERVICE_client_continue (tc->client);
576 }
577
578
579 /**
580  * Message was transmitted.  Process the request.
581  *
582  * @param cls the client
583  * @param sma the send message that was sent
584  */
585 static void
586 handle_send_message_ack (void *cls,
587                          const struct GNUNET_TRANSPORT_SendMessageToAck *sma)
588 {
589   struct TransportClient *tc = cls;
590
591   GNUNET_SERVICE_client_continue (tc->client);
592 }
593
594
595 /**
596  * Function called when the service shuts down.  Unloads our plugins
597  * and cancels pending validations.
598  *
599  * @param cls closure, unused
600  */
601 static void
602 shutdown_task (void *cls)
603 {
604   (void) cls;
605
606   if (NULL != GST_stats)
607   {
608     GNUNET_STATISTICS_destroy (GST_stats,
609                                GNUNET_NO);
610     GST_stats = NULL;
611   }
612   if (NULL != GST_my_private_key)
613   {
614     GNUNET_free (GST_my_private_key);
615     GST_my_private_key = NULL;
616   }
617 }
618
619
620 /**
621  * Initiate transport service.
622  *
623  * @param cls closure
624  * @param c configuration to use
625  * @param service the initialized service
626  */
627 static void
628 run (void *cls,
629      const struct GNUNET_CONFIGURATION_Handle *c,
630      struct GNUNET_SERVICE_Handle *service)
631 {
632   /* setup globals */
633   GST_cfg = c;
634   if (GNUNET_OK !=
635       GNUNET_CONFIGURATION_get_value_time (c,
636                                            "transport",
637                                            "HELLO_EXPIRATION",
638                                            &hello_expiration))
639   {
640     hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION;
641   }
642   GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
643   if (NULL == GST_my_private_key)
644   {
645     GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
646         _("Transport service is lacking key configuration settings. Exiting.\n"));
647     GNUNET_SCHEDULER_shutdown ();
648     return;
649   }
650   GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key,
651                                       &GST_my_identity.public_key);
652   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
653              "My identity is `%s'\n",
654              GNUNET_i2s_full (&GST_my_identity));
655
656   GST_stats = GNUNET_STATISTICS_create ("transport",
657                                         GST_cfg);
658   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
659                                  NULL);
660   /* start subsystems */
661 }
662
663
664 /**
665  * Define "main" method using service macro.
666  */
667 GNUNET_SERVICE_MAIN
668 ("transport",
669  GNUNET_SERVICE_OPTION_NONE,
670  &run,
671  &client_connect_cb,
672  &client_disconnect_cb,
673  NULL,
674  /* communication with core */
675  GNUNET_MQ_hd_fixed_size (client_start,
676                           GNUNET_MESSAGE_TYPE_TRANSPORT_START,
677                           struct StartMessage,
678                           NULL),
679  GNUNET_MQ_hd_var_size (client_hello,
680                         GNUNET_MESSAGE_TYPE_HELLO,
681                         struct GNUNET_MessageHeader,
682                         NULL),
683  GNUNET_MQ_hd_var_size (client_send,
684                         GNUNET_MESSAGE_TYPE_TRANSPORT_SEND,
685                         struct OutboundMessage,
686                         NULL),
687  /* communication with communicators */
688  GNUNET_MQ_hd_var_size (communicator_available,
689                         GNUNET_MESSAGE_TYPE_TRANSPORT_NEW_COMMUNICATOR,
690                         struct GNUNET_TRANSPORT_CommunicatorAvailableMessage,
691                         NULL),
692  GNUNET_MQ_hd_var_size (add_address,
693                         GNUNET_MESSAGE_TYPE_TRANSPORT_ADD_ADDRESS,
694                         struct GNUNET_TRANSPORT_AddAddressMessage,
695                         NULL),
696  GNUNET_MQ_hd_fixed_size (del_address,
697                           GNUNET_MESSAGE_TYPE_TRANSPORT_DEL_ADDRESS,
698                           struct GNUNET_TRANSPORT_DelAddressMessage,
699                           NULL),
700  GNUNET_MQ_hd_var_size (incoming_msg,
701                         GNUNET_MESSAGE_TYPE_TRANSPORT_INCOMING_MSG,
702                         struct GNUNET_TRANSPORT_IncomingMessage,
703                         NULL),
704  GNUNET_MQ_hd_var_size (add_queue_message,
705                         GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_SETUP,
706                         struct GNUNET_TRANSPORT_AddQueueMessage,
707                         NULL),
708  GNUNET_MQ_hd_fixed_size (del_queue_message,
709                           GNUNET_MESSAGE_TYPE_TRANSPORT_QUEUE_TEARDOWN,
710                           struct GNUNET_TRANSPORT_DelQueueMessage,
711                           NULL),
712  GNUNET_MQ_hd_fixed_size (send_message_ack,
713                           GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_MSG_ACK,
714                           struct GNUNET_TRANSPORT_SendMessageToAck,
715                           NULL),
716  GNUNET_MQ_handler_end ());
717
718
719 /* end of file gnunet-service-transport.c */