2 This file is part of GNUnet.
3 Copyright (C) 2011 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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
21 * @file ats/gnunet-service-ats.c
23 * @author Matthias Wachs
24 * @author Christian Grothoff
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"
40 * Handle for statistics.
42 struct GNUNET_STATISTICS_Handle *GSA_stats;
46 * We have received a `struct ClientStartMessage` from a client. Find
47 * out which type of client it is and notify the respective subsystem.
49 * @param cls handle to the client
50 * @param msg the start message
53 handle_ats_start (void *cls,
54 const struct ClientStartMessage *msg)
56 struct GNUNET_SERVICE_Client *client = cls;
59 flag = ntohl (msg->start_flag);
60 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
61 "Received ATS_START (%d) message\n",
65 case START_FLAG_SCHEDULING:
67 GAS_scheduling_add_client (client))
69 GNUNET_SERVICE_client_drop (client);
74 case START_FLAG_PERFORMANCE_WITH_PIC:
75 GAS_performance_add_client (client,
79 case START_FLAG_PERFORMANCE_NO_PIC:
80 GAS_performance_add_client (client,
84 case START_FLAG_CONNECTION_SUGGESTION:
85 /* This client won't receive messages from us, no need to 'add' */
90 GNUNET_SERVICE_client_drop (client);
93 GNUNET_SERVICE_client_continue (client);
98 * Handle 'reservation request' messages from clients.
100 * @param cls client that sent the request
101 * @param message the request message
104 handle_reservation_request (void *cls,
105 const struct ReservationRequestMessage *message)
107 struct GNUNET_SERVICE_Client *client = cls;
109 GAS_handle_reservation_request (client,
111 GNUNET_SERVICE_client_continue (client);
116 * Check 'preference feedback' message is well-formed
118 * @param cls client that sent the request
119 * @param message the request message
120 * @return #GNUNET_OK if @a message is well-formed
123 check_feedback (void *cls,
124 const struct FeedbackPreferenceMessage *message)
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);
134 sizeof(struct FeedbackPreferenceMessage)
135 + nump * sizeof(struct PreferenceInformation))
138 return GNUNET_SYSERR;
145 * Handle 'preference feedback' messages from clients.
147 * @param cls client that sent the request
148 * @param msg the request message
151 handle_feedback (void *cls,
152 const struct FeedbackPreferenceMessage *msg)
154 struct GNUNET_SERVICE_Client *client = cls;
155 const struct PreferenceInformation *pi;
158 nump = ntohl (msg->num_feedback);
160 GNUNET_CONTAINER_multipeermap_contains (GSA_addresses,
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);
170 GNUNET_STATISTICS_update (GSA_stats,
171 "# preference feedbacks requests processed",
174 pi = (const struct PreferenceInformation *) &msg[1];
175 for (uint32_t i = 0; i < nump; i++)
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,
182 GNUNET_TIME_relative_ntoh (msg->scope),
183 (enum GNUNET_ATS_PreferenceKind) ntohl (
184 pi[i].preference_kind),
185 pi[i].preference_value);
187 GNUNET_SERVICE_client_continue (client);
192 * Handle 'request address list' messages from clients.
194 * @param cls client that sent the request
195 * @param message the request message
198 handle_request_address_list (void *cls,
199 const struct AddressListRequestMessage *message)
201 struct GNUNET_SERVICE_Client *client = cls;
203 GAS_handle_request_address_list (client,
205 GNUNET_SERVICE_client_continue (client);
210 * Handle 'request address' messages from clients.
212 * @param cls client that sent the request
213 * @param message the request message
216 handle_request_address (void *cls,
217 const struct RequestAddressMessage *message)
219 struct GNUNET_SERVICE_Client *client = cls;
221 GAS_handle_request_address (client,
223 GNUNET_SERVICE_client_continue (client);
228 * Cancel 'request address' messages from clients.
230 * @param cls client that sent the request
231 * @param message the request message
234 handle_request_address_cancel (void *cls,
235 const struct RequestAddressMessage *message)
237 struct GNUNET_SERVICE_Client *client = cls;
239 GAS_handle_request_address_cancel (client,
241 GNUNET_SERVICE_client_continue (client);
246 * Handle 'address add' messages from clients.
248 * @param cls client that sent the request
249 * @param m the request message
252 check_address_add (void *cls,
253 const struct AddressAddMessage *m)
256 const char *plugin_name;
257 uint16_t address_length;
258 uint16_t plugin_name_length;
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];
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')))
276 return GNUNET_SYSERR;
283 * Handle 'address add' messages from clients.
285 * @param cls client that sent the request
286 * @param message the request message
289 handle_address_add (void *cls,
290 const struct AddressAddMessage *message)
292 struct GNUNET_SERVICE_Client *client = cls;
294 GAS_handle_address_add (message);
295 GNUNET_SERVICE_client_continue (client);
300 * Handle 'address update' messages from clients.
302 * @param cls client that sent the request
303 * @param message the request message
306 handle_address_update (void *cls,
307 const struct AddressUpdateMessage *message)
309 struct GNUNET_SERVICE_Client *client = cls;
311 GAS_handle_address_update (message);
312 GNUNET_SERVICE_client_continue (client);
317 * Handle 'address destroyed' messages from clients.
319 * @param cls client that sent the request
320 * @param message the request message
323 handle_address_destroyed (void *cls,
324 const struct AddressDestroyedMessage *message)
326 struct GNUNET_SERVICE_Client *client = cls;
328 GAS_handle_address_destroyed (message);
329 GNUNET_SERVICE_client_continue (client);
334 * Check that 'change preference' message is well-formed.
336 * @param cls client that sent the request
337 * @param message the request message
338 * @return #GNUNET_OK if @a message is well-formed
341 check_preference_change (void *cls,
342 const struct ChangePreferenceMessage *message)
347 msize = ntohs (message->header.size);
348 nump = ntohl (message->num_preferences);
350 sizeof(struct ChangePreferenceMessage)
351 + nump * sizeof(struct PreferenceInformation)) ||
352 (UINT16_MAX / sizeof(struct PreferenceInformation) < nump))
355 return GNUNET_SYSERR;
362 * Handle 'change preference' messages from clients.
364 * @param cls client that sent the request
365 * @param message the request message
368 handle_preference_change (void *cls,
369 const struct ChangePreferenceMessage *message)
371 struct GNUNET_SERVICE_Client *client = cls;
373 GAS_handle_preference_change (client,
375 GNUNET_SERVICE_client_continue (client);
380 * A client connected to us. Setup the local client
384 * @param client handle of the client
385 * @param mq message queue to talk to @a client
389 client_connect_cb (void *cls,
390 struct GNUNET_SERVICE_Client *client,
391 struct GNUNET_MQ_Handle *mq)
398 * A client disconnected from us. Tear down the local client
402 * @param client handle of the client
406 client_disconnect_cb (void *cls,
407 struct GNUNET_SERVICE_Client *client,
412 GAS_scheduling_remove_client (client);
413 GAS_connectivity_remove_client (client);
414 GAS_preference_client_disconnect (client);
419 * Task run during shutdown.
424 cleanup_task (void *cls)
426 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
427 "ATS shutdown initiated\n");
428 GAS_connectivity_done ();
429 GAS_addresses_done ();
431 GAS_normalization_stop ();
432 GAS_performance_done ();
433 GAS_preference_done ();
434 GAS_reservations_done ();
435 if (NULL != GSA_stats)
437 GNUNET_STATISTICS_destroy (GSA_stats, GNUNET_NO);
444 * Process template requests.
447 * @param cfg configuration to use
448 * @param service the initialized service
452 const struct GNUNET_CONFIGURATION_Handle *cfg,
453 struct GNUNET_SERVICE_Handle *service)
455 GSA_stats = GNUNET_STATISTICS_create ("ats",
457 GAS_reservations_init ();
458 GAS_connectivity_init ();
459 GAS_preference_init ();
460 GAS_normalization_start ();
461 GAS_addresses_init ();
463 GAS_plugin_init (cfg))
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)
473 GNUNET_STATISTICS_destroy (GSA_stats,
479 GAS_performance_init ();
480 GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
486 * Define "main" method using service macro.
490 GNUNET_SERVICE_OPTION_NONE,
493 &client_disconnect_cb,
495 GNUNET_MQ_hd_fixed_size (ats_start,
496 GNUNET_MESSAGE_TYPE_ATS_START,
497 struct ClientStartMessage,
499 GNUNET_MQ_hd_fixed_size (request_address,
500 GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS,
501 struct RequestAddressMessage,
503 GNUNET_MQ_hd_fixed_size (request_address_cancel,
504 GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL,
505 struct RequestAddressMessage,
507 GNUNET_MQ_hd_fixed_size (request_address_list,
508 GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_REQUEST,
509 struct AddressListRequestMessage,
511 GNUNET_MQ_hd_var_size (address_add,
512 GNUNET_MESSAGE_TYPE_ATS_ADDRESS_ADD,
513 struct AddressAddMessage,
515 GNUNET_MQ_hd_fixed_size (address_update,
516 GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE,
517 struct AddressUpdateMessage,
519 GNUNET_MQ_hd_fixed_size (address_destroyed,
520 GNUNET_MESSAGE_TYPE_ATS_ADDRESS_DESTROYED,
521 struct AddressDestroyedMessage,
523 GNUNET_MQ_hd_fixed_size (reservation_request,
524 GNUNET_MESSAGE_TYPE_ATS_RESERVATION_REQUEST,
525 struct ReservationRequestMessage,
527 GNUNET_MQ_hd_var_size (preference_change,
528 GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_CHANGE,
529 struct ChangePreferenceMessage,
531 GNUNET_MQ_hd_var_size (feedback,
532 GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_FEEDBACK,
533 struct FeedbackPreferenceMessage,
535 GNUNET_MQ_handler_end ());
538 /* end of gnunet-service-ats.c */