0143772db2248ebf2a45ccaaf0baeca1e7062ff0
[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,
169               "Disconnecting from transports!\n");
170 #endif
171   GNUNET_TRANSPORT_disconnect (p1.th);
172   GNUNET_TRANSPORT_disconnect (p2.th);
173 #if DEBUG_CONNECTIONS
174   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
175               "Transports disconnected, returning success!\n");
176 #endif
177   GNUNET_SCHEDULER_shutdown ();
178 }
179
180
181
182 static void
183 stop_arm (struct PeerContext *p)
184 {
185 #if START_ARM
186   if (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM))
187     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
188   GNUNET_OS_process_wait (p->arm_proc);
189   GNUNET_OS_process_close (p->arm_proc);
190   p->arm_proc = NULL;
191 #endif
192   GNUNET_CONFIGURATION_destroy (p->cfg);
193 }
194
195
196 static void
197 end_badly (void *cls,
198            const struct GNUNET_SCHEDULER_TaskContext *tc)
199 {
200   if (measurement_task != GNUNET_SCHEDULER_NO_TASK)
201   {
202     GNUNET_SCHEDULER_cancel (measurement_task);
203     measurement_task = GNUNET_SCHEDULER_NO_TASK;
204   }
205   if (measurement_counter_task != GNUNET_SCHEDULER_NO_TASK)
206     {
207       GNUNET_SCHEDULER_cancel (measurement_counter_task);
208       measurement_counter_task = GNUNET_SCHEDULER_NO_TASK;
209     }
210   GNUNET_break (0);
211   if (GNUNET_SCHEDULER_NO_TASK != tct)
212     {
213       GNUNET_SCHEDULER_cancel (tct);
214       tct = GNUNET_SCHEDULER_NO_TASK;
215     }
216   if (p1.th != NULL)
217     GNUNET_TRANSPORT_disconnect (p1.th);
218   if (p2.th != NULL)
219     GNUNET_TRANSPORT_disconnect (p2.th);
220   ok = 1;
221 }
222
223 struct TestMessage
224 {
225   struct GNUNET_MessageHeader header;
226   uint32_t num;
227 };
228
229
230 static unsigned int
231 get_size ()
232 {
233   return MEASUREMENT_MSG_SIZE + sizeof (struct TestMessage);
234 }
235
236 static void
237 notify_receive_new (void *cls,
238                 const struct GNUNET_PeerIdentity *peer,
239                 const struct GNUNET_MessageHeader *message,
240                 const struct GNUNET_TRANSPORT_ATS_Information *ats, uint32_t ats_count)
241 {
242   const struct TestMessage *hdr;
243
244   GNUNET_assert (message != NULL);
245   hdr = (const struct TestMessage*) message;
246   if (measurement_running == GNUNET_NO)
247           return;
248   if (MTYPE != ntohs (message->type))
249     return;
250
251 #if DEBUG_MEASUREMENT
252   if (ntohl(hdr->num) % 5000 == 0)
253     {
254       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
255                   "Got message %u of size %u\n",
256                   ntohl (hdr->num),
257                   ntohs (message->size));
258     }
259 #endif
260   /*
261   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
262               "Got message %u\n",
263               ntohl (hdr->num));*/
264   last_msg_recv = ntohl (hdr->num);
265 }
266
267
268 static size_t
269 notify_ready (void *cls, size_t size, void *buf)
270 {
271   char *cbuf = buf;
272   struct TestMessage hdr;
273   unsigned int s;
274   unsigned int ret;
275
276   transmit_handle = NULL;
277   if (measurement_task == GNUNET_SCHEDULER_NO_TASK)
278     return 0;
279
280   if (buf == NULL)
281     {
282       ok = 42;
283       return 0;
284     }
285   if (measurement_running != GNUNET_YES)
286     {
287       send_running = GNUNET_NO;
288       return 0;
289     }
290   send_running = GNUNET_YES;
291   ret = 0;
292   s = get_size ();
293   GNUNET_assert (size >= s);
294   GNUNET_assert (buf != NULL);
295   last_msg_sent++;
296   cbuf = buf;
297   do
298     {
299       hdr.header.size = htons (s);
300       hdr.header.type = htons (MTYPE);
301       hdr.num = htonl (last_msg_sent);
302       memcpy (&cbuf[ret], &hdr, sizeof (struct TestMessage));
303       ret += sizeof (struct TestMessage);
304       memset (&cbuf[ret], last_msg_sent, s - sizeof (struct TestMessage));
305       ret += s - sizeof (struct TestMessage);
306
307       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
308                   "Sending message %u\n",last_msg_sent);
309
310       s = get_size ();
311       if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16))
312         break; /* sometimes pack buffer full, sometimes not */
313     }
314   while (size - ret >= s);
315   transmit_handle = GNUNET_TRANSPORT_notify_transmit_ready (p2.th,
316                                             &p1.id,
317                                             s, 0, SEND_TIMEOUT,
318                                             &notify_ready,
319                                             NULL);
320   total_bytes_sent += s;
321   return ret;
322 }
323
324
325 static void
326 measure (unsigned long long quota_p1, unsigned long long quota_p2);
327
328 static void 
329 measurement_counter (void *cls,
330                      const struct GNUNET_SCHEDULER_TaskContext *tc)
331 {
332   measurement_counter_task = GNUNET_SCHEDULER_NO_TASK;
333   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
334     return;
335   
336   fprintf(stderr,".");
337   measurement_counter_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
338                                                            &measurement_counter,
339                                                            NULL);
340 }
341
342
343 static void
344 measurement_end (void *cls,
345                  const struct GNUNET_SCHEDULER_TaskContext *tc)
346 {
347   static int strike_counter;
348   static int failed_measurement_counter = 1;
349   unsigned long long  quota_allowed = 0;
350   int delta = 0;
351
352   measurement_task  = GNUNET_SCHEDULER_NO_TASK;
353   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
354     return;
355
356   measurement_running = GNUNET_NO;
357   struct GNUNET_TIME_Relative duration
358     = GNUNET_TIME_absolute_get_difference(start_time, GNUNET_TIME_absolute_get());
359
360
361   if (measurement_counter_task != GNUNET_SCHEDULER_NO_TASK)
362     {
363       GNUNET_SCHEDULER_cancel (measurement_counter_task);
364       measurement_counter_task = GNUNET_SCHEDULER_NO_TASK;
365     }
366   
367   if (transmit_handle != NULL)
368     {
369       GNUNET_TRANSPORT_notify_transmit_ready_cancel(transmit_handle);
370       transmit_handle = NULL;
371     }
372   
373   if (current_quota_p1 < current_quota_p2)
374     quota_allowed = current_quota_p1;
375   else
376     quota_allowed = current_quota_p2;
377   
378   
379   if (MEASUREMENT_SOFT_LIMIT > (quota_allowed/3))
380     delta = MEASUREMENT_SOFT_LIMIT;
381   else
382     delta = (quota_allowed/3);
383   
384   /* Throughput is far too slow. This is to prevent the test to exit with success when throughput is 0 */
385   if ((total_bytes_sent/(duration.rel_value / 1000)) < 100)
386     {
387       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
388                   "\nQuota compliance failed: \n"                       \
389                   "Hard quota limit allowed: %10llu kB/s (%llu B/s)\n"  \
390                   "Soft quota limit allowed: %10llu kB/s (%llu B/s)\n"  \
391                   "Throughput              : %10llu kB/s (%llu B/s)\n",
392                   (quota_allowed / (1024)), quota_allowed,
393                   ((quota_allowed+delta) / (1024)),  quota_allowed+delta,
394                   (total_bytes_sent/(duration.rel_value / 1000)/1024),
395                   total_bytes_sent/(duration.rel_value / 1000));
396       ok = 1;
397       failed_measurement_counter--;
398       if (failed_measurement_counter < 0)
399         {
400           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
401                       "\nQuota measurement failed and no free strike: %i\n",
402                       failed_measurement_counter);
403           end();
404           return;
405         }
406       else
407         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
408                     "\nQuota measurement failed and %i free strikes\n",
409                     failed_measurement_counter);
410     }
411   
412   /* Throughput is bigger than allowed quota + some extra*/
413   if ((total_bytes_sent/(duration.rel_value / 1000)) > (quota_allowed + delta))
414     {
415       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
416                   "\nQuota compliance failed: \n"                       \
417                   "Hard quota limit allowed: %10llu kB/s (%llu B/s)\n"  \
418                   "Soft quota limit allowed: %10llu kB/s (%llu B/s)\n"  \
419                   "Throughput              : %10llu kB/s (%llu B/s)\n", 
420                   (quota_allowed / (1024)), quota_allowed, 
421                   ((quota_allowed+delta) / (1024)),  quota_allowed+delta, 
422                   (total_bytes_sent/(duration.rel_value / 1000)/1024), 
423                   total_bytes_sent/(duration.rel_value / 1000));
424       ok = 1;
425       failed_measurement_counter--;
426       if (failed_measurement_counter < 0)
427         {
428           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
429                       "\nQuota measurement failed and no free strike: %i\n",failed_measurement_counter);
430           end();
431           return;
432         }
433       else
434         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
435                     "\nQuota measurement failed and %i free strikes\n",failed_measurement_counter);
436     }
437   else
438     {
439       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
440                   "\nQuota compliance ok: \n"                   \
441                   "Quota allowed: %10llu kB/s\n"                        \
442                   "Throughput   : %10llu kB/s\n",
443                   (quota_allowed / (1024)), 
444                   (total_bytes_sent/(duration.rel_value / 1000)/1024));
445       if (failed_measurement_counter < 2)
446         failed_measurement_counter++;
447       ok = 0;
448     }
449   
450   if ((quota_allowed) > (2 *(total_bytes_sent/(duration.rel_value / 1000))))
451     {
452       if (failed_measurement_counter < 2)
453         failed_measurement_counter++;
454       if (strike_counter == 2)
455         {
456           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
457                       "Maximum transmission rate reached, stopping test\n");
458           end();
459           return;
460         }
461     }
462   else
463     {
464       strike_counter = 0;
465     }
466   
467   if (quota_allowed == MEASUREMENT_MAX_QUOTA)
468     {
469       end();
470       return;
471     }
472   if (is_asymmetric_send_constant == GNUNET_YES)
473     {
474       if ((quota_allowed * 2) < MEASUREMENT_MAX_QUOTA)
475         measure (current_quota_p1 * 2, MEASUREMENT_MAX_QUOTA);
476       else
477         measure (MEASUREMENT_MAX_QUOTA, MEASUREMENT_MAX_QUOTA);
478     }
479   else if (is_asymmetric_recv_constant == GNUNET_YES)
480     {
481       if ((quota_allowed * 2) < MEASUREMENT_MAX_QUOTA)
482         measure (MEASUREMENT_MAX_QUOTA, current_quota_p2 * 2);
483       else
484         measure (MEASUREMENT_MAX_QUOTA, MEASUREMENT_MAX_QUOTA);
485     }
486   else
487     {
488       if ((quota_allowed * 2) < MEASUREMENT_MAX_QUOTA)
489         measure ((current_quota_p1) * 2, (current_quota_p2) * 2);
490       else
491         measure (MEASUREMENT_MAX_QUOTA, MEASUREMENT_MAX_QUOTA);
492     }
493 }
494
495 static void 
496 measure (unsigned long long quota_p1, unsigned long long quota_p2)
497 {
498   current_quota_p1 = quota_p1;
499   current_quota_p2 = quota_p2;
500 #if VERBOSE
501   if ((is_asymmetric_send_constant == GNUNET_YES) || (is_asymmetric_recv_constant == GNUNET_YES))
502     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
503                 "Starting transport level measurement for %u seconds, receiving peer quota %llu kB/s, sending peer quota %llu kB/s\n",
504                 MEASUREMENT_INTERVALL.rel_value / 1000 ,
505                 current_quota_p1 / 1024,
506                 current_quota_p2 / 1024);
507   else
508     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
509                 "Starting transport level measurement for %u seconds, symmetric quota %llu kB/s\n", 
510                 MEASUREMENT_INTERVALL.rel_value / 1000,
511                 current_quota_p2 / 1024);
512   
513 #endif
514   GNUNET_TRANSPORT_set_quota (p1.th,
515                               &p2.id,
516                               GNUNET_BANDWIDTH_value_init (current_quota_p1),
517                               GNUNET_BANDWIDTH_value_init (current_quota_p1));
518   GNUNET_TRANSPORT_set_quota (p2.th,
519                               &p1.id,
520                               GNUNET_BANDWIDTH_value_init (current_quota_p2),
521                               GNUNET_BANDWIDTH_value_init (current_quota_p2));
522   GNUNET_SCHEDULER_cancel (die_task);
523   die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
524                                            &end_badly,
525                                            NULL);
526   if (measurement_counter_task != GNUNET_SCHEDULER_NO_TASK)
527     GNUNET_SCHEDULER_cancel (measurement_counter_task);
528   measurement_counter_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
529                                                            &measurement_counter,
530                                                            NULL);
531   measurement_task = GNUNET_SCHEDULER_add_delayed (MEASUREMENT_INTERVALL,
532                                                    &measurement_end,
533                                                    NULL);
534   total_bytes_sent = 0;
535   last_msg_sent = 0;
536   last_msg_recv = 0;
537   measurement_running = GNUNET_YES;
538   start_time = GNUNET_TIME_absolute_get ();
539   
540   if (transmit_handle != NULL)
541     GNUNET_TRANSPORT_notify_transmit_ready_cancel(transmit_handle);
542   transmit_handle = GNUNET_TRANSPORT_notify_transmit_ready (p2.th,
543                                                             &p1.id,
544                                                             get_size (), 0, SEND_TIMEOUT,
545                                                             &notify_ready,
546                                                             NULL);
547 }
548
549
550 static void
551 exchange_hello_last (void *cls,
552                      const struct GNUNET_MessageHeader *message)
553 {
554   struct PeerContext *me = cls;
555
556   GNUNET_assert (message != NULL);
557   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
558               "Exchanging HELLO of size %d with peer (%s)!\n", 
559               (int) GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message),
560               GNUNET_i2s (&me->id));
561   GNUNET_assert (GNUNET_OK ==
562                  GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
563                                       message, &me->id));
564   GNUNET_TRANSPORT_offer_hello (p1.th, message, NULL, NULL);
565 }
566
567
568
569 static void
570 exchange_hello (void *cls,
571                 const struct GNUNET_MessageHeader *message)
572 {
573   struct PeerContext *me = cls;
574
575   GNUNET_assert (message != NULL);
576   GNUNET_assert (GNUNET_OK ==
577                  GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
578                                       message, &me->id));
579   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
580               "Exchanging HELLO of size %d from peer %s!\n", 
581               (int) GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message),
582               GNUNET_i2s (&me->id));
583   GNUNET_TRANSPORT_offer_hello (p2.th, message, NULL, NULL);
584 }
585
586
587 static void
588 notify_connect (void *cls,
589                 const struct GNUNET_PeerIdentity *peer,
590                 const struct GNUNET_TRANSPORT_ATS_Information *ats, 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", 
598                   GNUNET_i2s (peer), 
599                   cls);
600 #endif
601     }
602   else
603     {
604 #if DEBUG_CONNECTIONS
605       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
606                   "Peer 2 `%4s' connected to us (%p)!\n", 
607                   GNUNET_i2s (peer), 
608                   cls);
609 #endif
610     }
611   if (connected == 2)
612     {
613       GNUNET_SCHEDULER_cancel (tct);
614       tct = GNUNET_SCHEDULER_NO_TASK;
615       GNUNET_TRANSPORT_get_hello_cancel (p2.th, &exchange_hello_last, &p2);
616       GNUNET_TRANSPORT_get_hello_cancel (p1.th, &exchange_hello, &p1);
617       if (is_asymmetric_send_constant == GNUNET_YES)
618         measure (MEASUREMENT_MIN_QUOTA, MEASUREMENT_MAX_QUOTA);
619       else if (is_asymmetric_recv_constant == GNUNET_YES)
620         measure (MEASUREMENT_MAX_QUOTA, MEASUREMENT_MIN_QUOTA);
621       else
622         measure (MEASUREMENT_MIN_QUOTA, MEASUREMENT_MIN_QUOTA);
623     }
624 }
625
626
627 static void
628 notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
629 {
630   connected--;
631 #if DEBUG_CONNECTIONS
632   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
633               "Peer `%4s' disconnected (%p)!\n",
634               GNUNET_i2s (peer), cls);
635 #endif
636 }
637
638
639 static void
640 setup_peer (struct PeerContext *p, const char *cfgname)
641 {
642   p->cfg = GNUNET_CONFIGURATION_create ();
643   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
644   if (GNUNET_CONFIGURATION_have_value (p->cfg,"PATHS", "SERVICEHOME"))
645     {
646       GNUNET_CONFIGURATION_get_value_string (p->cfg, "PATHS", "SERVICEHOME", &p->servicehome);
647       GNUNET_DISK_directory_remove (p->servicehome);
648     }
649
650 #if START_ARM
651   p->arm_proc = GNUNET_OS_start_process (NULL, NULL,
652                                         "gnunet-service-arm",
653                                         "gnunet-service-arm",
654 #if VERBOSE_ARM
655                                         "-L", "DEBUG",
656 #endif
657                                         "-c", cfgname, NULL);
658 #endif
659
660   p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL,
661                                     p,
662                                     &notify_receive_new,
663                                     &notify_connect,
664                                     &notify_disconnect);
665   GNUNET_assert (p->th != NULL);
666 }
667
668
669 static void
670 try_connect (void *cls,
671              const struct GNUNET_SCHEDULER_TaskContext *tc)
672 {
673   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
674               "Asking peers to connect...\n");
675   GNUNET_TRANSPORT_try_connect (p2.th,
676                                 &p1.id);
677   GNUNET_TRANSPORT_try_connect (p1.th,
678                                 &p2.id);
679   tct = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
680                                       &try_connect,
681                                       NULL);
682 }
683
684
685 static void
686 run (void *cls,
687      char *const *args,
688      const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
689 {
690   GNUNET_assert (ok == 1);
691   OKPP;
692
693   die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
694                                            &end_badly,
695                                            NULL);
696   measurement_running = GNUNET_NO;
697   send_running = GNUNET_NO;
698   recv_running = GNUNET_NO;
699
700   if (is_tcp)
701     {
702       if (is_asymmetric_recv_constant == GNUNET_YES)
703         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
704                     "Testing asymmetric quota compliance (receiver quota constant) for TCP transport plugin\n");
705       else if (is_asymmetric_send_constant == GNUNET_YES)
706         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
707                     "Testing asymmetric quota compliance (sender quota constant) for TCP transport plugin\n");
708       else
709         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
710                     "Testing symmetric quota compliance for TCP transport plugin\n");
711       setup_peer (&p1, "test_quota_compliance_tcp_peer1.conf");
712       setup_peer (&p2, "test_quota_compliance_tcp_peer2.conf");
713     }
714   else if (is_http)
715     {
716       if (is_asymmetric_recv_constant == GNUNET_YES)
717         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
718                     "Testing asymmetric quota compliance (receiver quota constant) for HTTP transport plugin\n");
719       else if (is_asymmetric_send_constant == GNUNET_YES)
720         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
721                     "Testing asymmetric quota compliance (sender quota constant) for HTTP transport plugin\n");
722       else
723         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
724                     "Testing symmetric quota compliance for HTTP transport plugin\n");
725       setup_peer (&p1, "test_quota_compliance_http_peer1.conf");
726       setup_peer (&p2, "test_quota_compliance_http_peer2.conf");
727     }
728   else if (is_https)
729     {
730       if (is_asymmetric_recv_constant == GNUNET_YES)
731         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
732                     "Testing asymmetric quota compliance (receiver quota constant) for HTTPS transport plugin\n");
733       else if (is_asymmetric_send_constant == GNUNET_YES)
734         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
735                     "Testing asymmetric quota compliance (sender quota constant) for HTTPS transport plugin\n");
736       else
737         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
738                     "Testing symmetric quota compliance for HTTPS transport plugin\n");
739       setup_peer (&p1, "test_quota_compliance_https_peer1.conf");
740       setup_peer (&p2, "test_quota_compliance_https_peer2.conf");
741     }
742   else if (is_udp)
743     {
744       if (is_asymmetric_recv_constant == GNUNET_YES)
745         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
746                     "Testing asymmetric quota compliance (receiver quota constant) for UDP transport plugin\n");
747       else if (is_asymmetric_send_constant == GNUNET_YES)
748         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
749                     "Testing asymmetric quota compliance (sender quota constant) for UDP transport plugin\n");
750       else
751         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
752                     "Testing symmetric quota compliance for UDP transport plugin\n");
753       setup_peer (&p1, "test_quota_compliance_udp_peer1.conf");
754       setup_peer (&p2, "test_quota_compliance_udp_peer2.conf");
755     }
756   else if (is_unix)
757     {
758       if (is_asymmetric_recv_constant == GNUNET_YES)
759         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
760                     "Testing asymmetric quota compliance (receiver quota constant) for UNIX transport plugin\n");
761       else if (is_asymmetric_send_constant == GNUNET_YES)
762         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
763                     "Testing asymmetric quota compliance (sender quota constant) for UNIX transport plugin\n");
764       else
765         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
766                     "Testing symmetric quota compliance for UNIX transport plugin\n");
767       setup_peer (&p1, "test_quota_compliance_unix_peer1.conf");
768       setup_peer (&p2, "test_quota_compliance_unix_peer2.conf");
769     }
770   else if (is_tcp_nat)
771     {
772       if (is_asymmetric_recv_constant == GNUNET_YES)
773         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
774                     "Testing asymmetric quota compliance (receiver quota constant) for TCP NAT transport plugin\n");
775       else if (is_asymmetric_send_constant == GNUNET_YES)
776         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
777                     "Testing asymmetric quota compliance (sender quota constant) for TCP NAT transport plugin\n");
778       else
779         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
780                     "Testing symmetric quota compliance for TCP NAT transport plugin\n");
781       setup_peer (&p1, "test_quota_compliance_tcp_peer1.conf");
782       setup_peer (&p2, "test_quota_compliance_tcp_peer2.conf");
783     }
784   else
785     GNUNET_assert (0);
786
787   GNUNET_assert(p1.th != NULL);
788   GNUNET_assert(p2.th != NULL);
789   GNUNET_TRANSPORT_get_hello (p1.th, &exchange_hello, &p1);
790   GNUNET_TRANSPORT_get_hello (p2.th, &exchange_hello_last, &p2);
791   tct = GNUNET_SCHEDULER_add_now (&try_connect, NULL);
792 }
793
794
795 int
796 main (int argc, char *argv[])
797 {
798   int ret = 0;
799   if (strstr(argv[0], "tcp_nat") != NULL)
800     {
801       is_tcp_nat = GNUNET_YES;
802 #ifdef MINGW
803       return 0;
804 #endif
805     }
806   else if (strstr(argv[0], "tcp") != NULL)
807     {
808       is_tcp = GNUNET_YES;
809     }
810   else if (strstr(argv[0], "https") != NULL)
811     {
812       is_https = GNUNET_YES;
813 #ifdef MINGW
814       return 0;
815 #endif
816     }
817   else if (strstr(argv[0], "http") != NULL)
818     {
819       is_http = GNUNET_YES;
820     }
821   else if (strstr(argv[0], "udp") != NULL)
822     {
823       is_udp = GNUNET_YES;
824     }
825   else if (strstr(argv[0], "unix") != NULL)
826     {
827       is_unix = GNUNET_YES;
828     }
829
830   if (strstr(argv[0], "asymmetric_recv") != NULL)
831   {
832     is_asymmetric_recv_constant = GNUNET_YES;
833   }
834   else
835     is_asymmetric_recv_constant = GNUNET_NO;
836   if (strstr(argv[0], "asymmetric_send") != NULL)
837     {
838       is_asymmetric_send_constant = GNUNET_YES;
839     }
840   else
841     is_asymmetric_send_constant = GNUNET_NO;
842   
843   char * logger;
844   if (is_tcp == GNUNET_YES)
845     {
846       if (is_asymmetric_recv_constant == GNUNET_YES)
847         GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","tcp","asymmetric_recv_constant");
848       else if (is_asymmetric_send_constant == GNUNET_YES)
849         GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","tcp","asymmetric_send_constant");
850       else
851         GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","tcp","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","asymmetric_recv_constant");
857       else if (is_asymmetric_send_constant == GNUNET_YES)
858         GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","udp","asymmetric_send_constant");
859       else
860         GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","udp","symmetric");
861     }
862   else if (is_unix == GNUNET_YES)
863     {
864       if (is_asymmetric_recv_constant == GNUNET_YES)
865         GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","unix","asymmetric_recv_constant");
866       else if (is_asymmetric_send_constant == GNUNET_YES)
867         GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","unix","asymmetric_send_constant");
868       else
869         GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","unix","symmetric");
870     }
871   else if (is_http == GNUNET_YES)
872     {
873       if (is_asymmetric_recv_constant == GNUNET_YES)
874         GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","http","asymmetric_recv_constant");
875       else if (is_asymmetric_send_constant == GNUNET_YES)
876         GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","http","asymmetric_send_constant");
877       else
878         GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","http","symmetric");
879     }
880   else if (is_https == GNUNET_YES)
881     {
882       if (is_asymmetric_recv_constant == GNUNET_YES)
883         GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","https","asymmetric_recv_constant");
884       else if (is_asymmetric_send_constant == GNUNET_YES)
885         GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","https","asymmetric_send_constant");
886       else
887         GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","https","symmetric");
888     }
889   else
890     {
891       GNUNET_asprintf(&logger, "test-quota-compliance-%s-%s","noplugin","none");
892     }
893
894   fprintf(stderr,  "Running `%s'\n", logger);
895   GNUNET_log_setup ("test-quota-compliance",
896 #if VERBOSE
897                     "DEBUG",
898 #else
899                     "WARNING",
900 #endif
901                     NULL);
902   char *const argv1[] = { "test-quota-compliance",
903     "-c",
904     "test_quota_compliance_data.conf",
905 #if VERBOSE
906     "-L", "DEBUG",
907 #endif
908     NULL
909   };
910   struct GNUNET_GETOPT_CommandLineOption options[] = {
911     GNUNET_GETOPT_OPTION_END
912   };
913   ok = 1;
914   GNUNET_PROGRAM_run ((sizeof (argv1) / sizeof (char *)) - 1,
915                       argv1, logger , "nohelp",
916                       options, &run, &ok);
917   ret = ok;
918   stop_arm (&p1);
919   stop_arm (&p2);
920
921   if (p1.servicehome != NULL)
922     {
923       GNUNET_DISK_directory_remove (p1.servicehome);
924       GNUNET_free(p1.servicehome);
925     }
926   if (p2.servicehome != NULL)
927     {
928       GNUNET_DISK_directory_remove (p2.servicehome);
929       GNUNET_free(p2.servicehome);
930     }
931   GNUNET_free(logger);
932   return ret;
933 }
934
935 /* end of test_quota_compliance.c */