use NULL value in load_path_suffix to NOT load any files
[oweals/gnunet.git] / src / ats / gnunet-service-ats.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2011 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      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 /**
21  * @file ats/gnunet-service-ats.c
22  * @brief ats service
23  * @author Matthias Wachs
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet-service-ats.h"
29 #include "gnunet-service-ats_addresses.h"
30 #include "gnunet-service-ats_connectivity.h"
31 #include "gnunet-service-ats_normalization.h"
32 #include "gnunet-service-ats_performance.h"
33 #include "gnunet-service-ats_preferences.h"
34 #include "gnunet-service-ats_scheduling.h"
35 #include "gnunet-service-ats_reservations.h"
36 #include "gnunet-service-ats_plugins.h"
37 #include "ats.h"
38
39 /**
40  * Handle for statistics.
41  */
42 struct GNUNET_STATISTICS_Handle *GSA_stats;
43
44
45 /**
46  * We have received a `struct ClientStartMessage` from a client.  Find
47  * out which type of client it is and notify the respective subsystem.
48  *
49  * @param cls handle to the client
50  * @param msg the start message
51  */
52 static void
53 handle_ats_start (void *cls,
54                   const struct ClientStartMessage *msg)
55 {
56   struct GNUNET_SERVICE_Client *client = cls;
57   enum StartFlag flag;
58
59   flag = ntohl (msg->start_flag);
60   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
61               "Received ATS_START (%d) message\n",
62               (int) flag);
63   switch (flag)
64   {
65   case START_FLAG_SCHEDULING:
66     if (GNUNET_OK !=
67         GAS_scheduling_add_client (client))
68     {
69       GNUNET_SERVICE_client_drop (client);
70       return;
71     }
72     break;
73
74   case START_FLAG_PERFORMANCE_WITH_PIC:
75     GAS_performance_add_client (client,
76                                 flag);
77     break;
78
79   case START_FLAG_PERFORMANCE_NO_PIC:
80     GAS_performance_add_client (client,
81                                 flag);
82     break;
83
84   case START_FLAG_CONNECTION_SUGGESTION:
85     /* This client won't receive messages from us, no need to 'add' */
86     break;
87
88   default:
89     GNUNET_break (0);
90     GNUNET_SERVICE_client_drop (client);
91     return;
92   }
93   GNUNET_SERVICE_client_continue (client);
94 }
95
96
97 /**
98  * Handle 'reservation request' messages from clients.
99  *
100  * @param cls client that sent the request
101  * @param message the request message
102  */
103 static void
104 handle_reservation_request (void *cls,
105                             const struct ReservationRequestMessage *message)
106 {
107   struct GNUNET_SERVICE_Client *client = cls;
108
109   GAS_handle_reservation_request (client,
110                                   message);
111   GNUNET_SERVICE_client_continue (client);
112 }
113
114
115 /**
116  * Check 'preference feedback' message is well-formed
117  *
118  * @param cls client that sent the request
119  * @param message the request message
120  * @return #GNUNET_OK if @a message is well-formed
121  */
122 static int
123 check_feedback (void *cls,
124                 const struct FeedbackPreferenceMessage *message)
125 {
126   uint16_t msize;
127   uint32_t nump;
128
129   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
130               "Received PREFERENCE_FEEDBACK message\n");
131   msize = ntohs (message->header.size);
132   nump = ntohl (message->num_feedback);
133   if (msize !=
134       sizeof(struct FeedbackPreferenceMessage)
135       + nump * sizeof(struct PreferenceInformation))
136   {
137     GNUNET_break (0);
138     return GNUNET_SYSERR;
139   }
140   return GNUNET_OK;
141 }
142
143
144 /**
145  * Handle 'preference feedback' messages from clients.
146  *
147  * @param cls client that sent the request
148  * @param msg the request message
149  */
150 static void
151 handle_feedback (void *cls,
152                  const struct FeedbackPreferenceMessage *msg)
153 {
154   struct GNUNET_SERVICE_Client *client = cls;
155   const struct PreferenceInformation *pi;
156   uint32_t nump;
157
158   nump = ntohl (msg->num_feedback);
159   if (GNUNET_NO ==
160       GNUNET_CONTAINER_multipeermap_contains (GSA_addresses,
161                                               &msg->peer))
162   {
163     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
164                 "Received PREFERENCE FEEDBACK for unknown peer `%s'\n",
165                 GNUNET_i2s (&msg->peer));
166     GNUNET_SERVICE_client_continue (client);
167     return;
168   }
169
170   GNUNET_STATISTICS_update (GSA_stats,
171                             "# preference feedbacks requests processed",
172                             1,
173                             GNUNET_NO);
174   pi = (const struct PreferenceInformation *) &msg[1];
175   for (uint32_t i = 0; i < nump; i++)
176   {
177     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
178                 "Received PREFERENCE FEEDBACK for peer `%s'\n",
179                 GNUNET_i2s (&msg->peer));
180     GAS_plugin_notify_feedback (client,
181                                 &msg->peer,
182                                 GNUNET_TIME_relative_ntoh (msg->scope),
183                                 (enum GNUNET_ATS_PreferenceKind) ntohl (
184                                   pi[i].preference_kind),
185                                 pi[i].preference_value);
186   }
187   GNUNET_SERVICE_client_continue (client);
188 }
189
190
191 /**
192  * Handle 'request address list' messages from clients.
193  *
194  * @param cls client that sent the request
195  * @param message the request message
196  */
197 static void
198 handle_request_address_list (void *cls,
199                              const struct AddressListRequestMessage *message)
200 {
201   struct GNUNET_SERVICE_Client *client = cls;
202
203   GAS_handle_request_address_list (client,
204                                    message);
205   GNUNET_SERVICE_client_continue (client);
206 }
207
208
209 /**
210  * Handle 'request address' messages from clients.
211  *
212  * @param cls client that sent the request
213  * @param message the request message
214  */
215 static void
216 handle_request_address (void *cls,
217                         const struct RequestAddressMessage *message)
218 {
219   struct GNUNET_SERVICE_Client *client = cls;
220
221   GAS_handle_request_address (client,
222                               message);
223   GNUNET_SERVICE_client_continue (client);
224 }
225
226
227 /**
228  * Cancel 'request address' messages from clients.
229  *
230  * @param cls client that sent the request
231  * @param message the request message
232  */
233 static void
234 handle_request_address_cancel (void *cls,
235                                const struct RequestAddressMessage *message)
236 {
237   struct GNUNET_SERVICE_Client *client = cls;
238
239   GAS_handle_request_address_cancel (client,
240                                      message);
241   GNUNET_SERVICE_client_continue (client);
242 }
243
244
245 /**
246  * Handle 'address add' messages from clients.
247  *
248  * @param cls client that sent the request
249  * @param m the request message
250  */
251 static int
252 check_address_add (void *cls,
253                    const struct AddressAddMessage *m)
254 {
255   const char *address;
256   const char *plugin_name;
257   uint16_t address_length;
258   uint16_t plugin_name_length;
259   uint16_t size;
260
261   size = ntohs (m->header.size);
262   address_length = ntohs (m->address_length);
263   plugin_name_length = ntohs (m->plugin_name_length);
264   address = (const char *) &m[1];
265   if (plugin_name_length != 0)
266     plugin_name = &address[address_length];
267   else
268     plugin_name = "";
269
270   if ((address_length + plugin_name_length
271        + sizeof(struct AddressAddMessage) != size) ||
272       ((plugin_name_length > 0) &&
273        (plugin_name[plugin_name_length - 1] != '\0')))
274   {
275     GNUNET_break (0);
276     return GNUNET_SYSERR;
277   }
278   return GNUNET_OK;
279 }
280
281
282 /**
283  * Handle 'address add' messages from clients.
284  *
285  * @param cls client that sent the request
286  * @param message the request message
287  */
288 static void
289 handle_address_add (void *cls,
290                     const struct AddressAddMessage *message)
291 {
292   struct GNUNET_SERVICE_Client *client = cls;
293
294   GAS_handle_address_add (message);
295   GNUNET_SERVICE_client_continue (client);
296 }
297
298
299 /**
300  * Handle 'address update' messages from clients.
301  *
302  * @param cls client that sent the request
303  * @param message the request message
304  */
305 static void
306 handle_address_update (void *cls,
307                        const struct AddressUpdateMessage *message)
308 {
309   struct GNUNET_SERVICE_Client *client = cls;
310
311   GAS_handle_address_update (message);
312   GNUNET_SERVICE_client_continue (client);
313 }
314
315
316 /**
317  * Handle 'address destroyed' messages from clients.
318  *
319  * @param cls client that sent the request
320  * @param message the request message
321  */
322 static void
323 handle_address_destroyed (void *cls,
324                           const struct AddressDestroyedMessage *message)
325 {
326   struct GNUNET_SERVICE_Client *client = cls;
327
328   GAS_handle_address_destroyed (message);
329   GNUNET_SERVICE_client_continue (client);
330 }
331
332
333 /**
334  * Check that 'change preference' message is well-formed.
335  *
336  * @param cls client that sent the request
337  * @param message the request message
338  * @return #GNUNET_OK if @a message is well-formed
339  */
340 static int
341 check_preference_change (void *cls,
342                          const struct ChangePreferenceMessage *message)
343 {
344   uint16_t msize;
345   uint32_t nump;
346
347   msize = ntohs (message->header.size);
348   nump = ntohl (message->num_preferences);
349   if ((msize !=
350        sizeof(struct ChangePreferenceMessage)
351        + nump * sizeof(struct PreferenceInformation)) ||
352       (UINT16_MAX / sizeof(struct PreferenceInformation) < nump))
353   {
354     GNUNET_break (0);
355     return GNUNET_SYSERR;
356   }
357   return GNUNET_OK;
358 }
359
360
361 /**
362  * Handle 'change preference' messages from clients.
363  *
364  * @param cls client that sent the request
365  * @param message the request message
366  */
367 static void
368 handle_preference_change (void *cls,
369                           const struct ChangePreferenceMessage *message)
370 {
371   struct GNUNET_SERVICE_Client *client = cls;
372
373   GAS_handle_preference_change (client,
374                                 message);
375   GNUNET_SERVICE_client_continue (client);
376 }
377
378
379 /**
380  * A client connected to us. Setup the local client
381  * record.
382  *
383  * @param cls unused
384  * @param client handle of the client
385  * @param mq message queue to talk to @a client
386  * @return @a client
387  */
388 static void *
389 client_connect_cb (void *cls,
390                    struct GNUNET_SERVICE_Client *client,
391                    struct GNUNET_MQ_Handle *mq)
392 {
393   return client;
394 }
395
396
397 /**
398  * A client disconnected from us.  Tear down the local client
399  * record.
400  *
401  * @param cls unused
402  * @param client handle of the client
403  * @param app_ctx
404  */
405 static void
406 client_disconnect_cb (void *cls,
407                       struct GNUNET_SERVICE_Client *client,
408                       void *app_ctx)
409 {
410   if (NULL == client)
411     return;
412   GAS_scheduling_remove_client (client);
413   GAS_connectivity_remove_client (client);
414   GAS_preference_client_disconnect (client);
415 }
416
417
418 /**
419  * Task run during shutdown.
420  *
421  * @param cls unused
422  */
423 static void
424 cleanup_task (void *cls)
425 {
426   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
427               "ATS shutdown initiated\n");
428   GAS_connectivity_done ();
429   GAS_addresses_done ();
430   GAS_plugin_done ();
431   GAS_normalization_stop ();
432   GAS_performance_done ();
433   GAS_preference_done ();
434   GAS_reservations_done ();
435   if (NULL != GSA_stats)
436   {
437     GNUNET_STATISTICS_destroy (GSA_stats, GNUNET_NO);
438     GSA_stats = NULL;
439   }
440 }
441
442
443 /**
444  * Process template requests.
445  *
446  * @param cls closure
447  * @param cfg configuration to use
448  * @param service the initialized service
449  */
450 static void
451 run (void *cls,
452      const struct GNUNET_CONFIGURATION_Handle *cfg,
453      struct GNUNET_SERVICE_Handle *service)
454 {
455   GSA_stats = GNUNET_STATISTICS_create ("ats",
456                                         cfg);
457   GAS_reservations_init ();
458   GAS_connectivity_init ();
459   GAS_preference_init ();
460   GAS_normalization_start ();
461   GAS_addresses_init ();
462   if (GNUNET_OK !=
463       GAS_plugin_init (cfg))
464   {
465     GNUNET_break (0);
466     GAS_addresses_done ();
467     GAS_normalization_stop ();
468     GAS_reservations_done ();
469     GAS_connectivity_done ();
470     GAS_preference_done ();
471     if (NULL != GSA_stats)
472     {
473       GNUNET_STATISTICS_destroy (GSA_stats,
474                                  GNUNET_NO);
475       GSA_stats = NULL;
476     }
477     return;
478   }
479   GAS_performance_init ();
480   GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
481                                  NULL);
482 }
483
484
485 /**
486  * Define "main" method using service macro.
487  */
488 GNUNET_SERVICE_MAIN
489   ("ats",
490   GNUNET_SERVICE_OPTION_NONE,
491   &run,
492   &client_connect_cb,
493   &client_disconnect_cb,
494   NULL,
495   GNUNET_MQ_hd_fixed_size (ats_start,
496                            GNUNET_MESSAGE_TYPE_ATS_START,
497                            struct ClientStartMessage,
498                            NULL),
499   GNUNET_MQ_hd_fixed_size (request_address,
500                            GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS,
501                            struct RequestAddressMessage,
502                            NULL),
503   GNUNET_MQ_hd_fixed_size (request_address_cancel,
504                            GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL,
505                            struct RequestAddressMessage,
506                            NULL),
507   GNUNET_MQ_hd_fixed_size (request_address_list,
508                            GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_REQUEST,
509                            struct AddressListRequestMessage,
510                            NULL),
511   GNUNET_MQ_hd_var_size (address_add,
512                          GNUNET_MESSAGE_TYPE_ATS_ADDRESS_ADD,
513                          struct AddressAddMessage,
514                          NULL),
515   GNUNET_MQ_hd_fixed_size (address_update,
516                            GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE,
517                            struct AddressUpdateMessage,
518                            NULL),
519   GNUNET_MQ_hd_fixed_size (address_destroyed,
520                            GNUNET_MESSAGE_TYPE_ATS_ADDRESS_DESTROYED,
521                            struct AddressDestroyedMessage,
522                            NULL),
523   GNUNET_MQ_hd_fixed_size (reservation_request,
524                            GNUNET_MESSAGE_TYPE_ATS_RESERVATION_REQUEST,
525                            struct ReservationRequestMessage,
526                            NULL),
527   GNUNET_MQ_hd_var_size (preference_change,
528                          GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_CHANGE,
529                          struct ChangePreferenceMessage,
530                          NULL),
531   GNUNET_MQ_hd_var_size (feedback,
532                          GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_FEEDBACK,
533                          struct FeedbackPreferenceMessage,
534                          NULL),
535   GNUNET_MQ_handler_end ());
536
537
538 /* end of gnunet-service-ats.c */