aboutsummaryrefslogtreecommitdiff
path: root/src/ats/test_ats_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ats/test_ats_lib.c')
-rw-r--r--src/ats/test_ats_lib.c1107
1 files changed, 0 insertions, 1107 deletions
diff --git a/src/ats/test_ats_lib.c b/src/ats/test_ats_lib.c
deleted file mode 100644
index d19da0106..000000000
--- a/src/ats/test_ats_lib.c
+++ /dev/null
@@ -1,1107 +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/test_ats_lib.c
22 * @brief test ATS library with a generic interpreter for running ATS tests
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_ats_service.h"
28#include "gnunet_testing_lib.h"
29#include "test_ats_lib.h"
30
31/**
32 * Information about the last address suggestion we got for a peer.
33 */
34struct AddressSuggestData
35{
36 /**
37 * Which session were we given?
38 */
39 struct GNUNET_ATS_Session *session;
40
41 /**
42 * What address was assigned?
43 */
44 struct GNUNET_HELLO_Address *address;
45
46 /**
47 * Outbound bandwidth assigned.
48 */
49 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
50
51 /**
52 * Inbound bandwidth assigned.
53 */
54 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
55
56 /**
57 * Was the bandwidth assigned non-zero?
58 */
59 int active;
60};
61
62
63/**
64 * Information about the last address information we got for an address.
65 */
66struct AddressInformationData
67{
68 /**
69 * What address is this data about?
70 */
71 struct GNUNET_HELLO_Address *address;
72
73 /**
74 * Which properties were given?
75 */
76 struct GNUNET_ATS_Properties properties;
77
78 /**
79 * Outbound bandwidth reported.
80 */
81 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
82
83 /**
84 * Inbound bandwidth reported.
85 */
86 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
87
88 /**
89 * Was the address said to be 'active'?
90 */
91 int active;
92};
93
94
95/**
96 * Scheduling handle
97 */
98static struct GNUNET_ATS_SchedulingHandle *sched_ats;
99
100/**
101 * Connectivity handle
102 */
103static struct GNUNET_ATS_ConnectivityHandle *con_ats;
104
105/**
106 * Performance handle
107 */
108static struct GNUNET_ATS_PerformanceHandle *perf_ats;
109
110/**
111 * Handle for the interpreter task.
112 */
113static struct GNUNET_SCHEDULER_Task *interpreter_task;
114
115/**
116 * Map from peer identities to the last address suggestion
117 * `struct AddressSuggestData` we got for the respective peer.
118 */
119static struct GNUNET_CONTAINER_MultiPeerMap *p2asd;
120
121/**
122 * Map from peer identities to the last address information
123 * sets for all addresses of this peer. Each peer is mapped
124 * to one or more `struct AddressInformationData` entries.
125 */
126static struct GNUNET_CONTAINER_MultiPeerMap *p2aid;
127
128/**
129 * Global timeout for the test.
130 */
131static struct GNUNET_TIME_Relative TIMEOUT;
132
133/**
134 * Return value from #main().
135 */
136static int ret;
137
138/**
139 * Current global command offset into the #commands array.
140 */
141static unsigned int off;
142
143/**
144 * Commands for the current test.
145 */
146static struct Command *test_commands;
147
148
149/**
150 * Free `struct AddressSuggestData` entry.
151 *
152 * @param cls NULL
153 * @param key ignored
154 * @param value the `struct AddressSuggestData` to release
155 * @return #GNUNET_OK (continue to iterate)
156 */
157static int
158free_asd (void *cls,
159 const struct GNUNET_PeerIdentity *key,
160 void *value)
161{
162 struct AddressSuggestData *asd = value;
163
164 GNUNET_assert (GNUNET_YES ==
165 GNUNET_CONTAINER_multipeermap_remove (p2asd,
166 key,
167 asd));
168 GNUNET_free (asd->address);
169 GNUNET_free (asd);
170 return GNUNET_OK;
171}
172
173
174/**
175 * Free `struct AddressInformationData` entry.
176 *
177 * @param cls NULL
178 * @param key ignored
179 * @param value the `struct AddressSuggestData` to release
180 * @return #GNUNET_OK (continue to iterate)
181 */
182static int
183free_aid (void *cls,
184 const struct GNUNET_PeerIdentity *key,
185 void *value)
186{
187 struct AddressInformationData *aid = value;
188
189 GNUNET_assert (GNUNET_YES ==
190 GNUNET_CONTAINER_multipeermap_remove (p2aid,
191 key,
192 aid));
193 GNUNET_free (aid->address);
194 GNUNET_free (aid);
195 return GNUNET_OK;
196}
197
198
199/**
200 * Find latest address suggestion made for the given peer.
201 *
202 * @param pid peer to look up
203 * @return NULL if peer was never involved
204 */
205static struct AddressSuggestData *
206find_address_suggestion (const struct GNUNET_PeerIdentity *pid)
207{
208 return GNUNET_CONTAINER_multipeermap_get (p2asd,
209 pid);
210}
211
212
213/**
214 * Closure for #match_address()
215 */
216struct MatchAddressContext
217{
218 /**
219 * Address to find.
220 */
221 const struct GNUNET_HELLO_Address *addr;
222
223 /**
224 * Where to return address information if found.
225 */
226 struct AddressInformationData *ret;
227};
228
229
230/**
231 * Find matching address information.
232 *
233 * @param cls a `struct MatchAddressContext`
234 * @param key unused
235 * @param value a `struct AddressInformationData`
236 * @return #GNUNET_OK if not found
237 */
238static int
239match_address (void *cls,
240 const struct GNUNET_PeerIdentity *key,
241 void *value)
242{
243 struct MatchAddressContext *mac = cls;
244 struct AddressInformationData *aid = value;
245
246 if (0 == GNUNET_HELLO_address_cmp (mac->addr,
247 aid->address))
248 {
249 mac->ret = aid;
250 return GNUNET_NO;
251 }
252 return GNUNET_OK;
253}
254
255
256/**
257 * Find latest address information made for the given address.
258 *
259 * @param addr address to look up
260 * @return NULL if peer was never involved
261 */
262static struct AddressInformationData *
263find_address_information (const struct GNUNET_HELLO_Address *addr)
264{
265 struct MatchAddressContext mac;
266
267 mac.ret = NULL;
268 mac.addr = addr;
269 GNUNET_CONTAINER_multipeermap_get_multiple (p2aid,
270 &addr->peer,
271 &match_address,
272 &mac);
273 return mac.ret;
274}
275
276
277/**
278 * Task run to terminate the testcase.
279 *
280 * @param cls NULL
281 */
282static void
283end (void *cls)
284{
285 if (0 != ret)
286 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
287 "Test failed at stage %u %s\n",
288 off,
289 (NULL != test_commands[off].label)
290 ? test_commands[off].label
291 : "");
292 if (NULL != interpreter_task)
293 {
294 GNUNET_SCHEDULER_cancel (interpreter_task);
295 interpreter_task = NULL;
296 }
297 if (NULL != sched_ats)
298 {
299 GNUNET_ATS_scheduling_done (sched_ats);
300 sched_ats = NULL;
301 }
302 if (NULL != con_ats)
303 {
304 GNUNET_ATS_connectivity_done (con_ats);
305 con_ats = NULL;
306 }
307 if (NULL != perf_ats)
308 {
309 GNUNET_ATS_performance_done (perf_ats);
310 perf_ats = NULL;
311 }
312 if (NULL != p2asd)
313 {
314 GNUNET_CONTAINER_multipeermap_iterate (p2asd,
315 &free_asd,
316 NULL);
317 GNUNET_CONTAINER_multipeermap_destroy (p2asd);
318 p2asd = NULL;
319 }
320 if (NULL != p2aid)
321 {
322 GNUNET_CONTAINER_multipeermap_iterate (p2aid,
323 &free_aid,
324 NULL);
325 GNUNET_CONTAINER_multipeermap_destroy (p2aid);
326 p2aid = NULL;
327 }
328}
329
330
331/**
332 * Main interpreter loop. Runs the steps of the test.
333 *
334 * @param cls NULL
335 */
336static void
337interpreter (void *cls);
338
339
340/**
341 * Run the interpreter next.
342 */
343static void
344run_interpreter ()
345{
346 if (NULL != interpreter_task)
347 GNUNET_SCHEDULER_cancel (interpreter_task);
348 interpreter_task = GNUNET_SCHEDULER_add_now (&interpreter,
349 NULL);
350}
351
352
353/**
354 * Initialize public key of a peer based on a single number.
355 *
356 * @param pid number to use as the basis
357 * @param pk resulting fake public key
358 */
359static void
360make_peer (uint32_t pid,
361 struct GNUNET_PeerIdentity *pk)
362{
363 memset (pk,
364 (int) pid,
365 sizeof(struct GNUNET_PeerIdentity));
366 GNUNET_memcpy (pk,
367 &pid,
368 sizeof(uint32_t));
369}
370
371
372/**
373 * Generate a fake address based on the given parameters.
374 *
375 * @param pid number of the peer
376 * @param num number of the address at peer @a pid
377 * @param addr_flags flags to use for the address
378 * @return the address
379 */
380static struct GNUNET_HELLO_Address *
381make_address (uint32_t pid,
382 uint32_t num,
383 enum GNUNET_HELLO_AddressInfo addr_flags)
384{
385 struct GNUNET_PeerIdentity pk;
386 uint32_t nbo;
387
388 nbo = htonl (num);
389 make_peer (pid,
390 &pk);
391 return GNUNET_HELLO_address_allocate (&pk,
392 "test",
393 &nbo,
394 sizeof(nbo),
395 addr_flags);
396}
397
398
399/**
400 * Our dummy sessions.
401 */
402struct GNUNET_ATS_Session
403{
404 /**
405 * Field to avoid `0 == sizeof(struct GNUNET_ATS_Session)`.
406 */
407 unsigned int non_empty;
408};
409
410
411/**
412 * Create a session instance for ATS.
413 *
414 * @param i which session number to return
415 * @return NULL if @a i is 0, otherwise a pointer unique to @a i
416 */
417static struct GNUNET_ATS_Session *
418make_session (unsigned int i)
419{
420 struct GNUNET_ATS_Session *baseptr = NULL;
421
422 if (0 == i)
423 return NULL;
424 /* Yes, these are *intentionally* out-of-bounds,
425 and offset from NULL, as nobody should ever
426 use those other than to compare pointers! */
427 return baseptr + i;
428}
429
430
431/**
432 * Find a @a code command before the global #off with the
433 * specified @a label.
434 *
435 * @param code opcode to look for
436 * @param label label to look for, NULL for none
437 * @return previous command with the matching label
438 */
439static struct Command *
440find_command (enum CommandCode code,
441 const char *label)
442{
443 int i;
444
445 if (NULL == label)
446 return NULL;
447 for (i = off - 1; i >= 0; i--)
448 if ((code == test_commands[i].code) &&
449 (0 == strcmp (test_commands[i].label,
450 label)))
451 return &test_commands[i];
452 GNUNET_break (0);
453 return NULL;
454}
455
456
457/**
458 * Function called from #GNUNET_ATS_performance_list_addresses when
459 * we process a #CMD_LIST_ADDRESSES command.
460 *
461 * @param cls the `struct Command` that caused the call
462 * @param address the address, NULL if ATS service was disconnected
463 * @param address_active #GNUNET_YES if this address is actively used
464 * to maintain a connection to a peer;
465 * #GNUNET_NO if the address is not actively used;
466 * #GNUNET_SYSERR if this address is no longer available for ATS
467 * @param bandwidth_out assigned outbound bandwidth for the connection
468 * @param bandwidth_in assigned inbound bandwidth for the connection
469 * @param prop performance data for the address
470 */
471static void
472info_cb (void *cls,
473 const struct GNUNET_HELLO_Address *address,
474 int address_active,
475 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
476 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
477 const struct GNUNET_ATS_Properties *prop)
478{
479 struct Command *c = cls;
480 struct CommandListAddresses *cmd = &c->details.list_addresses;
481
482 if (NULL == address)
483 {
484 cmd->alh = NULL;
485 /* we are done with the iteration, continue to execute */
486 if ((cmd->calls < cmd->min_calls) &&
487 (cmd->active_calls < cmd->min_active_calls))
488 {
489 GNUNET_SCHEDULER_shutdown ();
490 return;
491 }
492 off++;
493 run_interpreter ();
494 return;
495 }
496 switch (address_active)
497 {
498 case GNUNET_YES:
499 cmd->active_calls++;
500 cmd->calls++;
501 break;
502
503 case GNUNET_NO:
504 cmd->calls++;
505 break;
506
507 case GNUNET_SYSERR:
508 return;
509 }
510 if ((cmd->calls > cmd->max_calls) &&
511 (cmd->active_calls < cmd->max_active_calls))
512 {
513 GNUNET_break (0);
514 GNUNET_ATS_performance_list_addresses_cancel (cmd->alh);
515 cmd->alh = NULL;
516 GNUNET_SCHEDULER_shutdown ();
517 return;
518 }
519}
520
521
522/**
523 * Function called with reservation result.
524 *
525 * @param cls closure with the reservation command (`struct Command`)
526 * @param peer identifies the peer
527 * @param amount set to the amount that was actually reserved or unreserved;
528 * either the full requested amount or zero (no partial reservations)
529 * @param res_delay if the reservation could not be satisfied (amount was 0), how
530 * long should the client wait until re-trying?
531 */
532static void
533reservation_cb (void *cls,
534 const struct GNUNET_PeerIdentity *peer,
535 int32_t amount,
536 struct GNUNET_TIME_Relative res_delay)
537{
538 struct Command *cmd = cls;
539 struct GNUNET_PeerIdentity pid;
540
541 cmd->details.reserve_bandwidth.rc = NULL;
542 make_peer (cmd->details.reserve_bandwidth.pid,
543 &pid);
544 GNUNET_assert (0 == GNUNET_memcmp (peer,
545 &pid));
546 switch (cmd->details.reserve_bandwidth.expected_result)
547 {
548 case GNUNET_OK:
549 if (amount != cmd->details.reserve_bandwidth.amount)
550 {
551 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
552 "Unexpectedly failed to reserve %d/%d bytes with delay %s!\n",
553 (int) amount,
554 (int) cmd->details.reserve_bandwidth.amount,
555 GNUNET_STRINGS_relative_time_to_string (res_delay,
556 GNUNET_YES));
557 GNUNET_break (0);
558 GNUNET_SCHEDULER_shutdown ();
559 return;
560 }
561 break;
562
563 case GNUNET_NO:
564 GNUNET_break ((0 != amount) ||
565 (0 != res_delay.rel_value_us));
566 break;
567
568 case GNUNET_SYSERR:
569 if ((amount != 0) ||
570 (0 == res_delay.rel_value_us))
571 {
572 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
573 "Unexpectedly reserved %d bytes with delay %s!\n",
574 (int) amount,
575 GNUNET_STRINGS_relative_time_to_string (res_delay,
576 GNUNET_YES));
577 GNUNET_break (0);
578 GNUNET_SCHEDULER_shutdown ();
579 return;
580 }
581 break;
582 }
583 off++;
584 run_interpreter ();
585}
586
587
588/**
589 * Main interpreter loop. Runs the steps of the test.
590 *
591 * @param cls NULL
592 */
593static void
594interpreter (void *cls)
595
596{
597 struct Command *cmd;
598
599 interpreter_task = NULL;
600 while (1)
601 {
602 cmd = &test_commands[off];
603 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
604 "#%u: %d %s\n",
605 off,
606 (int) cmd->code,
607 (NULL != cmd->label) ? cmd->label : "");
608 switch (cmd->code)
609 {
610 case CMD_END_PASS:
611 ret = 0;
612 GNUNET_SCHEDULER_shutdown ();
613 return;
614
615 case CMD_ADD_ADDRESS:
616 {
617 struct GNUNET_HELLO_Address *addr;
618 struct GNUNET_ATS_Session *session;
619
620 addr = make_address (cmd->details.add_address.pid,
621 cmd->details.add_address.addr_num,
622 cmd->details.add_address.addr_flags);
623 session = make_session (cmd->details.add_address.session);
624 if (cmd->details.add_address.expect_fail)
625 GNUNET_log_skip (1, GNUNET_NO);
626 cmd->details.add_address.ar
627 = GNUNET_ATS_address_add (sched_ats,
628 addr,
629 session,
630 &cmd->details.add_address.properties);
631 GNUNET_free (addr);
632 if (cmd->details.add_address.expect_fail)
633 {
634 GNUNET_log_skip (0, GNUNET_YES);
635 }
636 else if (NULL == cmd->details.add_address.ar)
637 {
638 GNUNET_break (0);
639 GNUNET_SCHEDULER_shutdown ();
640 return;
641 }
642 off++;
643 break;
644 }
645
646 case CMD_DEL_ADDRESS:
647 {
648 struct Command *add;
649
650 add = find_command (CMD_ADD_ADDRESS,
651 cmd->details.del_address.add_label);
652 GNUNET_assert (NULL != add->details.add_address.ar);
653 GNUNET_ATS_address_destroy (add->details.add_address.ar);
654 add->details.add_address.ar = NULL;
655 off++;
656 break;
657 }
658
659 case CMD_AWAIT_ADDRESS_SUGGESTION:
660 {
661 struct GNUNET_PeerIdentity pid;
662 struct GNUNET_HELLO_Address *addr;
663 struct Command *add;
664 struct AddressSuggestData *asd;
665 int done;
666
667 make_peer (cmd->details.await_address_suggestion.pid,
668 &pid);
669 asd = find_address_suggestion (&pid);
670 if (NULL == asd)
671 return;
672 if (GNUNET_NO == asd->active)
673 return; /* last suggestion was to disconnect, wait longer */
674 done = GNUNET_YES;
675 if (NULL != cmd->details.await_address_suggestion.add_label)
676 {
677 done = GNUNET_NO;
678 add = find_command (CMD_ADD_ADDRESS,
679 cmd->details.await_address_suggestion.add_label);
680 addr = make_address (add->details.add_address.pid,
681 add->details.add_address.addr_num,
682 add->details.add_address.addr_flags);
683 if ((asd->session ==
684 make_session (add->details.add_address.session)) &&
685 (0 ==
686 GNUNET_HELLO_address_cmp (addr,
687 asd->address)))
688 done = GNUNET_YES;
689 GNUNET_free (addr);
690 }
691 if (GNUNET_NO == done)
692 return;
693 off++;
694 break;
695 }
696
697 case CMD_AWAIT_DISCONNECT_SUGGESTION:
698 {
699 struct GNUNET_PeerIdentity pid;
700 struct AddressSuggestData *asd;
701
702 make_peer (cmd->details.await_disconnect_suggestion.pid,
703 &pid);
704 asd = find_address_suggestion (&pid);
705 if (NULL == asd)
706 return; /* odd, no suggestion at all yet!? */
707 if (GNUNET_YES == asd->active)
708 return; /* last suggestion was to activate, wait longer */
709 /* last suggestion was to deactivate, condition satisfied! */
710 off++;
711 break;
712 }
713
714 case CMD_REQUEST_CONNECTION_START:
715 {
716 struct GNUNET_PeerIdentity pid;
717
718 make_peer (cmd->details.request_connection_start.pid,
719 &pid);
720 cmd->details.request_connection_start.csh
721 = GNUNET_ATS_connectivity_suggest (con_ats,
722 &pid,
723 1);
724 off++;
725 break;
726 }
727
728 case CMD_REQUEST_CONNECTION_STOP:
729 {
730 struct Command *start;
731
732 start = find_command (CMD_REQUEST_CONNECTION_START,
733 cmd->details.request_connection_stop.connect_label);
734 GNUNET_ATS_connectivity_suggest_cancel (
735 start->details.request_connection_start.csh);
736 start->details.request_connection_start.csh = NULL;
737 off++;
738 break;
739 }
740
741 case CMD_AWAIT_ADDRESS_INFORMATION:
742 {
743 struct AddressInformationData *aid;
744 struct Command *add;
745 struct Command *update;
746 struct GNUNET_HELLO_Address *addr;
747 const struct GNUNET_ATS_Properties *cmp;
748
749 add = find_command (CMD_ADD_ADDRESS,
750 cmd->details.await_address_information.add_label);
751 update = find_command (CMD_UPDATE_ADDRESS,
752 cmd->details.await_address_information.
753 update_label);
754 addr = make_address (add->details.add_address.pid,
755 add->details.add_address.addr_num,
756 add->details.add_address.addr_flags);
757 aid = find_address_information (addr);
758 GNUNET_free (addr);
759 if (NULL == update)
760 cmp = &add->details.add_address.properties;
761 else
762 cmp = &update->details.update_address.properties;
763 if ((NULL != aid) &&
764 (cmp->delay.rel_value_us == aid->properties.delay.rel_value_us) &&
765 (cmp->utilization_out == aid->properties.utilization_out) &&
766 (cmp->utilization_in == aid->properties.utilization_in) &&
767 (cmp->distance == aid->properties.distance) &&
768 (cmp->scope == aid->properties.scope))
769 {
770 off++;
771 break;
772 }
773 return;
774 }
775
776 case CMD_UPDATE_ADDRESS:
777 {
778 struct Command *add;
779
780 add = find_command (CMD_ADD_ADDRESS,
781 cmd->details.update_address.add_label);
782 GNUNET_assert (NULL != add->details.add_address.ar);
783 GNUNET_ATS_address_update (add->details.add_address.ar,
784 &cmd->details.update_address.properties);
785 off++;
786 break;
787 }
788
789 case CMD_ADD_SESSION:
790 {
791 struct Command *add;
792 struct GNUNET_ATS_Session *session;
793
794 add = find_command (CMD_ADD_ADDRESS,
795 cmd->details.add_session.add_label);
796 session = make_session (cmd->details.add_session.session);
797 GNUNET_assert (NULL != add->details.add_address.ar);
798 GNUNET_ATS_address_add_session (add->details.add_address.ar,
799 session);
800 off++;
801 break;
802 }
803
804 case CMD_DEL_SESSION:
805 {
806 struct Command *add_address;
807 struct Command *add_session;
808 struct GNUNET_ATS_Session *session;
809
810 add_session = find_command (CMD_ADD_SESSION,
811 cmd->details.del_session.add_session_label);
812 add_address = find_command (CMD_ADD_ADDRESS,
813 add_session->details.add_session.add_label);
814 GNUNET_assert (NULL != add_address->details.add_address.ar);
815 session = make_session (add_session->details.add_session.session);
816 GNUNET_ATS_address_del_session (add_address->details.add_address.ar,
817 session);
818 off++;
819 break;
820 }
821
822 case CMD_CHANGE_PREFERENCE:
823 {
824 struct GNUNET_PeerIdentity pid;
825
826 make_peer (cmd->details.change_preference.pid,
827 &pid);
828 GNUNET_ATS_performance_change_preference (perf_ats,
829 &pid,
830 GNUNET_ATS_PREFERENCE_END);
831 off++;
832 break;
833 }
834
835 case CMD_PROVIDE_FEEDBACK:
836 {
837 struct GNUNET_PeerIdentity pid;
838
839 make_peer (cmd->details.provide_feedback.pid,
840 &pid);
841 GNUNET_ATS_performance_give_feedback (perf_ats,
842 &pid,
843 cmd->details.provide_feedback.
844 scope,
845 GNUNET_ATS_PREFERENCE_END);
846 off++;
847 break;
848 }
849
850 case CMD_LIST_ADDRESSES:
851 {
852 struct GNUNET_PeerIdentity pid;
853
854 make_peer (cmd->details.list_addresses.pid,
855 &pid);
856 cmd->details.list_addresses.alh
857 = GNUNET_ATS_performance_list_addresses (perf_ats,
858 &pid,
859 cmd->details.list_addresses.
860 all,
861 &info_cb,
862 cmd);
863 return;
864 }
865
866 case CMD_RESERVE_BANDWIDTH:
867 {
868 struct GNUNET_PeerIdentity pid;
869
870 make_peer (cmd->details.reserve_bandwidth.pid,
871 &pid);
872 cmd->details.reserve_bandwidth.rc
873 = GNUNET_ATS_reserve_bandwidth (perf_ats,
874 &pid,
875 cmd->details.reserve_bandwidth.amount,
876 &reservation_cb,
877 cmd);
878 return;
879 }
880
881 case CMD_SLEEP:
882 off++;
883 interpreter_task = GNUNET_SCHEDULER_add_delayed (cmd->details.sleep.delay,
884 &interpreter,
885 NULL);
886 return;
887 } /* end switch */
888 } /* end while(1) */
889}
890
891
892/**
893 * Signature of a function called by ATS with the current bandwidth
894 * and address preferences as determined by ATS.
895 *
896 * @param cls closure, should point to "asc-closure"
897 * @param peer for which we suggest an address, NULL if ATS connection died
898 * @param address suggested address (including peer identity of the peer),
899 * may be NULL to signal disconnect from peer
900 * @param session session to use, NULL to establish a new outgoing session
901 * @param bandwidth_out assigned outbound bandwidth for the connection,
902 * 0 to signal disconnect
903 * @param bandwidth_in assigned inbound bandwidth for the connection,
904 * 0 to signal disconnect
905 */
906static void
907address_suggest_cb (void *cls,
908 const struct GNUNET_PeerIdentity *peer,
909 const struct GNUNET_HELLO_Address *address,
910 struct GNUNET_ATS_Session *session,
911 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
912 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
913{
914 const char *asc_cls = cls;
915 struct AddressSuggestData *asd;
916
917 GNUNET_break (0 == strcmp (asc_cls, "asc-closure"));
918 if (NULL == peer)
919 {
920 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
921 "Connection to ATS died, likely a crash!\n");
922 GNUNET_SCHEDULER_shutdown ();
923#if 0
924 /* This is what we should do if we wanted to continue past
925 the ATS crash. */
926 GNUNET_CONTAINER_multipeermap_iterate (p2asd,
927 &free_asd,
928 NULL);
929 GNUNET_CONTAINER_multipeermap_iterate (p2aid,
930 &free_aid,
931 NULL);
932#endif
933 return;
934 }
935
936 asd = find_address_suggestion (peer);
937 if (NULL == asd)
938 {
939 asd = GNUNET_new (struct AddressSuggestData);
940 GNUNET_assert (GNUNET_YES ==
941 GNUNET_CONTAINER_multipeermap_put (p2asd,
942 peer,
943 asd,
944 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
945 }
946 if ((0 == ntohl (bandwidth_out.value__)) &&
947 (0 == ntohl (bandwidth_in.value__)))
948 asd->active = GNUNET_NO;
949 else
950 asd->active = GNUNET_YES;
951 asd->bandwidth_out = bandwidth_out;
952 asd->bandwidth_in = bandwidth_in;
953 asd->session = session;
954 GNUNET_free (asd->address);
955 asd->address = NULL;
956 if (NULL != address)
957 asd->address = GNUNET_HELLO_address_copy (address);
958 if (NULL == interpreter_task)
959 run_interpreter ();
960}
961
962
963/**
964 * Signature of a function that is called with QoS information about an address.
965 *
966 * @param cls closure, should point to "aic-closure"
967 * @param address the address, NULL if ATS service was disconnected
968 * @param address_active #GNUNET_YES if this address is actively used
969 * to maintain a connection to a peer;
970 * #GNUNET_NO if the address is not actively used;
971 * #GNUNET_SYSERR if this address is no longer available for ATS
972 * @param bandwidth_out assigned outbound bandwidth for the connection
973 * @param bandwidth_in assigned inbound bandwidth for the connection
974 * @param prop performance data for the address
975 */
976static void
977address_information_cb (void *cls,
978 const struct GNUNET_HELLO_Address *address,
979 int address_active,
980 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
981 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
982 const struct GNUNET_ATS_Properties *prop)
983{
984 const char *aic_cls = cls;
985 struct AddressInformationData *aid;
986
987 GNUNET_break (0 == strcmp (aic_cls, "aic-closure"));
988 if (NULL == address)
989 {
990 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
991 "Connection to ATS died, likely a crash!\n");
992 GNUNET_CONTAINER_multipeermap_iterate (p2aid,
993 &free_aid,
994 NULL);
995 return;
996 }
997
998 aid = find_address_information (address);
999 if (NULL == aid)
1000 {
1001 aid = GNUNET_new (struct AddressInformationData);
1002 aid->address = GNUNET_HELLO_address_copy (address);
1003 GNUNET_assert (GNUNET_YES ==
1004 GNUNET_CONTAINER_multipeermap_put (p2aid,
1005 &address->peer,
1006 aid,
1007 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1008 }
1009 aid->active = address_active;
1010 aid->bandwidth_out = bandwidth_out;
1011 aid->bandwidth_in = bandwidth_in;
1012 aid->properties = *prop;
1013 if (NULL == interpreter_task)
1014 run_interpreter ();
1015}
1016
1017
1018/**
1019 * Function run once the ATS service has been started.
1020 *
1021 * @param cls NULL
1022 * @param cfg configuration for the testcase
1023 * @param peer handle to the peer
1024 */
1025static void
1026run (void *cls,
1027 const struct GNUNET_CONFIGURATION_Handle *cfg,
1028 struct GNUNET_TESTING_Peer *peer)
1029{
1030 p2asd = GNUNET_CONTAINER_multipeermap_create (128,
1031 GNUNET_NO);
1032 p2aid = GNUNET_CONTAINER_multipeermap_create (128,
1033 GNUNET_NO);
1034 GNUNET_SCHEDULER_add_delayed (TIMEOUT,
1035 &end,
1036 NULL);
1037
1038 sched_ats = GNUNET_ATS_scheduling_init (cfg,
1039 &address_suggest_cb,
1040 "asc-closure");
1041 if (NULL == sched_ats)
1042 {
1043 GNUNET_break (0);
1044 GNUNET_SCHEDULER_shutdown ();
1045 return;
1046 }
1047 con_ats = GNUNET_ATS_connectivity_init (cfg);
1048 if (NULL == con_ats)
1049 {
1050 GNUNET_break (0);
1051 GNUNET_SCHEDULER_shutdown ();
1052 return;
1053 }
1054 perf_ats = GNUNET_ATS_performance_init (cfg,
1055 &address_information_cb,
1056 "aic-closure");
1057 if (NULL == perf_ats)
1058 {
1059 GNUNET_break (0);
1060 GNUNET_SCHEDULER_shutdown ();
1061 return;
1062 }
1063 run_interpreter ();
1064}
1065
1066
1067/**
1068 * Run ATS test.
1069 *
1070 * @param argc length of @a argv
1071 * @param argv command line
1072 * @param cmds commands to run with the interpreter
1073 * @param timeout how long is the test allowed to take?
1074 * @return 0 on success
1075 */
1076int
1077TEST_ATS_run (int argc,
1078 char *argv[],
1079 struct Command *cmds,
1080 struct GNUNET_TIME_Relative timeout)
1081{
1082 char *test_filename = GNUNET_strdup (argv[0]);
1083 char *sep;
1084 char *config_file;
1085 char *underscore;
1086
1087 test_commands = cmds;
1088 TIMEOUT = timeout;
1089 if (NULL != (sep = strstr (test_filename, ".exe")))
1090 sep[0] = '\0';
1091 underscore = strrchr (test_filename, (int) '_');
1092 GNUNET_assert (NULL != underscore);
1093 GNUNET_asprintf (&config_file,
1094 "test_ats_api_%s.conf",
1095 underscore + 1);
1096 ret = 2;
1097 if (0 != GNUNET_TESTING_peer_run ("test-ats-api",
1098 config_file,
1099 &run, NULL))
1100 ret = 1;
1101 GNUNET_free (test_filename);
1102 GNUNET_free (config_file);
1103 return ret;
1104}
1105
1106
1107/* end of test_ats_lib.c */