aboutsummaryrefslogtreecommitdiff
path: root/src/ats/gnunet-service-ats_addresses.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ats/gnunet-service-ats_addresses.c')
-rw-r--r--src/ats/gnunet-service-ats_addresses.c717
1 files changed, 0 insertions, 717 deletions
diff --git a/src/ats/gnunet-service-ats_addresses.c b/src/ats/gnunet-service-ats_addresses.c
deleted file mode 100644
index d02efd939..000000000
--- a/src/ats/gnunet-service-ats_addresses.c
+++ /dev/null
@@ -1,717 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2015 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/**
22 * @file ats/gnunet-service-ats_addresses.c
23 * @brief ats service address management
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet-service-ats_addresses.h"
29#include "gnunet-service-ats_performance.h"
30#include "gnunet-service-ats_normalization.h"
31#include "gnunet-service-ats_plugins.h"
32
33
34/**
35 * A multihashmap to store all addresses
36 */
37struct GNUNET_CONTAINER_MultiPeerMap *GSA_addresses;
38
39
40/**
41 * Update statistic on number of addresses.
42 */
43static void
44update_addresses_stat ()
45{
46 GNUNET_STATISTICS_set (GSA_stats,
47 "# addresses",
48 GNUNET_CONTAINER_multipeermap_size (GSA_addresses),
49 GNUNET_NO);
50}
51
52
53/**
54 * Free the given address
55 *
56 * @param addr address to destroy
57 */
58static void
59free_address (struct ATS_Address *addr)
60{
61 GNUNET_assert (GNUNET_YES ==
62 GNUNET_CONTAINER_multipeermap_remove (GSA_addresses,
63 &addr->peer,
64 addr));
65 update_addresses_stat ();
66 GAS_plugin_delete_address (addr);
67 GAS_performance_notify_all_clients (&addr->peer,
68 addr->plugin,
69 addr->addr,
70 addr->addr_len,
71 GNUNET_NO,
72 NULL,
73 addr->local_address_info,
74 GNUNET_BANDWIDTH_ZERO,
75 GNUNET_BANDWIDTH_ZERO);
76 GNUNET_free (addr->plugin);
77 GNUNET_free (addr);
78}
79
80
81/**
82 * Initialize @a norm. Sets all historic values to undefined.
83 *
84 * @param norm normalization data to initialize
85 */
86static void
87init_norm (struct GAS_NormalizationInfo *norm)
88{
89 unsigned int c;
90
91 for (c = 0; c < GAS_normalization_queue_length; c++)
92 norm->atsi_abs[c] = UINT64_MAX;
93}
94
95
96/**
97 * Create a ATS_address with the given information
98 *
99 * @param peer peer
100 * @param plugin_name plugin
101 * @param plugin_addr address
102 * @param plugin_addr_len address length
103 * @param local_address_info additional local info for the address
104 * @param session_id session identifier, can never be 0
105 * @return the ATS_Address
106 */
107static struct ATS_Address *
108create_address (const struct GNUNET_PeerIdentity *peer,
109 const char *plugin_name,
110 const void *plugin_addr,
111 size_t plugin_addr_len,
112 uint32_t local_address_info,
113 uint32_t session_id)
114{
115 struct ATS_Address *aa;
116
117 aa = GNUNET_malloc (sizeof(struct ATS_Address) + plugin_addr_len);
118 aa->peer = *peer;
119 aa->addr_len = plugin_addr_len;
120 aa->addr = &aa[1];
121 GNUNET_memcpy (&aa[1],
122 plugin_addr,
123 plugin_addr_len);
124 aa->plugin = GNUNET_strdup (plugin_name);
125 aa->session_id = session_id;
126 aa->local_address_info = local_address_info;
127 init_norm (&aa->norm_delay);
128 init_norm (&aa->norm_distance);
129 init_norm (&aa->norm_utilization_in);
130 init_norm (&aa->norm_utilization_out);
131 return aa;
132}
133
134
135/**
136 * Closure for #find_address_cb()
137 */
138struct FindAddressContext
139{
140 /**
141 * Session Id to look for.
142 */
143 uint32_t session_id;
144
145 /**
146 * Where to store matching address result.
147 */
148 struct ATS_Address *exact_address;
149};
150
151
152/**
153 * Find session matching given session ID.
154 *
155 * @param cls a `struct FindAddressContext`
156 * @param key peer id
157 * @param value the address to compare with
158 * @return #GNUNET_YES to continue, #GNUNET_NO if address is found
159 */
160static int
161find_address_cb (void *cls,
162 const struct GNUNET_PeerIdentity *key,
163 void *value)
164{
165 struct FindAddressContext *fac = cls;
166 struct ATS_Address *aa = value;
167
168 if (aa->session_id == fac->session_id)
169 {
170 fac->exact_address = aa;
171 return GNUNET_NO;
172 }
173 return GNUNET_YES;
174}
175
176
177/**
178 * Find the exact address
179 *
180 * @param peer peer
181 * @param session_id session id, can never be 0
182 * @return an ATS_address or NULL
183 */
184static struct ATS_Address *
185find_exact_address (const struct GNUNET_PeerIdentity *peer,
186 uint32_t session_id)
187{
188 struct FindAddressContext fac;
189
190 fac.exact_address = NULL;
191 fac.session_id = session_id;
192 GNUNET_CONTAINER_multipeermap_get_multiple (GSA_addresses,
193 peer,
194 &find_address_cb, &fac);
195 return fac.exact_address;
196}
197
198
199/**
200 * Add a new address for a peer.
201 *
202 * @param peer peer
203 * @param plugin_name transport plugin name
204 * @param plugin_addr plugin address
205 * @param plugin_addr_len length of the plugin address in @a plugin_addr
206 * @param local_address_info the local address for the address
207 * @param session_id session id, can be 0
208 * @param prop performance information for this address
209 */
210void
211GAS_addresses_add (const struct GNUNET_PeerIdentity *peer,
212 const char *plugin_name,
213 const void *plugin_addr,
214 size_t plugin_addr_len,
215 uint32_t local_address_info,
216 uint32_t session_id,
217 const struct GNUNET_ATS_Properties *prop)
218{
219 struct ATS_Address *new_address;
220
221 if (NULL != find_exact_address (peer,
222 session_id))
223 {
224 GNUNET_break (0);
225 return;
226 }
227 GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope);
228 new_address = create_address (peer,
229 plugin_name,
230 plugin_addr,
231 plugin_addr_len,
232 local_address_info,
233 session_id);
234 /* Add a new address */
235 new_address->properties = *prop;
236 new_address->t_added = GNUNET_TIME_absolute_get ();
237 new_address->t_last_activity = GNUNET_TIME_absolute_get ();
238 GNUNET_assert (GNUNET_OK ==
239 GNUNET_CONTAINER_multipeermap_put (GSA_addresses,
240 peer,
241 new_address,
242 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
243 update_addresses_stat ();
244 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
245 "Adding new address for peer `%s' slot %u\n",
246 GNUNET_i2s (peer),
247 session_id);
248 /* Tell solver about new address */
249 GAS_plugin_solver_lock ();
250 GAS_plugin_new_address (new_address);
251 GAS_normalization_update_property (new_address); // FIXME: needed?
252 GAS_plugin_solver_unlock ();
253 /* Notify performance clients about new address */
254 GAS_performance_notify_all_clients (&new_address->peer,
255 new_address->plugin,
256 new_address->addr,
257 new_address->addr_len,
258 new_address->active,
259 &new_address->properties,
260 new_address->local_address_info,
261 GNUNET_BANDWIDTH_value_init (
262 new_address->assigned_bw_out),
263 GNUNET_BANDWIDTH_value_init (
264 new_address->assigned_bw_in));
265}
266
267
268/**
269 * Update an address with new performance information for a peer.
270 *
271 * @param peer peer
272 * @param session_id session id, never 0
273 * @param prop performance information for this address
274 */
275void
276GAS_addresses_update (const struct GNUNET_PeerIdentity *peer,
277 uint32_t session_id,
278 const struct GNUNET_ATS_Properties *prop)
279{
280 struct ATS_Address *aa;
281
282 /* Get existing address */
283 aa = find_exact_address (peer,
284 session_id);
285 if (NULL == aa)
286 {
287 GNUNET_break (0);
288 return;
289 }
290 if (NULL == aa->solver_information)
291 {
292 GNUNET_break (0);
293 return;
294 }
295 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
296 "Received ADDRESS_UPDATE for peer `%s' slot %u\n",
297 GNUNET_i2s (peer),
298 (unsigned int) session_id);
299 GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope);
300 /* Update address */
301 aa->t_last_activity = GNUNET_TIME_absolute_get ();
302 aa->properties = *prop;
303 /* Notify performance clients about updated address */
304 GAS_performance_notify_all_clients (&aa->peer,
305 aa->plugin,
306 aa->addr,
307 aa->addr_len,
308 aa->active,
309 prop,
310 aa->local_address_info,
311 GNUNET_BANDWIDTH_value_init (
312 aa->assigned_bw_out),
313 GNUNET_BANDWIDTH_value_init (
314 aa->assigned_bw_in));
315
316 GAS_normalization_update_property (aa);
317}
318
319
320/**
321 * Remove an address for a peer.
322 *
323 * @param peer peer
324 * @param session_id session id, can never be 0
325 */
326void
327GAS_addresses_destroy (const struct GNUNET_PeerIdentity *peer,
328 uint32_t session_id)
329{
330 struct ATS_Address *ea;
331
332 /* Get existing address */
333 ea = find_exact_address (peer,
334 session_id);
335 if (NULL == ea)
336 {
337 GNUNET_break (0);
338 return;
339 }
340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
341 "Received ADDRESS_DESTROYED for peer `%s' session %u\n",
342 GNUNET_i2s (peer),
343 session_id);
344 free_address (ea);
345}
346
347
348/**
349 * Initialize address subsystem. The addresses subsystem manages the addresses
350 * known and current performance information. It has a solver component
351 * responsible for the resource allocation. It tells the solver about changes
352 * and receives updates when the solver changes the resource allocation.
353 */
354void
355GAS_addresses_init ()
356{
357 GSA_addresses
358 = GNUNET_CONTAINER_multipeermap_create (128,
359 GNUNET_NO);
360 update_addresses_stat ();
361}
362
363
364/**
365 * Destroy all addresses iterator
366 *
367 * @param cls NULL
368 * @param key peer identity (unused)
369 * @param value the 'struct ATS_Address' to free
370 * @return #GNUNET_OK (continue to iterate)
371 */
372static int
373destroy_all_address_it (void *cls,
374 const struct GNUNET_PeerIdentity *key,
375 void *value)
376{
377 struct ATS_Address *aa = value;
378
379 free_address (aa);
380 return GNUNET_OK;
381}
382
383
384/**
385 * Remove all addresses
386 */
387void
388GAS_addresses_destroy_all ()
389{
390 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
391 "Destroying all addresses\n");
392 if (NULL == GSA_addresses)
393 return;
394 if (0 ==
395 GNUNET_CONTAINER_multipeermap_size (GSA_addresses))
396 return;
397 GAS_plugin_solver_lock ();
398 GNUNET_CONTAINER_multipeermap_iterate (GSA_addresses,
399 &destroy_all_address_it,
400 NULL);
401 GAS_plugin_solver_unlock ();
402}
403
404
405/**
406 * Shutdown address subsystem.
407 */
408void
409GAS_addresses_done ()
410{
411 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
412 "Shutting down addresses\n");
413 GAS_plugin_solver_lock ();
414 GAS_addresses_destroy_all ();
415 GAS_plugin_solver_unlock ();
416 GNUNET_CONTAINER_multipeermap_destroy (GSA_addresses);
417 GSA_addresses = NULL;
418}
419
420
421/**
422 * Closure for #peerinfo_it().
423 */
424struct PeerInfoIteratorContext
425{
426 /**
427 * Function to call for each address.
428 */
429 GNUNET_ATS_PeerInfo_Iterator it;
430
431 /**
432 * Closure for @e it.
433 */
434 void *it_cls;
435};
436
437
438/**
439 * Iterator to iterate over a peer's addresses
440 *
441 * @param cls a `struct PeerInfoIteratorContext`
442 * @param key the peer id
443 * @param value the `struct ATS_address`
444 * @return #GNUNET_OK to continue
445 */
446static int
447peerinfo_it (void *cls,
448 const struct GNUNET_PeerIdentity *key,
449 void *value)
450{
451 struct PeerInfoIteratorContext *pi_ctx = cls;
452 struct ATS_Address *addr = value;
453
454 pi_ctx->it (pi_ctx->it_cls,
455 &addr->peer,
456 addr->plugin,
457 addr->addr,
458 addr->addr_len,
459 addr->active,
460 &addr->properties,
461 addr->local_address_info,
462 GNUNET_BANDWIDTH_value_init (addr->assigned_bw_out),
463 GNUNET_BANDWIDTH_value_init (addr->assigned_bw_in));
464 return GNUNET_OK;
465}
466
467
468/**
469 * Return information all peers currently known to ATS
470 *
471 * @param peer the respective peer, NULL for 'all' peers
472 * @param pi_it the iterator to call for every peer
473 * @param pi_it_cls the closure for @a pi_it
474 */
475void
476GAS_addresses_get_peer_info (const struct GNUNET_PeerIdentity *peer,
477 GNUNET_ATS_PeerInfo_Iterator pi_it,
478 void *pi_it_cls)
479{
480 struct PeerInfoIteratorContext pi_ctx;
481
482 if (NULL == pi_it)
483 {
484 /* does not make sense without callback */
485 GNUNET_break (0);
486 return;
487 }
488 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
489 "Returning information for %s from a total of %u known addresses\n",
490 (NULL == peer)
491 ? "all peers"
492 : GNUNET_i2s (peer),
493 (unsigned int) GNUNET_CONTAINER_multipeermap_size (
494 GSA_addresses));
495 pi_ctx.it = pi_it;
496 pi_ctx.it_cls = pi_it_cls;
497 if (NULL == peer)
498 GNUNET_CONTAINER_multipeermap_iterate (GSA_addresses,
499 &peerinfo_it,
500 &pi_ctx);
501 else
502 GNUNET_CONTAINER_multipeermap_get_multiple (GSA_addresses,
503 peer,
504 &peerinfo_it, &pi_ctx);
505 pi_it (pi_it_cls,
506 NULL, NULL, NULL, 0,
507 GNUNET_NO,
508 NULL,
509 GNUNET_HELLO_ADDRESS_INFO_NONE,
510 GNUNET_BANDWIDTH_ZERO,
511 GNUNET_BANDWIDTH_ZERO);
512}
513
514
515/**
516 * Information we need for the callbacks to return a list of addresses
517 * back to the client.
518 */
519struct AddressIteration
520{
521 /**
522 * Actual handle to the client.
523 */
524 struct GNUNET_SERVICE_Client *client;
525
526 /**
527 * Are we sending all addresses, or only those that are active?
528 */
529 int all;
530
531 /**
532 * Which ID should be included in the response?
533 */
534 uint32_t id;
535};
536
537
538/**
539 * Send a #GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE with the
540 * given address details to the client identified in @a ai.
541 *
542 * @param ai our address information context (identifies the client)
543 * @param id the peer id this address is for
544 * @param plugin_name name of the plugin that supports this address
545 * @param plugin_addr address
546 * @param plugin_addr_len length of @a plugin_addr
547 * @param active #GNUNET_YES if this address is actively used
548 * @param prop performance information
549 * @param local_address_info flags for the address
550 * @param bandwidth_out current outbound bandwidth assigned to address
551 * @param bandwidth_in current inbound bandwidth assigned to address
552 */
553static void
554transmit_req_addr (struct AddressIteration *ai,
555 const struct GNUNET_PeerIdentity *id,
556 const char *plugin_name,
557 const void *plugin_addr,
558 size_t plugin_addr_len,
559 int active,
560 const struct GNUNET_ATS_Properties *prop,
561 enum GNUNET_HELLO_AddressInfo local_address_info,
562 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
563 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
564
565{
566 struct GNUNET_MQ_Envelope *env;
567 struct PeerInformationMessage *msg;
568 char *addrp;
569 size_t plugin_name_length;
570 size_t msize;
571
572 if (NULL != plugin_name)
573 plugin_name_length = strlen (plugin_name) + 1;
574 else
575 plugin_name_length = 0;
576 msize = plugin_addr_len + plugin_name_length;
577
578 GNUNET_assert (sizeof(struct PeerInformationMessage) + msize
579 < GNUNET_MAX_MESSAGE_SIZE);
580 env = GNUNET_MQ_msg_extra (msg,
581 msize,
582 GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE);
583 msg->id = htonl (ai->id);
584 if (NULL != id)
585 msg->peer = *id;
586 msg->address_length = htons (plugin_addr_len);
587 msg->address_active = ntohl (active);
588 msg->plugin_name_length = htons (plugin_name_length);
589 msg->bandwidth_out = bandwidth_out;
590 msg->bandwidth_in = bandwidth_in;
591 if (NULL != prop)
592 GNUNET_ATS_properties_hton (&msg->properties,
593 prop);
594 msg->address_local_info = htonl ((uint32_t) local_address_info);
595 addrp = (char *) &msg[1];
596 GNUNET_memcpy (addrp,
597 plugin_addr,
598 plugin_addr_len);
599 if (NULL != plugin_name)
600 strcpy (&addrp[plugin_addr_len],
601 plugin_name);
602 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (ai->client),
603 env);
604}
605
606
607/**
608 * Iterator for #GAS_addresses_get_peer_info(), called with peer-specific
609 * information to be passed back to the client.
610 *
611 * @param cls closure with our `struct AddressIteration *`
612 * @param id the peer id
613 * @param plugin_name plugin name
614 * @param plugin_addr address
615 * @param plugin_addr_len length of @a plugin_addr
616 * @param active is address actively used
617 * @param prop performance information
618 * @param local_address_info additional local info for the address
619 * @param bandwidth_out current outbound bandwidth assigned to address
620 * @param bandwidth_in current inbound bandwidth assigned to address
621 */
622static void
623req_addr_peerinfo_it (void *cls,
624 const struct GNUNET_PeerIdentity *id,
625 const char *plugin_name,
626 const void *plugin_addr,
627 size_t plugin_addr_len,
628 int active,
629 const struct GNUNET_ATS_Properties *prop,
630 enum GNUNET_HELLO_AddressInfo local_address_info,
631 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
632 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
633{
634 struct AddressIteration *ai = cls;
635
636 if ((NULL == id) &&
637 (NULL == plugin_name) &&
638 (NULL == plugin_addr))
639 {
640 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
641 "Address iteration done for one peer\n");
642 return;
643 }
644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
645 "Callback for %s peer `%s' plugin `%s' BW out %u, BW in %u\n",
646 (active == GNUNET_YES) ? "ACTIVE" : "INACTIVE",
647 GNUNET_i2s (id),
648 plugin_name,
649 (unsigned int) ntohl (bandwidth_out.value__),
650 (unsigned int) ntohl (bandwidth_in.value__));
651 /* Transmit result (either if address is active, or if
652 client wanted all addresses) */
653 if ((GNUNET_YES != ai->all) &&
654 (GNUNET_YES != active))
655 return;
656 transmit_req_addr (ai,
657 id,
658 plugin_name,
659 plugin_addr, plugin_addr_len,
660 active,
661 prop,
662 local_address_info,
663 bandwidth_out,
664 bandwidth_in);
665}
666
667
668/**
669 * Handle 'address list request' messages from clients.
670 *
671 * @param cls client that sent the request
672 * @param alrm the request message
673 */
674void
675GAS_handle_request_address_list (struct GNUNET_SERVICE_Client *client,
676 const struct AddressListRequestMessage *alrm)
677{
678 struct AddressIteration ai;
679 struct GNUNET_PeerIdentity allzeros;
680
681 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
682 "Received ADDRESSLIST_REQUEST message\n");
683 ai.all = ntohl (alrm->all);
684 ai.id = ntohl (alrm->id);
685 ai.client = client;
686
687 memset (&allzeros,
688 '\0',
689 sizeof(struct GNUNET_PeerIdentity));
690 if (GNUNET_YES == GNUNET_is_zero (&alrm->peer))
691 {
692 /* Return addresses for all peers */
693 GAS_addresses_get_peer_info (NULL,
694 &req_addr_peerinfo_it,
695 &ai);
696 }
697 else
698 {
699 /* Return addresses for a specific peer */
700 GAS_addresses_get_peer_info (&alrm->peer,
701 &req_addr_peerinfo_it,
702 &ai);
703 }
704 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
705 "Finished handling `%s' message\n",
706 "ADDRESSLIST_REQUEST");
707 transmit_req_addr (&ai,
708 NULL, NULL, NULL,
709 0, GNUNET_NO,
710 NULL,
711 GNUNET_HELLO_ADDRESS_INFO_NONE,
712 GNUNET_BANDWIDTH_ZERO,
713 GNUNET_BANDWIDTH_ZERO);
714}
715
716
717/* end of gnunet-service-ats_addresses.c */