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 | |
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
-rw-r--r-- | doc/man/gnunet-arm.1 | 16 | ||||
-rw-r--r-- | po/POTFILES.in | 2 | ||||
-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 | ||||
-rw-r--r-- | src/include/gnunet_arm_service.h | 67 | ||||
-rw-r--r-- | src/include/gnunet_protocols.h | 24 |
15 files changed, 1318 insertions, 1537 deletions
diff --git a/doc/man/gnunet-arm.1 b/doc/man/gnunet-arm.1 index 30e0082ef..e8b7c7a61 100644 --- a/doc/man/gnunet-arm.1 +++ b/doc/man/gnunet-arm.1 | |||
@@ -9,7 +9,7 @@ gnunet\-arm \- control GNUnet services | |||
9 | .br | 9 | .br |
10 | 10 | ||
11 | .SH DESCRIPTION | 11 | .SH DESCRIPTION |
12 | \fBgnunet\-arm\fP can be used to start or stop GNUnet services, including the ARM service itself. | 12 | \fBgnunet\-arm\fP can be used to start or stop GNUnet services, including the ARM service itself. The ARM service is a supervisor for GNUnet's service processes. ARM starts services on-demand or as configured and re-starts them if they crash. |
13 | 13 | ||
14 | .SH OPTIONS | 14 | .SH OPTIONS |
15 | 15 | ||
@@ -19,7 +19,7 @@ Use the configuration file FILENAME. | |||
19 | 19 | ||
20 | .TP | 20 | .TP |
21 | .IP "\-e, \-\-end" | 21 | .IP "\-e, \-\-end" |
22 | Shutdown all GNUnet services (including ARM). | 22 | Shutdown all GNUnet services (including ARM itself). Running "gnunet-arm -e" is the usual way to shutdown a GNUnet peer. |
23 | 23 | ||
24 | .TP | 24 | .TP |
25 | .IP "\-h, \-\-help" | 25 | .IP "\-h, \-\-help" |
@@ -31,19 +31,15 @@ Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. | |||
31 | 31 | ||
32 | .TP | 32 | .TP |
33 | .IP "\-i SERVICE, \-\-init=SERVICE" | 33 | .IP "\-i SERVICE, \-\-init=SERVICE" |
34 | Starts the specified SERVICE if it is not already running. | 34 | Starts the specified SERVICE if it is not already running. More specifically, this makes the service behave as if it were in the default services list. |
35 | 35 | ||
36 | .TP | 36 | .TP |
37 | .IP "\-k SERVICE, \-\-kill=SERVICE" | 37 | .IP "\-k SERVICE, \-\-kill=SERVICE" |
38 | Stop the specified SERVICE if it is running. | 38 | Stop the specified SERVICE if it is running. While this will kill the service right now, the service may be restarted immediately if other services depend on it (service is then started 'on-demand'). If the service used to be a 'default' service, its default-service status will be revoked. If the service was not a default service, it will just be (temporarily) stopped, but could be re-started on-demand at any time. |
39 | 39 | ||
40 | .TP | 40 | .TP |
41 | .IP "\-s, \-\-start" | 41 | .IP "\-s, \-\-start" |
42 | Start all GNUnet default services on this system (including ARM). | 42 | Start all GNUnet default services on this system (and also ARM). Naturally, if a service is demanded by a default service, it will then also be started. Running "gnunet-arm -s" is the usual way to start a GNUnet peer. |
43 | |||
44 | .TP | ||
45 | .IP "\-t SERVICE, \-\-test=SERVICE" | ||
46 | Report if the specified SERVICE is running. | ||
47 | 43 | ||
48 | .TP | 44 | .TP |
49 | .IP "\-v, \-\-version" | 45 | .IP "\-v, \-\-version" |
@@ -51,7 +47,7 @@ Print GNUnet version number. | |||
51 | 47 | ||
52 | 48 | ||
53 | .SH BUGS | 49 | .SH BUGS |
54 | Report bugs by using Mantis <https://gnunet.org/mantis/> or by sending electronic mail to <gnunet\-developers@gnu.org> | 50 | Report bugs by using Mantis <https://gnunet.org/bugs/> or by sending electronic mail to <gnunet\-developers@gnu.org> |
55 | 51 | ||
56 | .SH SEE ALSO | 52 | .SH SEE ALSO |
57 | gnunet\-service\-arm(1) | 53 | gnunet\-service\-arm(1) |
diff --git a/po/POTFILES.in b/po/POTFILES.in index dc8e00a3f..c008d61dd 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in | |||
@@ -95,7 +95,6 @@ src/arm/gnunet-arm.c | |||
95 | src/arm/mockup-service.c | 95 | src/arm/mockup-service.c |
96 | src/arm/gnunet-service-arm.c | 96 | src/arm/gnunet-service-arm.c |
97 | src/arm/arm_api.c | 97 | src/arm/arm_api.c |
98 | src/arm/gnunet-service-arm_interceptor.c | ||
99 | src/arm/do_start_process.c | 98 | src/arm/do_start_process.c |
100 | src/ats/gnunet-service-ats_reservations.c | 99 | src/ats/gnunet-service-ats_reservations.c |
101 | src/ats/ats_api.c | 100 | src/ats/ats_api.c |
@@ -219,7 +218,6 @@ src/dht/gnunet-service-dht.h | |||
219 | src/dht/gnunet-service-dht_hello.h | 218 | src/dht/gnunet-service-dht_hello.h |
220 | src/dht/gnunet-service-dht_nse.h | 219 | src/dht/gnunet-service-dht_nse.h |
221 | src/arm/arm.h | 220 | src/arm/arm.h |
222 | src/arm/gnunet-service-arm.h | ||
223 | src/ats/gnunet-service-ats_performance.h | 221 | src/ats/gnunet-service-ats_performance.h |
224 | src/ats/gnunet-service-ats_math.h | 222 | src/ats/gnunet-service-ats_math.h |
225 | src/ats/gnunet-service-ats.h | 223 | src/ats/gnunet-service-ats.h |
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 | } |
diff --git a/src/include/gnunet_arm_service.h b/src/include/gnunet_arm_service.h index 6d52773de..af1c8cd94 100644 --- a/src/include/gnunet_arm_service.h +++ b/src/include/gnunet_arm_service.h | |||
@@ -42,19 +42,74 @@ extern "C" | |||
42 | /** | 42 | /** |
43 | * Version of the arm API. | 43 | * Version of the arm API. |
44 | */ | 44 | */ |
45 | #define GNUNET_ARM_VERSION 0x00000000 | 45 | #define GNUNET_ARM_VERSION 0x00000001 |
46 | |||
47 | |||
48 | /** | ||
49 | * Values characterizing GNUnet process states. | ||
50 | */ | ||
51 | enum GNUNET_ARM_ProcessStatus | ||
52 | { | ||
53 | /** | ||
54 | * Service name is unknown to ARM. | ||
55 | */ | ||
56 | GNUNET_ARM_PROCESS_UNKNOWN = -1, | ||
57 | |||
58 | /** | ||
59 | * Service is now down (due to client request). | ||
60 | */ | ||
61 | GNUNET_ARM_PROCESS_DOWN = 0, | ||
62 | |||
63 | /** | ||
64 | * Service is already running. | ||
65 | */ | ||
66 | GNUNET_ARM_PROCESS_ALREADY_RUNNING = 1, | ||
67 | |||
68 | /** | ||
69 | * Service is currently being started (due to client request). | ||
70 | */ | ||
71 | GNUNET_ARM_PROCESS_STARTING = 2, | ||
72 | |||
73 | /** | ||
74 | * Service is already being stopped by some other client. | ||
75 | */ | ||
76 | GNUNET_ARM_PROCESS_ALREADY_STOPPING = 3, | ||
77 | |||
78 | /** | ||
79 | * Service is already down (no action taken) | ||
80 | */ | ||
81 | GNUNET_ARM_PROCESS_ALREADY_DOWN = 4, | ||
82 | |||
83 | /** | ||
84 | * ARM is currently being shut down (no more process starts) | ||
85 | */ | ||
86 | GNUNET_ARM_PROCESS_SHUTDOWN = 5, | ||
87 | |||
88 | /** | ||
89 | * Error in communication with ARM | ||
90 | */ | ||
91 | GNUNET_ARM_PROCESS_COMMUNICATION_ERROR = 6, | ||
92 | |||
93 | /** | ||
94 | * Timeout in communication with ARM | ||
95 | */ | ||
96 | GNUNET_ARM_PROCESS_COMMUNICATION_TIMEOUT = 7, | ||
97 | |||
98 | /** | ||
99 | * Failure to perform operation | ||
100 | */ | ||
101 | GNUNET_ARM_PROCESS_FAILURE = 8 | ||
102 | }; | ||
46 | 103 | ||
47 | 104 | ||
48 | /** | 105 | /** |
49 | * Callback function invoked when operation is complete. | 106 | * Callback function invoked when operation is complete. |
50 | * | 107 | * |
51 | * @param cls closure | 108 | * @param cls closure |
52 | * @param success GNUNET_YES if we think the service is running | 109 | * @param result outcome of the operation |
53 | * GNUNET_NO if we think the service is stopped | ||
54 | * GNUNET_SYSERR if we think ARM was not running or | ||
55 | * if the service status is unknown | ||
56 | */ | 110 | */ |
57 | typedef void (*GNUNET_ARM_Callback) (void *cls, int success); | 111 | typedef void (*GNUNET_ARM_Callback) (void *cls, |
112 | enum GNUNET_ARM_ProcessStatus result); | ||
58 | 113 | ||
59 | 114 | ||
60 | /** | 115 | /** |
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index e959a5cf9..5b9f0612a 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h | |||
@@ -78,31 +78,15 @@ extern "C" | |||
78 | #define GNUNET_MESSAGE_TYPE_ARM_STOP 9 | 78 | #define GNUNET_MESSAGE_TYPE_ARM_STOP 9 |
79 | 79 | ||
80 | /** | 80 | /** |
81 | * Response from ARM: service is now up. | 81 | * Request ARM service itself to shutdown. |
82 | */ | 82 | */ |
83 | #define GNUNET_MESSAGE_TYPE_ARM_IS_UP 10 | 83 | #define GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN 10 |
84 | 84 | ||
85 | /** | 85 | /** |
86 | * Response from ARM: service is now down. | 86 | * Response from ARM. |
87 | * (failed to start it or shut it down). | ||
88 | */ | 87 | */ |
89 | #define GNUNET_MESSAGE_TYPE_ARM_IS_DOWN 11 | 88 | #define GNUNET_MESSAGE_TYPE_ARM_RESULT 11 |
90 | 89 | ||
91 | /** | ||
92 | * Response from ARM: service status is unknown. | ||
93 | */ | ||
94 | #define GNUNET_MESSAGE_TYPE_ARM_IS_UNKNOWN 12 | ||
95 | |||
96 | /** | ||
97 | * Request ARM service shutdown. | ||
98 | */ | ||
99 | #define GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN 13 | ||
100 | |||
101 | /** | ||
102 | * Acknowledge service shutting down, disconnect | ||
103 | * indicates service stopped. | ||
104 | */ | ||
105 | #define GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN_ACK 14 | ||
106 | 90 | ||
107 | /******************************************************************************* | 91 | /******************************************************************************* |
108 | * HELLO message types | 92 | * HELLO message types |