diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-12-08 15:45:10 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-12-08 15:45:10 +0000 |
commit | cbd09ba94fde1331cb4fe6ea29f5f164adc8db25 (patch) | |
tree | 7d6d205b2f0fbaf894770334733c589c34fb4864 /src/arm | |
parent | 7ecae6c47bc658cce69de75c1addb0c6db75ced9 (diff) | |
download | gnunet-cbd09ba94fde1331cb4fe6ea29f5f164adc8db25.tar.gz gnunet-cbd09ba94fde1331cb4fe6ea29f5f164adc8db25.zip |
major rewrite of ARM service and a bit of the ARM IPC to take advantage of the simplifications possible now that we no longer intercept traffic; the new code in particular is better at communicating what exactly ARM was doing in response to requests. A major change is that gnunet-arm -i/-k now only impacts if a service is running by-default, on-demand starting is no longer impacted, option -t from gnunet-arm was removed
Diffstat (limited to 'src/arm')
-rw-r--r-- | src/arm/Makefile.am | 2 | ||||
-rw-r--r-- | src/arm/arm.h | 19 | ||||
-rw-r--r-- | src/arm/arm_api.c | 446 | ||||
-rw-r--r-- | src/arm/do_start_process.c | 56 | ||||
-rw-r--r-- | src/arm/gnunet-arm.c | 319 | ||||
-rw-r--r-- | src/arm/gnunet-service-arm.c | 1466 | ||||
-rw-r--r-- | src/arm/mockup-service.c | 2 | ||||
-rw-r--r-- | src/arm/test_arm_api.c | 73 | ||||
-rw-r--r-- | src/arm/test_exponential_backoff.c | 221 | ||||
-rwxr-xr-x | src/arm/test_gnunet_arm.sh | 39 | ||||
-rw-r--r-- | src/arm/test_gnunet_service_manager.c | 103 |
11 files changed, 1247 insertions, 1499 deletions
diff --git a/src/arm/Makefile.am b/src/arm/Makefile.am index 7d96ba594..2bc81653c 100644 --- a/src/arm/Makefile.am +++ b/src/arm/Makefile.am | |||
@@ -23,7 +23,7 @@ libgnunetarm_la_LIBADD = \ | |||
23 | $(GN_LIBINTL) $(XLIB) | 23 | $(GN_LIBINTL) $(XLIB) |
24 | libgnunetarm_la_LDFLAGS = \ | 24 | libgnunetarm_la_LDFLAGS = \ |
25 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | 25 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ |
26 | -version-info 0:0:0 | 26 | -version-info 1:0:0 |
27 | 27 | ||
28 | 28 | ||
29 | bin_PROGRAMS = \ | 29 | bin_PROGRAMS = \ |
diff --git a/src/arm/arm.h b/src/arm/arm.h index f20562c20..615079b7c 100644 --- a/src/arm/arm.h +++ b/src/arm/arm.h | |||
@@ -33,4 +33,23 @@ | |||
33 | */ | 33 | */ |
34 | #define DEBUG_ARM GNUNET_EXTRA_LOGGING | 34 | #define DEBUG_ARM GNUNET_EXTRA_LOGGING |
35 | 35 | ||
36 | |||
37 | /** | ||
38 | * Reply from ARM to client. | ||
39 | */ | ||
40 | struct GNUNET_ARM_ResultMessage | ||
41 | { | ||
42 | |||
43 | /** | ||
44 | * Reply to client, of type is GNUNET_MESSAGE_TYPE_ARM_RESULT. | ||
45 | */ | ||
46 | struct GNUNET_MessageHeader header; | ||
47 | |||
48 | /** | ||
49 | * Status from the 'enum GNUNET_ARM_ProcessStatus' | ||
50 | */ | ||
51 | uint32_t status; | ||
52 | }; | ||
53 | |||
54 | |||
36 | #endif | 55 | #endif |
diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c index c15c59875..12395fea9 100644 --- a/src/arm/arm_api.c +++ b/src/arm/arm_api.c | |||
@@ -84,12 +84,13 @@ struct ShutdownContext | |||
84 | void *cont_cls; | 84 | void *cont_cls; |
85 | 85 | ||
86 | /** | 86 | /** |
87 | * We received a confirmation that the service will shut down. | 87 | * Result of the operation |
88 | */ | 88 | */ |
89 | int confirmed; | 89 | enum GNUNET_ARM_ProcessStatus confirmed; |
90 | 90 | ||
91 | }; | 91 | }; |
92 | 92 | ||
93 | |||
93 | /** | 94 | /** |
94 | * Handler receiving response to service shutdown requests. | 95 | * Handler receiving response to service shutdown requests. |
95 | * First call with NULL: service misbehaving, or something. | 96 | * First call with NULL: service misbehaving, or something. |
@@ -105,76 +106,61 @@ static void | |||
105 | service_shutdown_handler (void *cls, const struct GNUNET_MessageHeader *msg) | 106 | service_shutdown_handler (void *cls, const struct GNUNET_MessageHeader *msg) |
106 | { | 107 | { |
107 | struct ShutdownContext *shutdown_ctx = cls; | 108 | struct ShutdownContext *shutdown_ctx = cls; |
109 | const struct GNUNET_ARM_ResultMessage *rmsg; | ||
108 | 110 | ||
109 | if ((msg == NULL) && (shutdown_ctx->confirmed != GNUNET_YES)) | 111 | if (msg == NULL) |
110 | { | ||
111 | #if DEBUG_ARM | ||
112 | /* Means the other side closed the connection and never confirmed a shutdown */ | ||
113 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Service handle shutdown before ACK!\n"); | ||
114 | #endif | ||
115 | if (shutdown_ctx->cont != NULL) | ||
116 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR); | ||
117 | GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); | ||
118 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); | ||
119 | GNUNET_free (shutdown_ctx); | ||
120 | } | ||
121 | else if ((msg == NULL) && (shutdown_ctx->confirmed == GNUNET_YES)) | ||
122 | { | 112 | { |
123 | #if DEBUG_ARM | ||
124 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Service shutdown complete.\n"); | ||
125 | #endif | ||
126 | if (shutdown_ctx->cont != NULL) | 113 | if (shutdown_ctx->cont != NULL) |
127 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_NO); | 114 | { |
128 | 115 | if (shutdown_ctx->confirmed == GNUNET_ARM_PROCESS_SHUTDOWN) | |
116 | { | ||
117 | /* shutdown is now complete, as we waited for the network disconnect... */ | ||
118 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_ARM_PROCESS_DOWN); | ||
119 | } | ||
120 | else | ||
121 | { | ||
122 | /* communication error */ | ||
123 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR); | ||
124 | } | ||
125 | } | ||
129 | GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); | 126 | GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); |
130 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); | 127 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); |
131 | GNUNET_free (shutdown_ctx); | 128 | GNUNET_free (shutdown_ctx); |
129 | return; | ||
132 | } | 130 | } |
133 | else | 131 | if (ntohs (msg->size) == |
132 | sizeof (struct GNUNET_ARM_ResultMessage)) | ||
134 | { | 133 | { |
135 | GNUNET_assert (ntohs (msg->size) == sizeof (struct GNUNET_MessageHeader)); | 134 | rmsg = (const struct GNUNET_ARM_ResultMessage*) msg; |
136 | switch (ntohs (msg->type)) | 135 | shutdown_ctx->confirmed = (enum GNUNET_ARM_ProcessStatus) ntohl (rmsg->status); |
136 | if (shutdown_ctx->confirmed != GNUNET_ARM_PROCESS_SHUTDOWN) | ||
137 | { | 137 | { |
138 | case GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN_ACK: | 138 | /* ARM is not shutting down, well, report the error and be done with it... */ |
139 | #if DEBUG_ARM | 139 | shutdown_ctx->cont (shutdown_ctx->cont_cls, shutdown_ctx->confirmed); |
140 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
141 | "Received confirmation for service shutdown.\n"); | ||
142 | #endif | ||
143 | shutdown_ctx->confirmed = GNUNET_YES; | ||
144 | GNUNET_CLIENT_receive (shutdown_ctx->sock, &service_shutdown_handler, | ||
145 | shutdown_ctx, GNUNET_TIME_UNIT_FOREVER_REL); | ||
146 | break; | ||
147 | default: | ||
148 | #if DEBUG_ARM | ||
149 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Service shutdown refused!\n"); | ||
150 | #endif | ||
151 | if (shutdown_ctx->cont != NULL) | ||
152 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_YES); | ||
153 | |||
154 | GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); | 140 | GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); |
155 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); | 141 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); |
156 | GNUNET_free (shutdown_ctx); | 142 | GNUNET_free (shutdown_ctx); |
157 | break; | 143 | return; |
158 | } | 144 | } |
159 | } | 145 | } |
146 | GNUNET_CLIENT_receive (shutdown_ctx->sock, &service_shutdown_handler, | ||
147 | shutdown_ctx, GNUNET_TIME_UNIT_FOREVER_REL); | ||
160 | } | 148 | } |
161 | 149 | ||
150 | |||
162 | /** | 151 | /** |
163 | * Shutting down took too long, cancel receive and return error. | 152 | * Shutting down took too long, cancel receive and return error. |
164 | * | 153 | * |
165 | * @param cls closure | 154 | * @param cls closure |
166 | * @param tc context information (why was this task triggered now) | 155 | * @param tc context information (why was this task triggered now) |
167 | */ | 156 | */ |
168 | void | 157 | static void |
169 | service_shutdown_cancel (void *cls, | 158 | service_shutdown_cancel (void *cls, |
170 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 159 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
171 | { | 160 | { |
172 | struct ShutdownContext *shutdown_ctx = cls; | 161 | struct ShutdownContext *shutdown_ctx = cls; |
173 | 162 | ||
174 | #if DEBUG_ARM | 163 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_ARM_PROCESS_COMMUNICATION_TIMEOUT); |
175 | LOG (GNUNET_ERROR_TYPE_DEBUG, "service_shutdown_cancel called!\n"); | ||
176 | #endif | ||
177 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR); | ||
178 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); | 164 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); |
179 | GNUNET_free (shutdown_ctx); | 165 | GNUNET_free (shutdown_ctx); |
180 | } | 166 | } |
@@ -196,21 +182,21 @@ write_shutdown (void *cls, size_t size, void *buf) | |||
196 | struct ShutdownContext *shutdown_ctx = cls; | 182 | struct ShutdownContext *shutdown_ctx = cls; |
197 | 183 | ||
198 | if (size < sizeof (struct GNUNET_MessageHeader)) | 184 | if (size < sizeof (struct GNUNET_MessageHeader)) |
199 | { | 185 | { |
200 | LOG (GNUNET_ERROR_TYPE_WARNING, | 186 | LOG (GNUNET_ERROR_TYPE_WARNING, |
201 | _("Failed to transmit shutdown request to client.\n")); | 187 | _("Failed to transmit shutdown request to client.\n")); |
202 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR); | 188 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR); |
203 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); | 189 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); |
204 | GNUNET_free (shutdown_ctx); | 190 | GNUNET_free (shutdown_ctx); |
205 | return 0; /* client disconnected */ | 191 | return 0; /* client disconnected */ |
206 | } | 192 | } |
207 | 193 | ||
208 | GNUNET_CLIENT_receive (shutdown_ctx->sock, &service_shutdown_handler, | 194 | GNUNET_CLIENT_receive (shutdown_ctx->sock, &service_shutdown_handler, |
209 | shutdown_ctx, GNUNET_TIME_UNIT_FOREVER_REL); | 195 | shutdown_ctx, GNUNET_TIME_UNIT_FOREVER_REL); |
210 | shutdown_ctx->cancel_task = | 196 | shutdown_ctx->cancel_task = |
211 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining | 197 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining |
212 | (shutdown_ctx->timeout), | 198 | (shutdown_ctx->timeout), |
213 | &service_shutdown_cancel, shutdown_ctx); | 199 | &service_shutdown_cancel, shutdown_ctx); |
214 | msg = (struct GNUNET_MessageHeader *) buf; | 200 | msg = (struct GNUNET_MessageHeader *) buf; |
215 | msg->type = htons (GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN); | 201 | msg->type = htons (GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN); |
216 | msg->size = htons (sizeof (struct GNUNET_MessageHeader)); | 202 | msg->size = htons (sizeof (struct GNUNET_MessageHeader)); |
@@ -233,8 +219,8 @@ write_shutdown (void *cls, size_t size, void *buf) | |||
233 | */ | 219 | */ |
234 | static void | 220 | static void |
235 | arm_service_shutdown (struct GNUNET_CLIENT_Connection *sock, | 221 | arm_service_shutdown (struct GNUNET_CLIENT_Connection *sock, |
236 | struct GNUNET_TIME_Relative timeout, | 222 | struct GNUNET_TIME_Relative timeout, |
237 | GNUNET_CLIENT_ShutdownTask cont, void *cont_cls) | 223 | GNUNET_CLIENT_ShutdownTask cont, void *cont_cls) |
238 | { | 224 | { |
239 | struct ShutdownContext *shutdown_ctx; | 225 | struct ShutdownContext *shutdown_ctx; |
240 | 226 | ||
@@ -243,10 +229,12 @@ arm_service_shutdown (struct GNUNET_CLIENT_Connection *sock, | |||
243 | shutdown_ctx->cont_cls = cont_cls; | 229 | shutdown_ctx->cont_cls = cont_cls; |
244 | shutdown_ctx->sock = sock; | 230 | shutdown_ctx->sock = sock; |
245 | shutdown_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); | 231 | shutdown_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); |
232 | shutdown_ctx->confirmed = GNUNET_ARM_PROCESS_COMMUNICATION_ERROR; | ||
233 | /* FIXME: store return value? */ | ||
246 | GNUNET_CLIENT_notify_transmit_ready (sock, | 234 | GNUNET_CLIENT_notify_transmit_ready (sock, |
247 | sizeof (struct GNUNET_MessageHeader), | 235 | sizeof (struct GNUNET_MessageHeader), |
248 | timeout, GNUNET_YES, &write_shutdown, | 236 | timeout, GNUNET_YES, &write_shutdown, |
249 | shutdown_ctx); | 237 | shutdown_ctx); |
250 | } | 238 | } |
251 | 239 | ||
252 | 240 | ||
@@ -262,7 +250,7 @@ arm_service_shutdown (struct GNUNET_CLIENT_Connection *sock, | |||
262 | */ | 250 | */ |
263 | struct GNUNET_ARM_Handle * | 251 | struct GNUNET_ARM_Handle * |
264 | GNUNET_ARM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | 252 | GNUNET_ARM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, |
265 | const char *service) | 253 | const char *service) |
266 | { | 254 | { |
267 | struct GNUNET_ARM_Handle *ret; | 255 | struct GNUNET_ARM_Handle *ret; |
268 | 256 | ||
@@ -286,6 +274,7 @@ GNUNET_ARM_disconnect (struct GNUNET_ARM_Handle *h) | |||
286 | GNUNET_free (h); | 274 | GNUNET_free (h); |
287 | } | 275 | } |
288 | 276 | ||
277 | |||
289 | struct ARM_ShutdownContext | 278 | struct ARM_ShutdownContext |
290 | { | 279 | { |
291 | /** | 280 | /** |
@@ -300,7 +289,6 @@ struct ARM_ShutdownContext | |||
300 | }; | 289 | }; |
301 | 290 | ||
302 | 291 | ||
303 | |||
304 | /** | 292 | /** |
305 | * Internal state for a request with ARM. | 293 | * Internal state for a request with ARM. |
306 | */ | 294 | */ |
@@ -357,17 +345,17 @@ arm_service_report (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
357 | char *lopostfix; | 345 | char *lopostfix; |
358 | 346 | ||
359 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) | 347 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) |
360 | { | 348 | { |
361 | #if DEBUG_ARM | 349 | #if DEBUG_ARM |
362 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Looks like `%s' is already running.\n", | 350 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Looks like `%s' is already running.\n", |
363 | "gnunet-service-arm"); | 351 | "gnunet-service-arm"); |
364 | #endif | 352 | #endif |
365 | /* arm is running! */ | 353 | /* arm is running! */ |
366 | if (pos->callback != NULL) | 354 | if (pos->callback != NULL) |
367 | pos->callback (pos->cls, GNUNET_YES); | 355 | pos->callback (pos->cls, GNUNET_ARM_PROCESS_ALREADY_RUNNING); |
368 | GNUNET_free (pos); | 356 | GNUNET_free (pos); |
369 | return; | 357 | return; |
370 | } | 358 | } |
371 | #if DEBUG_ARM | 359 | #if DEBUG_ARM |
372 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 360 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
373 | "Looks like `%s' is not running, will start it.\n", | 361 | "Looks like `%s' is not running, will start it.\n", |
@@ -375,73 +363,81 @@ arm_service_report (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
375 | #endif | 363 | #endif |
376 | if (GNUNET_OK != | 364 | if (GNUNET_OK != |
377 | GNUNET_CONFIGURATION_get_value_string (pos->h->cfg, "arm", "PREFIX", | 365 | GNUNET_CONFIGURATION_get_value_string (pos->h->cfg, "arm", "PREFIX", |
378 | &loprefix)) | 366 | &loprefix)) |
379 | loprefix = GNUNET_strdup (""); | 367 | loprefix = GNUNET_strdup (""); |
380 | if (GNUNET_OK != | 368 | if (GNUNET_OK != |
381 | GNUNET_CONFIGURATION_get_value_string (pos->h->cfg, "arm", "OPTIONS", | 369 | GNUNET_CONFIGURATION_get_value_string (pos->h->cfg, "arm", "OPTIONS", |
382 | &lopostfix)) | 370 | &lopostfix)) |
383 | lopostfix = GNUNET_strdup (""); | 371 | lopostfix = GNUNET_strdup (""); |
384 | if (GNUNET_OK != | 372 | if (GNUNET_OK != |
385 | GNUNET_CONFIGURATION_get_value_string (pos->h->cfg, "arm", "BINARY", | 373 | GNUNET_CONFIGURATION_get_value_string (pos->h->cfg, "arm", "BINARY", |
386 | &binary)) | 374 | &binary)) |
387 | { | 375 | { |
388 | LOG (GNUNET_ERROR_TYPE_WARNING, | 376 | LOG (GNUNET_ERROR_TYPE_WARNING, |
389 | _("Configuration failes to specify option `%s' in section `%s'!\n"), | 377 | _ |
390 | "BINARY", "arm"); | 378 | ("Configuration failes to specify option `%s' in section `%s'!\n"), |
391 | if (pos->callback != NULL) | 379 | "BINARY", "arm"); |
392 | pos->callback (pos->cls, GNUNET_SYSERR); | 380 | if (pos->callback != NULL) |
393 | GNUNET_free (pos); | 381 | pos->callback (pos->cls, GNUNET_ARM_PROCESS_UNKNOWN); |
394 | GNUNET_free (loprefix); | 382 | GNUNET_free (pos); |
395 | GNUNET_free (lopostfix); | 383 | GNUNET_free (loprefix); |
396 | return; | 384 | GNUNET_free (lopostfix); |
397 | } | 385 | return; |
386 | } | ||
398 | if (GNUNET_OK != | 387 | if (GNUNET_OK != |
399 | GNUNET_CONFIGURATION_get_value_filename (pos->h->cfg, "arm", "CONFIG", | 388 | GNUNET_CONFIGURATION_get_value_filename (pos->h->cfg, "arm", "CONFIG", |
400 | &config)) | 389 | &config)) |
401 | { | 390 | { |
402 | LOG (GNUNET_ERROR_TYPE_WARNING, | 391 | LOG (GNUNET_ERROR_TYPE_WARNING, |
403 | _("Configuration fails to specify option `%s' in section `%s'!\n"), | 392 | _("Configuration fails to specify option `%s' in section `%s'!\n"), |
404 | "CONFIG", "arm"); | 393 | "CONFIG", "arm"); |
405 | if (pos->callback != NULL) | 394 | if (pos->callback != NULL) |
406 | pos->callback (pos->cls, GNUNET_SYSERR); | 395 | pos->callback (pos->cls, GNUNET_ARM_PROCESS_UNKNOWN); |
407 | GNUNET_free (binary); | 396 | GNUNET_free (binary); |
408 | GNUNET_free (pos); | 397 | GNUNET_free (pos); |
409 | GNUNET_free (loprefix); | 398 | GNUNET_free (loprefix); |
410 | GNUNET_free (lopostfix); | 399 | GNUNET_free (lopostfix); |
411 | return; | 400 | return; |
412 | } | 401 | } |
413 | if ((GNUNET_YES == GNUNET_CONFIGURATION_have_value (pos->h->cfg, "TESTING", "WEAKRANDOM")) && (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (pos->h->cfg, "TESTING", "WEAKRANDOM")) && (GNUNET_NO == GNUNET_CONFIGURATION_have_value (pos->h->cfg, "TESTING", "HOSTFILE")) /* Means we are ONLY running locally */ | 402 | if ((GNUNET_YES == |
414 | ) | 403 | GNUNET_CONFIGURATION_have_value (pos->h->cfg, "TESTING", "WEAKRANDOM")) |
415 | { | 404 | && (GNUNET_YES == |
416 | /* we're clearly running a test, don't daemonize */ | 405 | GNUNET_CONFIGURATION_get_value_yesno (pos->h->cfg, "TESTING", |
417 | proc = do_start_process (NULL, loprefix, binary, "-c", config, | 406 | "WEAKRANDOM")) |
407 | && (GNUNET_NO == | ||
408 | GNUNET_CONFIGURATION_have_value (pos->h->cfg, "TESTING", | ||
409 | "HOSTFILE"))) | ||
410 | { | ||
411 | /* Means we are ONLY running locally */ | ||
412 | /* we're clearly running a test, don't daemonize */ | ||
413 | proc = do_start_process (NULL, loprefix, binary, "-c", config, | ||
418 | #if DEBUG_ARM | 414 | #if DEBUG_ARM |
419 | "-L", "DEBUG", | 415 | "-L", "DEBUG", |
420 | #endif | 416 | #endif |
421 | /* no daemonization! */ | 417 | /* no daemonization! */ |
422 | lopostfix, NULL); | 418 | lopostfix, NULL); |
423 | } | 419 | } |
424 | else | 420 | else |
425 | { | 421 | { |
426 | proc = do_start_process (NULL, loprefix, binary, "-c", config, | 422 | proc = do_start_process (NULL, loprefix, binary, "-c", config, |
427 | #if DEBUG_ARM | 423 | #if DEBUG_ARM |
428 | "-L", "DEBUG", | 424 | "-L", "DEBUG", |
429 | #endif | 425 | #endif |
430 | "-d", lopostfix, NULL); | 426 | "-d", lopostfix, NULL); |
431 | } | 427 | } |
432 | GNUNET_free (binary); | 428 | GNUNET_free (binary); |
433 | GNUNET_free (config); | 429 | GNUNET_free (config); |
434 | GNUNET_free (loprefix); | 430 | GNUNET_free (loprefix); |
435 | GNUNET_free (lopostfix); | 431 | GNUNET_free (lopostfix); |
436 | if (proc == NULL) | 432 | if (proc == NULL) |
437 | { | 433 | { |
438 | if (pos->callback != NULL) | 434 | if (pos->callback != NULL) |
439 | pos->callback (pos->cls, GNUNET_SYSERR); | 435 | pos->callback (pos->cls, GNUNET_ARM_PROCESS_FAILURE); |
440 | GNUNET_free (pos); | 436 | GNUNET_free (pos); |
441 | return; | 437 | return; |
442 | } | 438 | } |
443 | if (pos->callback != NULL) | 439 | if (pos->callback != NULL) |
444 | pos->callback (pos->cls, GNUNET_YES); | 440 | pos->callback (pos->cls, GNUNET_ARM_PROCESS_STARTING); |
445 | GNUNET_free (proc); | 441 | GNUNET_free (proc); |
446 | GNUNET_free (pos); | 442 | GNUNET_free (pos); |
447 | } | 443 | } |
@@ -458,45 +454,34 @@ static void | |||
458 | handle_response (void *cls, const struct GNUNET_MessageHeader *msg) | 454 | handle_response (void *cls, const struct GNUNET_MessageHeader *msg) |
459 | { | 455 | { |
460 | struct RequestContext *sc = cls; | 456 | struct RequestContext *sc = cls; |
461 | int ret; | 457 | const struct GNUNET_ARM_ResultMessage *res; |
458 | enum GNUNET_ARM_ProcessStatus status; | ||
462 | 459 | ||
463 | if (msg == NULL) | 460 | if ((msg == NULL) || |
464 | { | 461 | (ntohs (msg->size) != sizeof (struct GNUNET_ARM_ResultMessage))) |
465 | LOG (GNUNET_ERROR_TYPE_WARNING, | 462 | { |
466 | _ | 463 | LOG (GNUNET_ERROR_TYPE_WARNING, |
467 | ("Error receiving response to `%s' request from ARM for service `%s'\n"), | 464 | _ |
468 | (sc->type == GNUNET_MESSAGE_TYPE_ARM_START) ? "START" : "STOP", | 465 | ("Error receiving response to `%s' request from ARM for service `%s'\n"), |
469 | (const char *) &sc[1]); | 466 | (sc->type == GNUNET_MESSAGE_TYPE_ARM_START) ? "START" : "STOP", |
470 | GNUNET_CLIENT_disconnect (sc->h->client, GNUNET_NO); | 467 | (const char *) &sc[1]); |
471 | sc->h->client = GNUNET_CLIENT_connect ("arm", sc->h->cfg); | 468 | GNUNET_CLIENT_disconnect (sc->h->client, GNUNET_NO); |
472 | GNUNET_assert (NULL != sc->h->client); | 469 | sc->h->client = GNUNET_CLIENT_connect ("arm", sc->h->cfg); |
473 | if (sc->callback != NULL) | 470 | GNUNET_assert (NULL != sc->h->client); |
474 | sc->callback (sc->cls, GNUNET_SYSERR); | 471 | if (sc->callback != NULL) |
475 | GNUNET_free (sc); | 472 | sc->callback (sc->cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR); |
476 | return; | 473 | GNUNET_free (sc); |
477 | } | 474 | return; |
475 | } | ||
476 | res = (const struct GNUNET_ARM_ResultMessage *) msg; | ||
478 | #if DEBUG_ARM | 477 | #if DEBUG_ARM |
479 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 478 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
480 | "Received response from ARM for service `%s': %u\n", | 479 | "Received response from ARM for service `%s': %u\n", |
481 | (const char *) &sc[1], ntohs (msg->type)); | 480 | (const char *) &sc[1], ntohs (msg->type)); |
482 | #endif | 481 | #endif |
483 | switch (ntohs (msg->type)) | 482 | status = (enum GNUNET_ARM_ProcessStatus) ntohl (res->status); |
484 | { | ||
485 | case GNUNET_MESSAGE_TYPE_ARM_IS_UP: | ||
486 | ret = GNUNET_YES; | ||
487 | break; | ||
488 | case GNUNET_MESSAGE_TYPE_ARM_IS_DOWN: | ||
489 | ret = GNUNET_NO; | ||
490 | break; | ||
491 | case GNUNET_MESSAGE_TYPE_ARM_IS_UNKNOWN: | ||
492 | ret = GNUNET_SYSERR; | ||
493 | break; | ||
494 | default: | ||
495 | GNUNET_break (0); | ||
496 | ret = GNUNET_SYSERR; | ||
497 | } | ||
498 | if (sc->callback != NULL) | 483 | if (sc->callback != NULL) |
499 | sc->callback (sc->cls, ret); | 484 | sc->callback (sc->cls, status); |
500 | GNUNET_free (sc); | 485 | GNUNET_free (sc); |
501 | } | 486 | } |
502 | 487 | ||
@@ -513,8 +498,8 @@ handle_response (void *cls, const struct GNUNET_MessageHeader *msg) | |||
513 | */ | 498 | */ |
514 | static void | 499 | static void |
515 | change_service (struct GNUNET_ARM_Handle *h, const char *service_name, | 500 | change_service (struct GNUNET_ARM_Handle *h, const char *service_name, |
516 | struct GNUNET_TIME_Relative timeout, GNUNET_ARM_Callback cb, | 501 | struct GNUNET_TIME_Relative timeout, GNUNET_ARM_Callback cb, |
517 | void *cb_cls, uint16_t type) | 502 | void *cb_cls, uint16_t type) |
518 | { | 503 | { |
519 | struct RequestContext *sctx; | 504 | struct RequestContext *sctx; |
520 | size_t slen; | 505 | size_t slen; |
@@ -523,16 +508,16 @@ change_service (struct GNUNET_ARM_Handle *h, const char *service_name, | |||
523 | slen = strlen (service_name) + 1; | 508 | slen = strlen (service_name) + 1; |
524 | if (slen + sizeof (struct GNUNET_MessageHeader) >= | 509 | if (slen + sizeof (struct GNUNET_MessageHeader) >= |
525 | GNUNET_SERVER_MAX_MESSAGE_SIZE) | 510 | GNUNET_SERVER_MAX_MESSAGE_SIZE) |
526 | { | 511 | { |
527 | GNUNET_break (0); | 512 | GNUNET_break (0); |
528 | if (cb != NULL) | 513 | if (cb != NULL) |
529 | cb (cb_cls, GNUNET_NO); | 514 | cb (cb_cls, GNUNET_NO); |
530 | return; | 515 | return; |
531 | } | 516 | } |
532 | #if DEBUG_ARM | 517 | #if DEBUG_ARM |
533 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 518 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
534 | (type == | 519 | (type == |
535 | GNUNET_MESSAGE_TYPE_ARM_START) ? | 520 | GNUNET_MESSAGE_TYPE_ARM_START) ? |
536 | _("Requesting start of service `%s'.\n") : | 521 | _("Requesting start of service `%s'.\n") : |
537 | _("Requesting termination of service `%s'.\n"), service_name); | 522 | _("Requesting termination of service `%s'.\n"), service_name); |
538 | #endif | 523 | #endif |
@@ -549,22 +534,23 @@ change_service (struct GNUNET_ARM_Handle *h, const char *service_name, | |||
549 | memcpy (&msg[1], service_name, slen); | 534 | memcpy (&msg[1], service_name, slen); |
550 | if (GNUNET_OK != | 535 | if (GNUNET_OK != |
551 | GNUNET_CLIENT_transmit_and_get_response (sctx->h->client, msg, | 536 | GNUNET_CLIENT_transmit_and_get_response (sctx->h->client, msg, |
552 | GNUNET_TIME_absolute_get_remaining | 537 | GNUNET_TIME_absolute_get_remaining |
553 | (sctx->timeout), GNUNET_YES, | 538 | (sctx->timeout), GNUNET_YES, |
554 | &handle_response, sctx)) | 539 | &handle_response, sctx)) |
555 | { | 540 | { |
556 | LOG (GNUNET_ERROR_TYPE_WARNING, | 541 | LOG (GNUNET_ERROR_TYPE_WARNING, |
557 | (type == | 542 | (type == |
558 | GNUNET_MESSAGE_TYPE_ARM_START) ? | 543 | GNUNET_MESSAGE_TYPE_ARM_START) ? |
559 | _("Error while trying to transmit request to start `%s' to ARM\n") : | 544 | _("Error while trying to transmit request to start `%s' to ARM\n") |
560 | _("Error while trying to transmit request to stop `%s' to ARM\n"), | 545 | : |
561 | (const char *) &service_name); | 546 | _("Error while trying to transmit request to stop `%s' to ARM\n"), |
562 | if (cb != NULL) | 547 | (const char *) &service_name); |
563 | cb (cb_cls, GNUNET_SYSERR); | 548 | if (cb != NULL) |
564 | GNUNET_free (sctx); | 549 | cb (cb_cls, GNUNET_SYSERR); |
565 | GNUNET_free (msg); | 550 | GNUNET_free (sctx); |
566 | return; | 551 | GNUNET_free (msg); |
567 | } | 552 | return; |
553 | } | ||
568 | GNUNET_free (msg); | 554 | GNUNET_free (msg); |
569 | } | 555 | } |
570 | 556 | ||
@@ -579,9 +565,10 @@ change_service (struct GNUNET_ARM_Handle *h, const char *service_name, | |||
579 | * @param cb_cls closure for callback | 565 | * @param cb_cls closure for callback |
580 | */ | 566 | */ |
581 | void | 567 | void |
582 | GNUNET_ARM_start_service (struct GNUNET_ARM_Handle *h, const char *service_name, | 568 | GNUNET_ARM_start_service (struct GNUNET_ARM_Handle *h, |
583 | struct GNUNET_TIME_Relative timeout, | 569 | const char *service_name, |
584 | GNUNET_ARM_Callback cb, void *cb_cls) | 570 | struct GNUNET_TIME_Relative timeout, |
571 | GNUNET_ARM_Callback cb, void *cb_cls) | ||
585 | { | 572 | { |
586 | struct RequestContext *sctx; | 573 | struct RequestContext *sctx; |
587 | struct GNUNET_CLIENT_Connection *client; | 574 | struct GNUNET_CLIENT_Connection *client; |
@@ -593,47 +580,47 @@ GNUNET_ARM_start_service (struct GNUNET_ARM_Handle *h, const char *service_name, | |||
593 | (unsigned long long) timeout.rel_value); | 580 | (unsigned long long) timeout.rel_value); |
594 | #endif | 581 | #endif |
595 | if (0 == strcasecmp ("arm", service_name)) | 582 | if (0 == strcasecmp ("arm", service_name)) |
596 | { | 583 | { |
597 | slen = strlen ("arm") + 1; | 584 | slen = strlen ("arm") + 1; |
598 | sctx = GNUNET_malloc (sizeof (struct RequestContext) + slen); | 585 | sctx = GNUNET_malloc (sizeof (struct RequestContext) + slen); |
599 | sctx->h = h; | 586 | sctx->h = h; |
600 | sctx->callback = cb; | 587 | sctx->callback = cb; |
601 | sctx->cls = cb_cls; | 588 | sctx->cls = cb_cls; |
602 | sctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); | 589 | sctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); |
603 | memcpy (&sctx[1], service_name, slen); | 590 | memcpy (&sctx[1], service_name, slen); |
604 | GNUNET_CLIENT_service_test ("arm", h->cfg, timeout, &arm_service_report, | 591 | GNUNET_CLIENT_service_test ("arm", h->cfg, timeout, &arm_service_report, |
605 | sctx); | 592 | sctx); |
606 | return; | 593 | return; |
607 | } | 594 | } |
608 | if (h->client == NULL) | 595 | if (h->client == NULL) |
609 | { | ||
610 | client = GNUNET_CLIENT_connect ("arm", h->cfg); | ||
611 | if (client == NULL) | ||
612 | { | 596 | { |
597 | client = GNUNET_CLIENT_connect ("arm", h->cfg); | ||
598 | if (client == NULL) | ||
599 | { | ||
600 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
601 | "arm_api, GNUNET_CLIENT_connect returned NULL\n"); | ||
602 | cb (cb_cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR); | ||
603 | return; | ||
604 | } | ||
613 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 605 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
614 | "arm_api, GNUNET_CLIENT_connect returned NULL\n"); | 606 | "arm_api, GNUNET_CLIENT_connect returned non-NULL\n"); |
615 | cb (cb_cls, GNUNET_SYSERR); | 607 | h->client = client; |
616 | return; | ||
617 | } | 608 | } |
618 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
619 | "arm_api, GNUNET_CLIENT_connect returned non-NULL\n"); | ||
620 | h->client = client; | ||
621 | } | ||
622 | LOG (GNUNET_ERROR_TYPE_DEBUG, "arm_api, h->client non-NULL\n"); | 609 | LOG (GNUNET_ERROR_TYPE_DEBUG, "arm_api, h->client non-NULL\n"); |
623 | change_service (h, service_name, timeout, cb, cb_cls, | 610 | change_service (h, service_name, timeout, cb, cb_cls, |
624 | GNUNET_MESSAGE_TYPE_ARM_START); | 611 | GNUNET_MESSAGE_TYPE_ARM_START); |
625 | } | 612 | } |
626 | 613 | ||
614 | |||
627 | /** | 615 | /** |
628 | * Callback from the arm stop service call, indicates that the arm service | 616 | * Callback from the arm stop service call, indicates that the arm service |
629 | * is well and truly dead, won't die, or an error occurred. | 617 | * is well and truly dead, won't die, or an error occurred. |
630 | * | 618 | * |
631 | * @param cls closure for the callback | 619 | * @param cls closure for the callback |
632 | * @param reason reason for callback, GNUNET_NO if arm is shutdown | 620 | * @param reason reason for callback |
633 | * GNUNET_YES if arm remains running, and GNUNET_SYSERR on error | ||
634 | */ | 621 | */ |
635 | void | 622 | static void |
636 | arm_shutdown_callback (void *cls, int reason) | 623 | arm_shutdown_callback (void *cls, enum GNUNET_ARM_ProcessStatus reason) |
637 | { | 624 | { |
638 | struct ARM_ShutdownContext *arm_shutdown_ctx = cls; | 625 | struct ARM_ShutdownContext *arm_shutdown_ctx = cls; |
639 | 626 | ||
@@ -654,9 +641,10 @@ arm_shutdown_callback (void *cls, int reason) | |||
654 | * @param cb_cls closure for callback | 641 | * @param cb_cls closure for callback |
655 | */ | 642 | */ |
656 | void | 643 | void |
657 | GNUNET_ARM_stop_service (struct GNUNET_ARM_Handle *h, const char *service_name, | 644 | GNUNET_ARM_stop_service (struct GNUNET_ARM_Handle *h, |
658 | struct GNUNET_TIME_Relative timeout, | 645 | const char *service_name, |
659 | GNUNET_ARM_Callback cb, void *cb_cls) | 646 | struct GNUNET_TIME_Relative timeout, |
647 | GNUNET_ARM_Callback cb, void *cb_cls) | ||
660 | { | 648 | { |
661 | struct ARM_ShutdownContext *arm_shutdown_ctx; | 649 | struct ARM_ShutdownContext *arm_shutdown_ctx; |
662 | struct GNUNET_CLIENT_Connection *client; | 650 | struct GNUNET_CLIENT_Connection *client; |
@@ -664,27 +652,27 @@ GNUNET_ARM_stop_service (struct GNUNET_ARM_Handle *h, const char *service_name, | |||
664 | LOG (GNUNET_ERROR_TYPE_INFO, _("Stopping service `%s' within %llu ms\n"), | 652 | LOG (GNUNET_ERROR_TYPE_INFO, _("Stopping service `%s' within %llu ms\n"), |
665 | service_name, (unsigned long long) timeout.rel_value); | 653 | service_name, (unsigned long long) timeout.rel_value); |
666 | if (h->client == NULL) | 654 | if (h->client == NULL) |
667 | { | ||
668 | client = GNUNET_CLIENT_connect ("arm", h->cfg); | ||
669 | if (client == NULL) | ||
670 | { | 655 | { |
671 | cb (cb_cls, GNUNET_SYSERR); | 656 | client = GNUNET_CLIENT_connect ("arm", h->cfg); |
672 | return; | 657 | if (client == NULL) |
658 | { | ||
659 | cb (cb_cls, GNUNET_SYSERR); | ||
660 | return; | ||
661 | } | ||
662 | h->client = client; | ||
673 | } | 663 | } |
674 | h->client = client; | ||
675 | } | ||
676 | if (0 == strcasecmp ("arm", service_name)) | 664 | if (0 == strcasecmp ("arm", service_name)) |
677 | { | 665 | { |
678 | arm_shutdown_ctx = GNUNET_malloc (sizeof (struct ARM_ShutdownContext)); | 666 | arm_shutdown_ctx = GNUNET_malloc (sizeof (struct ARM_ShutdownContext)); |
679 | arm_shutdown_ctx->cb = cb; | 667 | arm_shutdown_ctx->cb = cb; |
680 | arm_shutdown_ctx->cb_cls = cb_cls; | 668 | arm_shutdown_ctx->cb_cls = cb_cls; |
681 | arm_service_shutdown (h->client, timeout, &arm_shutdown_callback, | 669 | arm_service_shutdown (h->client, timeout, &arm_shutdown_callback, |
682 | arm_shutdown_ctx); | 670 | arm_shutdown_ctx); |
683 | h->client = NULL; | 671 | h->client = NULL; |
684 | return; | 672 | return; |
685 | } | 673 | } |
686 | change_service (h, service_name, timeout, cb, cb_cls, | 674 | change_service (h, service_name, timeout, cb, cb_cls, |
687 | GNUNET_MESSAGE_TYPE_ARM_STOP); | 675 | GNUNET_MESSAGE_TYPE_ARM_STOP); |
688 | } | 676 | } |
689 | 677 | ||
690 | 678 | ||
diff --git a/src/arm/do_start_process.c b/src/arm/do_start_process.c index f4d3424ff..fd7fc17ed 100644 --- a/src/arm/do_start_process.c +++ b/src/arm/do_start_process.c | |||
@@ -10,10 +10,10 @@ | |||
10 | * @param lsocks array of listen sockets to dup starting at fd3 (systemd-style), or NULL | 10 | * @param lsocks array of listen sockets to dup starting at fd3 (systemd-style), or NULL |
11 | * @param first_arg first argument for argv (may be an empty string) | 11 | * @param first_arg first argument for argv (may be an empty string) |
12 | * @param ... more arguments, NULL terminated | 12 | * @param ... more arguments, NULL terminated |
13 | * @return PID of the started process, -1 on error | 13 | * @return handle of the started process, NULL on error |
14 | */ | 14 | */ |
15 | static struct GNUNET_OS_Process * | 15 | static struct GNUNET_OS_Process * |
16 | do_start_process (const SOCKTYPE *lsocks, const char *first_arg, ...) | 16 | do_start_process (const SOCKTYPE * lsocks, const char *first_arg, ...) |
17 | { | 17 | { |
18 | va_list ap; | 18 | va_list ap; |
19 | char **argv; | 19 | char **argv; |
@@ -35,20 +35,20 @@ do_start_process (const SOCKTYPE *lsocks, const char *first_arg, ...) | |||
35 | /* *INDENT-ON* */ | 35 | /* *INDENT-ON* */ |
36 | rpos = arg; | 36 | rpos = arg; |
37 | while ('\0' != *rpos) | 37 | while ('\0' != *rpos) |
38 | { | ||
39 | if (' ' == *rpos) | ||
40 | { | 38 | { |
41 | if (last != NULL) | 39 | if (' ' == *rpos) |
42 | argv_size++; | 40 | { |
43 | last = NULL; | 41 | if (last != NULL) |
44 | while (' ' == *rpos) | 42 | argv_size++; |
45 | rpos++; | 43 | last = NULL; |
44 | while (' ' == *rpos) | ||
45 | rpos++; | ||
46 | } | ||
47 | if ((last == NULL) && (*rpos != '\0')) | ||
48 | last = rpos; | ||
49 | if (*rpos != '\0') | ||
50 | rpos++; | ||
46 | } | 51 | } |
47 | if ((last == NULL) && (*rpos != '\0')) | ||
48 | last = rpos; | ||
49 | if (*rpos != '\0') | ||
50 | rpos++; | ||
51 | } | ||
52 | if (last != NULL) | 52 | if (last != NULL) |
53 | argv_size++; | 53 | argv_size++; |
54 | /* *INDENT-OFF* */ | 54 | /* *INDENT-OFF* */ |
@@ -69,22 +69,22 @@ do_start_process (const SOCKTYPE *lsocks, const char *first_arg, ...) | |||
69 | cp = GNUNET_strdup (arg); | 69 | cp = GNUNET_strdup (arg); |
70 | pos = cp; | 70 | pos = cp; |
71 | while ('\0' != *pos) | 71 | while ('\0' != *pos) |
72 | { | ||
73 | if (' ' == *pos) | ||
74 | { | 72 | { |
75 | *pos = '\0'; | 73 | if (' ' == *pos) |
76 | if (last != NULL) | 74 | { |
77 | argv[argv_size++] = GNUNET_strdup (last); | 75 | *pos = '\0'; |
78 | last = NULL; | 76 | if (last != NULL) |
79 | pos++; | 77 | argv[argv_size++] = GNUNET_strdup (last); |
80 | while (' ' == *pos) | 78 | last = NULL; |
81 | pos++; | 79 | pos++; |
80 | while (' ' == *pos) | ||
81 | pos++; | ||
82 | } | ||
83 | if ((last == NULL) && (*pos != '\0')) | ||
84 | last = pos; | ||
85 | if (*pos != '\0') | ||
86 | pos++; | ||
82 | } | 87 | } |
83 | if ((last == NULL) && (*pos != '\0')) | ||
84 | last = pos; | ||
85 | if (*pos != '\0') | ||
86 | pos++; | ||
87 | } | ||
88 | if (last != NULL) | 88 | if (last != NULL) |
89 | argv[argv_size++] = GNUNET_strdup (last); | 89 | argv[argv_size++] = GNUNET_strdup (last); |
90 | last = NULL; | 90 | last = NULL; |
diff --git a/src/arm/gnunet-arm.c b/src/arm/gnunet-arm.c index db5687dbc..13b1fdc17 100644 --- a/src/arm/gnunet-arm.c +++ b/src/arm/gnunet-arm.c | |||
@@ -49,13 +49,6 @@ | |||
49 | #define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) | 49 | #define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) |
50 | 50 | ||
51 | /** | 51 | /** |
52 | * Timeout for starting services, very short because of the strange way start works | ||
53 | * (by checking if running before starting, so really this time is always waited on | ||
54 | * startup (annoying)). | ||
55 | */ | ||
56 | #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) | ||
57 | |||
58 | /** | ||
59 | * Set if we are to shutdown all services (including ARM). | 52 | * Set if we are to shutdown all services (including ARM). |
60 | */ | 53 | */ |
61 | static int end; | 54 | static int end; |
@@ -91,11 +84,6 @@ static char *init; | |||
91 | static char *term; | 84 | static char *term; |
92 | 85 | ||
93 | /** | 86 | /** |
94 | * Set to the name of a service to test. | ||
95 | */ | ||
96 | static char *test; | ||
97 | |||
98 | /** | ||
99 | * Set to the name of the config file used. | 87 | * Set to the name of the config file used. |
100 | */ | 88 | */ |
101 | static const char *config_file; | 89 | static const char *config_file; |
@@ -118,7 +106,7 @@ static struct GNUNET_ARM_Handle *h; | |||
118 | /** | 106 | /** |
119 | * Our configuration. | 107 | * Our configuration. |
120 | */ | 108 | */ |
121 | const struct GNUNET_CONFIGURATION_Handle *cfg; | 109 | static const struct GNUNET_CONFIGURATION_Handle *cfg; |
122 | 110 | ||
123 | /** | 111 | /** |
124 | * Processing stage that we are in. Simple counter. | 112 | * Processing stage that we are in. Simple counter. |
@@ -147,72 +135,62 @@ cps_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | |||
147 | * user and then runs the next phase in the FSM. | 135 | * user and then runs the next phase in the FSM. |
148 | * | 136 | * |
149 | * @param cls pointer to "const char*" identifying service that was manipulated | 137 | * @param cls pointer to "const char*" identifying service that was manipulated |
150 | * @param success GNUNET_OK if service is now running, GNUNET_NO if not, GNUNET_SYSERR on error | 138 | * @param result result of the operation |
151 | */ | 139 | */ |
152 | static void | 140 | static void |
153 | confirm_cb (void *cls, int success) | 141 | confirm_cb (void *cls, |
142 | enum GNUNET_ARM_ProcessStatus result) | ||
154 | { | 143 | { |
155 | const char *service = cls; | 144 | const char *service = cls; |
156 | 145 | ||
157 | switch (success) | 146 | switch (result) |
158 | { | 147 | { |
159 | case GNUNET_OK: | 148 | case GNUNET_ARM_PROCESS_UNKNOWN: |
160 | if (quiet != GNUNET_YES) | 149 | fprintf (stderr, _("Service `%s' is unknown to ARM.\n"), service); |
161 | fprintf (stdout, _("Service `%s' has been started.\n"), service); | 150 | ret = 1; |
162 | if ((phase - 1 != 2) && (phase - 1 != 3)) | ||
163 | { | ||
164 | if (quiet != GNUNET_YES) | ||
165 | fprintf (stdout, _("Failed to stop service `%s'!\n"), service); | ||
166 | ret = 1; | ||
167 | } | ||
168 | break; | 151 | break; |
169 | case GNUNET_NO: | 152 | case GNUNET_ARM_PROCESS_DOWN: |
170 | if (quiet != GNUNET_YES) | 153 | if (quiet != GNUNET_YES) |
171 | fprintf (stdout, _("Service `%s' has been stopped.\n"), service); | 154 | fprintf (stdout, _("Service `%s' has been stopped.\n"), service); |
172 | if ((phase - 1 != 0) && (phase - 1 != 1)) | ||
173 | { | ||
174 | if (quiet != GNUNET_YES) | ||
175 | fprintf (stdout, _("Failed to start service `%s'!\n"), service); | ||
176 | ret = 1; | ||
177 | } | ||
178 | break; | 155 | break; |
179 | case GNUNET_SYSERR: | 156 | case GNUNET_ARM_PROCESS_ALREADY_RUNNING: |
180 | if (quiet != GNUNET_YES) | 157 | fprintf (stderr, _("Service `%s' was already running.\n"), service); |
181 | fprintf (stdout, _("Some error communicating with service `%s'.\n"), | ||
182 | service); | ||
183 | ret = 1; | 158 | ret = 1; |
184 | break; | 159 | break; |
185 | } | 160 | case GNUNET_ARM_PROCESS_STARTING: |
186 | |||
187 | GNUNET_SCHEDULER_add_continuation (&cps_loop, NULL, | ||
188 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | ||
189 | } | ||
190 | |||
191 | |||
192 | /** | ||
193 | * Function called to confirm that a service is running (or that | ||
194 | * it is not running). | ||
195 | * | ||
196 | * @param cls pointer to "const char*" identifying service that was manipulated | ||
197 | * @param tc reason determines if service is now running | ||
198 | */ | ||
199 | static void | ||
200 | confirm_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
201 | { | ||
202 | const char *service = cls; | ||
203 | |||
204 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) | ||
205 | { | ||
206 | if (quiet != GNUNET_YES) | ||
207 | fprintf (stdout, _("Service `%s' is running.\n"), service); | ||
208 | } | ||
209 | else | ||
210 | { | ||
211 | if (quiet != GNUNET_YES) | 161 | if (quiet != GNUNET_YES) |
212 | fprintf (stdout, _("Service `%s' is not running.\n"), service); | 162 | fprintf (stdout, _("Service `%s' has been started.\n"), service); |
163 | break; | ||
164 | case GNUNET_ARM_PROCESS_ALREADY_STOPPING: | ||
165 | fprintf (stderr, _("Service `%s' was already being stopped.\n"), service); | ||
166 | ret = 1; | ||
167 | break; | ||
168 | case GNUNET_ARM_PROCESS_ALREADY_DOWN: | ||
169 | fprintf (stderr, _("Service `%s' was already not running.\n"), service); | ||
170 | ret = 1; | ||
171 | break; | ||
172 | case GNUNET_ARM_PROCESS_SHUTDOWN: | ||
173 | fprintf (stderr, _("Request ignored as ARM is shutting down.\n")); | ||
174 | ret = 1; | ||
175 | break; | ||
176 | case GNUNET_ARM_PROCESS_COMMUNICATION_ERROR: | ||
177 | fprintf (stderr, _("Error communicating with ARM service.\n")); | ||
178 | ret = 1; | ||
179 | break; | ||
180 | case GNUNET_ARM_PROCESS_COMMUNICATION_TIMEOUT: | ||
181 | fprintf (stderr, _("Timeout communicating with ARM service.\n")); | ||
182 | ret = 1; | ||
183 | break; | ||
184 | case GNUNET_ARM_PROCESS_FAILURE: | ||
185 | fprintf (stderr, _("Operation failed.\n")); | ||
186 | ret = 1; | ||
187 | break; | ||
188 | default: | ||
189 | fprintf (stderr, _("Unknown response code from ARM.\n")); | ||
190 | break; | ||
213 | } | 191 | } |
214 | GNUNET_SCHEDULER_add_continuation (&cps_loop, NULL, | 192 | GNUNET_SCHEDULER_add_continuation (&cps_loop, NULL, |
215 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | 193 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); |
216 | } | 194 | } |
217 | 195 | ||
218 | 196 | ||
@@ -230,25 +208,25 @@ run (void *cls, char *const *args, const char *cfgfile, | |||
230 | { | 208 | { |
231 | cfg = c; | 209 | cfg = c; |
232 | config_file = cfgfile; | 210 | config_file = cfgfile; |
233 | if (GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "SERVICEHOME", &dir) | 211 | if (GNUNET_CONFIGURATION_get_value_string |
234 | != GNUNET_OK) | 212 | (cfg, "PATHS", "SERVICEHOME", &dir) != GNUNET_OK) |
235 | { | 213 | { |
236 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 214 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
237 | _ | 215 | _ |
238 | ("Fatal configuration error: `%s' option in section `%s' missing.\n"), | 216 | ("Fatal configuration error: `%s' option in section `%s' missing.\n"), |
239 | "SERVICEHOME", "PATHS"); | 217 | "SERVICEHOME", "PATHS"); |
240 | return; | 218 | return; |
241 | } | 219 | } |
242 | h = GNUNET_ARM_connect (cfg, NULL); | 220 | h = GNUNET_ARM_connect (cfg, NULL); |
243 | if (h == NULL) | 221 | if (h == NULL) |
244 | { | 222 | { |
245 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 223 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
246 | _("Fatal error initializing ARM API.\n")); | 224 | _("Fatal error initializing ARM API.\n")); |
247 | ret = 1; | 225 | ret = 1; |
248 | return; | 226 | return; |
249 | } | 227 | } |
250 | GNUNET_SCHEDULER_add_continuation (&cps_loop, NULL, | 228 | GNUNET_SCHEDULER_add_continuation (&cps_loop, NULL, |
251 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | 229 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); |
252 | } | 230 | } |
253 | 231 | ||
254 | /** | 232 | /** |
@@ -260,21 +238,21 @@ static void | |||
260 | delete_files () | 238 | delete_files () |
261 | { | 239 | { |
262 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 240 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
263 | "Will attempt to remove configuration file %s and service directory %s\n", | 241 | "Will attempt to remove configuration file %s and service directory %s\n", |
264 | config_file, dir); | 242 | config_file, dir); |
265 | 243 | ||
266 | if (UNLINK (config_file) != 0) | 244 | if (UNLINK (config_file) != 0) |
267 | { | 245 | { |
268 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 246 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
269 | _("Failed to remove configuration file %s\n"), config_file); | 247 | _("Failed to remove configuration file %s\n"), config_file); |
270 | } | 248 | } |
271 | 249 | ||
272 | if (GNUNET_DISK_directory_remove (dir) != GNUNET_OK) | 250 | if (GNUNET_DISK_directory_remove (dir) != GNUNET_OK) |
273 | { | 251 | { |
274 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 252 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
275 | _("Failed to remove servicehome directory %s\n"), dir); | 253 | _("Failed to remove servicehome directory %s\n"), dir); |
276 | 254 | ||
277 | } | 255 | } |
278 | } | 256 | } |
279 | 257 | ||
280 | /** | 258 | /** |
@@ -288,86 +266,76 @@ static void | |||
288 | cps_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 266 | cps_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
289 | { | 267 | { |
290 | while (1) | 268 | while (1) |
291 | { | ||
292 | switch (phase++) | ||
293 | { | 269 | { |
294 | case 0: | 270 | switch (phase++) |
295 | if (term != NULL) | 271 | { |
296 | { | 272 | case 0: |
297 | GNUNET_ARM_stop_service (h, term, | 273 | if (term != NULL) |
298 | (0 == | 274 | { |
299 | timeout.rel_value) ? STOP_TIMEOUT : timeout, | 275 | GNUNET_ARM_stop_service (h, term, |
300 | &confirm_cb, term); | 276 | (0 == |
301 | return; | 277 | timeout.rel_value) ? STOP_TIMEOUT : |
302 | } | 278 | timeout, &confirm_cb, term); |
303 | break; | 279 | return; |
304 | case 1: | 280 | } |
305 | if ((end) || (restart)) | 281 | break; |
306 | { | 282 | case 1: |
307 | GNUNET_ARM_stop_service (h, "arm", | 283 | if ((end) || (restart)) |
308 | (0 == | 284 | { |
309 | timeout.rel_value) ? STOP_TIMEOUT_ARM : | 285 | GNUNET_ARM_stop_service (h, "arm", |
310 | timeout, &confirm_cb, "arm"); | 286 | (0 == |
311 | return; | 287 | timeout.rel_value) ? STOP_TIMEOUT_ARM |
312 | } | 288 | : timeout, &confirm_cb, "arm"); |
313 | break; | 289 | return; |
314 | case 2: | 290 | } |
315 | if (start) | 291 | break; |
316 | { | 292 | case 2: |
317 | GNUNET_ARM_start_service (h, "arm", | 293 | if (start) |
318 | (0 == | 294 | { |
319 | timeout.rel_value) ? START_TIMEOUT : timeout, | 295 | GNUNET_ARM_start_service (h, "arm", |
320 | &confirm_cb, "arm"); | 296 | (0 == |
321 | return; | 297 | timeout.rel_value) ? START_TIMEOUT : |
322 | } | 298 | timeout, &confirm_cb, "arm"); |
323 | break; | 299 | return; |
324 | case 3: | 300 | } |
325 | if (init != NULL) | 301 | break; |
326 | { | 302 | case 3: |
327 | GNUNET_ARM_start_service (h, init, | 303 | if (init != NULL) |
328 | (0 == | 304 | { |
329 | timeout.rel_value) ? START_TIMEOUT : timeout, | 305 | GNUNET_ARM_start_service (h, init, |
330 | &confirm_cb, init); | 306 | (0 == |
331 | return; | 307 | timeout.rel_value) ? START_TIMEOUT : |
332 | } | 308 | timeout, &confirm_cb, init); |
333 | break; | 309 | return; |
334 | case 4: | 310 | } |
335 | if (test != NULL) | 311 | break; |
336 | { | 312 | case 4: |
337 | GNUNET_CLIENT_service_test (test, cfg, | 313 | if (restart) |
338 | (0 == | 314 | { |
339 | timeout.rel_value) ? TEST_TIMEOUT : | 315 | GNUNET_ARM_disconnect (h); |
340 | timeout, &confirm_task, test); | 316 | phase = 0; |
341 | return; | 317 | end = 0; |
342 | } | 318 | start = 1; |
343 | break; | 319 | restart = 0; |
344 | case 5: | 320 | h = GNUNET_ARM_connect (cfg, NULL); |
345 | if (restart) | 321 | if (h == NULL) |
346 | { | 322 | { |
347 | GNUNET_ARM_disconnect (h); | 323 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
348 | phase = 0; | 324 | _("Fatal error initializing ARM API.\n")); |
349 | end = 0; | 325 | ret = 1; |
350 | start = 1; | 326 | return; |
351 | restart = 0; | 327 | } |
352 | h = GNUNET_ARM_connect (cfg, NULL); | 328 | GNUNET_SCHEDULER_add_now (&cps_loop, NULL); |
353 | if (h == NULL) | 329 | return; |
354 | { | 330 | } |
355 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 331 | /* Fall through */ |
356 | _("Fatal error initializing ARM API.\n")); | 332 | default: /* last phase */ |
357 | ret = 1; | 333 | GNUNET_ARM_disconnect (h); |
358 | return; | 334 | if ((end == GNUNET_YES) && (delete == GNUNET_YES)) |
359 | } | 335 | delete_files (); |
360 | GNUNET_SCHEDULER_add_now (&cps_loop, NULL); | 336 | return; |
361 | return; | 337 | } |
362 | } | ||
363 | /* Fall through */ | ||
364 | default: /* last phase */ | ||
365 | GNUNET_ARM_disconnect (h); | ||
366 | if ((end == GNUNET_YES) && (delete == GNUNET_YES)) | ||
367 | delete_files (); | ||
368 | return; | ||
369 | } | 338 | } |
370 | } | ||
371 | } | 339 | } |
372 | 340 | ||
373 | 341 | ||
@@ -395,9 +363,6 @@ main (int argc, char *const *argv) | |||
395 | {'r', "restart", NULL, | 363 | {'r', "restart", NULL, |
396 | gettext_noop ("stop and start all GNUnet default services"), | 364 | gettext_noop ("stop and start all GNUnet default services"), |
397 | GNUNET_NO, &GNUNET_GETOPT_set_one, &restart}, | 365 | GNUNET_NO, &GNUNET_GETOPT_set_one, &restart}, |
398 | {'t', "test", "SERVICE", | ||
399 | gettext_noop ("test if a particular service is running"), | ||
400 | GNUNET_YES, &GNUNET_GETOPT_set_string, &test}, | ||
401 | {'d', "delete", NULL, | 366 | {'d', "delete", NULL, |
402 | gettext_noop ("delete config file and directory on exit"), | 367 | gettext_noop ("delete config file and directory on exit"), |
403 | GNUNET_NO, &GNUNET_GETOPT_set_one, &delete}, | 368 | GNUNET_NO, &GNUNET_GETOPT_set_one, &delete}, |
@@ -414,12 +379,12 @@ main (int argc, char *const *argv) | |||
414 | 379 | ||
415 | if (GNUNET_OK == | 380 | if (GNUNET_OK == |
416 | GNUNET_PROGRAM_run (argc, argv, "gnunet-arm", | 381 | GNUNET_PROGRAM_run (argc, argv, "gnunet-arm", |
417 | gettext_noop | 382 | gettext_noop |
418 | ("Control services and the Automated Restart Manager (ARM)"), | 383 | ("Control services and the Automated Restart Manager (ARM)"), |
419 | options, &run, NULL)) | 384 | options, &run, NULL)) |
420 | { | 385 | { |
421 | return ret; | 386 | return ret; |
422 | } | 387 | } |
423 | 388 | ||
424 | return 1; | 389 | return 1; |
425 | } | 390 | } |
diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c index 74bbd76c2..733eac6c6 100644 --- a/src/arm/gnunet-service-arm.c +++ b/src/arm/gnunet-service-arm.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2009, 2010 Christian Grothoff (and other contributing authors) | 3 | (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 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 | 6 | it under the terms of the GNU General Public License as published |
@@ -22,31 +22,18 @@ | |||
22 | * @file arm/gnunet-service-arm.c | 22 | * @file arm/gnunet-service-arm.c |
23 | * @brief the automated restart manager service | 23 | * @brief the automated restart manager service |
24 | * @author Christian Grothoff | 24 | * @author Christian Grothoff |
25 | * | ||
26 | * TODO: | ||
27 | * - need to test auto-restart code on configuration changes; | ||
28 | * - should refine restart code to check if *relevant* parts of the | ||
29 | * configuration were changed (anything in the section for the service) | ||
30 | * - should have a way to specify dependencies between services and | ||
31 | * manage restarts of groups of services | ||
32 | * | ||
33 | * + install handler for disconnecting clients!? | ||
34 | */ | 25 | */ |
35 | #include "platform.h" | 26 | #include "platform.h" |
36 | #include "gnunet_util_lib.h" | 27 | #include "gnunet_util_lib.h" |
28 | #include "gnunet_arm_service.h" | ||
37 | #include "gnunet_protocols.h" | 29 | #include "gnunet_protocols.h" |
38 | #include "arm.h" | 30 | #include "arm.h" |
39 | 31 | ||
40 | |||
41 | /** | ||
42 | * Check for configuration file changes every 5s. | ||
43 | */ | ||
44 | #define MAINT_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | ||
45 | |||
46 | /** | 32 | /** |
47 | * Threshold after which exponential backoff shouldn't increase (in ms); 30m | 33 | * Threshold after which exponential backoff shouldn't increase (in ms); 30m |
48 | */ | 34 | */ |
49 | #define EXPONENTIAL_BACKOFF_THRESHOLD (1000 * 60 * 30) | 35 | #define EXPONENTIAL_BACKOFF_THRESHOLD GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30) |
36 | |||
50 | 37 | ||
51 | /** | 38 | /** |
52 | * List of our services. | 39 | * List of our services. |
@@ -55,6 +42,49 @@ struct ServiceList; | |||
55 | 42 | ||
56 | 43 | ||
57 | /** | 44 | /** |
45 | * Record with information about a listen socket we have open. | ||
46 | */ | ||
47 | struct ServiceListeningInfo | ||
48 | { | ||
49 | /** | ||
50 | * This is a linked list. | ||
51 | */ | ||
52 | struct ServiceListeningInfo *next; | ||
53 | |||
54 | /** | ||
55 | * This is a linked list. | ||
56 | */ | ||
57 | struct ServiceListeningInfo *prev; | ||
58 | |||
59 | /** | ||
60 | * Address this socket is listening on. | ||
61 | */ | ||
62 | struct sockaddr *service_addr; | ||
63 | |||
64 | /** | ||
65 | * Service this listen socket is for. | ||
66 | */ | ||
67 | struct ServiceList *sl; | ||
68 | |||
69 | /** | ||
70 | * Number of bytes in 'service_addr' | ||
71 | */ | ||
72 | socklen_t service_addr_len; | ||
73 | |||
74 | /** | ||
75 | * Our listening socket. | ||
76 | */ | ||
77 | struct GNUNET_NETWORK_Handle *listen_socket; | ||
78 | |||
79 | /** | ||
80 | * Task doing the accepting. | ||
81 | */ | ||
82 | GNUNET_SCHEDULER_TaskIdentifier accept_task; | ||
83 | |||
84 | }; | ||
85 | |||
86 | |||
87 | /** | ||
58 | * List of our services. | 88 | * List of our services. |
59 | */ | 89 | */ |
60 | struct ServiceList | 90 | struct ServiceList |
@@ -70,6 +100,16 @@ struct ServiceList | |||
70 | struct ServiceList *prev; | 100 | struct ServiceList *prev; |
71 | 101 | ||
72 | /** | 102 | /** |
103 | * Linked list of listen sockets associated with this service. | ||
104 | */ | ||
105 | struct ServiceListeningInfo *listen_head; | ||
106 | |||
107 | /** | ||
108 | * Linked list of listen sockets associated with this service. | ||
109 | */ | ||
110 | struct ServiceListeningInfo *listen_tail; | ||
111 | |||
112 | /** | ||
73 | * Name of the service. | 113 | * Name of the service. |
74 | */ | 114 | */ |
75 | char *name; | 115 | char *name; |
@@ -96,12 +136,6 @@ struct ServiceList | |||
96 | struct GNUNET_OS_Process *proc; | 136 | struct GNUNET_OS_Process *proc; |
97 | 137 | ||
98 | /** | 138 | /** |
99 | * Last time the config of this service was | ||
100 | * modified. | ||
101 | */ | ||
102 | time_t mtime; | ||
103 | |||
104 | /** | ||
105 | * Process exponential backoff time | 139 | * Process exponential backoff time |
106 | */ | 140 | */ |
107 | struct GNUNET_TIME_Relative backoff; | 141 | struct GNUNET_TIME_Relative backoff; |
@@ -109,7 +143,14 @@ struct ServiceList | |||
109 | /** | 143 | /** |
110 | * Absolute time at which the process is scheduled to restart in case of death | 144 | * Absolute time at which the process is scheduled to restart in case of death |
111 | */ | 145 | */ |
112 | struct GNUNET_TIME_Absolute restartAt; | 146 | struct GNUNET_TIME_Absolute restart_at; |
147 | |||
148 | /** | ||
149 | * Is this service to be started by default (or did a client tell us explicitly | ||
150 | * to start it)? GNUNET_NO if the service is started only upon 'accept' on a | ||
151 | * listen socket or possibly explicitly by a client changing the value. | ||
152 | */ | ||
153 | int is_default; | ||
113 | 154 | ||
114 | }; | 155 | }; |
115 | 156 | ||
@@ -150,84 +191,15 @@ static GNUNET_SCHEDULER_TaskIdentifier child_death_task; | |||
150 | static GNUNET_SCHEDULER_TaskIdentifier child_restart_task; | 191 | static GNUNET_SCHEDULER_TaskIdentifier child_restart_task; |
151 | 192 | ||
152 | /** | 193 | /** |
153 | * | ||
154 | */ | ||
155 | struct ServiceListeningInfo | ||
156 | { | ||
157 | /** | ||
158 | * This is a linked list. | ||
159 | */ | ||
160 | struct ServiceListeningInfo *next; | ||
161 | |||
162 | /** | ||
163 | * This is a linked list. | ||
164 | */ | ||
165 | struct ServiceListeningInfo *prev; | ||
166 | |||
167 | /** | ||
168 | * Name of the service being forwarded. | ||
169 | */ | ||
170 | char *serviceName; | ||
171 | |||
172 | /** | ||
173 | * | ||
174 | */ | ||
175 | struct sockaddr *service_addr; | ||
176 | |||
177 | /** | ||
178 | * | ||
179 | */ | ||
180 | socklen_t service_addr_len; | ||
181 | |||
182 | /** | ||
183 | * Our listening socket. | ||
184 | */ | ||
185 | struct GNUNET_NETWORK_Handle *listeningSocket; | ||
186 | |||
187 | /** | ||
188 | * Task doing the accepting. | ||
189 | */ | ||
190 | GNUNET_SCHEDULER_TaskIdentifier acceptTask; | ||
191 | }; | ||
192 | |||
193 | |||
194 | /** | ||
195 | * Array with the names of the services started by default. | ||
196 | */ | ||
197 | static char **defaultServicesList; | ||
198 | |||
199 | /** | ||
200 | * Size of the defaultServicesList array. | ||
201 | */ | ||
202 | static unsigned int numDefaultServices; | ||
203 | |||
204 | /** | ||
205 | * | ||
206 | */ | ||
207 | static struct ServiceListeningInfo *serviceListeningInfoList_head; | ||
208 | |||
209 | /** | ||
210 | * | ||
211 | */ | ||
212 | static struct ServiceListeningInfo *serviceListeningInfoList_tail; | ||
213 | |||
214 | |||
215 | /** | ||
216 | * Pipe used to communicate shutdown via signal. | 194 | * Pipe used to communicate shutdown via signal. |
217 | */ | 195 | */ |
218 | static struct GNUNET_DISK_PipeHandle *sigpipe; | 196 | static struct GNUNET_DISK_PipeHandle *sigpipe; |
219 | 197 | ||
220 | /** | 198 | /** |
221 | * Reading end of the signal pipe. | ||
222 | */ | ||
223 | static const struct GNUNET_DISK_FileHandle *pr; | ||
224 | |||
225 | /** | ||
226 | * Are we in shutdown mode? | 199 | * Are we in shutdown mode? |
227 | */ | 200 | */ |
228 | static int in_shutdown; | 201 | static int in_shutdown; |
229 | 202 | ||
230 | |||
231 | /** | 203 | /** |
232 | * Handle to our server instance. Our server is a bit special in that | 204 | * Handle to our server instance. Our server is a bit special in that |
233 | * its service is not immediately stopped once we get a shutdown | 205 | * its service is not immediately stopped once we get a shutdown |
@@ -248,10 +220,9 @@ static struct GNUNET_SERVER_Handle *server; | |||
248 | * Actually start the process for the given service. | 220 | * Actually start the process for the given service. |
249 | * | 221 | * |
250 | * @param sl identifies service to start | 222 | * @param sl identifies service to start |
251 | * @param lsocks -1 terminated list of listen sockets to pass (systemd style), or NULL | ||
252 | */ | 223 | */ |
253 | static void | 224 | static void |
254 | start_process (struct ServiceList *sl, const SOCKTYPE *lsocks) | 225 | start_process (struct ServiceList *sl) |
255 | { | 226 | { |
256 | char *loprefix; | 227 | char *loprefix; |
257 | char *options; | 228 | char *options; |
@@ -261,161 +232,100 @@ start_process (struct ServiceList *sl, const SOCKTYPE *lsocks) | |||
261 | int use_debug; | 232 | int use_debug; |
262 | char b; | 233 | char b; |
263 | char *val; | 234 | char *val; |
235 | struct ServiceListeningInfo *sli; | ||
236 | SOCKTYPE *lsocks; | ||
237 | unsigned int ls; | ||
238 | |||
239 | /* calculate listen socket list */ | ||
240 | lsocks = NULL; | ||
241 | ls = 0; | ||
242 | for (sli = sl->listen_head; NULL != sli; sli = sli->next) | ||
243 | { | ||
244 | GNUNET_array_append (lsocks, ls, | ||
245 | GNUNET_NETWORK_get_fd (sli->listen_socket)); | ||
246 | if (sli->accept_task != GNUNET_SCHEDULER_NO_TASK) | ||
247 | { | ||
248 | GNUNET_SCHEDULER_cancel (sli->accept_task); | ||
249 | sli->accept_task = GNUNET_SCHEDULER_NO_TASK; | ||
250 | } | ||
251 | } | ||
252 | #if WINDOWS | ||
253 | GNUNET_array_append (lsocks, ls, INVALID_SOCKET); | ||
254 | #else | ||
255 | GNUNET_array_append (lsocks, ls, -1); | ||
256 | #endif | ||
264 | 257 | ||
265 | /* start service */ | 258 | /* obtain configuration */ |
266 | if (GNUNET_OK != | 259 | if (GNUNET_OK != |
267 | GNUNET_CONFIGURATION_get_value_string (cfg, sl->name, "PREFIX", | 260 | GNUNET_CONFIGURATION_get_value_string (cfg, sl->name, "PREFIX", |
268 | &loprefix)) | 261 | &loprefix)) |
269 | loprefix = GNUNET_strdup (prefix_command); | 262 | loprefix = GNUNET_strdup (prefix_command); |
270 | if (GNUNET_OK != | 263 | if (GNUNET_OK != |
271 | GNUNET_CONFIGURATION_get_value_string (cfg, sl->name, "OPTIONS", | 264 | GNUNET_CONFIGURATION_get_value_string (cfg, sl->name, "OPTIONS", |
272 | &options)) | 265 | &options)) |
273 | { | ||
274 | options = GNUNET_strdup (final_option); | ||
275 | if (NULL == strstr (options, "%")) | ||
276 | { | 266 | { |
277 | /* replace '{}' with service name */ | 267 | options = GNUNET_strdup (final_option); |
278 | while (NULL != (optpos = strstr (options, "{}"))) | 268 | if (NULL == strstr (options, "%")) |
279 | { | 269 | { |
280 | optpos[0] = '%'; | 270 | /* replace '{}' with service name */ |
281 | optpos[1] = 's'; | 271 | while (NULL != (optpos = strstr (options, "{}"))) |
282 | GNUNET_asprintf (&optpos, options, sl->name); | 272 | { |
283 | GNUNET_free (options); | 273 | optpos[0] = '%'; |
284 | options = optpos; | 274 | optpos[1] = 's'; |
285 | } | 275 | GNUNET_asprintf (&optpos, options, sl->name); |
286 | /* replace '$PATH' with value associated with "PATH" */ | 276 | GNUNET_free (options); |
287 | while (NULL != (optpos = strstr (options, "$"))) | 277 | options = optpos; |
288 | { | 278 | } |
289 | optend = optpos + 1; | 279 | /* replace '$PATH' with value associated with "PATH" */ |
290 | while (isupper ((unsigned char) *optend)) | 280 | while (NULL != (optpos = strstr (options, "$"))) |
291 | optend++; | 281 | { |
292 | b = *optend; | 282 | optend = optpos + 1; |
293 | if ('\0' == b) | 283 | while (isupper ((unsigned char) *optend)) |
294 | next = ""; | 284 | optend++; |
295 | else | 285 | b = *optend; |
296 | next = optend + 1; | 286 | if ('\0' == b) |
297 | *optend = '\0'; | 287 | next = ""; |
298 | if (GNUNET_OK != | 288 | else |
299 | GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", optpos + 1, | 289 | next = optend + 1; |
300 | &val)) | 290 | *optend = '\0'; |
301 | val = GNUNET_strdup (""); | 291 | if (GNUNET_OK != |
302 | *optpos = '\0'; | 292 | GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", |
303 | GNUNET_asprintf (&optpos, "%s%s%c%s", options, val, b, next); | 293 | optpos + 1, &val)) |
304 | GNUNET_free (options); | 294 | val = GNUNET_strdup (""); |
305 | GNUNET_free (val); | 295 | *optpos = '\0'; |
306 | options = optpos; | 296 | GNUNET_asprintf (&optpos, "%s%s%c%s", options, val, b, next); |
307 | } | 297 | GNUNET_free (options); |
298 | GNUNET_free (val); | ||
299 | options = optpos; | ||
300 | } | ||
301 | } | ||
308 | } | 302 | } |
309 | } | ||
310 | use_debug = GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "DEBUG"); | 303 | use_debug = GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "DEBUG"); |
311 | 304 | ||
305 | /* actually start process */ | ||
312 | #if DEBUG_ARM | 306 | #if DEBUG_ARM |
313 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 307 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
314 | "Starting service `%s' using binary `%s' and configuration `%s'\n", | 308 | "Starting service `%s' using binary `%s' and configuration `%s'\n", |
315 | sl->name, sl->binary, sl->config); | 309 | sl->name, sl->binary, sl->config); |
316 | #endif | 310 | #endif |
317 | if (GNUNET_YES == use_debug) | 311 | if (GNUNET_YES == use_debug) |
318 | sl->proc = | 312 | sl->proc = |
319 | do_start_process (lsocks, loprefix, sl->binary, "-c", sl->config, "-L", | 313 | do_start_process (lsocks, loprefix, sl->binary, "-c", sl->config, "-L", |
320 | "DEBUG", options, NULL); | 314 | "DEBUG", options, NULL); |
321 | else | 315 | else |
322 | sl->proc = | 316 | sl->proc = |
323 | do_start_process (lsocks, loprefix, sl->binary, "-c", sl->config, | 317 | do_start_process (lsocks, loprefix, sl->binary, "-c", sl->config, |
324 | options, NULL); | 318 | options, NULL); |
325 | if (sl->proc == NULL) | 319 | if (sl->proc == NULL) |
326 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to start service `%s'\n"), | 320 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to start service `%s'\n"), |
327 | sl->name); | 321 | sl->name); |
328 | else | 322 | else |
329 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting service `%s'\n"), sl->name); | 323 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting service `%s'\n"), |
324 | sl->name); | ||
325 | /* clean up */ | ||
330 | GNUNET_free (loprefix); | 326 | GNUNET_free (loprefix); |
331 | GNUNET_free (options); | 327 | GNUNET_free (options); |
332 | } | 328 | GNUNET_array_grow (lsocks, ls, 0); |
333 | |||
334 | |||
335 | /** | ||
336 | * Put the default services represented by a space separated string into an array of strings | ||
337 | * | ||
338 | * @param services space separated string of default services | ||
339 | */ | ||
340 | static void | ||
341 | addDefaultServicesToList (const char *services) | ||
342 | { | ||
343 | unsigned int i; | ||
344 | const char *token; | ||
345 | char *s; | ||
346 | |||
347 | if (strlen (services) == 0) | ||
348 | return; | ||
349 | s = GNUNET_strdup (services); | ||
350 | token = strtok (s, " "); | ||
351 | while (NULL != token) | ||
352 | { | ||
353 | numDefaultServices++; | ||
354 | token = strtok (NULL, " "); | ||
355 | } | ||
356 | GNUNET_free (s); | ||
357 | |||
358 | defaultServicesList = GNUNET_malloc (numDefaultServices * sizeof (char *)); | ||
359 | i = 0; | ||
360 | s = GNUNET_strdup (services); | ||
361 | token = strtok (s, " "); | ||
362 | while (NULL != token) | ||
363 | { | ||
364 | defaultServicesList[i++] = GNUNET_strdup (token); | ||
365 | token = strtok (NULL, " "); | ||
366 | } | ||
367 | GNUNET_free (s); | ||
368 | GNUNET_assert (i == numDefaultServices); | ||
369 | } | ||
370 | |||
371 | |||
372 | /** | ||
373 | * Checks whether the serviceName is in the list of default services | ||
374 | * | ||
375 | * @param serviceName string to check its existance in the list | ||
376 | * @return GNUNET_YES if the service is started by default | ||
377 | */ | ||
378 | static int | ||
379 | isInDefaultList (const char *serviceName) | ||
380 | { | ||
381 | unsigned int i; | ||
382 | |||
383 | for (i = 0; i < numDefaultServices; i++) | ||
384 | if (strcmp (serviceName, defaultServicesList[i]) == 0) | ||
385 | return GNUNET_YES; | ||
386 | return GNUNET_NO; | ||
387 | } | ||
388 | |||
389 | |||
390 | /** | ||
391 | * | ||
392 | */ | ||
393 | static int | ||
394 | stop_listening (const char *serviceName) | ||
395 | { | ||
396 | struct ServiceListeningInfo *pos; | ||
397 | struct ServiceListeningInfo *next; | ||
398 | int ret; | ||
399 | |||
400 | ret = GNUNET_NO; | ||
401 | next = serviceListeningInfoList_head; | ||
402 | while (NULL != (pos = next)) | ||
403 | { | ||
404 | next = pos->next; | ||
405 | if ((serviceName != NULL) && (strcmp (pos->serviceName, serviceName) != 0)) | ||
406 | continue; | ||
407 | if (pos->acceptTask != GNUNET_SCHEDULER_NO_TASK) | ||
408 | GNUNET_SCHEDULER_cancel (pos->acceptTask); | ||
409 | GNUNET_break (GNUNET_OK == | ||
410 | GNUNET_NETWORK_socket_close (pos->listeningSocket)); | ||
411 | GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head, | ||
412 | serviceListeningInfoList_tail, pos); | ||
413 | GNUNET_free (pos->serviceName); | ||
414 | GNUNET_free (pos->service_addr); | ||
415 | GNUNET_free (pos); | ||
416 | ret = GNUNET_OK; | ||
417 | } | ||
418 | return ret; | ||
419 | } | 329 | } |
420 | 330 | ||
421 | 331 | ||
@@ -430,25 +340,26 @@ stop_listening (const char *serviceName) | |||
430 | static size_t | 340 | static size_t |
431 | write_result (void *cls, size_t size, void *buf) | 341 | write_result (void *cls, size_t size, void *buf) |
432 | { | 342 | { |
433 | uint16_t *res = cls; | 343 | enum GNUNET_ARM_ProcessStatus *res = cls; |
434 | struct GNUNET_MessageHeader *msg; | 344 | struct GNUNET_ARM_ResultMessage *msg; |
435 | 345 | ||
436 | if (buf == NULL) | 346 | if (buf == NULL) |
437 | { | 347 | { |
438 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 348 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
439 | _("Could not send status result to client\n")); | 349 | _("Could not send status result to client\n")); |
440 | return 0; /* error, not much we can do */ | 350 | return 0; /* error, not much we can do */ |
441 | } | 351 | } |
442 | #if DEBUG_ARM | 352 | #if DEBUG_ARM |
443 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending status response %u to client\n", | 353 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
444 | (unsigned int) *res); | 354 | "Sending status response %u to client\n", (unsigned int) *res); |
445 | #endif | 355 | #endif |
446 | GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); | 356 | GNUNET_assert (size >= sizeof (struct GNUNET_ARM_ResultMessage)); |
447 | msg = buf; | 357 | msg = buf; |
448 | msg->size = htons (sizeof (struct GNUNET_MessageHeader)); | 358 | msg->header.size = htons (sizeof (struct GNUNET_ARM_ResultMessage)); |
449 | msg->type = htons (*res); | 359 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_ARM_RESULT); |
360 | msg->status = htonl ((uint32_t) (*res)); | ||
450 | GNUNET_free (res); | 361 | GNUNET_free (res); |
451 | return sizeof (struct GNUNET_MessageHeader); | 362 | return sizeof (struct GNUNET_ARM_ResultMessage); |
452 | } | 363 | } |
453 | 364 | ||
454 | 365 | ||
@@ -463,27 +374,21 @@ write_result (void *cls, size_t size, void *buf) | |||
463 | */ | 374 | */ |
464 | static void | 375 | static void |
465 | signal_result (struct GNUNET_SERVER_Client *client, const char *name, | 376 | signal_result (struct GNUNET_SERVER_Client *client, const char *name, |
466 | uint16_t result) | 377 | enum GNUNET_ARM_ProcessStatus result) |
467 | { | 378 | { |
468 | uint16_t *res; | 379 | enum GNUNET_ARM_ProcessStatus *res; |
469 | 380 | ||
470 | if (NULL == client) | 381 | if (NULL == client) |
471 | { | ||
472 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
473 | _("Not sending status result to client: no client known\n")); | ||
474 | return; | 382 | return; |
475 | } | 383 | /* FIXME: this is not super-clean yet... */ |
476 | #if DEBUG_ARM | 384 | res = GNUNET_malloc (sizeof (enum GNUNET_ARM_ProcessStatus)); |
477 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
478 | "Telling client that service `%s' is now %s\n", name, | ||
479 | result == GNUNET_MESSAGE_TYPE_ARM_IS_DOWN ? "down" : "up"); | ||
480 | #endif | ||
481 | res = GNUNET_malloc (sizeof (uint16_t)); | ||
482 | *res = result; | 385 | *res = result; |
483 | GNUNET_SERVER_notify_transmit_ready (client, | 386 | GNUNET_SERVER_notify_transmit_ready (client, |
484 | sizeof (struct GNUNET_MessageHeader), | 387 | sizeof (struct |
485 | GNUNET_TIME_UNIT_FOREVER_REL, | 388 | GNUNET_ARM_ResultMessage), |
486 | &write_result, res); | 389 | GNUNET_TIME_UNIT_FOREVER_REL, |
390 | &write_result, res); | ||
391 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
487 | } | 392 | } |
488 | 393 | ||
489 | 394 | ||
@@ -497,88 +402,16 @@ signal_result (struct GNUNET_SERVER_Client *client, const char *name, | |||
497 | static struct ServiceList * | 402 | static struct ServiceList * |
498 | find_service (const char *name) | 403 | find_service (const char *name) |
499 | { | 404 | { |
500 | struct ServiceList *pos; | ||
501 | |||
502 | pos = running_head; | ||
503 | while (pos != NULL) | ||
504 | { | ||
505 | if (0 == strcmp (pos->name, name)) | ||
506 | return pos; | ||
507 | pos = pos->next; | ||
508 | } | ||
509 | return NULL; | ||
510 | } | ||
511 | |||
512 | |||
513 | /** | ||
514 | * Start the specified service. | ||
515 | * | ||
516 | * @param client who is asking for this | ||
517 | * @param servicename name of the service to start | ||
518 | * @param lsocks -1 terminated list of listen sockets to pass (systemd style), or NULL | ||
519 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
520 | */ | ||
521 | static int | ||
522 | start_service (struct GNUNET_SERVER_Client *client, const char *servicename, | ||
523 | const SOCKTYPE *lsocks) | ||
524 | { | ||
525 | struct ServiceList *sl; | 405 | struct ServiceList *sl; |
526 | char *binary; | ||
527 | char *config; | ||
528 | struct stat sbuf; | ||
529 | 406 | ||
530 | if (GNUNET_YES == in_shutdown) | 407 | sl = running_head; |
531 | { | 408 | while (sl != NULL) |
532 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 409 | { |
533 | _("ARM is shutting down, service `%s' not started.\n"), | 410 | if (0 == strcmp (sl->name, name)) |
534 | servicename); | 411 | return sl; |
535 | signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN); | 412 | sl = sl->next; |
536 | return GNUNET_SYSERR; | 413 | } |
537 | } | 414 | return NULL; |
538 | sl = find_service (servicename); | ||
539 | if (sl != NULL) | ||
540 | { | ||
541 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Service `%s' already running.\n"), | ||
542 | servicename); | ||
543 | signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_UP); | ||
544 | return GNUNET_SYSERR; | ||
545 | } | ||
546 | if (GNUNET_OK != | ||
547 | GNUNET_CONFIGURATION_get_value_string (cfg, servicename, "BINARY", | ||
548 | &binary)) | ||
549 | { | ||
550 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
551 | _("Binary implementing service `%s' not known!\n"), | ||
552 | servicename); | ||
553 | signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN); | ||
554 | return GNUNET_SYSERR; | ||
555 | } | ||
556 | if ((GNUNET_OK != | ||
557 | GNUNET_CONFIGURATION_get_value_filename (cfg, servicename, "CONFIG", | ||
558 | &config)) || | ||
559 | (0 != STAT (config, &sbuf))) | ||
560 | { | ||
561 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
562 | _("Configuration file `%s' for service `%s' not known!\n"), | ||
563 | config, servicename); | ||
564 | signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN); | ||
565 | GNUNET_free (binary); | ||
566 | GNUNET_free_non_null (config); | ||
567 | return GNUNET_SYSERR; | ||
568 | } | ||
569 | (void) stop_listening (servicename); | ||
570 | sl = GNUNET_malloc (sizeof (struct ServiceList)); | ||
571 | sl->name = GNUNET_strdup (servicename); | ||
572 | sl->binary = binary; | ||
573 | sl->config = config; | ||
574 | sl->mtime = sbuf.st_mtime; | ||
575 | sl->backoff = GNUNET_TIME_UNIT_MILLISECONDS; | ||
576 | sl->restartAt = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
577 | GNUNET_CONTAINER_DLL_insert (running_head, running_tail, sl); | ||
578 | start_process (sl, lsocks); | ||
579 | if (NULL != client) | ||
580 | signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_UP); | ||
581 | return GNUNET_OK; | ||
582 | } | 415 | } |
583 | 416 | ||
584 | 417 | ||
@@ -590,58 +423,15 @@ start_service (struct GNUNET_SERVER_Client *client, const char *servicename, | |||
590 | * @param tc context | 423 | * @param tc context |
591 | */ | 424 | */ |
592 | static void | 425 | static void |
593 | acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 426 | accept_connection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
594 | { | 427 | { |
595 | struct ServiceListeningInfo *sli = cls; | 428 | struct ServiceListeningInfo *sli = cls; |
596 | struct ServiceListeningInfo *pos; | 429 | struct ServiceList *sl = sli->sl; |
597 | struct ServiceListeningInfo *next; | ||
598 | SOCKTYPE *lsocks; | ||
599 | unsigned int ls; | ||
600 | 430 | ||
601 | sli->acceptTask = GNUNET_SCHEDULER_NO_TASK; | 431 | sli->accept_task = GNUNET_SCHEDULER_NO_TASK; |
602 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) | 432 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) |
603 | return; | 433 | return; |
604 | GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head, | 434 | start_process (sl); |
605 | serviceListeningInfoList_tail, sli); | ||
606 | lsocks = NULL; | ||
607 | ls = 0; | ||
608 | next = serviceListeningInfoList_head; | ||
609 | while (NULL != (pos = next)) | ||
610 | { | ||
611 | next = pos->next; | ||
612 | if (0 == strcmp (pos->serviceName, sli->serviceName)) | ||
613 | { | ||
614 | GNUNET_array_append (lsocks, ls, | ||
615 | GNUNET_NETWORK_get_fd (pos->listeningSocket)); | ||
616 | GNUNET_free (pos->listeningSocket); /* deliberately no closing! */ | ||
617 | GNUNET_free (pos->service_addr); | ||
618 | GNUNET_free (pos->serviceName); | ||
619 | GNUNET_SCHEDULER_cancel (pos->acceptTask); | ||
620 | GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head, | ||
621 | serviceListeningInfoList_tail, pos); | ||
622 | GNUNET_free (pos); | ||
623 | } | ||
624 | } | ||
625 | GNUNET_array_append (lsocks, ls, | ||
626 | GNUNET_NETWORK_get_fd (sli->listeningSocket)); | ||
627 | GNUNET_free (sli->listeningSocket); /* deliberately no closing! */ | ||
628 | GNUNET_free (sli->service_addr); | ||
629 | #if WINDOWS | ||
630 | GNUNET_array_append (lsocks, ls, INVALID_SOCKET); | ||
631 | #else | ||
632 | GNUNET_array_append (lsocks, ls, -1); | ||
633 | #endif | ||
634 | start_service (NULL, sli->serviceName, lsocks); | ||
635 | ls = 0; | ||
636 | while (lsocks[ls] != -1) | ||
637 | #if WINDOWS | ||
638 | GNUNET_break (0 == closesocket (lsocks[ls++])); | ||
639 | #else | ||
640 | GNUNET_break (0 == close (lsocks[ls++])); | ||
641 | #endif | ||
642 | GNUNET_array_grow (lsocks, ls, 0); | ||
643 | GNUNET_free (sli->serviceName); | ||
644 | GNUNET_free (sli); | ||
645 | } | 435 | } |
646 | 436 | ||
647 | 437 | ||
@@ -651,263 +441,104 @@ acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
651 | * | 441 | * |
652 | * @param sa address associated with the service | 442 | * @param sa address associated with the service |
653 | * @param addr_len length of sa | 443 | * @param addr_len length of sa |
654 | * @param serviceName the name of the service in question | 444 | * @param sl service entry for the service in question |
655 | */ | 445 | */ |
656 | static void | 446 | static void |
657 | createListeningSocket (struct sockaddr *sa, socklen_t addr_len, | 447 | create_listen_socket (struct sockaddr *sa, socklen_t addr_len, |
658 | const char *serviceName) | 448 | struct ServiceList *sl) |
659 | { | 449 | { |
660 | const static int on = 1; | 450 | const static int on = 1; |
661 | struct GNUNET_NETWORK_Handle *sock; | 451 | struct GNUNET_NETWORK_Handle *sock; |
662 | struct ServiceListeningInfo *serviceListeningInfo; | 452 | struct ServiceListeningInfo *sli; |
663 | 453 | ||
664 | switch (sa->sa_family) | 454 | switch (sa->sa_family) |
665 | { | 455 | { |
666 | case AF_INET: | 456 | case AF_INET: |
667 | sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0); | 457 | sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0); |
668 | break; | 458 | break; |
669 | case AF_INET6: | 459 | case AF_INET6: |
670 | sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); | 460 | sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); |
671 | break; | 461 | break; |
672 | case AF_UNIX: | 462 | case AF_UNIX: |
673 | if (strcmp (GNUNET_a2s (sa, addr_len), "@") == 0) /* Do not bind to blank UNIX path! */ | 463 | if (strcmp (GNUNET_a2s (sa, addr_len), "@") == 0) /* Do not bind to blank UNIX path! */ |
674 | return; | 464 | return; |
675 | sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0); | 465 | sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0); |
676 | break; | 466 | break; |
677 | default: | 467 | default: |
678 | GNUNET_break (0); | 468 | GNUNET_break (0); |
679 | sock = NULL; | 469 | sock = NULL; |
680 | errno = EAFNOSUPPORT; | 470 | errno = EAFNOSUPPORT; |
681 | break; | 471 | break; |
682 | } | 472 | } |
683 | if (NULL == sock) | 473 | if (NULL == sock) |
684 | { | 474 | { |
685 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 475 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
686 | _("Unable to create socket for service `%s': %s\n"), | 476 | _("Unable to create socket for service `%s': %s\n"), |
687 | serviceName, STRERROR (errno)); | 477 | sl->name, STRERROR (errno)); |
688 | GNUNET_free (sa); | 478 | GNUNET_free (sa); |
689 | return; | 479 | return; |
690 | } | 480 | } |
691 | if (GNUNET_NETWORK_socket_setsockopt | 481 | if (GNUNET_NETWORK_socket_setsockopt |
692 | (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK) | 482 | (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK) |
693 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 483 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
694 | "setsockopt"); | 484 | "setsockopt"); |
695 | #ifdef IPV6_V6ONLY | 485 | #ifdef IPV6_V6ONLY |
696 | if ((sa->sa_family == AF_INET6) && | 486 | if ((sa->sa_family == AF_INET6) && |
697 | (GNUNET_NETWORK_socket_setsockopt | 487 | (GNUNET_NETWORK_socket_setsockopt |
698 | (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK)) | 488 | (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK)) |
699 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 489 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
700 | "setsockopt"); | 490 | "setsockopt"); |
701 | #endif | 491 | #endif |
702 | 492 | ||
703 | if (GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len) | 493 | if (GNUNET_NETWORK_socket_bind |
704 | != GNUNET_OK) | 494 | (sock, (const struct sockaddr *) sa, addr_len) != GNUNET_OK) |
705 | { | 495 | { |
706 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 496 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
707 | _ | 497 | _ |
708 | ("Unable to bind listening socket for service `%s' to address `%s': %s\n"), | 498 | ("Unable to bind listening socket for service `%s' to address `%s': %s\n"), |
709 | serviceName, GNUNET_a2s (sa, addr_len), STRERROR (errno)); | 499 | sl->name, GNUNET_a2s (sa, addr_len), STRERROR (errno)); |
710 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); | 500 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); |
711 | GNUNET_free (sa); | 501 | GNUNET_free (sa); |
712 | return; | 502 | return; |
713 | } | 503 | } |
714 | if (GNUNET_NETWORK_socket_listen (sock, 5) != GNUNET_OK) | 504 | if (GNUNET_NETWORK_socket_listen (sock, 5) != GNUNET_OK) |
715 | { | ||
716 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen"); | ||
717 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); | ||
718 | GNUNET_free (sa); | ||
719 | return; | ||
720 | } | ||
721 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
722 | _("ARM now monitors connections to service `%s' at `%s'\n"), | ||
723 | serviceName, GNUNET_a2s (sa, addr_len)); | ||
724 | serviceListeningInfo = GNUNET_malloc (sizeof (struct ServiceListeningInfo)); | ||
725 | serviceListeningInfo->serviceName = GNUNET_strdup (serviceName); | ||
726 | serviceListeningInfo->service_addr = sa; | ||
727 | serviceListeningInfo->service_addr_len = addr_len; | ||
728 | serviceListeningInfo->listeningSocket = sock; | ||
729 | serviceListeningInfo->acceptTask = | ||
730 | GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, sock, | ||
731 | &acceptConnection, serviceListeningInfo); | ||
732 | GNUNET_CONTAINER_DLL_insert (serviceListeningInfoList_head, | ||
733 | serviceListeningInfoList_tail, | ||
734 | serviceListeningInfo); | ||
735 | } | ||
736 | |||
737 | |||
738 | /** | ||
739 | * Callback function, checks whether the current tokens are representing a service, | ||
740 | * gets its addresses and create listening socket for it. | ||
741 | * | ||
742 | * @param cls callback data, not used | ||
743 | * @param section configuration section | ||
744 | * @param option configuration option | ||
745 | * @param value the option's value | ||
746 | */ | ||
747 | static void | ||
748 | checkPortNumberCB (void *cls, const char *section, const char *option, | ||
749 | const char *value) | ||
750 | { | ||
751 | struct sockaddr **addrs; | ||
752 | socklen_t *addr_lens; | ||
753 | int ret; | ||
754 | unsigned int i; | ||
755 | |||
756 | if ((strcasecmp (section, "arm") == 0) || | ||
757 | (strcasecmp (option, "AUTOSTART") != 0) || | ||
758 | (strcasecmp (value, "YES") != 0) || | ||
759 | (isInDefaultList (section) == GNUNET_YES)) | ||
760 | return; | ||
761 | if (0 >= | ||
762 | (ret = | ||
763 | GNUNET_SERVICE_get_server_addresses (section, cfg, &addrs, &addr_lens))) | ||
764 | return; | ||
765 | /* this will free (or capture) addrs[i] */ | ||
766 | for (i = 0; i < ret; i++) | ||
767 | createListeningSocket (addrs[i], addr_lens[i], section); | ||
768 | GNUNET_free (addrs); | ||
769 | GNUNET_free (addr_lens); | ||
770 | } | ||
771 | |||
772 | |||
773 | /** | ||
774 | * Entry point to the Service Manager | ||
775 | * | ||
776 | * @param configurationHandle configuration to use to get services | ||
777 | */ | ||
778 | static void | ||
779 | prepare_services (const struct GNUNET_CONFIGURATION_Handle *configurationHandle) | ||
780 | { | ||
781 | char *defaultServicesString; | ||
782 | |||
783 | cfg = configurationHandle; | ||
784 | /* Split the default services into a list */ | ||
785 | if (GNUNET_OK == | ||
786 | GNUNET_CONFIGURATION_get_value_string (cfg, "arm", "DEFAULTSERVICES", | ||
787 | &defaultServicesString)) | ||
788 | { | ||
789 | addDefaultServicesToList (defaultServicesString); | ||
790 | GNUNET_free (defaultServicesString); | ||
791 | } | ||
792 | /* Spot the services from the configuration and create a listening | ||
793 | * socket for each */ | ||
794 | GNUNET_CONFIGURATION_iterate (cfg, &checkPortNumberCB, NULL); | ||
795 | } | ||
796 | |||
797 | |||
798 | |||
799 | /** | ||
800 | * If the configuration file changes, restart tasks that depended on that | ||
801 | * option. | ||
802 | * | ||
803 | * @param cls closure, NULL if we need to self-restart | ||
804 | * @param tc context | ||
805 | */ | ||
806 | static void | ||
807 | config_change_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
808 | { | ||
809 | struct ServiceList *pos; | ||
810 | struct stat sbuf; | ||
811 | |||
812 | pos = running_head; | ||
813 | while (pos != NULL) | ||
814 | { | ||
815 | /* FIXME: this test for config change may be a bit too coarse grained */ | ||
816 | if ((0 == STAT (pos->config, &sbuf)) && (pos->mtime < sbuf.st_mtime) && | ||
817 | (pos->proc != NULL)) | ||
818 | { | 505 | { |
819 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 506 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen"); |
820 | _ | 507 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); |
821 | ("Restarting service `%s' due to configuration file change.\n")); | 508 | GNUNET_free (sa); |
822 | if (0 != GNUNET_OS_process_kill (pos->proc, SIGTERM)) | 509 | return; |
823 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); | ||
824 | else | ||
825 | pos->backoff = GNUNET_TIME_UNIT_MILLISECONDS; | ||
826 | } | 510 | } |
827 | pos = pos->next; | 511 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
828 | } | 512 | _("ARM now monitors connections to service `%s' at `%s'\n"), |
829 | } | 513 | sl->name, GNUNET_a2s (sa, addr_len)); |
830 | 514 | sli = GNUNET_malloc (sizeof (struct ServiceListeningInfo)); | |
831 | 515 | sli->service_addr = sa; | |
832 | /** | 516 | sli->service_addr_len = addr_len; |
833 | * Remove and free an entry in the service list. | 517 | sli->listen_socket = sock; |
834 | * | 518 | sli->sl = sl; |
835 | * @param pos entry to free | 519 | sli->accept_task = |
836 | */ | 520 | GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, sock, |
837 | static void | 521 | &accept_connection, sli); |
838 | free_service (struct ServiceList *pos) | 522 | GNUNET_CONTAINER_DLL_insert (sl->listen_head, sl->listen_tail, sli); |
839 | { | ||
840 | GNUNET_CONTAINER_DLL_remove (running_head, running_tail, pos); | ||
841 | GNUNET_free_non_null (pos->config); | ||
842 | GNUNET_free_non_null (pos->binary); | ||
843 | GNUNET_free (pos->name); | ||
844 | GNUNET_free (pos); | ||
845 | } | 523 | } |
846 | 524 | ||
847 | 525 | ||
848 | /** | 526 | /** |
849 | * Stop the specified service. | 527 | * Remove and free an entry in the service list. Listen sockets |
528 | * must have already been cleaned up. Only to be called during shutdown. | ||
850 | * | 529 | * |
851 | * @param client who is asking for this | 530 | * @param sl entry to free |
852 | * @param servicename name of the service to stop | ||
853 | */ | 531 | */ |
854 | static void | 532 | static void |
855 | stop_service (struct GNUNET_SERVER_Client *client, const char *servicename) | 533 | free_service (struct ServiceList *sl) |
856 | { | 534 | { |
857 | struct ServiceList *pos; | 535 | GNUNET_assert (GNUNET_YES == in_shutdown); |
858 | 536 | GNUNET_CONTAINER_DLL_remove (running_head, running_tail, sl); | |
859 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Preparing to stop `%s'\n"), | 537 | GNUNET_assert (NULL == sl->listen_head); |
860 | servicename); | 538 | GNUNET_free_non_null (sl->config); |
861 | pos = find_service (servicename); | 539 | GNUNET_free_non_null (sl->binary); |
862 | if (pos == NULL) | 540 | GNUNET_free (sl->name); |
863 | { | 541 | GNUNET_free (sl); |
864 | if (GNUNET_OK == stop_listening (servicename)) | ||
865 | signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN); | ||
866 | else | ||
867 | signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_UNKNOWN); | ||
868 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
869 | return; | ||
870 | } | ||
871 | if (pos->killing_client != NULL) | ||
872 | { | ||
873 | /* killing already in progress */ | ||
874 | #if DEBUG_ARM | ||
875 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' is already down\n", | ||
876 | servicename); | ||
877 | #endif | ||
878 | signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN); | ||
879 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
880 | return; | ||
881 | } | ||
882 | |||
883 | if (GNUNET_YES == in_shutdown) | ||
884 | { | ||
885 | #if DEBUG_ARM | ||
886 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
887 | "Termination request already sent to `%s' (since ARM is in shutdown).\n", | ||
888 | servicename); | ||
889 | #endif | ||
890 | signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN); | ||
891 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
892 | return; | ||
893 | } | ||
894 | if (pos->proc == NULL) | ||
895 | { | ||
896 | /* process is in delayed restart, simply remove it! */ | ||
897 | free_service (pos); | ||
898 | signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN); | ||
899 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
900 | return; | ||
901 | } | ||
902 | #if DEBUG_ARM | ||
903 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
904 | "Sending kill signal to service `%s', waiting for process to die.\n", | ||
905 | servicename); | ||
906 | #endif | ||
907 | if (0 != GNUNET_OS_process_kill (pos->proc, SIGTERM)) | ||
908 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); | ||
909 | pos->killing_client = client; | ||
910 | GNUNET_SERVER_client_keep (client); | ||
911 | } | 542 | } |
912 | 543 | ||
913 | 544 | ||
@@ -922,22 +553,40 @@ stop_service (struct GNUNET_SERVER_Client *client, const char *servicename) | |||
922 | */ | 553 | */ |
923 | static void | 554 | static void |
924 | handle_start (void *cls, struct GNUNET_SERVER_Client *client, | 555 | handle_start (void *cls, struct GNUNET_SERVER_Client *client, |
925 | const struct GNUNET_MessageHeader *message) | 556 | const struct GNUNET_MessageHeader *message) |
926 | { | 557 | { |
927 | const char *servicename; | 558 | const char *servicename; |
559 | struct ServiceList *sl; | ||
928 | uint16_t size; | 560 | uint16_t size; |
929 | 561 | ||
930 | size = ntohs (message->size); | 562 | size = ntohs (message->size); |
931 | size -= sizeof (struct GNUNET_MessageHeader); | 563 | size -= sizeof (struct GNUNET_MessageHeader); |
932 | servicename = (const char *) &message[1]; | 564 | servicename = (const char *) &message[1]; |
933 | if ((size == 0) || (servicename[size - 1] != '\0')) | 565 | if ((size == 0) || (servicename[size - 1] != '\0')) |
934 | { | 566 | { |
935 | GNUNET_break (0); | 567 | GNUNET_break (0); |
936 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 568 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
937 | return; | 569 | return; |
938 | } | 570 | } |
939 | start_service (client, servicename, NULL); | 571 | if (GNUNET_YES == in_shutdown) |
940 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 572 | { |
573 | signal_result (client, servicename, GNUNET_ARM_PROCESS_SHUTDOWN); | ||
574 | return; | ||
575 | } | ||
576 | sl = find_service (servicename); | ||
577 | if (NULL == sl) | ||
578 | { | ||
579 | signal_result (client, servicename, GNUNET_ARM_PROCESS_UNKNOWN); | ||
580 | return; | ||
581 | } | ||
582 | sl->is_default = GNUNET_YES; | ||
583 | if (sl->proc != NULL) | ||
584 | { | ||
585 | signal_result (client, servicename, GNUNET_ARM_PROCESS_ALREADY_RUNNING); | ||
586 | return; | ||
587 | } | ||
588 | start_process (sl); | ||
589 | signal_result (client, servicename, GNUNET_ARM_PROCESS_STARTING); | ||
941 | } | 590 | } |
942 | 591 | ||
943 | 592 | ||
@@ -952,8 +601,9 @@ handle_start (void *cls, struct GNUNET_SERVER_Client *client, | |||
952 | */ | 601 | */ |
953 | static void | 602 | static void |
954 | handle_stop (void *cls, struct GNUNET_SERVER_Client *client, | 603 | handle_stop (void *cls, struct GNUNET_SERVER_Client *client, |
955 | const struct GNUNET_MessageHeader *message) | 604 | const struct GNUNET_MessageHeader *message) |
956 | { | 605 | { |
606 | struct ServiceList *sl; | ||
957 | const char *servicename; | 607 | const char *servicename; |
958 | uint16_t size; | 608 | uint16_t size; |
959 | 609 | ||
@@ -961,33 +611,48 @@ handle_stop (void *cls, struct GNUNET_SERVER_Client *client, | |||
961 | size -= sizeof (struct GNUNET_MessageHeader); | 611 | size -= sizeof (struct GNUNET_MessageHeader); |
962 | servicename = (const char *) &message[1]; | 612 | servicename = (const char *) &message[1]; |
963 | if ((size == 0) || (servicename[size - 1] != '\0')) | 613 | if ((size == 0) || (servicename[size - 1] != '\0')) |
964 | { | 614 | { |
965 | GNUNET_break (0); | 615 | GNUNET_break (0); |
966 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 616 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
967 | return; | 617 | return; |
968 | } | 618 | } |
969 | stop_service (client, servicename); | 619 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
970 | } | 620 | _("Preparing to stop `%s'\n"), servicename); |
971 | 621 | sl = find_service (servicename); | |
972 | 622 | if (sl == NULL) | |
973 | /** | 623 | { |
974 | * Remove all entries for tasks that are not running | 624 | signal_result (client, servicename, GNUNET_ARM_PROCESS_UNKNOWN); |
975 | * (proc = NULL) from the running list (they will no longer | 625 | return; |
976 | * be restarted since we are shutting down). | 626 | } |
977 | */ | 627 | sl->is_default = GNUNET_NO; |
978 | static void | 628 | if (GNUNET_YES == in_shutdown) |
979 | clean_up_running () | 629 | { |
980 | { | 630 | /* shutdown in progress */ |
981 | struct ServiceList *pos; | 631 | signal_result (client, servicename, GNUNET_ARM_PROCESS_SHUTDOWN); |
982 | struct ServiceList *next; | 632 | return; |
983 | 633 | } | |
984 | next = running_head; | 634 | if (sl->killing_client != NULL) |
985 | while (NULL != (pos = next)) | 635 | { |
986 | { | 636 | /* killing already in progress */ |
987 | next = pos->next; | 637 | signal_result (client, servicename, |
988 | if (pos->proc == NULL) | 638 | GNUNET_ARM_PROCESS_ALREADY_STOPPING); |
989 | free_service (pos); | 639 | return; |
990 | } | 640 | } |
641 | if (sl->proc == NULL) | ||
642 | { | ||
643 | /* process is down */ | ||
644 | signal_result (client, servicename, GNUNET_ARM_PROCESS_ALREADY_DOWN); | ||
645 | return; | ||
646 | } | ||
647 | #if DEBUG_ARM | ||
648 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
649 | "Sending kill signal to service `%s', waiting for process to die.\n", | ||
650 | servicename); | ||
651 | #endif | ||
652 | if (0 != GNUNET_OS_process_kill (sl->proc, SIGTERM)) | ||
653 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); | ||
654 | sl->killing_client = client; | ||
655 | GNUNET_SERVER_client_keep (client); | ||
991 | } | 656 | } |
992 | 657 | ||
993 | 658 | ||
@@ -999,15 +664,15 @@ static void | |||
999 | do_shutdown () | 664 | do_shutdown () |
1000 | { | 665 | { |
1001 | if (NULL != server) | 666 | if (NULL != server) |
1002 | { | 667 | { |
1003 | GNUNET_SERVER_destroy (server); | 668 | GNUNET_SERVER_destroy (server); |
1004 | server = NULL; | 669 | server = NULL; |
1005 | } | 670 | } |
1006 | if (GNUNET_SCHEDULER_NO_TASK != child_death_task) | 671 | if (GNUNET_SCHEDULER_NO_TASK != child_death_task) |
1007 | { | 672 | { |
1008 | GNUNET_SCHEDULER_cancel (child_death_task); | 673 | GNUNET_SCHEDULER_cancel (child_death_task); |
1009 | child_death_task = GNUNET_SCHEDULER_NO_TASK; | 674 | child_death_task = GNUNET_SCHEDULER_NO_TASK; |
1010 | } | 675 | } |
1011 | } | 676 | } |
1012 | 677 | ||
1013 | 678 | ||
@@ -1022,33 +687,50 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1022 | { | 687 | { |
1023 | struct ServiceList *pos; | 688 | struct ServiceList *pos; |
1024 | struct ServiceList *nxt; | 689 | struct ServiceList *nxt; |
690 | struct ServiceListeningInfo *sli; | ||
1025 | 691 | ||
1026 | #if DEBUG_ARM | ||
1027 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Stopping all services\n")); | ||
1028 | #endif | ||
1029 | if (GNUNET_SCHEDULER_NO_TASK != child_restart_task) | 692 | if (GNUNET_SCHEDULER_NO_TASK != child_restart_task) |
1030 | { | 693 | { |
1031 | GNUNET_SCHEDULER_cancel (child_restart_task); | 694 | GNUNET_SCHEDULER_cancel (child_restart_task); |
1032 | child_restart_task = GNUNET_SCHEDULER_NO_TASK; | 695 | child_restart_task = GNUNET_SCHEDULER_NO_TASK; |
1033 | } | 696 | } |
1034 | in_shutdown = GNUNET_YES; | 697 | in_shutdown = GNUNET_YES; |
1035 | stop_listening (NULL); | 698 | /* first, stop listening */ |
1036 | pos = running_head; | 699 | for (pos = running_head; NULL != pos; pos = pos->next) |
1037 | while (NULL != pos) | ||
1038 | { | ||
1039 | nxt = pos->next; | ||
1040 | if (pos->proc != NULL) | ||
1041 | { | 700 | { |
1042 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping service `%s'\n", pos->name); | 701 | while (NULL != (sli = pos->listen_head)) |
1043 | if (0 != GNUNET_OS_process_kill (pos->proc, SIGTERM)) | 702 | { |
1044 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); | 703 | GNUNET_CONTAINER_DLL_remove (pos->listen_head, |
704 | pos->listen_tail, sli); | ||
705 | if (sli->accept_task != GNUNET_SCHEDULER_NO_TASK) | ||
706 | { | ||
707 | GNUNET_SCHEDULER_cancel (sli->accept_task); | ||
708 | sli->accept_task = GNUNET_SCHEDULER_NO_TASK; | ||
709 | } | ||
710 | GNUNET_break (GNUNET_OK == | ||
711 | GNUNET_NETWORK_socket_close (sli->listen_socket)); | ||
712 | GNUNET_free (sli->service_addr); | ||
713 | GNUNET_free (sli); | ||
714 | } | ||
1045 | } | 715 | } |
1046 | else | 716 | /* then, shutdown all existing service processes */ |
717 | nxt = running_head; | ||
718 | while (NULL != (pos = nxt)) | ||
1047 | { | 719 | { |
1048 | free_service (pos); | 720 | nxt = pos->next; |
721 | if (pos->proc != NULL) | ||
722 | { | ||
723 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping service `%s'\n", | ||
724 | pos->name); | ||
725 | if (0 != GNUNET_OS_process_kill (pos->proc, SIGTERM)) | ||
726 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); | ||
727 | } | ||
728 | else | ||
729 | { | ||
730 | free_service (pos); | ||
731 | } | ||
1049 | } | 732 | } |
1050 | pos = nxt; | 733 | /* finally, should all service processes be already gone, terminate for real */ |
1051 | } | ||
1052 | if (running_head == NULL) | 734 | if (running_head == NULL) |
1053 | do_shutdown (); | 735 | do_shutdown (); |
1054 | } | 736 | } |
@@ -1061,10 +743,12 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1061 | * @param tc context | 743 | * @param tc context |
1062 | */ | 744 | */ |
1063 | static void | 745 | static void |
1064 | delayed_restart_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 746 | delayed_restart_task (void *cls, |
747 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1065 | { | 748 | { |
1066 | struct ServiceList *pos; | 749 | struct ServiceList *sl; |
1067 | struct GNUNET_TIME_Relative lowestRestartDelay; | 750 | struct GNUNET_TIME_Relative lowestRestartDelay; |
751 | struct ServiceListeningInfo *sli; | ||
1068 | 752 | ||
1069 | child_restart_task = GNUNET_SCHEDULER_NO_TASK; | 753 | child_restart_task = GNUNET_SCHEDULER_NO_TASK; |
1070 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | 754 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) |
@@ -1074,37 +758,56 @@ delayed_restart_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1074 | 758 | ||
1075 | /* check for services that need to be restarted due to | 759 | /* check for services that need to be restarted due to |
1076 | * configuration changes or because the last restart failed */ | 760 | * configuration changes or because the last restart failed */ |
1077 | pos = running_head; | 761 | for (sl = running_head; NULL != sl; sl = sl->next) |
1078 | while (pos != NULL) | ||
1079 | { | ||
1080 | if (pos->proc == NULL) | ||
1081 | { | 762 | { |
1082 | if (GNUNET_TIME_absolute_get_remaining (pos->restartAt).rel_value == 0) | 763 | if (sl->proc == NULL) |
1083 | { | 764 | { |
1084 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Restarting service `%s'.\n"), | 765 | /* service is currently not running */ |
1085 | pos->name); | 766 | if (GNUNET_TIME_absolute_get_remaining (sl->restart_at).rel_value == |
1086 | start_process (pos, NULL); | 767 | 0) |
1087 | } | 768 | { |
1088 | else | 769 | /* restart is now allowed */ |
1089 | { | 770 | if (sl->is_default) |
1090 | lowestRestartDelay = | 771 | { |
1091 | GNUNET_TIME_relative_min (lowestRestartDelay, | 772 | /* process should run by default, start immediately */ |
1092 | GNUNET_TIME_absolute_get_remaining | 773 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
1093 | (pos->restartAt)); | 774 | _("Restarting service `%s'.\n"), sl->name); |
1094 | } | 775 | start_process (sl); |
776 | } | ||
777 | else | ||
778 | { | ||
779 | /* process is run on-demand, ensure it is re-started if there is demand */ | ||
780 | for (sli = sl->listen_head; NULL != sli; sli = sli->next) | ||
781 | if (GNUNET_SCHEDULER_NO_TASK == sli->accept_task) | ||
782 | { | ||
783 | /* accept was actually paused, so start it again */ | ||
784 | sli->accept_task = | ||
785 | GNUNET_SCHEDULER_add_read_net | ||
786 | (GNUNET_TIME_UNIT_FOREVER_REL, sli->listen_socket, | ||
787 | &accept_connection, sli); | ||
788 | } | ||
789 | } | ||
790 | } | ||
791 | else | ||
792 | { | ||
793 | /* update calculation for earliest time to reactivate a service */ | ||
794 | lowestRestartDelay = | ||
795 | GNUNET_TIME_relative_min (lowestRestartDelay, | ||
796 | GNUNET_TIME_absolute_get_remaining | ||
797 | (sl->restart_at)); | ||
798 | } | ||
799 | } | ||
1095 | } | 800 | } |
1096 | pos = pos->next; | ||
1097 | } | ||
1098 | if (lowestRestartDelay.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value) | 801 | if (lowestRestartDelay.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value) |
1099 | { | 802 | { |
1100 | #if DEBUG_ARM | 803 | #if DEBUG_ARM |
1101 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Will restart process in %llums\n", | 804 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Will restart process in %llums\n", |
1102 | (unsigned long long) lowestRestartDelay.rel_value); | 805 | (unsigned long long) lowestRestartDelay.rel_value); |
1103 | #endif | 806 | #endif |
1104 | child_restart_task = | 807 | child_restart_task = |
1105 | GNUNET_SCHEDULER_add_delayed (lowestRestartDelay, &delayed_restart_task, | 808 | GNUNET_SCHEDULER_add_delayed (lowestRestartDelay, |
1106 | NULL); | 809 | &delayed_restart_task, NULL); |
1107 | } | 810 | } |
1108 | } | 811 | } |
1109 | 812 | ||
1110 | 813 | ||
@@ -1120,126 +823,150 @@ maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1120 | { | 823 | { |
1121 | struct ServiceList *pos; | 824 | struct ServiceList *pos; |
1122 | struct ServiceList *next; | 825 | struct ServiceList *next; |
826 | struct ServiceListeningInfo *sli; | ||
1123 | const char *statstr; | 827 | const char *statstr; |
1124 | int statcode; | 828 | int statcode; |
1125 | int ret; | 829 | int ret; |
1126 | char c[16]; | 830 | char c[16]; |
1127 | enum GNUNET_OS_ProcessStatusType statusType; | 831 | enum GNUNET_OS_ProcessStatusType statusType; |
1128 | unsigned long statusCode; | 832 | unsigned long statusCode; |
833 | const struct GNUNET_DISK_FileHandle *pr; | ||
1129 | 834 | ||
835 | pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); | ||
1130 | child_death_task = GNUNET_SCHEDULER_NO_TASK; | 836 | child_death_task = GNUNET_SCHEDULER_NO_TASK; |
1131 | if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) | 837 | if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) |
1132 | { | 838 | { |
1133 | /* shutdown scheduled us, ignore! */ | 839 | /* shutdown scheduled us, ignore! */ |
1134 | child_death_task = | 840 | child_death_task = |
1135 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, pr, | 841 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, |
1136 | &maint_child_death, NULL); | 842 | pr, &maint_child_death, NULL); |
1137 | return; | 843 | return; |
1138 | } | 844 | } |
1139 | /* consume the signal */ | 845 | /* consume the signal */ |
1140 | GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c))); | 846 | GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c))); |
1141 | 847 | ||
1142 | /* check for services that died (WAITPID) */ | 848 | /* check for services that died (WAITPID) */ |
1143 | next = running_head; | 849 | next = running_head; |
1144 | while (NULL != (pos = next)) | 850 | while (NULL != (pos = next)) |
1145 | { | ||
1146 | next = pos->next; | ||
1147 | if (pos->proc == NULL) | ||
1148 | continue; | ||
1149 | if ((GNUNET_SYSERR == | ||
1150 | (ret = GNUNET_OS_process_status (pos->proc, &statusType, &statusCode))) | ||
1151 | || ((ret == GNUNET_NO) || (statusType == GNUNET_OS_PROCESS_STOPPED) || | ||
1152 | (statusType == GNUNET_OS_PROCESS_RUNNING))) | ||
1153 | continue; | ||
1154 | |||
1155 | if (statusType == GNUNET_OS_PROCESS_EXITED) | ||
1156 | { | ||
1157 | statstr = _( /* process termination method */ "exit"); | ||
1158 | statcode = statusCode; | ||
1159 | } | ||
1160 | else if (statusType == GNUNET_OS_PROCESS_SIGNALED) | ||
1161 | { | ||
1162 | statstr = _( /* process termination method */ "signal"); | ||
1163 | statcode = statusCode; | ||
1164 | } | ||
1165 | else | ||
1166 | { | ||
1167 | statstr = _( /* process termination method */ "unknown"); | ||
1168 | statcode = 0; | ||
1169 | } | ||
1170 | GNUNET_OS_process_close (pos->proc); | ||
1171 | pos->proc = NULL; | ||
1172 | if (NULL != pos->killing_client) | ||
1173 | { | ||
1174 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Service `%s' stopped\n"), | ||
1175 | pos->name); | ||
1176 | signal_result (pos->killing_client, pos->name, | ||
1177 | GNUNET_MESSAGE_TYPE_ARM_IS_DOWN); | ||
1178 | GNUNET_SERVER_receive_done (pos->killing_client, GNUNET_OK); | ||
1179 | GNUNET_SERVER_client_drop (pos->killing_client); | ||
1180 | free_service (pos); | ||
1181 | continue; | ||
1182 | } | ||
1183 | if (GNUNET_YES != in_shutdown) | ||
1184 | { | 851 | { |
1185 | if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | 852 | next = pos->next; |
1186 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 853 | |
1187 | _ | 854 | if (pos->proc == NULL) |
1188 | ("Service `%s' terminated with status %s/%d, will try to restart it!\n"), | 855 | { |
1189 | pos->name, statstr, statcode); | 856 | if (GNUNET_YES == in_shutdown) |
1190 | /* schedule restart */ | 857 | free_service (pos); |
1191 | pos->restartAt = GNUNET_TIME_relative_to_absolute (pos->backoff); | 858 | continue; |
1192 | if (pos->backoff.rel_value < EXPONENTIAL_BACKOFF_THRESHOLD) | 859 | } |
1193 | pos->backoff = GNUNET_TIME_relative_multiply (pos->backoff, 2); | 860 | if ((GNUNET_SYSERR == |
1194 | if (GNUNET_SCHEDULER_NO_TASK != child_restart_task) | 861 | (ret = |
1195 | GNUNET_SCHEDULER_cancel (child_restart_task); | 862 | GNUNET_OS_process_status (pos->proc, &statusType, &statusCode))) |
1196 | child_restart_task = | 863 | || ((ret == GNUNET_NO) || (statusType == GNUNET_OS_PROCESS_STOPPED) |
1197 | GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, | 864 | || (statusType == GNUNET_OS_PROCESS_RUNNING))) |
1198 | &delayed_restart_task, NULL); | 865 | continue; |
866 | if (statusType == GNUNET_OS_PROCESS_EXITED) | ||
867 | { | ||
868 | statstr = _( /* process termination method */ "exit"); | ||
869 | statcode = statusCode; | ||
870 | } | ||
871 | else if (statusType == GNUNET_OS_PROCESS_SIGNALED) | ||
872 | { | ||
873 | statstr = _( /* process termination method */ "signal"); | ||
874 | statcode = statusCode; | ||
875 | } | ||
876 | else | ||
877 | { | ||
878 | statstr = _( /* process termination method */ "unknown"); | ||
879 | statcode = 0; | ||
880 | } | ||
881 | GNUNET_OS_process_close (pos->proc); | ||
882 | pos->proc = NULL; | ||
883 | if (NULL != pos->killing_client) | ||
884 | { | ||
885 | signal_result (pos->killing_client, pos->name, | ||
886 | GNUNET_ARM_PROCESS_DOWN); | ||
887 | GNUNET_SERVER_client_drop (pos->killing_client); | ||
888 | pos->killing_client = NULL; | ||
889 | /* process can still be re-started on-demand, ensure it is re-started if there is demand */ | ||
890 | for (sli = pos->listen_head; NULL != sli; sli = sli->next) | ||
891 | { | ||
892 | GNUNET_break (GNUNET_SCHEDULER_NO_TASK == sli->accept_task); | ||
893 | sli->accept_task = | ||
894 | GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | ||
895 | sli->listen_socket, | ||
896 | &accept_connection, sli); | ||
897 | } | ||
898 | continue; | ||
899 | } | ||
900 | if (GNUNET_YES != in_shutdown) | ||
901 | { | ||
902 | if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0)) | ||
903 | { | ||
904 | /* process terminated normally, allow restart at any time */ | ||
905 | pos->restart_at.abs_value = 0; | ||
906 | continue; | ||
907 | } | ||
908 | if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
909 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
910 | _ | ||
911 | ("Service `%s' terminated with status %s/%d, will restart in %llu ms\n"), | ||
912 | pos->name, statstr, statcode, pos->backoff.rel_value); | ||
913 | /* schedule restart */ | ||
914 | pos->restart_at = GNUNET_TIME_relative_to_absolute (pos->backoff); | ||
915 | pos->backoff = | ||
916 | GNUNET_TIME_relative_min (EXPONENTIAL_BACKOFF_THRESHOLD, | ||
917 | GNUNET_TIME_relative_multiply | ||
918 | (pos->backoff, 2)); | ||
919 | if (GNUNET_SCHEDULER_NO_TASK != child_restart_task) | ||
920 | GNUNET_SCHEDULER_cancel (child_restart_task); | ||
921 | child_restart_task = | ||
922 | GNUNET_SCHEDULER_add_with_priority | ||
923 | (GNUNET_SCHEDULER_PRIORITY_IDLE, &delayed_restart_task, NULL); | ||
924 | } | ||
925 | else | ||
926 | { | ||
927 | free_service (pos); | ||
928 | } | ||
1199 | } | 929 | } |
1200 | #if DEBUG_ARM | ||
1201 | else | ||
1202 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1203 | "Service `%s' terminated with status %s/%d\n", pos->name, | ||
1204 | statstr, statcode); | ||
1205 | #endif | ||
1206 | } | ||
1207 | child_death_task = | 930 | child_death_task = |
1208 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, pr, | 931 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, |
1209 | &maint_child_death, NULL); | 932 | pr, &maint_child_death, NULL); |
1210 | if (GNUNET_YES == in_shutdown) | ||
1211 | clean_up_running (); | ||
1212 | if ((NULL == running_head) && (GNUNET_YES == in_shutdown)) | 933 | if ((NULL == running_head) && (GNUNET_YES == in_shutdown)) |
1213 | do_shutdown (); | 934 | do_shutdown (); |
1214 | } | 935 | } |
1215 | 936 | ||
1216 | 937 | ||
938 | /** | ||
939 | * Transmit our shutdown acknowledgement to the client. | ||
940 | * | ||
941 | * @param cls the 'struct GNUNET_SERVER_Client' | ||
942 | * @param size number of bytes available in buf | ||
943 | * @param buf where to write the message | ||
944 | * @return number of bytes written | ||
945 | */ | ||
1217 | static size_t | 946 | static size_t |
1218 | transmit_shutdown_ack (void *cls, size_t size, void *buf) | 947 | transmit_shutdown_ack (void *cls, size_t size, void *buf) |
1219 | { | 948 | { |
1220 | struct GNUNET_SERVER_Client *client = cls; | 949 | struct GNUNET_SERVER_Client *client = cls; |
1221 | struct GNUNET_MessageHeader *msg; | 950 | struct GNUNET_ARM_ResultMessage *msg; |
1222 | |||
1223 | if (size < sizeof (struct GNUNET_MessageHeader)) | ||
1224 | { | ||
1225 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1226 | _("Failed to transmit shutdown ACK.\n")); | ||
1227 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1228 | return 0; /* client disconnected */ | ||
1229 | } | ||
1230 | |||
1231 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting shutdown ACK.\n")); | ||
1232 | 951 | ||
952 | if (size < sizeof (struct GNUNET_ARM_ResultMessage)) | ||
953 | { | ||
954 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
955 | _("Failed to transmit shutdown ACK.\n")); | ||
956 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
957 | return 0; /* client disconnected */ | ||
958 | } | ||
1233 | /* Make the connection flushing for the purpose of ACK transmitting, | 959 | /* Make the connection flushing for the purpose of ACK transmitting, |
1234 | * needed on W32 to ensure that the message is even received, harmless | 960 | * needed on W32 to ensure that the message is even received, harmless |
1235 | * on other platforms... */ | 961 | * on other platforms... */ |
1236 | GNUNET_break (GNUNET_OK == GNUNET_SERVER_client_disable_corking (client)); | 962 | GNUNET_break (GNUNET_OK == GNUNET_SERVER_client_disable_corking (client)); |
1237 | msg = (struct GNUNET_MessageHeader *) buf; | 963 | msg = (struct GNUNET_ARM_ResultMessage *) buf; |
1238 | msg->type = htons (GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN_ACK); | 964 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_ARM_RESULT); |
1239 | msg->size = htons (sizeof (struct GNUNET_MessageHeader)); | 965 | msg->header.size = htons (sizeof (struct GNUNET_ARM_ResultMessage)); |
966 | msg->status = htonl ((uint32_t) GNUNET_ARM_PROCESS_SHUTDOWN); | ||
1240 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 967 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
1241 | GNUNET_SERVER_client_drop (client); | 968 | GNUNET_SERVER_client_drop (client); |
1242 | return sizeof (struct GNUNET_MessageHeader); | 969 | return sizeof (struct GNUNET_ARM_ResultMessage); |
1243 | } | 970 | } |
1244 | 971 | ||
1245 | 972 | ||
@@ -1252,17 +979,15 @@ transmit_shutdown_ack (void *cls, size_t size, void *buf) | |||
1252 | */ | 979 | */ |
1253 | static void | 980 | static void |
1254 | handle_shutdown (void *cls, struct GNUNET_SERVER_Client *client, | 981 | handle_shutdown (void *cls, struct GNUNET_SERVER_Client *client, |
1255 | const struct GNUNET_MessageHeader *message) | 982 | const struct GNUNET_MessageHeader *message) |
1256 | { | 983 | { |
984 | GNUNET_SCHEDULER_shutdown (); | ||
1257 | GNUNET_SERVER_client_keep (client); | 985 | GNUNET_SERVER_client_keep (client); |
1258 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1259 | _("Initiating shutdown as requested by client.\n")); | ||
1260 | GNUNET_SERVER_notify_transmit_ready (client, | 986 | GNUNET_SERVER_notify_transmit_ready (client, |
1261 | sizeof (struct GNUNET_MessageHeader), | 987 | sizeof (struct GNUNET_ARM_ResultMessage), |
1262 | GNUNET_TIME_UNIT_FOREVER_REL, | 988 | GNUNET_TIME_UNIT_FOREVER_REL, |
1263 | &transmit_shutdown_ack, client); | 989 | &transmit_shutdown_ack, client); |
1264 | GNUNET_SERVER_client_persist_ (client); | 990 | GNUNET_SERVER_client_persist_ (client); |
1265 | GNUNET_SCHEDULER_shutdown (); | ||
1266 | } | 991 | } |
1267 | 992 | ||
1268 | 993 | ||
@@ -1274,13 +999,77 @@ static void | |||
1274 | sighandler_child_death () | 999 | sighandler_child_death () |
1275 | { | 1000 | { |
1276 | static char c; | 1001 | static char c; |
1277 | int old_errno = errno; /* back-up errno */ | 1002 | int old_errno = errno; /* back-up errno */ |
1278 | 1003 | ||
1279 | GNUNET_break (1 == | 1004 | GNUNET_break (1 == |
1280 | GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle | 1005 | GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle |
1281 | (sigpipe, GNUNET_DISK_PIPE_END_WRITE), | 1006 | (sigpipe, GNUNET_DISK_PIPE_END_WRITE), |
1282 | &c, sizeof (c))); | 1007 | &c, sizeof (c))); |
1283 | errno = old_errno; /* restore errno */ | 1008 | errno = old_errno; /* restore errno */ |
1009 | } | ||
1010 | |||
1011 | |||
1012 | /** | ||
1013 | * Setup our service record for the given section in the configuration file | ||
1014 | * (assuming the section is for a service). | ||
1015 | * | ||
1016 | * @param cls unused | ||
1017 | * @param section a section in the configuration file | ||
1018 | * @return GNUNET_OK (continue) | ||
1019 | */ | ||
1020 | static void | ||
1021 | setup_service (void *cls, const char *section) | ||
1022 | { | ||
1023 | struct ServiceList *sl; | ||
1024 | char *binary; | ||
1025 | char *config; | ||
1026 | struct stat sbuf; | ||
1027 | struct sockaddr **addrs; | ||
1028 | socklen_t *addr_lens; | ||
1029 | int ret; | ||
1030 | unsigned int i; | ||
1031 | |||
1032 | if (strcasecmp (section, "arm") == 0) | ||
1033 | return; | ||
1034 | if (GNUNET_OK != | ||
1035 | GNUNET_CONFIGURATION_get_value_string (cfg, section, "BINARY", &binary)) | ||
1036 | { | ||
1037 | /* not a service section */ | ||
1038 | return; | ||
1039 | } | ||
1040 | config = NULL; | ||
1041 | if ((GNUNET_OK != | ||
1042 | GNUNET_CONFIGURATION_get_value_filename (cfg, section, "CONFIG", | ||
1043 | &config)) || | ||
1044 | (0 != STAT (config, &sbuf))) | ||
1045 | { | ||
1046 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1047 | _ | ||
1048 | ("Configuration file `%s' for service `%s' not valid: %s\n"), | ||
1049 | config, section, | ||
1050 | (config == NULL) ? _("option missing") : STRERROR (errno)); | ||
1051 | GNUNET_free (binary); | ||
1052 | GNUNET_free_non_null (config); | ||
1053 | return; | ||
1054 | } | ||
1055 | sl = GNUNET_malloc (sizeof (struct ServiceList)); | ||
1056 | sl->name = GNUNET_strdup (section); | ||
1057 | sl->binary = binary; | ||
1058 | sl->config = config; | ||
1059 | sl->backoff = GNUNET_TIME_UNIT_MILLISECONDS; | ||
1060 | sl->restart_at = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
1061 | GNUNET_CONTAINER_DLL_insert (running_head, running_tail, sl); | ||
1062 | if (GNUNET_YES != | ||
1063 | GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "AUTOSTART")) | ||
1064 | return; | ||
1065 | if (0 >= (ret = GNUNET_SERVICE_get_server_addresses (section, cfg, | ||
1066 | &addrs, &addr_lens))) | ||
1067 | return; | ||
1068 | /* this will free (or capture) addrs[i] */ | ||
1069 | for (i = 0; i < ret; i++) | ||
1070 | create_listen_socket (addrs[i], addr_lens[i], sl); | ||
1071 | GNUNET_free (addrs); | ||
1072 | GNUNET_free (addr_lens); | ||
1284 | } | 1073 | } |
1285 | 1074 | ||
1286 | 1075 | ||
@@ -1303,64 +1092,68 @@ run (void *cls, struct GNUNET_SERVER_Handle *serv, | |||
1303 | {NULL, NULL, 0, 0} | 1092 | {NULL, NULL, 0, 0} |
1304 | }; | 1093 | }; |
1305 | char *defaultservices; | 1094 | char *defaultservices; |
1306 | char *pos; | 1095 | const char *pos; |
1096 | struct ServiceList *sl; | ||
1307 | 1097 | ||
1308 | cfg = c; | 1098 | cfg = c; |
1309 | server = serv; | 1099 | server = serv; |
1310 | GNUNET_assert (serv != NULL); | 1100 | GNUNET_assert (serv != NULL); |
1311 | pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); | ||
1312 | GNUNET_assert (pr != NULL); | ||
1313 | GNUNET_SERVER_ignore_shutdown (serv, GNUNET_YES); | 1101 | GNUNET_SERVER_ignore_shutdown (serv, GNUNET_YES); |
1314 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, | 1102 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, |
1315 | NULL); | 1103 | NULL); |
1316 | child_death_task = | 1104 | child_death_task = |
1317 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, pr, | 1105 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, |
1318 | &maint_child_death, NULL); | 1106 | GNUNET_DISK_pipe_handle (sigpipe, |
1107 | GNUNET_DISK_PIPE_END_READ), | ||
1108 | &maint_child_death, NULL); | ||
1319 | 1109 | ||
1320 | if (GNUNET_OK != | 1110 | if (GNUNET_OK != |
1321 | GNUNET_CONFIGURATION_get_value_string (cfg, "ARM", "GLOBAL_PREFIX", | 1111 | GNUNET_CONFIGURATION_get_value_string (cfg, "ARM", "GLOBAL_PREFIX", |
1322 | &prefix_command)) | 1112 | &prefix_command)) |
1323 | prefix_command = GNUNET_strdup (""); | 1113 | prefix_command = GNUNET_strdup (""); |
1324 | if (GNUNET_OK != | 1114 | if (GNUNET_OK != |
1325 | GNUNET_CONFIGURATION_get_value_string (cfg, "ARM", "GLOBAL_POSTFIX", | 1115 | GNUNET_CONFIGURATION_get_value_string (cfg, "ARM", "GLOBAL_POSTFIX", |
1326 | &final_option)) | 1116 | &final_option)) |
1327 | final_option = GNUNET_strdup (""); | 1117 | final_option = GNUNET_strdup (""); |
1118 | |||
1119 | GNUNET_CONFIGURATION_iterate_sections (cfg, &setup_service, NULL); | ||
1120 | |||
1328 | /* start default services... */ | 1121 | /* start default services... */ |
1329 | if (GNUNET_OK == | 1122 | if (GNUNET_OK == |
1330 | GNUNET_CONFIGURATION_get_value_string (cfg, "ARM", "DEFAULTSERVICES", | 1123 | GNUNET_CONFIGURATION_get_value_string (cfg, "ARM", "DEFAULTSERVICES", |
1331 | &defaultservices)) | 1124 | &defaultservices)) |
1332 | { | ||
1333 | #if DEBUG_ARM | ||
1334 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting default services `%s'\n", | ||
1335 | defaultservices); | ||
1336 | #endif | ||
1337 | if (0 < strlen (defaultservices)) | ||
1338 | { | 1125 | { |
1339 | pos = strtok (defaultservices, " "); | 1126 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
1340 | while (pos != NULL) | 1127 | _("Starting default services `%s'\n"), defaultservices); |
1341 | { | 1128 | if (0 < strlen (defaultservices)) |
1342 | start_service (NULL, pos, NULL); | 1129 | { |
1343 | pos = strtok (NULL, " "); | 1130 | for (pos = strtok (defaultservices, " "); NULL != pos; |
1344 | } | 1131 | pos = strtok (NULL, " ")) |
1132 | { | ||
1133 | sl = find_service (pos); | ||
1134 | if (NULL == sl) | ||
1135 | { | ||
1136 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1137 | _ | ||
1138 | ("Default service `%s' not configured correctly!\n"), | ||
1139 | pos); | ||
1140 | continue; | ||
1141 | } | ||
1142 | sl->is_default = GNUNET_YES; | ||
1143 | start_process (sl); | ||
1144 | } | ||
1145 | } | ||
1146 | GNUNET_free (defaultservices); | ||
1345 | } | 1147 | } |
1346 | GNUNET_free (defaultservices); | ||
1347 | } | ||
1348 | else | 1148 | else |
1349 | { | 1149 | { |
1350 | #if DEBUG_ARM | 1150 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
1351 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No default services configured.\n"); | 1151 | _ |
1352 | #endif | 1152 | ("No default services configured, GNUnet will not really start right now.\n")); |
1353 | } | 1153 | } |
1354 | |||
1355 | /* create listening sockets for future services */ | ||
1356 | prepare_services (cfg); | ||
1357 | 1154 | ||
1358 | /* process client requests */ | 1155 | /* process client requests */ |
1359 | GNUNET_SERVER_add_handlers (server, handlers); | 1156 | GNUNET_SERVER_add_handlers (server, handlers); |
1360 | |||
1361 | /* manage services */ | ||
1362 | GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, | ||
1363 | &config_change_task, NULL); | ||
1364 | } | 1157 | } |
1365 | 1158 | ||
1366 | 1159 | ||
@@ -1380,10 +1173,10 @@ main (int argc, char *const *argv) | |||
1380 | sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO); | 1173 | sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO); |
1381 | GNUNET_assert (sigpipe != NULL); | 1174 | GNUNET_assert (sigpipe != NULL); |
1382 | shc_chld = | 1175 | shc_chld = |
1383 | GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); | 1176 | GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); |
1384 | ret = | 1177 | ret = |
1385 | (GNUNET_OK == | 1178 | (GNUNET_OK == |
1386 | GNUNET_SERVICE_run (argc, argv, "arm", GNUNET_YES, &run, NULL)) ? 0 : 1; | 1179 | GNUNET_SERVICE_run (argc, argv, "arm", GNUNET_YES, &run, NULL)) ? 0 : 1; |
1387 | GNUNET_SIGNAL_handler_uninstall (shc_chld); | 1180 | GNUNET_SIGNAL_handler_uninstall (shc_chld); |
1388 | shc_chld = NULL; | 1181 | shc_chld = NULL; |
1389 | GNUNET_DISK_pipe_close (sigpipe); | 1182 | GNUNET_DISK_pipe_close (sigpipe); |
@@ -1391,6 +1184,7 @@ main (int argc, char *const *argv) | |||
1391 | return ret; | 1184 | return ret; |
1392 | } | 1185 | } |
1393 | 1186 | ||
1187 | |||
1394 | #ifdef LINUX | 1188 | #ifdef LINUX |
1395 | #include <malloc.h> | 1189 | #include <malloc.h> |
1396 | 1190 | ||
diff --git a/src/arm/mockup-service.c b/src/arm/mockup-service.c index 53a502fa8..1e9748809 100644 --- a/src/arm/mockup-service.c +++ b/src/arm/mockup-service.c | |||
@@ -46,7 +46,7 @@ transmit_shutdown_ack (void *cls, size_t size, void *buf) | |||
46 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting shutdown ACK.\n")); | 46 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Transmitting shutdown ACK.\n")); |
47 | 47 | ||
48 | msg = (struct GNUNET_MessageHeader *) buf; | 48 | msg = (struct GNUNET_MessageHeader *) buf; |
49 | msg->type = htons (GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN_ACK); | 49 | msg->type = htons (GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN); |
50 | msg->size = htons (sizeof (struct GNUNET_MessageHeader)); | 50 | msg->size = htons (sizeof (struct GNUNET_MessageHeader)); |
51 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 51 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
52 | GNUNET_SERVER_client_drop (client); | 52 | GNUNET_SERVER_client_drop (client); |
diff --git a/src/arm/test_arm_api.c b/src/arm/test_arm_api.c index 5fbbaa6b1..74e225809 100644 --- a/src/arm/test_arm_api.c +++ b/src/arm/test_arm_api.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2009 Christian Grothoff (and other contributing authors) | 3 | (C) 2009, 2011 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 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 | 6 | it under the terms of the GNU General Public License as published |
@@ -45,18 +45,20 @@ static struct GNUNET_ARM_Handle *arm; | |||
45 | static int ok = 1; | 45 | static int ok = 1; |
46 | 46 | ||
47 | static void | 47 | static void |
48 | arm_stopped (void *cls, int success) | 48 | arm_stopped (void *cls, enum GNUNET_ARM_ProcessStatus success) |
49 | { | 49 | { |
50 | if (success != GNUNET_NO) | 50 | GNUNET_break (success == GNUNET_ARM_PROCESS_DOWN); |
51 | if (success != GNUNET_ARM_PROCESS_DOWN) | ||
51 | ok = 3; | 52 | ok = 3; |
52 | else if (ok == 1) | 53 | else if (ok == 1) |
53 | ok = 0; | 54 | ok = 0; |
54 | } | 55 | } |
55 | 56 | ||
57 | |||
56 | static void | 58 | static void |
57 | arm_notify_stop (void *cls, int success) | 59 | arm_notify_stop (void *cls, enum GNUNET_ARM_ProcessStatus success) |
58 | { | 60 | { |
59 | GNUNET_assert (success == GNUNET_NO); | 61 | GNUNET_break (success == GNUNET_ARM_PROCESS_DOWN); |
60 | #if START_ARM | 62 | #if START_ARM |
61 | GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, &arm_stopped, NULL); | 63 | GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, &arm_stopped, NULL); |
62 | #endif | 64 | #endif |
@@ -67,49 +69,50 @@ static void | |||
67 | dns_notify (void *cls, const struct sockaddr *addr, socklen_t addrlen) | 69 | dns_notify (void *cls, const struct sockaddr *addr, socklen_t addrlen) |
68 | { | 70 | { |
69 | if (addr == NULL) | 71 | if (addr == NULL) |
70 | { | ||
71 | if (ok != 0) | ||
72 | { | 72 | { |
73 | GNUNET_break (0); | 73 | if (ok != 0) |
74 | ok = 2; | 74 | { |
75 | GNUNET_break (0); | ||
76 | ok = 2; | ||
77 | } | ||
78 | GNUNET_ARM_stop_service (arm, "resolver", TIMEOUT, &arm_notify_stop, | ||
79 | NULL); | ||
80 | return; | ||
75 | } | 81 | } |
76 | GNUNET_ARM_stop_service (arm, "resolver", TIMEOUT, &arm_notify_stop, NULL); | 82 | GNUNET_break (addr != NULL); |
77 | return; | ||
78 | } | ||
79 | GNUNET_assert (addr != NULL); | ||
80 | ok = 0; | 83 | ok = 0; |
81 | } | 84 | } |
82 | 85 | ||
83 | 86 | ||
84 | static void | 87 | static void |
85 | resolver_notify (void *cls, int success) | 88 | resolver_notify (void *cls, enum GNUNET_ARM_ProcessStatus success) |
86 | { | 89 | { |
87 | if (success != GNUNET_YES) | 90 | if (success != GNUNET_ARM_PROCESS_STARTING) |
88 | { | 91 | { |
89 | GNUNET_break (0); | 92 | GNUNET_break (0); |
90 | ok = 2; | 93 | ok = 2; |
91 | #if START_ARM | 94 | #if START_ARM |
92 | GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, &arm_stopped, NULL); | 95 | GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, &arm_stopped, NULL); |
93 | #endif | 96 | #endif |
94 | return; | 97 | return; |
95 | } | 98 | } |
96 | GNUNET_RESOLVER_ip_get ("localhost", AF_INET, TIMEOUT, &dns_notify, NULL); | 99 | GNUNET_RESOLVER_ip_get ("localhost", AF_INET, TIMEOUT, &dns_notify, NULL); |
97 | } | 100 | } |
98 | 101 | ||
99 | 102 | ||
100 | static void | 103 | static void |
101 | arm_notify (void *cls, int success) | 104 | arm_notify (void *cls, enum GNUNET_ARM_ProcessStatus success) |
102 | { | 105 | { |
103 | if (success != GNUNET_YES) | 106 | if (success != GNUNET_ARM_PROCESS_STARTING) |
104 | { | 107 | { |
105 | GNUNET_break (0); | 108 | GNUNET_break (0); |
106 | ok = 2; | 109 | ok = 2; |
107 | #if START_ARM | 110 | #if START_ARM |
108 | GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, &arm_stopped, NULL); | 111 | GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, &arm_stopped, NULL); |
109 | #endif | 112 | #endif |
110 | } | 113 | } |
111 | GNUNET_ARM_start_service (arm, "resolver", START_TIMEOUT, &resolver_notify, | 114 | GNUNET_ARM_start_service (arm, "resolver", START_TIMEOUT, &resolver_notify, |
112 | NULL); | 115 | NULL); |
113 | } | 116 | } |
114 | 117 | ||
115 | 118 | ||
@@ -143,9 +146,9 @@ check () | |||
143 | GNUNET_GETOPT_OPTION_END | 146 | GNUNET_GETOPT_OPTION_END |
144 | }; | 147 | }; |
145 | GNUNET_assert (GNUNET_OK == | 148 | GNUNET_assert (GNUNET_OK == |
146 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, | 149 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, |
147 | argv, "test-arm-api", "nohelp", options, | 150 | argv, "test-arm-api", "nohelp", options, |
148 | &task, NULL)); | 151 | &task, NULL)); |
149 | return ok; | 152 | return ok; |
150 | } | 153 | } |
151 | 154 | ||
@@ -157,11 +160,11 @@ main (int argc, char *argv[]) | |||
157 | 160 | ||
158 | GNUNET_log_setup ("test-arm-api", | 161 | GNUNET_log_setup ("test-arm-api", |
159 | #if VERBOSE | 162 | #if VERBOSE |
160 | "DEBUG", | 163 | "DEBUG", |
161 | #else | 164 | #else |
162 | "WARNING", | 165 | "WARNING", |
163 | #endif | 166 | #endif |
164 | NULL); | 167 | NULL); |
165 | ret = check (); | 168 | ret = check (); |
166 | 169 | ||
167 | return ret; | 170 | return ret; |
diff --git a/src/arm/test_exponential_backoff.c b/src/arm/test_exponential_backoff.c index 3ff4d284f..029ed145a 100644 --- a/src/arm/test_exponential_backoff.c +++ b/src/arm/test_exponential_backoff.c | |||
@@ -29,22 +29,33 @@ | |||
29 | #include "gnunet_protocols.h" | 29 | #include "gnunet_protocols.h" |
30 | 30 | ||
31 | #define VERBOSE GNUNET_EXTRA_LOGGING | 31 | #define VERBOSE GNUNET_EXTRA_LOGGING |
32 | |||
32 | #define START_ARM GNUNET_YES | 33 | #define START_ARM GNUNET_YES |
34 | |||
33 | #define LOG_BACKOFF GNUNET_NO | 35 | #define LOG_BACKOFF GNUNET_NO |
36 | |||
34 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) | 37 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) |
38 | |||
35 | #define SERVICE_TEST_TIMEOUT GNUNET_TIME_UNIT_FOREVER_REL | 39 | #define SERVICE_TEST_TIMEOUT GNUNET_TIME_UNIT_FOREVER_REL |
40 | |||
36 | #define FIVE_MILLISECONDS GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 5) | 41 | #define FIVE_MILLISECONDS GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 5) |
37 | 42 | ||
43 | |||
38 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 44 | static const struct GNUNET_CONFIGURATION_Handle *cfg; |
45 | |||
39 | static struct GNUNET_ARM_Handle *arm; | 46 | static struct GNUNET_ARM_Handle *arm; |
47 | |||
40 | static int ok = 1; | 48 | static int ok = 1; |
41 | 49 | ||
42 | static int trialCount; | 50 | static int trialCount; |
51 | |||
43 | static struct GNUNET_TIME_Absolute startedWaitingAt; | 52 | static struct GNUNET_TIME_Absolute startedWaitingAt; |
53 | |||
44 | struct GNUNET_TIME_Relative waitedFor; | 54 | struct GNUNET_TIME_Relative waitedFor; |
45 | 55 | ||
46 | #if LOG_BACKOFF | 56 | #if LOG_BACKOFF |
47 | static FILE *killLogFilePtr; | 57 | static FILE *killLogFilePtr; |
58 | |||
48 | static char *killLogFileName; | 59 | static char *killLogFileName; |
49 | #endif | 60 | #endif |
50 | 61 | ||
@@ -89,7 +100,7 @@ struct ShutdownContext | |||
89 | /** | 100 | /** |
90 | * Handler receiving response to service shutdown requests. | 101 | * Handler receiving response to service shutdown requests. |
91 | * First call with NULL: service misbehaving, or something. | 102 | * First call with NULL: service misbehaving, or something. |
92 | * First call with GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN_ACK: | 103 | * First call with GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN: |
93 | * - service will shutdown | 104 | * - service will shutdown |
94 | * Second call with NULL: | 105 | * Second call with NULL: |
95 | * - service has now really shut down. | 106 | * - service has now really shut down. |
@@ -103,53 +114,56 @@ service_shutdown_handler (void *cls, const struct GNUNET_MessageHeader *msg) | |||
103 | struct ShutdownContext *shutdown_ctx = cls; | 114 | struct ShutdownContext *shutdown_ctx = cls; |
104 | 115 | ||
105 | if ((msg == NULL) && (shutdown_ctx->confirmed != GNUNET_YES)) | 116 | if ((msg == NULL) && (shutdown_ctx->confirmed != GNUNET_YES)) |
106 | { | 117 | { |
107 | /* Means the other side closed the connection and never confirmed a shutdown */ | 118 | /* Means the other side closed the connection and never confirmed a shutdown */ |
108 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 119 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
109 | "Service handle shutdown before ACK!\n"); | 120 | "Service handle shutdown before ACK!\n"); |
110 | if (shutdown_ctx->cont != NULL) | 121 | if (shutdown_ctx->cont != NULL) |
111 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR); | 122 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR); |
112 | GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); | 123 | GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); |
113 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); | 124 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); |
114 | GNUNET_free (shutdown_ctx); | 125 | GNUNET_free (shutdown_ctx); |
115 | } | 126 | } |
116 | else if ((msg == NULL) && (shutdown_ctx->confirmed == GNUNET_YES)) | 127 | else if ((msg == NULL) && (shutdown_ctx->confirmed == GNUNET_YES)) |
117 | { | ||
118 | #if VERBOSE | ||
119 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service shutdown complete.\n"); | ||
120 | #endif | ||
121 | if (shutdown_ctx->cont != NULL) | ||
122 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_NO); | ||
123 | |||
124 | GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); | ||
125 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); | ||
126 | GNUNET_free (shutdown_ctx); | ||
127 | } | ||
128 | else | ||
129 | { | ||
130 | GNUNET_assert (ntohs (msg->size) == sizeof (struct GNUNET_MessageHeader)); | ||
131 | switch (ntohs (msg->type)) | ||
132 | { | 128 | { |
133 | case GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN_ACK: | ||
134 | #if VERBOSE | 129 | #if VERBOSE |
135 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 130 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service shutdown complete.\n"); |
136 | "Received confirmation for service shutdown.\n"); | ||
137 | #endif | 131 | #endif |
138 | shutdown_ctx->confirmed = GNUNET_YES; | ||
139 | GNUNET_CLIENT_receive (shutdown_ctx->sock, &service_shutdown_handler, | ||
140 | shutdown_ctx, GNUNET_TIME_UNIT_FOREVER_REL); | ||
141 | break; | ||
142 | default: /* Fall through */ | ||
143 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Service shutdown refused!\n"); | ||
144 | if (shutdown_ctx->cont != NULL) | 132 | if (shutdown_ctx->cont != NULL) |
145 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_YES); | 133 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_NO); |
146 | 134 | ||
147 | GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); | 135 | GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); |
148 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); | 136 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); |
149 | GNUNET_free (shutdown_ctx); | 137 | GNUNET_free (shutdown_ctx); |
150 | break; | ||
151 | } | 138 | } |
152 | } | 139 | else |
140 | { | ||
141 | GNUNET_assert (ntohs (msg->size) == | ||
142 | sizeof (struct GNUNET_MessageHeader)); | ||
143 | switch (ntohs (msg->type)) | ||
144 | { | ||
145 | case GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN: | ||
146 | #if VERBOSE | ||
147 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
148 | "Received confirmation for service shutdown.\n"); | ||
149 | #endif | ||
150 | shutdown_ctx->confirmed = GNUNET_YES; | ||
151 | GNUNET_CLIENT_receive (shutdown_ctx->sock, | ||
152 | &service_shutdown_handler, shutdown_ctx, | ||
153 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
154 | break; | ||
155 | default: /* Fall through */ | ||
156 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
157 | "Service shutdown refused!\n"); | ||
158 | if (shutdown_ctx->cont != NULL) | ||
159 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_YES); | ||
160 | |||
161 | GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); | ||
162 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); | ||
163 | GNUNET_free (shutdown_ctx); | ||
164 | break; | ||
165 | } | ||
166 | } | ||
153 | } | 167 | } |
154 | 168 | ||
155 | /** | 169 | /** |
@@ -160,7 +174,7 @@ service_shutdown_handler (void *cls, const struct GNUNET_MessageHeader *msg) | |||
160 | */ | 174 | */ |
161 | void | 175 | void |
162 | service_shutdown_cancel (void *cls, | 176 | service_shutdown_cancel (void *cls, |
163 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 177 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
164 | { | 178 | { |
165 | struct ShutdownContext *shutdown_ctx = cls; | 179 | struct ShutdownContext *shutdown_ctx = cls; |
166 | 180 | ||
@@ -187,21 +201,21 @@ write_shutdown (void *cls, size_t size, void *buf) | |||
187 | struct ShutdownContext *shutdown_ctx = cls; | 201 | struct ShutdownContext *shutdown_ctx = cls; |
188 | 202 | ||
189 | if (size < sizeof (struct GNUNET_MessageHeader)) | 203 | if (size < sizeof (struct GNUNET_MessageHeader)) |
190 | { | 204 | { |
191 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 205 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
192 | _("Failed to transmit shutdown request to client.\n")); | 206 | _("Failed to transmit shutdown request to client.\n")); |
193 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR); | 207 | shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR); |
194 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); | 208 | GNUNET_CLIENT_disconnect (shutdown_ctx->sock, GNUNET_NO); |
195 | GNUNET_free (shutdown_ctx); | 209 | GNUNET_free (shutdown_ctx); |
196 | return 0; /* client disconnected */ | 210 | return 0; /* client disconnected */ |
197 | } | 211 | } |
198 | 212 | ||
199 | GNUNET_CLIENT_receive (shutdown_ctx->sock, &service_shutdown_handler, | 213 | GNUNET_CLIENT_receive (shutdown_ctx->sock, &service_shutdown_handler, |
200 | shutdown_ctx, GNUNET_TIME_UNIT_FOREVER_REL); | 214 | shutdown_ctx, GNUNET_TIME_UNIT_FOREVER_REL); |
201 | shutdown_ctx->cancel_task = | 215 | shutdown_ctx->cancel_task = |
202 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining | 216 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining |
203 | (shutdown_ctx->timeout), | 217 | (shutdown_ctx->timeout), |
204 | &service_shutdown_cancel, shutdown_ctx); | 218 | &service_shutdown_cancel, shutdown_ctx); |
205 | msg = (struct GNUNET_MessageHeader *) buf; | 219 | msg = (struct GNUNET_MessageHeader *) buf; |
206 | msg->type = htons (GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN); | 220 | msg->type = htons (GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN); |
207 | msg->size = htons (sizeof (struct GNUNET_MessageHeader)); | 221 | msg->size = htons (sizeof (struct GNUNET_MessageHeader)); |
@@ -224,8 +238,8 @@ write_shutdown (void *cls, size_t size, void *buf) | |||
224 | */ | 238 | */ |
225 | static void | 239 | static void |
226 | arm_service_shutdown (struct GNUNET_CLIENT_Connection *sock, | 240 | arm_service_shutdown (struct GNUNET_CLIENT_Connection *sock, |
227 | struct GNUNET_TIME_Relative timeout, | 241 | struct GNUNET_TIME_Relative timeout, |
228 | GNUNET_CLIENT_ShutdownTask cont, void *cont_cls) | 242 | GNUNET_CLIENT_ShutdownTask cont, void *cont_cls) |
229 | { | 243 | { |
230 | struct ShutdownContext *shutdown_ctx; | 244 | struct ShutdownContext *shutdown_ctx; |
231 | 245 | ||
@@ -235,16 +249,17 @@ arm_service_shutdown (struct GNUNET_CLIENT_Connection *sock, | |||
235 | shutdown_ctx->sock = sock; | 249 | shutdown_ctx->sock = sock; |
236 | shutdown_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); | 250 | shutdown_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); |
237 | GNUNET_CLIENT_notify_transmit_ready (sock, | 251 | GNUNET_CLIENT_notify_transmit_ready (sock, |
238 | sizeof (struct GNUNET_MessageHeader), | 252 | sizeof (struct GNUNET_MessageHeader), |
239 | timeout, GNUNET_NO, &write_shutdown, | 253 | timeout, GNUNET_NO, &write_shutdown, |
240 | shutdown_ctx); | 254 | shutdown_ctx); |
241 | } | 255 | } |
242 | 256 | ||
243 | 257 | ||
244 | static void | 258 | static void |
245 | arm_notify_stop (void *cls, int success) | 259 | arm_notify_stop (void *cls, enum GNUNET_ARM_ProcessStatus status) |
246 | { | 260 | { |
247 | GNUNET_assert (success == GNUNET_NO); | 261 | GNUNET_assert ( (status == GNUNET_ARM_PROCESS_DOWN) || |
262 | (status == GNUNET_ARM_PROCESS_ALREADY_DOWN) ); | ||
248 | #if START_ARM | 263 | #if START_ARM |
249 | GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, NULL, NULL); | 264 | GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, NULL, NULL); |
250 | #endif | 265 | #endif |
@@ -256,20 +271,19 @@ kill_task (void *cbData, const struct GNUNET_SCHEDULER_TaskContext *tc); | |||
256 | 271 | ||
257 | 272 | ||
258 | static void | 273 | static void |
259 | do_nothing_notify (void *cls, int success) | 274 | do_nothing_notify (void *cls, enum GNUNET_ARM_ProcessStatus status) |
260 | { | 275 | { |
261 | GNUNET_assert (success == GNUNET_YES); | 276 | GNUNET_assert (status == GNUNET_ARM_PROCESS_STARTING); |
262 | ok = 1; | 277 | ok = 1; |
263 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &kill_task, NULL); | 278 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &kill_task, NULL); |
264 | } | 279 | } |
265 | 280 | ||
266 | |||
267 | static void | 281 | static void |
268 | arm_notify (void *cls, int success) | 282 | arm_notify (void *cls, enum GNUNET_ARM_ProcessStatus status) |
269 | { | 283 | { |
270 | GNUNET_assert (success == GNUNET_YES); | 284 | GNUNET_assert (status == GNUNET_ARM_PROCESS_STARTING); |
271 | GNUNET_ARM_start_service (arm, "do-nothing", TIMEOUT, &do_nothing_notify, | 285 | GNUNET_ARM_start_service (arm, "do-nothing", TIMEOUT, &do_nothing_notify, |
272 | NULL); | 286 | NULL); |
273 | } | 287 | } |
274 | 288 | ||
275 | 289 | ||
@@ -279,7 +293,8 @@ kill_task (void *cbData, const struct GNUNET_SCHEDULER_TaskContext *tc); | |||
279 | 293 | ||
280 | static void | 294 | static void |
281 | do_nothing_restarted_notify_task (void *cls, | 295 | do_nothing_restarted_notify_task (void *cls, |
282 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 296 | const struct GNUNET_SCHEDULER_TaskContext |
297 | *tc) | ||
283 | { | 298 | { |
284 | static char a; | 299 | static char a; |
285 | 300 | ||
@@ -287,17 +302,17 @@ do_nothing_restarted_notify_task (void *cls, | |||
287 | 302 | ||
288 | #if LOG_BACKOFF | 303 | #if LOG_BACKOFF |
289 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | 304 | if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) |
290 | { | 305 | { |
291 | fprintf (killLogFilePtr, "%d.Reason is shutdown!\n", trialCount); | 306 | fprintf (killLogFilePtr, "%d.Reason is shutdown!\n", trialCount); |
292 | } | 307 | } |
293 | else if ((tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT) != 0) | 308 | else if ((tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT) != 0) |
294 | { | 309 | { |
295 | fprintf (killLogFilePtr, "%d.Reason is timeout!\n", trialCount); | 310 | fprintf (killLogFilePtr, "%d.Reason is timeout!\n", trialCount); |
296 | } | 311 | } |
297 | else if ((tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE) != 0) | 312 | else if ((tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE) != 0) |
298 | { | 313 | { |
299 | fprintf (killLogFilePtr, "%d.Service is running!\n", trialCount); | 314 | fprintf (killLogFilePtr, "%d.Service is running!\n", trialCount); |
300 | } | 315 | } |
301 | #endif | 316 | #endif |
302 | GNUNET_SCHEDULER_add_now (&kill_task, &a); | 317 | GNUNET_SCHEDULER_add_now (&kill_task, &a); |
303 | } | 318 | } |
@@ -307,7 +322,7 @@ static void | |||
307 | do_test (void *cbData, const struct GNUNET_SCHEDULER_TaskContext *tc) | 322 | do_test (void *cbData, const struct GNUNET_SCHEDULER_TaskContext *tc) |
308 | { | 323 | { |
309 | GNUNET_CLIENT_service_test ("do-nothing", cfg, TIMEOUT, | 324 | GNUNET_CLIENT_service_test ("do-nothing", cfg, TIMEOUT, |
310 | &do_nothing_restarted_notify_task, NULL); | 325 | &do_nothing_restarted_notify_task, NULL); |
311 | } | 326 | } |
312 | 327 | ||
313 | 328 | ||
@@ -326,29 +341,29 @@ kill_task (void *cbData, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
326 | static struct GNUNET_CLIENT_Connection *doNothingConnection = NULL; | 341 | static struct GNUNET_CLIENT_Connection *doNothingConnection = NULL; |
327 | 342 | ||
328 | if (NULL != cbData) | 343 | if (NULL != cbData) |
329 | { | 344 | { |
330 | waitedFor = GNUNET_TIME_absolute_get_duration (startedWaitingAt); | 345 | waitedFor = GNUNET_TIME_absolute_get_duration (startedWaitingAt); |
331 | 346 | ||
332 | #if LOG_BACKOFF | 347 | #if LOG_BACKOFF |
333 | fprintf (killLogFilePtr, "Waited for: %llu ms\n", | 348 | fprintf (killLogFilePtr, "Waited for: %llu ms\n", |
334 | (unsigned long long) waitedFor.rel_value); | 349 | (unsigned long long) waitedFor.rel_value); |
335 | #endif | 350 | #endif |
336 | } | 351 | } |
337 | else | 352 | else |
338 | { | 353 | { |
339 | waitedFor.rel_value = 0; | 354 | waitedFor.rel_value = 0; |
340 | } | 355 | } |
341 | /* Connect to the doNothing task */ | 356 | /* Connect to the doNothing task */ |
342 | doNothingConnection = GNUNET_CLIENT_connect ("do-nothing", cfg); | 357 | doNothingConnection = GNUNET_CLIENT_connect ("do-nothing", cfg); |
343 | GNUNET_assert (doNothingConnection != NULL); | 358 | GNUNET_assert (doNothingConnection != NULL); |
344 | if (trialCount == 12) | 359 | if (trialCount == 12) |
345 | { | 360 | { |
346 | GNUNET_CLIENT_disconnect (doNothingConnection, GNUNET_NO); | 361 | GNUNET_CLIENT_disconnect (doNothingConnection, GNUNET_NO); |
347 | GNUNET_ARM_stop_service (arm, "do-nothing", TIMEOUT, &arm_notify_stop, | 362 | GNUNET_ARM_stop_service (arm, "do-nothing", TIMEOUT, &arm_notify_stop, |
348 | NULL); | 363 | NULL); |
349 | ok = 0; | 364 | ok = 0; |
350 | return; | 365 | return; |
351 | } | 366 | } |
352 | /* Use the created connection to kill the doNothingTask */ | 367 | /* Use the created connection to kill the doNothingTask */ |
353 | arm_service_shutdown (doNothingConnection, TIMEOUT, &shutdown_cont, NULL); | 368 | arm_service_shutdown (doNothingConnection, TIMEOUT, &shutdown_cont, NULL); |
354 | } | 369 | } |
@@ -363,7 +378,7 @@ task (void *cls, char *const *args, const char *cfgfile, | |||
363 | arm = GNUNET_ARM_connect (cfg, NULL); | 378 | arm = GNUNET_ARM_connect (cfg, NULL); |
364 | #if START_ARM | 379 | #if START_ARM |
365 | GNUNET_ARM_start_service (arm, "arm", GNUNET_TIME_UNIT_ZERO, &arm_notify, | 380 | GNUNET_ARM_start_service (arm, "arm", GNUNET_TIME_UNIT_ZERO, &arm_notify, |
366 | NULL); | 381 | NULL); |
367 | #else | 382 | #else |
368 | arm_do_nothing (NULL, GNUNET_YES); | 383 | arm_do_nothing (NULL, GNUNET_YES); |
369 | #endif | 384 | #endif |
@@ -387,9 +402,9 @@ check () | |||
387 | 402 | ||
388 | /* Running ARM and running the do_nothing task */ | 403 | /* Running ARM and running the do_nothing task */ |
389 | GNUNET_assert (GNUNET_OK == | 404 | GNUNET_assert (GNUNET_OK == |
390 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, | 405 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, |
391 | argv, "test-exponential-backoff", "nohelp", | 406 | argv, "test-exponential-backoff", |
392 | options, &task, NULL)); | 407 | "nohelp", options, &task, NULL)); |
393 | 408 | ||
394 | 409 | ||
395 | return ok; | 410 | return ok; |
@@ -401,12 +416,12 @@ init () | |||
401 | #if LOG_BACKOFF | 416 | #if LOG_BACKOFF |
402 | killLogFileName = GNUNET_DISK_mktemp ("exponential-backoff-waiting.log"); | 417 | killLogFileName = GNUNET_DISK_mktemp ("exponential-backoff-waiting.log"); |
403 | if (NULL == (killLogFilePtr = FOPEN (killLogFileName, "w"))) | 418 | if (NULL == (killLogFilePtr = FOPEN (killLogFileName, "w"))) |
404 | { | 419 | { |
405 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "fopen", | 420 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "fopen", |
406 | killLogFileName); | 421 | killLogFileName); |
407 | GNUNET_free (killLogFileName); | 422 | GNUNET_free (killLogFileName); |
408 | return GNUNET_SYSERR; | 423 | return GNUNET_SYSERR; |
409 | } | 424 | } |
410 | #endif | 425 | #endif |
411 | return GNUNET_OK; | 426 | return GNUNET_OK; |
412 | } | 427 | } |
@@ -429,11 +444,11 @@ main (int argc, char *argv[]) | |||
429 | 444 | ||
430 | GNUNET_log_setup ("test-exponential-backoff", | 445 | GNUNET_log_setup ("test-exponential-backoff", |
431 | #if VERBOSE | 446 | #if VERBOSE |
432 | "DEBUG", | 447 | "DEBUG", |
433 | #else | 448 | #else |
434 | "WARNING", | 449 | "WARNING", |
435 | #endif | 450 | #endif |
436 | NULL); | 451 | NULL); |
437 | 452 | ||
438 | init (); | 453 | init (); |
439 | ret = check (); | 454 | ret = check (); |
diff --git a/src/arm/test_gnunet_arm.sh b/src/arm/test_gnunet_arm.sh index d36c2ca38..4a5b7266d 100755 --- a/src/arm/test_gnunet_arm.sh +++ b/src/arm/test_gnunet_arm.sh | |||
@@ -40,28 +40,6 @@ sleep 1 | |||
40 | echo "PASS" | 40 | echo "PASS" |
41 | 41 | ||
42 | # ---------------------------------------------------------------------------------- | 42 | # ---------------------------------------------------------------------------------- |
43 | echo -n "TEST: Test -t on running service... " | ||
44 | if ! $exe $DEBUG -t resolver > $out; then | ||
45 | echo "FAIL: error running $exe" | ||
46 | exit 1 | ||
47 | fi | ||
48 | LINES=`cat $out | grep resolver | grep not | wc -l` | ||
49 | if test $LINES -ne 0; then | ||
50 | echo "FAIL: unexpected output:" | ||
51 | cat $out | ||
52 | $exe -e | ||
53 | exit 1 | ||
54 | fi | ||
55 | LINES=`cat $out | grep resolver | grep -v not | wc -l` | ||
56 | if test $LINES -ne 1; then | ||
57 | echo "FAIL: unexpected output" | ||
58 | cat $out | ||
59 | $exe -e | ||
60 | exit 1 | ||
61 | fi | ||
62 | echo "PASS" | ||
63 | |||
64 | # ---------------------------------------------------------------------------------- | ||
65 | echo -n "TEST: Stop a service... " | 43 | echo -n "TEST: Stop a service... " |
66 | 44 | ||
67 | if ! $exe $DEBUG -k resolver > $out; then | 45 | if ! $exe $DEBUG -k resolver > $out; then |
@@ -73,23 +51,6 @@ sleep 1 | |||
73 | echo "PASS" | 51 | echo "PASS" |
74 | 52 | ||
75 | # ---------------------------------------------------------------------------------- | 53 | # ---------------------------------------------------------------------------------- |
76 | echo -n "TEST: Test -t on stopped service... " | ||
77 | if ! $exe $DEBUG -t resolver > $out; then | ||
78 | echo "FAIL: error running $exe" | ||
79 | cat $out | ||
80 | $exe -e > /dev/null | ||
81 | exit 1 | ||
82 | fi | ||
83 | LINES=`cat $out | grep resolver | grep not | wc -l` | ||
84 | if test $LINES -ne 1; then | ||
85 | echo "FAIL: unexpected output" | ||
86 | cat $out | ||
87 | $exe -e > /dev/null | ||
88 | exit 1 | ||
89 | fi | ||
90 | echo "PASS" | ||
91 | |||
92 | # ---------------------------------------------------------------------------------- | ||
93 | echo -n "TEST: Stop ARM... " | 54 | echo -n "TEST: Stop ARM... " |
94 | 55 | ||
95 | if ! $exe $DEBUG -e > $out; then | 56 | if ! $exe $DEBUG -e > $out; then |
diff --git a/src/arm/test_gnunet_service_manager.c b/src/arm/test_gnunet_service_manager.c index 100e1569c..2be86e79f 100644 --- a/src/arm/test_gnunet_service_manager.c +++ b/src/arm/test_gnunet_service_manager.c | |||
@@ -51,17 +51,17 @@ static struct GNUNET_ARM_Handle *arm; | |||
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | static void | 53 | static void |
54 | arm_stopped (void *cls, int success) | 54 | arm_stopped (void *cls, enum GNUNET_ARM_ProcessStatus success) |
55 | { | 55 | { |
56 | if (success != GNUNET_NO) | 56 | if (success != GNUNET_ARM_PROCESS_DOWN) |
57 | { | 57 | { |
58 | GNUNET_break (0); | 58 | GNUNET_break (0); |
59 | ret = 4; | 59 | ret = 4; |
60 | } | 60 | } |
61 | else | 61 | else |
62 | { | 62 | { |
63 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM stopped\n"); | 63 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM stopped\n"); |
64 | } | 64 | } |
65 | #if START_ARM | 65 | #if START_ARM |
66 | GNUNET_ARM_disconnect (arm); | 66 | GNUNET_ARM_disconnect (arm); |
67 | arm = NULL; | 67 | arm = NULL; |
@@ -74,15 +74,16 @@ hostNameResolveCB (void *cls, const struct sockaddr *addr, socklen_t addrlen) | |||
74 | if ((ret == 0) || (ret == 4)) | 74 | if ((ret == 0) || (ret == 4)) |
75 | return; | 75 | return; |
76 | if (NULL == addr) | 76 | if (NULL == addr) |
77 | { | 77 | { |
78 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Name not resolved!\n"); | 78 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Name not resolved!\n"); |
79 | #if START_ARM | 79 | #if START_ARM |
80 | GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, &arm_stopped, NULL); | 80 | GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, &arm_stopped, NULL); |
81 | #endif | 81 | #endif |
82 | ret = 3; | 82 | ret = 3; |
83 | return; | 83 | return; |
84 | } | 84 | } |
85 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Resolved hostname, now stopping ARM\n"); | 85 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
86 | "Resolved hostname, now stopping ARM\n"); | ||
86 | ret = 0; | 87 | ret = 0; |
87 | #if START_ARM | 88 | #if START_ARM |
88 | GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, &arm_stopped, NULL); | 89 | GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, &arm_stopped, NULL); |
@@ -91,27 +92,28 @@ hostNameResolveCB (void *cls, const struct sockaddr *addr, socklen_t addrlen) | |||
91 | 92 | ||
92 | 93 | ||
93 | static void | 94 | static void |
94 | arm_notify (void *cls, int success) | 95 | arm_notify (void *cls, enum GNUNET_ARM_ProcessStatus success) |
95 | { | 96 | { |
96 | if (success != GNUNET_YES) | 97 | if (success != GNUNET_ARM_PROCESS_STARTING) |
97 | { | 98 | { |
98 | GNUNET_break (0); | 99 | GNUNET_break (0); |
99 | ret = 1; | 100 | ret = 1; |
100 | return; | 101 | return; |
101 | } | 102 | } |
102 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to resolve our own hostname!\n"); | 103 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
104 | "Trying to resolve our own hostname!\n"); | ||
103 | /* connect to the resolver service */ | 105 | /* connect to the resolver service */ |
104 | if (NULL == | 106 | if (NULL == |
105 | GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC, TIMEOUT, &hostNameResolveCB, | 107 | GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC, TIMEOUT, |
106 | NULL)) | 108 | &hostNameResolveCB, NULL)) |
107 | { | 109 | { |
108 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 110 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
109 | "Unable initiate connection to resolver service\n"); | 111 | "Unable initiate connection to resolver service\n"); |
110 | ret = 2; | 112 | ret = 2; |
111 | #if START_ARM | 113 | #if START_ARM |
112 | GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, &arm_stopped, NULL); | 114 | GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, &arm_stopped, NULL); |
113 | #endif | 115 | #endif |
114 | } | 116 | } |
115 | } | 117 | } |
116 | 118 | ||
117 | 119 | ||
@@ -144,9 +146,9 @@ check () | |||
144 | GNUNET_GETOPT_OPTION_END | 146 | GNUNET_GETOPT_OPTION_END |
145 | }; | 147 | }; |
146 | GNUNET_assert (GNUNET_OK == | 148 | GNUNET_assert (GNUNET_OK == |
147 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, | 149 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, |
148 | argv, "test-gnunet-service-manager", | 150 | argv, "test-gnunet-service-manager", |
149 | "nohelp", options, &run, NULL)); | 151 | "nohelp", options, &run, NULL)); |
150 | } | 152 | } |
151 | 153 | ||
152 | 154 | ||
@@ -156,27 +158,28 @@ main (int argc, char *argv[]) | |||
156 | char hostname[GNUNET_OS_get_hostname_max_length () + 1]; | 158 | char hostname[GNUNET_OS_get_hostname_max_length () + 1]; |
157 | 159 | ||
158 | if (0 != gethostname (hostname, sizeof (hostname) - 1)) | 160 | if (0 != gethostname (hostname, sizeof (hostname) - 1)) |
159 | { | 161 | { |
160 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 162 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
161 | "gethostname"); | 163 | "gethostname"); |
162 | fprintf (stderr, | 164 | fprintf (stderr, |
163 | "Failed to determine my own hostname, testcase not run.\n"); | 165 | "Failed to determine my own hostname, testcase not run.\n"); |
164 | return 0; | 166 | return 0; |
165 | } | 167 | } |
166 | if (NULL == gethostbyname (hostname)) | 168 | if (NULL == gethostbyname (hostname)) |
167 | { | 169 | { |
168 | fprintf (stderr, "Failed to resolve my hostname `%s', testcase not run.\n", | 170 | fprintf (stderr, |
169 | hostname); | 171 | "Failed to resolve my hostname `%s', testcase not run.\n", |
170 | return 0; | 172 | hostname); |
171 | } | 173 | return 0; |
174 | } | ||
172 | 175 | ||
173 | GNUNET_log_setup ("test-gnunet-service-manager", | 176 | GNUNET_log_setup ("test-gnunet-service-manager", |
174 | #if VERBOSE | 177 | #if VERBOSE |
175 | "DEBUG", | 178 | "DEBUG", |
176 | #else | 179 | #else |
177 | "WARNING", | 180 | "WARNING", |
178 | #endif | 181 | #endif |
179 | NULL); | 182 | NULL); |
180 | check (); | 183 | check (); |
181 | return ret; | 184 | return ret; |
182 | } | 185 | } |