-code cleanup
[oweals/gnunet.git] / src / testbed / gnunet-testbed-helper.c
1 /*
2       This file is part of GNUnet
3       (C) 2012 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 testbed/gnunet-testbed-helper.c
23  * @brief Helper binary that is started from a remote controller to start
24  *          gnunet-service-testbed. This binary also receives configuration
25  *          from the remove controller which is put in a temporary location
26  *          with ports and paths fixed so that gnunet-service-testbed runs
27  *          without any hurdels. This binary also kills the testbed service
28  *          should the connection from the remote controller is dropped
29  * @author Sree Harsha Totakura <sreeharsha@totakura.in> 
30  */
31 #include "platform.h"
32 #include "gnunet_util_lib.h"
33 #include "gnunet_testing_lib-new.h"
34 #include "testbed_helper.h"
35
36
37 /**
38  * Generic debug logging shortcut
39  */
40 #define LOG_DEBUG(...)                                  \
41   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
42
43
44 /**
45  * Handle to the testing system
46  */
47 static struct GNUNET_TESTING_System *test_system;
48
49 /**
50  * Our message stream tokenizer
51  */
52 struct GNUNET_SERVER_MessageStreamTokenizer *tokenizer;
53
54 /**
55  * Disk handle from stdin
56  */
57 static struct GNUNET_DISK_FileHandle *stdin_fd;
58
59 /**
60  * Task identifier for the read task
61  */
62 static GNUNET_SCHEDULER_TaskIdentifier read_task_id;
63
64 /**
65  * Are we done reading messages from stdin?
66  */
67 static int done_reading;
68
69
70 /**
71  * Task to shutting down nicely
72  *
73  * @param cls NULL
74  * @return tc the task context
75  */
76 static void
77 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
78 {
79   if (GNUNET_SCHEDULER_NO_TASK != read_task_id)
80   {
81     GNUNET_SCHEDULER_cancel (read_task_id);
82     read_task_id = GNUNET_SCHEDULER_NO_TASK;
83   }
84   (void) GNUNET_DISK_file_close (stdin_fd);
85   GNUNET_SERVER_mst_destroy (tokenizer);  
86   tokenizer = NULL;
87   if (NULL != test_system)
88   {
89     GNUNET_TESTING_system_destroy (test_system, GNUNET_YES);
90     test_system = NULL;
91   }
92 }
93
94
95 /**
96  * Functions with this signature are called whenever a
97  * complete message is received by the tokenizer.
98  *
99  * Do not call GNUNET_SERVER_mst_destroy in callback
100  *
101  * @param cls closure
102  * @param client identification of the client
103  * @param message the actual message
104  *
105  * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing
106  */
107 static int 
108 tokenizer_cb (void *cls, void *client,
109               const struct GNUNET_MessageHeader *message)
110 {
111   GNUNET_break (0);
112   // FIXME: write config & start gnunet-service-testbed
113   done_reading = GNUNET_YES;
114   return GNUNET_OK;
115 }
116
117
118 /**
119  * Task to read from stdin
120  *
121  * @param cls NULL
122  * @return tc the task context
123  */
124 static void
125 read_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
126 {
127   char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE];
128   ssize_t sread;
129
130   read_task_id = GNUNET_SCHEDULER_NO_TASK;
131   if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
132     return;  
133   sread = GNUNET_DISK_file_read (stdin_fd, buf, sizeof (buf));
134   if (GNUNET_SYSERR == sread)
135   {
136     GNUNET_break (0);           /* FIXME: stdin closed - kill child */
137     GNUNET_SCHEDULER_shutdown ();
138     return;
139   }
140   if (GNUNET_YES == done_reading)
141   {
142     /* didn't expect any more data! */
143     GNUNET_break (0);
144     GNUNET_SCHEDULER_shutdown ();
145     return;
146   }
147   LOG_DEBUG ("Read %u bytes\n", sread);
148   if (GNUNET_OK !=
149       GNUNET_SERVER_mst_receive (tokenizer, NULL, buf, sread,
150                                  GNUNET_NO, GNUNET_NO))
151   {
152     GNUNET_break (0);
153     GNUNET_SCHEDULER_shutdown ();
154     return;
155   }
156   read_task_id =                /* No timeout while reading */
157     GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
158                                     stdin_fd, &read_task, NULL);
159 }
160
161
162 /**
163  * Main function that will be run.
164  *
165  * @param cls closure
166  * @param args remaining command-line arguments
167  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
168  * @param cfg configuration
169  */
170 static void 
171 run (void *cls, char *const *args, const char *cfgfile,
172      const struct GNUNET_CONFIGURATION_Handle * cfg)
173 {
174   LOG_DEBUG ("Starting testbed helper...\n");
175   tokenizer = GNUNET_SERVER_mst_create (&tokenizer_cb, NULL);
176   stdin_fd = GNUNET_DISK_get_handle_from_native (stdin);
177   read_task_id =
178     GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
179                                     stdin_fd, &read_task, NULL);
180   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
181                                 &shutdown_task, NULL);
182 }
183
184
185 /**
186  * Main function
187  *
188  * @param argc the number of command line arguments
189  * @param argv command line arg array
190  * @return return code
191  */
192 int main (int argc, char **argv)
193 {
194   struct GNUNET_GETOPT_CommandLineOption options[] = {
195     GNUNET_GETOPT_OPTION_END
196   };
197   if (GNUNET_OK != 
198       GNUNET_PROGRAM_run (argc, argv, "gnunet-testbed-helper",
199                           "Helper for starting gnunet-service-testbed",
200                           options, &run, NULL))
201     return 1;
202   return 0;
203 }
204
205 /* end of gnunet-testbed-helper.c */