aboutsummaryrefslogtreecommitdiff
path: root/src/transport/transport-testing.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/transport-testing.c')
-rw-r--r--src/transport/transport-testing.c932
1 files changed, 0 insertions, 932 deletions
diff --git a/src/transport/transport-testing.c b/src/transport/transport-testing.c
deleted file mode 100644
index baced62e3..000000000
--- a/src/transport/transport-testing.c
+++ /dev/null
@@ -1,932 +0,0 @@
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-testing.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->oh)
229 {
230 GNUNET_TRANSPORT_offer_hello_cancel (cc->oh);
231 cc->oh = NULL;
232 }
233 if (NULL != cc->ats_sh)
234 {
235 GNUNET_ATS_connectivity_suggest_cancel (cc->ats_sh);
236 cc->ats_sh = NULL;
237 }
238 }
239 }
240 /* then notify application */
241 for (cc = tth->cc_head; NULL != cc; cc = ccn)
242 {
243 ccn = cc->next;
244 if ((GNUNET_YES == cc->connected) &&
245 (NULL != cc->cb))
246 {
247 cc->cb (cc->cb_cls);
248 cc->cb = NULL; /* only notify once! */
249 }
250 }
251 return ret;
252}
253
254
255/**
256 * Offer the current HELLO of P2 to P1.
257 *
258 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequest`
259 */
260static void
261offer_hello (void *cls);
262
263
264static void
265notify_disconnect (void *cls,
266 const struct GNUNET_PeerIdentity *peer,
267 void *handler_cls)
268{
269 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cls;
270 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
271 char *p2_s;
272 /* Find PeerContext */
273 int no = 0;
274 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2 = NULL;
275 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
276
277 p2 = find_peer_context (p->tth,
278 peer);
279 no = p->no;
280 if (NULL != p2)
281 GNUNET_asprintf (&p2_s,
282 "%u (`%s')",
283 p2->no,
284 GNUNET_i2s (&p2->id));
285 else
286 GNUNET_asprintf (&p2_s,
287 "`%s'",
288 GNUNET_i2s (peer));
289 LOG (GNUNET_ERROR_TYPE_DEBUG,
290 "Peers %s disconnected from peer %u (`%s')\n",
291 p2_s,
292 no,
293 GNUNET_i2s (&p->id));
294 GNUNET_free (p2_s);
295 /* notify about disconnect */
296 if (NULL != p->nd)
297 p->nd (p->cb_cls,
298 peer,
299 handler_cls);
300 if (NULL == p2)
301 return;
302 /* clear MQ, it is now invalid */
303 GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
304 p2,
305 &set_mq,
306 NULL);
307 /* update set connected flags for all requests */
308 GNUNET_TRANSPORT_TESTING_find_connecting_context (p,
309 p2,
310 &clear_p1c,
311 NULL);
312 GNUNET_TRANSPORT_TESTING_find_connecting_context (p2,
313 p,
314 &clear_p2c,
315 NULL);
316 /* resume connectivity requests as necessary */
317 for (cc = tth->cc_head; NULL != cc; cc = cc->next)
318 {
319 if (GNUNET_NO == cc->connected)
320 continue;
321 if ((GNUNET_YES != cc->p1_c) ||
322 (GNUNET_YES != cc->p2_c))
323 {
324 cc->connected = GNUNET_NO;
325 /* start trying to connect */
326 if ((NULL == cc->tct) &&
327 (NULL == cc->oh))
328 cc->tct = GNUNET_SCHEDULER_add_now (&offer_hello,
329 cc);
330 if (NULL == cc->ats_sh)
331 cc->ats_sh = GNUNET_ATS_connectivity_suggest (cc->p1->ats,
332 &p2->id,
333 1);
334 }
335 }
336}
337
338
339static void
340get_hello (void *cb_cls,
341 const struct GNUNET_MessageHeader *message)
342{
343 struct GNUNET_TRANSPORT_TESTING_PeerContext *p = cb_cls;
344 struct GNUNET_PeerIdentity hello_id;
345
346 GNUNET_assert (GNUNET_OK ==
347 GNUNET_HELLO_get_id ((const struct
348 GNUNET_HELLO_Message *) message,
349 &hello_id));
350 GNUNET_assert (0 == memcmp (&hello_id,
351 &p->id,
352 sizeof(hello_id)));
353 GNUNET_free (p->hello);
354 p->hello = (struct GNUNET_HELLO_Message *) GNUNET_copy_message (message);
355
356 if (NULL != p->start_cb)
357 {
358 LOG (GNUNET_ERROR_TYPE_DEBUG,
359 "Peer %u (`%s') successfully started\n",
360 p->no,
361 GNUNET_i2s (&p->id));
362 p->start_cb (p->start_cb_cls);
363 p->start_cb = NULL;
364 }
365}
366
367
368/**
369 * Start a peer with the given configuration
370 * @param tth the testing handle
371 * @param cfgname configuration file
372 * @param peer_id a unique number to identify the peer
373 * @param handlers functions for receiving messages
374 * @param nc connect callback
375 * @param nd disconnect callback
376 * @param cb_cls closure for callback
377 * @param start_cb start callback
378 * @param start_cb_cls closure for callback
379 * @return the peer context
380 */
381struct GNUNET_TRANSPORT_TESTING_PeerContext *
382GNUNET_TRANSPORT_TESTING_start_peer (struct
383 GNUNET_TRANSPORT_TESTING_Handle *tth,
384 const char *cfgname,
385 int peer_id,
386 const struct
387 GNUNET_MQ_MessageHandler *handlers,
388 GNUNET_TRANSPORT_NotifyConnect nc,
389 GNUNET_TRANSPORT_NotifyDisconnect nd,
390 void *cb_cls,
391 GNUNET_SCHEDULER_TaskCallback start_cb,
392 void *start_cb_cls)
393{
394 char *emsg = NULL;
395 struct GNUNET_TRANSPORT_TESTING_PeerContext *p;
396 struct GNUNET_PeerIdentity dummy;
397 unsigned int i;
398
399 if (GNUNET_NO == GNUNET_DISK_file_test (cfgname))
400 {
401 LOG (GNUNET_ERROR_TYPE_ERROR,
402 "File not found: `%s'\n",
403 cfgname);
404 return NULL;
405 }
406
407 p = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_PeerContext);
408 p->tth = tth;
409 p->nc = nc;
410 p->nd = nd;
411 if (NULL != handlers)
412 {
413 for (i = 0; NULL != handlers[i].cb; i++)
414 ;
415 p->handlers = GNUNET_new_array (i + 1,
416 struct GNUNET_MQ_MessageHandler);
417 GNUNET_memcpy (p->handlers,
418 handlers,
419 i * sizeof(struct GNUNET_MQ_MessageHandler));
420 }
421 if (NULL != cb_cls)
422 p->cb_cls = cb_cls;
423 else
424 p->cb_cls = p;
425 p->start_cb = start_cb;
426 if (NULL != start_cb_cls)
427 p->start_cb_cls = start_cb_cls;
428 else
429 p->start_cb_cls = p;
430 GNUNET_CONTAINER_DLL_insert (tth->p_head,
431 tth->p_tail,
432 p);
433
434 /* Create configuration and call testing lib to modify it */
435 p->cfg = GNUNET_CONFIGURATION_create ();
436 GNUNET_assert (GNUNET_OK ==
437 GNUNET_CONFIGURATION_load (p->cfg, cfgname));
438 if (GNUNET_SYSERR ==
439 GNUNET_TESTING_configuration_create (tth->tl_system,
440 p->cfg))
441 {
442 LOG (GNUNET_ERROR_TYPE_ERROR,
443 "Testing library failed to create unique configuration based on `%s'\n",
444 cfgname);
445 GNUNET_CONFIGURATION_destroy (p->cfg);
446 GNUNET_free (p);
447 return NULL;
448 }
449
450 p->no = peer_id;
451 /* Configure peer with configuration */
452 p->peer = GNUNET_TESTING_peer_configure (tth->tl_system,
453 p->cfg,
454 p->no,
455 NULL,
456 &emsg);
457 if (NULL == p->peer)
458 {
459 LOG (GNUNET_ERROR_TYPE_ERROR,
460 "Testing library failed to create unique configuration based on `%s': `%s'\n",
461 cfgname,
462 emsg);
463 GNUNET_TRANSPORT_TESTING_stop_peer (p);
464 GNUNET_free (emsg);
465 return NULL;
466 }
467
468 if (GNUNET_OK != GNUNET_TESTING_peer_start (p->peer))
469 {
470 LOG (GNUNET_ERROR_TYPE_ERROR,
471 "Testing library failed to create unique configuration based on `%s'\n",
472 cfgname);
473 GNUNET_TRANSPORT_TESTING_stop_peer (p);
474 return NULL;
475 }
476
477 memset (&dummy,
478 '\0',
479 sizeof(dummy));
480 GNUNET_TESTING_peer_get_identity (p->peer,
481 &p->id);
482 if (0 == memcmp (&dummy,
483 &p->id,
484 sizeof(struct GNUNET_PeerIdentity)))
485 {
486 LOG (GNUNET_ERROR_TYPE_ERROR,
487 "Testing library failed to obtain peer identity for peer %u\n",
488 p->no);
489 GNUNET_TRANSPORT_TESTING_stop_peer (p);
490 return NULL;
491 }
492 LOG (GNUNET_ERROR_TYPE_DEBUG,
493 "Peer %u configured with identity `%s'\n",
494 p->no,
495 GNUNET_i2s_full (&p->id));
496 p->tmh = GNUNET_TRANSPORT_manipulation_connect (p->cfg);
497 p->th = GNUNET_TRANSPORT_core_connect (p->cfg,
498 NULL,
499 handlers,
500 p,
501 &notify_connect,
502 &notify_disconnect,
503 NULL);
504 if ((NULL == p->th) ||
505 (NULL == p->tmh))
506 {
507 LOG (GNUNET_ERROR_TYPE_ERROR,
508 "Failed to connect to transport service for peer `%s': `%s'\n",
509 cfgname,
510 emsg);
511 GNUNET_TRANSPORT_TESTING_stop_peer (p);
512 GNUNET_free (emsg);
513 return NULL;
514 }
515 p->ats = GNUNET_ATS_connectivity_init (p->cfg);
516 if (NULL == p->ats)
517 {
518 LOG (GNUNET_ERROR_TYPE_ERROR,
519 "Failed to connect to ATS service for peer `%s': `%s'\n",
520 cfgname,
521 emsg);
522 GNUNET_TRANSPORT_TESTING_stop_peer (p);
523 GNUNET_free (emsg);
524 return NULL;
525 }
526 p->ghh = GNUNET_TRANSPORT_hello_get (p->cfg,
527 GNUNET_TRANSPORT_AC_ANY,
528 &get_hello,
529 p);
530 GNUNET_assert (NULL != p->ghh);
531 return p;
532}
533
534
535/**
536 * Stops and restarts the given peer, sleeping (!) for 5s in between.
537 *
538 * @param p the peer
539 * @param restart_cb callback to call when restarted
540 * @param restart_cb_cls callback closure
541 * @return #GNUNET_OK in success otherwise #GNUNET_SYSERR
542 */
543int
544GNUNET_TRANSPORT_TESTING_restart_peer (struct
545 GNUNET_TRANSPORT_TESTING_PeerContext *p,
546 GNUNET_SCHEDULER_TaskCallback restart_cb,
547 void *restart_cb_cls)
548{
549 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
550 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
551
552 /* shutdown */
553 LOG (GNUNET_ERROR_TYPE_DEBUG,
554 "Stopping peer %u (`%s')\n",
555 p->no,
556 GNUNET_i2s (&p->id));
557 if (NULL != p->ghh)
558 {
559 GNUNET_TRANSPORT_hello_get_cancel (p->ghh);
560 p->ghh = NULL;
561 }
562 if (NULL != p->th)
563 {
564 GNUNET_TRANSPORT_core_disconnect (p->th);
565 p->th = NULL;
566 }
567 if (NULL != p->tmh)
568 {
569 GNUNET_TRANSPORT_manipulation_disconnect (p->tmh);
570 p->tmh = NULL;
571 }
572 for (cc = p->tth->cc_head; NULL != cc; cc = ccn)
573 {
574 ccn = cc->next;
575 if ((cc->p1 == p) ||
576 (cc->p2 == p))
577 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
578 }
579 if (NULL != p->ats)
580 {
581 GNUNET_ATS_connectivity_done (p->ats);
582 p->ats = NULL;
583 }
584 if (GNUNET_SYSERR ==
585 GNUNET_TESTING_peer_stop (p->peer))
586 {
587 LOG (GNUNET_ERROR_TYPE_ERROR,
588 "Failed to stop peer %u (`%s')\n",
589 p->no,
590 GNUNET_i2s (&p->id));
591 return GNUNET_SYSERR;
592 }
593
594 sleep (5); // YUCK!
595
596 LOG (GNUNET_ERROR_TYPE_DEBUG,
597 "Restarting peer %u (`%s')\n",
598 p->no,
599 GNUNET_i2s (&p->id));
600 /* restart */
601 if (GNUNET_SYSERR == GNUNET_TESTING_peer_start (p->peer))
602 {
603 LOG (GNUNET_ERROR_TYPE_ERROR,
604 "Failed to restart peer %u (`%s')\n",
605 p->no,
606 GNUNET_i2s (&p->id));
607 return GNUNET_SYSERR;
608 }
609
610 GNUNET_assert (NULL == p->start_cb);
611 p->start_cb = restart_cb;
612 p->start_cb_cls = restart_cb_cls;
613
614 p->th = GNUNET_TRANSPORT_core_connect (p->cfg,
615 NULL,
616 p->handlers,
617 p,
618 &notify_connect,
619 &notify_disconnect,
620 NULL);
621 GNUNET_assert (NULL != p->th);
622 p->ats = GNUNET_ATS_connectivity_init (p->cfg);
623 p->ghh = GNUNET_TRANSPORT_hello_get (p->cfg,
624 GNUNET_TRANSPORT_AC_ANY,
625 &get_hello,
626 p);
627 GNUNET_assert (NULL != p->ghh);
628 return GNUNET_OK;
629}
630
631
632/**
633 * Shutdown the given peer
634 *
635 * @param p the peer
636 */
637void
638GNUNET_TRANSPORT_TESTING_stop_peer (struct
639 GNUNET_TRANSPORT_TESTING_PeerContext *p)
640{
641 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p->tth;
642 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
643 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
644
645 for (cc = tth->cc_head; NULL != cc; cc = ccn)
646 {
647 ccn = cc->next;
648 if ((cc->p1 == p) ||
649 (cc->p2 == p))
650 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
651 }
652 if (NULL != p->ghh)
653 {
654 GNUNET_TRANSPORT_hello_get_cancel (p->ghh);
655 p->ghh = NULL;
656 }
657 if (NULL != p->tmh)
658 {
659 GNUNET_TRANSPORT_manipulation_disconnect (p->tmh);
660 p->tmh = NULL;
661 }
662 if (NULL != p->th)
663 {
664 GNUNET_TRANSPORT_core_disconnect (p->th);
665 p->th = NULL;
666 }
667 if (NULL != p->peer)
668 {
669 if (GNUNET_OK !=
670 GNUNET_TESTING_peer_stop (p->peer))
671 {
672 LOG (GNUNET_ERROR_TYPE_DEBUG,
673 "Testing lib failed to stop peer %u (`%s')\n",
674 p->no,
675 GNUNET_i2s (&p->id));
676 }
677 GNUNET_TESTING_peer_destroy (p->peer);
678 p->peer = NULL;
679 }
680 if (NULL != p->ats)
681 {
682 GNUNET_ATS_connectivity_done (p->ats);
683 p->ats = NULL;
684 }
685 if (NULL != p->hello)
686 {
687 GNUNET_free (p->hello);
688 p->hello = NULL;
689 }
690 if (NULL != p->cfg)
691 {
692 GNUNET_CONFIGURATION_destroy (p->cfg);
693 p->cfg = NULL;
694 }
695 if (NULL != p->handlers)
696 {
697 GNUNET_free (p->handlers);
698 p->handlers = NULL;
699 }
700 GNUNET_CONTAINER_DLL_remove (tth->p_head,
701 tth->p_tail,
702 p);
703 LOG (GNUNET_ERROR_TYPE_DEBUG,
704 "Peer %u (`%s') stopped\n",
705 p->no,
706 GNUNET_i2s (&p->id));
707 GNUNET_free (p);
708}
709
710
711/**
712 * Function called after the HELLO was passed to the
713 * transport service.
714 */
715static void
716hello_offered (void *cls)
717{
718 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = cls;
719
720 cc->oh = NULL;
721 cc->tct = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
722 &offer_hello,
723 cc);
724}
725
726
727/**
728 * Offer the current HELLO of P2 to P1.
729 *
730 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequest`
731 */
732static void
733offer_hello (void *cls)
734{
735 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = cls;
736 struct GNUNET_TRANSPORT_TESTING_PeerContext *p1 = cc->p1;
737 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2 = cc->p2;
738
739 cc->tct = NULL;
740 {
741 char *p2_s = GNUNET_strdup (GNUNET_i2s (&p2->id));
742
743 LOG (GNUNET_ERROR_TYPE_DEBUG,
744 "Asking peer %u (`%s') to connect peer %u (`%s'), providing HELLO with %u bytes\n",
745 p1->no,
746 GNUNET_i2s (&p1->id),
747 p2->no,
748 p2_s,
749 GNUNET_HELLO_size (cc->p2->hello));
750 GNUNET_free (p2_s);
751 }
752
753 if (NULL != cc->oh)
754 GNUNET_TRANSPORT_offer_hello_cancel (cc->oh);
755 cc->oh =
756 GNUNET_TRANSPORT_offer_hello (cc->p1->cfg,
757 (const struct
758 GNUNET_MessageHeader *) cc->p2->hello,
759 &hello_offered,
760 cc);
761}
762
763
764/**
765 * Initiate a connection from p1 to p2 by offering p1 p2's HELLO message
766 *
767 * Remarks: start_peer's notify_connect callback can be called before.
768 *
769 * @param tth transport testing handle
770 * @param p1 peer 1
771 * @param p2 peer 2
772 * @param cb the callback to call when both peers notified that they are connected
773 * @param cls callback cls
774 * @return a connect request handle
775 */
776struct GNUNET_TRANSPORT_TESTING_ConnectRequest *
777GNUNET_TRANSPORT_TESTING_connect_peers (struct
778 GNUNET_TRANSPORT_TESTING_PeerContext *p1,
779 struct
780 GNUNET_TRANSPORT_TESTING_PeerContext *p2,
781 GNUNET_SCHEDULER_TaskCallback cb,
782 void *cls)
783{
784 struct GNUNET_TRANSPORT_TESTING_Handle *tth = p1->tth;
785 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
786 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ccn;
787
788 ccn = NULL;
789 for (cc = tth->cc_head; NULL != cc; cc = cc->next)
790 {
791 if ((cc->p1 == p1) &&
792 (cc->p2 == p2))
793 {
794 ccn = cc;
795 break;
796 }
797 }
798
799 cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest);
800 cc->p1 = p1;
801 cc->p2 = p2;
802 cc->cb = cb;
803 if (NULL != cls)
804 cc->cb_cls = cls;
805 else
806 cc->cb_cls = cc;
807 if (NULL != ccn)
808 {
809 cc->p1_c = ccn->p1_c;
810 cc->p2_c = ccn->p2_c;
811 cc->connected = ccn->connected;
812 }
813 GNUNET_CONTAINER_DLL_insert (tth->cc_head,
814 tth->cc_tail,
815 cc);
816 cc->tct = GNUNET_SCHEDULER_add_now (&offer_hello,
817 cc);
818 cc->ats_sh = GNUNET_ATS_connectivity_suggest (cc->p1->ats,
819 &p2->id,
820 1);
821 LOG (GNUNET_ERROR_TYPE_DEBUG,
822 "New connect request %p\n",
823 cc);
824 return cc;
825}
826
827
828/**
829 * Cancel the request to connect two peers
830 * Tou MUST cancel the request if you stop the peers before the peers connected successfully
831 *
832 * @param tth transport testing handle
833 * @param cc a connect request handle
834 */
835void
836GNUNET_TRANSPORT_TESTING_connect_peers_cancel (struct
837 GNUNET_TRANSPORT_TESTING_ConnectRequest
838 *cc)
839{
840 struct GNUNET_TRANSPORT_TESTING_Handle *tth = cc->p1->tth;
841
842 LOG (GNUNET_ERROR_TYPE_DEBUG,
843 "Canceling connect request!\n");
844 if (NULL != cc->tct)
845 {
846 GNUNET_SCHEDULER_cancel (cc->tct);
847 cc->tct = NULL;
848 }
849 if (NULL != cc->oh)
850 {
851 GNUNET_TRANSPORT_offer_hello_cancel (cc->oh);
852 cc->oh = NULL;
853 }
854 if (NULL != cc->ats_sh)
855 {
856 GNUNET_ATS_connectivity_suggest_cancel (cc->ats_sh);
857 cc->ats_sh = NULL;
858 }
859 GNUNET_CONTAINER_DLL_remove (tth->cc_head,
860 tth->cc_tail,
861 cc);
862 GNUNET_free (cc);
863}
864
865
866/**
867 * Clean up the transport testing
868 *
869 * @param tth transport testing handle
870 */
871void
872GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_Handle *tth)
873{
874 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc;
875 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ct;
876 struct GNUNET_TRANSPORT_TESTING_PeerContext *p;
877 struct GNUNET_TRANSPORT_TESTING_PeerContext *t;
878
879 if (NULL == tth)
880 return;
881 cc = tth->cc_head;
882 while (NULL != cc)
883 {
884 ct = cc->next;
885 LOG (GNUNET_ERROR_TYPE_ERROR,
886 "Developer forgot to cancel connect request!\n");
887 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
888 cc = ct;
889 }
890 p = tth->p_head;
891 while (NULL != p)
892 {
893 t = p->next;
894 LOG (GNUNET_ERROR_TYPE_ERROR,
895 "Developer forgot to stop peer!\n");
896 GNUNET_TRANSPORT_TESTING_stop_peer (p);
897 p = t;
898 }
899 GNUNET_TESTING_system_destroy (tth->tl_system,
900 GNUNET_YES);
901
902 GNUNET_free (tth);
903}
904
905
906/**
907 * Initialize the transport testing
908 *
909 * @return transport testing handle
910 */
911struct GNUNET_TRANSPORT_TESTING_Handle *
912GNUNET_TRANSPORT_TESTING_init ()
913{
914 struct GNUNET_TRANSPORT_TESTING_Handle *tth;
915
916 tth = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_Handle);
917 tth->tl_system = GNUNET_TESTING_system_create ("transport-testing",
918 NULL,
919 NULL,
920 NULL);
921 if (NULL == tth->tl_system)
922 {
923 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
924 "Failed to initialize testing library!\n");
925 GNUNET_free (tth);
926 return NULL;
927 }
928 return tth;
929}
930
931
932/* end of transport-testing.c */