diff options
author | Christian Grothoff <christian@grothoff.org> | 2009-10-05 09:56:25 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2009-10-05 09:56:25 +0000 |
commit | d75fb1880a887a8f5339c5e8cf5e9d2b8755fdad (patch) | |
tree | f8dff53b4b88b0d87ca31a772607ee51fb0653ec | |
parent | b9b0940e261a4b1713d909f0a2fd54134ed5b148 (diff) | |
download | gnunet-d75fb1880a887a8f5339c5e8cf5e9d2b8755fdad.tar.gz gnunet-d75fb1880a887a8f5339c5e8cf5e9d2b8755fdad.zip |
improving ARM API
-rw-r--r-- | BUGS | 2 | ||||
-rw-r--r-- | src/arm/arm_api.c | 564 | ||||
-rw-r--r-- | src/arm/gnunet-arm.c | 152 | ||||
-rw-r--r-- | src/arm/gnunet-service-arm.c | 87 | ||||
-rw-r--r-- | src/arm/test_arm_api.c | 28 | ||||
-rw-r--r-- | src/core/test_core_api.c | 10 | ||||
-rw-r--r-- | src/core/test_core_api_start_only.c | 6 | ||||
-rw-r--r-- | src/include/gnunet_arm_service.h | 92 | ||||
-rw-r--r-- | src/testing/testing.c | 69 | ||||
-rw-r--r-- | src/transport/transport_api.c | 13 |
10 files changed, 815 insertions, 208 deletions
@@ -92,8 +92,6 @@ sane end-user should care about this codebase yet anyway. | |||
92 | - implement exponential back-off for service restarts | 92 | - implement exponential back-off for service restarts |
93 | - better tracking of which config changes actually need to cause process restarts by ARM. | 93 | - better tracking of which config changes actually need to cause process restarts by ARM. |
94 | - have way to specify dependencies between services (to manage ARM restarts better) | 94 | - have way to specify dependencies between services (to manage ARM restarts better) |
95 | - client-API is inefficient since it opens a TCP connection per service that is started | ||
96 | (instead of re-using connections). | ||
97 | * CORE: | 95 | * CORE: |
98 | - code currently notifies clients about "encrypted" connections being up well before | 96 | - code currently notifies clients about "encrypted" connections being up well before |
99 | we get the encrypted PONG; sometimes this may be OK (for topology killing | 97 | we get the encrypted PONG; sometimes this may be OK (for topology killing |
diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c index f0ab8d189..7f2274958 100644 --- a/src/arm/arm_api.c +++ b/src/arm/arm_api.c | |||
@@ -32,85 +32,200 @@ | |||
32 | #include "gnunet_server_lib.h" | 32 | #include "gnunet_server_lib.h" |
33 | #include "arm.h" | 33 | #include "arm.h" |
34 | 34 | ||
35 | /** | ||
36 | * How often do we re-try tranmsitting requests to ARM before | ||
37 | * giving up? Note that if we succeeded transmitting a request | ||
38 | * but failed to read a response, we do NOT re-try (since that | ||
39 | * might result in ARM getting a request twice). | ||
40 | */ | ||
41 | #define MAX_ATTEMPTS 4 | ||
35 | 42 | ||
36 | /** | 43 | /** |
37 | * FIXME: document. | 44 | * Minimum delay between attempts to talk to ARM. |
38 | */ | 45 | */ |
39 | struct ArmContext | 46 | #define MIN_RETRY_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100) |
47 | |||
48 | |||
49 | /** | ||
50 | * How long are we willing to wait for a service operation during the multi-operation | ||
51 | * request processing? | ||
52 | */ | ||
53 | #define MULTI_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | ||
54 | |||
55 | |||
56 | /** | ||
57 | * Handle for interacting with ARM. | ||
58 | */ | ||
59 | struct GNUNET_ARM_Handle | ||
40 | { | 60 | { |
41 | 61 | ||
42 | /** | 62 | /** |
43 | * FIXME: document. | 63 | * Our connection to the ARM service. |
64 | */ | ||
65 | struct GNUNET_CLIENT_Connection *client; | ||
66 | |||
67 | /** | ||
68 | * The configuration that we are using. | ||
69 | */ | ||
70 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
71 | |||
72 | /** | ||
73 | * Scheduler to use. | ||
74 | */ | ||
75 | struct GNUNET_SCHEDULER_Handle *sched; | ||
76 | |||
77 | }; | ||
78 | |||
79 | |||
80 | /** | ||
81 | * Setup a context for communicating with ARM. Note that this | ||
82 | * can be done even if the ARM service is not yet running. | ||
83 | * | ||
84 | * @param cfg configuration to use (needed to contact ARM; | ||
85 | * the ARM service may internally use a different | ||
86 | * configuration to determine how to start the service). | ||
87 | * @param sched scheduler to use | ||
88 | * @param service service that *this* process is implementing/providing, can be NULL | ||
89 | * @return context to use for further ARM operations, NULL on error | ||
90 | */ | ||
91 | struct GNUNET_ARM_Handle * | ||
92 | GNUNET_ARM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
93 | struct GNUNET_SCHEDULER_Handle *sched, | ||
94 | const char *service) | ||
95 | { | ||
96 | struct GNUNET_ARM_Handle *ret; | ||
97 | struct GNUNET_CLIENT_Connection *client; | ||
98 | |||
99 | client = GNUNET_CLIENT_connect (sched, "arm", cfg); | ||
100 | if (client == NULL) | ||
101 | return NULL; | ||
102 | ret = GNUNET_malloc (sizeof (struct GNUNET_ARM_Handle)); | ||
103 | ret->cfg = cfg; | ||
104 | ret->sched = sched; | ||
105 | ret->client = client; | ||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | |||
110 | /** | ||
111 | * Disconnect from the ARM service. | ||
112 | * | ||
113 | * @param h the handle that was being used | ||
114 | */ | ||
115 | void | ||
116 | GNUNET_ARM_disconnect (struct GNUNET_ARM_Handle *h) | ||
117 | { | ||
118 | if (h->client != NULL) | ||
119 | GNUNET_CLIENT_disconnect (h->client); | ||
120 | GNUNET_free (h); | ||
121 | } | ||
122 | |||
123 | |||
124 | /** | ||
125 | * Internal state for a request with ARM. | ||
126 | */ | ||
127 | struct RequestContext | ||
128 | { | ||
129 | |||
130 | /** | ||
131 | * Pointer to our handle with ARM. | ||
132 | */ | ||
133 | struct GNUNET_ARM_Handle *h; | ||
134 | |||
135 | /** | ||
136 | * Function to call with a status code for the requested operation. | ||
44 | */ | 137 | */ |
45 | GNUNET_ARM_Callback callback; | 138 | GNUNET_ARM_Callback callback; |
46 | 139 | ||
47 | /** | 140 | /** |
48 | * FIXME: document. | 141 | * Closure for "callback". |
49 | */ | 142 | */ |
50 | void *cls; | 143 | void *cls; |
51 | 144 | ||
52 | /** | 145 | /** |
53 | * FIXME: document. | 146 | * The service that is being manipulated. Do not free. |
54 | */ | 147 | */ |
55 | char *service_name; | 148 | const char *service_name; |
56 | 149 | ||
57 | /** | 150 | /** |
58 | * FIXME: document. | 151 | * Timeout for the operation. |
59 | */ | 152 | */ |
60 | struct GNUNET_CLIENT_Connection *client; | 153 | struct GNUNET_TIME_Absolute timeout; |
61 | 154 | ||
62 | /** | 155 | /** |
63 | * FIXME: document. | 156 | * Length of service_name plus one. |
64 | */ | 157 | */ |
65 | const struct GNUNET_CONFIGURATION_Handle *cfg; | 158 | size_t slen; |
66 | 159 | ||
67 | /** | 160 | /** |
68 | * FIXME: document. | 161 | * Number of attempts left for transmitting the request to ARM. |
162 | * We may fail the first time (say because ARM is not yet up), | ||
163 | * in which case we wait a bit and re-try (timeout permitting). | ||
69 | */ | 164 | */ |
70 | struct GNUNET_TIME_Absolute timeout; | 165 | unsigned int attempts_left; |
71 | 166 | ||
72 | /** | 167 | /** |
73 | * FIXME: document. | 168 | * Type of the request expressed as a message type (start or stop). |
74 | */ | 169 | */ |
75 | uint16_t type; | 170 | uint16_t type; |
171 | |||
76 | }; | 172 | }; |
77 | 173 | ||
78 | 174 | ||
79 | /** | 175 | /** |
80 | * FIXME: document. | 176 | * A client specifically requested starting of ARM itself. |
177 | * This function is called with information about whether | ||
178 | * or not ARM is running; if it is, report success. If | ||
179 | * it is not, start the ARM process. | ||
180 | * | ||
181 | * @param cls the context for the request that we will report on (struct RequestContext*) | ||
182 | * @param tc why were we called (reason says if ARM is running) | ||
81 | */ | 183 | */ |
82 | static void | 184 | static void |
83 | arm_service_report (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 185 | arm_service_report (void *cls, |
186 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
84 | { | 187 | { |
85 | struct ArmContext *pos = cls; | 188 | struct RequestContext *pos = cls; |
86 | pid_t pid; | 189 | pid_t pid; |
87 | char *binary; | 190 | char *binary; |
88 | char *config; | 191 | char *config; |
89 | 192 | ||
90 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) | 193 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) |
91 | { | 194 | { |
195 | /* arm is running! */ | ||
92 | if (pos->callback != NULL) | 196 | if (pos->callback != NULL) |
93 | pos->callback (pos->cls, GNUNET_YES); | 197 | pos->callback (pos->cls, GNUNET_YES); |
94 | GNUNET_free (pos); | 198 | GNUNET_free (pos); |
95 | return; | 199 | return; |
96 | } | 200 | } |
97 | binary = NULL; | 201 | /* FIXME: should we check that HOSTNAME for 'arm' is localhost? */ |
98 | config = NULL; | ||
99 | /* start service */ | 202 | /* start service */ |
100 | if ((GNUNET_OK != | 203 | if (GNUNET_OK != |
101 | GNUNET_CONFIGURATION_get_value_string (pos->cfg, | 204 | GNUNET_CONFIGURATION_get_value_string (pos->h->cfg, |
102 | "arm", | 205 | "arm", |
103 | "BINARY", | 206 | "BINARY", |
104 | &binary)) || | 207 | &binary)) |
105 | (GNUNET_OK != | 208 | { |
106 | GNUNET_CONFIGURATION_get_value_filename (pos->cfg, | 209 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
107 | "arm", "CONFIG", &config))) | 210 | _("Configuration failes to specify option `%s' in section `%s'!\n"), |
211 | "BINARY", | ||
212 | "arm"); | ||
213 | if (pos->callback != NULL) | ||
214 | pos->callback (pos->cls, GNUNET_SYSERR); | ||
215 | GNUNET_free (pos); | ||
216 | return; | ||
217 | } | ||
218 | if (GNUNET_OK != | ||
219 | GNUNET_CONFIGURATION_get_value_filename (pos->h->cfg, | ||
220 | "arm", "CONFIG", &config)) | ||
108 | { | 221 | { |
109 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 222 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
110 | _("Configuration file or binary for ARM not known!\n")); | 223 | _("Configuration fails to specify option `%s' in section `%s'!\n"), |
224 | "CONFIG", | ||
225 | "arm"); | ||
111 | if (pos->callback != NULL) | 226 | if (pos->callback != NULL) |
112 | pos->callback (pos->cls, GNUNET_SYSERR); | 227 | pos->callback (pos->cls, GNUNET_SYSERR); |
113 | GNUNET_free_non_null (binary); | 228 | GNUNET_free (binary); |
114 | GNUNET_free (pos); | 229 | GNUNET_free (pos); |
115 | return; | 230 | return; |
116 | } | 231 | } |
@@ -128,24 +243,34 @@ arm_service_report (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
128 | GNUNET_free (pos); | 243 | GNUNET_free (pos); |
129 | return; | 244 | return; |
130 | } | 245 | } |
131 | /* FIXME: consider checking again to see if it worked!? */ | ||
132 | if (pos->callback != NULL) | 246 | if (pos->callback != NULL) |
133 | pos->callback (pos->cls, GNUNET_YES); | 247 | pos->callback (pos->cls, GNUNET_YES); |
134 | GNUNET_free (pos); | 248 | GNUNET_free (pos); |
135 | } | 249 | } |
136 | 250 | ||
137 | 251 | ||
252 | /** | ||
253 | * Process a response from ARM to a request for a change in service | ||
254 | * status. | ||
255 | * | ||
256 | * @param cls the request context | ||
257 | * @param msg the response | ||
258 | */ | ||
138 | static void | 259 | static void |
139 | handle_response (void *cls, const struct GNUNET_MessageHeader *msg) | 260 | handle_response (void *cls, const struct GNUNET_MessageHeader *msg) |
140 | { | 261 | { |
141 | struct ArmContext *sc = cls; | 262 | struct RequestContext *sc = cls; |
142 | int ret; | 263 | int ret; |
143 | 264 | ||
144 | if (msg == NULL) | 265 | if (msg == NULL) |
145 | { | 266 | { |
146 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 267 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
147 | _("Error receiving response from ARM service\n")); | 268 | _("Error receiving response from ARM service\n")); |
148 | GNUNET_CLIENT_disconnect (sc->client); | 269 | GNUNET_CLIENT_disconnect (sc->h->client); |
270 | sc->h->client = GNUNET_CLIENT_connect (sc->h->sched, | ||
271 | "arm", | ||
272 | sc->h->cfg); | ||
273 | GNUNET_assert (NULL != sc->h->client); | ||
149 | if (sc->callback != NULL) | 274 | if (sc->callback != NULL) |
150 | sc->callback (sc->cls, GNUNET_SYSERR); | 275 | sc->callback (sc->cls, GNUNET_SYSERR); |
151 | GNUNET_free (sc); | 276 | GNUNET_free (sc); |
@@ -170,73 +295,144 @@ handle_response (void *cls, const struct GNUNET_MessageHeader *msg) | |||
170 | GNUNET_break (0); | 295 | GNUNET_break (0); |
171 | ret = GNUNET_SYSERR; | 296 | ret = GNUNET_SYSERR; |
172 | } | 297 | } |
173 | GNUNET_CLIENT_disconnect (sc->client); | ||
174 | if (sc->callback != NULL) | 298 | if (sc->callback != NULL) |
175 | sc->callback (sc->cls, ret); | 299 | sc->callback (sc->cls, ret); |
176 | GNUNET_free (sc); | 300 | GNUNET_free (sc); |
177 | } | 301 | } |
178 | 302 | ||
179 | 303 | ||
304 | /** | ||
305 | * We've failed to transmit the request to the ARM service. | ||
306 | * Report our failure and clean up the state. | ||
307 | * | ||
308 | * @param sctx the state of the (now failed) request | ||
309 | */ | ||
310 | static void | ||
311 | report_transmit_failure (struct RequestContext *sctx) | ||
312 | { | ||
313 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
314 | _("Error while trying to transmit to ARM service\n")); | ||
315 | if (sctx->callback != NULL) | ||
316 | sctx->callback (sctx->cls, GNUNET_SYSERR); | ||
317 | GNUNET_free (sctx); | ||
318 | } | ||
319 | |||
320 | |||
321 | /** | ||
322 | * Transmit a request for a service status change to the | ||
323 | * ARM service. | ||
324 | * | ||
325 | * @param cls the "struct RequestContext" identifying the request | ||
326 | * @param size how many bytes are available in buf | ||
327 | * @param buf where to write the request, NULL on error | ||
328 | * @return number of bytes written to buf | ||
329 | */ | ||
330 | static size_t | ||
331 | send_service_msg (void *cls, size_t size, void *buf); | ||
332 | |||
333 | |||
334 | /** | ||
335 | * We've failed to transmit the request to the ARM service but | ||
336 | * are now going to try again. | ||
337 | * | ||
338 | * @param cls state of the request | ||
339 | * @param tc task context (unused) | ||
340 | */ | ||
341 | static void | ||
342 | retry_request (void *cls, | ||
343 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
344 | { | ||
345 | struct RequestContext *sctx = cls; | ||
346 | |||
347 | if (NULL == | ||
348 | GNUNET_CLIENT_notify_transmit_ready (sctx->h->client, | ||
349 | sctx->slen + | ||
350 | sizeof (struct | ||
351 | GNUNET_MessageHeader), | ||
352 | GNUNET_TIME_absolute_get_remaining (sctx->timeout), | ||
353 | &send_service_msg, | ||
354 | sctx)) | ||
355 | { | ||
356 | report_transmit_failure (sctx); | ||
357 | return; | ||
358 | } | ||
359 | } | ||
360 | |||
361 | |||
362 | /** | ||
363 | * Transmit a request for a service status change to the | ||
364 | * ARM service. | ||
365 | * | ||
366 | * @param cls the "struct RequestContext" identifying the request | ||
367 | * @param size how many bytes are available in buf | ||
368 | * @param buf where to write the request, NULL on error | ||
369 | * @return number of bytes written to buf | ||
370 | */ | ||
180 | static size_t | 371 | static size_t |
181 | send_service_msg (void *cls, size_t size, void *buf) | 372 | send_service_msg (void *cls, size_t size, void *buf) |
182 | { | 373 | { |
183 | struct ArmContext *sctx = cls; | 374 | struct RequestContext *sctx = cls; |
184 | struct GNUNET_MessageHeader *msg; | 375 | struct GNUNET_MessageHeader *msg; |
185 | size_t slen; | 376 | struct GNUNET_TIME_Relative rem; |
186 | 377 | ||
187 | if (buf == NULL) | 378 | if (buf == NULL) |
188 | { | 379 | { |
189 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 380 | GNUNET_CLIENT_disconnect (sctx->h->client); |
190 | _("Error while trying to transmit to ARM service\n")); | 381 | sctx->h->client = GNUNET_CLIENT_connect (sctx->h->sched, |
191 | GNUNET_CLIENT_disconnect (sctx->client); | 382 | "arm", |
192 | if (sctx->callback != NULL) | 383 | sctx->h->cfg); |
193 | sctx->callback (sctx->cls, GNUNET_SYSERR); | 384 | GNUNET_assert (sctx->h->client != NULL); |
194 | GNUNET_free (sctx->service_name); | 385 | rem = GNUNET_TIME_absolute_get_remaining (sctx->timeout); |
195 | GNUNET_free (sctx); | 386 | if ( (sctx->attempts_left-- > 0) && |
387 | (rem.value > 0) ) | ||
388 | { | ||
389 | GNUNET_SCHEDULER_add_delayed (sctx->h->sched, | ||
390 | GNUNET_NO, | ||
391 | GNUNET_SCHEDULER_PRIORITY_KEEP, | ||
392 | GNUNET_SCHEDULER_NO_TASK, | ||
393 | GNUNET_TIME_relative_min (MIN_RETRY_DELAY, | ||
394 | rem), | ||
395 | &retry_request, | ||
396 | sctx); | ||
397 | return 0; | ||
398 | } | ||
399 | report_transmit_failure (sctx); | ||
196 | return 0; | 400 | return 0; |
197 | } | 401 | } |
198 | #if DEBUG_ARM | 402 | #if DEBUG_ARM |
199 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 403 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
200 | _("Transmitting service request to ARM.\n")); | 404 | _("Transmitting service request to ARM.\n")); |
201 | #endif | 405 | #endif |
202 | slen = strlen (sctx->service_name) + 1; | 406 | GNUNET_assert (size >= sctx->slen); |
203 | GNUNET_assert (size >= slen); | ||
204 | msg = buf; | 407 | msg = buf; |
205 | msg->size = htons (sizeof (struct GNUNET_MessageHeader) + slen); | 408 | msg->size = htons (sizeof (struct GNUNET_MessageHeader) + sctx->slen); |
206 | msg->type = htons (sctx->type); | 409 | msg->type = htons (sctx->type); |
207 | memcpy (&msg[1], sctx->service_name, slen); | 410 | memcpy (&msg[1], sctx->service_name, sctx->slen); |
208 | GNUNET_free (sctx->service_name); | 411 | GNUNET_CLIENT_receive (sctx->h->client, |
209 | sctx->service_name = NULL; | ||
210 | GNUNET_CLIENT_receive (sctx->client, | ||
211 | &handle_response, | 412 | &handle_response, |
212 | sctx, | 413 | sctx, |
213 | GNUNET_TIME_absolute_get_remaining (sctx->timeout)); | 414 | GNUNET_TIME_absolute_get_remaining (sctx->timeout)); |
214 | return slen + sizeof (struct GNUNET_MessageHeader); | 415 | return sctx->slen + sizeof (struct GNUNET_MessageHeader); |
215 | } | 416 | } |
216 | 417 | ||
217 | 418 | ||
218 | /** | 419 | /** |
219 | * Start or stop a service. | 420 | * Start or stop a service. |
220 | * | 421 | * |
422 | * @param h handle to ARM | ||
221 | * @param service_name name of the service | 423 | * @param service_name name of the service |
222 | * @param cfg configuration to use (needed to contact ARM; | ||
223 | * the ARM service may internally use a different | ||
224 | * configuration to determine how to start the service). | ||
225 | * @param sched scheduler to use | ||
226 | * @param timeout how long to wait before failing for good | 424 | * @param timeout how long to wait before failing for good |
227 | * @param cb callback to invoke when service is ready | 425 | * @param cb callback to invoke when service is ready |
228 | * @param cb_cls closure for callback | 426 | * @param cb_cls closure for callback |
229 | * @param type type of the request | 427 | * @param type type of the request |
230 | */ | 428 | */ |
231 | static void | 429 | static void |
232 | change_service (const char *service_name, | 430 | change_service (struct GNUNET_ARM_Handle *h, |
233 | const struct GNUNET_CONFIGURATION_Handle *cfg, | 431 | const char *service_name, |
234 | struct GNUNET_SCHEDULER_Handle *sched, | ||
235 | struct GNUNET_TIME_Relative timeout, | 432 | struct GNUNET_TIME_Relative timeout, |
236 | GNUNET_ARM_Callback cb, void *cb_cls, uint16_t type) | 433 | GNUNET_ARM_Callback cb, void *cb_cls, uint16_t type) |
237 | { | 434 | { |
238 | struct GNUNET_CLIENT_Connection *client; | 435 | struct RequestContext *sctx; |
239 | struct ArmContext *sctx; | ||
240 | size_t slen; | 436 | size_t slen; |
241 | 437 | ||
242 | slen = strlen (service_name) + 1; | 438 | slen = strlen (service_name) + 1; |
@@ -248,128 +444,248 @@ change_service (const char *service_name, | |||
248 | cb (cb_cls, GNUNET_NO); | 444 | cb (cb_cls, GNUNET_NO); |
249 | return; | 445 | return; |
250 | } | 446 | } |
251 | client = GNUNET_CLIENT_connect (sched, "arm", cfg); | ||
252 | if (client == NULL) | ||
253 | { | ||
254 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
255 | _("Failed to connect to ARM service\n")); | ||
256 | if (cb != NULL) | ||
257 | cb (cb_cls, GNUNET_SYSERR); | ||
258 | return; | ||
259 | } | ||
260 | #if DEBUG_ARM | 447 | #if DEBUG_ARM |
261 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 448 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
262 | _("ARM requests starting of service `%s'.\n"), service_name); | 449 | _("ARM requests starting of service `%s'.\n"), service_name); |
263 | #endif | 450 | #endif |
264 | sctx = GNUNET_malloc (sizeof (struct ArmContext)); | 451 | sctx = GNUNET_malloc (sizeof (struct RequestContext) + slen); |
452 | sctx->h = h; | ||
265 | sctx->callback = cb; | 453 | sctx->callback = cb; |
266 | sctx->cls = cb_cls; | 454 | sctx->cls = cb_cls; |
267 | sctx->client = client; | 455 | sctx->service_name = (const char*) &sctx[1]; |
268 | sctx->service_name = GNUNET_strdup (service_name); | 456 | memcpy (&sctx[1], |
457 | service_name, | ||
458 | slen); | ||
269 | sctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); | 459 | sctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); |
460 | sctx->slen = slen; | ||
461 | sctx->attempts_left = MAX_ATTEMPTS; | ||
270 | sctx->type = type; | 462 | sctx->type = type; |
271 | if (NULL == | 463 | retry_request (sctx, NULL); |
272 | GNUNET_CLIENT_notify_transmit_ready (client, | ||
273 | slen + | ||
274 | sizeof (struct | ||
275 | GNUNET_MessageHeader), | ||
276 | timeout, &send_service_msg, sctx)) | ||
277 | { | ||
278 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
279 | _("Failed to transmit request to ARM service\n")); | ||
280 | GNUNET_free (sctx->service_name); | ||
281 | GNUNET_free (sctx); | ||
282 | if (cb != NULL) | ||
283 | cb (cb_cls, GNUNET_SYSERR); | ||
284 | GNUNET_CLIENT_disconnect (client); | ||
285 | return; | ||
286 | } | ||
287 | } | 464 | } |
288 | 465 | ||
289 | 466 | ||
290 | /** | 467 | /** |
291 | * Start a service. | 468 | * Start a service. |
292 | * | 469 | * |
470 | * @param h handle to ARM | ||
293 | * @param service_name name of the service | 471 | * @param service_name name of the service |
294 | * @param cfg configuration to use (needed to contact ARM; | ||
295 | * the ARM service may internally use a different | ||
296 | * configuration to determine how to start the service). | ||
297 | * @param sched scheduler to use | ||
298 | * @param timeout how long to wait before failing for good | 472 | * @param timeout how long to wait before failing for good |
299 | * @param cb callback to invoke when service is ready | 473 | * @param cb callback to invoke when service is ready |
300 | * @param cb_cls closure for callback | 474 | * @param cb_cls closure for callback |
301 | */ | 475 | */ |
302 | void | 476 | void |
303 | GNUNET_ARM_start_service (const char *service_name, | 477 | GNUNET_ARM_start_service (struct GNUNET_ARM_Handle *h, |
304 | const struct GNUNET_CONFIGURATION_Handle *cfg, | 478 | const char *service_name, |
305 | struct GNUNET_SCHEDULER_Handle *sched, | ||
306 | struct GNUNET_TIME_Relative timeout, | 479 | struct GNUNET_TIME_Relative timeout, |
307 | GNUNET_ARM_Callback cb, void *cb_cls) | 480 | GNUNET_ARM_Callback cb, void *cb_cls) |
308 | { | 481 | { |
309 | struct ArmContext *sctx; | 482 | struct RequestContext *sctx; |
310 | 483 | ||
311 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 484 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
312 | _("Starting service `%s'\n"), service_name); | 485 | _("Starting service `%s'\n"), service_name); |
313 | if (0 == strcmp ("arm", service_name)) | 486 | if (0 == strcmp ("arm", service_name)) |
314 | { | 487 | { |
315 | sctx = GNUNET_malloc (sizeof (struct ArmContext)); | 488 | sctx = GNUNET_malloc (sizeof (struct RequestContext)); |
489 | sctx->h = h; | ||
316 | sctx->callback = cb; | 490 | sctx->callback = cb; |
317 | sctx->cls = cb_cls; | 491 | sctx->cls = cb_cls; |
318 | sctx->cfg = cfg; | 492 | sctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); |
319 | GNUNET_CLIENT_service_test (sched, | 493 | GNUNET_CLIENT_service_test (h->sched, |
320 | "arm", | 494 | "arm", |
321 | cfg, timeout, &arm_service_report, sctx); | 495 | h->cfg, timeout, &arm_service_report, sctx); |
322 | return; | 496 | return; |
323 | } | 497 | } |
324 | change_service (service_name, | 498 | change_service (h, service_name, timeout, cb, cb_cls, GNUNET_MESSAGE_TYPE_ARM_START); |
325 | cfg, | ||
326 | sched, timeout, cb, cb_cls, GNUNET_MESSAGE_TYPE_ARM_START); | ||
327 | } | 499 | } |
328 | 500 | ||
329 | 501 | ||
330 | |||
331 | |||
332 | /** | 502 | /** |
333 | * Stop a service. | 503 | * Stop a service. |
334 | * | 504 | * |
505 | * @param h handle to ARM | ||
335 | * @param service_name name of the service | 506 | * @param service_name name of the service |
336 | * @param cfg configuration to use (needed to contact ARM; | ||
337 | * the ARM service may internally use a different | ||
338 | * configuration to determine how to start the service). | ||
339 | * @param sched scheduler to use | ||
340 | * @param timeout how long to wait before failing for good | 507 | * @param timeout how long to wait before failing for good |
341 | * @param cb callback to invoke when service is ready | 508 | * @param cb callback to invoke when service is ready |
342 | * @param cb_cls closure for callback | 509 | * @param cb_cls closure for callback |
343 | */ | 510 | */ |
344 | void | 511 | void |
345 | GNUNET_ARM_stop_service (const char *service_name, | 512 | GNUNET_ARM_stop_service (struct GNUNET_ARM_Handle *h, |
346 | const struct GNUNET_CONFIGURATION_Handle *cfg, | 513 | const char *service_name, |
347 | struct GNUNET_SCHEDULER_Handle *sched, | ||
348 | struct GNUNET_TIME_Relative timeout, | 514 | struct GNUNET_TIME_Relative timeout, |
349 | GNUNET_ARM_Callback cb, void *cb_cls) | 515 | GNUNET_ARM_Callback cb, void *cb_cls) |
350 | { | 516 | { |
351 | struct GNUNET_CLIENT_Connection *client; | ||
352 | |||
353 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 517 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
354 | _("Stopping service `%s'\n"), service_name); | 518 | _("Stopping service `%s'\n"), service_name); |
355 | if (0 == strcmp ("arm", service_name)) | 519 | if (0 == strcmp ("arm", service_name)) |
356 | { | 520 | { |
357 | client = GNUNET_CLIENT_connect (sched, "arm", cfg); | 521 | GNUNET_CLIENT_service_shutdown (h->client); |
358 | if (client == NULL) | ||
359 | { | ||
360 | if (cb != NULL) | ||
361 | cb (cb_cls, GNUNET_SYSERR); | ||
362 | return; | ||
363 | } | ||
364 | GNUNET_CLIENT_service_shutdown (client); | ||
365 | GNUNET_CLIENT_disconnect (client); | ||
366 | if (cb != NULL) | 522 | if (cb != NULL) |
367 | cb (cb_cls, GNUNET_NO); | 523 | cb (cb_cls, GNUNET_NO); |
368 | return; | 524 | return; |
369 | } | 525 | } |
370 | change_service (service_name, | 526 | change_service (h, service_name, timeout, cb, cb_cls, GNUNET_MESSAGE_TYPE_ARM_STOP); |
371 | cfg, | ||
372 | sched, timeout, cb, cb_cls, GNUNET_MESSAGE_TYPE_ARM_STOP); | ||
373 | } | 527 | } |
374 | 528 | ||
529 | |||
530 | /** | ||
531 | * Function to call for each service. | ||
532 | * | ||
533 | * @param h handle to ARM | ||
534 | * @param service_name name of the service | ||
535 | * @param timeout how long to wait before failing for good | ||
536 | * @param cb callback to invoke when service is ready | ||
537 | * @param cb_cls closure for callback | ||
538 | */ | ||
539 | typedef void (*ServiceOperation) (struct GNUNET_ARM_Handle *h, | ||
540 | const char *service_name, | ||
541 | struct GNUNET_TIME_Relative timeout, | ||
542 | GNUNET_ARM_Callback cb, void *cb_cls); | ||
543 | |||
544 | |||
545 | /** | ||
546 | * Context for starting or stopping multiple services. | ||
547 | */ | ||
548 | struct MultiContext | ||
549 | { | ||
550 | /** | ||
551 | * NULL-terminated array of services to start or stop. | ||
552 | */ | ||
553 | char **services; | ||
554 | |||
555 | /** | ||
556 | * Our handle to ARM. | ||
557 | */ | ||
558 | struct GNUNET_ARM_Handle *h; | ||
559 | |||
560 | /** | ||
561 | * Identifies the operation (start or stop). | ||
562 | */ | ||
563 | ServiceOperation op; | ||
564 | |||
565 | /** | ||
566 | * Current position in "services". | ||
567 | */ | ||
568 | unsigned int pos; | ||
569 | }; | ||
570 | |||
571 | |||
572 | /** | ||
573 | * Run the operation for the next service in the multi-service | ||
574 | * request. | ||
575 | * | ||
576 | * @param cls the "struct MultiContext" that is being processed | ||
577 | * @param success status of the previous operation (ignored) | ||
578 | */ | ||
579 | static void | ||
580 | next_operation (void *cls, | ||
581 | int success) | ||
582 | { | ||
583 | struct MultiContext *mc = cls; | ||
584 | char *pos; | ||
585 | |||
586 | if (NULL == (pos = mc->services[mc->pos])) | ||
587 | { | ||
588 | GNUNET_free (mc->services); | ||
589 | GNUNET_ARM_disconnect (mc->h); | ||
590 | GNUNET_free (mc); | ||
591 | return; | ||
592 | } | ||
593 | mc->pos++; | ||
594 | mc->op (mc->h, pos, MULTI_TIMEOUT, &next_operation, mc); | ||
595 | GNUNET_free (pos); | ||
596 | } | ||
597 | |||
598 | |||
599 | /** | ||
600 | * Run a multi-service request. | ||
601 | * | ||
602 | * @param cfg configuration to use (needed to contact ARM; | ||
603 | * the ARM service may internally use a different | ||
604 | * configuration to determine how to start the service). | ||
605 | * @param sched scheduler to use | ||
606 | * @param op the operation to perform for each service | ||
607 | * @param va NULL-terminated list of services | ||
608 | */ | ||
609 | static void | ||
610 | run_multi_request (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
611 | struct GNUNET_SCHEDULER_Handle *sched, | ||
612 | ServiceOperation op, | ||
613 | va_list va) | ||
614 | { | ||
615 | va_list cp; | ||
616 | unsigned int total; | ||
617 | struct MultiContext *mc; | ||
618 | struct GNUNET_ARM_Handle *h; | ||
619 | const char *c; | ||
620 | |||
621 | h = GNUNET_ARM_connect (cfg, sched, NULL); | ||
622 | if (NULL == h) | ||
623 | { | ||
624 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
625 | _("Error while trying to transmit to ARM service\n")); | ||
626 | return; | ||
627 | } | ||
628 | total = 1; | ||
629 | va_copy (cp, va); | ||
630 | while (NULL != (va_arg (cp, const char*))) total++; | ||
631 | va_end (cp); | ||
632 | mc = GNUNET_malloc (sizeof(struct MultiContext)); | ||
633 | mc->services = GNUNET_malloc (total * sizeof (char*)); | ||
634 | mc->h = h; | ||
635 | mc->op = op; | ||
636 | total = 0; | ||
637 | va_copy (cp, va); | ||
638 | while (NULL != (c = va_arg (cp, const char*))) | ||
639 | mc->services[total++] = GNUNET_strdup (c); | ||
640 | va_end (cp); | ||
641 | next_operation (mc, GNUNET_YES); | ||
642 | } | ||
643 | |||
644 | |||
645 | /** | ||
646 | * Start multiple services in the specified order. Convenience | ||
647 | * function. Works asynchronously, failures are not reported. | ||
648 | * | ||
649 | * @param cfg configuration to use (needed to contact ARM; | ||
650 | * the ARM service may internally use a different | ||
651 | * configuration to determine how to start the service). | ||
652 | * @param sched scheduler to use | ||
653 | * @param ... NULL-terminated list of service names (const char*) | ||
654 | */ | ||
655 | void | ||
656 | GNUNET_ARM_start_services (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
657 | struct GNUNET_SCHEDULER_Handle *sched, | ||
658 | ...) | ||
659 | { | ||
660 | va_list ap; | ||
661 | |||
662 | va_start (ap, sched); | ||
663 | run_multi_request (cfg, sched, &GNUNET_ARM_start_service, ap); | ||
664 | va_end (ap); | ||
665 | } | ||
666 | |||
667 | |||
668 | /** | ||
669 | * Stop multiple services in the specified order. Convenience | ||
670 | * function. Works asynchronously, failures are not reported. | ||
671 | * | ||
672 | * @param cfg configuration to use (needed to contact ARM; | ||
673 | * the ARM service may internally use a different | ||
674 | * configuration to determine how to start the service). | ||
675 | * @param sched scheduler to use | ||
676 | * @param ... NULL-terminated list of service names (const char*) | ||
677 | */ | ||
678 | void | ||
679 | GNUNET_ARM_stop_services (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
680 | struct GNUNET_SCHEDULER_Handle *sched, | ||
681 | ...) | ||
682 | { | ||
683 | va_list ap; | ||
684 | |||
685 | va_start (ap, sched); | ||
686 | run_multi_request (cfg, sched, &GNUNET_ARM_stop_service, ap); | ||
687 | va_end (ap); | ||
688 | } | ||
689 | |||
690 | |||
375 | /* end of arm_api.c */ | 691 | /* end of arm_api.c */ |
diff --git a/src/arm/gnunet-arm.c b/src/arm/gnunet-arm.c index 740fd2533..09a1305a5 100644 --- a/src/arm/gnunet-arm.c +++ b/src/arm/gnunet-arm.c | |||
@@ -65,7 +65,46 @@ static char *test; | |||
65 | */ | 65 | */ |
66 | static int ret; | 66 | static int ret; |
67 | 67 | ||
68 | /** | ||
69 | * Connection with ARM. | ||
70 | */ | ||
71 | static struct GNUNET_ARM_Handle *h; | ||
72 | |||
73 | /** | ||
74 | * Our scheduler. | ||
75 | */ | ||
76 | static struct GNUNET_SCHEDULER_Handle *sched; | ||
77 | |||
78 | /** | ||
79 | * Our configuration. | ||
80 | */ | ||
81 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
82 | |||
83 | /** | ||
84 | * Processing stage that we are in. Simple counter. | ||
85 | */ | ||
86 | static unsigned int phase; | ||
87 | |||
68 | 88 | ||
89 | /** | ||
90 | * Main continuation-passing-style loop. Runs the various | ||
91 | * jobs that we've been asked to do in order. | ||
92 | * | ||
93 | * @param cls closure, unused | ||
94 | * @param tc context, unused | ||
95 | */ | ||
96 | static void | ||
97 | cps_loop (void *cls, | ||
98 | const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
99 | |||
100 | |||
101 | /** | ||
102 | * Callback invoked with the status of the last operation. Reports to the | ||
103 | * user and then runs the next phase in the FSM. | ||
104 | * | ||
105 | * @param cls pointer to "const char*" identifying service that was manipulated | ||
106 | * @param success GNUNET_OK if service is now running, GNUNET_NO if not, GNUNET_SYSERR on error | ||
107 | */ | ||
69 | static void | 108 | static void |
70 | confirm_cb (void *cls, int success) | 109 | confirm_cb (void *cls, int success) |
71 | { | 110 | { |
@@ -83,9 +122,21 @@ confirm_cb (void *cls, int success) | |||
83 | _("Error updating service `%s': ARM not running\n"), service); | 122 | _("Error updating service `%s': ARM not running\n"), service); |
84 | break; | 123 | break; |
85 | } | 124 | } |
125 | GNUNET_SCHEDULER_add_continuation (sched, | ||
126 | GNUNET_NO, | ||
127 | &cps_loop, | ||
128 | NULL, | ||
129 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | ||
86 | } | 130 | } |
87 | 131 | ||
88 | 132 | ||
133 | /** | ||
134 | * Function called to confirm that a service is running (or that | ||
135 | * it is not running). | ||
136 | * | ||
137 | * @param cls pointer to "const char*" identifying service that was manipulated | ||
138 | * @param tc reason determines if service is now running | ||
139 | */ | ||
89 | static void | 140 | static void |
90 | confirm_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 141 | confirm_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
91 | { | 142 | { |
@@ -95,6 +146,11 @@ confirm_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
95 | fprintf (stdout, _("Service `%s' is running.\n"), service); | 146 | fprintf (stdout, _("Service `%s' is running.\n"), service); |
96 | else | 147 | else |
97 | fprintf (stdout, _("Service `%s' is not running.\n"), service); | 148 | fprintf (stdout, _("Service `%s' is not running.\n"), service); |
149 | GNUNET_SCHEDULER_add_continuation (sched, | ||
150 | GNUNET_NO, | ||
151 | &cps_loop, | ||
152 | NULL, | ||
153 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); | ||
98 | } | 154 | } |
99 | 155 | ||
100 | 156 | ||
@@ -102,40 +158,90 @@ confirm_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
102 | * Main function that will be run by the scheduler. | 158 | * Main function that will be run by the scheduler. |
103 | * | 159 | * |
104 | * @param cls closure | 160 | * @param cls closure |
105 | * @param sched the scheduler to use | 161 | * @param s the scheduler to use |
106 | * @param args remaining command-line arguments | 162 | * @param args remaining command-line arguments |
107 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | 163 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) |
108 | * @param cfg configuration | 164 | * @param c configuration |
109 | */ | 165 | */ |
110 | static void | 166 | static void |
111 | run (void *cls, | 167 | run (void *cls, |
112 | struct GNUNET_SCHEDULER_Handle *sched, | 168 | struct GNUNET_SCHEDULER_Handle *s, |
113 | char *const *args, | 169 | char *const *args, |
114 | const char *cfgfile, | 170 | const char *cfgfile, |
115 | const struct GNUNET_CONFIGURATION_Handle *cfg) | 171 | const struct GNUNET_CONFIGURATION_Handle *c) |
116 | { | 172 | { |
117 | if (term != NULL) | 173 | sched = s; |
118 | { | 174 | cfg = c; |
119 | GNUNET_ARM_stop_service (term, cfg, sched, TIMEOUT, &confirm_cb, term); | 175 | h = GNUNET_ARM_connect (cfg, sched, NULL); |
120 | } | 176 | if (h == NULL) |
121 | if (end) | ||
122 | { | ||
123 | GNUNET_ARM_stop_service ("arm", | ||
124 | cfg, sched, TIMEOUT, &confirm_cb, "arm"); | ||
125 | } | ||
126 | if (start) | ||
127 | { | 177 | { |
128 | GNUNET_ARM_start_service ("arm", | 178 | fprintf (stderr, |
129 | cfg, sched, TIMEOUT, &confirm_cb, "arm"); | 179 | _("Fatal error initializing ARM API.\n")); |
180 | ret = 1; | ||
181 | return; | ||
130 | } | 182 | } |
131 | if (init != NULL) | 183 | GNUNET_SCHEDULER_add_continuation (sched, |
132 | { | 184 | GNUNET_NO, |
133 | GNUNET_ARM_start_service (init, cfg, sched, TIMEOUT, &confirm_cb, init); | 185 | &cps_loop, |
134 | } | 186 | NULL, |
135 | if (test != NULL) | 187 | GNUNET_SCHEDULER_REASON_PREREQ_DONE); |
188 | } | ||
189 | |||
190 | |||
191 | /** | ||
192 | * Main continuation-passing-style loop. Runs the various | ||
193 | * jobs that we've been asked to do in order. | ||
194 | * | ||
195 | * @param cls closure, unused | ||
196 | * @param tc context, unused | ||
197 | */ | ||
198 | static void | ||
199 | cps_loop (void *cls, | ||
200 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
201 | { | ||
202 | while (1) | ||
136 | { | 203 | { |
137 | GNUNET_CLIENT_service_test (sched, | 204 | switch (phase++) |
138 | test, cfg, TIMEOUT, &confirm_task, test); | 205 | { |
206 | case 0: | ||
207 | if (term != NULL) | ||
208 | { | ||
209 | GNUNET_ARM_stop_service (h, term, TIMEOUT, &confirm_cb, term); | ||
210 | return; | ||
211 | } | ||
212 | break; | ||
213 | case 1: | ||
214 | if (end) | ||
215 | { | ||
216 | GNUNET_ARM_stop_service (h, "arm", TIMEOUT, &confirm_cb, "arm"); | ||
217 | return; | ||
218 | } | ||
219 | break; | ||
220 | case 2: | ||
221 | if (start) | ||
222 | { | ||
223 | GNUNET_ARM_start_service (h, "arm", TIMEOUT, &confirm_cb, "arm"); | ||
224 | return; | ||
225 | } | ||
226 | break; | ||
227 | case 3: | ||
228 | if (init != NULL) | ||
229 | { | ||
230 | GNUNET_ARM_start_service (h, init, TIMEOUT, &confirm_cb, init); | ||
231 | return; | ||
232 | } | ||
233 | break; | ||
234 | case 4: | ||
235 | if (test != NULL) | ||
236 | { | ||
237 | GNUNET_CLIENT_service_test (sched, test, cfg, TIMEOUT, &confirm_task, test); | ||
238 | return; | ||
239 | } | ||
240 | break; | ||
241 | default: /* last phase */ | ||
242 | GNUNET_ARM_disconnect (h); | ||
243 | return; | ||
244 | } | ||
139 | } | 245 | } |
140 | } | 246 | } |
141 | 247 | ||
diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c index c7143e3a7..d43adeae2 100644 --- a/src/arm/gnunet-service-arm.c +++ b/src/arm/gnunet-service-arm.c | |||
@@ -46,9 +46,15 @@ | |||
46 | 46 | ||
47 | 47 | ||
48 | /** | 48 | /** |
49 | * Run maintenance every second. | 49 | * Run normal maintenance every 2s. |
50 | */ | 50 | */ |
51 | #define MAINT_FREQUENCY GNUNET_TIME_UNIT_SECONDS | 51 | #define MAINT_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) |
52 | |||
53 | /** | ||
54 | * Run fast maintenance after 100ms. This is used for an extra-job | ||
55 | * that is run to check for a process that we just killed. | ||
56 | */ | ||
57 | #define MAINT_FAST_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100) | ||
52 | 58 | ||
53 | /** | 59 | /** |
54 | * How long do we wait until we decide that a service | 60 | * How long do we wait until we decide that a service |
@@ -56,8 +62,18 @@ | |||
56 | */ | 62 | */ |
57 | #define CHECK_TIMEOUT GNUNET_TIME_UNIT_MINUTES | 63 | #define CHECK_TIMEOUT GNUNET_TIME_UNIT_MINUTES |
58 | 64 | ||
65 | /** | ||
66 | * List of our services. | ||
67 | */ | ||
59 | struct ServiceList; | 68 | struct ServiceList; |
60 | 69 | ||
70 | /** | ||
71 | * Function to call if waitpid informs us that | ||
72 | * a process has died. | ||
73 | * | ||
74 | * @param cls closure | ||
75 | * @param pos entry in the service list of the process that died | ||
76 | */ | ||
61 | typedef void (*CleanCallback) (void *cls, struct ServiceList * pos); | 77 | typedef void (*CleanCallback) (void *cls, struct ServiceList * pos); |
62 | 78 | ||
63 | /** | 79 | /** |
@@ -137,6 +153,24 @@ static struct GNUNET_SCHEDULER_Handle *sched; | |||
137 | static char *prefix_command; | 153 | static char *prefix_command; |
138 | 154 | ||
139 | 155 | ||
156 | /** | ||
157 | * Background task doing maintenance. | ||
158 | * | ||
159 | * @param cls closure, NULL if we need to self-restart | ||
160 | * @param tc context | ||
161 | */ | ||
162 | static void | ||
163 | maint (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
164 | |||
165 | |||
166 | /** | ||
167 | * Transmit a status result message. | ||
168 | * | ||
169 | * @param cls pointer to "unit16_t*" with message type | ||
170 | * @param size number of bytes available in buf | ||
171 | * @param buf where to copy the message, NULL on error | ||
172 | * @return number of bytes copied to buf | ||
173 | */ | ||
140 | static size_t | 174 | static size_t |
141 | write_result (void *cls, size_t size, void *buf) | 175 | write_result (void *cls, size_t size, void *buf) |
142 | { | 176 | { |
@@ -159,6 +193,9 @@ write_result (void *cls, size_t size, void *buf) | |||
159 | * Signal our client that we will start or stop the | 193 | * Signal our client that we will start or stop the |
160 | * service. | 194 | * service. |
161 | * | 195 | * |
196 | * @param client who is being signalled | ||
197 | * @param name name of the service | ||
198 | * @param result message type to send | ||
162 | * @return NULL if it was not found | 199 | * @return NULL if it was not found |
163 | */ | 200 | */ |
164 | static void | 201 | static void |
@@ -188,6 +225,7 @@ signal_result (struct GNUNET_SERVER_Client *client, | |||
188 | * Find the process with the given service | 225 | * Find the process with the given service |
189 | * name in the given list, remove it and return it. | 226 | * name in the given list, remove it and return it. |
190 | * | 227 | * |
228 | * @param name which service entry to look up | ||
191 | * @return NULL if it was not found | 229 | * @return NULL if it was not found |
192 | */ | 230 | */ |
193 | static struct ServiceList * | 231 | static struct ServiceList * |
@@ -216,6 +254,11 @@ find_name (const char *name) | |||
216 | } | 254 | } |
217 | 255 | ||
218 | 256 | ||
257 | /** | ||
258 | * Free an entry in the service list. | ||
259 | * | ||
260 | * @param pos entry to free | ||
261 | */ | ||
219 | static void | 262 | static void |
220 | free_entry (struct ServiceList *pos) | 263 | free_entry (struct ServiceList *pos) |
221 | { | 264 | { |
@@ -226,8 +269,6 @@ free_entry (struct ServiceList *pos) | |||
226 | } | 269 | } |
227 | 270 | ||
228 | 271 | ||
229 | |||
230 | |||
231 | /** | 272 | /** |
232 | * Actually start the process for the given service. | 273 | * Actually start the process for the given service. |
233 | * | 274 | * |
@@ -335,6 +376,9 @@ start_process (struct ServiceList *sl) | |||
335 | 376 | ||
336 | /** | 377 | /** |
337 | * Start the specified service. | 378 | * Start the specified service. |
379 | * | ||
380 | * @param client who is asking for this | ||
381 | * @param servicename name of the service to start | ||
338 | */ | 382 | */ |
339 | static void | 383 | static void |
340 | start_service (struct GNUNET_SERVER_Client *client, const char *servicename) | 384 | start_service (struct GNUNET_SERVER_Client *client, const char *servicename) |
@@ -394,6 +438,13 @@ start_service (struct GNUNET_SERVER_Client *client, const char *servicename) | |||
394 | } | 438 | } |
395 | 439 | ||
396 | 440 | ||
441 | /** | ||
442 | * Free the given entry in the service list and signal | ||
443 | * the given client that the service is now down. | ||
444 | * | ||
445 | * @param cls pointer to the client ("struct GNUNET_SERVER_Client*") | ||
446 | * @param pos entry for the service | ||
447 | */ | ||
397 | static void | 448 | static void |
398 | free_and_signal (void *cls, struct ServiceList *pos) | 449 | free_and_signal (void *cls, struct ServiceList *pos) |
399 | { | 450 | { |
@@ -409,9 +460,13 @@ free_and_signal (void *cls, struct ServiceList *pos) | |||
409 | 460 | ||
410 | /** | 461 | /** |
411 | * Stop the specified service. | 462 | * Stop the specified service. |
463 | * | ||
464 | * @param client who is asking for this | ||
465 | * @param servicename name of the service to stop | ||
412 | */ | 466 | */ |
413 | static void | 467 | static void |
414 | stop_service (struct GNUNET_SERVER_Client *client, const char *servicename) | 468 | stop_service (struct GNUNET_SERVER_Client *client, |
469 | const char *servicename) | ||
415 | { | 470 | { |
416 | struct ServiceList *pos; | 471 | struct ServiceList *pos; |
417 | struct GNUNET_CLIENT_Connection *sc; | 472 | struct GNUNET_CLIENT_Connection *sc; |
@@ -445,6 +500,11 @@ stop_service (struct GNUNET_SERVER_Client *client, const char *servicename) | |||
445 | pos->kill_continuation = &free_and_signal; | 500 | pos->kill_continuation = &free_and_signal; |
446 | pos->kill_continuation_cls = client; | 501 | pos->kill_continuation_cls = client; |
447 | GNUNET_SERVER_client_keep (client); | 502 | GNUNET_SERVER_client_keep (client); |
503 | GNUNET_SCHEDULER_add_delayed (sched, | ||
504 | GNUNET_YES, | ||
505 | GNUNET_SCHEDULER_PRIORITY_IDLE, | ||
506 | GNUNET_SCHEDULER_NO_TASK, | ||
507 | MAINT_FAST_FREQUENCY, &maint, NULL); | ||
448 | } | 508 | } |
449 | else | 509 | else |
450 | { | 510 | { |
@@ -529,11 +589,10 @@ handle_stop (void *cls, | |||
529 | } | 589 | } |
530 | 590 | ||
531 | 591 | ||
532 | |||
533 | /** | 592 | /** |
534 | * Background task doing maintenance. | 593 | * Background task doing maintenance. |
535 | * | 594 | * |
536 | * @param cls closure | 595 | * @param cls closure, NULL if we need to self-restart |
537 | * @param tc context | 596 | * @param tc context |
538 | */ | 597 | */ |
539 | static void | 598 | static void |
@@ -561,11 +620,12 @@ maint (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
561 | } | 620 | } |
562 | return; | 621 | return; |
563 | } | 622 | } |
564 | GNUNET_SCHEDULER_add_delayed (tc->sched, | 623 | if (cls == NULL) |
565 | GNUNET_YES, | 624 | GNUNET_SCHEDULER_add_delayed (tc->sched, |
566 | GNUNET_SCHEDULER_PRIORITY_IDLE, | 625 | GNUNET_YES, |
567 | GNUNET_SCHEDULER_NO_TASK, | 626 | GNUNET_SCHEDULER_PRIORITY_IDLE, |
568 | MAINT_FREQUENCY, &maint, NULL); | 627 | GNUNET_SCHEDULER_NO_TASK, |
628 | MAINT_FREQUENCY, &maint, NULL); | ||
569 | 629 | ||
570 | /* check for services that died (WAITPID) */ | 630 | /* check for services that died (WAITPID) */ |
571 | prev = NULL; | 631 | prev = NULL; |
@@ -656,8 +716,7 @@ maint (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
656 | 716 | ||
657 | 717 | ||
658 | /** | 718 | /** |
659 | * List of handlers for the messages understood by this | 719 | * List of handlers for the messages understood by this service. |
660 | * service. | ||
661 | */ | 720 | */ |
662 | static struct GNUNET_SERVER_MessageHandler handlers[] = { | 721 | static struct GNUNET_SERVER_MessageHandler handlers[] = { |
663 | {&handle_start, NULL, GNUNET_MESSAGE_TYPE_ARM_START, 0}, | 722 | {&handle_start, NULL, GNUNET_MESSAGE_TYPE_ARM_START, 0}, |
diff --git a/src/arm/test_arm_api.c b/src/arm/test_arm_api.c index fbd90583e..22fa3716e 100644 --- a/src/arm/test_arm_api.c +++ b/src/arm/test_arm_api.c | |||
@@ -40,17 +40,28 @@ static struct GNUNET_SCHEDULER_Handle *sched; | |||
40 | 40 | ||
41 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 41 | static const struct GNUNET_CONFIGURATION_Handle *cfg; |
42 | 42 | ||
43 | static struct GNUNET_ARM_Handle *arm; | ||
44 | |||
43 | static int ok = 1; | 45 | static int ok = 1; |
44 | 46 | ||
47 | |||
48 | static void | ||
49 | arm_notify_stop (void *cls, int success) | ||
50 | { | ||
51 | GNUNET_assert (success == GNUNET_NO); | ||
52 | #if START_ARM | ||
53 | GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, NULL, NULL); | ||
54 | #endif | ||
55 | } | ||
56 | |||
57 | |||
45 | static void | 58 | static void |
46 | dns_notify (void *cls, const struct sockaddr *addr, socklen_t addrlen) | 59 | dns_notify (void *cls, const struct sockaddr *addr, socklen_t addrlen) |
47 | { | 60 | { |
48 | if (addr == NULL) | 61 | if (addr == NULL) |
49 | { | 62 | { |
50 | GNUNET_assert (ok == 0); | 63 | GNUNET_assert (ok == 0); |
51 | #if START_ARM | 64 | GNUNET_ARM_stop_service (arm, "resolver", TIMEOUT, &arm_notify_stop, NULL); |
52 | GNUNET_ARM_stop_service ("arm", cfg, sched, TIMEOUT, NULL, NULL); | ||
53 | #endif | ||
54 | return; | 65 | return; |
55 | } | 66 | } |
56 | GNUNET_assert (addr != NULL); | 67 | GNUNET_assert (addr != NULL); |
@@ -62,21 +73,17 @@ static void | |||
62 | resolver_notify (void *cls, int success) | 73 | resolver_notify (void *cls, int success) |
63 | { | 74 | { |
64 | GNUNET_assert (success == GNUNET_YES); | 75 | GNUNET_assert (success == GNUNET_YES); |
65 | sleep (1); /* FIXME: that we need to do this is a problem... */ | ||
66 | GNUNET_RESOLVER_ip_get (sched, | 76 | GNUNET_RESOLVER_ip_get (sched, |
67 | cfg, | 77 | cfg, |
68 | "localhost", AF_INET, TIMEOUT, &dns_notify, NULL); | 78 | "localhost", AF_INET, TIMEOUT, &dns_notify, NULL); |
69 | } | 79 | } |
70 | 80 | ||
81 | |||
71 | static void | 82 | static void |
72 | arm_notify (void *cls, int success) | 83 | arm_notify (void *cls, int success) |
73 | { | 84 | { |
74 | GNUNET_assert (success == GNUNET_YES); | 85 | GNUNET_assert (success == GNUNET_YES); |
75 | #if START_ARM | 86 | GNUNET_ARM_start_service (arm, "resolver", TIMEOUT, &resolver_notify, NULL); |
76 | sleep (1); /* FIXME: that we need to do this is a problem... */ | ||
77 | #endif | ||
78 | GNUNET_ARM_start_service ("resolver", | ||
79 | cfg, sched, TIMEOUT, &resolver_notify, NULL); | ||
80 | } | 87 | } |
81 | 88 | ||
82 | 89 | ||
@@ -89,8 +96,9 @@ task (void *cls, | |||
89 | { | 96 | { |
90 | cfg = c; | 97 | cfg = c; |
91 | sched = s; | 98 | sched = s; |
99 | arm = GNUNET_ARM_connect (cfg, sched, NULL); | ||
92 | #if START_ARM | 100 | #if START_ARM |
93 | GNUNET_ARM_start_service ("arm", cfg, sched, TIMEOUT, &arm_notify, NULL); | 101 | GNUNET_ARM_start_service (arm, "arm", TIMEOUT, &arm_notify, NULL); |
94 | #else | 102 | #else |
95 | arm_notify (NULL, GNUNET_YES); | 103 | arm_notify (NULL, GNUNET_YES); |
96 | #endif | 104 | #endif |
diff --git a/src/core/test_core_api.c b/src/core/test_core_api.c index 13c1dc48e..d72af8254 100644 --- a/src/core/test_core_api.c +++ b/src/core/test_core_api.c | |||
@@ -82,8 +82,8 @@ terminate_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
82 | GNUNET_CORE_disconnect (p2.ch); | 82 | GNUNET_CORE_disconnect (p2.ch); |
83 | GNUNET_TRANSPORT_disconnect (p1.th); | 83 | GNUNET_TRANSPORT_disconnect (p1.th); |
84 | GNUNET_TRANSPORT_disconnect (p2.th); | 84 | GNUNET_TRANSPORT_disconnect (p2.th); |
85 | GNUNET_ARM_stop_service ("core", p1.cfg, sched, TIMEOUT, NULL, NULL); | 85 | GNUNET_ARM_stop_services (p1.cfg, sched, "core", NULL); |
86 | GNUNET_ARM_stop_service ("core", p2.cfg, sched, TIMEOUT, NULL, NULL); | 86 | GNUNET_ARM_stop_services (p2.cfg, sched, "core", NULL); |
87 | ok = 0; | 87 | ok = 0; |
88 | } | 88 | } |
89 | 89 | ||
@@ -96,8 +96,8 @@ terminate_task_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
96 | GNUNET_CORE_disconnect (p2.ch); | 96 | GNUNET_CORE_disconnect (p2.ch); |
97 | GNUNET_TRANSPORT_disconnect (p1.th); | 97 | GNUNET_TRANSPORT_disconnect (p1.th); |
98 | GNUNET_TRANSPORT_disconnect (p2.th); | 98 | GNUNET_TRANSPORT_disconnect (p2.th); |
99 | GNUNET_ARM_stop_service ("core", p1.cfg, sched, TIMEOUT, NULL, NULL); | 99 | GNUNET_ARM_stop_services (p1.cfg, sched, "core", NULL); |
100 | GNUNET_ARM_stop_service ("core", p2.cfg, sched, TIMEOUT, NULL, NULL); | 100 | GNUNET_ARM_stop_services (p2.cfg, sched, "core", NULL); |
101 | ok = 42; | 101 | ok = 42; |
102 | } | 102 | } |
103 | 103 | ||
@@ -303,7 +303,7 @@ setup_peer (struct PeerContext *p, const char *cfgname) | |||
303 | sleep (1); /* allow ARM to start */ | 303 | sleep (1); /* allow ARM to start */ |
304 | #endif | 304 | #endif |
305 | GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); | 305 | GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); |
306 | GNUNET_ARM_start_service ("core", p->cfg, sched, TIMEOUT, NULL, NULL); | 306 | GNUNET_ARM_start_services (p->cfg, sched, "core", NULL); |
307 | p->th = GNUNET_TRANSPORT_connect (sched, p->cfg, p, NULL, NULL, NULL); | 307 | p->th = GNUNET_TRANSPORT_connect (sched, p->cfg, p, NULL, NULL, NULL); |
308 | GNUNET_assert (p->th != NULL); | 308 | GNUNET_assert (p->th != NULL); |
309 | GNUNET_TRANSPORT_get_hello (p->th, TIMEOUT, &process_hello, p); | 309 | GNUNET_TRANSPORT_get_hello (p->th, TIMEOUT, &process_hello, p); |
diff --git a/src/core/test_core_api_start_only.c b/src/core/test_core_api_start_only.c index d0a5aedc4..ce2668b89 100644 --- a/src/core/test_core_api_start_only.c +++ b/src/core/test_core_api_start_only.c | |||
@@ -147,8 +147,8 @@ init_notify (void *cls, | |||
147 | GNUNET_assert (cls == &p2); | 147 | GNUNET_assert (cls == &p2); |
148 | GNUNET_CORE_disconnect (p1.ch); | 148 | GNUNET_CORE_disconnect (p1.ch); |
149 | GNUNET_CORE_disconnect (p2.ch); | 149 | GNUNET_CORE_disconnect (p2.ch); |
150 | GNUNET_ARM_stop_service ("core", p1.cfg, sched, TIMEOUT, NULL, NULL); | 150 | GNUNET_ARM_stop_services (p1.cfg, sched, "core", NULL); |
151 | GNUNET_ARM_stop_service ("core", p2.cfg, sched, TIMEOUT, NULL, NULL); | 151 | GNUNET_ARM_stop_services (p2.cfg, sched, "core", NULL); |
152 | 152 | ||
153 | ok = 0; | 153 | ok = 0; |
154 | } | 154 | } |
@@ -169,7 +169,7 @@ setup_peer (struct PeerContext *p, const char *cfgname) | |||
169 | sleep (1); /* allow ARM to start */ | 169 | sleep (1); /* allow ARM to start */ |
170 | #endif | 170 | #endif |
171 | GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); | 171 | GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); |
172 | GNUNET_ARM_start_service ("core", p->cfg, sched, TIMEOUT, NULL, NULL); | 172 | GNUNET_ARM_start_services (p->cfg, sched, "core", NULL); |
173 | } | 173 | } |
174 | 174 | ||
175 | 175 | ||
diff --git a/src/include/gnunet_arm_service.h b/src/include/gnunet_arm_service.h index bbb8cb0f6..8e68cd5ee 100644 --- a/src/include/gnunet_arm_service.h +++ b/src/include/gnunet_arm_service.h | |||
@@ -58,45 +58,111 @@ typedef void (*GNUNET_ARM_Callback) (void *cls, int success); | |||
58 | 58 | ||
59 | 59 | ||
60 | /** | 60 | /** |
61 | * Start a service. | 61 | * Handle for interacting with ARM. |
62 | */ | ||
63 | struct GNUNET_ARM_Handle; | ||
64 | |||
65 | |||
66 | /** | ||
67 | * Setup a context for communicating with ARM. Note that this | ||
68 | * can be done even if the ARM service is not yet running. | ||
62 | * | 69 | * |
63 | * @param service_name name of the service | ||
64 | * @param cfg configuration to use (needed to contact ARM; | 70 | * @param cfg configuration to use (needed to contact ARM; |
65 | * the ARM service may internally use a different | 71 | * the ARM service may internally use a different |
66 | * configuration to determine how to start the service). | 72 | * configuration to determine how to start the service). |
67 | * @param sched scheduler to use | 73 | * @param sched scheduler to use |
74 | * @param service service that *this* process is implementing/providing, can be NULL | ||
75 | * @return context to use for further ARM operations, NULL on error | ||
76 | */ | ||
77 | struct GNUNET_ARM_Handle * | ||
78 | GNUNET_ARM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
79 | struct GNUNET_SCHEDULER_Handle *sched, | ||
80 | const char *service); | ||
81 | |||
82 | |||
83 | /** | ||
84 | * Disconnect from the ARM service. | ||
85 | * | ||
86 | * @param h the handle that was being used | ||
87 | */ | ||
88 | void | ||
89 | GNUNET_ARM_disconnect (struct GNUNET_ARM_Handle *h); | ||
90 | |||
91 | |||
92 | /** | ||
93 | * Start a service. Note that this function merely asks ARM to start | ||
94 | * the service and that ARM merely confirms that it forked the | ||
95 | * respective process. The specified callback may thus return before | ||
96 | * the service has started to listen on the server socket and it may | ||
97 | * also be that the service has crashed in the meantime. Clients | ||
98 | * should repeatedly try to connect to the service at the respective | ||
99 | * port (with some delays in between) before assuming that the service | ||
100 | * actually failed to start. Note that if an error is returned to the | ||
101 | * callback, clients obviously should not bother with trying to | ||
102 | * contact the service. | ||
103 | * | ||
104 | * @param h handle to ARM | ||
105 | * @param service_name name of the service | ||
68 | * @param timeout how long to wait before failing for good | 106 | * @param timeout how long to wait before failing for good |
69 | * @param cb callback to invoke when service is ready | 107 | * @param cb callback to invoke when service is ready |
70 | * @param cb_cls closure for callback | 108 | * @param cb_cls closure for callback |
71 | */ | 109 | */ |
72 | void | 110 | void |
73 | GNUNET_ARM_start_service (const char *service_name, | 111 | GNUNET_ARM_start_service (struct GNUNET_ARM_Handle *h, |
74 | const struct GNUNET_CONFIGURATION_Handle *cfg, | 112 | const char *service_name, |
75 | struct GNUNET_SCHEDULER_Handle *sched, | ||
76 | struct GNUNET_TIME_Relative timeout, | 113 | struct GNUNET_TIME_Relative timeout, |
77 | GNUNET_ARM_Callback cb, void *cb_cls); | 114 | GNUNET_ARM_Callback cb, void *cb_cls); |
78 | 115 | ||
79 | 116 | ||
80 | /** | 117 | /** |
81 | * Stop a service. | 118 | * Stop a service. Note that the callback is invoked as soon |
119 | * as ARM confirms that it will ask the service to terminate. | ||
120 | * The actual termination may still take some time. | ||
82 | * | 121 | * |
122 | * @param h handle to ARM | ||
83 | * @param service_name name of the service | 123 | * @param service_name name of the service |
84 | * @param cfg configuration to use (needed to contact ARM; | ||
85 | * the ARM service may internally use a different | ||
86 | * configuration to determine how to start the service). | ||
87 | * @param sched scheduler to use | ||
88 | * @param timeout how long to wait before failing for good | 124 | * @param timeout how long to wait before failing for good |
89 | * @param cb callback to invoke when service is ready | 125 | * @param cb callback to invoke when service is ready |
90 | * @param cb_cls closure for callback | 126 | * @param cb_cls closure for callback |
91 | */ | 127 | */ |
92 | void | 128 | void |
93 | GNUNET_ARM_stop_service (const char *service_name, | 129 | GNUNET_ARM_stop_service (struct GNUNET_ARM_Handle *h, |
94 | const struct GNUNET_CONFIGURATION_Handle *cfg, | 130 | const char *service_name, |
95 | struct GNUNET_SCHEDULER_Handle *sched, | ||
96 | struct GNUNET_TIME_Relative timeout, | 131 | struct GNUNET_TIME_Relative timeout, |
97 | GNUNET_ARM_Callback cb, void *cb_cls); | 132 | GNUNET_ARM_Callback cb, void *cb_cls); |
98 | 133 | ||
99 | 134 | ||
135 | /** | ||
136 | * Start multiple services in the specified order. Convenience | ||
137 | * function. Works asynchronously, failures are not reported. | ||
138 | * | ||
139 | * @param cfg configuration to use (needed to contact ARM; | ||
140 | * the ARM service may internally use a different | ||
141 | * configuration to determine how to start the service). | ||
142 | * @param sched scheduler to use | ||
143 | * @param ... NULL-terminated list of service names (const char*) | ||
144 | */ | ||
145 | void | ||
146 | GNUNET_ARM_start_services (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
147 | struct GNUNET_SCHEDULER_Handle *sched, | ||
148 | ...); | ||
149 | |||
150 | |||
151 | /** | ||
152 | * Stop multiple services in the specified order. Convenience | ||
153 | * function. Works asynchronously, failures are not reported. | ||
154 | * | ||
155 | * @param cfg configuration to use (needed to contact ARM; | ||
156 | * the ARM service may internally use a different | ||
157 | * configuration to determine how to start the service). | ||
158 | * @param sched scheduler to use | ||
159 | * @param ... NULL-terminated list of service names (const char*) | ||
160 | */ | ||
161 | void | ||
162 | GNUNET_ARM_stop_services (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
163 | struct GNUNET_SCHEDULER_Handle *sched, | ||
164 | ...); | ||
165 | |||
100 | 166 | ||
101 | #if 0 /* keep Emacsens' auto-indent happy */ | 167 | #if 0 /* keep Emacsens' auto-indent happy */ |
102 | { | 168 | { |
diff --git a/src/testing/testing.c b/src/testing/testing.c index a82842777..4bdad178f 100644 --- a/src/testing/testing.c +++ b/src/testing/testing.c | |||
@@ -49,9 +49,8 @@ | |||
49 | #define ARM_START_WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) | 49 | #define ARM_START_WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) |
50 | 50 | ||
51 | /** | 51 | /** |
52 | * How many times are we willing to try to | 52 | * How many times are we willing to try to wait for "scp" or |
53 | * wait for "scp" or "gnunet-service-arm" to | 53 | * "gnunet-service-arm" to complete (waitpid) before giving up? |
54 | * complete (waitpid) before giving up? | ||
55 | */ | 54 | */ |
56 | #define MAX_EXEC_WAIT_RUNS 50 | 55 | #define MAX_EXEC_WAIT_RUNS 50 |
57 | 56 | ||
@@ -60,12 +59,39 @@ | |||
60 | */ | 59 | */ |
61 | enum StartPhase | 60 | enum StartPhase |
62 | { | 61 | { |
62 | /** | ||
63 | * FIXME. | ||
64 | */ | ||
63 | SP_COPYING, | 65 | SP_COPYING, |
66 | |||
67 | /** | ||
68 | * FIXME. | ||
69 | */ | ||
64 | SP_COPIED, | 70 | SP_COPIED, |
71 | |||
72 | /** | ||
73 | * FIXME. | ||
74 | */ | ||
65 | SP_START_ARMING, | 75 | SP_START_ARMING, |
76 | |||
77 | /** | ||
78 | * FIXME. | ||
79 | */ | ||
66 | SP_START_CORE, | 80 | SP_START_CORE, |
81 | |||
82 | /** | ||
83 | * FIXME. | ||
84 | */ | ||
67 | SP_START_DONE, | 85 | SP_START_DONE, |
86 | |||
87 | /** | ||
88 | * FIXME. | ||
89 | */ | ||
68 | SP_CLEANUP, | 90 | SP_CLEANUP, |
91 | |||
92 | /** | ||
93 | * FIXME. | ||
94 | */ | ||
69 | SP_CONFIG_UPDATE | 95 | SP_CONFIG_UPDATE |
70 | }; | 96 | }; |
71 | 97 | ||
@@ -839,21 +865,56 @@ void GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d, | |||
839 | d); | 865 | d); |
840 | } | 866 | } |
841 | 867 | ||
842 | 868 | /** | |
869 | * FIXME. | ||
870 | */ | ||
843 | struct ConnectContext | 871 | struct ConnectContext |
844 | { | 872 | { |
873 | /** | ||
874 | * FIXME. | ||
875 | */ | ||
845 | struct GNUNET_TESTING_Daemon *d1; | 876 | struct GNUNET_TESTING_Daemon *d1; |
877 | |||
878 | /** | ||
879 | * FIXME. | ||
880 | */ | ||
846 | struct GNUNET_TESTING_Daemon *d2; | 881 | struct GNUNET_TESTING_Daemon *d2; |
882 | |||
883 | /** | ||
884 | * FIXME. | ||
885 | */ | ||
847 | struct GNUNET_TRANSPORT_Handle *d1th; | 886 | struct GNUNET_TRANSPORT_Handle *d1th; |
887 | |||
888 | /** | ||
889 | * FIXME. | ||
890 | */ | ||
848 | struct GNUNET_TRANSPORT_Handle *d2th; | 891 | struct GNUNET_TRANSPORT_Handle *d2th; |
892 | |||
893 | /** | ||
894 | * When should this operation be complete (or we must trigger | ||
895 | * a timeout). | ||
896 | */ | ||
849 | struct GNUNET_TIME_Absolute timeout; | 897 | struct GNUNET_TIME_Absolute timeout; |
898 | |||
899 | /** | ||
900 | * Function to call once we are done (or have timed out). | ||
901 | */ | ||
850 | GNUNET_TESTING_NotifyCompletion cb; | 902 | GNUNET_TESTING_NotifyCompletion cb; |
903 | |||
904 | /** | ||
905 | * Closure for "nb". | ||
906 | */ | ||
851 | void *cb_cls; | 907 | void *cb_cls; |
852 | }; | 908 | }; |
853 | 909 | ||
854 | 910 | ||
855 | /** | 911 | /** |
856 | * Success, connection is up. Signal client our success. | 912 | * Success, connection is up. Signal client our success. |
913 | * | ||
914 | * @param cls FIXME | ||
915 | * @param size number of bytes available in buf | ||
916 | * @param buf where to copy the message, NULL on error | ||
917 | * @return number of bytes copied to buf | ||
857 | */ | 918 | */ |
858 | static size_t | 919 | static size_t |
859 | transmit_ready (void *cls, size_t size, void *buf) | 920 | transmit_ready (void *cls, size_t size, void *buf) |
diff --git a/src/transport/transport_api.c b/src/transport/transport_api.c index b1b8ce445..9a7068e42 100644 --- a/src/transport/transport_api.c +++ b/src/transport/transport_api.c | |||
@@ -1458,10 +1458,7 @@ GNUNET_TRANSPORT_connect (struct GNUNET_SCHEDULER_Handle *sched, | |||
1458 | { | 1458 | { |
1459 | struct GNUNET_TRANSPORT_Handle *ret; | 1459 | struct GNUNET_TRANSPORT_Handle *ret; |
1460 | 1460 | ||
1461 | GNUNET_ARM_start_service ("peerinfo", | 1461 | GNUNET_ARM_start_services (cfg, sched, "peerinfo", "transport", NULL); |
1462 | cfg, sched, START_SERVICE_TIMEOUT, NULL, NULL); | ||
1463 | GNUNET_ARM_start_service ("transport", | ||
1464 | cfg, sched, START_SERVICE_TIMEOUT, NULL, NULL); | ||
1465 | ret = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_Handle)); | 1462 | ret = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_Handle)); |
1466 | ret->sched = sched; | 1463 | ret->sched = sched; |
1467 | ret->cfg = cfg; | 1464 | ret->cfg = cfg; |
@@ -1483,12 +1480,8 @@ static void | |||
1483 | stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 1480 | stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
1484 | { | 1481 | { |
1485 | struct GNUNET_TRANSPORT_Handle *handle = cls; | 1482 | struct GNUNET_TRANSPORT_Handle *handle = cls; |
1486 | GNUNET_ARM_stop_service ("transport", | 1483 | |
1487 | handle->cfg, | 1484 | GNUNET_ARM_stop_services (handle->cfg, handle->sched, "transport", "peerinfo", NULL); |
1488 | tc->sched, STOP_SERVICE_TIMEOUT, NULL, NULL); | ||
1489 | GNUNET_ARM_stop_service ("peerinfo", | ||
1490 | handle->cfg, | ||
1491 | tc->sched, STOP_SERVICE_TIMEOUT, NULL, NULL); | ||
1492 | } | 1485 | } |
1493 | 1486 | ||
1494 | 1487 | ||