cf0d6f9db693fcf190c1ffadd6125b1d636cc139
[oweals/gnunet.git] / src / transport / test_transport_address_switch.c
1 /*
2  This file is part of GNUnet.
3  (C) 2009, 2010, 2011 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 transport/test_transport_address_switch.c
22  * @brief base test case for transport implementations
23  *
24  * This test case tests if peers can successfully switch address when connected
25  * connected
26  */
27 #include "platform.h"
28 #include "gnunet_transport_service.h"
29 #include "gnunet_ats_service.h"
30 #include "gauger.h"
31 #include "transport-testing.h"
32
33 /*
34  * Testcase specific declarations
35  */
36
37 GNUNET_NETWORK_STRUCT_BEGIN
38 struct TestMessage
39 {
40   struct GNUNET_MessageHeader header;
41   uint32_t num;
42 };
43 GNUNET_NETWORK_STRUCT_END
44
45 /**
46  * Note that this value must not significantly exceed
47  * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise
48  * messages may be dropped even for a reliable transport.
49  */
50 #define TOTAL_MSGS (4096 * 2)
51
52 /**
53  * Message type for test messages
54  */
55 #define MTYPE 12345
56
57 /**
58  * Testcase timeout
59  */
60 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
61
62 /**
63  * How long until we give up on transmitting the message?
64  */
65 #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
66
67 #define DURATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
68 #define DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
69
70 static GNUNET_SCHEDULER_TaskIdentifier die_task;
71
72 static GNUNET_SCHEDULER_TaskIdentifier delayed_end_task;
73
74 static GNUNET_SCHEDULER_TaskIdentifier measure_task;
75
76 struct PeerContext *p1;
77 char *cfg_file_p1;
78 struct GNUNET_STATISTICS_Handle *p1_stat;
79
80 struct PeerContext *p2;
81 char *cfg_file_p2;
82 struct GNUNET_STATISTICS_Handle *p2_stat;
83
84 struct PeerContext *sender;
85
86 struct PeerContext *receiver;
87
88 struct GNUNET_TRANSPORT_TransmitHandle *th;
89
90 static int test_connected;
91 static int res;
92
93 struct GNUNET_TRANSPORT_TESTING_handle *tth;
94
95 static GNUNET_TRANSPORT_TESTING_ConnectRequest cc;
96
97 static unsigned int p1_switch_attempts;
98 static unsigned int p1_switch_success;
99 static unsigned int p1_switch_fail;
100
101 static unsigned int p2_switch_attempts;
102 static unsigned int p2_switch_success;
103 static unsigned int p2_switch_fail;
104
105 static unsigned long long bytes_sent_total;
106 static unsigned long long bytes_recv_total;
107
108 static unsigned long long bytes_sent_after_switch;
109 static unsigned long long bytes_recv_after_switch;
110
111 static struct GNUNET_TIME_Absolute start_time;
112 static struct GNUNET_TIME_Absolute start_time;
113
114 /*
115  * END Testcase specific declarations
116  */
117
118 #if VERBOSE
119 #define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
120 #else
121 #define OKPP do { ok++; } while (0)
122 #endif
123
124 static void end ();
125
126 static int
127 stat_start_attempt_cb (void *cls, const char *subsystem, const char *name,
128     uint64_t value, int is_persistent)
129 {
130   if (cls == p1)
131   {
132     p1_switch_attempts++;
133     FPRINTF (stderr, "Peer 1 tries to switch.");
134   }
135   else if (cls == p2)
136   {
137     p2_switch_attempts++;
138     FPRINTF (stderr, "Peer 2 tries to switch.");
139   }
140   else
141     return GNUNET_OK;
142
143   if (GNUNET_SCHEDULER_NO_TASK == delayed_end_task)
144     delayed_end_task = GNUNET_SCHEDULER_add_delayed (DELAY, &end, NULL );
145   return GNUNET_OK;
146 }
147
148
149 static int
150 stat_success_attempt_cb (void *cls, const char *subsystem, const char *name,
151     uint64_t value, int is_persistent)
152 {
153   if (cls == p1)
154   {
155     p1_switch_success++;
156     FPRINTF (stderr, "Peer 1 switched successfully.");
157   }
158   if (cls == p2)
159   {
160     p2_switch_success++;
161     FPRINTF (stderr, "Peer 2 switched successfully.");
162   }
163
164   return GNUNET_OK;
165 }
166
167
168 static int
169 stat_fail_attempt_cb (void *cls, const char *subsystem, const char *name,
170     uint64_t value, int is_persistent)
171 {
172   if (cls == p1)
173   {
174     p1_switch_fail++;
175     FPRINTF (stderr, "Peer 1 failed to switch.");
176   }
177   if (cls == p2)
178   {
179     p2_switch_fail++;
180     FPRINTF (stderr, "Peer 2 failed to switch.");
181   }
182
183   return GNUNET_OK;
184 }
185
186
187 static void
188 clean_up ()
189 {
190   if (measure_task != GNUNET_SCHEDULER_NO_TASK )
191   {
192     GNUNET_SCHEDULER_cancel (measure_task);
193     measure_task = GNUNET_SCHEDULER_NO_TASK;
194   }
195
196   if (delayed_end_task != GNUNET_SCHEDULER_NO_TASK )
197   {
198     GNUNET_SCHEDULER_cancel (delayed_end_task);
199     delayed_end_task = GNUNET_SCHEDULER_NO_TASK;
200   }
201
202   if (die_task != GNUNET_SCHEDULER_NO_TASK )
203   {
204     GNUNET_SCHEDULER_cancel (die_task);
205     die_task = GNUNET_SCHEDULER_NO_TASK;
206   }
207
208   if (NULL != p1_stat)
209   {
210     GNUNET_STATISTICS_watch_cancel (p1_stat, "transport",
211         "# Attempts to switch addresses", stat_start_attempt_cb, p1);
212     GNUNET_STATISTICS_watch_cancel (p1_stat, "transport",
213         "# Successful attempts to switch addresses", stat_success_attempt_cb, p1);
214     GNUNET_STATISTICS_watch_cancel (p1_stat, "transport",
215         "# Failed attempts to switch addresses (failed to send CONNECT CONT)",
216         stat_fail_attempt_cb, p1);
217     GNUNET_STATISTICS_watch_cancel (p1_stat, "transport",
218         "# Failed attempts to switch addresses (failed to send CONNECT)",
219         stat_fail_attempt_cb, p1);
220     GNUNET_STATISTICS_watch_cancel (p1_stat, "transport",
221         "# Failed attempts to switch addresses (no response)",
222         stat_fail_attempt_cb, p1);
223     GNUNET_STATISTICS_destroy (p1_stat, GNUNET_NO);
224     p1_stat = NULL;
225   }
226   if (NULL != p2_stat)
227   {
228     GNUNET_STATISTICS_watch_cancel (p2_stat, "transport",
229         "# Attempts to switch addresses", stat_start_attempt_cb, p2);
230     GNUNET_STATISTICS_watch_cancel (p2_stat, "transport",
231         "# Successful attempts to switch addresses", stat_success_attempt_cb, p2);
232     GNUNET_STATISTICS_watch_cancel (p2_stat, "transport",
233         "# Failed attempts to switch addresses (failed to send CONNECT CONT)",
234         stat_fail_attempt_cb, p2);
235     GNUNET_STATISTICS_watch_cancel (p2_stat, "transport",
236         "# Failed attempts to switch addresses (failed to send CONNECT)",
237         stat_fail_attempt_cb, p2);
238     GNUNET_STATISTICS_watch_cancel (p2_stat, "transport",
239         "# Failed attempts to switch addresses (no response)",
240         stat_fail_attempt_cb, p2);
241     GNUNET_STATISTICS_destroy (p2_stat, GNUNET_NO);
242     p2_stat = NULL;
243   }
244
245   if (die_task != GNUNET_SCHEDULER_NO_TASK )
246   {
247     GNUNET_SCHEDULER_cancel (die_task);
248     die_task = GNUNET_SCHEDULER_NO_TASK;
249   }
250
251   if (th != NULL )
252   {
253     GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
254     th = NULL;
255   }
256
257   if (cc != NULL )
258   {
259     GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc);
260     cc = NULL;
261   }
262
263   if (p1 != NULL )
264   {
265     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1);
266     p1 = NULL;
267   }
268   if (p2 != NULL )
269   {
270     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2);
271     p2 = NULL;
272   }
273
274 }
275
276
277 static void
278 end ()
279 {
280   int result = 0;
281   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n");
282
283   delayed_end_task = GNUNET_SCHEDULER_NO_TASK;
284
285   if (p1_switch_attempts > 0)
286   {
287     FPRINTF (stderr, "Peer 1 tried %u times to switch and succeeded %u times, failed %u times\n",
288         p1_switch_attempts, p1_switch_success, p1_switch_fail);
289     if (p1_switch_success != p1_switch_attempts)
290       result ++;
291   }
292   if (p2_switch_attempts > 0)
293   {
294     FPRINTF (stderr, "Peer 2 tried %u times to switch and succeeded %u times, failed %u times\n",
295         p2_switch_attempts, p2_switch_success, p2_switch_fail);
296     if (p2_switch_success != p2_switch_attempts)
297       result ++;
298   }
299
300   if ( ((p1_switch_attempts > 0) || (p2_switch_attempts > 0)) &&
301        (bytes_sent_after_switch == 0) )
302   {
303     FPRINTF (stderr, "No data sent after switching!\n");
304     res ++;
305   }
306   if ( ((p1_switch_attempts > 0) || (p2_switch_attempts > 0)) &&
307        (bytes_recv_after_switch == 0) )
308   {
309     FPRINTF (stderr, "No data received after switching!\n");
310     res ++;
311   }
312
313   clean_up();
314
315   res = result;
316 }
317
318
319 static void
320 end_badly ()
321 {
322   die_task = GNUNET_SCHEDULER_NO_TASK;
323   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n");
324
325   if (test_connected == GNUNET_YES)
326     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Peers got connected\n");
327   else
328     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Peers got NOT connected\n");
329
330   clean_up();
331
332   res = GNUNET_YES;
333 }
334
335
336 static unsigned int
337 get_size (unsigned int iter)
338 {
339   unsigned int ret;
340   ret = (iter * iter * iter);
341   return sizeof(struct TestMessage) + (ret % 60000);
342 }
343
344
345 static void
346 notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
347     const struct GNUNET_MessageHeader *message)
348 {
349   const struct TestMessage *hdr;
350
351   hdr = (const struct TestMessage *) message;
352   if (MTYPE != ntohs (message->type))
353     return;
354
355   struct PeerContext *p = cls;
356   char *ps = GNUNET_strdup (GNUNET_i2s (&p->id));
357
358   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
359       "Peer %u (`%s') got message %u of size %u from peer (`%s')\n", p->no, ps,
360       ntohl (hdr->num), ntohs (message->size), GNUNET_i2s (peer));
361
362   bytes_recv_total += ntohs(hdr->header.size);
363   if ((p1_switch_attempts > 0) || (p2_switch_attempts > 0))
364     bytes_recv_after_switch += ntohs(hdr->header.size);
365
366   GNUNET_free(ps);
367 }
368
369
370 static size_t
371 notify_ready (void *cls, size_t size, void *buf)
372 {
373   static int n;
374   char *cbuf = buf;
375   struct TestMessage hdr;
376   unsigned int s;
377   unsigned int ret;
378
379   th = NULL;
380   if (buf == NULL )
381   {
382     GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
383         "Timeout occurred while waiting for transmit_ready for message\n");
384     if (GNUNET_SCHEDULER_NO_TASK != die_task)
385       GNUNET_SCHEDULER_cancel (die_task);
386     die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL );
387     res = 1;
388     return 0;
389   }
390
391   ret = 0;
392   s = get_size (n);
393   GNUNET_assert(size >= s);
394   GNUNET_assert(buf != NULL);
395   cbuf = buf;
396   do
397   {
398     hdr.header.size = htons (s);
399     hdr.header.type = htons (MTYPE);
400     hdr.num = htonl (n);
401     memcpy (&cbuf[ret], &hdr, sizeof(struct TestMessage));
402     ret += sizeof(struct TestMessage);
403     memset (&cbuf[ret], n, s - sizeof(struct TestMessage));
404     ret += s - sizeof(struct TestMessage);
405 #if VERBOSE
406     if (n % 5000 == 0)
407     {
408 #endif
409     char *receiver_s = GNUNET_strdup (GNUNET_i2s (&receiver->id));
410
411     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
412         "Sending message %u of size %u from peer %u (`%4s') -> peer %u (`%s') !\n",
413         n, s, sender->no, GNUNET_i2s (&sender->id), receiver->no, receiver_s);
414     GNUNET_free(receiver_s);
415 #if 0
416   }
417 #endif
418     n++;
419     s = get_size (n);
420     if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16))
421       break; /* sometimes pack buffer full, sometimes not */
422   }
423   while (size - ret >= s);
424   if (n < TOTAL_MSGS)
425   {
426     if (th == NULL )
427       th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, s,
428           TIMEOUT_TRANSMIT, &notify_ready, NULL );
429   }
430   if (n % 5000 == 0)
431   {
432
433   }
434   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
435       "Returning total message block of size %u\n", ret);
436
437   bytes_sent_total += ret;
438   if ((p1_switch_attempts > 0) || (p2_switch_attempts > 0))
439     bytes_sent_after_switch += ret;
440
441   if (n == TOTAL_MSGS)
442   {
443     FPRINTF (stderr, "%s", "\n");
444     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "All messages sent\n");
445   }
446   return ret;
447 }
448
449
450 static void
451 notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
452 {
453   struct PeerContext *p = cls;
454   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') connected to us!\n",
455       p->no, GNUNET_i2s (peer));
456 }
457
458
459 static void
460 notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
461 {
462   struct PeerContext *p = cls;
463   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') disconnected!\n", p->no,
464       GNUNET_i2s (peer));
465   if (th != NULL )
466     GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
467   th = NULL;
468
469 }
470
471
472 static void
473 sendtask ()
474 {
475   start_time = GNUNET_TIME_absolute_get ();
476   th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, get_size (0),
477       TIMEOUT_TRANSMIT, &notify_ready, NULL );
478 }
479
480
481 static void
482 measure (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
483 {
484   static int counter;
485
486   measure_task = GNUNET_SCHEDULER_NO_TASK;
487
488   counter++;
489   if ((DURATION.rel_value_us / 1000 / 1000LL) < counter)
490   {
491     FPRINTF (stderr, "%s", ".\n");
492   }
493   else
494   {
495     FPRINTF (stderr, "%s", ".");
496     measure_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
497         &measure, NULL );
498   }
499 }
500
501
502 static void
503 testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls)
504 {
505   char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id));
506
507   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %u (%s) <-> %u (%s)\n",
508       p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id));
509   GNUNET_free(p1_c);
510
511   cc = NULL;
512   test_connected = GNUNET_YES;
513
514   measure_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
515       &measure, NULL );
516  GNUNET_SCHEDULER_add_now (&sendtask, NULL );
517 }
518
519
520 static void
521 start_cb (struct PeerContext *p, void *cls)
522 {
523   static int started;
524   started++;
525
526   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no,
527       GNUNET_i2s (&p->id));
528   if (started != 2)
529     return;
530
531   test_connected = GNUNET_NO;
532   sender = p2;
533   receiver = p1;
534
535   char *sender_c = GNUNET_strdup (GNUNET_i2s (&sender->id));
536   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
537       "Test tries to send from %u (%s) -> peer %u (%s)\n", sender->no, sender_c,
538       receiver->no, GNUNET_i2s (&receiver->id));
539   GNUNET_free(sender_c);
540   cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb,
541       NULL );
542 }
543
544
545 static void
546 run (void *cls, char * const *args, const char *cfgfile,
547     const struct GNUNET_CONFIGURATION_Handle *cfg)
548 {
549   die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL );
550
551   p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1,
552       &notify_receive, &notify_connect, &notify_disconnect, &start_cb, NULL );
553   p1_stat = GNUNET_STATISTICS_create ("transport", p1->cfg);
554   GNUNET_STATISTICS_watch (p1_stat, "transport",
555       "# Attempts to switch addresses",
556       stat_start_attempt_cb, p1);
557   GNUNET_STATISTICS_watch (p1_stat, "transport",
558       "# Successful attempts to switch addresses",
559       stat_success_attempt_cb, p1);
560   GNUNET_STATISTICS_watch (p1_stat, "transport",
561       "# Failed attempts to switch addresses (failed to send CONNECT CONT)",
562       stat_fail_attempt_cb, p1);
563   GNUNET_STATISTICS_watch (p1_stat, "transport",
564       "# Failed attempts to switch addresses (failed to send CONNECT)",
565       stat_fail_attempt_cb, p1);
566   GNUNET_STATISTICS_watch (p1_stat, "transport",
567       "# Failed attempts to switch addresses (no response)",
568       stat_fail_attempt_cb, p1);
569
570   p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2,
571       &notify_receive, &notify_connect, &notify_disconnect, &start_cb, NULL );
572
573   p2_stat = GNUNET_STATISTICS_create ("transport", p2->cfg);
574   GNUNET_STATISTICS_watch (p2_stat, "transport",
575       "# Attempts to switch addresses",
576       stat_start_attempt_cb, p2);
577   GNUNET_STATISTICS_watch (p2_stat, "transport",
578       "# Successful attempts to switch addresses",
579       stat_success_attempt_cb, p2);
580   GNUNET_STATISTICS_watch (p2_stat, "transport",
581       "# Failed attempts to switch addresses (failed to send CONNECT CONT)",
582       stat_fail_attempt_cb, p2);
583   GNUNET_STATISTICS_watch (p2_stat, "transport",
584       "# Failed attempts to switch addresses (failed to send CONNECT)",
585       stat_fail_attempt_cb, p2);
586   GNUNET_STATISTICS_watch (p2_stat, "transport",
587       "# Failed attempts to switch addresses (no response)",
588       stat_fail_attempt_cb, p2);
589
590   if ((p1 == NULL )|| (p2 == NULL))
591   {
592     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n");
593     if (die_task != GNUNET_SCHEDULER_NO_TASK)
594     GNUNET_SCHEDULER_cancel (die_task);
595     die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
596     return;
597   }
598
599   if ((p1_stat == NULL )|| (p2_stat == NULL))
600   {
601     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not create statistics for peers!\n");
602     if (die_task != GNUNET_SCHEDULER_NO_TASK)
603     GNUNET_SCHEDULER_cancel (die_task);
604     die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
605     return;
606   }
607 }
608
609 int
610 main (int argc, char *argv[])
611 {
612   char *test_plugin;
613   char *test_source;
614   char *test_name;
615
616   static char *argv_new[] = { "test-transport-address-switch", "-c",
617       "test_transport_startonly.conf", NULL };
618
619   static struct GNUNET_GETOPT_CommandLineOption options[] = {
620       GNUNET_GETOPT_OPTION_END };
621
622   GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name);
623
624   GNUNET_log_setup (test_name, "WARNING", NULL );
625
626   GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source);
627   GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source,
628       &test_plugin);
629
630   tth = GNUNET_TRANSPORT_TESTING_init ();
631
632   GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1);
633   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Using cfg [%u] : %s \n", 1, cfg_file_p1);
634   GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2);
635   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Using cfg [%u] : %s \n", 2, cfg_file_p2);
636
637   GNUNET_PROGRAM_run ((sizeof(argv_new) / sizeof(char *)) - 1, argv_new,
638       test_name, "nohelp", options, &run, NULL );
639
640   GNUNET_free(cfg_file_p1);
641   GNUNET_free(cfg_file_p2);
642
643   GNUNET_free(test_source);
644   GNUNET_free(test_plugin);
645   GNUNET_free(test_name);
646
647   GNUNET_TRANSPORT_TESTING_done (tth);
648
649   return res;
650 }
651
652 /* end of test_transport_address_switch.c */