diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-02-11 16:17:20 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-02-11 16:17:20 +0000 |
commit | 8af9412585b17289e8fa5ca905eaa33415927dc3 (patch) | |
tree | f4cc0ed3a8b745a04832157a173a9eefc8f28e89 /src/ats/test_ats_lib.c | |
parent | 567ca9a20a7afe3573cb1c11ad89c116a0650fe7 (diff) | |
download | gnunet-8af9412585b17289e8fa5ca905eaa33415927dc3.tar.gz gnunet-8af9412585b17289e8fa5ca905eaa33415927dc3.zip |
new testsuite, obsoleting (most of) the old one
Diffstat (limited to 'src/ats/test_ats_lib.c')
-rw-r--r-- | src/ats/test_ats_lib.c | 999 |
1 files changed, 999 insertions, 0 deletions
diff --git a/src/ats/test_ats_lib.c b/src/ats/test_ats_lib.c new file mode 100644 index 000000000..74cff1e61 --- /dev/null +++ b/src/ats/test_ats_lib.c | |||
@@ -0,0 +1,999 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2010-2015 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | 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 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
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 | */ | ||
34 | struct AddressSuggestData | ||
35 | { | ||
36 | /** | ||
37 | * Which session were we given? | ||
38 | */ | ||
39 | struct 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 | */ | ||
66 | struct 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 | */ | ||
98 | static struct GNUNET_ATS_SchedulingHandle *sched_ats; | ||
99 | |||
100 | /** | ||
101 | * Connectivity handle | ||
102 | */ | ||
103 | static struct GNUNET_ATS_ConnectivityHandle *con_ats; | ||
104 | |||
105 | /** | ||
106 | * Performance handle | ||
107 | */ | ||
108 | static struct GNUNET_ATS_PerformanceHandle *perf_ats; | ||
109 | |||
110 | /** | ||
111 | * Handle for the interpreter task. | ||
112 | */ | ||
113 | static 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 | */ | ||
119 | static 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 | */ | ||
126 | static struct GNUNET_CONTAINER_MultiPeerMap *p2aid; | ||
127 | |||
128 | /** | ||
129 | * Global timeout for the test. | ||
130 | */ | ||
131 | static struct GNUNET_TIME_Relative TIMEOUT; | ||
132 | |||
133 | /** | ||
134 | * Return value from #main(). | ||
135 | */ | ||
136 | static int ret; | ||
137 | |||
138 | /** | ||
139 | * Current global command offset into the #commands array. | ||
140 | */ | ||
141 | static unsigned int off; | ||
142 | |||
143 | /** | ||
144 | * Commands for the current test. | ||
145 | */ | ||
146 | static struct Command *test_commands; | ||
147 | |||
148 | |||
149 | |||
150 | /** | ||
151 | * Free `struct AddressSuggestData` entry. | ||
152 | * | ||
153 | * @param cls NULL | ||
154 | * @param key ignored | ||
155 | * @param value the `struct AddressSuggestData` to release | ||
156 | * @return #GNUNET_OK (continue to iterate) | ||
157 | */ | ||
158 | static int | ||
159 | free_asd (void *cls, | ||
160 | const struct GNUNET_PeerIdentity *key, | ||
161 | void *value) | ||
162 | { | ||
163 | struct AddressSuggestData *asd = value; | ||
164 | |||
165 | GNUNET_assert (GNUNET_YES == | ||
166 | GNUNET_CONTAINER_multipeermap_remove (p2asd, | ||
167 | key, | ||
168 | asd)); | ||
169 | GNUNET_free (asd->address); | ||
170 | GNUNET_free (asd); | ||
171 | return GNUNET_OK; | ||
172 | } | ||
173 | |||
174 | |||
175 | /** | ||
176 | * Free `struct AddressInformationData` entry. | ||
177 | * | ||
178 | * @param cls NULL | ||
179 | * @param key ignored | ||
180 | * @param value the `struct AddressSuggestData` to release | ||
181 | * @return #GNUNET_OK (continue to iterate) | ||
182 | */ | ||
183 | static int | ||
184 | free_aid (void *cls, | ||
185 | const struct GNUNET_PeerIdentity *key, | ||
186 | void *value) | ||
187 | { | ||
188 | struct AddressInformationData *aid = value; | ||
189 | |||
190 | GNUNET_assert (GNUNET_YES == | ||
191 | GNUNET_CONTAINER_multipeermap_remove (p2aid, | ||
192 | key, | ||
193 | aid)); | ||
194 | GNUNET_free (aid->address); | ||
195 | GNUNET_free (aid); | ||
196 | return GNUNET_OK; | ||
197 | } | ||
198 | |||
199 | |||
200 | /** | ||
201 | * Find latest address suggestion made for the given peer. | ||
202 | * | ||
203 | * @param pid peer to look up | ||
204 | * @return NULL if peer was never involved | ||
205 | */ | ||
206 | static struct AddressSuggestData * | ||
207 | find_address_suggestion (const struct GNUNET_PeerIdentity *pid) | ||
208 | { | ||
209 | return GNUNET_CONTAINER_multipeermap_get (p2asd, | ||
210 | pid); | ||
211 | } | ||
212 | |||
213 | |||
214 | /** | ||
215 | * Closure for #match_address() | ||
216 | */ | ||
217 | struct MatchAddressContext | ||
218 | { | ||
219 | /** | ||
220 | * Address to find. | ||
221 | */ | ||
222 | const struct GNUNET_HELLO_Address *addr; | ||
223 | |||
224 | /** | ||
225 | * Where to return address information if found. | ||
226 | */ | ||
227 | struct AddressInformationData *ret; | ||
228 | }; | ||
229 | |||
230 | |||
231 | /** | ||
232 | * Find matching address information. | ||
233 | * | ||
234 | * @param cls a `struct MatchAddressContext` | ||
235 | * @param key unused | ||
236 | * @param value a `struct AddressInformationData` | ||
237 | * @return #GNUNET_OK if not found | ||
238 | */ | ||
239 | static int | ||
240 | match_address (void *cls, | ||
241 | const struct GNUNET_PeerIdentity *key, | ||
242 | void *value) | ||
243 | { | ||
244 | struct MatchAddressContext *mac = cls; | ||
245 | struct AddressInformationData *aid = value; | ||
246 | |||
247 | if (0 == GNUNET_HELLO_address_cmp (mac->addr, | ||
248 | aid->address)) | ||
249 | { | ||
250 | mac->ret = aid; | ||
251 | return GNUNET_NO; | ||
252 | } | ||
253 | return GNUNET_OK; | ||
254 | } | ||
255 | |||
256 | |||
257 | /** | ||
258 | * Find latest address information made for the given address. | ||
259 | * | ||
260 | * @param addr address to look up | ||
261 | * @return NULL if peer was never involved | ||
262 | */ | ||
263 | static struct AddressInformationData * | ||
264 | find_address_information (const struct GNUNET_HELLO_Address *addr) | ||
265 | { | ||
266 | struct MatchAddressContext mac; | ||
267 | |||
268 | mac.ret = NULL; | ||
269 | mac.addr = addr; | ||
270 | GNUNET_CONTAINER_multipeermap_get_multiple (p2aid, | ||
271 | &addr->peer, | ||
272 | &match_address, | ||
273 | &mac); | ||
274 | return mac.ret; | ||
275 | } | ||
276 | |||
277 | |||
278 | /** | ||
279 | * Task run to terminate the testcase. | ||
280 | * | ||
281 | * @param cls NULL | ||
282 | * @param tc unused | ||
283 | */ | ||
284 | static void | ||
285 | end (void *cls, | ||
286 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
287 | { | ||
288 | if (0 != ret) | ||
289 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
290 | "Test failed at stage %u %s\n", | ||
291 | off, | ||
292 | (NULL != test_commands[off].label) | ||
293 | ? test_commands[off].label | ||
294 | : ""); | ||
295 | if (NULL != interpreter_task) | ||
296 | { | ||
297 | GNUNET_SCHEDULER_cancel (interpreter_task); | ||
298 | interpreter_task = NULL; | ||
299 | } | ||
300 | if (NULL != sched_ats) | ||
301 | { | ||
302 | GNUNET_ATS_scheduling_done (sched_ats); | ||
303 | sched_ats = NULL; | ||
304 | } | ||
305 | if (NULL != con_ats) | ||
306 | { | ||
307 | GNUNET_ATS_connectivity_done (con_ats); | ||
308 | con_ats = NULL; | ||
309 | } | ||
310 | if (NULL != perf_ats) | ||
311 | { | ||
312 | GNUNET_ATS_performance_done (perf_ats); | ||
313 | perf_ats = NULL; | ||
314 | } | ||
315 | if (NULL != p2asd) | ||
316 | { | ||
317 | GNUNET_CONTAINER_multipeermap_iterate (p2asd, | ||
318 | &free_asd, | ||
319 | NULL); | ||
320 | GNUNET_CONTAINER_multipeermap_destroy (p2asd); | ||
321 | p2asd = NULL; | ||
322 | } | ||
323 | if (NULL != p2aid) | ||
324 | { | ||
325 | GNUNET_CONTAINER_multipeermap_iterate (p2aid, | ||
326 | &free_aid, | ||
327 | NULL); | ||
328 | GNUNET_CONTAINER_multipeermap_destroy (p2aid); | ||
329 | p2aid = NULL; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | |||
334 | /** | ||
335 | * Main interpreter loop. Runs the steps of the test. | ||
336 | * | ||
337 | * @param cls NULL | ||
338 | * @param tc unused | ||
339 | */ | ||
340 | static void | ||
341 | interpreter (void *cls, | ||
342 | const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
343 | |||
344 | |||
345 | /** | ||
346 | * Run the interpreter next. | ||
347 | */ | ||
348 | static void | ||
349 | run_interpreter () | ||
350 | { | ||
351 | if (NULL != interpreter_task) | ||
352 | GNUNET_SCHEDULER_cancel (interpreter_task); | ||
353 | interpreter_task = GNUNET_SCHEDULER_add_now (&interpreter, | ||
354 | NULL); | ||
355 | } | ||
356 | |||
357 | |||
358 | /** | ||
359 | * Initialize public key of a peer based on a single number. | ||
360 | * | ||
361 | * @param pid number to use as the basis | ||
362 | * @param pk resulting fake public key | ||
363 | */ | ||
364 | static void | ||
365 | make_peer (uint32_t pid, | ||
366 | struct GNUNET_PeerIdentity *pk) | ||
367 | { | ||
368 | memset (pk, | ||
369 | (int) pid, | ||
370 | sizeof (struct GNUNET_PeerIdentity)); | ||
371 | memcpy (pk, | ||
372 | &pid, | ||
373 | sizeof (uint32_t)); | ||
374 | } | ||
375 | |||
376 | |||
377 | /** | ||
378 | * Generate a fake address based on the given parameters. | ||
379 | * | ||
380 | * @param pid number of the peer | ||
381 | * @param num number of the address at peer @a pid | ||
382 | * @param addr_flags flags to use for the address | ||
383 | * @return the address | ||
384 | */ | ||
385 | static struct GNUNET_HELLO_Address * | ||
386 | make_address (uint32_t pid, | ||
387 | uint32_t num, | ||
388 | enum GNUNET_HELLO_AddressInfo addr_flags) | ||
389 | { | ||
390 | struct GNUNET_PeerIdentity pk; | ||
391 | uint32_t nbo; | ||
392 | |||
393 | nbo = htonl (num); | ||
394 | make_peer (pid, | ||
395 | &pk); | ||
396 | return GNUNET_HELLO_address_allocate (&pk, | ||
397 | "test", | ||
398 | &nbo, | ||
399 | sizeof (nbo), | ||
400 | addr_flags); | ||
401 | } | ||
402 | |||
403 | |||
404 | /** | ||
405 | * Our dummy sessions. | ||
406 | */ | ||
407 | struct Session { | ||
408 | /** | ||
409 | * Field to avoid `0 == sizeof(struct Session)`. | ||
410 | */ | ||
411 | unsigned int non_empty; | ||
412 | }; | ||
413 | |||
414 | |||
415 | /** | ||
416 | * Create a session instance for ATS. | ||
417 | * | ||
418 | * @param i which session number to return | ||
419 | * @return NULL if @a i is 0, otherwise a pointer unique to @a i | ||
420 | */ | ||
421 | static struct Session * | ||
422 | make_session (unsigned int i) | ||
423 | { | ||
424 | struct Session *baseptr = NULL; | ||
425 | |||
426 | if (0 == i) | ||
427 | return NULL; | ||
428 | /* Yes, these are *intentionally* out-of-bounds, | ||
429 | and offset from NULL, as nobody should ever | ||
430 | use those other than to compare pointers! */ | ||
431 | return baseptr + i; | ||
432 | } | ||
433 | |||
434 | |||
435 | /** | ||
436 | * Find a @a code command before the global #off with the | ||
437 | * specified @a label. | ||
438 | * | ||
439 | * @param code opcode to look for | ||
440 | * @param label label to look for, NULL for none | ||
441 | * @return previous command with the matching label | ||
442 | */ | ||
443 | static struct Command * | ||
444 | find_command (enum CommandCode code, | ||
445 | const char *label) | ||
446 | { | ||
447 | int i; | ||
448 | |||
449 | if (NULL == label) | ||
450 | return NULL; | ||
451 | for (i=off-1;i>=0;i--) | ||
452 | if ( (code == test_commands[i].code) && | ||
453 | (0 == strcmp (test_commands[i].label, | ||
454 | label)) ) | ||
455 | return &test_commands[i]; | ||
456 | GNUNET_break (0); | ||
457 | return NULL; | ||
458 | } | ||
459 | |||
460 | |||
461 | /** | ||
462 | * Function called from #GNUNET_ATS_performance_list_addresses when | ||
463 | * we process a #CMD_LIST_ADDRESSES command. | ||
464 | * | ||
465 | * @param cls the `struct Command` that caused the call | ||
466 | * @param address the address, NULL if ATS service was disconnected | ||
467 | * @param address_active #GNUNET_YES if this address is actively used | ||
468 | * to maintain a connection to a peer; | ||
469 | * #GNUNET_NO if the address is not actively used; | ||
470 | * #GNUNET_SYSERR if this address is no longer available for ATS | ||
471 | * @param bandwidth_out assigned outbound bandwidth for the connection | ||
472 | * @param bandwidth_in assigned inbound bandwidth for the connection | ||
473 | * @param prop performance data for the address | ||
474 | */ | ||
475 | static void | ||
476 | info_cb (void *cls, | ||
477 | const struct GNUNET_HELLO_Address *address, | ||
478 | int address_active, | ||
479 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, | ||
480 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, | ||
481 | const struct GNUNET_ATS_Properties *prop) | ||
482 | { | ||
483 | struct Command *c = cls; | ||
484 | struct CommandListAddresses *cmd = &c->details.list_addresses; | ||
485 | |||
486 | if (NULL == address) | ||
487 | { | ||
488 | cmd->alh = NULL; | ||
489 | /* we are done with the iteration, continue to execute */ | ||
490 | if ( (cmd->calls < cmd->min_calls) && | ||
491 | (cmd->active_calls < cmd->min_active_calls) ) | ||
492 | { | ||
493 | GNUNET_SCHEDULER_shutdown (); | ||
494 | return; | ||
495 | } | ||
496 | off++; | ||
497 | run_interpreter (); | ||
498 | return; | ||
499 | } | ||
500 | switch (address_active) | ||
501 | { | ||
502 | case GNUNET_YES: | ||
503 | cmd->active_calls++; | ||
504 | cmd->calls++; | ||
505 | break; | ||
506 | case GNUNET_NO: | ||
507 | cmd->calls++; | ||
508 | break; | ||
509 | case GNUNET_SYSERR: | ||
510 | return; | ||
511 | } | ||
512 | if ( (cmd->calls > cmd->max_calls) && | ||
513 | (cmd->active_calls < cmd->max_active_calls) ) | ||
514 | { | ||
515 | GNUNET_break (0); | ||
516 | GNUNET_ATS_performance_list_addresses_cancel (cmd->alh); | ||
517 | cmd->alh = NULL; | ||
518 | GNUNET_SCHEDULER_shutdown (); | ||
519 | return; | ||
520 | } | ||
521 | } | ||
522 | |||
523 | |||
524 | /** | ||
525 | * Main interpreter loop. Runs the steps of the test. | ||
526 | * | ||
527 | * @param cls NULL | ||
528 | * @param tc unused | ||
529 | */ | ||
530 | static void | ||
531 | interpreter (void *cls, | ||
532 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
533 | |||
534 | { | ||
535 | struct Command *cmd; | ||
536 | |||
537 | interpreter_task = NULL; | ||
538 | while (1) | ||
539 | { | ||
540 | cmd = &test_commands[off]; | ||
541 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
542 | "#%u: %d %s\n", | ||
543 | off, | ||
544 | (int) cmd->code, | ||
545 | (NULL != cmd->label) ? cmd->label : ""); | ||
546 | switch (cmd->code) | ||
547 | { | ||
548 | case CMD_END_PASS: | ||
549 | ret = 0; | ||
550 | GNUNET_SCHEDULER_shutdown (); | ||
551 | return; | ||
552 | case CMD_ADD_ADDRESS: | ||
553 | { | ||
554 | struct GNUNET_HELLO_Address *addr; | ||
555 | struct Session *session; | ||
556 | |||
557 | addr = make_address (cmd->details.add_address.pid, | ||
558 | cmd->details.add_address.addr_num, | ||
559 | cmd->details.add_address.addr_flags); | ||
560 | session = make_session (cmd->details.add_address.session); | ||
561 | if (cmd->details.add_address.expect_fail) | ||
562 | GNUNET_log_skip (1, GNUNET_NO); | ||
563 | cmd->details.add_address.ar | ||
564 | = GNUNET_ATS_address_add (sched_ats, | ||
565 | addr, | ||
566 | session, | ||
567 | &cmd->details.add_address.properties); | ||
568 | GNUNET_free (addr); | ||
569 | if (cmd->details.add_address.expect_fail) | ||
570 | { | ||
571 | GNUNET_log_skip (0, GNUNET_YES); | ||
572 | } | ||
573 | else if (NULL == cmd->details.add_address.ar) | ||
574 | { | ||
575 | GNUNET_break (0); | ||
576 | GNUNET_SCHEDULER_shutdown (); | ||
577 | return; | ||
578 | } | ||
579 | off++; | ||
580 | break; | ||
581 | } | ||
582 | case CMD_DEL_ADDRESS: | ||
583 | { | ||
584 | struct Command *add; | ||
585 | |||
586 | add = find_command (CMD_ADD_ADDRESS, | ||
587 | cmd->details.del_address.add_label); | ||
588 | GNUNET_assert (NULL != add->details.add_address.ar); | ||
589 | GNUNET_ATS_address_destroy (add->details.add_address.ar); | ||
590 | add->details.add_address.ar = NULL; | ||
591 | off++; | ||
592 | break; | ||
593 | } | ||
594 | case CMD_AWAIT_ADDRESS_SUGGESTION: | ||
595 | { | ||
596 | struct GNUNET_PeerIdentity pid; | ||
597 | struct GNUNET_HELLO_Address *addr; | ||
598 | struct Command *add; | ||
599 | struct AddressSuggestData *asd; | ||
600 | int done; | ||
601 | |||
602 | make_peer (cmd->details.await_address_suggestion.pid, | ||
603 | &pid); | ||
604 | asd = find_address_suggestion (&pid); | ||
605 | if (NULL == asd) | ||
606 | return; | ||
607 | if (GNUNET_NO == asd->active) | ||
608 | return; | ||
609 | done = GNUNET_YES; | ||
610 | if (NULL != cmd->details.await_address_suggestion.add_label) | ||
611 | { | ||
612 | done = GNUNET_NO; | ||
613 | add = find_command (CMD_ADD_ADDRESS, | ||
614 | cmd->details.await_address_suggestion.add_label); | ||
615 | addr = make_address (add->details.add_address.pid, | ||
616 | add->details.add_address.addr_num, | ||
617 | add->details.add_address.addr_flags); | ||
618 | if ( (asd->session == | ||
619 | make_session (add->details.add_address.session)) && | ||
620 | (0 == | ||
621 | GNUNET_HELLO_address_cmp (addr, | ||
622 | asd->address)) ) | ||
623 | done = GNUNET_YES; | ||
624 | GNUNET_free (addr); | ||
625 | } | ||
626 | if (GNUNET_NO == done) | ||
627 | return; | ||
628 | off++; | ||
629 | break; | ||
630 | } | ||
631 | case CMD_AWAIT_DISCONNECT_SUGGESTION: | ||
632 | { | ||
633 | struct GNUNET_PeerIdentity pid; | ||
634 | struct AddressSuggestData *asd; | ||
635 | |||
636 | make_peer (cmd->details.await_disconnect_suggestion.pid, | ||
637 | &pid); | ||
638 | asd = find_address_suggestion (&pid); | ||
639 | if (NULL == asd) | ||
640 | return; | ||
641 | if (GNUNET_NO == asd->active) | ||
642 | return; | ||
643 | off++; | ||
644 | break; | ||
645 | } | ||
646 | case CMD_REQUEST_CONNECTION_START: | ||
647 | { | ||
648 | struct GNUNET_PeerIdentity pid; | ||
649 | |||
650 | make_peer (cmd->details.request_connection_start.pid, | ||
651 | &pid); | ||
652 | cmd->details.request_connection_start.csh | ||
653 | = GNUNET_ATS_connectivity_suggest (con_ats, | ||
654 | &pid); | ||
655 | off++; | ||
656 | break; | ||
657 | } | ||
658 | case CMD_REQUEST_CONNECTION_STOP: | ||
659 | { | ||
660 | struct Command *start; | ||
661 | |||
662 | start = find_command (CMD_REQUEST_CONNECTION_START, | ||
663 | cmd->details.request_connection_stop.connect_label); | ||
664 | GNUNET_ATS_connectivity_suggest_cancel (start->details.request_connection_start.csh); | ||
665 | start->details.request_connection_start.csh = NULL; | ||
666 | off++; | ||
667 | break; | ||
668 | } | ||
669 | case CMD_AWAIT_ADDRESS_INFORMATION: | ||
670 | { | ||
671 | struct AddressInformationData *aid; | ||
672 | struct Command *add; | ||
673 | struct Command *update; | ||
674 | struct GNUNET_HELLO_Address *addr; | ||
675 | const struct GNUNET_ATS_Properties *cmp; | ||
676 | |||
677 | add = find_command (CMD_ADD_ADDRESS, | ||
678 | cmd->details.await_address_information.add_label); | ||
679 | update = find_command (CMD_UPDATE_ADDRESS, | ||
680 | cmd->details.await_address_information.update_label); | ||
681 | addr = make_address (add->details.add_address.pid, | ||
682 | add->details.add_address.addr_num, | ||
683 | add->details.add_address.addr_flags); | ||
684 | aid = find_address_information (addr); | ||
685 | GNUNET_free (addr); | ||
686 | if (NULL == update) | ||
687 | cmp = &add->details.add_address.properties; | ||
688 | else | ||
689 | cmp = &update->details.update_address.properties; | ||
690 | if ( (NULL != aid) && | ||
691 | (0 == memcmp (cmp, | ||
692 | &aid->properties, | ||
693 | sizeof (struct GNUNET_ATS_Properties))) ) | ||
694 | { | ||
695 | off++; | ||
696 | break; | ||
697 | } | ||
698 | return; | ||
699 | } | ||
700 | case CMD_UPDATE_ADDRESS: | ||
701 | { | ||
702 | struct Command *add; | ||
703 | |||
704 | add = find_command (CMD_ADD_ADDRESS, | ||
705 | cmd->details.update_address.add_label); | ||
706 | GNUNET_assert (NULL != add->details.add_address.ar); | ||
707 | GNUNET_ATS_address_update (add->details.add_address.ar, | ||
708 | &cmd->details.update_address.properties); | ||
709 | off++; | ||
710 | break; | ||
711 | } | ||
712 | case CMD_ADD_SESSION: | ||
713 | { | ||
714 | struct Command *add; | ||
715 | struct Session *session; | ||
716 | |||
717 | add = find_command (CMD_ADD_ADDRESS, | ||
718 | cmd->details.add_session.add_label); | ||
719 | session = make_session (cmd->details.add_session.session); | ||
720 | GNUNET_assert (NULL != add->details.add_address.ar); | ||
721 | GNUNET_ATS_address_add_session (add->details.add_address.ar, | ||
722 | session); | ||
723 | off++; | ||
724 | break; | ||
725 | } | ||
726 | case CMD_DEL_SESSION: | ||
727 | { | ||
728 | struct Command *add_address; | ||
729 | struct Command *add_session; | ||
730 | struct Session *session; | ||
731 | |||
732 | add_session = find_command (CMD_ADD_SESSION, | ||
733 | cmd->details.del_session.add_session_label); | ||
734 | add_address = find_command (CMD_ADD_ADDRESS, | ||
735 | add_session->details.add_session.add_label); | ||
736 | GNUNET_assert (NULL != add_address->details.add_address.ar); | ||
737 | session = make_session (add_session->details.add_session.session); | ||
738 | GNUNET_ATS_address_del_session (add_address->details.add_address.ar, | ||
739 | session); | ||
740 | off++; | ||
741 | break; | ||
742 | } | ||
743 | case CMD_CHANGE_PREFERENCE: | ||
744 | { | ||
745 | struct GNUNET_PeerIdentity pid; | ||
746 | |||
747 | make_peer (cmd->details.change_preference.pid, | ||
748 | &pid); | ||
749 | GNUNET_ATS_performance_change_preference (perf_ats, | ||
750 | &pid, | ||
751 | GNUNET_ATS_PREFERENCE_END); | ||
752 | off++; | ||
753 | break; | ||
754 | } | ||
755 | case CMD_PROVIDE_FEEDBACK: | ||
756 | { | ||
757 | struct GNUNET_PeerIdentity pid; | ||
758 | |||
759 | make_peer (cmd->details.provide_feedback.pid, | ||
760 | &pid); | ||
761 | GNUNET_ATS_performance_give_feedback (perf_ats, | ||
762 | &pid, | ||
763 | cmd->details.provide_feedback.scope, | ||
764 | GNUNET_ATS_PREFERENCE_END); | ||
765 | off++; | ||
766 | break; | ||
767 | } | ||
768 | case CMD_LIST_ADDRESSES: | ||
769 | { | ||
770 | struct GNUNET_PeerIdentity pid; | ||
771 | |||
772 | make_peer (cmd->details.list_addresses.pid, | ||
773 | &pid); | ||
774 | cmd->details.list_addresses.alh | ||
775 | = GNUNET_ATS_performance_list_addresses (perf_ats, | ||
776 | &pid, | ||
777 | cmd->details.list_addresses.all, | ||
778 | &info_cb, | ||
779 | cmd); | ||
780 | return; | ||
781 | } | ||
782 | } /* end switch */ | ||
783 | } /* end while(1) */ | ||
784 | } | ||
785 | |||
786 | |||
787 | /** | ||
788 | * Signature of a function called by ATS with the current bandwidth | ||
789 | * and address preferences as determined by ATS. | ||
790 | * | ||
791 | * @param cls closure, should point to "asc-closure" | ||
792 | * @param peer for which we suggest an address, NULL if ATS connection died | ||
793 | * @param address suggested address (including peer identity of the peer), | ||
794 | * may be NULL to signal disconnect from peer | ||
795 | * @param session session to use, NULL to establish a new outgoing session | ||
796 | * @param bandwidth_out assigned outbound bandwidth for the connection, | ||
797 | * 0 to signal disconnect | ||
798 | * @param bandwidth_in assigned inbound bandwidth for the connection, | ||
799 | * 0 to signal disconnect | ||
800 | */ | ||
801 | static void | ||
802 | address_suggest_cb (void *cls, | ||
803 | const struct GNUNET_PeerIdentity *peer, | ||
804 | const struct GNUNET_HELLO_Address *address, | ||
805 | struct Session *session, | ||
806 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, | ||
807 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) | ||
808 | { | ||
809 | const char *asc_cls = cls; | ||
810 | struct AddressSuggestData *asd; | ||
811 | |||
812 | GNUNET_break (0 == strcmp (asc_cls, "asc-closure")); | ||
813 | if (NULL == peer) | ||
814 | { | ||
815 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
816 | "Connection to ATS died, likely a crash!\n"); | ||
817 | GNUNET_SCHEDULER_shutdown (); | ||
818 | #if 0 | ||
819 | /* This is what we should do if we wanted to continue past | ||
820 | the ATS crash. */ | ||
821 | GNUNET_CONTAINER_multipeermap_iterate (p2asd, | ||
822 | &free_asd, | ||
823 | NULL); | ||
824 | GNUNET_CONTAINER_multipeermap_iterate (p2aid, | ||
825 | &free_aid, | ||
826 | NULL); | ||
827 | #endif | ||
828 | return; | ||
829 | } | ||
830 | |||
831 | asd = find_address_suggestion (peer); | ||
832 | if (NULL == asd) | ||
833 | { | ||
834 | asd = GNUNET_new (struct AddressSuggestData); | ||
835 | GNUNET_assert (GNUNET_YES == | ||
836 | GNUNET_CONTAINER_multipeermap_put (p2asd, | ||
837 | peer, | ||
838 | asd, | ||
839 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
840 | } | ||
841 | if ( (0 == ntohl (bandwidth_out.value__)) && | ||
842 | (0 == ntohl (bandwidth_in.value__)) ) | ||
843 | asd->active = GNUNET_NO; | ||
844 | else | ||
845 | asd->active = GNUNET_YES; | ||
846 | asd->bandwidth_out = bandwidth_out; | ||
847 | asd->bandwidth_in = bandwidth_in; | ||
848 | asd->session = session; | ||
849 | GNUNET_free_non_null (asd->address); | ||
850 | asd->address = NULL; | ||
851 | if (NULL != address) | ||
852 | asd->address = GNUNET_HELLO_address_copy (address); | ||
853 | run_interpreter (); | ||
854 | } | ||
855 | |||
856 | |||
857 | /** | ||
858 | * Signature of a function that is called with QoS information about an address. | ||
859 | * | ||
860 | * @param cls closure, should point to "aic-closure" | ||
861 | * @param address the address, NULL if ATS service was disconnected | ||
862 | * @param address_active #GNUNET_YES if this address is actively used | ||
863 | * to maintain a connection to a peer; | ||
864 | * #GNUNET_NO if the address is not actively used; | ||
865 | * #GNUNET_SYSERR if this address is no longer available for ATS | ||
866 | * @param bandwidth_out assigned outbound bandwidth for the connection | ||
867 | * @param bandwidth_in assigned inbound bandwidth for the connection | ||
868 | * @param prop performance data for the address | ||
869 | */ | ||
870 | static void | ||
871 | address_information_cb (void *cls, | ||
872 | const struct GNUNET_HELLO_Address *address, | ||
873 | int address_active, | ||
874 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, | ||
875 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, | ||
876 | const struct GNUNET_ATS_Properties *prop) | ||
877 | { | ||
878 | const char *aic_cls = cls; | ||
879 | struct AddressInformationData *aid; | ||
880 | |||
881 | GNUNET_break (0 == strcmp (aic_cls, "aic-closure")); | ||
882 | if (NULL == address) | ||
883 | { | ||
884 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
885 | "Connection to ATS died, likely a crash!\n"); | ||
886 | GNUNET_CONTAINER_multipeermap_iterate (p2aid, | ||
887 | &free_aid, | ||
888 | NULL); | ||
889 | return; | ||
890 | } | ||
891 | |||
892 | aid = find_address_information (address); | ||
893 | if (NULL == aid) | ||
894 | { | ||
895 | aid = GNUNET_new (struct AddressInformationData); | ||
896 | aid->address = GNUNET_HELLO_address_copy (address); | ||
897 | GNUNET_assert (GNUNET_YES == | ||
898 | GNUNET_CONTAINER_multipeermap_put (p2aid, | ||
899 | &address->peer, | ||
900 | aid, | ||
901 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); | ||
902 | } | ||
903 | aid->active = address_active; | ||
904 | aid->bandwidth_out = bandwidth_out; | ||
905 | aid->bandwidth_in = bandwidth_in; | ||
906 | aid->properties = *prop; | ||
907 | run_interpreter (); | ||
908 | } | ||
909 | |||
910 | |||
911 | /** | ||
912 | * Function run once the ATS service has been started. | ||
913 | * | ||
914 | * @param cls NULL | ||
915 | * @param cfg configuration for the testcase | ||
916 | * @param peer handle to the peer | ||
917 | */ | ||
918 | static void | ||
919 | run (void *cls, | ||
920 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
921 | struct GNUNET_TESTING_Peer *peer) | ||
922 | { | ||
923 | p2asd = GNUNET_CONTAINER_multipeermap_create (128, | ||
924 | GNUNET_NO); | ||
925 | p2aid = GNUNET_CONTAINER_multipeermap_create (128, | ||
926 | GNUNET_NO); | ||
927 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
928 | &end, | ||
929 | NULL); | ||
930 | |||
931 | sched_ats = GNUNET_ATS_scheduling_init (cfg, | ||
932 | &address_suggest_cb, | ||
933 | "asc-closure"); | ||
934 | if (NULL == sched_ats) | ||
935 | { | ||
936 | GNUNET_break (0); | ||
937 | GNUNET_SCHEDULER_shutdown (); | ||
938 | return; | ||
939 | } | ||
940 | con_ats = GNUNET_ATS_connectivity_init (cfg); | ||
941 | if (NULL == con_ats) | ||
942 | { | ||
943 | GNUNET_break (0); | ||
944 | GNUNET_SCHEDULER_shutdown (); | ||
945 | return; | ||
946 | } | ||
947 | perf_ats = GNUNET_ATS_performance_init (cfg, | ||
948 | &address_information_cb, | ||
949 | "aic-closure"); | ||
950 | if (NULL == perf_ats) | ||
951 | { | ||
952 | GNUNET_break (0); | ||
953 | GNUNET_SCHEDULER_shutdown (); | ||
954 | return; | ||
955 | } | ||
956 | run_interpreter (); | ||
957 | } | ||
958 | |||
959 | |||
960 | /** | ||
961 | * Run ATS test. | ||
962 | * | ||
963 | * @param argc length of @a argv | ||
964 | * @param argv command line | ||
965 | * @param cmds commands to run with the interpreter | ||
966 | * @param timeout how long is the test allowed to take? | ||
967 | * @return 0 on success | ||
968 | */ | ||
969 | int | ||
970 | TEST_ATS_run (int argc, | ||
971 | char *argv[], | ||
972 | struct Command *cmds, | ||
973 | struct GNUNET_TIME_Relative timeout) | ||
974 | { | ||
975 | char *test_filename = GNUNET_strdup (argv[0]); | ||
976 | char *sep; | ||
977 | char *config_file; | ||
978 | char *underscore; | ||
979 | |||
980 | test_commands = cmds; | ||
981 | TIMEOUT = timeout; | ||
982 | if (NULL != (sep = strstr (test_filename, ".exe"))) | ||
983 | sep[0] = '\0'; | ||
984 | underscore = strrchr (test_filename, (int) '_'); | ||
985 | GNUNET_assert (NULL != underscore); | ||
986 | GNUNET_asprintf (&config_file, | ||
987 | "test_ats_api_%s.conf", | ||
988 | underscore + 1); | ||
989 | ret = 2; | ||
990 | if (0 != GNUNET_TESTING_peer_run ("test-ats-api", | ||
991 | config_file, | ||
992 | &run, NULL)) | ||
993 | ret = 1; | ||
994 | GNUNET_free (test_filename); | ||
995 | GNUNET_free (config_file); | ||
996 | return ret; | ||
997 | } | ||
998 | |||
999 | /* end of test_ats_lib.c */ | ||