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