wip
[oweals/gnunet.git] / src / transport / test_quota_compliance.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 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_quota_compliance.c
22  * @brief base test case for transport implementations
23  *
24  * This test case tests quota compliance both on core and transport level
25  */
26 #include "platform.h"
27 #include "gnunet_common.h"
28 #include "gnunet_hello_lib.h"
29 #include "gnunet_getopt_lib.h"
30 #include "gnunet_os_lib.h"
31 #include "gnunet_program_lib.h"
32 #include "gnunet_scheduler_lib.h"
33 #include "gnunet_server_lib.h"
34 #include "gnunet_transport_service.h"
35 #include "transport.h"
36
37 #define VERBOSE GNUNET_NO
38
39 #define VERBOSE_ARM GNUNET_NO
40
41 #define START_ARM GNUNET_YES
42 #define DEBUG_MEASUREMENT GNUNET_NO
43 #define DEBUG_CONNECTIONS GNUNET_NO
44
45 #define MEASUREMENT_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
46 #define MEASUREMENT_MSG_SIZE 1024
47 #define MEASUREMENT_MSG_SIZE_BIG 32768
48 #define MEASUREMENT_MAX_QUOTA 1024 * 1024 * 1024
49 #define MEASUREMENT_MIN_QUOTA 1024
50 #define SEND_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
51 #define MEASUREMENT_SOFT_LIMIT 1024
52
53 /**
54  * Testcase timeout
55  */
56 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 200)
57
58
59
60 #define MTYPE 11111
61
62 struct PeerContext
63 {
64   struct GNUNET_CONFIGURATION_Handle *cfg;
65   struct GNUNET_TRANSPORT_Handle *th;
66   struct GNUNET_PeerIdentity id;
67 #if START_ARM
68   struct GNUNET_OS_Process *arm_proc;
69 #endif
70 };
71
72 /**
73  * Handle for a transmission-ready request.
74  */
75 struct GNUNET_TRANSPORT_TransmitHandle
76 {
77
78   /**
79    * Neighbour for this handle, NULL for control-traffic.
80    */
81   struct NeighbourList *neighbour;
82
83   /**
84    * Function to call when notify_size bytes are available
85    * for transmission.
86    */
87   GNUNET_CONNECTION_TransmitReadyNotify notify;
88
89   /**
90    * Closure for notify.
91    */
92   void *notify_cls;
93
94   /**
95    * transmit_ready task Id.  The task is used to introduce the
96    * artificial delay that may be required to maintain the bandwidth
97    * limits.  Later, this will be the ID of the "transmit_timeout"
98    * task which is used to signal a timeout if the transmission could
99    * not be done in a timely fashion.
100    */
101   GNUNET_SCHEDULER_TaskIdentifier notify_delay_task;
102
103   /**
104    * Timeout for this request.
105    */
106   struct GNUNET_TIME_Absolute timeout;
107
108   /**
109    * How many bytes is our notify callback waiting for?
110    */
111   size_t notify_size;
112
113   /**
114    * How important is this message?
115    */
116   unsigned int priority;
117
118 };
119
120 static struct PeerContext p1;
121
122 static struct PeerContext p2;
123
124 static int ok;
125
126 static int connected;
127 static int measurement_running;
128 static int send_running;
129 static int recv_running;
130
131 static unsigned long long total_bytes_sent;
132 static unsigned long long last_msg_sent;
133 static unsigned long long last_msg_recv;
134 static unsigned long long current_quota_p1;
135 static unsigned long long current_quota_p2;
136
137 static int is_tcp;
138 static int is_tcp_nat;
139 static int is_http;
140 static int is_https;
141 static int is_udp;
142 static int is_unix;
143 static int is_asymmetric_send_constant;
144 static int is_asymmetric_recv_constant;
145
146 static struct GNUNET_TIME_Absolute start_time;
147
148 static GNUNET_SCHEDULER_TaskIdentifier die_task;
149 static GNUNET_SCHEDULER_TaskIdentifier measurement_task;
150 static GNUNET_SCHEDULER_TaskIdentifier measurement_counter_task;
151
152 static struct GNUNET_TRANSPORT_TransmitHandle * transmit_handle;
153
154 #define OKPP do { ok++; } while (0)
155
156
157
158 static void
159 end_send ()
160 {
161
162 }
163
164 static void
165 end ()
166 {
167   GNUNET_SCHEDULER_cancel (die_task);
168   die_task = GNUNET_SCHEDULER_NO_TASK;
169
170   if (measurement_task != GNUNET_SCHEDULER_NO_TASK)
171   {
172             GNUNET_SCHEDULER_cancel (measurement_task);
173             measurement_task = GNUNET_SCHEDULER_NO_TASK;
174   }
175   if (measurement_counter_task != GNUNET_SCHEDULER_NO_TASK)
176   {
177             GNUNET_SCHEDULER_cancel (measurement_counter_task);
178             measurement_counter_task = GNUNET_SCHEDULER_NO_TASK;
179   }
180   fprintf(stderr,"\n");
181   GNUNET_SCHEDULER_shutdown ();
182 #if DEBUG_CONNECTIONS
183   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from transports!\n");
184 #endif
185   GNUNET_TRANSPORT_disconnect (p1.th);
186   GNUNET_TRANSPORT_disconnect (p2.th);
187 #if DEBUG_CONNECTIONS
188   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
189               "Transports disconnected, returning success!\n");
190 #endif
191   GNUNET_SCHEDULER_shutdown ();
192 }
193
194
195
196 static void
197 stop_arm (struct PeerContext *p)
198 {
199 #if START_ARM
200   if (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM))
201     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
202   GNUNET_OS_process_wait (p->arm_proc);
203   GNUNET_OS_process_close (p->arm_proc);
204   p->arm_proc = NULL;
205 #endif
206   GNUNET_CONFIGURATION_destroy (p->cfg);
207 }
208
209
210 static void
211 end_badly (void *cls,
212            const struct GNUNET_SCHEDULER_TaskContext *tc)
213 {
214   if (measurement_task != GNUNET_SCHEDULER_NO_TASK)
215   {
216             GNUNET_SCHEDULER_cancel (measurement_task);
217             measurement_task = GNUNET_SCHEDULER_NO_TASK;
218   }
219   if (measurement_counter_task != GNUNET_SCHEDULER_NO_TASK)
220   {
221             GNUNET_SCHEDULER_cancel (measurement_counter_task);
222             measurement_counter_task = GNUNET_SCHEDULER_NO_TASK;
223   }
224   GNUNET_break (0);
225   if (p1.th != NULL)
226           GNUNET_TRANSPORT_disconnect (p1.th);
227   if (p2.th != NULL)
228           GNUNET_TRANSPORT_disconnect (p2.th);
229   ok = 1;
230 }
231
232 struct TestMessage
233 {
234   struct GNUNET_MessageHeader header;
235   uint32_t num;
236 };
237
238 static unsigned int
239 get_size (void)
240 {
241   return MEASUREMENT_MSG_SIZE + sizeof (struct TestMessage);
242 }
243
244 static void
245 notify_receive_new (void *cls,
246                 const struct GNUNET_PeerIdentity *peer,
247                 const struct GNUNET_MessageHeader *message,
248                 const struct GNUNET_TRANSPORT_ATS_Information *ats, uint32_t ats_count)
249 {
250   unsigned int s;
251   const struct TestMessage *hdr;
252
253   hdr = (const struct TestMessage*) message;
254   s = get_size ();
255   if (measurement_running == GNUNET_NO)
256           return;
257   if (MTYPE != ntohs (message->type))
258     return;
259
260 #if DEBUG_MEASUREMENT
261   if (ntohl(hdr->num) % 5000 == 0)
262     {
263       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
264                   "Got message %u of size %u\n",
265                   ntohl (hdr->num),
266                   ntohs (message->size));
267     }
268 #endif
269   /*
270   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
271               "Got message %u\n",
272               ntohl (hdr->num));*/
273   last_msg_recv = ntohl (hdr->num);
274 }
275
276 static size_t
277 notify_ready (void *cls, size_t size, void *buf)
278 {
279   char *cbuf = buf;
280   struct TestMessage hdr;
281   unsigned int s;
282   unsigned int ret;
283
284   transmit_handle = NULL;
285
286   if (measurement_task == GNUNET_SCHEDULER_NO_TASK)
287           return 0;
288
289   if (buf == NULL)
290     {
291       ok = 42;
292       return 0;
293     }
294
295   if (measurement_running != GNUNET_YES)
296   {
297           send_running = GNUNET_NO;
298           end_send();
299           return 0;
300   }
301
302   send_running = GNUNET_YES;
303   ret = 0;
304   s = get_size ();
305   GNUNET_assert (size >= s);
306   GNUNET_assert (buf != NULL);
307   last_msg_sent++;
308   cbuf = buf;
309   do
310     {
311       hdr.header.size = htons (s);
312       hdr.header.type = htons (MTYPE);
313       hdr.num = htonl (last_msg_sent);
314       memcpy (&cbuf[ret], &hdr, sizeof (struct TestMessage));
315       ret += sizeof (struct TestMessage);
316       memset (&cbuf[ret], last_msg_sent, s - sizeof (struct TestMessage));
317       ret += s - sizeof (struct TestMessage);
318 #if DEBUG_MEASUREMENT
319       if (n % 5000 == 0)
320        {
321           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
322                       "Sending message %u\n",n);
323        }
324 #endif
325
326     /*      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
327                       "Sending message %u\n",last_msg_sent);*/
328
329       s = get_size ();
330       if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16))
331         break; /* sometimes pack buffer full, sometimes not */
332     }
333   while (size - ret >= s);
334   transmit_handle = GNUNET_TRANSPORT_notify_transmit_ready (p2.th,
335                                             &p1.id,
336                                             s, 0, SEND_TIMEOUT,
337                                             &notify_ready,
338                                             NULL);
339   total_bytes_sent += s;
340   return ret;
341 }
342
343 static void measure (unsigned long long quota_p1, unsigned long long quota_p2 );
344
345 static void measurement_counter
346  (void *cls,
347            const struct GNUNET_SCHEDULER_TaskContext *tc)
348 {
349   measurement_counter_task = GNUNET_SCHEDULER_NO_TASK;
350
351   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
352         return;
353
354   fprintf(stderr,".");
355   measurement_counter_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
356                                                            &measurement_counter,
357                                                            NULL);
358 }
359
360 static void
361 measurement_end (void *cls,
362            const struct GNUNET_SCHEDULER_TaskContext *tc)
363 {
364   static int strike_counter;
365   static int failed_measurement_counter = 1;
366   unsigned long long  quota_allowed = 0;
367   int delta = 0;
368
369   measurement_task  = GNUNET_SCHEDULER_NO_TASK;
370   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
371         return;
372
373   measurement_running = GNUNET_NO;
374   struct GNUNET_TIME_Relative duration = GNUNET_TIME_absolute_get_difference(start_time, GNUNET_TIME_absolute_get());
375
376
377   if (measurement_counter_task != GNUNET_SCHEDULER_NO_TASK)
378   {
379     GNUNET_SCHEDULER_cancel (measurement_counter_task);
380     measurement_counter_task = GNUNET_SCHEDULER_NO_TASK;
381   }
382
383   if (transmit_handle != NULL)
384   {
385           GNUNET_TRANSPORT_notify_transmit_ready_cancel(transmit_handle);
386           transmit_handle = NULL;
387   }
388
389   if (current_quota_p1 < current_quota_p2)
390           quota_allowed = current_quota_p1;
391   else
392           quota_allowed = current_quota_p2;
393
394
395   if (MEASUREMENT_SOFT_LIMIT > (quota_allowed/3))
396           delta = MEASUREMENT_SOFT_LIMIT;
397   else
398           delta = (quota_allowed/3);
399
400   /* Throughput is far too slow. This is to prevent the test to exit with success when throughput is 0 */
401   if ((total_bytes_sent/(duration.rel_value / 1000)) < 100)
402   {
403           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
404                           "\nQuota compliance failed: \n"\
405                           "Hard quota limit allowed: %10llu kB/s (%llu B/s)\n"\
406                           "Soft quota limit allowed: %10llu kB/s (%llu B/s)\n"\
407                           "Throughput              : %10llu kB/s (%llu B/s)\n",
408                           (quota_allowed / (1024)), quota_allowed,
409                           ((quota_allowed+delta) / (1024)),  quota_allowed+delta,
410                           (total_bytes_sent/(duration.rel_value / 1000)/1024),
411                           total_bytes_sent/(duration.rel_value / 1000));
412           ok = 1;
413           failed_measurement_counter--;
414           if (failed_measurement_counter < 0)
415           {
416                   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
417                                   "\nQuota measurement failed and no free strike: %i\n",failed_measurement_counter);
418                   end();
419                   return;
420           }
421           else
422                   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
423                                   "\nQuota measurement failed and %i free strikes\n",failed_measurement_counter);
424   }
425
426   /* Throughput is bigger than allowed quota + some extra*/
427   if ((total_bytes_sent/(duration.rel_value / 1000)) > (quota_allowed + delta))
428   {
429           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
430                           "\nQuota compliance failed: \n"\
431                           "Hard quota limit allowed: %10llu kB/s (%llu B/s)\n"\
432                           "Soft quota limit allowed: %10llu kB/s (%llu B/s)\n"\
433                           "Throughput              : %10llu kB/s (%llu B/s)\n", 
434                           (quota_allowed / (1024)), quota_allowed, 
435                           ((quota_allowed+delta) / (1024)),  quota_allowed+delta, 
436                           (total_bytes_sent/(duration.rel_value / 1000)/1024), 
437                           total_bytes_sent/(duration.rel_value / 1000));
438           ok = 1;
439           failed_measurement_counter--;
440           if (failed_measurement_counter < 0)
441           {
442                   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
443                                   "\nQuota measurement failed and no free strike: %i\n",failed_measurement_counter);
444                   end();
445                   return;
446           }
447           else
448                   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
449                                   "\nQuota measurement failed and %i free strikes\n",failed_measurement_counter);
450   }
451   else
452   {
453           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
454                           "\nQuota compliance ok: \n"\
455                           "Quota allowed: %10llu kB/s\n"\
456                           "Throughput   : %10llu kB/s\n", (quota_allowed / (1024)) , (total_bytes_sent/(duration.rel_value / 1000)/1024));
457           if (failed_measurement_counter < 2)
458                   failed_measurement_counter++;
459           ok = 0;
460   }
461
462   if ((quota_allowed) > (2 *(total_bytes_sent/(duration.rel_value / 1000))))
463   {
464           if (failed_measurement_counter < 2)
465                   failed_measurement_counter++;
466           if (strike_counter == 2)
467           {
468                   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
469                                   "Maximum transmission rate reached, stopping test\n");
470                   end();
471                   return;
472           }
473   }
474   else
475   {
476           strike_counter = 0;
477   }
478
479   if (quota_allowed == MEASUREMENT_MAX_QUOTA)
480   {
481           end();
482           return;
483   }
484   if (is_asymmetric_send_constant == GNUNET_YES)
485   {
486    if ((quota_allowed * 2) < MEASUREMENT_MAX_QUOTA)
487           measure (current_quota_p1 * 2, MEASUREMENT_MAX_QUOTA);
488    else
489            measure (MEASUREMENT_MAX_QUOTA, MEASUREMENT_MAX_QUOTA);
490   }
491   else if (is_asymmetric_recv_constant == GNUNET_YES)
492   {
493    if ((quota_allowed * 2) < MEASUREMENT_MAX_QUOTA)
494           measure (MEASUREMENT_MAX_QUOTA, current_quota_p2 * 2);
495    else
496            measure (MEASUREMENT_MAX_QUOTA, MEASUREMENT_MAX_QUOTA);
497   }
498   else
499   {
500    if ((quota_allowed * 2) < MEASUREMENT_MAX_QUOTA)
501           measure ((current_quota_p1) * 2, (current_quota_p2) * 2);
502    else
503            measure (MEASUREMENT_MAX_QUOTA, MEASUREMENT_MAX_QUOTA);
504   }
505 }
506
507 static void measure (unsigned long long quota_p1, unsigned long long quota_p2 )
508 {
509           current_quota_p1 = quota_p1;
510           current_quota_p2 = quota_p2;
511 #if VERBOSE
512   if ((is_asymmetric_send_constant == GNUNET_YES) || (is_asymmetric_recv_constant == GNUNET_YES))
513           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
514               "Starting transport level measurement for %u seconds, receiving peer quota %llu kB/s, sending peer quota %llu kB/s\n", MEASUREMENT_INTERVALL.rel_value / 1000 , current_quota_p1 / 1024, current_quota_p2 / 1024);
515   else
516           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
517               "Starting transport level measurement for %u seconds, symmetric quota %llu kB/s\n", MEASUREMENT_INTERVALL.rel_value / 1000 , current_quota_p2 / 1024);
518
519 #endif
520                 GNUNET_TRANSPORT_set_quota (p1.th,
521                           &p2.id,
522                           GNUNET_BANDWIDTH_value_init (current_quota_p1 ),
523                           GNUNET_BANDWIDTH_value_init (current_quota_p1 ),
524                           GNUNET_TIME_UNIT_FOREVER_REL,
525                           NULL, NULL);
526                 GNUNET_TRANSPORT_set_quota (p2.th,
527                           &p1.id,
528                           GNUNET_BANDWIDTH_value_init (current_quota_p2),
529                           GNUNET_BANDWIDTH_value_init (current_quota_p2),
530                           GNUNET_TIME_UNIT_FOREVER_REL,
531                           NULL, NULL);
532
533                 GNUNET_SCHEDULER_cancel (die_task);
534                 die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
535                                                    &end_badly,
536                                                    NULL);
537                 if (measurement_counter_task != GNUNET_SCHEDULER_NO_TASK)
538                   GNUNET_SCHEDULER_cancel (measurement_counter_task);
539                 measurement_counter_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
540                                                                    &measurement_counter,
541                                                                    NULL);
542                 measurement_task = GNUNET_SCHEDULER_add_delayed (MEASUREMENT_INTERVALL,
543                                                    &measurement_end,
544                                                    NULL);
545                 total_bytes_sent = 0;
546                 last_msg_sent = 0;
547                 last_msg_recv = 0;
548                 measurement_running = GNUNET_YES;
549                 start_time = GNUNET_TIME_absolute_get ();
550
551                 if (transmit_handle != NULL)
552                           GNUNET_TRANSPORT_notify_transmit_ready_cancel(transmit_handle);
553                 transmit_handle = GNUNET_TRANSPORT_notify_transmit_ready (p2.th,
554                                                                                           &p1.id,
555                                                                                           get_size (), 0, SEND_TIMEOUT,
556                                                                                           &notify_ready,
557                                                                                           NULL);
558 }
559
560 static void
561 notify_connect (void *cls,
562                 const struct GNUNET_PeerIdentity *peer,
563                 const struct GNUNET_TRANSPORT_ATS_Information *ats, uint32_t ats_count)
564 {
565   if (cls == &p1)
566     {
567 #if DEBUG_CONNECTIONS
568   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
569               "Peer 1 `%4s' connected to us (%p)!\n", GNUNET_i2s (peer), cls);
570 #endif
571           connected++;
572     }
573   else
574     {
575 #if DEBUG_CONNECTIONS
576   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
577               "Peer 2 `%4s' connected to us (%p)!\n", GNUNET_i2s (peer), cls);
578 #endif
579       connected++;
580     }
581   if (connected == 2)
582     {
583            if (is_asymmetric_send_constant == GNUNET_YES)
584                    measure (MEASUREMENT_MIN_QUOTA, MEASUREMENT_MAX_QUOTA);
585            else if (is_asymmetric_recv_constant == GNUNET_YES)
586                    measure (MEASUREMENT_MAX_QUOTA, MEASUREMENT_MIN_QUOTA);
587            else
588                    measure (MEASUREMENT_MIN_QUOTA, MEASUREMENT_MIN_QUOTA);
589     }
590 }
591
592
593 static void
594 notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
595 {
596 #if DEBUG_CONNECTIONS
597   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
598               "Peer `%4s' disconnected (%p)!\n",
599               GNUNET_i2s (peer), cls);
600 #endif
601 }
602
603
604 static void
605 setup_peer (struct PeerContext *p, const char *cfgname)
606 {
607   p->cfg = GNUNET_CONFIGURATION_create ();
608 #if START_ARM
609   p->arm_proc = GNUNET_OS_start_process (NULL, NULL,
610                                         "gnunet-service-arm",
611                                         "gnunet-service-arm",
612 #if VERBOSE_ARM
613                                         "-L", "DEBUG",
614 #endif
615                                         "-c", cfgname, NULL);
616 #endif
617
618   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
619   p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL,
620                                     p,
621                                     &notify_receive_new,
622                                     &notify_connect,
623                                     &notify_disconnect);
624   GNUNET_assert (p->th != NULL);
625 }
626
627 static size_t
628 notify_ready_connect (void *cls, size_t size, void *buf)
629 {
630   return 0;
631 }
632
633 static void
634 exchange_hello_last (void *cls,
635                      const struct GNUNET_MessageHeader *message)
636 {
637   struct PeerContext *me = cls;
638
639   GNUNET_TRANSPORT_get_hello_cancel (p2.th, &exchange_hello_last, me);
640
641   GNUNET_assert (ok >= 3);
642   OKPP;
643   GNUNET_assert (message != NULL);
644   GNUNET_assert (GNUNET_OK ==
645                  GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
646                                       message, &me->id));
647
648   GNUNET_assert(NULL != (transmit_handle = GNUNET_TRANSPORT_notify_transmit_ready (p2.th,
649                                           &p1.id,
650                                           sizeof (struct GNUNET_MessageHeader), 0,
651                                           TIMEOUT,
652                                           &notify_ready_connect,
653                                           NULL)));
654
655   /* both HELLOs exchanged, get ready to test transmission! */
656 }
657
658
659 static void
660 exchange_hello (void *cls,
661                 const struct GNUNET_MessageHeader *message)
662 {
663   struct PeerContext *me = cls;
664
665   GNUNET_TRANSPORT_get_hello_cancel (p1.th, &exchange_hello, me);
666   GNUNET_assert (ok >= 2);
667   OKPP;
668   GNUNET_assert (message != NULL);
669   GNUNET_assert (GNUNET_OK ==
670                  GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
671                                       message, &me->id));
672   GNUNET_TRANSPORT_offer_hello (p2.th, message, NULL, NULL);
673   GNUNET_TRANSPORT_get_hello (p2.th, &exchange_hello_last, &p2);
674 }
675
676 static void
677 run (void *cls,
678      char *const *args,
679      const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
680 {
681   GNUNET_assert (ok == 1);
682   OKPP;
683
684   die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
685                                            &end_badly,
686                                            NULL);
687   measurement_running = GNUNET_NO;
688   send_running = GNUNET_NO;
689   recv_running = GNUNET_NO;
690
691   if (is_tcp)
692     {
693           if (is_asymmetric_recv_constant == GNUNET_YES)
694                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing asymmetric quota compliance (receiver quota constant) for TCP transport plugin\n");
695           else if (is_asymmetric_send_constant == GNUNET_YES)
696                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing asymmetric quota compliance (sender quota constant) for TCP transport plugin\n");
697           else
698                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing symmetric quota compliance for TCP transport plugin\n");
699       setup_peer (&p1, "test_quota_compliance_tcp_peer1.conf");
700       setup_peer (&p2, "test_quota_compliance_tcp_peer2.conf");
701     }
702   else if (is_http)
703     {
704           if (is_asymmetric_recv_constant == GNUNET_YES)
705                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing asymmetric quota compliance (receiver quota constant) for HTTP transport plugin\n");
706           else if (is_asymmetric_send_constant == GNUNET_YES)
707                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing asymmetric quota compliance (sender quota constant) for HTTP transport plugin\n");
708           else
709                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing symmetric quota compliance for HTTP transport plugin\n");
710       setup_peer (&p1, "test_quota_compliance_http_peer1.conf");
711       setup_peer (&p2, "test_quota_compliance_http_peer2.conf");
712     }
713   else if (is_https)
714     {
715           if (is_asymmetric_recv_constant == GNUNET_YES)
716                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing asymmetric quota compliance (receiver quota constant) for HTTPS transport plugin\n");
717           else if (is_asymmetric_send_constant == GNUNET_YES)
718                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing asymmetric quota compliance (sender quota constant) for HTTPS transport plugin\n");
719           else
720                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing symmetric quota compliance for HTTPS transport plugin\n");
721       setup_peer (&p1, "test_quota_compliance_https_peer1.conf");
722       setup_peer (&p2, "test_quota_compliance_https_peer2.conf");
723     }
724   else if (is_udp)
725     {
726           if (is_asymmetric_recv_constant == GNUNET_YES)
727                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing asymmetric quota compliance (receiver quota constant) for UDP transport plugin\n");
728           else if (is_asymmetric_send_constant == GNUNET_YES)
729                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing asymmetric quota compliance (sender quota constant) for UDP transport plugin\n");
730           else
731                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing symmetric quota compliance for UDP transport plugin\n");
732       setup_peer (&p1, "test_quota_compliance_udp_peer1.conf");
733       setup_peer (&p2, "test_quota_compliance_udp_peer2.conf");
734     }
735   else if (is_unix)
736     {
737           if (is_asymmetric_recv_constant == GNUNET_YES)
738                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing asymmetric quota compliance (receiver quota constant) for UNIX transport plugin\n");
739           else if (is_asymmetric_send_constant == GNUNET_YES)
740                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing asymmetric quota compliance (sender quota constant) for UNIX transport plugin\n");
741           else
742                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing symmetric quota compliance for UNIX transport plugin\n");
743       setup_peer (&p1, "test_quota_compliance_unix_peer1.conf");
744       setup_peer (&p2, "test_quota_compliance_unix_peer2.conf");
745     }
746   else if (is_tcp_nat)
747     {
748           if (is_asymmetric_recv_constant == GNUNET_YES)
749                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing asymmetric quota compliance (receiver quota constant) for TCP NAT transport plugin\n");
750           else if (is_asymmetric_send_constant == GNUNET_YES)
751                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing asymmetric quota compliance (sender quota constant) for TCP NAT transport plugin\n");
752           else
753                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing symmetric quota compliance for TCP NAT transport plugin\n");
754       setup_peer (&p1, "test_quota_compliance_tcp_peer1.conf");
755       setup_peer (&p2, "test_quota_compliance_tcp_peer2.conf");
756     }
757   else
758     GNUNET_assert (0);
759
760   GNUNET_assert(p1.th != NULL);
761   GNUNET_assert(p2.th != NULL);
762   GNUNET_TRANSPORT_get_hello (p1.th, &exchange_hello, &p1);
763 }
764
765 int
766 main (int argc, char *argv[])
767 {
768   int ret = 0;
769 #ifdef MINGW
770   return GNUNET_SYSERR;
771 #endif
772   if (strstr(argv[0], "tcp_nat") != NULL)
773     {
774       is_tcp_nat = GNUNET_YES;
775     }
776   else if (strstr(argv[0], "tcp") != NULL)
777     {
778       is_tcp = GNUNET_YES;
779     }
780   else if (strstr(argv[0], "https") != NULL)
781     {
782       is_https = GNUNET_YES;
783     }
784   else if (strstr(argv[0], "http") != NULL)
785     {
786       is_http = GNUNET_YES;
787     }
788   else if (strstr(argv[0], "udp") != NULL)
789     {
790       is_udp = GNUNET_YES;
791     }
792   else if (strstr(argv[0], "unix") != NULL)
793     {
794       is_unix = GNUNET_YES;
795     }
796
797   if (strstr(argv[0], "asymmetric_recv") != NULL)
798   {
799       is_asymmetric_recv_constant = GNUNET_YES;
800   }
801   else
802           is_asymmetric_recv_constant = GNUNET_NO;
803   if (strstr(argv[0], "asymmetric_send") != NULL)
804   {
805       is_asymmetric_send_constant = GNUNET_YES;
806   }
807   else
808           is_asymmetric_send_constant = GNUNET_NO;
809
810   char * logger;
811   if (is_tcp == GNUNET_YES)
812   {
813           if (is_asymmetric_recv_constant == GNUNET_YES)
814                   GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","tcp","asymmetric_recv_constant");
815           else if (is_asymmetric_send_constant == GNUNET_YES)
816                   GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","tcp","asymmetric_send_constant");
817           else
818                   GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","tcp","symmetric");
819   }
820   else if (is_udp == GNUNET_YES)
821   {
822           if (is_asymmetric_recv_constant == GNUNET_YES)
823                   GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","udp","asymmetric_recv_constant");
824           else if (is_asymmetric_send_constant == GNUNET_YES)
825                   GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","udp","asymmetric_send_constant");
826           else
827                   GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","udp","symmetric");
828   }
829   else if (is_unix == GNUNET_YES)
830   {
831           if (is_asymmetric_recv_constant == GNUNET_YES)
832                   GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","unix","asymmetric_recv_constant");
833           else if (is_asymmetric_send_constant == GNUNET_YES)
834                   GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","unix","asymmetric_send_constant");
835           else
836                   GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","unix","symmetric");
837   }
838   else if (is_http == GNUNET_YES)
839   {
840           if (is_asymmetric_recv_constant == GNUNET_YES)
841                   GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","http","asymmetric_recv_constant");
842           else if (is_asymmetric_send_constant == GNUNET_YES)
843                   GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","http","asymmetric_send_constant");
844           else
845                   GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","http","symmetric");
846   }
847   else if (is_https == GNUNET_YES)
848   {
849           if (is_asymmetric_recv_constant == GNUNET_YES)
850                   GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","https","asymmetric_recv_constant");
851           else if (is_asymmetric_send_constant == GNUNET_YES)
852                   GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","https","asymmetric_send_constant");
853           else
854                   GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","https","symmetric");
855   }
856   else
857   {
858           GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","noplugin","none");
859   }
860
861   GNUNET_DISK_directory_remove ("/tmp/test_quota_compliance_peer1");
862   GNUNET_DISK_directory_remove ("/tmp/test_quota_compliance_peer2");
863
864   fprintf(stderr,  "Running `%s'\n", logger);
865   GNUNET_log_setup ("test-quota-compliance",
866 #if VERBOSE
867                     "DEBUG",
868 #else
869                     "WARNING",
870 #endif
871                     NULL);
872   char *const argv1[] = { "test-quota-compliance",
873     "-c",
874     "test_quota_compliance_data.conf",
875 #if VERBOSE
876     "-L", "DEBUG",
877 #endif
878     NULL
879   };
880   struct GNUNET_GETOPT_CommandLineOption options[] = {
881     GNUNET_GETOPT_OPTION_END
882   };
883   ok = 1;
884   GNUNET_PROGRAM_run ((sizeof (argv1) / sizeof (char *)) - 1,
885                       argv1, logger , "nohelp",
886                       options, &run, &ok);
887   ret = ok;
888   stop_arm (&p1);
889   stop_arm (&p2);
890   GNUNET_free(logger);
891   GNUNET_DISK_directory_remove ("/tmp/test_quota_compliance_peer1");
892   GNUNET_DISK_directory_remove ("/tmp/test_quota_compliance_peer2");
893   return ret;
894 }
895
896 /* end of test_quota_compliance.c */