f59edfb264df2301fc20025d5630459ea226dc34
[oweals/gnunet.git] / src / transport / test_plugin_transport_http.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010 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_plugin_transport_http.c
22  * @brief testcase for plugin_transport_http.c
23  * @author Matthias Wachs
24  */
25
26 #include "platform.h"
27 #include "gnunet_constants.h"
28 #include "gnunet_common.h"
29 #include "gnunet_getopt_lib.h"
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_os_lib.h"
32 #include "gnunet_peerinfo_service.h"
33 #include "gnunet_plugin_lib.h"
34 #include "gnunet_protocols.h"
35 #include "gnunet_program_lib.h"
36 #include "gnunet_signatures.h"
37 #include "gnunet_service_lib.h"
38 #include "gnunet_crypto_lib.h"
39
40 #include "gnunet_transport_plugin.h"
41 #include "gnunet_statistics_service.h"
42 #include "transport.h"
43 #include <curl/curl.h>
44
45 #define VERBOSE GNUNET_NO
46 #define DEBUG_CURL GNUNET_NO
47 #define HTTP_BUFFER_SIZE 2048
48
49 #define PROTOCOL_PREFIX "http"
50
51 #define PLUGIN libgnunet_plugin_transport_template
52
53 /**
54  * How long until we give up on transmitting the message?
55  */
56 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
57
58 /**
59  * Testcase timeout
60  */
61 #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
62
63 /**
64  * How long between recieve and send?
65  */
66 #define WAIT_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
67
68
69
70 /**
71  *  Struct for plugin addresses
72  */
73 struct Plugin_Address
74 {
75   /**
76    * Next field for linked list
77    */
78   struct Plugin_Address *next;
79
80   /**
81    * buffer containing data to send
82    */
83   void *addr;
84
85   /**
86    * amount of data to sent
87    */
88   size_t addrlen;
89 };
90
91 /**
92  *  Message to send using http
93  */
94 struct HTTP_Message
95 {
96   /**
97    * buffer
98    */
99   unsigned char buf[HTTP_BUFFER_SIZE];
100
101   /**
102    * current position in buffer
103    */
104   size_t pos;
105
106   /**
107    * buffer size
108    */
109   size_t size;
110
111   /**
112    * data size
113    */
114   size_t len;
115 };
116
117
118 /**
119  *  Struct for plugin addresses
120  */
121 struct HTTP_Transfer
122 {
123   /**
124    * amount of bytes we recieved
125    */
126   size_t data_size;
127
128   /**
129    * buffer for http transfers
130    */
131   unsigned char buf[HTTP_BUFFER_SIZE];
132
133   /**
134    * buffer size this transfer
135    */
136   size_t size;
137
138   /**
139    * amount of bytes we recieved
140    */
141   size_t pos;
142
143   /**
144    * HTTP Header result for transfer
145    */
146   unsigned int http_result_code;
147
148   /**
149    * did the test fail?
150    */
151   unsigned int test_failed;
152
153   /**
154    * was this test already executed?
155    */
156   unsigned int test_executed;
157 };
158
159
160 /**
161  * Network format for IPv4 addresses.
162  */
163 struct IPv4HttpAddress
164 {
165   struct IPv4HttpAddress *next;
166
167   struct IPv4HttpAddress *prev;
168
169   /**
170    * IPv4 address, in network byte order.
171    */
172   uint32_t ipv4_addr GNUNET_PACKED;
173
174   /**
175    * Port number, in network byte order.
176    */
177   uint16_t u_port GNUNET_PACKED;
178
179 };
180
181
182 /**
183  * Network format for IPv6 addresses.
184  */
185 struct IPv6HttpAddress
186 {
187   struct IPv6HttpAddress *next;
188
189   struct IPv6HttpAddress *prev;
190
191   /**
192    * IPv6 address.
193    */
194   struct in6_addr ipv6_addr GNUNET_PACKED;
195
196   /**
197    * Port number, in network byte order.
198    */
199   uint16_t u6_port GNUNET_PACKED;
200
201 };
202
203
204 /**
205  * Our public key.
206  */
207 /* static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; */
208
209 /**
210  * Our public key.
211  */
212 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
213
214 /**
215  * Our identity.
216  */
217 static struct GNUNET_PeerIdentity my_identity;
218
219 /**
220  * Our private key.
221  */
222 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
223
224 /**
225  * Peer's port
226  */
227 static long long unsigned int port;
228
229 /**
230  * Peer's addr
231  */
232 static char *test_addr;
233
234 /**
235  * Our statistics handle.
236  */
237 struct GNUNET_STATISTICS_Handle *stats;
238
239
240 /**
241  * Our configuration.
242  */
243 const struct GNUNET_CONFIGURATION_Handle *cfg;
244
245 /**
246  * Number of neighbours we'd like to have.
247  */
248 static uint32_t max_connect_per_transport;
249
250 /**
251  * Environment for this plugin.
252  */
253 static struct GNUNET_TRANSPORT_PluginEnvironment env;
254
255 /**
256  *handle for the api provided by this plugin
257  */
258 static struct GNUNET_TRANSPORT_PluginFunctions *api;
259
260 /**
261  * ID of the task controlling the testcase timeout
262  */
263 static GNUNET_SCHEDULER_TaskIdentifier ti_timeout;
264
265 static GNUNET_SCHEDULER_TaskIdentifier ti_send;
266
267 //const struct GNUNET_PeerIdentity * p;
268
269 /**
270  * buffer for data to send
271  */
272 static struct HTTP_Message buffer_out;
273
274 /**
275  * buffer for data to recieve
276  */
277 static struct HTTP_Message buffer_in;
278
279
280 struct Plugin_Address *addr_head;
281
282 /**
283  * Did the test pass or fail?
284  */
285 static int fail_notify_address;
286
287 /**
288  * Did the test pass or fail?
289  */
290 static int fail_notify_address_count;
291
292 /**
293  * Did the test pass or fail?
294  */
295 static int fail_pretty_printer;
296
297 /**
298  * Did the test pass or fail?
299  */
300 static int fail_pretty_printer_count;
301
302 /**
303  * Did the test pass or fail?
304  */
305 static int fail_addr_to_str;
306
307 /**
308  * No. of msgs transmitted successfully to local addresses
309  */
310 static int fail_msgs_transmited_to_local_addrs;
311
312 /**
313  * Test: transmit msg of max. size
314  */
315 static int fail_msg_transmited_bigger_max_size;
316
317 /**
318  * Test: transmit msg of max. size
319  */
320 static int fail_msg_transmited_max_size;
321
322 /**
323  * Test: transmit 2 msgs. in in send operation
324  */
325 static int fail_multiple_msgs_in_transmission;
326
327 /**
328  * Test: connect to peer without peer identification
329  */
330 static struct HTTP_Transfer test_no_ident;
331
332 /**
333  * Test: connect to peer without peer identification
334  */
335 static struct HTTP_Transfer test_too_short_ident;
336
337 /**
338  * Test: connect to peer without peer identification
339  */
340 static struct HTTP_Transfer test_too_long_ident;
341
342 /**
343  * Test: connect to peer with valid peer identification
344  */
345 static struct HTTP_Transfer test_valid_ident;
346
347 /**
348  * Test: session selection, use any existing
349  */
350 static int fail_session_selection_any;
351
352 /**
353  * Test: session selection, use existing inbound session
354  */
355 static int fail_session_selection_session;
356
357 /**
358  * Test: session selection, use existing inbound session
359  * max message, not fitting in send & recv buffers at one time
360  */
361 static int fail_session_selection_session_big;
362
363 /**
364 * Test: session selection, use reliable existing
365  */
366 static int fail_session_selection_reliable;
367
368 /**
369  * Did the test pass or fail?
370  */
371 static int fail;
372
373 /**
374  * Number of local addresses
375  */
376 static unsigned int count_str_addr;
377
378 CURL *curl_handle;
379
380 /**
381  * cURL Multihandle
382  */
383 static CURLM *multi_handle;
384
385 /**
386  * The task sending data
387  */
388 static GNUNET_SCHEDULER_TaskIdentifier http_task_send;
389
390 static char *servicehome;
391
392 /**
393  * Shutdown testcase
394  */
395 static void
396 shutdown_clean ()
397 {
398   struct Plugin_Address *tmp;
399
400   /* Evaluate results  */
401   fail = 0;
402   if ((fail_notify_address == GNUNET_YES) || (fail_pretty_printer == GNUNET_YES)
403       || (fail_addr_to_str == GNUNET_YES))
404   {
405     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
406                 "Phase 0: Test plugin functions failed\n");
407     fail = 1;
408   }
409   if ((test_no_ident.test_failed == GNUNET_YES) ||
410       (test_too_short_ident.test_failed == GNUNET_YES) ||
411       (test_too_long_ident.test_failed == GNUNET_YES) ||
412       (test_valid_ident.test_failed == GNUNET_YES))
413   {
414     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
415                 "Phase 1: Test connect with wrong data failed\n");
416     fail = 1;
417   }
418   if ((fail_session_selection_any != GNUNET_NO) ||
419       (fail_session_selection_reliable != GNUNET_NO) ||
420       (fail_session_selection_session != GNUNET_NO) ||
421       (fail_session_selection_session_big != GNUNET_NO))
422   {
423     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
424                 "Phase 2: Test session selection failed\n");
425     fail = 1;
426   }
427   if ((fail_msgs_transmited_to_local_addrs != count_str_addr) ||
428       (fail_multiple_msgs_in_transmission != 2) ||
429       (fail_msg_transmited_max_size == GNUNET_YES))
430   {
431     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
432                 "Phase 3: Test sending with plugin failed\n");
433     fail = 1;
434   }
435   if (fail != 1)
436   {
437     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All tests successful\n");
438   }
439
440   api->disconnect (api->cls, &my_identity);
441
442   curl_multi_cleanup (multi_handle);
443
444   if (NULL != curl_handle)
445     curl_easy_cleanup (curl_handle);
446
447   /* cleaning addresses */
448   while (addr_head != NULL)
449   {
450     tmp = addr_head->next;
451     GNUNET_free (addr_head->addr);
452     GNUNET_free (addr_head);
453     addr_head = tmp;
454   }
455
456   if (ti_send != GNUNET_SCHEDULER_NO_TASK)
457   {
458     GNUNET_SCHEDULER_cancel (ti_send);
459     ti_send = GNUNET_SCHEDULER_NO_TASK;
460   }
461
462   if (http_task_send != GNUNET_SCHEDULER_NO_TASK)
463   {
464     GNUNET_SCHEDULER_cancel (http_task_send);
465     http_task_send = GNUNET_SCHEDULER_NO_TASK;
466   }
467
468   if (ti_timeout != GNUNET_SCHEDULER_NO_TASK)
469   {
470     GNUNET_SCHEDULER_cancel (ti_timeout);
471     ti_timeout = GNUNET_SCHEDULER_NO_TASK;
472   }
473
474   GNUNET_free (test_addr);
475   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unloading http plugin\n");
476   GNUNET_assert (NULL ==
477                  GNUNET_PLUGIN_unload ("libgnunet_gnunet_transport_plugin_http",
478                                        api));
479
480   GNUNET_SCHEDULER_shutdown ();
481   GNUNET_DISK_directory_remove ("/tmp/test_gnunet_transport_plugin_http");
482
483   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Exiting testcase\n");
484
485   if (servicehome != NULL)
486   {
487     GNUNET_DISK_directory_remove (servicehome);
488     GNUNET_free (servicehome);
489   }
490
491   exit (fail);
492   return;
493 }
494
495
496 /**
497  * Continuation called after plugin send message
498  * @cls closure
499  * @target target
500  * @result GNUNET_OK or GNUNET_SYSERR
501  */
502
503 static void
504 task_send_cont (void *cls, const struct GNUNET_PeerIdentity *target, int result)
505 {
506   if ((cls == &fail_msg_transmited_bigger_max_size) &&
507       (result == GNUNET_SYSERR))
508   {
509     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
510                 "Message bigger max msg size was not sent!\n");
511     fail_msg_transmited_bigger_max_size = GNUNET_NO;
512     return;
513   }
514
515   if ((cls == &fail_msg_transmited_max_size) && (result == GNUNET_OK))
516   {
517     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
518                 "Message with max msg size succesfully sent!\n",
519                 fail_msgs_transmited_to_local_addrs);
520     fail_msg_transmited_max_size = GNUNET_NO;
521   }
522 }
523
524
525 static void run_connection_tests (int phase, void *cls);
526
527 /**
528  * Recieves messages from plugin, in real world transport
529  */
530 static struct GNUNET_TIME_Relative
531 receive (void *cls, const struct GNUNET_PeerIdentity *peer,
532          const struct GNUNET_MessageHeader *message,
533          const struct GNUNET_TRANSPORT_ATS_Information *ats, uint32_t ats_count,
534          struct Session *session, const char *sender_address,
535          uint16_t sender_address_len)
536 {
537   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
538               "Testcase recieved new message from peer `%s' with type %u and length %u, session %X\n",
539               GNUNET_i2s (peer), ntohs (message->type), ntohs (message->size),
540               session);
541
542   if ((ntohs (message->type) >= 10) && (ntohs (message->type) < 20))
543   {
544     fail_msgs_transmited_to_local_addrs++;
545     if (fail_msgs_transmited_to_local_addrs == count_str_addr)
546       run_connection_tests (2, session);
547   }
548   if ((ntohs (message->type) == 20))
549   {
550     fail_session_selection_reliable = GNUNET_NO;
551   }
552   if ((ntohs (message->type) == 21))
553   {
554     fail_session_selection_any = GNUNET_NO;
555   }
556   if ((ntohs (message->type) == 22))
557   {
558     fail_session_selection_session = GNUNET_NO;
559   }
560   if ((ntohs (message->type) == 23))
561   {
562     fail_session_selection_session_big = GNUNET_NO;
563     run_connection_tests (3, NULL);
564   }
565   if ((ntohs (message->type) == 30) || (ntohs (message->type) == 31))
566   {
567     fail_multiple_msgs_in_transmission++;
568   }
569   if ((ntohs (message->type) == 32) &&
570       (ntohs (message->size) == GNUNET_SERVER_MAX_MESSAGE_SIZE - 1))
571   {
572     fail_msg_transmited_max_size = GNUNET_NO;
573     shutdown_clean ();
574   }
575   return GNUNET_TIME_UNIT_ZERO;
576 }
577
578
579 static size_t
580 send_function (void *stream, size_t size, size_t nmemb, void *ptr)
581 {
582   unsigned int len;
583
584   len = buffer_out.len;
585
586   if ((buffer_out.pos == len) || (len > (size * nmemb)))
587     return 0;
588   memcpy (stream, buffer_out.buf, len);
589   buffer_out.pos = len;
590   return len;
591
592 }
593
594 static size_t
595 recv_function (void *ptr, size_t size, size_t nmemb, void *ctx)
596 {
597
598   if (buffer_in.pos + size * nmemb > buffer_in.size)
599     return 0;                   /* overflow */
600
601   buffer_in.len = size * nmemb;
602   memcpy (&buffer_in.buf[buffer_in.pos], ptr, size * nmemb);
603   buffer_in.pos += size * nmemb;
604   buffer_in.len = buffer_in.pos;
605   buffer_in.buf[buffer_in.pos] = '\0';
606   return buffer_in.pos;
607 }
608
609 static size_t
610 header_function (void *ptr, size_t size, size_t nmemb, void *stream)
611 {
612   struct HTTP_Transfer *res = stream;
613   char *tmp;
614   unsigned int len = size * nmemb;
615
616   tmp = GNUNET_malloc (len + 1);
617   memcpy (tmp, ptr, len);
618   if (tmp[len - 2] == 13)
619     tmp[len - 2] = '\0';
620 #if DEBUG_CURL
621   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Header: `%s'\n", tmp);
622 #endif
623   if (0 == strcmp (tmp, "HTTP/1.1 100 Continue"))
624   {
625     res->http_result_code = 100;
626   }
627   if (0 == strcmp (tmp, "HTTP/1.1 200 OK"))
628   {
629     res->http_result_code = 200;
630   }
631   if (0 == strcmp (tmp, "HTTP/1.1 400 Bad Request"))
632   {
633     res->http_result_code = 400;
634   }
635   if (0 == strcmp (tmp, "HTTP/1.1 404 Not Found"))
636   {
637     res->http_result_code = 404;
638   }
639   if (0 == strcmp (tmp, "HTTP/1.1 413 Request entity too large"))
640   {
641     res->http_result_code = 413;
642   }
643
644   GNUNET_free (tmp);
645   return size * nmemb;
646 }
647
648
649 static size_t send_prepare (struct HTTP_Transfer *result);
650
651
652 static void
653 send_execute (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
654 {
655   struct HTTP_Transfer *res;
656
657   int running;
658   struct CURLMsg *msg;
659   CURLMcode mret;
660
661   res = (struct HTTP_Transfer *) cls;
662   http_task_send = GNUNET_SCHEDULER_NO_TASK;
663   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
664     return;
665
666   do
667   {
668     running = 0;
669     mret = curl_multi_perform (multi_handle, &running);
670     if (running == 0)
671     {
672       do
673       {
674
675         msg = curl_multi_info_read (multi_handle, &running);
676         if (msg == NULL)
677           break;
678         /* get session for affected curl handle */
679         //cs = find_session_by_curlhandle (msg->easy_handle);
680         //GNUNET_assert ( cs != NULL );
681         switch (msg->msg)
682         {
683
684         case CURLMSG_DONE:
685           if ((msg->data.result != CURLE_OK) &&
686               (msg->data.result != CURLE_GOT_NOTHING))
687           {
688
689             GNUNET_log (GNUNET_ERROR_TYPE_INFO,
690                         _("curl failed for `%s' at %s:%d: `%s'\n"),
691                         "curl_multi_perform", __FILE__, __LINE__,
692                         curl_easy_strerror (msg->data.result));
693             /* sending msg failed */
694             curl_easy_cleanup (curl_handle);
695             curl_handle = NULL;
696
697             run_connection_tests (0, NULL);
698           }
699           if (res == &test_no_ident)
700           {
701             if ((res->http_result_code == 404) && (buffer_in.len == 208))
702             {
703               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
704                           "Connecting to peer without any peer identification: test passed\n");
705               res->test_failed = GNUNET_NO;
706             }
707             else
708               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
709                           _
710                           ("Connecting to peer without any peer identification: test failed\n"));
711           }
712           if (res == &test_too_short_ident)
713           {
714             if ((res->http_result_code == 404) && (buffer_in.len == 208))
715             {
716               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
717                           "Connecting to peer with too short peer identification: test passed\n");
718               res->test_failed = GNUNET_NO;
719             }
720             else
721               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
722                           _
723                           ("Connecting to peer with too short peer identification: test failed\n"));
724           }
725           if (res == &test_too_long_ident)
726           {
727             if ((res->http_result_code == 404) && (buffer_in.len == 208))
728             {
729               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
730                           "Connecting to peer with too long peer identification: test passed\n");
731               res->test_failed = GNUNET_NO;
732             }
733             else
734               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
735                           _
736                           ("Connecting to peer with too long peer identification: test failed\n"));
737           }
738           if (res == &test_valid_ident)
739           {
740             if ((res->http_result_code == 200))
741             {
742               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
743                           "Connecting to peer with valid peer identification: test passed\n");
744               res->test_failed = GNUNET_NO;
745             }
746             else
747               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
748                           "Connecting to peer with valid peer identification: test failed\n");
749           }
750           curl_easy_cleanup (curl_handle);
751           curl_handle = NULL;
752           if ((res == &test_valid_ident) && (res->test_failed == GNUNET_NO))
753             run_connection_tests (1, NULL);
754           run_connection_tests (0, NULL);
755           return;
756         default:
757           break;
758         }
759
760       }
761       while ((running > 0));
762     }
763   }
764   while (mret == CURLM_CALL_MULTI_PERFORM);
765   send_prepare (cls);
766 }
767
768
769 /**
770  * Function setting up file descriptors and scheduling task to run
771  * @param ses session to send data to
772  * @return bytes sent to peer
773  */
774 static size_t
775 send_prepare (struct HTTP_Transfer *result)
776 {
777   fd_set rs;
778   fd_set ws;
779   fd_set es;
780   int max;
781   struct GNUNET_NETWORK_FDSet *grs;
782   struct GNUNET_NETWORK_FDSet *gws;
783   long to;
784   CURLMcode mret;
785
786   max = -1;
787   FD_ZERO (&rs);
788   FD_ZERO (&ws);
789   FD_ZERO (&es);
790   mret = curl_multi_fdset (multi_handle, &rs, &ws, &es, &max);
791   if (mret != CURLM_OK)
792   {
793     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
794                 "curl_multi_fdset", __FILE__, __LINE__,
795                 curl_multi_strerror (mret));
796     return -1;
797   }
798   mret = curl_multi_timeout (multi_handle, &to);
799   if (mret != CURLM_OK)
800   {
801     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
802                 "curl_multi_timeout", __FILE__, __LINE__,
803                 curl_multi_strerror (mret));
804     return -1;
805   }
806
807   grs = GNUNET_NETWORK_fdset_create ();
808   gws = GNUNET_NETWORK_fdset_create ();
809   GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
810   GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
811   http_task_send =
812       GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
813                                    GNUNET_SCHEDULER_NO_TASK,
814                                    GNUNET_TIME_relative_multiply
815                                    (GNUNET_TIME_UNIT_SECONDS, 0), grs, gws,
816                                    &send_execute, result);
817   GNUNET_NETWORK_fdset_destroy (gws);
818   GNUNET_NETWORK_fdset_destroy (grs);
819
820   /* FIXME: return bytes REALLY sent */
821   return 0;
822 }
823
824 /**
825  * function to send data to server
826  */
827 static int
828 send_data (struct HTTP_Transfer *result, char *url)
829 {
830
831   curl_handle = curl_easy_init ();
832   if (NULL == curl_handle)
833   {
834     printf ("easy_init failed \n");
835     return GNUNET_SYSERR;
836   }
837 #if DEBUG_CURL
838   curl_easy_setopt (curl_handle, CURLOPT_VERBOSE, 1L);
839 #endif
840   curl_easy_setopt (curl_handle, CURLOPT_URL, url);
841   curl_easy_setopt (curl_handle, CURLOPT_PUT, 1L);
842   curl_easy_setopt (curl_handle, CURLOPT_HEADERFUNCTION, &header_function);
843   curl_easy_setopt (curl_handle, CURLOPT_WRITEHEADER, result);
844   curl_easy_setopt (curl_handle, CURLOPT_WRITEFUNCTION, &recv_function);
845   curl_easy_setopt (curl_handle, CURLOPT_WRITEDATA, result);
846   curl_easy_setopt (curl_handle, CURLOPT_READFUNCTION, &send_function);
847   curl_easy_setopt (curl_handle, CURLOPT_READDATA, result);
848   curl_easy_setopt (curl_handle, CURLOPT_INFILESIZE_LARGE,
849                     (curl_off_t) buffer_out.len);
850   curl_easy_setopt (curl_handle, CURLOPT_TIMEOUT, 30);
851   curl_easy_setopt (curl_handle, CURLOPT_CONNECTTIMEOUT, 20);
852
853   curl_multi_add_handle (multi_handle, curl_handle);
854
855   send_prepare (result);
856
857   return GNUNET_OK;
858 }
859
860 /**
861  * Plugin notifies transport (aka testcase) about its addresses
862  */
863 static void
864 notify_address (void *cls, int add_remove, const void *addr, size_t addrlen)
865 {
866   char address[INET6_ADDRSTRLEN];
867   unsigned int port;
868   struct Plugin_Address *pl_addr;
869   struct Plugin_Address *cur;
870
871   if (addrlen == (sizeof (struct IPv4HttpAddress)))
872   {
873     inet_ntop (AF_INET, (struct in_addr *) addr, address, INET_ADDRSTRLEN);
874     port = ntohs (((struct IPv4HttpAddress *) addr)->u_port);
875   }
876   else if (addrlen == (sizeof (struct IPv6HttpAddress)))
877   {
878     inet_ntop (AF_INET6, (struct in6_addr *) addr, address, INET6_ADDRSTRLEN);
879     port = ntohs (((struct IPv6HttpAddress *) addr)->u6_port);
880   }
881   else
882   {
883     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
884                 _
885                 ("Unknown address size: ipv6 has %u ipv4 has %u but this has %u\n"),
886                 sizeof (struct IPv6HttpAddress),
887                 sizeof (struct IPv4HttpAddress), addrlen);
888     return;
889   }
890   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
891               _("Transport plugin notification for address: `%s':%u\n"),
892               address, port);
893   pl_addr = GNUNET_malloc (sizeof (struct Plugin_Address));
894   pl_addr->addrlen = addrlen;
895   pl_addr->addr = GNUNET_malloc (addrlen);
896   memcpy (pl_addr->addr, addr, addrlen);
897   pl_addr->next = NULL;
898
899   if (NULL == addr_head)
900   {
901     addr_head = pl_addr;
902   }
903   else
904   {
905     cur = addr_head;
906     while (NULL != cur->next)
907     {
908       cur = cur->next;
909     }
910     cur->next = pl_addr;
911   }
912   fail_notify_address_count++;
913   fail_notify_address = GNUNET_NO;
914 }
915
916 static void
917 plugin_env_session_end (void *cls, const struct GNUNET_PeerIdentity *peer,
918                         struct Session *session)
919 {
920   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
921               "Pluging tells me: session %X to peer `%s' ended\n", session,
922               GNUNET_i2s (peer));
923 }
924
925
926 /**
927  * Setup plugin environment
928  */
929 static void
930 setup_plugin_environment ()
931 {
932   env.cfg = cfg;
933   env.stats = stats;
934   env.my_identity = &my_identity;
935   env.cls = &env;
936   env.receive = &receive;
937   env.notify_address = &notify_address;
938   env.max_connections = max_connect_per_transport;
939   env.session_end = &plugin_env_session_end;
940 }
941
942
943 /**
944  * Task shutting down testcase if it a timeout occurs
945  */
946 static void
947 task_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
948 {
949   ti_timeout = GNUNET_SCHEDULER_NO_TASK;
950   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
951     return;
952
953   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testcase timeout\n");
954   fail = GNUNET_YES;
955   shutdown_clean ();
956   return;
957 }
958
959
960 static void
961 pretty_printer_cb (void *cls, const char *address)
962 {
963   if (NULL == address)
964     return;
965   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Plugin returned pretty address: `%s'\n",
966               address);
967   fail_pretty_printer_count++;
968 }
969
970 /**
971  * Runs every single test to test the plugin
972  */
973 static void
974 run_connection_tests (int phase, void *cls)
975 {
976   struct GNUNET_MessageHeader *msg;
977   unsigned int size;
978
979   if (phase == 0)
980   {
981     char *host_str = NULL;
982
983     /* resetting buffers */
984     buffer_in.size = HTTP_BUFFER_SIZE;
985     buffer_in.pos = 0;
986     buffer_in.len = 0;
987
988     buffer_out.size = HTTP_BUFFER_SIZE;
989     buffer_out.pos = 0;
990     buffer_out.len = 0;
991
992     if (test_no_ident.test_executed == GNUNET_NO)
993     {
994       /* Connecting to peer without identification */
995       const char *ident = "";
996
997       GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr,
998                        ident);
999       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1000                   _("Connecting to peer without any peer identification.\n"));
1001       test_no_ident.test_executed = GNUNET_YES;
1002       send_data (&test_no_ident, host_str);
1003       GNUNET_free (host_str);
1004       return;
1005     }
1006     if (test_too_short_ident.test_executed == GNUNET_NO)
1007     {
1008       const char *ident = "AAAAAAAAAA";
1009
1010       /* Connecting to peer with too short identification */
1011       GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr,
1012                        ident);
1013       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1014                   _
1015                   ("Connecting to peer with too short peer identification.\n"));
1016       test_too_short_ident.test_executed = GNUNET_YES;
1017       send_data (&test_too_short_ident, host_str);
1018       GNUNET_free (host_str);
1019       return;
1020     }
1021
1022     if (test_too_long_ident.test_executed == GNUNET_NO)
1023     {
1024       const char *ident =
1025           "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1026
1027       /* Connecting to peer with too long identification */
1028       GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr,
1029                        ident);
1030       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1031                   _("Connecting to peer with too long peer identification.\n"));
1032       test_too_long_ident.test_executed = GNUNET_YES;
1033       send_data (&test_too_long_ident, host_str);
1034       GNUNET_free (host_str);
1035       return;
1036     }
1037     if (test_valid_ident.test_executed == GNUNET_NO)
1038     {
1039       struct GNUNET_CRYPTO_HashAsciiEncoded ident;
1040
1041       GNUNET_CRYPTO_hash_to_enc (&my_identity.hashPubKey, &ident);
1042       GNUNET_asprintf (&host_str, "%s://%s/%s%s", PROTOCOL_PREFIX, test_addr,
1043                        (char *) &ident, ";0");
1044       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1045                   _("Connecting to peer with valid peer identification.\n"));
1046       test_valid_ident.test_executed = GNUNET_YES;
1047       send_data (&test_valid_ident, host_str);
1048       GNUNET_free (host_str);
1049       return;
1050     }
1051   }
1052   if (phase == 1)
1053   {
1054     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1055                 "\nPhase 1: transmit data to all suggested addresses\n\n");
1056     /* Using one of the addresses the plugin proposed */
1057     GNUNET_assert (addr_head->addr != NULL);
1058
1059     struct Plugin_Address *tmp_addr;
1060     struct GNUNET_MessageHeader msg;
1061     char *tmp = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader));
1062     char address[INET6_ADDRSTRLEN];
1063     unsigned int port;
1064     unsigned int type = 10;
1065
1066     msg.size = htons (sizeof (struct GNUNET_MessageHeader));
1067     tmp_addr = addr_head;
1068     /* send a message to all addresses advertised by plugin */
1069
1070     int count = 0;
1071
1072     while (tmp_addr != NULL)
1073     {
1074       if (tmp_addr->addrlen == (sizeof (struct IPv4HttpAddress)))
1075       {
1076         inet_ntop (AF_INET, (struct in_addr *) tmp_addr->addr, address,
1077                    INET_ADDRSTRLEN);
1078         port = ntohs (((struct IPv4HttpAddress *) tmp_addr->addr)->u_port);
1079         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1080                     "Sending message to addres no. %u: `%s':%u\n", count,
1081                     address, port);
1082       }
1083       if (tmp_addr->addrlen == (sizeof (struct IPv6HttpAddress)))
1084       {
1085         inet_ntop (AF_INET6, (struct in6_addr *) tmp_addr->addr, address,
1086                    INET6_ADDRSTRLEN);
1087         port = ntohs (((struct IPv6HttpAddress *) tmp_addr->addr)->u6_port);
1088         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1089                     "Sending message to addres no. %u: `%s':%u\n", count,
1090                     address, port);
1091       }
1092       msg.type = htons (type);
1093       memcpy (tmp, &msg, sizeof (struct GNUNET_MessageHeader));
1094       api->send (api->cls, &my_identity, tmp,
1095                  sizeof (struct GNUNET_MessageHeader), 0, TIMEOUT, NULL,
1096                  tmp_addr->addr, tmp_addr->addrlen, GNUNET_YES, &task_send_cont,
1097                  &fail_msgs_transmited_to_local_addrs);
1098       tmp_addr = tmp_addr->next;
1099       count++;
1100       type++;
1101     }
1102     GNUNET_free (tmp);
1103     return;
1104   }
1105
1106   if (phase == 2)
1107   {
1108     struct Session *session = cls;
1109
1110     msg = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader));
1111
1112     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Phase 2: session selection\n\n");
1113     size = sizeof (struct GNUNET_MessageHeader);
1114     msg->size = htons (size);
1115     msg->type = htons (20);
1116     api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT,
1117                NULL, NULL, 0, GNUNET_NO, &task_send_cont, NULL);
1118
1119     msg->type = htons (21);
1120     api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT,
1121                NULL, NULL, 0, GNUNET_SYSERR, &task_send_cont, NULL);
1122
1123     /* answer on session */
1124     size = sizeof (struct GNUNET_MessageHeader);
1125     msg->size = htons (size);
1126     msg->type = htons (22);
1127     api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT,
1128                session, NULL, 0, GNUNET_SYSERR, &task_send_cont, NULL);
1129     GNUNET_free (msg);
1130
1131     /* answer on session with big message not fitting in mhd send buffer */
1132     size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1;
1133     msg = GNUNET_malloc (size);
1134     msg->size = htons (size);
1135     msg->type = htons (23);
1136     api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT,
1137                session, NULL, 0, GNUNET_NO, &task_send_cont, NULL);
1138     GNUNET_free (msg);
1139     return;
1140   }
1141
1142   if (phase == 3)
1143   {
1144
1145     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1146                 "Phase 3: send multiple or big messages after disconnect\n\n");
1147     /* disconnect from peer, so new connections are created */
1148     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect from peer: `%s'\n",
1149                 GNUNET_i2s (&my_identity));
1150     api->disconnect (api->cls, &my_identity);
1151
1152     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Phase 3: sending messages\n");
1153     /* send a multiple GNUNET_messages at a time */
1154     size = 2 * sizeof (struct GNUNET_MessageHeader);
1155     msg = GNUNET_malloc (2 * size);
1156     msg->size = htons (size);
1157     msg->type = htons (30);
1158     struct GNUNET_MessageHeader *msg2 = &msg[2];
1159
1160     msg2->size = htons (2 * sizeof (struct GNUNET_MessageHeader));
1161     msg2->type = htons (31);
1162     api->send (api->cls, &my_identity, (const char *) msg,
1163                4 * sizeof (struct GNUNET_MessageHeader), 0, TIMEOUT, NULL,
1164                addr_head->addr, addr_head->addrlen, GNUNET_NO, &task_send_cont,
1165                &fail_multiple_msgs_in_transmission);
1166     GNUNET_free (msg);
1167     /* send a message with size GNUNET_SERVER_MAX_MESSAGE_SIZE-1  */
1168
1169     size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1;
1170     msg = GNUNET_malloc (size);
1171     msg->size = htons (size);
1172     msg->type = htons (32);
1173     api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT,
1174                NULL, addr_head->addr, addr_head->addrlen, GNUNET_NO,
1175                &task_send_cont, &fail_msg_transmited_max_size);
1176     GNUNET_free (msg);
1177     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more tests to run\n");
1178   }
1179 }
1180
1181
1182 /**
1183  * Runs the test.
1184  *
1185  * @param cls closure
1186  * @param c configuration to use
1187  */
1188 static void
1189 run (void *cls, char *const *args, const char *cfgfile,
1190      const struct GNUNET_CONFIGURATION_Handle *c)
1191 {
1192   char *libname;
1193
1194   cfg = c;
1195   char *keyfile;
1196   unsigned long long tneigh;
1197   struct Plugin_Address *cur;
1198   const char *addr_str;
1199
1200
1201   unsigned int suggest_res;
1202
1203   fail_pretty_printer = GNUNET_YES;
1204   fail_notify_address = GNUNET_YES;
1205   fail_addr_to_str = GNUNET_YES;
1206   fail_msgs_transmited_to_local_addrs = 0;
1207   fail_msg_transmited_max_size = GNUNET_YES;
1208   fail_multiple_msgs_in_transmission = 0;
1209   fail_session_selection_reliable = GNUNET_YES;
1210   fail_session_selection_reliable = GNUNET_YES;
1211   fail_session_selection_session = GNUNET_YES;
1212   fail_session_selection_session_big = GNUNET_YES;
1213
1214   addr_head = NULL;
1215   count_str_addr = 0;
1216   /* parse configuration */
1217   if (GNUNET_CONFIGURATION_have_value (c, "PATHS", "SERVICEHOME"))
1218     GNUNET_CONFIGURATION_get_value_string (c, "PATHS", "SERVICEHOME",
1219                                            &servicehome);
1220
1221   if ((GNUNET_OK !=
1222        GNUNET_CONFIGURATION_get_value_number (c, "TRANSPORT", "NEIGHBOUR_LIMIT",
1223                                               &tneigh)) ||
1224       (GNUNET_OK !=
1225        GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY",
1226                                                 &keyfile)))
1227   {
1228     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1229                 _
1230                 ("Transport service is lacking key configuration settings.  Exiting.\n"));
1231     GNUNET_SCHEDULER_shutdown ();
1232     fail = 1;
1233     return;
1234   }
1235
1236   if ((GNUNET_OK !=
1237        GNUNET_CONFIGURATION_get_value_number (cfg, "transport-http", "PORT",
1238                                               &port)) || (port > 65535) ||
1239       (port == 0))
1240   {
1241     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "http",
1242                      _
1243                      ("Require valid port number for transport plugin `%s' in configuration!\n"),
1244                      "transport-http");
1245   }
1246
1247   max_connect_per_transport = (uint32_t) tneigh;
1248   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
1249   GNUNET_free (keyfile);
1250   if (my_private_key == NULL)
1251   {
1252     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1253                 _("Transport service could not access hostkey.  Exiting.\n"));
1254     GNUNET_SCHEDULER_shutdown ();
1255     fail = 1;
1256     return;
1257   }
1258
1259   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
1260   GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key),
1261                       &my_identity.hashPubKey);
1262
1263   /* assertions before start */
1264   GNUNET_assert ((port > 0) && (port <= 65535));
1265
1266   /* load plugins... */
1267   setup_plugin_environment ();
1268   GNUNET_asprintf (&libname, "libgnunet_plugin_transport_http");
1269   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading HTTP transport plugin `%s'\n"),
1270               libname);
1271   api = GNUNET_PLUGIN_load (libname, &env);
1272   GNUNET_free (libname);
1273   if (api == NULL)
1274   {
1275     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1276                 _("Failed to load transport plugin for http\n"));
1277     fail = 1;
1278     return;
1279   }
1280
1281
1282   ti_timeout = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &task_timeout, NULL);
1283
1284   /* testing plugin functionality */
1285   GNUNET_assert (0 != fail_notify_address_count);
1286   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1287               "Transport plugin returned %u addresses to connect to\n",
1288               fail_notify_address_count);
1289
1290   /* testing pretty printer with all addresses obtained from the plugin */
1291   cur = addr_head;
1292   while (cur != NULL)
1293   {
1294     api->address_pretty_printer (api->cls, "http", cur->addr, cur->addrlen,
1295                                  GNUNET_NO, TEST_TIMEOUT, &pretty_printer_cb,
1296                                  NULL);
1297     addr_str = api->address_to_string (api->cls, cur->addr, cur->addrlen);
1298     suggest_res = api->check_address (api->cls, cur->addr, cur->addrlen);
1299
1300     GNUNET_assert (GNUNET_OK == suggest_res);
1301     GNUNET_assert (NULL != addr_str);
1302     count_str_addr++;
1303     GNUNET_free ((char *) addr_str);
1304     cur = cur->next;
1305   }
1306   GNUNET_assert (fail_pretty_printer_count > 0);
1307   GNUNET_assert (fail_pretty_printer_count == fail_notify_address_count);
1308   GNUNET_assert (fail_pretty_printer_count == count_str_addr);
1309   fail_pretty_printer = GNUNET_NO;
1310   fail_addr_to_str = GNUNET_NO;
1311
1312   struct IPv4HttpAddress failing_addr;
1313
1314   /* Suggesting addresses with wrong size */
1315   failing_addr.ipv4_addr = htonl (INADDR_LOOPBACK);
1316   failing_addr.u_port = htons (0);
1317   suggest_res =
1318       api->check_address (api->cls, &failing_addr,
1319                           sizeof (struct IPv6HttpAddress));
1320   GNUNET_assert (GNUNET_SYSERR == suggest_res);
1321
1322   /* Suggesting addresses with wrong address */
1323   failing_addr.ipv4_addr = htonl (0xffc00000);
1324   failing_addr.u_port = htons (12389);
1325   suggest_res = api->check_address (api->cls, &failing_addr, 100);
1326   GNUNET_assert (GNUNET_SYSERR == suggest_res);
1327
1328   /* test sending to client */
1329   multi_handle = curl_multi_init ();
1330
1331   /* Setting up buffers */
1332   buffer_in.size = HTTP_BUFFER_SIZE;
1333   buffer_in.pos = 0;
1334   buffer_in.len = 0;
1335
1336   buffer_out.size = HTTP_BUFFER_SIZE;
1337   buffer_out.pos = 0;
1338   buffer_out.len = 0;
1339
1340   /* Setting up connection tests */
1341
1342   /* Test: connecting without a peer identification */
1343   test_no_ident.test_executed = GNUNET_NO;
1344   test_no_ident.test_failed = GNUNET_YES;
1345
1346   /* Test: connecting with too short peer identification */
1347   test_too_short_ident.test_executed = GNUNET_NO;
1348   test_too_short_ident.test_failed = GNUNET_YES;
1349
1350   /* Test: connecting with too long peer identification */
1351   test_too_long_ident.test_executed = GNUNET_NO;
1352   test_too_long_ident.test_failed = GNUNET_YES;
1353
1354   /* Test: connecting with valid identification */
1355   test_valid_ident.test_executed = GNUNET_NO;
1356   test_valid_ident.test_failed = GNUNET_YES;
1357
1358   test_addr =
1359       (char *) api->address_to_string (api->cls, addr_head->addr,
1360                                        addr_head->addrlen);
1361
1362   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Phase 0\n\n"));
1363   run_connection_tests (0, NULL);
1364   /* testing finished */
1365 }
1366
1367
1368 /**
1369  * The main function for the transport service.
1370  *
1371  * @param argc number of arguments from the command line
1372  * @param argv command line arguments
1373  * @return 0 ok, 1 on error
1374  */
1375 int
1376 main (int argc, char *const *argv)
1377 {
1378   static struct GNUNET_GETOPT_CommandLineOption options[] = {
1379     GNUNET_GETOPT_OPTION_END
1380   };
1381   int ret;
1382
1383   char *const argv_prog[] = {
1384     "test_gnunet_transport_plugin_http",
1385     "-c",
1386     "test_plugin_transport_data_http.conf",
1387     "-L",
1388 #if VERBOSE
1389     "DEBUG",
1390 #else
1391     "WARNING",
1392 #endif
1393     NULL
1394   };
1395   GNUNET_log_setup ("test_gnunet_transport_plugin_http",
1396 #if VERBOSE
1397                     "DEBUG",
1398 #else
1399                     "WARNING",
1400 #endif
1401                     NULL);
1402
1403   struct GNUNET_CONFIGURATION_Handle *cfg;
1404
1405   cfg = GNUNET_CONFIGURATION_create ();
1406
1407   GNUNET_assert (GNUNET_OK ==
1408                  GNUNET_CONFIGURATION_load (cfg,
1409                                             "test_plugin_transport_data_http.conf"));
1410   if (GNUNET_CONFIGURATION_have_value (cfg, "PATHS", "SERVICEHOME"))
1411     GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "SERVICEHOME",
1412                                            &servicehome);
1413   GNUNET_DISK_directory_remove (servicehome);
1414   GNUNET_CONFIGURATION_destroy (cfg);
1415
1416   ret =
1417       (GNUNET_OK ==
1418        GNUNET_PROGRAM_run (5, argv_prog, "test_gnunet_transport_plugin_http",
1419                            "testcase", options, &run,
1420                            NULL)) ? GNUNET_NO : GNUNET_YES;
1421
1422   if (servicehome != NULL)
1423   {
1424     GNUNET_DISK_directory_remove (servicehome);
1425     GNUNET_free (servicehome);
1426   }
1427   if (ret != GNUNET_OK)
1428     return 1;
1429   return fail;
1430 }
1431
1432 /* end of test_gnunet_transport_plugin_http.c */