aboutsummaryrefslogtreecommitdiff
path: root/src/arm
diff options
context:
space:
mode:
Diffstat (limited to 'src/arm')
-rw-r--r--src/arm/Makefile.am58
-rw-r--r--src/arm/arm.h32
-rw-r--r--src/arm/arm_api.c337
-rw-r--r--src/arm/gnunet-arm.c180
-rw-r--r--src/arm/gnunet-service-arm.c712
-rw-r--r--src/arm/test_arm_api.c140
-rw-r--r--src/arm/test_arm_api_data.conf7
-rwxr-xr-xsrc/arm/test_gnunet_arm.sh117
8 files changed, 1583 insertions, 0 deletions
diff --git a/src/arm/Makefile.am b/src/arm/Makefile.am
new file mode 100644
index 000000000..65fa145ee
--- /dev/null
+++ b/src/arm/Makefile.am
@@ -0,0 +1,58 @@
1INCLUDES = -I$(top_srcdir)/src/include
2
3if MINGW
4 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
5endif
6
7if USE_COVERAGE
8 AM_CFLAGS = -fprofile-arcs -ftest-coverage
9endif
10
11lib_LTLIBRARIES = libgnunetarm.la
12
13libgnunetarm_la_SOURCES = \
14 arm_api.c arm.h
15libgnunetarm_la_LIBADD = \
16 $(top_builddir)/src/util/libgnunetutil.la \
17 $(GN_LIBINTL)
18libgnunetarm_la_LDFLAGS = \
19 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
20 -version-info 0:0:0
21
22
23bin_PROGRAMS = \
24 gnunet-arm \
25 gnunet-service-arm
26
27gnunet_arm_SOURCES = \
28 gnunet-arm.c
29gnunet_arm_LDADD = \
30 $(top_builddir)/src/arm/libgnunetarm.la \
31 $(top_builddir)/src/util/libgnunetutil.la \
32 $(GN_LIBINTL)
33
34gnunet_service_arm_SOURCES = \
35 gnunet-service-arm.c
36gnunet_service_arm_LDADD = \
37 $(top_builddir)/src/util/libgnunetutil.la \
38 $(GN_LIBINTL)
39
40
41check_PROGRAMS = \
42 test_arm_api
43
44check_SCRIPTS = \
45 test_gnunet_arm.sh
46
47TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
48
49test_arm_api_SOURCES = \
50 test_arm_api.c
51test_arm_api_LDADD = \
52 $(top_builddir)/src/arm/libgnunetarm.la \
53 $(top_builddir)/src/resolver/libgnunetresolver.la \
54 $(top_builddir)/src/util/libgnunetutil.la
55
56
57EXTRA_DIST = \
58 test_arm_api_data.conf
diff --git a/src/arm/arm.h b/src/arm/arm.h
new file mode 100644
index 000000000..2293ec036
--- /dev/null
+++ b/src/arm/arm.h
@@ -0,0 +1,32 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 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 2, 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 * @author Christian Grothoff
23 * @file arm/arm.h
24 */
25#ifndef ARM_H
26#define ARM_H
27
28#include "gnunet_common.h"
29
30#define DEBUG_ARM GNUNET_NO
31
32#endif
diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c
new file mode 100644
index 000000000..c5bb15fd3
--- /dev/null
+++ b/src/arm/arm_api.c
@@ -0,0 +1,337 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 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 2, 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 arm/arm_api.c
23 * @brief API for accessing the ARM service
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_arm_service.h"
28#include "gnunet_client_lib.h"
29#include "gnunet_getopt_lib.h"
30#include "gnunet_os_lib.h"
31#include "gnunet_protocols.h"
32#include "gnunet_server_lib.h"
33#include "arm.h"
34
35
36struct ArmContext
37{
38 GNUNET_ARM_Callback callback;
39 void *cls;
40 char *service_name;
41 struct GNUNET_CLIENT_Connection *client;
42 struct GNUNET_CONFIGURATION_Handle *cfg;
43 struct GNUNET_TIME_Absolute timeout;
44 uint16_t type;
45};
46
47
48static void
49arm_service_report (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
50{
51 struct ArmContext *pos = cls;
52 pid_t pid;
53 char *binary;
54 char *config;
55
56 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE))
57 {
58 if (pos->callback != NULL)
59 pos->callback (pos->cls, GNUNET_YES);
60 GNUNET_free (pos);
61 return;
62 }
63 binary = NULL;
64 config = NULL;
65 /* start service */
66 if ((GNUNET_OK !=
67 GNUNET_CONFIGURATION_get_value_filename (pos->cfg,
68 "arm",
69 "BINARY",
70 &binary)) ||
71 (GNUNET_OK !=
72 GNUNET_CONFIGURATION_get_value_filename (pos->cfg,
73 "arm", "CONFIG", &config)))
74 {
75 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
76 _("Configuration file or binary for ARM not known!\n"));
77 if (pos->callback != NULL)
78 pos->callback (pos->cls, GNUNET_SYSERR);
79 GNUNET_free_non_null (binary);
80 GNUNET_free (pos);
81 return;
82 }
83 pid = GNUNET_OS_start_process (binary, binary, "-d", "-c", config,
84#if DEBUG_ARM
85 "-L", "DEBUG",
86#endif
87 NULL);
88 GNUNET_free (binary);
89 GNUNET_free (config);
90 if (pid == -1)
91 {
92 if (pos->callback != NULL)
93 pos->callback (pos->cls, GNUNET_SYSERR);
94 GNUNET_free (pos);
95 return;
96 }
97 /* FIXME: consider checking again to see if it worked!? */
98 if (pos->callback != NULL)
99 pos->callback (pos->cls, GNUNET_YES);
100 GNUNET_free (pos);
101}
102
103
104static void
105handle_response (void *cls, const struct GNUNET_MessageHeader *msg)
106{
107 struct ArmContext *sc = cls;
108 int ret;
109
110 if (msg == NULL)
111 {
112 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
113 _("Error receiving response from ARM service\n"));
114 GNUNET_CLIENT_disconnect (sc->client);
115 if (sc->callback != NULL)
116 sc->callback (sc->cls, GNUNET_SYSERR);
117 GNUNET_free (sc);
118 return;
119 }
120#if DEBUG_ARM
121 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
122 _("Received response from ARM service\n"));
123#endif
124 switch (ntohs (msg->type))
125 {
126 case GNUNET_MESSAGE_TYPE_ARM_IS_UP:
127 ret = GNUNET_YES;
128 break;
129 case GNUNET_MESSAGE_TYPE_ARM_IS_DOWN:
130 ret = GNUNET_NO;
131 break;
132 default:
133 GNUNET_break (0);
134 ret = GNUNET_SYSERR;
135 }
136 GNUNET_CLIENT_disconnect (sc->client);
137 if (sc->callback != NULL)
138 sc->callback (sc->cls, ret);
139 GNUNET_free (sc);
140}
141
142
143static size_t
144send_service_msg (void *cls, size_t size, void *buf)
145{
146 struct ArmContext *sctx = cls;
147 struct GNUNET_MessageHeader *msg;
148 size_t slen;
149
150 if (buf == NULL)
151 {
152 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
153 _("Error while trying to transmit to ARM service\n"));
154 GNUNET_CLIENT_disconnect (sctx->client);
155 if (sctx->callback != NULL)
156 sctx->callback (sctx->cls, GNUNET_SYSERR);
157 GNUNET_free (sctx->service_name);
158 GNUNET_free (sctx);
159 return 0;
160 }
161#if DEBUG_ARM
162 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
163 _("Transmitting service request to ARM.\n"));
164#endif
165 slen = strlen (sctx->service_name) + 1;
166 GNUNET_assert (size >= slen);
167 msg = buf;
168 msg->size = htons (sizeof (struct GNUNET_MessageHeader) + slen);
169 msg->type = htons (sctx->type);
170 memcpy (&msg[1], sctx->service_name, slen);
171 GNUNET_free (sctx->service_name);
172 sctx->service_name = NULL;
173 GNUNET_CLIENT_receive (sctx->client,
174 &handle_response,
175 sctx,
176 GNUNET_TIME_absolute_get_remaining (sctx->timeout));
177 return slen + sizeof (struct GNUNET_MessageHeader);
178}
179
180
181/**
182 * Start or stop a service.
183 *
184 * @param service_name name of the service
185 * @param cfg configuration to use (needed to contact ARM;
186 * the ARM service may internally use a different
187 * configuration to determine how to start the service).
188 * @param sched scheduler to use
189 * @param timeout how long to wait before failing for good
190 * @param cb callback to invoke when service is ready
191 * @param cb_cls closure for callback
192 */
193static void
194change_service (const char *service_name,
195 struct GNUNET_CONFIGURATION_Handle *cfg,
196 struct GNUNET_SCHEDULER_Handle *sched,
197 struct GNUNET_TIME_Relative timeout,
198 GNUNET_ARM_Callback cb, void *cb_cls, uint16_t type)
199{
200 struct GNUNET_CLIENT_Connection *client;
201 struct ArmContext *sctx;
202 size_t slen;
203
204 slen = strlen (service_name) + 1;
205 if (slen + sizeof (struct GNUNET_MessageHeader) >
206 GNUNET_SERVER_MAX_MESSAGE_SIZE)
207 {
208 GNUNET_break (0);
209 if (cb != NULL)
210 cb (cb_cls, GNUNET_NO);
211 return;
212 }
213 client = GNUNET_CLIENT_connect (sched, "arm", cfg);
214 if (client == NULL)
215 {
216 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
217 _("Failed to connect to ARM service\n"));
218 if (cb != NULL)
219 cb (cb_cls, GNUNET_SYSERR);
220 return;
221 }
222#if DEBUG_ARM
223 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
224 _("ARM requests starting of service `%s'.\n"), service_name);
225#endif
226 sctx = GNUNET_malloc (sizeof (struct ArmContext));
227 sctx->callback = cb;
228 sctx->cls = cb_cls;
229 sctx->client = client;
230 sctx->service_name = GNUNET_strdup (service_name);
231 sctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
232 sctx->type = type;
233 if (NULL ==
234 GNUNET_CLIENT_notify_transmit_ready (client,
235 slen +
236 sizeof (struct
237 GNUNET_MessageHeader),
238 timeout, &send_service_msg, sctx))
239 {
240 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
241 _("Failed to transmit request to ARM service\n"));
242 GNUNET_free (sctx->service_name);
243 GNUNET_free (sctx);
244 if (cb != NULL)
245 cb (cb_cls, GNUNET_SYSERR);
246 GNUNET_CLIENT_disconnect (client);
247 return;
248 }
249}
250
251
252/**
253 * Start a service.
254 *
255 * @param service_name name of the service
256 * @param cfg configuration to use (needed to contact ARM;
257 * the ARM service may internally use a different
258 * configuration to determine how to start the service).
259 * @param sched scheduler to use
260 * @param timeout how long to wait before failing for good
261 * @param cb callback to invoke when service is ready
262 * @param cb_cls closure for callback
263 */
264void
265GNUNET_ARM_start_service (const char *service_name,
266 struct GNUNET_CONFIGURATION_Handle *cfg,
267 struct GNUNET_SCHEDULER_Handle *sched,
268 struct GNUNET_TIME_Relative timeout,
269 GNUNET_ARM_Callback cb, void *cb_cls)
270{
271 struct ArmContext *sctx;
272
273 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
274 _("Starting service `%s'\n"), service_name);
275 if (0 == strcmp ("arm", service_name))
276 {
277 sctx = GNUNET_malloc (sizeof (struct ArmContext));
278 sctx->callback = cb;
279 sctx->cls = cb_cls;
280 sctx->cfg = cfg;
281 GNUNET_CLIENT_service_test (sched,
282 "arm",
283 cfg, timeout, &arm_service_report, sctx);
284 return;
285 }
286 change_service (service_name,
287 cfg,
288 sched, timeout, cb, cb_cls, GNUNET_MESSAGE_TYPE_ARM_START);
289}
290
291
292
293
294/**
295 * Stop a service.
296 *
297 * @param service_name name of the service
298 * @param cfg configuration to use (needed to contact ARM;
299 * the ARM service may internally use a different
300 * configuration to determine how to start the service).
301 * @param sched scheduler to use
302 * @param timeout how long to wait before failing for good
303 * @param cb callback to invoke when service is ready
304 * @param cb_cls closure for callback
305 */
306void
307GNUNET_ARM_stop_service (const char *service_name,
308 struct GNUNET_CONFIGURATION_Handle *cfg,
309 struct GNUNET_SCHEDULER_Handle *sched,
310 struct GNUNET_TIME_Relative timeout,
311 GNUNET_ARM_Callback cb, void *cb_cls)
312{
313 struct GNUNET_CLIENT_Connection *client;
314
315 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
316 _("Stopping service `%s'\n"), service_name);
317 if (0 == strcmp ("arm", service_name))
318 {
319 client = GNUNET_CLIENT_connect (sched, "arm", cfg);
320 if (client == NULL)
321 {
322 if (cb != NULL)
323 cb (cb_cls, GNUNET_SYSERR);
324 return;
325 }
326 GNUNET_CLIENT_service_shutdown (client);
327 GNUNET_CLIENT_disconnect (client);
328 if (cb != NULL)
329 cb (cb_cls, GNUNET_NO);
330 return;
331 }
332 change_service (service_name,
333 cfg,
334 sched, timeout, cb, cb_cls, GNUNET_MESSAGE_TYPE_ARM_STOP);
335}
336
337/* end of arm_api.c */
diff --git a/src/arm/gnunet-arm.c b/src/arm/gnunet-arm.c
new file mode 100644
index 000000000..f8f5bc20f
--- /dev/null
+++ b/src/arm/gnunet-arm.c
@@ -0,0 +1,180 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 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 2, 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 arm/gnunet-arm.c
23 * @brief arm for writing a tool
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_arm_service.h"
28#include "gnunet_client_lib.h"
29#include "gnunet_getopt_lib.h"
30#include "gnunet_program_lib.h"
31#include "gnunet_time_lib.h"
32
33/**
34 * Timeout for all operations.
35 */
36#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
37
38/**
39 * Set if we are to shutdown all services (including ARM).
40 */
41static int end;
42
43/**
44 * Set if we are to start default services (including ARM).
45 */
46static int start;
47
48/**
49 * Set to the name of a service to start.
50 */
51static char *init;
52
53/**
54 * Set to the name of a service to kill.
55 */
56static char *term;
57
58/**
59 * Set to the name of a service to test.
60 */
61static char *test;
62
63/**
64 * Final status code.
65 */
66static int ret;
67
68
69static void
70confirm_cb (void *cls, int success)
71{
72 const char *service = cls;
73 switch (success)
74 {
75 case GNUNET_OK:
76 fprintf (stdout, _("Service `%s' is now running.\n"), service);
77 break;
78 case GNUNET_NO:
79 fprintf (stdout, _("Service `%s' is not running.\n"), service);
80 break;
81 case GNUNET_SYSERR:
82 fprintf (stdout,
83 _("Error updating service `%s': ARM not running\n"), service);
84 break;
85 }
86}
87
88
89static void
90confirm_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
91{
92 const char *service = cls;
93
94 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE))
95 fprintf (stdout, _("Service `%s' is running.\n"), service);
96 else
97 fprintf (stdout, _("Service `%s' is not running.\n"), service);
98}
99
100
101/**
102 * Main function that will be run by the scheduler.
103 *
104 * @param cls closure
105 * @param sched the scheduler to use
106 * @param args remaining command-line arguments
107 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
108 * @param cfg configuration
109 */
110static void
111run (void *cls,
112 struct GNUNET_SCHEDULER_Handle *sched,
113 char *const *args,
114 const char *cfgfile, struct GNUNET_CONFIGURATION_Handle *cfg)
115{
116 if (term != NULL)
117 {
118 GNUNET_ARM_stop_service (term, cfg, sched, TIMEOUT, &confirm_cb, term);
119 }
120 if (end)
121 {
122 GNUNET_ARM_stop_service ("arm",
123 cfg, sched, TIMEOUT, &confirm_cb, "arm");
124 }
125 if (start)
126 {
127 GNUNET_ARM_start_service ("arm",
128 cfg, sched, TIMEOUT, &confirm_cb, "arm");
129 }
130 if (init != NULL)
131 {
132 GNUNET_ARM_start_service (init, cfg, sched, TIMEOUT, &confirm_cb, init);
133 }
134 if (test != NULL)
135 {
136 GNUNET_CLIENT_service_test (sched,
137 test, cfg, TIMEOUT, &confirm_task, test);
138 }
139}
140
141
142/**
143 * gnunet-arm command line options
144 */
145static struct GNUNET_GETOPT_CommandLineOption options[] = {
146 {'e', "end", NULL, gettext_noop ("stop all GNUnet services"),
147 GNUNET_NO, &GNUNET_GETOPT_set_one, &end},
148 {'i', "init", "SERVICE", gettext_noop ("start a particular service"),
149 GNUNET_YES, &GNUNET_GETOPT_set_string, &init},
150 {'k', "kill", "SERVICE", gettext_noop ("stop a particular service"),
151 GNUNET_YES, &GNUNET_GETOPT_set_string, &term},
152 {'s', "start", NULL, gettext_noop ("start all GNUnet default services"),
153 GNUNET_NO, &GNUNET_GETOPT_set_one, &start},
154 {'t', "test", "SERVICE",
155 gettext_noop ("test if a particular service is running"),
156 GNUNET_YES, &GNUNET_GETOPT_set_string, &test},
157 GNUNET_GETOPT_OPTION_END
158};
159
160
161/**
162 * The main function to obtain arm from gnunetd.
163 *
164 * @param argc number of arguments from the command line
165 * @param argv command line arguments
166 * @return 0 ok, 1 on error
167 */
168int
169main (int argc, char *const *argv)
170{
171 return (GNUNET_OK ==
172 GNUNET_PROGRAM_run (argc,
173 argv,
174 "gnunet-arm",
175 gettext_noop
176 ("Control services and the Automated Restart Manager (ARM)"),
177 options, &run, NULL)) ? ret : 1;
178}
179
180/* end of gnunet-arm.c */
diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c
new file mode 100644
index 000000000..97d507890
--- /dev/null
+++ b/src/arm/gnunet-service-arm.c
@@ -0,0 +1,712 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 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 2, 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 arm/gnunet-service-arm.c
23 * @brief the automated restart manager service
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - multiple start-stop requests with RC>1 can result
28 * in UP/DOWN signals based on "pending" that are inaccurate...
29 * => have list of clients waiting for a resolution instead of
30 * giving instant (but incorrect) replies
31 * - code could go into restart-loop for a service
32 * if service crashes instantly -- need exponential back-off
33 * - need to test auto-restart code on configuration changes;
34 * - should refine restart code to check if *relevant* parts of the
35 * configuration were changed (anything in the section for the service)
36 * - should have a way to specify dependencies between services and
37 * manage restarts of groups of services
38 */
39#include "platform.h"
40#include "gnunet_client_lib.h"
41#include "gnunet_getopt_lib.h"
42#include "gnunet_os_lib.h"
43#include "gnunet_protocols.h"
44#include "gnunet_service_lib.h"
45#include "arm.h"
46
47
48/**
49 * Run maintenance every second.
50 */
51#define MAINT_FREQUENCY GNUNET_TIME_UNIT_SECONDS
52
53/**
54 * How long do we wait until we decide that a service
55 * did not start?
56 */
57#define CHECK_TIMEOUT GNUNET_TIME_UNIT_MINUTES
58
59struct ServiceList;
60
61typedef void (*CleanCallback) (void *cls, struct ServiceList * pos);
62
63/**
64 * List of our services.
65 */
66struct ServiceList
67{
68 /**
69 * This is a linked list.
70 */
71 struct ServiceList *next;
72
73 /**
74 * Name of the service.
75 */
76 char *name;
77
78 /**
79 * Name of the binary used.
80 */
81 char *binary;
82
83 /**
84 * Name of the configuration file used.
85 */
86 char *config;
87
88 /**
89 * Function to call upon kill completion (waitpid), NULL
90 * if we should simply restart the process.
91 */
92 CleanCallback kill_continuation;
93
94 /**
95 * Closure for kill_continuation.
96 */
97 void *kill_continuation_cls;
98
99 /**
100 * Process ID of the child.
101 */
102 pid_t pid;
103
104 /**
105 * Last time the config of this service was
106 * modified.
107 */
108 time_t mtime;
109
110 /**
111 * Reference counter (counts how many times we've been
112 * asked to start the service). We only actually stop
113 * it once rc hits zero.
114 */
115 unsigned int rc;
116
117};
118
119/**
120 * List of running services.
121 */
122static struct ServiceList *running;
123
124/**
125 * Our configuration
126 */
127static struct GNUNET_CONFIGURATION_Handle *cfg;
128
129/**
130 * Our scheduler.
131 */
132static struct GNUNET_SCHEDULER_Handle *sched;
133
134/**
135 * Command to prepend to each actual command.
136 */
137static char *prefix_command;
138
139
140static size_t
141write_result (void *cls, size_t size, void *buf)
142{
143 uint16_t *res = cls;
144 struct GNUNET_MessageHeader *msg;
145
146 if (buf == NULL)
147 return 0; /* error, not much we can do */
148 GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
149 msg = buf;
150 msg->size = htons (sizeof (struct GNUNET_MessageHeader));
151 msg->type = htons (*res);
152 GNUNET_free (res);
153 return sizeof (struct GNUNET_MessageHeader);
154}
155
156
157
158/**
159 * Signal our client that we will start or stop the
160 * service.
161 *
162 * @return NULL if it was not found
163 */
164static void
165signal_result (struct GNUNET_SERVER_Client *client,
166 const char *name, uint16_t result)
167{
168 uint16_t *res;
169
170#if DEBUG_ARM
171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
172 "Telling client that service `%s' is now %s\n",
173 name,
174 result == GNUNET_MESSAGE_TYPE_ARM_IS_DOWN ? "down" : "up");
175#endif
176 res = GNUNET_malloc (sizeof (uint16_t));
177 *res = result;
178 GNUNET_SERVER_notify_transmit_ready (client,
179 sizeof (struct GNUNET_MessageHeader),
180 GNUNET_TIME_UNIT_FOREVER_REL,
181 &write_result, res);
182}
183
184
185/**
186 * Find the process with the given PID in the
187 * given list.
188 *
189 * @return NULL if it was not found
190 */
191static struct ServiceList *
192find_pid (pid_t pid)
193{
194 struct ServiceList *pos;
195
196 pos = running;
197 while (pos != NULL)
198 {
199 if (pos->pid == pid)
200 return pos;
201 pos = pos->next;
202 }
203 return NULL;
204}
205
206
207/**
208 * Find the process with the given service
209 * name in the given list, remove it and return it.
210 *
211 * @return NULL if it was not found
212 */
213static struct ServiceList *
214find_name (const char *name)
215{
216 struct ServiceList *pos;
217 struct ServiceList *prev;
218
219 pos = running;
220 prev = NULL;
221 while (pos != NULL)
222 {
223 if (0 == strcmp (pos->name, name))
224 {
225 if (prev == NULL)
226 running = pos->next;
227 else
228 prev->next = pos->next;
229 pos->next = NULL;
230 return pos;
231 }
232 prev = pos;
233 pos = pos->next;
234 }
235 return NULL;
236}
237
238
239static void
240free_entry (struct ServiceList *pos)
241{
242 GNUNET_free_non_null (pos->config);
243 GNUNET_free_non_null (pos->binary);
244 GNUNET_free (pos->name);
245 GNUNET_free (pos);
246}
247
248
249
250
251/**
252 * Actually start the process for the given service.
253 *
254 * @param sl identifies service to start
255 */
256static void
257start_process (struct ServiceList *sl)
258{
259 char *loprefix;
260 char **argv;
261 unsigned int argv_size;
262 char *lopos;
263 const char *firstarg;
264 int use_debug;
265
266 /* start service */
267 if (GNUNET_OK !=
268 GNUNET_CONFIGURATION_get_value_string (cfg,
269 sl->name, "PREFIX", &loprefix))
270 loprefix = GNUNET_strdup (prefix_command);
271 use_debug = GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "DEBUG");
272
273 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting service `%s'\n"), sl->name);
274#if DEBUG_ARM
275 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
276 "Starting service `%s' using binary `%s' and configuration `%s'\n",
277 sl->name, sl->binary, sl->config);
278#endif
279 argv_size = 5;
280 if (use_debug)
281 argv_size += 2;
282 lopos = loprefix;
283 while ('\0' != *lopos)
284 {
285 if (*lopos == ' ')
286 argv_size++;
287 lopos++;
288 }
289 firstarg = NULL;
290 argv = GNUNET_malloc (argv_size * sizeof (char *));
291 argv_size = 0;
292 lopos = loprefix;
293 while ('\0' != *lopos)
294 {
295 while (*lopos == ' ')
296 lopos++;
297 if (*lopos == '\0')
298 continue;
299 if (argv_size == 0)
300 firstarg = lopos;
301 argv[argv_size++] = lopos;
302 while (('\0' != *lopos) && (' ' != *lopos))
303 lopos++;
304 if ('\0' == *lopos)
305 continue;
306 *lopos = '\0';
307 lopos++;
308 }
309 if (argv_size == 0)
310 firstarg = sl->binary;
311 argv[argv_size++] = sl->binary;
312 argv[argv_size++] = "-c";
313 argv[argv_size++] = sl->config;
314 if (GNUNET_YES == use_debug)
315 {
316 argv[argv_size++] = "-L";
317 argv[argv_size++] = "DEBUG";
318 }
319 argv[argv_size++] = NULL;
320 sl->pid = GNUNET_OS_start_process_v (firstarg, argv);
321 GNUNET_free (argv);
322 GNUNET_free (loprefix);
323}
324
325
326/**
327 * Start the specified service.
328 */
329static void
330start_service (struct GNUNET_SERVER_Handle *server,
331 struct GNUNET_SERVER_Client *client, const char *servicename)
332{
333 struct ServiceList *sl;
334 char *binary;
335 char *config;
336 struct stat sbuf;
337 sl = find_name (servicename);
338 if (sl != NULL)
339 {
340 /* already running, just increment RC */
341 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
342 _("Service `%s' already running.\n"), servicename);
343 sl->rc++;
344 sl->next = running;
345 running = sl;
346 signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_UP);
347 return;
348 }
349 if (GNUNET_OK !=
350 GNUNET_CONFIGURATION_get_value_string (cfg,
351 servicename, "BINARY", &binary))
352 {
353 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
354 _("Binary implementing service `%s' not known!\n"),
355 servicename);
356 signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN);
357 return;
358 }
359 if ((GNUNET_OK !=
360 GNUNET_CONFIGURATION_get_value_filename (cfg,
361 servicename,
362 "CONFIG",
363 &config)) ||
364 (0 != STAT (config, &sbuf)))
365 {
366 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
367 _("Configuration file `%s' for service `%s' not known!\n"),
368 config, servicename);
369 signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN);
370 GNUNET_free (binary);
371 return;
372 }
373 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
374 _("Preparing to start `%s'\n"), servicename);
375 sl = GNUNET_malloc (sizeof (struct ServiceList));
376 sl->name = GNUNET_strdup (servicename);
377 sl->next = running;
378 sl->rc = 1;
379 sl->binary = binary;
380 sl->config = config;
381 sl->mtime = sbuf.st_mtime;
382 running = sl;
383 start_process (sl);
384 signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_UP);
385}
386
387
388static void
389free_and_signal (void *cls, struct ServiceList *pos)
390{
391 struct GNUNET_SERVER_Client *client = cls;
392 /* find_name will remove "pos" from the list! */
393 GNUNET_assert (pos == find_name (pos->name));
394 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Service `%s' stopped\n", pos->name);
395 signal_result (client, pos->name, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN);
396 GNUNET_SERVER_receive_done (client, GNUNET_OK);
397 GNUNET_SERVER_client_drop (client);
398 free_entry (pos);
399}
400
401
402/**
403 * Stop the specified service.
404 */
405static void
406stop_service (struct GNUNET_SERVER_Handle *server,
407 struct GNUNET_SERVER_Client *client, const char *servicename)
408{
409 struct ServiceList *pos;
410 struct GNUNET_CLIENT_Connection *sc;
411
412 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
413 "Preparing to stop `%s'\n", servicename);
414 pos = find_name (servicename);
415 if (pos->kill_continuation != NULL)
416 {
417 /* killing already in progress */
418 signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN);
419 return;
420 }
421 if ((pos != NULL) && (pos->rc > 1))
422 {
423 /* RC>1, just decrement RC */
424 pos->rc--;
425 pos->next = running;
426 running = pos;
427 signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_UP);
428 GNUNET_SERVER_receive_done (client, GNUNET_OK);
429 return;
430 }
431 if (pos != NULL)
432 {
433 if (0 != PLIBC_KILL (pos->pid, SIGTERM))
434 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
435 pos->next = running;
436 running = pos;
437 pos->kill_continuation = &free_and_signal;
438 pos->kill_continuation_cls = client;
439 GNUNET_SERVER_client_keep (client);
440 }
441 else
442 {
443 sc = GNUNET_CLIENT_connect (sched, servicename, cfg);
444 GNUNET_CLIENT_service_shutdown (sc);
445 GNUNET_CLIENT_disconnect (sc);
446 signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN);
447 GNUNET_SERVER_receive_done (client, GNUNET_OK);
448 }
449}
450
451
452/**
453 * Handle START-message.
454 *
455 * @param cls closure (always NULL)
456 * @param server the server handling the message
457 * @param client identification of the client
458 * @param message the actual message
459 * @return GNUNET_OK to keep the connection open,
460 * GNUNET_SYSERR to close it (signal serious error)
461 */
462static void
463handle_start (void *cls,
464 struct GNUNET_SERVER_Handle *server,
465 struct GNUNET_SERVER_Client *client,
466 const struct GNUNET_MessageHeader *message)
467{
468 const char *servicename;
469 uint16_t size;
470
471 size = ntohs (message->size);
472 size -= sizeof (struct GNUNET_MessageHeader);
473 servicename = (const char *) &message[1];
474 if ((size == 0) || (servicename[size - 1] != '\0'))
475 {
476 GNUNET_break (0);
477 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
478 return;
479 }
480 start_service (server, client, servicename);
481 GNUNET_SERVER_receive_done (client, GNUNET_OK);
482}
483
484
485/**
486 * Handle STOP-message.
487 *
488 * @param cls closure (always NULL)
489 * @param server the server handling the message
490 * @param client identification of the client
491 * @param message the actual message
492 * @return GNUNET_OK to keep the connection open,
493 * GNUNET_SYSERR to close it (signal serious error)
494 */
495static void
496handle_stop (void *cls,
497 struct GNUNET_SERVER_Handle *server,
498 struct GNUNET_SERVER_Client *client,
499 const struct GNUNET_MessageHeader *message)
500{
501 const char *servicename;
502 uint16_t size;
503
504 size = ntohs (message->size);
505 size -= sizeof (struct GNUNET_MessageHeader);
506 servicename = (const char *) &message[1];
507 if ((size == 0) || (servicename[size - 1] != '\0'))
508 {
509 GNUNET_break (0);
510 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
511 return;
512 }
513 stop_service (server, client, servicename);
514}
515
516
517
518/**
519 * Background task doing maintenance.
520 *
521 * @param cls closure
522 * @param tc context
523 */
524static void
525maint (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
526{
527 struct ServiceList *pos;
528 pid_t pid;
529 int status;
530 const char *statstr;
531 int statcode;
532 struct stat sbuf;
533
534 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
535 {
536 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopping all services\n"));
537 while (NULL != (pos = running))
538 {
539 running = pos->next;
540 if (0 != PLIBC_KILL (pos->pid, SIGTERM))
541 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
542 if (pos->pid != waitpid (pos->pid, NULL, 0))
543 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
544 free_entry (pos);
545 }
546 return;
547 }
548 GNUNET_SCHEDULER_add_delayed (tc->sched,
549 GNUNET_YES,
550 GNUNET_SCHEDULER_PRIORITY_IDLE,
551 GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
552 MAINT_FREQUENCY, &maint, cfg);
553
554 /* check for services that died (WAITPID) */
555 while (0 < (pid = waitpid (0, &status, WNOHANG)))
556 {
557 if (WIFSTOPPED (status) || WIFCONTINUED (status))
558 continue;
559 pos = find_pid (pid);
560 if (pos == NULL)
561 {
562 /* we killed the service */
563 continue;
564 }
565 if (WIFEXITED (status))
566 {
567 statstr = _( /* process termination method */ "exit");
568 statcode = WEXITSTATUS (status);
569 }
570 else if (WTERMSIG (status))
571 {
572 statstr = _( /* process termination method */ "signal");
573 statcode = WTERMSIG (status);
574 }
575 else
576 {
577 statstr = _( /* process termination method */ "unknown");
578 statcode = 0;
579 }
580 if (NULL != pos->kill_continuation)
581 {
582 pos->kill_continuation (pos->kill_continuation_cls, pos);
583 }
584 else
585 {
586 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
587 _
588 ("Service `%s' terminated with status %s/%d, will try to restart it!\n"),
589 pos->name, statstr, statcode);
590 /* schedule restart */
591 pos->pid = 0;
592 }
593 }
594
595 /* check for services that need to be restarted due to
596 configuration changes or because the last restart failed */
597 pos = running;
598 while (pos != NULL)
599 {
600 if ((0 == STAT (pos->config, &sbuf)) && (pos->mtime < sbuf.st_mtime))
601 {
602 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
603 _
604 ("Restarting service `%s' due to configuration file change.\n"));
605 if (0 != PLIBC_KILL (pos->pid, SIGTERM))
606 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
607 }
608 if (pos->pid == 0)
609 {
610 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
611 _("Restarting service `%s'.\n"), pos->name);
612 /* FIXME: should have some exponentially
613 increasing timer to avoid tight restart loops */
614 start_process (pos);
615 }
616 pos = pos->next;
617 }
618}
619
620
621/**
622 * List of handlers for the messages understood by this
623 * service.
624 */
625static struct GNUNET_SERVER_MessageHandler handlers[] = {
626 {&handle_start, NULL, GNUNET_MESSAGE_TYPE_ARM_START, 0},
627 {&handle_stop, NULL, GNUNET_MESSAGE_TYPE_ARM_STOP, 0},
628 {NULL, NULL, 0, 0}
629};
630
631
632/**
633 * Process arm requests.
634 *
635 * @param cls closure
636 * @param s scheduler to use
637 * @param server the initialized server
638 * @param c configuration to use
639 */
640static void
641run (void *cls,
642 struct GNUNET_SCHEDULER_Handle *s,
643 struct GNUNET_SERVER_Handle *server,
644 struct GNUNET_CONFIGURATION_Handle *c)
645{
646 char *defaultservices;
647 char *pos;
648
649 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting...\n");
650 cfg = c;
651 sched = s;
652 if (GNUNET_OK !=
653 GNUNET_CONFIGURATION_get_value_string (cfg,
654 "ARM",
655 "GLOBAL_PREFIX",
656 &prefix_command))
657 prefix_command = GNUNET_strdup ("");
658 /* start default services... */
659 if (GNUNET_OK ==
660 GNUNET_CONFIGURATION_get_value_string (cfg,
661 "ARM",
662 "DEFAULTSERVICES",
663 &defaultservices))
664 {
665#if DEBUG_ARM
666 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
667 "Starting default services `%s'\n", defaultservices);
668#endif
669 pos = strtok (defaultservices, " ");
670 while (pos != NULL)
671 {
672 start_service (server, NULL, pos);
673 pos = strtok (NULL, " ");
674 }
675 GNUNET_free (defaultservices);
676 }
677 else
678 {
679#if DEBUG_ARM
680 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
681 "No default services configured.\n");
682#endif
683 }
684
685 /* process client requests */
686 GNUNET_SERVER_add_handlers (server, handlers);
687
688 /* manage services */
689 GNUNET_SCHEDULER_add_delayed (sched,
690 GNUNET_YES,
691 GNUNET_SCHEDULER_PRIORITY_IDLE,
692 GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
693 MAINT_FREQUENCY, &maint, NULL);
694}
695
696
697/**
698 * The main function for the arm service.
699 *
700 * @param argc number of arguments from the command line
701 * @param argv command line arguments
702 * @return 0 ok, 1 on error
703 */
704int
705main (int argc, char *const *argv)
706{
707 return (GNUNET_OK ==
708 GNUNET_SERVICE_run (argc,
709 argv, "arm", &run, NULL, NULL, NULL)) ? 0 : 1;
710}
711
712/* end of gnunet-service-arm.c */
diff --git a/src/arm/test_arm_api.c b/src/arm/test_arm_api.c
new file mode 100644
index 000000000..89f63d3ec
--- /dev/null
+++ b/src/arm/test_arm_api.c
@@ -0,0 +1,140 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 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 2, 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 arm/test_arm_api.c
22 * @brief testcase for arm_api.c
23 */
24#include "platform.h"
25#include "gnunet_common.h"
26#include "gnunet_arm_service.h"
27#include "gnunet_client_lib.h"
28#include "gnunet_configuration_lib.h"
29#include "gnunet_getopt_lib.h"
30#include "gnunet_program_lib.h"
31#include "gnunet_resolver_service.h"
32
33#define VERBOSE GNUNET_NO
34
35#define START_ARM GNUNET_YES
36
37#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
38
39static struct GNUNET_SCHEDULER_Handle *sched;
40
41static struct GNUNET_CONFIGURATION_Handle *cfg;
42
43static int ok = 1;
44
45static void
46dns_notify (void *cls, const struct sockaddr *addr, socklen_t addrlen)
47{
48 if (addr == NULL)
49 {
50 GNUNET_assert (ok == 0);
51#if START_ARM
52 GNUNET_ARM_stop_service ("arm", cfg, sched, TIMEOUT, NULL, NULL);
53#endif
54 return;
55 }
56 GNUNET_assert (addr != NULL);
57 ok = 0;
58}
59
60
61static void
62resolver_notify (void *cls, int success)
63{
64 GNUNET_assert (success == GNUNET_YES);
65 sleep (1); /* FIXME: that we need to do this is a problem... */
66 GNUNET_RESOLVER_ip_get (sched,
67 cfg,
68 "localhost", AF_INET, TIMEOUT, &dns_notify, NULL);
69}
70
71static void
72arm_notify (void *cls, int success)
73{
74 GNUNET_assert (success == GNUNET_YES);
75#if START_ARM
76 sleep (1); /* FIXME: that we need to do this is a problem... */
77#endif
78 GNUNET_ARM_start_service ("resolver",
79 cfg, sched, TIMEOUT, &resolver_notify, NULL);
80}
81
82
83static void
84task (void *cls,
85 struct GNUNET_SCHEDULER_Handle *s,
86 char *const *args,
87 const char *cfgfile, struct GNUNET_CONFIGURATION_Handle *c)
88{
89 cfg = c;
90 sched = s;
91#if START_ARM
92 GNUNET_ARM_start_service ("arm", cfg, sched, TIMEOUT, &arm_notify, NULL);
93#else
94 arm_notify (NULL, GNUNET_YES);
95#endif
96}
97
98
99
100static int
101check ()
102{
103 char *const argv[] = {
104 "test-arm-api",
105 "-c", "test_arm_api_data.conf",
106#if VERBOSE
107 "-L", "DEBUG",
108#endif
109 NULL
110 };
111 struct GNUNET_GETOPT_CommandLineOption options[] = {
112 GNUNET_GETOPT_OPTION_END
113 };
114 GNUNET_assert (GNUNET_OK ==
115 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
116 argv,
117 "test-arm-api",
118 "nohelp", options, &task, NULL));
119 return ok;
120}
121
122int
123main (int argc, char *argv[])
124{
125 int ret;
126
127
128 GNUNET_log_setup ("test-arm-api",
129#if VERBOSE
130 "DEBUG",
131#else
132 "WARNING",
133#endif
134 NULL);
135 ret = check ();
136
137 return ret;
138}
139
140/* end of test_arm_api.c */
diff --git a/src/arm/test_arm_api_data.conf b/src/arm/test_arm_api_data.conf
new file mode 100644
index 000000000..b25924917
--- /dev/null
+++ b/src/arm/test_arm_api_data.conf
@@ -0,0 +1,7 @@
1[PATHS]
2SERVICEHOME = /tmp/test-gnunetd-arm/
3DEFAULTCONFIG = test_arm_api_data.conf
4
5[arm]
6PORT = 23354
7
diff --git a/src/arm/test_gnunet_arm.sh b/src/arm/test_gnunet_arm.sh
new file mode 100755
index 000000000..72f7a176b
--- /dev/null
+++ b/src/arm/test_gnunet_arm.sh
@@ -0,0 +1,117 @@
1#!/bin/bash
2
3rm -rf /tmp/test-gnunetd-arm/
4exe="./gnunet-arm -c test_arm_api_data.conf"
5base=/tmp/gnunet-test-arm
6#DEBUG="-L DEBUG"
7
8# ----------------------------------------------------------------------------------
9echo -n "TEST: Bad argument checking... "
10
11if $exe -x 2> /dev/null; then
12 echo "FAIL: error running $exe"
13 exit 1
14fi
15echo "PASS"
16
17# ----------------------------------------------------------------------------------
18echo -n "TEST: Start ARM... "
19
20if ! $exe $DEBUG -s > /dev/null ; then
21 echo "FAIL: error running $exe"
22 exit 1
23fi
24LINES=`ps ax | grep gnunet-service-arm | grep -v grep | wc -l`
25if test $LINES -eq 0; then
26 echo "FAIL: found $LINES gnunet-service-arm processes"
27 exit 1
28fi
29echo "PASS"
30
31# ----------------------------------------------------------------------------------
32echo -n "TEST: Start another service... "
33
34if ! $exe $DEBUG -i resolver > /dev/null ; then
35 echo "FAIL: error running $exe"
36 kill %%
37 exit 1
38fi
39sleep 1
40LINES=`ps ax | grep gnunet-service-resolver | grep -v grep | wc -l`
41if test $LINES -ne 1; then
42 echo "FAIL: unexpected output (got $LINES lines, wanted 1)"
43 $exe -e
44 exit 1
45fi
46echo "PASS"
47
48# ----------------------------------------------------------------------------------
49echo -n "TEST: Test -t on running service... "
50
51if ! $exe $DEBUG -t resolver > $base.out; then
52 echo "FAIL: error running $exe"
53 exit 1
54fi
55LINES=`cat $base.out | grep resolver | grep not | wc -l`
56if test $LINES -ne 0; then
57 echo "FAIL: unexpected output"
58 $exe -e
59 exit 1
60fi
61LINES=`cat $base.out | grep resolver | grep -v not | wc -l`
62if test $LINES -ne 1; then
63 echo "FAIL: unexpected output"
64 $exe -e
65 exit 1
66fi
67echo "PASS"
68
69# ----------------------------------------------------------------------------------
70echo -n "TEST: Stop a service... "
71
72if ! $exe $DEBUG -k resolver > /dev/null; then
73 echo "FAIL: error running $exe"
74 $exe -e
75 exit 1
76fi
77sleep 1
78LINES=`ps ax | grep gnunet-service-resolver | grep -v grep | wc -l`
79if test $LINES -ne 0; then
80 echo "FAIL: unexpected output"
81 $exe -e
82 exit 1
83fi
84echo "PASS"
85
86# ----------------------------------------------------------------------------------
87echo -n "TEST: Test -t on stopped service... "
88
89if ! $exe $DEBUG -t resolver > $base.out; then
90 echo "FAIL: error running $exe"
91 $exe -e
92 exit 1
93fi
94LINES=`cat $base.out | grep resolver | grep not | wc -l`
95if test $LINES -ne 1; then
96 echo "FAIL: unexpected output"
97 $exe -e
98 exit 1
99fi
100echo "PASS"
101
102# ----------------------------------------------------------------------------------
103echo -n "TEST: Stop ARM... "
104
105if ! $exe $DEBUG -e > /dev/null; then
106 echo "FAIL: error running $exe"
107 exit 1
108fi
109LINES=`ps ax | grep gnunet-service-arm | grep -v grep | wc -l`
110if test $LINES -ne 0; then
111 echo "FAIL: unexpected output"
112 exit 1
113fi
114echo "PASS"
115
116rm -rf /tmp/test-gnunetd-arm/
117rm -f $base.out