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.c686
1 files changed, 0 insertions, 686 deletions
diff --git a/src/ats/gnunet-service-ats_addresses.c b/src/ats/gnunet-service-ats_addresses.c
deleted file mode 100644
index 9c9856094..000000000
--- a/src/ats/gnunet-service-ats_addresses.c
+++ /dev/null
@@ -1,686 +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
199void
200GAS_addresses_add (const struct GNUNET_PeerIdentity *peer,
201 const char *plugin_name,
202 const void *plugin_addr,
203 size_t plugin_addr_len,
204 uint32_t local_address_info,
205 uint32_t session_id,
206 const struct GNUNET_ATS_Properties *prop)
207{
208 struct ATS_Address *new_address;
209
210 if (NULL != find_exact_address (peer,
211 session_id))
212 {
213 GNUNET_break (0);
214 return;
215 }
216 GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope);
217 new_address = create_address (peer,
218 plugin_name,
219 plugin_addr,
220 plugin_addr_len,
221 local_address_info,
222 session_id);
223 /* Add a new address */
224 new_address->properties = *prop;
225 new_address->t_added = GNUNET_TIME_absolute_get ();
226 new_address->t_last_activity = GNUNET_TIME_absolute_get ();
227 GNUNET_assert (GNUNET_OK ==
228 GNUNET_CONTAINER_multipeermap_put (GSA_addresses,
229 peer,
230 new_address,
231 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
232 update_addresses_stat ();
233 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
234 "Adding new address for peer `%s' slot %u\n",
235 GNUNET_i2s (peer),
236 session_id);
237 /* Tell solver about new address */
238 GAS_plugin_solver_lock ();
239 GAS_plugin_new_address (new_address);
240 GAS_normalization_update_property (new_address); // FIXME: needed?
241 GAS_plugin_solver_unlock ();
242 /* Notify performance clients about new address */
243 GAS_performance_notify_all_clients (&new_address->peer,
244 new_address->plugin,
245 new_address->addr,
246 new_address->addr_len,
247 new_address->active,
248 &new_address->properties,
249 new_address->local_address_info,
250 GNUNET_BANDWIDTH_value_init (
251 new_address->assigned_bw_out),
252 GNUNET_BANDWIDTH_value_init (
253 new_address->assigned_bw_in));
254}
255
256
257void
258GAS_addresses_update (const struct GNUNET_PeerIdentity *peer,
259 uint32_t session_id,
260 const struct GNUNET_ATS_Properties *prop)
261{
262 struct ATS_Address *aa;
263
264 /* Get existing address */
265 aa = find_exact_address (peer,
266 session_id);
267 if (NULL == aa)
268 {
269 GNUNET_break (0);
270 return;
271 }
272 if (NULL == aa->solver_information)
273 {
274 GNUNET_break (0);
275 return;
276 }
277 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
278 "Received ADDRESS_UPDATE for peer `%s' slot %u\n",
279 GNUNET_i2s (peer),
280 (unsigned int) session_id);
281 GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope);
282 /* Update address */
283 aa->t_last_activity = GNUNET_TIME_absolute_get ();
284 aa->properties = *prop;
285 /* Notify performance clients about updated address */
286 GAS_performance_notify_all_clients (&aa->peer,
287 aa->plugin,
288 aa->addr,
289 aa->addr_len,
290 aa->active,
291 prop,
292 aa->local_address_info,
293 GNUNET_BANDWIDTH_value_init (
294 aa->assigned_bw_out),
295 GNUNET_BANDWIDTH_value_init (
296 aa->assigned_bw_in));
297
298 GAS_normalization_update_property (aa);
299}
300
301
302/**
303 * Remove an address for a peer.
304 *
305 * @param peer peer
306 * @param session_id session id, can never be 0
307 */
308void
309GAS_addresses_destroy (const struct GNUNET_PeerIdentity *peer,
310 uint32_t session_id)
311{
312 struct ATS_Address *ea;
313
314 /* Get existing address */
315 ea = find_exact_address (peer,
316 session_id);
317 if (NULL == ea)
318 {
319 GNUNET_break (0);
320 return;
321 }
322 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
323 "Received ADDRESS_DESTROYED for peer `%s' session %u\n",
324 GNUNET_i2s (peer),
325 session_id);
326 free_address (ea);
327}
328
329
330/**
331 * Initialize address subsystem. The addresses subsystem manages the addresses
332 * known and current performance information. It has a solver component
333 * responsible for the resource allocation. It tells the solver about changes
334 * and receives updates when the solver changes the resource allocation.
335 */
336void
337GAS_addresses_init ()
338{
339 GSA_addresses
340 = GNUNET_CONTAINER_multipeermap_create (128,
341 GNUNET_NO);
342 update_addresses_stat ();
343}
344
345
346/**
347 * Destroy all addresses iterator
348 *
349 * @param cls NULL
350 * @param key peer identity (unused)
351 * @param value the 'struct ATS_Address' to free
352 * @return #GNUNET_OK (continue to iterate)
353 */
354static int
355destroy_all_address_it (void *cls,
356 const struct GNUNET_PeerIdentity *key,
357 void *value)
358{
359 struct ATS_Address *aa = value;
360
361 free_address (aa);
362 return GNUNET_OK;
363}
364
365
366/**
367 * Remove all addresses
368 */
369void
370GAS_addresses_destroy_all ()
371{
372 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
373 "Destroying all addresses\n");
374 if (NULL == GSA_addresses)
375 return;
376 if (0 ==
377 GNUNET_CONTAINER_multipeermap_size (GSA_addresses))
378 return;
379 GAS_plugin_solver_lock ();
380 GNUNET_CONTAINER_multipeermap_iterate (GSA_addresses,
381 &destroy_all_address_it,
382 NULL);
383 GAS_plugin_solver_unlock ();
384}
385
386
387/**
388 * Shutdown address subsystem.
389 */
390void
391GAS_addresses_done ()
392{
393 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
394 "Shutting down addresses\n");
395 GAS_plugin_solver_lock ();
396 GAS_addresses_destroy_all ();
397 GAS_plugin_solver_unlock ();
398 GNUNET_CONTAINER_multipeermap_destroy (GSA_addresses);
399 GSA_addresses = NULL;
400}
401
402
403/**
404 * Closure for #peerinfo_it().
405 */
406struct PeerInfoIteratorContext
407{
408 /**
409 * Function to call for each address.
410 */
411 GNUNET_ATS_PeerInfo_Iterator it;
412
413 /**
414 * Closure for @e it.
415 */
416 void *it_cls;
417};
418
419
420/**
421 * Iterator to iterate over a peer's addresses
422 *
423 * @param cls a `struct PeerInfoIteratorContext`
424 * @param key the peer id
425 * @param value the `struct ATS_address`
426 * @return #GNUNET_OK to continue
427 */
428static int
429peerinfo_it (void *cls,
430 const struct GNUNET_PeerIdentity *key,
431 void *value)
432{
433 struct PeerInfoIteratorContext *pi_ctx = cls;
434 struct ATS_Address *addr = value;
435
436 pi_ctx->it (pi_ctx->it_cls,
437 &addr->peer,
438 addr->plugin,
439 addr->addr,
440 addr->addr_len,
441 addr->active,
442 &addr->properties,
443 addr->local_address_info,
444 GNUNET_BANDWIDTH_value_init (addr->assigned_bw_out),
445 GNUNET_BANDWIDTH_value_init (addr->assigned_bw_in));
446 return GNUNET_OK;
447}
448
449
450void
451GAS_addresses_get_peer_info (const struct GNUNET_PeerIdentity *peer,
452 GNUNET_ATS_PeerInfo_Iterator pi_it,
453 void *pi_it_cls)
454{
455 struct PeerInfoIteratorContext pi_ctx;
456
457 if (NULL == pi_it)
458 {
459 /* does not make sense without callback */
460 GNUNET_break (0);
461 return;
462 }
463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
464 "Returning information for %s from a total of %u known addresses\n",
465 (NULL == peer)
466 ? "all peers"
467 : GNUNET_i2s (peer),
468 (unsigned int) GNUNET_CONTAINER_multipeermap_size (
469 GSA_addresses));
470 pi_ctx.it = pi_it;
471 pi_ctx.it_cls = pi_it_cls;
472 if (NULL == peer)
473 GNUNET_CONTAINER_multipeermap_iterate (GSA_addresses,
474 &peerinfo_it,
475 &pi_ctx);
476 else
477 GNUNET_CONTAINER_multipeermap_get_multiple (GSA_addresses,
478 peer,
479 &peerinfo_it, &pi_ctx);
480 pi_it (pi_it_cls,
481 NULL, NULL, NULL, 0,
482 GNUNET_NO,
483 NULL,
484 GNUNET_HELLO_ADDRESS_INFO_NONE,
485 GNUNET_BANDWIDTH_ZERO,
486 GNUNET_BANDWIDTH_ZERO);
487}
488
489
490/**
491 * Information we need for the callbacks to return a list of addresses
492 * back to the client.
493 */
494struct AddressIteration
495{
496 /**
497 * Actual handle to the client.
498 */
499 struct GNUNET_SERVICE_Client *client;
500
501 /**
502 * Are we sending all addresses, or only those that are active?
503 */
504 int all;
505
506 /**
507 * Which ID should be included in the response?
508 */
509 uint32_t id;
510};
511
512
513/**
514 * Send a #GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE with the
515 * given address details to the client identified in @a ai.
516 *
517 * @param ai our address information context (identifies the client)
518 * @param id the peer id this address is for
519 * @param plugin_name name of the plugin that supports this address
520 * @param plugin_addr address
521 * @param plugin_addr_len length of @a plugin_addr
522 * @param active #GNUNET_YES if this address is actively used
523 * @param prop performance information
524 * @param local_address_info flags for the address
525 * @param bandwidth_out current outbound bandwidth assigned to address
526 * @param bandwidth_in current inbound bandwidth assigned to address
527 */
528static void
529transmit_req_addr (struct AddressIteration *ai,
530 const struct GNUNET_PeerIdentity *id,
531 const char *plugin_name,
532 const void *plugin_addr,
533 size_t plugin_addr_len,
534 int active,
535 const struct GNUNET_ATS_Properties *prop,
536 enum GNUNET_HELLO_AddressInfo local_address_info,
537 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
538 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
539
540{
541 struct GNUNET_MQ_Envelope *env;
542 struct PeerInformationMessage *msg;
543 char *addrp;
544 size_t plugin_name_length;
545 size_t msize;
546
547 if (NULL != plugin_name)
548 plugin_name_length = strlen (plugin_name) + 1;
549 else
550 plugin_name_length = 0;
551 msize = plugin_addr_len + plugin_name_length;
552
553 GNUNET_assert (sizeof(struct PeerInformationMessage) + msize
554 < GNUNET_MAX_MESSAGE_SIZE);
555 env = GNUNET_MQ_msg_extra (msg,
556 msize,
557 GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE);
558 msg->id = htonl (ai->id);
559 if (NULL != id)
560 msg->peer = *id;
561 msg->address_length = htons (plugin_addr_len);
562 msg->address_active = ntohl (active);
563 msg->plugin_name_length = htons (plugin_name_length);
564 msg->bandwidth_out = bandwidth_out;
565 msg->bandwidth_in = bandwidth_in;
566 if (NULL != prop)
567 GNUNET_ATS_properties_hton (&msg->properties,
568 prop);
569 msg->address_local_info = htonl ((uint32_t) local_address_info);
570 addrp = (char *) &msg[1];
571 GNUNET_memcpy (addrp,
572 plugin_addr,
573 plugin_addr_len);
574 if (NULL != plugin_name)
575 strcpy (&addrp[plugin_addr_len],
576 plugin_name);
577 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (ai->client),
578 env);
579}
580
581
582/**
583 * Iterator for #GAS_addresses_get_peer_info(), called with peer-specific
584 * information to be passed back to the client.
585 *
586 * @param cls closure with our `struct AddressIteration *`
587 * @param id the peer id
588 * @param plugin_name plugin name
589 * @param plugin_addr address
590 * @param plugin_addr_len length of @a plugin_addr
591 * @param active is address actively used
592 * @param prop performance information
593 * @param local_address_info additional local info for the address
594 * @param bandwidth_out current outbound bandwidth assigned to address
595 * @param bandwidth_in current inbound bandwidth assigned to address
596 */
597static void
598req_addr_peerinfo_it (void *cls,
599 const struct GNUNET_PeerIdentity *id,
600 const char *plugin_name,
601 const void *plugin_addr,
602 size_t plugin_addr_len,
603 int active,
604 const struct GNUNET_ATS_Properties *prop,
605 enum GNUNET_HELLO_AddressInfo local_address_info,
606 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
607 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
608{
609 struct AddressIteration *ai = cls;
610
611 if ((NULL == id) &&
612 (NULL == plugin_name) &&
613 (NULL == plugin_addr))
614 {
615 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
616 "Address iteration done for one peer\n");
617 return;
618 }
619 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
620 "Callback for %s peer `%s' plugin `%s' BW out %u, BW in %u\n",
621 (active == GNUNET_YES) ? "ACTIVE" : "INACTIVE",
622 GNUNET_i2s (id),
623 plugin_name,
624 (unsigned int) ntohl (bandwidth_out.value__),
625 (unsigned int) ntohl (bandwidth_in.value__));
626 /* Transmit result (either if address is active, or if
627 client wanted all addresses) */
628 if ((GNUNET_YES != ai->all) &&
629 (GNUNET_YES != active))
630 return;
631 transmit_req_addr (ai,
632 id,
633 plugin_name,
634 plugin_addr, plugin_addr_len,
635 active,
636 prop,
637 local_address_info,
638 bandwidth_out,
639 bandwidth_in);
640}
641
642
643void
644GAS_handle_request_address_list (struct GNUNET_SERVICE_Client *client,
645 const struct AddressListRequestMessage *alrm)
646{
647 struct AddressIteration ai;
648 struct GNUNET_PeerIdentity allzeros;
649
650 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
651 "Received ADDRESSLIST_REQUEST message\n");
652 ai.all = ntohl (alrm->all);
653 ai.id = ntohl (alrm->id);
654 ai.client = client;
655
656 memset (&allzeros,
657 '\0',
658 sizeof(struct GNUNET_PeerIdentity));
659 if (GNUNET_YES == GNUNET_is_zero (&alrm->peer))
660 {
661 /* Return addresses for all peers */
662 GAS_addresses_get_peer_info (NULL,
663 &req_addr_peerinfo_it,
664 &ai);
665 }
666 else
667 {
668 /* Return addresses for a specific peer */
669 GAS_addresses_get_peer_info (&alrm->peer,
670 &req_addr_peerinfo_it,
671 &ai);
672 }
673 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
674 "Finished handling `%s' message\n",
675 "ADDRESSLIST_REQUEST");
676 transmit_req_addr (&ai,
677 NULL, NULL, NULL,
678 0, GNUNET_NO,
679 NULL,
680 GNUNET_HELLO_ADDRESS_INFO_NONE,
681 GNUNET_BANDWIDTH_ZERO,
682 GNUNET_BANDWIDTH_ZERO);
683}
684
685
686/* end of gnunet-service-ats_addresses.c */