LRN: Use GNUNET_EXTRA_LOGGING to manage compile-time logging calls
[oweals/gnunet.git] / src / transport / gnunet-transport-connect-running-peers.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/gnunet-transport-connect-running-peers.c
22  * @brief utility to connect running peers
23  *
24  * This utility connects to running peers with each other
25  * The peers have to be started before, for example in the debugger with
26  * breakpoints set
27  */
28 #include "platform.h"
29 #include "gnunet_common.h"
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_getopt_lib.h"
32 #include "gnunet_os_lib.h"
33 #include "gnunet_program_lib.h"
34 #include "gnunet_scheduler_lib.h"
35 #include "gnunet_transport_service.h"
36 #include "transport.h"
37 #include "transport-testing.h"
38
39 #define VERBOSE GNUNET_EXTRA_LOGGING
40
41 #define VERBOSE_ARM GNUNET_EXTRA_LOGGING
42
43 #define START_ARM GNUNET_YES
44
45 /**
46  * How long until we give up on transmitting the message?
47  */
48 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
49
50 /**
51  * How long until we give up on transmitting the message?
52  */
53 #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
54
55 #define MTYPE 12345
56
57 static int ok;
58
59 static GNUNET_SCHEDULER_TaskIdentifier die_task;
60
61 static GNUNET_SCHEDULER_TaskIdentifier send_task;
62
63 struct PeerContext *p1;
64
65 struct PeerContext *p2;
66
67 static GNUNET_TRANSPORT_TESTING_ConnectRequest cc;
68
69 struct GNUNET_TRANSPORT_TransmitHandle *th;
70
71 char *cfg_file_p1;
72
73 char *cfg_file_p2;
74
75 #if VERBOSE
76 #define OKPP do { ok++; fprintf (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
77 #else
78 #define OKPP do { ok++; } while (0)
79 #endif
80
81 void
82 disconnect_from_peer (struct PeerContext *p)
83 {
84   GNUNET_assert (p != NULL);
85   if (p->th != NULL)
86     GNUNET_TRANSPORT_disconnect (p->th);
87
88   if (p->cfg != NULL)
89     GNUNET_CONFIGURATION_destroy (p->cfg);
90   GNUNET_free (p);
91   p = NULL;
92 }
93
94 static void
95 end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
96 {
97   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n");
98
99   if (send_task != GNUNET_SCHEDULER_NO_TASK)
100     GNUNET_SCHEDULER_cancel (send_task);
101
102   if (die_task != GNUNET_SCHEDULER_NO_TASK)
103     GNUNET_SCHEDULER_cancel (die_task);
104
105   if (th != NULL)
106     GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
107   th = NULL;
108
109   if (p1 != NULL)
110     disconnect_from_peer (p1);
111   if (p2 != NULL)
112     disconnect_from_peer (p2);
113 }
114
115 static void
116 end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
117 {
118   die_task = GNUNET_SCHEDULER_NO_TASK;
119
120   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n");
121
122   if (send_task != GNUNET_SCHEDULER_NO_TASK)
123     GNUNET_SCHEDULER_cancel (send_task);
124
125   if (cc != NULL)
126     GNUNET_TRANSPORT_TESTING_connect_peers_cancel (cc);
127
128   if (th != NULL)
129     GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
130   th = NULL;
131
132   if (p1 != NULL)
133     disconnect_from_peer (p1);
134   if (p2 != NULL)
135     disconnect_from_peer (p2);
136
137   ok = GNUNET_SYSERR;
138 }
139
140
141 static size_t
142 notify_ready (void *cls, size_t size, void *buf)
143 {
144   struct PeerContext *p = cls;
145   struct GNUNET_MessageHeader *hdr;
146
147   th = NULL;
148
149   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
150               "Transmitting message with %u bytes to peer %s\n",
151               sizeof (struct GNUNET_MessageHeader), GNUNET_i2s (&p->id));
152   GNUNET_assert (size >= 256);
153
154   if (buf != NULL)
155   {
156     hdr = buf;
157     hdr->size = htons (sizeof (struct GNUNET_MessageHeader));
158     hdr->type = htons (MTYPE);
159   }
160
161   return sizeof (struct GNUNET_MessageHeader);
162 }
163
164 static void
165 sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
166 {
167   send_task = GNUNET_SCHEDULER_NO_TASK;
168   static char t;
169
170   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
171     return;
172
173   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
174               "Press <q> to quit or <1> to send from p1 to p2, <2> to send from p2 to p1, <enter> repeat\n");
175
176 read:
177   t = getchar();
178   if (t == '1')
179   {
180     th = GNUNET_TRANSPORT_notify_transmit_ready (p1->th, &p2->id, 256, 0, TIMEOUT,
181                                                  &notify_ready, p1);
182     return;
183   }
184   if (t == '2')
185   {
186     th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, 256, 0, TIMEOUT,
187                                                  &notify_ready, p2);
188     return;
189   }
190   if (t == 'q')
191   {
192     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
193                 "Exiting %c!\n", t);
194     GNUNET_SCHEDULER_add_now(&end, NULL);
195     return;
196   }
197   goto read;
198 }
199
200 static void
201 notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
202                 const struct GNUNET_MessageHeader *message,
203                 const struct GNUNET_TRANSPORT_ATS_Information *ats,
204                 uint32_t ats_count)
205 {
206   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
207               "Received message of type %d from peer %s!\n",
208               ntohs (message->type), GNUNET_i2s (peer));
209
210   if ((MTYPE == ntohs (message->type)) &&
211       (sizeof (struct GNUNET_MessageHeader) == ntohs (message->size)))
212   {
213     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
214                 "Successfully received message\n");
215
216     send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL);
217   }
218 }
219
220 static void
221 notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
222                 const struct GNUNET_TRANSPORT_ATS_Information *ats,
223                 uint32_t ats_count)
224 {
225   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%4s' connected to us (%p)!\n",
226               GNUNET_i2s (peer), cls);
227 }
228
229
230 static void
231 notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
232 {
233   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%4s' disconnected (%p)!\n",
234               GNUNET_i2s (peer), cls);
235 }
236
237
238
239
240 struct PeerContext *
241 connect_to_peer (const char *cfgname, GNUNET_TRANSPORT_ReceiveCallback rec,
242                  GNUNET_TRANSPORT_NotifyConnect nc,
243                  GNUNET_TRANSPORT_NotifyDisconnect nd, void *cb_cls)
244 {
245   if (GNUNET_DISK_file_test (cfgname) == GNUNET_NO)
246   {
247     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "File not found: `%s' \n", cfgname);
248     return NULL;
249   }
250
251   struct PeerContext *p = GNUNET_malloc (sizeof (struct PeerContext));
252
253   p->cfg = GNUNET_CONFIGURATION_create ();
254
255   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
256   if (GNUNET_CONFIGURATION_have_value (p->cfg, "PATHS", "SERVICEHOME"))
257     GNUNET_CONFIGURATION_get_value_string (p->cfg, "PATHS", "SERVICEHOME",
258                                            &p->servicehome);
259   if (NULL != p->servicehome)
260     GNUNET_DISK_directory_remove (p->servicehome);
261   /*
262    * p->arm_proc =
263    * GNUNET_OS_start_process (NULL, NULL, "gnunet-service-arm",
264    * "gnunet-service-arm", "-c", cfgname,
265    * #if VERBOSE_PEERS
266    * "-L", "DEBUG",
267    * #else
268    * "-L", "ERROR",
269    * #endif
270    * NULL);
271    */
272   p->nc = nc;
273   p->nd = nd;
274   p->rec = rec;
275   if (cb_cls != NULL)
276     p->cb_cls = cb_cls;
277   else
278     p->cb_cls = p;
279
280   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to transport service `%s'\n",
281               p->servicehome);
282   p->th =
283       GNUNET_TRANSPORT_connect (p->cfg, NULL, p, &notify_receive,
284                                 &notify_connect, &notify_disconnect);
285   GNUNET_assert (p->th != NULL);
286   return p;
287 }
288
289 static void
290 testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls)
291 {
292   cc = NULL;
293   char *p1_c = strdup (GNUNET_i2s (&p1->id));
294
295   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers connected: %s <-> %s\n", p1_c,
296               GNUNET_i2s (&p2->id));
297   GNUNET_free (p1_c);
298
299   // FIXME: THIS IS REQUIRED! SEEMS TO BE A BUG!
300
301   send_task =
302       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &sendtask, NULL);
303 }
304
305 static void
306 run (void *cls, char *const *args, const char *cfgfile,
307      const struct GNUNET_CONFIGURATION_Handle *cfg)
308 {
309   die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
310
311   p1 = connect_to_peer (cfg_file_p1, &notify_receive, &notify_connect,
312                         &notify_disconnect, NULL);
313   p2 = connect_to_peer (cfg_file_p2, &notify_receive, &notify_connect,
314                         &notify_disconnect, NULL);
315
316   if ((p1 == NULL) || (p2 == NULL))
317   {
318     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n");
319     if (die_task != GNUNET_SCHEDULER_NO_TASK)
320       GNUNET_SCHEDULER_cancel (die_task);
321     die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
322     return;
323   }
324
325   cc = GNUNET_TRANSPORT_TESTING_connect_peers (p1, p2, &testing_connect_cb,
326                                                NULL);
327 }
328
329
330 static int
331 check ()
332 {
333   static char *const argv[] = { "test-transport-api",
334     "-c",
335     "test_transport_api_data.conf",
336 #if VERBOSE
337     "-L", "DEBUG",
338 #endif
339     NULL
340   };
341   static struct GNUNET_GETOPT_CommandLineOption options[] = {
342     GNUNET_GETOPT_OPTION_END
343   };
344
345 #if WRITECONFIG
346   setTransportOptions ("test_transport_api_data.conf");
347 #endif
348   send_task = GNUNET_SCHEDULER_NO_TASK;
349
350   ok = 1;
351   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
352                       "util_connect_running_peers", "nohelp", options, &run,
353                       &ok);
354
355   return ok;
356 }
357
358 int
359 main (int argc, char *argv[])
360 {
361   int ret;
362
363   GNUNET_log_setup ("gnunet-transport-connect-running-peers",
364 #if VERBOSE
365                     "DEBUG",
366 #else
367                     "WARNING",
368 #endif
369                     NULL);
370
371
372   if (argc < 3)
373   {
374     fprintf (stderr,
375              "usage gnunet-transport-connect-running-peers <cfg_peer1> <cfg_peer2>\n");
376     return -1;
377   }
378   else
379   {
380     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configuration file 1: `%s' \n",
381                 argv[1]);
382     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Configuration file 2: `%s'\n",
383                 argv[2]);
384   }
385
386   if (GNUNET_DISK_file_test (argv[1]) == GNUNET_NO)
387   {
388     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "File not found: `%s' \n", argv[1]);
389     return -1;
390   }
391   if (GNUNET_DISK_file_test (argv[2]) == GNUNET_NO)
392   {
393     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "File not found: `%s' \n", argv[2]);
394     return -1;
395   }
396
397   GNUNET_asprintf (&cfg_file_p1, argv[1]);
398   GNUNET_asprintf (&cfg_file_p2, argv[2]);
399
400   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
401               "Trying to connect peers, press control-d to stop... \n",
402               argv[1]);
403
404   ret = check ();
405
406   GNUNET_free (cfg_file_p1);
407   GNUNET_free (cfg_file_p2);
408   return ret;
409 }
410
411 /* end of gnunet-transport-connect-running-peers.c */