fixing and testing blacklisting api and service
[oweals/gnunet.git] / src / transport / test_transport_api_blacklisting.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 /**
22  * @file transport/transport_api_blacklisting.c
23  * @brief test for the blacklisting API
24  * @author Matthias Wachs
25  *
26  */
27 #include "platform.h"
28 #include "gnunet_common.h"
29 #include "gnunet_hello_lib.h"
30 #include "gnunet_getopt_lib.h"
31 #include "gnunet_os_lib.h"
32 #include "gnunet_program_lib.h"
33 #include "gnunet_scheduler_lib.h"
34 #include "gnunet_transport_service.h"
35 #include "transport.h"
36 #include "transport-testing.h"
37
38 #define VERBOSE GNUNET_EXTRA_LOGGING
39 #define VERBOSE_ARM GNUNET_EXTRA_LOGGING
40
41 #define START_ARM GNUNET_YES
42
43
44 struct PeerContext *p1;
45
46 struct PeerContext *p2;
47
48 static GNUNET_TRANSPORT_TESTING_ConnectRequest cc;
49
50 struct GNUNET_TRANSPORT_TransmitHandle *th;
51
52 struct GNUNET_TRANSPORT_TESTING_handle *tth;
53
54 /**
55  * How long until we give up on transmitting the message?
56  */
57 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
58
59 /**
60  * How long until we give up on transmitting the message?
61  */
62 #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
63
64 #define MSIZE 2600
65
66 #define MTYPE 12345
67
68
69 static int ok;
70 static int connected;
71 static int blacklist_request_p1;
72 static int blacklist_request_p2;
73
74 struct GNUNET_TRANSPORT_Blacklist * blacklist_p1;
75
76 struct GNUNET_TRANSPORT_Blacklist * blacklist_p2;
77
78 static GNUNET_SCHEDULER_TaskIdentifier die_task;
79
80 static GNUNET_SCHEDULER_TaskIdentifier send_task;
81
82 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
83
84 #if VERBOSE
85 #define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
86 #else
87 #define OKPP do { ok++; } while (0)
88 #endif
89
90
91 static void
92 end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
93 {
94   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping\n");
95
96   if (send_task != GNUNET_SCHEDULER_NO_TASK)
97     GNUNET_SCHEDULER_cancel (send_task);
98
99   if (die_task != GNUNET_SCHEDULER_NO_TASK)
100   {
101     GNUNET_SCHEDULER_cancel (die_task);
102     die_task = GNUNET_SCHEDULER_NO_TASK;
103   }
104
105   if (cc != NULL)
106   {
107     GNUNET_TRANSPORT_TESTING_connect_peers_cancel(tth, cc);
108     cc = NULL;
109   }
110
111   if (th != NULL)
112     GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
113   th = NULL;
114
115   if (blacklist_p1 != NULL)
116   {
117     GNUNET_TRANSPORT_blacklist_cancel (blacklist_p1);
118     blacklist_p1 = NULL;
119   }
120
121   if (blacklist_p2 != NULL)
122   {
123     GNUNET_TRANSPORT_blacklist_cancel (blacklist_p2);
124     blacklist_p2 = NULL;
125   }
126
127   if (p1 != NULL)
128   {
129     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1);
130     p1 = NULL;
131   }
132   if (p2 != NULL)
133   {
134     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2);
135     p2 = NULL;
136   }
137
138   if ((blacklist_request_p1 == GNUNET_YES) &&
139       (blacklist_request_p2 == GNUNET_YES) &&
140       (connected == GNUNET_NO))
141   {
142     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Peers were not connected, success\n"));
143     ok = 0;
144   }
145   else
146   {
147     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Peers were not connected, fail\n"));
148     ok = 1;
149   }
150 }
151
152 static void
153 end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
154 {
155   if (send_task != GNUNET_SCHEDULER_NO_TASK)
156   {
157     GNUNET_SCHEDULER_cancel (send_task);
158     send_task = GNUNET_SCHEDULER_NO_TASK;
159   }
160
161   if (shutdown_task != GNUNET_SCHEDULER_NO_TASK)
162   {
163     GNUNET_SCHEDULER_cancel (shutdown_task);
164     shutdown_task = GNUNET_SCHEDULER_NO_TASK;
165   }
166
167   if (cc != NULL)
168   {
169     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fail! Could not connect peers\n"));
170     GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc);
171     cc = NULL;
172   }
173
174   if (th != NULL)
175     GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
176   th = NULL;
177
178   if (blacklist_p1 != NULL)
179     GNUNET_TRANSPORT_blacklist_cancel (blacklist_p1);
180
181   if (blacklist_p2 != NULL)
182     GNUNET_TRANSPORT_blacklist_cancel (blacklist_p2);
183
184   if (p1 != NULL)
185     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1);
186   if (p2 != NULL)
187     GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2);
188
189   ok = GNUNET_SYSERR;
190 }
191
192
193 static void
194 notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
195                 const struct GNUNET_MessageHeader *message,
196                 const struct GNUNET_ATS_Information *ats, uint32_t ats_count)
197 {
198   struct PeerContext *p = cls;
199   struct PeerContext *t = NULL;
200
201   if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity)))
202     t = p1;
203   if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity)))
204     t = p2;
205   GNUNET_assert (t != NULL);
206
207   char *ps = GNUNET_strdup (GNUNET_i2s (&p->id));
208
209   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
210               "Peer %u (`%4s') received message of type %d and size %u size from peer %u (`%4s')!\n",
211               p->no, ps, ntohs (message->type), ntohs (message->size), t->no,
212               GNUNET_i2s (&t->id));
213   GNUNET_free (ps);
214
215   if ((MTYPE == ntohs (message->type)) &&
216       (MSIZE == ntohs (message->size)))
217   {
218     ok = 0;
219     shutdown_task = GNUNET_SCHEDULER_add_now(&end, NULL);
220   }
221   else
222   {
223     GNUNET_break (0);
224     ok = 1;
225     shutdown_task = GNUNET_SCHEDULER_add_now(&end, NULL);
226   }
227 }
228
229
230 static size_t
231 notify_ready (void *cls, size_t size, void *buf)
232 {
233   struct PeerContext *p = cls;
234   struct GNUNET_MessageHeader *hdr;
235
236   th = NULL;
237
238   if (buf == NULL)
239   {
240     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
241                 "Timeout occurred while waiting for transmit_ready\n");
242     if (GNUNET_SCHEDULER_NO_TASK != die_task)
243     {
244       GNUNET_SCHEDULER_cancel (die_task);
245       die_task = GNUNET_SCHEDULER_NO_TASK;
246     }
247     die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
248     ok = 42;
249     return 0;
250   }
251
252   GNUNET_assert (size >= MSIZE);
253
254   if (buf != NULL)
255   {
256     hdr = buf;
257     hdr->size = htons (MSIZE);
258     hdr->type = htons (MTYPE);
259   }
260
261   char *ps = GNUNET_strdup (GNUNET_i2s (&p2->id));
262   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
263               "Peer %u (`%4s') sending message with type %u and size %u bytes to peer %u (`%4s')\n",
264               p2->no, ps, ntohs (hdr->type), ntohs (hdr->size), p->no,
265               GNUNET_i2s (&p->id));
266   GNUNET_free (ps);
267
268   return MSIZE;
269 }
270
271 static void
272 sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
273 {
274   send_task = GNUNET_SCHEDULER_NO_TASK;
275
276   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
277     return;
278   char *receiver_s = GNUNET_strdup (GNUNET_i2s (&p1->id));
279
280   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
281               "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n",
282               p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s);
283   GNUNET_free (receiver_s);
284
285   th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, MSIZE, 0,
286                                                TIMEOUT_TRANSMIT, &notify_ready,
287                                                p1);
288 }
289
290 static void
291 notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
292                 const struct GNUNET_ATS_Information *ats, uint32_t ats_count)
293 {
294   static int c;
295
296   c++;
297   struct PeerContext *p = cls;
298   struct PeerContext *t = NULL;
299
300   if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity)))
301     t = p1;
302   if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity)))
303     t = p2;
304   GNUNET_assert (t != NULL);
305
306   char *ps = GNUNET_strdup (GNUNET_i2s (&p->id));
307
308   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
309               "Peer %u (`%4s'): peer %u (`%s') connected to me!\n", p->no, ps,
310               t->no, GNUNET_i2s (peer));
311   GNUNET_free (ps);
312 }
313
314
315 static void
316 notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
317 {
318   struct PeerContext *p = cls;
319   char *ps = GNUNET_strdup (GNUNET_i2s (&p->id));
320
321   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
322               "Peer %u (`%4s'): peer (`%s') disconnected from me!\n", p->no, ps,
323               GNUNET_i2s (peer));
324
325   GNUNET_free (ps);
326
327   if (th != NULL)
328     GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
329   th = NULL;
330 }
331
332 static void
333 testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls)
334 {
335   cc = NULL;
336   char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id));
337
338   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %u (%s) <-> %u (%s)\n",
339               p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id));
340   GNUNET_free (p1_c);
341
342
343
344   send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL);
345 }
346
347
348 int blacklist_cb (void *cls,
349                  const struct
350                  GNUNET_PeerIdentity * pid)
351 {
352   struct PeerContext * p = cls;
353   int res = GNUNET_SYSERR;
354   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer  %u : Blacklist request for peer `%s'\n", p->no, GNUNET_i2s (pid));
355
356   if (p == p1)
357   {
358     blacklist_request_p1 = GNUNET_YES;
359     res = GNUNET_OK;
360   }
361   else if (p == p2)
362   {
363     blacklist_request_p2 = GNUNET_YES;
364     res = GNUNET_SYSERR;
365   }
366
367   if (((blacklist_request_p2 == GNUNET_YES) && (blacklist_request_p1 == GNUNET_YES)) && (shutdown_task == GNUNET_SCHEDULER_NO_TASK))
368   {
369     shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3), &end, NULL);
370   }
371
372   return res;
373 }
374
375 void
376 start_cb (struct PeerContext *p, void *cls)
377 {
378   static int started;
379
380   started++;
381
382   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no,
383               GNUNET_i2s (&p->id));
384
385   if (started != 2)
386     return;
387
388   char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id));
389
390   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
391               "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n",
392               p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id));
393   GNUNET_free (sender_c);
394
395   cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb,
396                                                NULL);
397
398 }
399
400 static void
401 run (void *cls, char *const *args, const char *cfgfile,
402      const struct GNUNET_CONFIGURATION_Handle *cfg)
403 {
404   die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
405   connected = GNUNET_NO;
406   blacklist_request_p1 = GNUNET_NO;
407   blacklist_request_p2 = GNUNET_NO;
408
409   p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_api_tcp_peer1.conf", 1,
410                                             &notify_receive, &notify_connect,
411                                             &notify_disconnect, &start_cb,
412                                             NULL);
413
414   p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_api_tcp_peer2.conf", 2,
415                                             &notify_receive, &notify_connect,
416                                             &notify_disconnect, &start_cb,
417                                             NULL);
418
419   blacklist_p1 = GNUNET_TRANSPORT_blacklist (p1->cfg,
420                               &blacklist_cb,
421                               p1);
422
423   blacklist_p2 = GNUNET_TRANSPORT_blacklist (p2->cfg,
424                               &blacklist_cb,
425                               p2);
426
427   GNUNET_assert (blacklist_p1 != NULL);
428   GNUNET_assert (blacklist_p2 != NULL);
429 }
430
431
432 static int
433 check ()
434 {
435   static char *const argv[] = { "test-transport-api-blacklisting",
436     "-c",
437     "test_transport_api_data.conf",
438 #if VERBOSE
439     "-L", "DEBUG",
440 #endif
441     NULL
442   };
443   static struct GNUNET_GETOPT_CommandLineOption options[] = {
444     GNUNET_GETOPT_OPTION_END
445   };
446
447 #if WRITECONFIG
448   setTransportOptions ("test_transport_api_data.conf");
449 #endif
450
451   ok = 1;
452   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-transport-api-blacklisting",
453                       "nohelp", options, &run, &ok);
454
455   return ok;
456 }
457
458 int
459 main (int argc, char *argv[])
460 {
461   int ret;
462
463   GNUNET_log_setup ("test-transport-api-blacklisting",
464 #if VERBOSE
465                     "DEBUG",
466 #else
467                     "WARNING",
468 #endif
469                     NULL);
470
471   tth = GNUNET_TRANSPORT_TESTING_init ();
472
473   ret = check ();
474
475   GNUNET_TRANSPORT_TESTING_done (tth);
476
477   return ret;
478 }
479
480 /* end of transport_api_blacklisting.c */