86c67a039c3b8208ae80aa084b99055e8869cff3
[oweals/gnunet.git] / src / transport / transport-testing.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2006, 2009, 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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file transport-testing.c
23  * @brief testing lib for transport service
24  *
25  * @author Matthias Wachs
26  */
27 #include "transport-testing.h"
28
29
30 #define LOG(kind,...) GNUNET_log_from(kind, "transport-testing", __VA_ARGS__)
31
32
33 static struct PeerContext *
34 find_peer_context (struct GNUNET_TRANSPORT_TESTING_handle *tth,
35                    const struct GNUNET_PeerIdentity *peer)
36 {
37   GNUNET_assert (tth != NULL);
38   struct PeerContext *t = tth->p_head;
39
40   while (t != NULL)
41   {
42     if (0 == memcmp (&t->id, peer, sizeof (struct GNUNET_PeerIdentity)))
43       break;
44     t = t->next;
45   }
46
47   return t;
48 }
49
50
51 static struct GNUNET_TRANSPORT_TESTING_ConnectRequest *
52 find_connecting_context (struct GNUNET_TRANSPORT_TESTING_handle *tth,
53                          struct PeerContext *p1,
54                          struct PeerContext *p2)
55 {
56   GNUNET_assert (tth != NULL);
57   struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = tth->cc_head;
58
59   while (cc != NULL)
60   {
61     if ((cc->p1 == p1) && (cc->p2 == p2))
62       break;
63     if ((cc->p1 == p2) && (cc->p2 == p1))
64       break;
65     cc = cc->next;
66   }
67
68   return cc;
69 }
70
71
72 static void
73 notify_connect (void *cls,
74                 const struct GNUNET_PeerIdentity *peer)
75 {
76   struct PeerContext *p = cls;
77   char *p2_s;
78   struct PeerContext *p2;
79
80   GNUNET_assert (NULL != p);
81   GNUNET_assert (NULL != p->tth);
82   p2 = find_peer_context (p->tth, peer);
83   if (p->nc != NULL)
84     p->nc (p->cb_cls, peer);
85
86   if (p2 != NULL)
87     GNUNET_asprintf (&p2_s, "%u (`%s')", p2->no, GNUNET_i2s (&p2->id));
88   else
89     GNUNET_asprintf (&p2_s, "`%s'", GNUNET_i2s (peer));
90   LOG (GNUNET_ERROR_TYPE_DEBUG,
91        "Peers %s connected to peer %u (`%s')\n",
92        p2_s,
93        p->no,
94        GNUNET_i2s (&p->id));
95   GNUNET_free (p2_s);
96
97   /* Find ConnectingContext */
98   struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = find_connecting_context (p->tth, p, p2);
99
100   if (cc == NULL)
101     return;
102
103   if (p == cc->p1)
104     cc->p1_c = GNUNET_YES;
105
106   if (p == cc->p2)
107     cc->p2_c = GNUNET_YES;
108
109   if ((cc->p1_c == GNUNET_YES) && (cc->p2_c == GNUNET_YES))
110   {
111     cc->cb (cc->p1, cc->p2, cc->cb_cls);
112     GNUNET_TRANSPORT_TESTING_connect_peers_cancel (p->tth, cc);
113   }
114 }
115
116
117 static void
118 notify_disconnect (void *cls,
119                    const struct GNUNET_PeerIdentity *peer)
120 {
121   struct PeerContext *p = cls;
122
123   /* Find PeerContext */
124   int no = 0;
125   struct PeerContext *p2 = NULL;
126
127   if (p != NULL)
128   {
129     GNUNET_assert (p->tth != NULL);
130     p2 = find_peer_context (p->tth, peer);
131     no = p->no;
132   }
133
134   char *p2_s;
135
136   if (p2 != NULL)
137     GNUNET_asprintf (&p2_s, "%u (`%s')", p2->no, GNUNET_i2s (&p2->id));
138   else
139     GNUNET_asprintf (&p2_s, "`%s'", GNUNET_i2s (peer));
140   LOG (GNUNET_ERROR_TYPE_DEBUG,
141        "Peers %s disconnected from peer %u (`%s')\n",
142        p2_s,
143        no,
144        GNUNET_i2s (&p->id));
145   GNUNET_free (p2_s);
146
147   if (p == NULL)
148     return;
149   if (p->nd != NULL)
150     p->nd (p->cb_cls, peer);
151 }
152
153
154 static void
155 notify_receive (void *cls,
156                 const struct GNUNET_PeerIdentity *peer,
157                 const struct GNUNET_MessageHeader *message)
158 {
159   struct PeerContext *p = cls;
160
161   if (p == NULL)
162     return;
163   if (p->rec != NULL)
164     p->rec (p->cb_cls, peer, message);
165 }
166
167
168 static void
169 get_hello (void *cb_cls,
170            const struct GNUNET_MessageHeader *message)
171 {
172   struct PeerContext *p = cb_cls;
173   struct GNUNET_PeerIdentity hello_id;
174
175   GNUNET_assert (message != NULL);
176   GNUNET_assert (GNUNET_OK ==
177                  GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
178                                       message, &hello_id));
179   GNUNET_assert (0 == memcmp (&hello_id, &p->id, sizeof (hello_id)));
180   GNUNET_free_non_null (p->hello);
181   p->hello = (struct GNUNET_HELLO_Message *) GNUNET_copy_message (message);
182
183   if (NULL != p->start_cb)
184   {
185     LOG (GNUNET_ERROR_TYPE_DEBUG,
186          "Peer %u (`%s') successfully started\n", p->no,
187          GNUNET_i2s (&p->id));
188     p->start_cb (p, p->cb_cls);
189     p->start_cb = NULL;
190   }
191 }
192
193
194 static void
195 try_connect (void *cls,
196              const struct GNUNET_SCHEDULER_TaskContext *tc)
197 {
198   struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = cls;
199   struct PeerContext *p1 = cc->p1;
200   struct PeerContext *p2 = cc->p2;
201
202   cc->tct = NULL;
203   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
204     return;
205
206   GNUNET_assert (cc != NULL);
207   GNUNET_assert (cc->p1 != NULL);
208   GNUNET_assert (cc->p2 != NULL);
209
210   char *p2_s = GNUNET_strdup (GNUNET_i2s (&p2->id));
211
212   LOG (GNUNET_ERROR_TYPE_DEBUG,
213        "Asking peer %u (`%s') to connect peer %u (`%s'), providing HELLO with %u bytes\n",
214        p1->no, GNUNET_i2s (&p1->id), p2->no, p2_s,
215        GNUNET_HELLO_size (cc->p2->hello));
216   GNUNET_free (p2_s);
217
218   GNUNET_TRANSPORT_offer_hello (cc->th_p1,
219                                 (const struct GNUNET_MessageHeader *) cc->
220                                 p2->hello, NULL, NULL);
221   GNUNET_TRANSPORT_try_connect (cc->th_p1, &p2->id, NULL, NULL); /*FIXME TRY_CONNECT change */
222
223   cc->tct =
224       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &try_connect, cc);
225 }
226
227
228 /**
229  * Start a peer with the given configuration
230  * @param tth the testing handle
231  * @param cfgname configuration file
232  * @param peer_id a unique number to identify the peer
233  * @param rec receive callback
234  * @param nc connect callback
235  * @param nd disconnect callback
236  * @param start_cb start callback
237  * @param cb_cls closure for callback
238  * @return the peer context
239  */
240 struct PeerContext *
241 GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_handle *tth,
242                                      const char *cfgname, int peer_id,
243                                      GNUNET_TRANSPORT_ReceiveCallback rec,
244                                      GNUNET_TRANSPORT_NotifyConnect nc,
245                                      GNUNET_TRANSPORT_NotifyDisconnect nd,
246                                      GNUNET_TRANSPORT_TESTING_start_cb start_cb,
247                                      void *cb_cls)
248 {
249   char *emsg = NULL;
250   struct GNUNET_PeerIdentity *dummy;
251
252   GNUNET_assert (NULL != tth);
253   GNUNET_assert (NULL != tth->tl_system);
254
255   if (GNUNET_DISK_file_test (cfgname) == GNUNET_NO)
256   {
257     LOG (GNUNET_ERROR_TYPE_ERROR,
258          "File not found: `%s'\n",
259          cfgname);
260     return NULL;
261   }
262
263   struct PeerContext *p = GNUNET_new (struct PeerContext);
264   GNUNET_CONTAINER_DLL_insert (tth->p_head, tth->p_tail, p);
265
266   /* Create configuration and call testing lib to modify it */
267   p->cfg = GNUNET_CONFIGURATION_create ();
268   GNUNET_assert (GNUNET_OK ==
269                  GNUNET_CONFIGURATION_load (p->cfg, cfgname));
270   if (GNUNET_SYSERR == GNUNET_TESTING_configuration_create (tth->tl_system, p->cfg))
271   {
272     LOG (GNUNET_ERROR_TYPE_ERROR,
273          "Testing library failed to create unique configuration based on `%s'\n",
274          cfgname);
275     GNUNET_free (p);
276     return NULL;
277   }
278
279   p->no = peer_id;
280   /* Configure peer with configuration */
281   p->peer = GNUNET_TESTING_peer_configure (tth->tl_system, p->cfg, p->no, NULL, &emsg);
282   if (NULL == p->peer)
283   {
284     LOG (GNUNET_ERROR_TYPE_ERROR,
285          "Testing library failed to create unique configuration based on `%s': `%s'\n",
286          cfgname,
287          emsg);
288     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p);
289     GNUNET_free_non_null (emsg);
290     return NULL;
291   }
292   GNUNET_free_non_null (emsg);
293   if (GNUNET_OK != GNUNET_TESTING_peer_start (p->peer))
294   {
295     LOG (GNUNET_ERROR_TYPE_ERROR,
296          "Testing library failed to create unique configuration based on `%s'\n",
297          cfgname);
298     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p);
299     return NULL;
300   }
301
302   memset(&dummy, '\0', sizeof (dummy));
303   GNUNET_TESTING_peer_get_identity (p->peer, &p->id);
304   if (0 == memcmp (&dummy, &p->id, sizeof (struct GNUNET_PeerIdentity)))
305   {
306     LOG (GNUNET_ERROR_TYPE_ERROR,
307          "Testing library failed to obtain peer identity for peer %u\n",
308          p->no);
309     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p);
310     return NULL;
311   }
312   else
313   {
314     LOG (GNUNET_ERROR_TYPE_DEBUG,
315          "Peer %u configured with identity `%s'\n",
316          p->no,
317          GNUNET_i2s_full (&p->id));
318   }
319
320   p->tth = tth;
321   p->nc = nc;
322   p->nd = nd;
323   p->rec = rec;
324   p->start_cb = start_cb;
325   if (cb_cls != NULL)
326     p->cb_cls = cb_cls;
327   else
328     p->cb_cls = p;
329
330   p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL, p,
331                                     &notify_receive,
332                                     &notify_connect, &notify_disconnect);
333   if (NULL == p->th)
334   {
335     LOG (GNUNET_ERROR_TYPE_ERROR,
336          "Failed to connect to transport service for peer  `%s': `%s'\n",
337          cfgname,
338          emsg);
339     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p);
340     return NULL;
341   }
342
343   p->ghh = GNUNET_TRANSPORT_get_hello (p->th, &get_hello, p);
344   GNUNET_assert (p->ghh != NULL);
345
346   return p;
347 }
348
349 /**
350 * Restart the given peer
351 * @param tth testing handle
352 * @param p the peer
353 * @param cfgname the cfg file used to restart
354 * @param restart_cb callback to call when restarted
355 * @param cb_cls callback closure
356 * @return GNUNET_OK in success otherwise GNUNET_SYSERR
357 */
358 int
359 GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_handle
360                                        *tth, struct PeerContext *p,
361                                        const char *cfgname,
362                                        GNUNET_TRANSPORT_TESTING_start_cb
363                                        restart_cb, void *cb_cls)
364 {
365   GNUNET_assert (tth != NULL);
366   GNUNET_assert (p != NULL);
367   GNUNET_assert (NULL != p->peer);
368
369   LOG (GNUNET_ERROR_TYPE_DEBUG,
370        "Restarting peer %u (`%s')\n",
371        p->no,
372        GNUNET_i2s (&p->id));
373
374   /* shutdown */
375   LOG (GNUNET_ERROR_TYPE_DEBUG,
376        "Stopping peer %u (`%s')\n",
377        p->no,
378        GNUNET_i2s (&p->id));
379   if (NULL != p->ghh)
380     GNUNET_TRANSPORT_get_hello_cancel (p->ghh);
381   p->ghh = NULL;
382
383   if (NULL != p->th)
384     GNUNET_TRANSPORT_disconnect (p->th);
385
386   if (GNUNET_SYSERR == GNUNET_TESTING_peer_stop(p->peer))
387   {
388     LOG (GNUNET_ERROR_TYPE_ERROR,
389          "Failed to stop peer %u (`%s')\n",
390          p->no,
391          GNUNET_i2s (&p->id));
392     return GNUNET_SYSERR;
393   }
394
395   sleep (5); // YUCK!
396
397   /* restart */
398   if (GNUNET_SYSERR == GNUNET_TESTING_peer_start(p->peer))
399   {
400     LOG (GNUNET_ERROR_TYPE_ERROR,
401          "Failed to restart peer %u (`%s')\n",
402          p->no, GNUNET_i2s (&p->id));
403     return GNUNET_SYSERR;
404   }
405
406   GNUNET_assert (p->th != NULL);
407   GNUNET_assert (p->start_cb == NULL);
408   p->start_cb = restart_cb;
409   p->cb_cls = cb_cls;
410
411   p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL, p,
412                                     &notify_receive,
413                                     &notify_connect,
414                                     &notify_disconnect);
415   GNUNET_assert (NULL != p->th);
416
417   p->ghh = GNUNET_TRANSPORT_get_hello (p->th, &get_hello, p);
418   GNUNET_assert (p->ghh != NULL);
419   return GNUNET_OK;
420 }
421
422
423 /**
424  * shutdown the given peer
425  * @param tth testing handle
426  * @param p the peer
427  */
428 void
429 GNUNET_TRANSPORT_TESTING_stop_peer (struct GNUNET_TRANSPORT_TESTING_handle *tth,
430                                     struct PeerContext *p)
431 {
432   GNUNET_assert (p != NULL);
433   if (p->ghh != NULL)
434   {
435     GNUNET_TRANSPORT_get_hello_cancel (p->ghh);
436     p->ghh = NULL;
437   }
438   if (p->th != NULL)
439   {
440     GNUNET_TRANSPORT_disconnect (p->th);
441     p->th = NULL;
442   }
443
444   if (p->peer != NULL)
445   {
446     if (GNUNET_OK != GNUNET_TESTING_peer_stop (p->peer))
447     {
448       LOG (GNUNET_ERROR_TYPE_DEBUG,
449            "Testing lib failed to stop peer %u (`%s') \n", p->no,
450            GNUNET_i2s (&p->id));
451     }
452     GNUNET_TESTING_peer_destroy (p->peer);
453     p->peer = NULL;
454   }
455
456   if (p->hello != NULL)
457   {
458     GNUNET_free (p->hello);
459     p->hello = NULL;
460   }
461   if (p->cfg != NULL)
462   {
463     GNUNET_CONFIGURATION_destroy (p->cfg);
464     p->cfg = NULL;
465   }
466   GNUNET_CONTAINER_DLL_remove (tth->p_head, tth->p_tail, p);
467   LOG (GNUNET_ERROR_TYPE_DEBUG,
468        "Peer %u (`%s') stopped \n", p->no,
469        GNUNET_i2s (&p->id));
470   GNUNET_free (p);
471 }
472
473
474 /**
475  * Initiate a connection from p1 to p2 by offering p1 p2's HELLO message
476  *
477  * Remarks: start_peer's notify_connect callback can be called before.
478  *
479  * @param tth transport testing handle
480  * @param p1 peer 1
481  * @param p2 peer 2
482  * @param cb the callback to call when both peers notified that they are connected
483  * @param cls callback cls
484  * @return a connect request handle
485  */
486 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *
487 GNUNET_TRANSPORT_TESTING_connect_peers (struct GNUNET_TRANSPORT_TESTING_handle *tth,
488                                         struct PeerContext *p1,
489                                         struct PeerContext *p2,
490                                         GNUNET_TRANSPORT_TESTING_connect_cb cb,
491                                         void *cls)
492 {
493   struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequest);
494
495   GNUNET_assert (tth != NULL);
496   GNUNET_assert (p1 != NULL);
497   GNUNET_assert (p2 != NULL);
498   cc->p1 = p1;
499   cc->p2 = p2;
500   cc->cb = cb;
501   if (cls != NULL)
502     cc->cb_cls = cls;
503   else
504     cc->cb_cls = cc;
505   cc->th_p1 = p1->th;
506   cc->th_p2 = p2->th;
507   GNUNET_assert (cc->th_p1 != NULL);
508   GNUNET_assert (cc->th_p2 != NULL);
509   GNUNET_CONTAINER_DLL_insert (tth->cc_head,
510                                tth->cc_tail,
511                                cc);
512   cc->tct = GNUNET_SCHEDULER_add_now (&try_connect, cc);
513   LOG (GNUNET_ERROR_TYPE_DEBUG,
514        "New connect request %p\n",
515        cc);
516
517   return cc;
518 }
519
520
521 /**
522  * Cancel the request to connect two peers
523  * Tou MUST cancel the request if you stop the peers before the peers connected succesfully
524  *
525  * @param tth transport testing handle
526  * @param cc a connect request handle
527  */
528 void
529 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (struct GNUNET_TRANSPORT_TESTING_handle *tth,
530                                                struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc)
531 {
532   GNUNET_assert (tth != NULL);
533
534   LOG (GNUNET_ERROR_TYPE_DEBUG,
535        "Canceling connect request %p!\n",
536        cc);
537
538   if (cc->tct != NULL)
539     GNUNET_SCHEDULER_cancel (cc->tct);
540   cc->tct = NULL;
541
542   GNUNET_CONTAINER_DLL_remove (tth->cc_head, tth->cc_tail, cc);
543   GNUNET_free (cc);
544 }
545
546
547 /**
548  * Clean up the transport testing
549  * @param tth transport testing handle
550  */
551 void
552 GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_handle *tth)
553 {
554   struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cc = tth->cc_head;
555   struct GNUNET_TRANSPORT_TESTING_ConnectRequest *ct = NULL;
556   struct PeerContext *p = tth->p_head;
557   struct PeerContext *t = NULL;
558
559   GNUNET_assert (tth != NULL);
560
561   while (cc != tth->cc_tail)
562   {
563     ct = cc->next;
564     LOG (GNUNET_ERROR_TYPE_ERROR,
565          "Developer forgot to cancel connect request %p!\n",
566          cc);
567     GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc);
568     cc = ct;
569   }
570
571   while (p != NULL)
572   {
573     t = p->next;
574     LOG (GNUNET_ERROR_TYPE_ERROR,
575          "Developer forgot to stop peer!\n");
576     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p);
577     p = t;
578   }
579
580   GNUNET_TESTING_system_destroy (tth->tl_system, GNUNET_YES);
581
582   GNUNET_free (tth);
583   tth = NULL;
584 }
585
586
587 /**
588  * Initialize the transport testing
589  * @return transport testing handle
590  */
591 struct GNUNET_TRANSPORT_TESTING_handle *
592 GNUNET_TRANSPORT_TESTING_init ()
593 {
594   struct GNUNET_TRANSPORT_TESTING_handle *tth;
595
596   /* prepare hostkeys */
597   tth = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_handle);
598
599   /* Init testing the testing lib */
600   tth->tl_system = GNUNET_TESTING_system_create ("transport-testing",
601                                                  NULL,
602                                                  NULL,
603                                                  NULL);
604   if (NULL == tth->tl_system)
605   {
606     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
607                 _("Failed to initialize testing library!\n"));
608     GNUNET_free (tth);
609     return NULL;
610   }
611
612   return tth;
613 }
614
615
616 /*
617  * Some utility functions
618  */
619
620 /**
621  * Removes all directory separators from absolute filename
622  * @param file the absolute file name, e.g. as found in argv[0]
623  * @return extracted file name, has to be freed by caller
624  */
625 static char *
626 extract_filename (const char *file)
627 {
628   char *pch = GNUNET_strdup (file);
629   char *backup = pch;
630   char *filename = NULL;
631   char *res;
632 #if WINDOWS
633   if ((strlen (pch) >= 3) && pch[1] == ':')
634   {
635     if (NULL != strstr (pch, "\\"))
636     {
637       pch = strtok (pch, "\\");
638       while (pch != NULL)
639       {
640         pch = strtok (NULL, "\\");
641         if (pch != NULL)
642           filename = pch;
643       }
644     }
645   }
646   if (filename != NULL)
647     pch = filename; /* If we miss the next condition, filename = pch will
648                      * not harm us.
649                      */
650 #endif
651   if (NULL != strstr (pch, "/"))
652   {
653     pch = strtok (pch, "/");
654     while (pch != NULL)
655     {
656       pch = strtok (NULL, "/");
657       if (pch != NULL)
658       {
659         filename = pch;
660       }
661     }
662   }
663   else
664     filename = pch;
665
666   res = GNUNET_strdup (filename);
667   GNUNET_free (backup);
668   return res;
669 }
670
671
672 /**
673  * Extracts the test filename from an absolute file name and removes the extension
674  * @param file absolute file name
675  * @param dest where to store result
676  */
677 void
678 GNUNET_TRANSPORT_TESTING_get_test_name (const char *file,
679                                         char **dest)
680 {
681   char *filename = extract_filename (file);
682   char *backup = filename;
683   char *dotexe;
684
685   if (filename == NULL)
686     goto fail;
687
688   /* remove "lt-" */
689   filename = strstr (filename, "tes");
690   if (filename == NULL)
691     goto fail;
692
693   /* remove ".exe" */
694   if (NULL != (dotexe = strstr (filename, ".exe")))
695     dotexe[0] = '\0';
696
697   goto suc;
698
699 fail:
700   (*dest) = NULL;
701   return;
702
703 suc:
704   /* create filename */
705   GNUNET_asprintf (dest, "%s", filename);
706   GNUNET_free (backup);
707 }
708
709
710 /**
711  * Extracts the filename from an absolute file name and removes the extension
712  * @param file absolute file name
713  * @param dest where to store result
714  */
715 void
716 GNUNET_TRANSPORT_TESTING_get_test_source_name (const char *file,
717                                                char **dest)
718 {
719   char *src = extract_filename (file);
720   char *split;
721
722   split = strstr (src, ".");
723   if (split != NULL)
724   {
725     split[0] = '\0';
726   }
727   GNUNET_asprintf (dest, "%s", src);
728   GNUNET_free (src);
729 }
730
731
732 /**
733  * Extracts the plugin name from an absolute file name and the test name
734  *
735  * @param file absolute file name
736  * @param test test name
737  * @param dest where to store result
738  */
739 void
740 GNUNET_TRANSPORT_TESTING_get_test_plugin_name (const char *file,
741                                                const char *test,
742                                                char **dest)
743 {
744   char *filename;
745   char *dotexe;
746   char *e = extract_filename (file);
747   char *t = extract_filename (test);
748
749   if (NULL == e)
750     goto fail;
751   /* remove "lt-" */
752   filename = strstr (e, "tes");
753   if (NULL == filename)
754     goto fail;
755   /* remove ".exe" */
756   if (NULL != (dotexe = strstr (filename, ".exe")))
757     dotexe[0] = '\0';
758
759   /* find last _ */
760   filename = strstr (filename, t);
761   if (NULL == filename)
762     goto fail;
763   /* copy plugin */
764   filename += strlen (t);
765   if ('\0' != *filename)
766     filename++;
767   GNUNET_asprintf (dest, "%s", filename);
768   goto suc;
769 fail:
770   (*dest) = NULL;
771 suc:
772   GNUNET_free (t);
773   GNUNET_free (e);
774 }
775
776
777 /**
778  * This function takes the filename (e.g. argv[0), removes a "lt-"-prefix and
779  * if existing ".exe"-prefix and adds the peer-number
780  *
781  * @param file filename of the test, e.g. argv[0]
782  * @param dest where to write the filename
783  * @param count peer number
784  */
785 void
786 GNUNET_TRANSPORT_TESTING_get_config_name (const char *file,
787                                           char **dest,
788                                           int count)
789 {
790   char *filename = extract_filename (file);
791   char *backup = filename;
792   char *dotexe;
793
794   if (NULL == filename)
795     goto fail;
796   /* remove "lt-" */
797   filename = strstr (filename, "tes");
798   if (NULL == filename)
799     goto fail;
800   /* remove ".exe" */
801   if (NULL != (dotexe = strstr (filename, ".exe")))
802     dotexe[0] = '\0';
803   GNUNET_asprintf (dest, "%s_peer%u.conf", filename, count);
804   GNUNET_free (backup);
805   return;
806 fail:
807   (*dest) = NULL;
808   GNUNET_free (backup);
809 }
810
811
812 /* end of transport-testing.c */