aboutsummaryrefslogtreecommitdiff
path: root/src/ats/ats_api_scheduling.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ats/ats_api_scheduling.c')
-rw-r--r--src/ats/ats_api_scheduling.c801
1 files changed, 0 insertions, 801 deletions
diff --git a/src/ats/ats_api_scheduling.c b/src/ats/ats_api_scheduling.c
deleted file mode 100644
index ea4b27653..000000000
--- a/src/ats/ats_api_scheduling.c
+++ /dev/null
@@ -1,801 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-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 * @file ats/ats_api_scheduling.c
22 * @brief automatic transport selection and outbound bandwidth determination
23 * @author Christian Grothoff
24 * @author Matthias Wachs
25 *
26 * TODO:
27 * - we could avoid a linear scan over the
28 * active addresses in some cases, so if
29 * there is need, we can still optimize here
30 * - we might want to split off the logic to
31 * determine LAN vs. WAN, as it has nothing
32 * to do with accessing the ATS service.
33 */
34#include "platform.h"
35#include "gnunet_ats_service.h"
36#include "ats.h"
37
38/**
39 * How frequently do we scan the interfaces for changes to the addresses?
40 */
41#define INTERFACE_PROCESSING_INTERVAL GNUNET_TIME_relative_multiply ( \
42 GNUNET_TIME_UNIT_MINUTES, 2)
43
44#define LOG(kind, ...) GNUNET_log_from (kind, "ats-scheduling-api", __VA_ARGS__)
45
46/**
47 * Session ID we use if there is no session / slot.
48 */
49#define NOT_FOUND 0
50
51
52/**
53 * Information we track per address, incoming or outgoing. It also
54 * doesn't matter if we have a session, any address that ATS is
55 * allowed to suggest right now should be tracked.
56 */
57struct GNUNET_ATS_AddressRecord
58{
59 /**
60 * Scheduling handle this address record belongs to.
61 */
62 struct GNUNET_ATS_SchedulingHandle *sh;
63
64 /**
65 * Address data.
66 */
67 struct GNUNET_HELLO_Address *address;
68
69 /**
70 * Session handle. NULL if we have an address but no
71 * active session for this address.
72 */
73 struct GNUNET_ATS_Session *session;
74
75 /**
76 * Performance data about the address.
77 */
78 struct GNUNET_ATS_PropertiesNBO properties;
79
80 /**
81 * Which slot (index) in the session array does
82 * this record correspond to?
83 * FIXME: a linear search on this is really crappy!
84 * Maybe switch to a 64-bit global counter and be
85 * done with it? Or does that then cause too much
86 * trouble on the ATS-service side?
87 */
88 uint32_t slot;
89
90 /**
91 * We're about to destroy this address record, just ATS does
92 * not know this yet. Once ATS confirms its destruction,
93 * we can clean up.
94 */
95 int in_destroy;
96};
97
98
99/**
100 * Handle to the ATS subsystem for bandwidth/transport scheduling information.
101 */
102struct GNUNET_ATS_SchedulingHandle
103{
104 /**
105 * Our configuration.
106 */
107 const struct GNUNET_CONFIGURATION_Handle *cfg;
108
109 /**
110 * Callback to invoke on suggestions.
111 */
112 GNUNET_ATS_AddressSuggestionCallback suggest_cb;
113
114 /**
115 * Closure for @e suggest_cb.
116 */
117 void *suggest_cb_cls;
118
119 /**
120 * Message queue for sending requests to the ATS service.
121 */
122 struct GNUNET_MQ_Handle *mq;
123
124 /**
125 * Array of session objects (we need to translate them to numbers and back
126 * for the protocol; the offset in the array is the session number on the
127 * network). Index 0 is always NULL and reserved to represent the NULL pointer.
128 * Unused entries are also NULL.
129 */
130 struct GNUNET_ATS_AddressRecord **session_array;
131
132 /**
133 * Task to trigger reconnect.
134 */
135 struct GNUNET_SCHEDULER_Task *task;
136
137 /**
138 * Reconnect backoff delay.
139 */
140 struct GNUNET_TIME_Relative backoff;
141
142 /**
143 * Size of the @e session_array.
144 */
145 unsigned int session_array_size;
146};
147
148
149/**
150 * Re-establish the connection to the ATS service.
151 *
152 * @param sh handle to use to re-connect.
153 */
154static void
155reconnect (struct GNUNET_ATS_SchedulingHandle *sh);
156
157
158/**
159 * Re-establish the connection to the ATS service.
160 *
161 * @param cls handle to use to re-connect.
162 */
163static void
164reconnect_task (void *cls)
165{
166 struct GNUNET_ATS_SchedulingHandle *sh = cls;
167
168 sh->task = NULL;
169 reconnect (sh);
170}
171
172
173/**
174 * Disconnect from ATS and then reconnect.
175 *
176 * @param sh our handle
177 */
178static void
179force_reconnect (struct GNUNET_ATS_SchedulingHandle *sh)
180{
181 if (NULL != sh->mq)
182 {
183 GNUNET_MQ_destroy (sh->mq);
184 sh->mq = NULL;
185 }
186 sh->suggest_cb (sh->suggest_cb_cls,
187 NULL, NULL, NULL,
188 GNUNET_BANDWIDTH_ZERO,
189 GNUNET_BANDWIDTH_ZERO);
190 sh->backoff = GNUNET_TIME_STD_BACKOFF (sh->backoff);
191 sh->task = GNUNET_SCHEDULER_add_delayed (sh->backoff,
192 &reconnect_task,
193 sh);
194}
195
196
197/**
198 * Find the session object corresponding to the given session ID.
199 *
200 * @param sh our handle
201 * @param session_id current session ID
202 * @param peer peer the session belongs to
203 * @return the session object (or NULL)
204 */
205static struct GNUNET_ATS_AddressRecord *
206find_session (struct GNUNET_ATS_SchedulingHandle *sh,
207 uint32_t session_id,
208 const struct GNUNET_PeerIdentity *peer)
209{
210 struct GNUNET_ATS_AddressRecord *ar;
211
212 if (session_id >= sh->session_array_size)
213 {
214 GNUNET_break (0);
215 return NULL;
216 }
217 if (0 == session_id)
218 return NULL;
219 ar = sh->session_array[session_id];
220 if (NULL == ar)
221 {
222 GNUNET_break (0);
223 return NULL;
224 }
225 if (NULL == ar->address)
226 {
227 /* address was destroyed in the meantime, this can happen
228 as we communicate asynchronously with the ATS service. */
229 return NULL;
230 }
231 if (0 != GNUNET_memcmp (peer,
232 &ar->address->peer))
233 {
234 GNUNET_break (0);
235 return NULL;
236 }
237 return ar;
238}
239
240
241/**
242 * Get an available session ID.
243 *
244 * @param sh our handle
245 * @return an unused slot, but never NOT_FOUND (0)
246 */
247static uint32_t
248find_empty_session_slot (struct GNUNET_ATS_SchedulingHandle *sh)
249{
250 static uint32_t off;
251 uint32_t i;
252
253 GNUNET_assert (0 != sh->session_array_size);
254 i = 0;
255 while (((NOT_FOUND == off) ||
256 (NULL != sh->session_array[off % sh->session_array_size])) &&
257 (i < sh->session_array_size))
258 {
259 off++;
260 i++;
261 }
262 if ((NOT_FOUND != off % sh->session_array_size) &&
263 (NULL == sh->session_array[off % sh->session_array_size]))
264 return off;
265 i = sh->session_array_size;
266 GNUNET_array_grow (sh->session_array,
267 sh->session_array_size,
268 sh->session_array_size * 2);
269 return i;
270}
271
272
273/**
274 * Get the ID for the given session object.
275 *
276 * @param sh our handle
277 * @param session session object
278 * @param address the address we are looking for
279 * @return the session id or NOT_FOUND for error
280 */
281static uint32_t
282find_session_id (struct GNUNET_ATS_SchedulingHandle *sh,
283 struct GNUNET_ATS_Session *session,
284 const struct GNUNET_HELLO_Address *address)
285{
286 uint32_t i;
287
288 if (NULL == address)
289 {
290 GNUNET_break (0);
291 return NOT_FOUND;
292 }
293 for (i = 1; i < sh->session_array_size; i++)
294 if ((NULL != sh->session_array[i]) &&
295 (GNUNET_NO == sh->session_array[i]->in_destroy) &&
296 ((session == sh->session_array[i]->session) ||
297 (NULL == sh->session_array[i]->session)) &&
298 (0 == GNUNET_memcmp (&address->peer,
299 &sh->session_array[i]->address->peer)) &&
300 (0 == GNUNET_HELLO_address_cmp (address,
301 sh->session_array[i]->address)))
302 return i;
303 return NOT_FOUND;
304}
305
306
307/**
308 * Release the session slot from the session table (ATS service is
309 * also done using it).
310 *
311 * @param sh our handle
312 * @param session_id identifies session that is no longer valid
313 */
314static void
315release_session (struct GNUNET_ATS_SchedulingHandle *sh,
316 uint32_t session_id)
317{
318 struct GNUNET_ATS_AddressRecord *ar;
319
320 if (NOT_FOUND == session_id)
321 return;
322 if (session_id >= sh->session_array_size)
323 {
324 GNUNET_break (0);
325 force_reconnect (sh);
326 return;
327 }
328 /* this slot should have been removed from remove_session before */
329 ar = sh->session_array[session_id];
330 if (NULL != ar->session)
331 {
332 GNUNET_break (0);
333 force_reconnect (sh);
334 return;
335 }
336 GNUNET_HELLO_address_free (ar->address);
337 GNUNET_free (ar);
338 sh->session_array[session_id] = NULL;
339}
340
341
342/**
343 * Type of a function to call when we receive a session release
344 * message from the service.
345 *
346 * @param cls the `struct GNUNET_ATS_SchedulingHandle`
347 * @param srm message received
348 */
349static void
350handle_ats_session_release (void *cls,
351 const struct GNUNET_ATS_SessionReleaseMessage *srm)
352{
353 struct GNUNET_ATS_SchedulingHandle *sh = cls;
354
355 /* Note: peer field in srm not necessary right now,
356 but might be good to have in the future */
357 release_session (sh,
358 ntohl (srm->session_id));
359}
360
361
362/**
363 * Type of a function to call when we receive a address suggestion
364 * message from the service.
365 *
366 * @param cls the `struct GNUNET_ATS_SchedulingHandle`
367 * @param m message received
368 */
369static void
370handle_ats_address_suggestion (void *cls,
371 const struct AddressSuggestionMessage *m)
372{
373 struct GNUNET_ATS_SchedulingHandle *sh = cls;
374 struct GNUNET_ATS_AddressRecord *ar;
375 uint32_t session_id;
376
377 session_id = ntohl (m->session_id);
378 if (0 == session_id)
379 {
380 GNUNET_break (0);
381 force_reconnect (sh);
382 return;
383 }
384 ar = find_session (sh,
385 session_id,
386 &m->peer);
387 if (NULL == ar)
388 {
389 GNUNET_break (0);
390 force_reconnect (sh);
391 return;
392 }
393 if (NULL == sh->suggest_cb)
394 return;
395 if (GNUNET_YES == ar->in_destroy)
396 {
397 /* ignore suggestion, as this address is dying, unless BW is 0,
398 in that case signal 'disconnect' via BW 0 */
399 if ((0 == ntohl (m->bandwidth_out.value__)) &&
400 (0 == ntohl (m->bandwidth_in.value__)))
401 {
402 LOG (GNUNET_ERROR_TYPE_DEBUG,
403 "ATS suggests disconnect from peer `%s' with BW %u/%u\n",
404 GNUNET_i2s (&ar->address->peer),
405 (unsigned int) ntohl (m->bandwidth_out.value__),
406 (unsigned int) ntohl (m->bandwidth_in.value__));
407 sh->suggest_cb (sh->suggest_cb_cls,
408 &m->peer,
409 NULL,
410 NULL,
411 m->bandwidth_out,
412 m->bandwidth_in);
413 }
414 return;
415 }
416 if ((NULL == ar->session) &&
417 (GNUNET_HELLO_address_check_option (ar->address,
418 GNUNET_HELLO_ADDRESS_INFO_INBOUND)))
419 {
420 GNUNET_break (0);
421 return;
422 }
423 sh->backoff = GNUNET_TIME_UNIT_ZERO;
424 LOG (GNUNET_ERROR_TYPE_DEBUG,
425 "ATS suggests address slot %u for peer `%s' using plugin %s\n",
426 ar->slot,
427 GNUNET_i2s (&ar->address->peer),
428 ar->address->transport_name);
429 sh->suggest_cb (sh->suggest_cb_cls,
430 &m->peer,
431 ar->address,
432 ar->session,
433 m->bandwidth_out,
434 m->bandwidth_in);
435}
436
437
438/**
439 * We encountered an error handling the MQ to the
440 * ATS service. Reconnect.
441 *
442 * @param cls the `struct GNUNET_ATS_SchedulingHandle`
443 * @param error details about the error
444 */
445static void
446error_handler (void *cls,
447 enum GNUNET_MQ_Error error)
448{
449 struct GNUNET_ATS_SchedulingHandle *sh = cls;
450
451 LOG (GNUNET_ERROR_TYPE_DEBUG,
452 "ATS connection died (code %d), reconnecting\n",
453 (int) error);
454 force_reconnect (sh);
455}
456
457
458/**
459 * Generate and transmit the `struct AddressAddMessage` for the given
460 * address record.
461 *
462 * @param sh the scheduling handle to use for transmission
463 * @param ar the address to inform the ATS service about
464 */
465static void
466send_add_address_message (struct GNUNET_ATS_SchedulingHandle *sh,
467 const struct GNUNET_ATS_AddressRecord *ar)
468{
469 struct GNUNET_MQ_Envelope *ev;
470 struct AddressAddMessage *m;
471 char *pm;
472 size_t namelen;
473 size_t msize;
474
475 if (NULL == sh->mq)
476 return; /* disconnected, skip for now */
477 GNUNET_break (GNUNET_NT_UNSPECIFIED != ar->properties.scope);
478 namelen = strlen (ar->address->transport_name) + 1;
479 msize = ar->address->address_length + namelen;
480 ev = GNUNET_MQ_msg_extra (m, msize, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_ADD);
481 m->peer = ar->address->peer;
482 m->address_length = htons (ar->address->address_length);
483 m->address_local_info = htonl ((uint32_t) ar->address->local_info);
484 m->plugin_name_length = htons (namelen);
485 m->session_id = htonl (ar->slot);
486 m->properties = ar->properties;
487
488 LOG (GNUNET_ERROR_TYPE_DEBUG,
489 "Adding address for peer `%s', plugin `%s', session %p slot %u\n",
490 GNUNET_i2s (&ar->address->peer),
491 ar->address->transport_name,
492 ar->session,
493 ar->slot);
494 pm = (char *) &m[1];
495 GNUNET_memcpy (pm,
496 ar->address->address,
497 ar->address->address_length);
498 if (NULL != ar->address->transport_name)
499 GNUNET_memcpy (&pm[ar->address->address_length],
500 ar->address->transport_name,
501 namelen);
502 GNUNET_MQ_send (sh->mq, ev);
503}
504
505
506/**
507 * Re-establish the connection to the ATS service.
508 *
509 * @param sh handle to use to re-connect.
510 */
511static void
512reconnect (struct GNUNET_ATS_SchedulingHandle *sh)
513{
514 struct GNUNET_MQ_MessageHandler handlers[] = {
515 GNUNET_MQ_hd_fixed_size (ats_session_release,
516 GNUNET_MESSAGE_TYPE_ATS_SESSION_RELEASE,
517 struct GNUNET_ATS_SessionReleaseMessage,
518 sh),
519 GNUNET_MQ_hd_fixed_size (ats_address_suggestion,
520 GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION,
521 struct AddressSuggestionMessage,
522 sh),
523 GNUNET_MQ_handler_end ()
524 };
525 struct GNUNET_MQ_Envelope *ev;
526 struct ClientStartMessage *init;
527 unsigned int i;
528 struct GNUNET_ATS_AddressRecord *ar;
529
530 GNUNET_assert (NULL == sh->mq);
531 sh->mq = GNUNET_CLIENT_connect (sh->cfg,
532 "ats",
533 handlers,
534 &error_handler,
535 sh);
536 if (NULL == sh->mq)
537 {
538 GNUNET_break (0);
539 force_reconnect (sh);
540 return;
541 }
542 ev = GNUNET_MQ_msg (init,
543 GNUNET_MESSAGE_TYPE_ATS_START);
544 init->start_flag = htonl (START_FLAG_SCHEDULING);
545 GNUNET_MQ_send (sh->mq, ev);
546 if (NULL == sh->mq)
547 return;
548 for (i = 0; i < sh->session_array_size; i++)
549 {
550 ar = sh->session_array[i];
551 if (NULL == ar)
552 continue;
553 send_add_address_message (sh, ar);
554 if (NULL == sh->mq)
555 return;
556 }
557}
558
559
560/**
561 * Initialize the ATS subsystem.
562 *
563 * @param cfg configuration to use
564 * @param suggest_cb notification to call whenever the suggestation changed
565 * @param suggest_cb_cls closure for @a suggest_cb
566 * @return ats context
567 */
568struct GNUNET_ATS_SchedulingHandle *
569GNUNET_ATS_scheduling_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
570 GNUNET_ATS_AddressSuggestionCallback suggest_cb,
571 void *suggest_cb_cls)
572{
573 struct GNUNET_ATS_SchedulingHandle *sh;
574
575 sh = GNUNET_new (struct GNUNET_ATS_SchedulingHandle);
576 sh->cfg = cfg;
577 sh->suggest_cb = suggest_cb;
578 sh->suggest_cb_cls = suggest_cb_cls;
579 GNUNET_array_grow (sh->session_array,
580 sh->session_array_size,
581 4);
582 reconnect (sh);
583 return sh;
584}
585
586
587/**
588 * Client is done with ATS scheduling, release resources.
589 *
590 * @param sh handle to release
591 */
592void
593GNUNET_ATS_scheduling_done (struct GNUNET_ATS_SchedulingHandle *sh)
594{
595 struct GNUNET_ATS_AddressRecord *ar;
596 unsigned int i;
597
598 if (NULL != sh->mq)
599 {
600 GNUNET_MQ_destroy (sh->mq);
601 sh->mq = NULL;
602 }
603 if (NULL != sh->task)
604 {
605 GNUNET_SCHEDULER_cancel (sh->task);
606 sh->task = NULL;
607 }
608 for (i = 0; i < sh->session_array_size; i++)
609 {
610 if (NULL != (ar = sh->session_array[i]))
611 {
612 GNUNET_HELLO_address_free (ar->address);
613 GNUNET_free (ar);
614 sh->session_array[i] = NULL;
615 }
616 }
617 GNUNET_array_grow (sh->session_array,
618 sh->session_array_size,
619 0);
620 GNUNET_free (sh);
621}
622
623
624/**
625 * We have a new address ATS should know. Addresses have to be added
626 * with this function before they can be: updated, set in use and
627 * destroyed.
628 *
629 * @param sh handle
630 * @param address the address
631 * @param session session handle, can be NULL
632 * @param prop performance data for the address
633 * @return handle to the address representation inside ATS, NULL
634 * on error (i.e. ATS knows this exact address already)
635 */
636struct GNUNET_ATS_AddressRecord *
637GNUNET_ATS_address_add (struct GNUNET_ATS_SchedulingHandle *sh,
638 const struct GNUNET_HELLO_Address *address,
639 struct GNUNET_ATS_Session *session,
640 const struct GNUNET_ATS_Properties *prop)
641{
642 struct GNUNET_ATS_AddressRecord *ar;
643 size_t namelen;
644 size_t msize;
645 uint32_t s;
646
647 if (NULL == address)
648 {
649 /* we need a valid address */
650 GNUNET_break (0);
651 return NULL;
652 }
653 GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope);
654 namelen = strlen (address->transport_name) + 1;
655 msize = address->address_length + namelen;
656 if ((msize + sizeof(struct AddressUpdateMessage) >=
657 GNUNET_MAX_MESSAGE_SIZE) ||
658 (address->address_length >= GNUNET_MAX_MESSAGE_SIZE) ||
659 (namelen >= GNUNET_MAX_MESSAGE_SIZE))
660 {
661 /* address too large for us, this should not happen */
662 GNUNET_break (0);
663 return NULL;
664 }
665
666 if (NOT_FOUND !=
667 find_session_id (sh,
668 session,
669 address))
670 {
671 /* Already existing, nothing todo, but this should not happen */
672 GNUNET_break (0);
673 return NULL;
674 }
675 s = find_empty_session_slot (sh);
676 ar = GNUNET_new (struct GNUNET_ATS_AddressRecord);
677 ar->sh = sh;
678 ar->slot = s;
679 ar->session = session;
680 ar->address = GNUNET_HELLO_address_copy (address);
681 GNUNET_ATS_properties_hton (&ar->properties,
682 prop);
683 sh->session_array[s] = ar;
684 send_add_address_message (sh, ar);
685 return ar;
686}
687
688
689/**
690 * An address was used to initiate a session.
691 *
692 * @param ar address record to update information for
693 * @param session session handle
694 */
695void
696GNUNET_ATS_address_add_session (struct GNUNET_ATS_AddressRecord *ar,
697 struct GNUNET_ATS_Session *session)
698{
699 GNUNET_break (NULL == ar->session);
700 ar->session = session;
701}
702
703
704/**
705 * A session was destroyed, disassociate it from the
706 * given address record. If this was an incoming
707 * address, destroy the address as well.
708 *
709 * @param ar address record to update information for
710 * @param session session handle
711 * @return #GNUNET_YES if the @a ar was destroyed because
712 * it was an incoming address,
713 * #GNUNET_NO if the @ar was kept because we can
714 * use it still to establish a new session
715 */
716int
717GNUNET_ATS_address_del_session (struct GNUNET_ATS_AddressRecord *ar,
718 struct GNUNET_ATS_Session *session)
719{
720 GNUNET_assert (session == ar->session);
721 ar->session = NULL;
722 if (GNUNET_HELLO_address_check_option (ar->address,
723 GNUNET_HELLO_ADDRESS_INFO_INBOUND))
724 {
725 GNUNET_ATS_address_destroy (ar);
726 return GNUNET_YES;
727 }
728 return GNUNET_NO;
729}
730
731
732/**
733 * We have updated performance statistics for a given address. Note
734 * that this function can be called for addresses that are currently
735 * in use as well as addresses that are valid but not actively in use.
736 * Furthermore, the peer may not even be connected to us right now (in
737 * which case the call may be ignored or the information may be stored
738 * for later use). Update bandwidth assignments.
739 *
740 * @param ar address record to update information for
741 * @param prop performance data for the address
742 */
743void
744GNUNET_ATS_address_update (struct GNUNET_ATS_AddressRecord *ar,
745 const struct GNUNET_ATS_Properties *prop)
746{
747 struct GNUNET_ATS_SchedulingHandle *sh = ar->sh;
748 struct GNUNET_MQ_Envelope *ev;
749 struct AddressUpdateMessage *m;
750
751 LOG (GNUNET_ERROR_TYPE_DEBUG,
752 "Updating address for peer `%s', plugin `%s', session %p slot %u\n",
753 GNUNET_i2s (&ar->address->peer),
754 ar->address->transport_name,
755 ar->session,
756 ar->slot);
757 GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope);
758 GNUNET_ATS_properties_hton (&ar->properties,
759 prop);
760 if (NULL == sh->mq)
761 return; /* disconnected, skip for now */
762 ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE);
763 m->session_id = htonl (ar->slot);
764 m->peer = ar->address->peer;
765 m->properties = ar->properties;
766 GNUNET_MQ_send (sh->mq,
767 ev);
768}
769
770
771/**
772 * An address got destroyed, stop using it as a valid address.
773 *
774 * @param ar address to destroy
775 */
776void
777GNUNET_ATS_address_destroy (struct GNUNET_ATS_AddressRecord *ar)
778{
779 struct GNUNET_ATS_SchedulingHandle *sh = ar->sh;
780 struct GNUNET_MQ_Envelope *ev;
781 struct AddressDestroyedMessage *m;
782
783 LOG (GNUNET_ERROR_TYPE_DEBUG,
784 "Deleting address for peer `%s', plugin `%s', slot %u session %p\n",
785 GNUNET_i2s (&ar->address->peer),
786 ar->address->transport_name,
787 ar->slot,
788 ar->session);
789 GNUNET_break (NULL == ar->session);
790 ar->session = NULL;
791 ar->in_destroy = GNUNET_YES;
792 if (NULL == sh->mq)
793 return;
794 ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_DESTROYED);
795 m->session_id = htonl (ar->slot);
796 m->peer = ar->address->peer;
797 GNUNET_MQ_send (sh->mq, ev);
798}
799
800
801/* end of ats_api_scheduling.c */