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