aboutsummaryrefslogtreecommitdiff
path: root/src/service/transport/transport-testing2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/transport/transport-testing2.c')
-rw-r--r--src/service/transport/transport-testing2.c924
1 files changed, 924 insertions, 0 deletions
diff --git a/src/service/transport/transport-testing2.c b/src/service/transport/transport-testing2.c
new file mode 100644
index 000000000..afa0b0ad4
--- /dev/null
+++ b/src/service/transport/transport-testing2.c
@@ -0,0 +1,924 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2006, 2009, 2015, 2016 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 transport-testing.c
22 * @brief testing lib for transport service
23 * @author Matthias Wachs
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "transport-testing2.h"
28
29
30#define LOG(kind, ...) GNUNET_log_from (kind, "transport-testing", __VA_ARGS__)
31
32
33static struct GNUNET_TRANSPORT_TESTING_PeerContext *
34find_peer_context (struct GNUNET_TRANSPORT_TESTING_Handle *tth,
35 const struct GNUNET_PeerIdentity *peer)
36{
37 struct GNUNET_TRANSPORT_TESTING_PeerContext *t;
38
39 for (t = tth->p_head; NULL != t; t = t->next)
40 if (0 == memcmp (&t->id,
41 peer,
42 sizeof(struct GNUNET_PeerIdentity)))
43 return t;
44 return NULL;
45}
46
47
48/**
49 * Find any connecting context matching the given pair of peers.
50 *
51 * @param p1 first peer
52 * @param p2 second peer
53 * @param cb function to call
54 * @param cb_cls closure for @a cb
55 */
56void
57GNUNET_TRANSPORT_TESTING_find_connecting_context (struct
58 GNUNET_TRANSPORT_TESTING_PeerContext
59 *p1,
60 struct
61 GNUNET_TRANSPORT_TESTING_PeerContext
62 *p2,
63 GNUNET_TRANSPORT_TESTING_ConnectContextCallback
64 cb,
65 void *cb_cls)
66{
67 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p1->tth;
68 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
69 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
70
71 for (cc = tth->cc_head; NULL != cc; cc = ccn)
72 {
73 ccn = cc->next;
74 if ((cc->p1 == p1) &&
75 (cc->p2 == p2))
76 cb (cb_cls,
77 cc);
78 }
79}
80
81
82static void
83set_p1c (void *cls,
84 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
85{
86 int *found = cls;
87
88 if (NULL != found)
89 *found = GNUNET_YES;
90 cx->p1_c = GNUNET_YES;
91}
92
93
94static void
95set_mq (void *cls,
96 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
97{
98 struct GNUNET_MQ_Handle *mq = cls;
99
100 cx->mq = mq;
101}
102
103
104static void
105set_p2c (void *cls,
106 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
107{
108 int *found = cls;
109
110 if (NULL != found)
111 *found = GNUNET_YES;
112 cx->p2_c = GNUNET_YES;
113}
114
115
116static void
117clear_p1c (void *cls,
118 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
119{
120 int *found = cls;
121
122 if (NULL != found)
123 *found = GNUNET_YES;
124 cx->p1_c = GNUNET_NO;
125}
126
127
128static void
129clear_p2c (void *cls,
130 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cx)
131{
132 int *found = cls;
133
134 if (NULL != found)
135 *found = GNUNET_YES;
136 cx->p2_c = GNUNET_NO;
137}
138
139
140static void *
141notify_connect (void *cls,
142 const struct GNUNET_PeerIdentity *peer,
143 struct GNUNET_MQ_Handle *mq)
144{
145 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
146 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
147 char *p2_s;
148 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2;
149 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
150 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
151 int found;
152 void *ret;
153
154 p2 = find_peer_context (p->tth,
155 peer);
156 if (NULL != p->nc)
157 ret = p->nc (p->cb_cls,
158 peer,
159 mq);
160 else
161 ret = NULL;
162
163 if (NULL != p2)
164 GNUNET_asprintf (&p2_s,
165 "%u (`%s')",
166 p2->no,
167 GNUNET_i2s (&p2->id));
168 else
169 GNUNET_asprintf (&p2_s,
170 "`%s'",
171 GNUNET_i2s (peer));
172 LOG (GNUNET_ERROR_TYPE_DEBUG,
173 "Peers %s connected to peer %u (`%s')\n",
174 p2_s,
175 p->no,
176 GNUNET_i2s (&p->id));
177 GNUNET_free (p2_s);
178 /* update flags in connecting contexts */
179 found = GNUNET_NO;
180 GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
181 p2,
182 &set_p1c,
183 &found);
184 if (GNUNET_NO == found)
185 {
186 cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest);
187 cc->p1 = p;
188 cc->p2 = p2;
189 cc->p1_c = GNUNET_YES;
190 GNUNET_CONTAINER_DLL_insert (tth->cc_head,
191 tth->cc_tail,
192 cc);
193 }
194 found = GNUNET_NO;
195 GNUNET_TRANSPORT_TESTING_find_connecting_context (p2,
196 p,
197 &set_p2c,
198 &found);
199 if (GNUNET_NO == found)
200 {
201 cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest);
202 cc->p1 = p2;
203 cc->p2 = p;
204 cc->p1_c = GNUNET_YES;
205 GNUNET_CONTAINER_DLL_insert (tth->cc_head,
206 tth->cc_tail,
207 cc);
208 }
209 GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
210 p2,
211 &set_mq,
212 mq);
213 /* update set connected flag for all requests */
214 for (cc = tth->cc_head; NULL != cc; cc = cc->next)
215 {
216 if (GNUNET_YES == cc->connected)
217 continue;
218 if ((GNUNET_YES == cc->p1_c) &&
219 (GNUNET_YES == cc->p2_c))
220 {
221 cc->connected = GNUNET_YES;
222 /* stop trying to connect */
223 if (NULL != cc->tct)
224 {
225 GNUNET_SCHEDULER_cancel (cc->tct);
226 cc->tct = NULL;
227 }
228 if (NULL != cc->ah_sh)
229 {
230 GNUNET_TRANSPORT_application_suggest_cancel (cc->ah_sh);
231 cc->ah_sh = NULL;
232 }
233 }
234 }
235 /* then notify application */
236 for (cc = tth->cc_head; NULL != cc; cc = ccn)
237 {
238 ccn = cc->next;
239 if ((GNUNET_YES == cc->connected) &&
240 (NULL != cc->cb))
241 {
242 cc->cb (cc->cb_cls);
243 cc->cb = NULL; /* only notify once! */
244 }
245 }
246 return ret;
247}
248
249
250/**
251 * Offer the current HELLO of P2 to P1.
252 *
253 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequest`
254 */
255static void
256offer_hello (void *cls);
257
258
259static void
260notify_disconnect (void *cls,
261 const struct GNUNET_PeerIdentity *peer,
262 void *handler_cls)
263{
264 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
265 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
266 char *p2_s;
267 /* Find PeerContext */
268 int no = 0;
269 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2 = NULL;
270 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
271
272 p2 = find_peer_context (p->tth,
273 peer);
274 no = p->no;
275 if (NULL != p2)
276 GNUNET_asprintf (&p2_s,
277 "%u (`%s')",
278 p2->no,
279 GNUNET_i2s (&p2->id));
280 else
281 GNUNET_asprintf (&p2_s,
282 "`%s'",
283 GNUNET_i2s (peer));
284 LOG (GNUNET_ERROR_TYPE_DEBUG,
285 "Peers %s disconnected from peer %u (`%s')\n",
286 p2_s,
287 no,
288 GNUNET_i2s (&p->id));
289 GNUNET_free (p2_s);
290 /* notify about disconnect */
291 if (NULL != p->nd)
292 p->nd (p->cb_cls,
293 peer,
294 handler_cls);
295 if (NULL == p2)
296 return;
297 /* clear MQ, it is now invalid */
298 GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
299 p2,
300 &set_mq,
301 NULL);
302 /* update set connected flags for all requests */
303 GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
304 p2,
305 &clear_p1c,
306 NULL);
307 GNUNET_TRANSPORT_TESTING_find_connecting_context (p2,
308 p,
309 &clear_p2c,
310 NULL);
311 /* resume connectivity requests as necessary */
312 for (cc = tth->cc_head; NULL != cc; cc = cc->next)
313 {
314 if (GNUNET_NO == cc->connected)
315 continue;
316 if ((GNUNET_YES != cc->p1_c) ||
317 (GNUNET_YES != cc->p2_c))
318 {
319 cc->connected = GNUNET_NO;
320 /* start trying to connect */
321 if (NULL == cc->tct)
322 cc->tct = GNUNET_SCHEDULER_add_now (&offer_hello,
323 cc);
324 if (NULL == cc->ah_sh)
325 cc->ah_sh = GNUNET_TRANSPORT_application_suggest (cc->p1->ah,
326 &p2->id,
327 GNUNET_MQ_PRIO_BEST_EFFORT,
328 GNUNET_BANDWIDTH_ZERO);
329 }
330 }
331}
332
333
334static void
335retrieve_hello (void *cls);
336
337static void
338hello_iter_cb (void *cb_cls,
339 const struct GNUNET_PEERSTORE_Record *record,
340 const char *emsg)
341{
342 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cb_cls;
343 if (NULL == record)
344 {
345 p->pic = NULL;
346 if (NULL != p->start_cb)
347 p->rh_task = GNUNET_SCHEDULER_add_now (retrieve_hello, p);
348 return;
349 }
350 // Check record type et al?
351 p->hello_size = record->value_size;
352 p->hello = GNUNET_malloc (p->hello_size);
353 memcpy (p->hello, record->value, p->hello_size);
354 p->hello[p->hello_size - 1] = '\0';
355
356 GNUNET_PEERSTORE_iterate_cancel (p->pic);
357 p->pic = NULL;
358 if (NULL != p->start_cb)
359 {
360 LOG (GNUNET_ERROR_TYPE_DEBUG,
361 "Peer %u (`%s') successfully started\n",
362 p->no,
363 GNUNET_i2s (&p->id));
364 p->start_cb (p->start_cb_cls);
365 p->start_cb = NULL;
366 }
367}
368
369
370static void
371retrieve_hello (void *cls)
372{
373 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
374 p->rh_task = NULL;
375 p->pic = GNUNET_PEERSTORE_iterate (p->ph,
376 "transport",
377 &p->id,
378 GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY,
379 hello_iter_cb,
380 p);
381
382}
383
384
385struct GNUNET_TRANSPORT_TESTING_PeerContext *
386GNUNET_TRANSPORT_TESTING_start_peer (struct
387 GNUNET_TRANSPORT_TESTING_Handle *tth,
388 const char *cfgname,
389 int peer_id,
390 const struct
391 GNUNET_MQ_MessageHandler *handlers,
392 GNUNET_TRANSPORT_NotifyConnect nc,
393 GNUNET_TRANSPORT_NotifyDisconnect nd,
394 void *cb_cls,
395 GNUNET_SCHEDULER_TaskCallback start_cb,
396 void *start_cb_cls)
397{
398 char *emsg = NULL;
399 struct GNUNET_TRANSPORT_TESTING_PeerContext *p;
400 struct GNUNET_PeerIdentity dummy;
401 unsigned int i;
402
403 if (GNUNET_NO == GNUNET_DISK_file_test (cfgname))
404 {
405 LOG (GNUNET_ERROR_TYPE_ERROR,
406 "File not found: `%s'\n",
407 cfgname);
408 return NULL;
409 }
410
411 p = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_PeerContext);
412 p->tth = tth;
413 p->nc = nc;
414 p->nd = nd;
415 if (NULL != handlers)
416 {
417 for (i = 0; NULL != handlers[i].cb; i++)
418 ;
419 p->handlers = GNUNET_new_array (i + 1,
420 struct GNUNET_MQ_MessageHandler);
421 GNUNET_memcpy (p->handlers,
422 handlers,
423 i * sizeof(struct GNUNET_MQ_MessageHandler));
424 }
425 if (NULL != cb_cls)
426 p->cb_cls = cb_cls;
427 else
428 p->cb_cls = p;
429 p->start_cb = start_cb;
430 if (NULL != start_cb_cls)
431 p->start_cb_cls = start_cb_cls;
432 else
433 p->start_cb_cls = p;
434 GNUNET_CONTAINER_DLL_insert (tth->p_head,
435 tth->p_tail,
436 p);
437
438 /* Create configuration and call testing lib to modify it */
439 p->cfg = GNUNET_CONFIGURATION_create ();
440 GNUNET_assert (GNUNET_OK ==
441 GNUNET_CONFIGURATION_load (p->cfg, cfgname));
442 if (GNUNET_SYSERR ==
443 GNUNET_TESTING_configuration_create (tth->tl_system,
444 p->cfg))
445 {
446 LOG (GNUNET_ERROR_TYPE_ERROR,
447 "Testing library failed to create unique configuration based on `%s'\n",
448 cfgname);
449 GNUNET_CONFIGURATION_destroy (p->cfg);
450 GNUNET_free (p);
451 return NULL;
452 }
453
454 p->no = peer_id;
455 /* Configure peer with configuration */
456 p->peer = GNUNET_TESTING_peer_configure (tth->tl_system,
457 p->cfg,
458 p->no,
459 NULL,
460 &emsg);
461 if (NULL == p->peer)
462 {
463 LOG (GNUNET_ERROR_TYPE_ERROR,
464 "Testing library failed to create unique configuration based on `%s': `%s'\n",
465 cfgname,
466 emsg);
467 GNUNET_TRANSPORT_TESTING_stop_peer (p);
468 GNUNET_free (emsg);
469 return NULL;
470 }
471
472 if (GNUNET_OK != GNUNET_TESTING_peer_start (p->peer))
473 {
474 LOG (GNUNET_ERROR_TYPE_ERROR,
475 "Testing library failed to create unique configuration based on `%s'\n",
476 cfgname);
477 GNUNET_TRANSPORT_TESTING_stop_peer (p);
478 return NULL;
479 }
480
481 memset (&dummy,
482 '\0',
483 sizeof(dummy));
484 GNUNET_TESTING_peer_get_identity (p->peer,
485 &p->id);
486 if (0 == memcmp (&dummy,
487 &p->id,
488 sizeof(struct GNUNET_PeerIdentity)))
489 {
490 LOG (GNUNET_ERROR_TYPE_ERROR,
491 "Testing library failed to obtain peer identity for peer %u\n",
492 p->no);
493 GNUNET_TRANSPORT_TESTING_stop_peer (p);
494 return NULL;
495 }
496 LOG (GNUNET_ERROR_TYPE_DEBUG,
497 "Peer %u configured with identity `%s'\n",
498 p->no,
499 GNUNET_i2s_full (&p->id));
500 p->th = GNUNET_TRANSPORT_core_connect (p->cfg,
501 NULL,
502 handlers,
503 p,
504 &notify_connect,
505 &notify_disconnect);
506 if (NULL == p->th)
507 {
508 LOG (GNUNET_ERROR_TYPE_ERROR,
509 "Failed to connect to transport service for peer `%s': `%s'\n",
510 cfgname,
511 emsg);
512 GNUNET_TRANSPORT_TESTING_stop_peer (p);
513 GNUNET_free (emsg);
514 return NULL;
515 }
516 p->ah = GNUNET_TRANSPORT_application_init (p->cfg);
517 if (NULL == p->ah)
518 {
519 LOG (GNUNET_ERROR_TYPE_ERROR,
520 "Failed to connect to TNG service for peer `%s': `%s'\n",
521 cfgname,
522 emsg);
523 GNUNET_TRANSPORT_TESTING_stop_peer (p);
524 GNUNET_free (emsg);
525 return NULL;
526 }
527 p->ph = GNUNET_PEERSTORE_connect (p->cfg);
528 // FIXME Error handling
529 p->rh_task = GNUNET_SCHEDULER_add_now (retrieve_hello, p);
530
531 return p;
532}
533
534
535int
536GNUNET_TRANSPORT_TESTING_restart_peer (struct
537 GNUNET_TRANSPORT_TESTING_PeerContext *p,
538 GNUNET_SCHEDULER_TaskCallback restart_cb,
539 void *restart_cb_cls)
540{
541 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
542 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
543
544 /* shutdown */
545 LOG (GNUNET_ERROR_TYPE_DEBUG,
546 "Stopping peer %u (`%s')\n",
547 p->no,
548 GNUNET_i2s (&p->id));
549 if (NULL != p->pic)
550 {
551 GNUNET_PEERSTORE_iterate_cancel (p->pic);
552 p->pic = NULL;
553 }
554 if (NULL != p->th)
555 {
556 GNUNET_TRANSPORT_core_disconnect (p->th);
557 p->th = NULL;
558 }
559 for (cc = p->tth->cc_head; NULL != cc; cc = ccn)
560 {
561 ccn = cc->next;
562 if ((cc->p1 == p) ||
563 (cc->p2 == p))
564 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
565 }
566 if (NULL != p->ah)
567 {
568 GNUNET_TRANSPORT_application_done (p->ah);
569 p->ah = NULL;
570 }
571 if (GNUNET_SYSERR ==
572 GNUNET_TESTING_peer_stop (p->peer))
573 {
574 LOG (GNUNET_ERROR_TYPE_ERROR,
575 "Failed to stop peer %u (`%s')\n",
576 p->no,
577 GNUNET_i2s (&p->id));
578 return GNUNET_SYSERR;
579 }
580
581 sleep (5); // YUCK!
582
583 LOG (GNUNET_ERROR_TYPE_DEBUG,
584 "Restarting peer %u (`%s')\n",
585 p->no,
586 GNUNET_i2s (&p->id));
587 /* restart */
588 if (GNUNET_SYSERR == GNUNET_TESTING_peer_start (p->peer))
589 {
590 LOG (GNUNET_ERROR_TYPE_ERROR,
591 "Failed to restart peer %u (`%s')\n",
592 p->no,
593 GNUNET_i2s (&p->id));
594 return GNUNET_SYSERR;
595 }
596
597 GNUNET_assert (NULL == p->start_cb);
598 p->start_cb = restart_cb;
599 p->start_cb_cls = restart_cb_cls;
600
601 p->th = GNUNET_TRANSPORT_core_connect (p->cfg,
602 NULL,
603 p->handlers,
604 p,
605 &notify_connect,
606 &notify_disconnect);
607 GNUNET_assert (NULL != p->th);
608 p->ah = GNUNET_TRANSPORT_application_init (p->cfg);
609 p->pic = GNUNET_PEERSTORE_iterate (p->ph,
610 "transport",
611 &p->id,
612 GNUNET_PEERSTORE_TRANSPORT_HELLO_KEY,
613 hello_iter_cb,
614 p);
615 GNUNET_assert (NULL != p->pic);
616 return GNUNET_OK;
617}
618
619
620/**
621 * Shutdown the given peer
622 *
623 * @param p the peer
624 */
625void
626GNUNET_TRANSPORT_TESTING_stop_peer (struct
627 GNUNET_TRANSPORT_TESTING_PeerContext *p)
628{
629 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
630 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
631 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
632 /* shutdown */
633 LOG (GNUNET_ERROR_TYPE_DEBUG,
634 "Stopping peer %u (`%s')\n",
635 p->no,
636 GNUNET_i2s (&p->id));
637
638 for (cc = tth->cc_head; NULL != cc; cc = ccn)
639 {
640 ccn = cc->next;
641 if ((cc->p1 == p) ||
642 (cc->p2 == p))
643 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
644 }
645 if (NULL != p->pic)
646 {
647 GNUNET_PEERSTORE_iterate_cancel (p->pic);
648 p->pic = NULL;
649 }
650 if (NULL != p->th)
651 {
652 GNUNET_TRANSPORT_core_disconnect (p->th);
653 p->th = NULL;
654 }
655 if (NULL != p->ah)
656 {
657 GNUNET_TRANSPORT_application_done (p->ah);
658 p->ah = NULL;
659 }
660 if (NULL != p->ph)
661 {
662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
663 "Disconnecting from PEERSTORE service\n");
664 GNUNET_PEERSTORE_disconnect (p->ph, GNUNET_NO);
665 p->ph = NULL;
666 }
667
668 if (NULL != p->peer)
669 {
670 if (GNUNET_OK !=
671 GNUNET_TESTING_peer_stop (p->peer))
672 {
673 LOG (GNUNET_ERROR_TYPE_DEBUG,
674 "Testing lib failed to stop peer %u (`%s')\n",
675 p->no,
676 GNUNET_i2s (&p->id));
677 }
678 GNUNET_TESTING_peer_destroy (p->peer);
679 p->peer = NULL;
680 }
681 if (NULL != p->hello)
682 {
683 GNUNET_free (p->hello);
684 p->hello = NULL;
685 }
686 if (NULL != p->cfg)
687 {
688 GNUNET_CONFIGURATION_destroy (p->cfg);
689 p->cfg = NULL;
690 }
691 if (NULL != p->handlers)
692 {
693 GNUNET_free (p->handlers);
694 p->handlers = NULL;
695 }
696 GNUNET_CONTAINER_DLL_remove (tth->p_head,
697 tth->p_tail,
698 p);
699 LOG (GNUNET_ERROR_TYPE_DEBUG,
700 "Peer %u (`%s') stopped\n",
701 p->no,
702 GNUNET_i2s (&p->id));
703 if (NULL != p->rh_task)
704 GNUNET_SCHEDULER_cancel (p->rh_task);
705 p->rh_task = NULL;
706 GNUNET_free (p);
707}
708
709
710/**
711 * Function called after the HELLO was passed to the
712 * transport service.
713 * FIXME maybe schedule the application_validate somehow
714 */
715/*
716 static void
717 hello_offered (void *cls)
718 {
719 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = cls;
720
721 cc->oh = NULL;
722 cc->tct = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
723 &offer_hello,
724 cc);
725 }*/
726
727
728static void
729offer_hello (void *cls)
730{
731 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = cls;
732 struct GNUNET_TRANSPORT_TESTING_PeerContext *p1 = cc->p1;
733 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2 = cc->p2;
734 struct GNUNET_TIME_Absolute t;
735 enum GNUNET_NetworkType nt = 0;
736 char *addr;
737
738 cc->tct = NULL;
739 {
740 char *p2_s = GNUNET_strdup (GNUNET_i2s (&p2->id));
741
742 LOG (GNUNET_ERROR_TYPE_DEBUG,
743 "Asking peer %u (`%s') to connect peer %u (`%s'), providing HELLO with %s\n",
744 p1->no,
745 GNUNET_i2s (&p1->id),
746 p2->no,
747 p2_s,
748 p2->hello);
749 GNUNET_free (p2_s);
750 }
751
752 addr = GNUNET_HELLO_extract_address (p2->hello,
753 p2->hello_size,
754 &p2->id,
755 &nt,
756 &t);
757 GNUNET_assert (NULL != addr);
758 GNUNET_assert (NULL != p1->hello);
759 GNUNET_TRANSPORT_application_validate (p1->ah,
760 &p2->id,
761 nt,
762 addr);
763 GNUNET_free (addr);
764}
765
766
767/**
768 * Initiate a connection from p1 to p2 by offering p1 p2's HELLO message
769 *
770 * Remarks: start_peer's notify_connect callback can be called before.
771 *
772 * @param tth transport testing handle
773 * @param p1 peer 1
774 * @param p2 peer 2
775 * @param cb the callback to call when both peers notified that they are connected
776 * @param cls callback cls
777 * @return a connect request handle
778 */
779struct GNUNET_TRANSPORT_TESTING_ConnectRequest *
780GNUNET_TRANSPORT_TESTING_connect_peers (struct
781 GNUNET_TRANSPORT_TESTING_PeerContext *p1,
782 struct
783 GNUNET_TRANSPORT_TESTING_PeerContext *p2,
784 GNUNET_SCHEDULER_TaskCallback cb,
785 void *cls)
786{
787 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p1->tth;
788 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
789 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
790
791 ccn = NULL;
792 for (cc = tth->cc_head; NULL != cc; cc = cc->next)
793 {
794 if ((cc->p1 == p1) &&
795 (cc->p2 == p2))
796 {
797 ccn = cc;
798 break;
799 }
800 }
801
802 cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest);
803 cc->p1 = p1;
804 cc->p2 = p2;
805 cc->cb = cb;
806 if (NULL != cls)
807 cc->cb_cls = cls;
808 else
809 cc->cb_cls = cc;
810 if (NULL != ccn)
811 {
812 cc->p1_c = ccn->p1_c;
813 cc->p2_c = ccn->p2_c;
814 cc->connected = ccn->connected;
815 }
816 GNUNET_CONTAINER_DLL_insert (tth->cc_head,
817 tth->cc_tail,
818 cc);
819 cc->tct = GNUNET_SCHEDULER_add_now (&offer_hello,
820 cc);
821 cc->ah_sh = GNUNET_TRANSPORT_application_suggest (cc->p1->ah,
822 &p2->id,
823 GNUNET_MQ_PRIO_BEST_EFFORT,
824 GNUNET_BANDWIDTH_ZERO);
825 LOG (GNUNET_ERROR_TYPE_DEBUG,
826 "New connect request %p\n",
827 cc);
828 return cc;
829}
830
831
832void
833GNUNET_TRANSPORT_TESTING_connect_peers_cancel (struct
834 GNUNET_TRANSPORT_TESTING_ConnectRequest
835 *cc)
836{
837 struct GNUNET_TRANSPORT_TESTING_Handle *tth = cc->p1->tth;
838
839 LOG (GNUNET_ERROR_TYPE_DEBUG,
840 "Canceling connect request!\n");
841 if (NULL != cc->tct)
842 {
843 GNUNET_SCHEDULER_cancel (cc->tct);
844 cc->tct = NULL;
845 }
846 if (NULL != cc->ah_sh)
847 {
848 GNUNET_TRANSPORT_application_suggest_cancel (cc->ah_sh);
849 cc->ah_sh = NULL;
850 }
851 GNUNET_CONTAINER_DLL_remove (tth->cc_head,
852 tth->cc_tail,
853 cc);
854 GNUNET_free (cc);
855}
856
857
858/**
859 * Clean up the transport testing
860 *
861 * @param tth transport testing handle
862 */
863void
864GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_Handle *tth)
865{
866 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
867 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ct;
868 struct GNUNET_TRANSPORT_TESTING_PeerContext *p;
869 struct GNUNET_TRANSPORT_TESTING_PeerContext *t;
870
871 if (NULL == tth)
872 return;
873 cc = tth->cc_head;
874 while (NULL != cc)
875 {
876 ct = cc->next;
877 LOG (GNUNET_ERROR_TYPE_ERROR,
878 "Developer forgot to cancel connect request!\n");
879 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
880 cc = ct;
881 }
882 p = tth->p_head;
883 while (NULL != p)
884 {
885 t = p->next;
886 LOG (GNUNET_ERROR_TYPE_ERROR,
887 "Developer forgot to stop peer!\n");
888 GNUNET_TRANSPORT_TESTING_stop_peer (p);
889 p = t;
890 }
891 GNUNET_TESTING_system_destroy (tth->tl_system,
892 GNUNET_YES);
893
894 GNUNET_free (tth);
895}
896
897
898/**
899 * Initialize the transport testing
900 *
901 * @return transport testing handle
902 */
903struct GNUNET_TRANSPORT_TESTING_Handle *
904GNUNET_TRANSPORT_TESTING_init ()
905{
906 struct GNUNET_TRANSPORT_TESTING_Handle *tth;
907
908 tth = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_Handle);
909 tth->tl_system = GNUNET_TESTING_system_create ("transport-testing",
910 NULL,
911 NULL,
912 NULL);
913 if (NULL == tth->tl_system)
914 {
915 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
916 "Failed to initialize testing library!\n");
917 GNUNET_free (tth);
918 return NULL;
919 }
920 return tth;
921}
922
923
924/* end of transport-testing.c */