diff options
Diffstat (limited to 'src/arm/arm_api.c')
-rw-r--r-- | src/arm/arm_api.c | 933 |
1 files changed, 559 insertions, 374 deletions
diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c index b42c95dc0..da7268f67 100644 --- a/src/arm/arm_api.c +++ b/src/arm/arm_api.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2009, 2010, 2012, 2013, 2016 GNUnet e.V. | 3 | Copyright (C) 2009, 2010, 2012, 2013, 2016, 2019 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software: you can redistribute it and/or modify it | 5 | GNUnet is free software: you can redistribute it and/or modify it |
6 | under the terms of the GNU Affero General Public License as published | 6 | under the terms of the GNU Affero General Public License as published |
@@ -30,14 +30,15 @@ | |||
30 | #include "gnunet_protocols.h" | 30 | #include "gnunet_protocols.h" |
31 | #include "arm.h" | 31 | #include "arm.h" |
32 | 32 | ||
33 | #define LOG(kind, ...) GNUNET_log_from(kind, "arm-api", __VA_ARGS__) | 33 | #define LOG(kind, ...) GNUNET_log_from (kind, "arm-api", __VA_ARGS__) |
34 | 34 | ||
35 | 35 | ||
36 | /** | 36 | /** |
37 | * Entry in a doubly-linked list of operations awaiting for replies | 37 | * Entry in a doubly-linked list of operations awaiting for replies |
38 | * (in-order) from the ARM service. | 38 | * (in-order) from the ARM service. |
39 | */ | 39 | */ |
40 | struct GNUNET_ARM_Operation { | 40 | struct GNUNET_ARM_Operation |
41 | { | ||
41 | /** | 42 | /** |
42 | * This is a doubly-linked list. | 43 | * This is a doubly-linked list. |
43 | */ | 44 | */ |
@@ -84,6 +85,11 @@ struct GNUNET_ARM_Operation { | |||
84 | enum GNUNET_ARM_Result starting_ret; | 85 | enum GNUNET_ARM_Result starting_ret; |
85 | 86 | ||
86 | /** | 87 | /** |
88 | * File descriptor to close on operation stop, if not NULL. | ||
89 | */ | ||
90 | struct GNUNET_DISK_FileHandle *rfd; | ||
91 | |||
92 | /** | ||
87 | * Is this an operation to stop the ARM service? | 93 | * Is this an operation to stop the ARM service? |
88 | */ | 94 | */ |
89 | int is_arm_stop; | 95 | int is_arm_stop; |
@@ -93,7 +99,8 @@ struct GNUNET_ARM_Operation { | |||
93 | /** | 99 | /** |
94 | * Handle for interacting with ARM. | 100 | * Handle for interacting with ARM. |
95 | */ | 101 | */ |
96 | struct GNUNET_ARM_Handle { | 102 | struct GNUNET_ARM_Handle |
103 | { | ||
97 | /** | 104 | /** |
98 | * Our connection to the ARM service. | 105 | * Our connection to the ARM service. |
99 | */ | 106 | */ |
@@ -164,7 +171,7 @@ struct GNUNET_ARM_Handle { | |||
164 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure | 171 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure |
165 | */ | 172 | */ |
166 | static int | 173 | static int |
167 | reconnect_arm(struct GNUNET_ARM_Handle *h); | 174 | reconnect_arm (struct GNUNET_ARM_Handle *h); |
168 | 175 | ||
169 | 176 | ||
170 | /** | 177 | /** |
@@ -173,12 +180,12 @@ reconnect_arm(struct GNUNET_ARM_Handle *h); | |||
173 | * @param cls the `struct GNUNET_ARM_Handle` | 180 | * @param cls the `struct GNUNET_ARM_Handle` |
174 | */ | 181 | */ |
175 | static void | 182 | static void |
176 | reconnect_arm_task(void *cls) | 183 | reconnect_arm_task (void *cls) |
177 | { | 184 | { |
178 | struct GNUNET_ARM_Handle *h = cls; | 185 | struct GNUNET_ARM_Handle *h = cls; |
179 | 186 | ||
180 | h->reconnect_task = NULL; | 187 | h->reconnect_task = NULL; |
181 | reconnect_arm(h); | 188 | reconnect_arm (h); |
182 | } | 189 | } |
183 | 190 | ||
184 | 191 | ||
@@ -189,31 +196,39 @@ reconnect_arm_task(void *cls) | |||
189 | * @param h our handle | 196 | * @param h our handle |
190 | */ | 197 | */ |
191 | static void | 198 | static void |
192 | reconnect_arm_later(struct GNUNET_ARM_Handle *h) | 199 | reconnect_arm_later (struct GNUNET_ARM_Handle *h) |
193 | { | 200 | { |
194 | struct GNUNET_ARM_Operation *op; | 201 | struct GNUNET_ARM_Operation *op; |
195 | 202 | ||
196 | if (NULL != h->mq) | 203 | if (NULL != h->mq) |
197 | { | 204 | { |
198 | GNUNET_MQ_destroy(h->mq); | 205 | GNUNET_MQ_destroy (h->mq); |
199 | h->mq = NULL; | 206 | h->mq = NULL; |
200 | } | 207 | } |
201 | h->currently_up = GNUNET_NO; | 208 | h->currently_up = GNUNET_NO; |
202 | GNUNET_assert(NULL == h->reconnect_task); | 209 | GNUNET_assert (NULL == h->reconnect_task); |
203 | h->reconnect_task = | 210 | h->reconnect_task = |
204 | GNUNET_SCHEDULER_add_delayed(h->retry_backoff, &reconnect_arm_task, h); | 211 | GNUNET_SCHEDULER_add_delayed (h->retry_backoff, |
212 | &reconnect_arm_task, | ||
213 | h); | ||
205 | while (NULL != (op = h->operation_pending_head)) | 214 | while (NULL != (op = h->operation_pending_head)) |
206 | { | 215 | { |
207 | if (NULL != op->result_cont) | 216 | if (NULL != op->result_cont) |
208 | op->result_cont(op->cont_cls, GNUNET_ARM_REQUEST_DISCONNECTED, 0); | 217 | op->result_cont (op->cont_cls, |
209 | if (NULL != op->list_cont) | 218 | GNUNET_ARM_REQUEST_DISCONNECTED, |
210 | op->list_cont(op->cont_cls, GNUNET_ARM_REQUEST_DISCONNECTED, 0, NULL); | 219 | 0); |
211 | GNUNET_ARM_operation_cancel(op); | 220 | if (NULL != op->list_cont) |
212 | } | 221 | op->list_cont (op->cont_cls, |
213 | GNUNET_assert(NULL == h->operation_pending_head); | 222 | GNUNET_ARM_REQUEST_DISCONNECTED, |
214 | h->retry_backoff = GNUNET_TIME_STD_BACKOFF(h->retry_backoff); | 223 | 0, |
224 | NULL); | ||
225 | GNUNET_ARM_operation_cancel (op); | ||
226 | } | ||
227 | GNUNET_assert (NULL == h->operation_pending_head); | ||
228 | h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff); | ||
215 | if (NULL != h->conn_status) | 229 | if (NULL != h->conn_status) |
216 | h->conn_status(h->conn_status_cls, GNUNET_NO); | 230 | h->conn_status (h->conn_status_cls, |
231 | GNUNET_NO); | ||
217 | } | 232 | } |
218 | 233 | ||
219 | 234 | ||
@@ -225,11 +240,11 @@ reconnect_arm_later(struct GNUNET_ARM_Handle *h) | |||
225 | * @return NULL if not found | 240 | * @return NULL if not found |
226 | */ | 241 | */ |
227 | static struct GNUNET_ARM_Operation * | 242 | static struct GNUNET_ARM_Operation * |
228 | find_op_by_id(struct GNUNET_ARM_Handle *h, uint64_t id) | 243 | find_op_by_id (struct GNUNET_ARM_Handle *h, |
244 | uint64_t id) | ||
229 | { | 245 | { |
230 | struct GNUNET_ARM_Operation *result; | 246 | for (struct GNUNET_ARM_Operation *result = h->operation_pending_head; |
231 | 247 | NULL != result; | |
232 | for (result = h->operation_pending_head; NULL != result; | ||
233 | result = result->next) | 248 | result = result->next) |
234 | if (id == result->id) | 249 | if (id == result->id) |
235 | return result; | 250 | return result; |
@@ -244,7 +259,8 @@ find_op_by_id(struct GNUNET_ARM_Handle *h, uint64_t id) | |||
244 | * @param res the message received from the arm service | 259 | * @param res the message received from the arm service |
245 | */ | 260 | */ |
246 | static void | 261 | static void |
247 | handle_arm_result(void *cls, const struct GNUNET_ARM_ResultMessage *res) | 262 | handle_arm_result (void *cls, |
263 | const struct GNUNET_ARM_ResultMessage *res) | ||
248 | { | 264 | { |
249 | struct GNUNET_ARM_Handle *h = cls; | 265 | struct GNUNET_ARM_Handle *h = cls; |
250 | struct GNUNET_ARM_Operation *op; | 266 | struct GNUNET_ARM_Operation *op; |
@@ -253,75 +269,123 @@ handle_arm_result(void *cls, const struct GNUNET_ARM_ResultMessage *res) | |||
253 | GNUNET_ARM_ResultCallback result_cont; | 269 | GNUNET_ARM_ResultCallback result_cont; |
254 | void *result_cont_cls; | 270 | void *result_cont_cls; |
255 | 271 | ||
256 | id = GNUNET_ntohll(res->arm_msg.request_id); | 272 | id = GNUNET_ntohll (res->arm_msg.request_id); |
257 | op = find_op_by_id(h, id); | 273 | op = find_op_by_id (h, |
274 | id); | ||
258 | if (NULL == op) | 275 | if (NULL == op) |
276 | { | ||
277 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
278 | "Message with unknown id %llu\n", | ||
279 | (unsigned long long) id); | ||
280 | return; | ||
281 | } | ||
282 | |||
283 | result = (enum GNUNET_ARM_Result) ntohl (res->result); | ||
284 | if ( (GNUNET_YES == op->is_arm_stop) && | ||
285 | (GNUNET_ARM_RESULT_STOPPING == result) ) | ||
286 | { | ||
287 | /* special case: if we are stopping 'gnunet-service-arm', we do not just | ||
288 | wait for the result message, but also wait for the service to close | ||
289 | the connection (and then we have to close our client handle as well); | ||
290 | this is done by installing a different receive handler, waiting for | ||
291 | the connection to go down */ | ||
292 | if (NULL != h->thm) | ||
259 | { | 293 | { |
260 | LOG(GNUNET_ERROR_TYPE_DEBUG, | 294 | GNUNET_break (0); |
261 | "Message with unknown id %llu\n", | 295 | op->result_cont (h->thm->cont_cls, |
262 | (unsigned long long)id); | 296 | GNUNET_ARM_REQUEST_SENT_OK, |
263 | return; | 297 | GNUNET_ARM_RESULT_IS_NOT_KNOWN); |
264 | } | 298 | GNUNET_free (h->thm); |
265 | |||
266 | result = (enum GNUNET_ARM_Result)ntohl(res->result); | ||
267 | if ((GNUNET_YES == op->is_arm_stop) && (GNUNET_ARM_RESULT_STOPPING == result)) | ||
268 | { | ||
269 | /* special case: if we are stopping 'gnunet-service-arm', we do not just | ||
270 | wait for the result message, but also wait for the service to close | ||
271 | the connection (and then we have to close our client handle as well); | ||
272 | this is done by installing a different receive handler, waiting for | ||
273 | the connection to go down */ | ||
274 | if (NULL != h->thm) | ||
275 | { | ||
276 | GNUNET_break(0); | ||
277 | op->result_cont(h->thm->cont_cls, | ||
278 | GNUNET_ARM_REQUEST_SENT_OK, | ||
279 | GNUNET_ARM_RESULT_IS_NOT_KNOWN); | ||
280 | GNUNET_free(h->thm); | ||
281 | } | ||
282 | GNUNET_CONTAINER_DLL_remove(h->operation_pending_head, | ||
283 | h->operation_pending_tail, | ||
284 | op); | ||
285 | h->thm = op; | ||
286 | return; | ||
287 | } | 299 | } |
300 | GNUNET_CONTAINER_DLL_remove (h->operation_pending_head, | ||
301 | h->operation_pending_tail, | ||
302 | op); | ||
303 | h->thm = op; | ||
304 | return; | ||
305 | } | ||
288 | result_cont = op->result_cont; | 306 | result_cont = op->result_cont; |
289 | result_cont_cls = op->cont_cls; | 307 | result_cont_cls = op->cont_cls; |
290 | GNUNET_ARM_operation_cancel(op); | 308 | GNUNET_ARM_operation_cancel (op); |
291 | if (NULL != result_cont) | 309 | if (NULL != result_cont) |
292 | result_cont(result_cont_cls, GNUNET_ARM_REQUEST_SENT_OK, result); | 310 | result_cont (result_cont_cls, |
311 | GNUNET_ARM_REQUEST_SENT_OK, | ||
312 | result); | ||
293 | } | 313 | } |
294 | 314 | ||
295 | 315 | ||
296 | /** | 316 | /** |
297 | * Checked that list result message is well-formed. | 317 | * Read from a string pool. |
318 | * | ||
319 | * @param pool_start start of the string pool | ||
320 | * @param pool_size size of the string pool | ||
321 | * @param str_index index into the string pool | ||
322 | * @returns an index into the string pool, or | ||
323 | * NULL if the index is out of bounds | ||
324 | */ | ||
325 | static const char * | ||
326 | pool_get (const char *pool_start, | ||
327 | size_t pool_size, | ||
328 | size_t str_index) | ||
329 | { | ||
330 | const char *str_start; | ||
331 | const char *end; | ||
332 | |||
333 | if (str_index >= pool_size) | ||
334 | return NULL; | ||
335 | str_start = pool_start + str_index; | ||
336 | end = memchr (str_start, 0, pool_size - str_index); | ||
337 | if (NULL == end) | ||
338 | return NULL; | ||
339 | return str_start; | ||
340 | } | ||
341 | |||
342 | |||
343 | /** | ||
344 | * Check that list result message is well-formed. | ||
298 | * | 345 | * |
299 | * @param cls our `struct GNUNET_ARM_Handle` | 346 | * @param cls our `struct GNUNET_ARM_Handle` |
300 | * @param lres the message received from the arm service | 347 | * @param lres the message received from the arm service |
301 | * @return #GNUNET_OK if message is well-formed | 348 | * @return #GNUNET_OK if message is well-formed |
302 | */ | 349 | */ |
303 | static int | 350 | static int |
304 | check_arm_list_result(void *cls, | 351 | check_arm_list_result (void *cls, |
305 | const struct GNUNET_ARM_ListResultMessage *lres) | 352 | const struct GNUNET_ARM_ListResultMessage *lres) |
306 | { | 353 | { |
307 | const char *pos = (const char *)&lres[1]; | 354 | uint16_t rcount = ntohs (lres->count); |
308 | uint16_t rcount = ntohs(lres->count); | 355 | uint16_t msize = ntohs (lres->arm_msg.header.size) - sizeof(*lres); |
309 | uint16_t msize = ntohs(lres->arm_msg.header.size) - sizeof(*lres); | 356 | struct GNUNET_ARM_ServiceInfoMessage *ssm; |
310 | uint16_t size_check; | 357 | size_t pool_size; |
311 | 358 | char *pool_start; | |
312 | (void)cls; | 359 | |
313 | size_check = 0; | 360 | (void) cls; |
361 | if ((rcount * sizeof (struct GNUNET_ARM_ServiceInfoMessage) > msize)) | ||
362 | { | ||
363 | GNUNET_break_op (0); | ||
364 | return GNUNET_NO; | ||
365 | } | ||
366 | ssm = (struct GNUNET_ARM_ServiceInfoMessage *) &lres[1]; | ||
367 | pool_start = (char *) (ssm + rcount); | ||
368 | pool_size = msize - (rcount * sizeof (struct GNUNET_ARM_ServiceInfoMessage)); | ||
314 | for (unsigned int i = 0; i < rcount; i++) | 369 | for (unsigned int i = 0; i < rcount; i++) |
370 | { | ||
371 | uint16_t name_index = ntohs (ssm->name_index); | ||
372 | uint16_t binary_index = ntohs (ssm->binary_index); | ||
373 | if (NULL == pool_get (pool_start, | ||
374 | pool_size, | ||
375 | name_index)) | ||
315 | { | 376 | { |
316 | const char *end = memchr(pos, 0, msize - size_check); | 377 | GNUNET_break_op (0); |
317 | if (NULL == end) | 378 | return GNUNET_NO; |
318 | { | ||
319 | GNUNET_break(0); | ||
320 | return GNUNET_SYSERR; | ||
321 | } | ||
322 | size_check += (end - pos) + 1; | ||
323 | pos = end + 1; | ||
324 | } | 379 | } |
380 | if (NULL == pool_get (pool_start, | ||
381 | pool_size, | ||
382 | binary_index)) | ||
383 | { | ||
384 | GNUNET_break_op (0); | ||
385 | return GNUNET_NO; | ||
386 | } | ||
387 | ssm++; | ||
388 | } | ||
325 | return GNUNET_OK; | 389 | return GNUNET_OK; |
326 | } | 390 | } |
327 | 391 | ||
@@ -333,41 +397,65 @@ check_arm_list_result(void *cls, | |||
333 | * @param lres the message received from the arm service | 397 | * @param lres the message received from the arm service |
334 | */ | 398 | */ |
335 | static void | 399 | static void |
336 | handle_arm_list_result(void *cls, | 400 | handle_arm_list_result (void *cls, |
337 | const struct GNUNET_ARM_ListResultMessage *lres) | 401 | const struct GNUNET_ARM_ListResultMessage *lres) |
338 | { | 402 | { |
339 | struct GNUNET_ARM_Handle *h = cls; | 403 | struct GNUNET_ARM_Handle *h = cls; |
340 | uint16_t rcount = ntohs(lres->count); | 404 | uint16_t rcount = ntohs (lres->count); |
341 | const char *list[rcount]; | 405 | uint16_t msize = ntohs (lres->arm_msg.header.size) - sizeof(*lres); |
342 | const char *pos = (const char *)&lres[1]; | 406 | struct GNUNET_ARM_ServiceInfo list[rcount]; |
343 | uint16_t msize = ntohs(lres->arm_msg.header.size) - sizeof(*lres); | 407 | struct GNUNET_ARM_ServiceInfoMessage *ssm; |
344 | struct GNUNET_ARM_Operation *op; | 408 | struct GNUNET_ARM_Operation *op; |
345 | uint16_t size_check; | ||
346 | uint64_t id; | 409 | uint64_t id; |
410 | size_t pool_size; | ||
411 | char *pool_start; | ||
347 | 412 | ||
348 | id = GNUNET_ntohll(lres->arm_msg.request_id); | 413 | id = GNUNET_ntohll (lres->arm_msg.request_id); |
349 | op = find_op_by_id(h, id); | 414 | op = find_op_by_id (h, id); |
350 | if (NULL == op) | 415 | if (NULL == op) |
351 | { | 416 | { |
352 | LOG(GNUNET_ERROR_TYPE_DEBUG, | 417 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
353 | "Message with unknown id %llu\n", | 418 | "Message with unknown id %llu\n", |
354 | (unsigned long long)id); | 419 | (unsigned long long) id); |
355 | return; | 420 | return; |
356 | } | 421 | } |
357 | size_check = 0; | ||
358 | for (unsigned int i = 0; i < rcount; i++) | ||
359 | { | ||
360 | const char *end = memchr(pos, 0, msize - size_check); | ||
361 | 422 | ||
362 | /* Assert, as this was already checked in #check_arm_list_result() */ | 423 | GNUNET_assert ((rcount * sizeof (struct GNUNET_ARM_ServiceInfoMessage) <= |
363 | GNUNET_assert(NULL != end); | 424 | msize)); |
364 | list[i] = pos; | 425 | |
365 | size_check += (end - pos) + 1; | 426 | ssm = (struct GNUNET_ARM_ServiceInfoMessage *) &lres[1]; |
366 | pos = end + 1; | 427 | pool_start = (char *) (ssm + rcount); |
367 | } | 428 | pool_size = msize - (rcount * sizeof (struct GNUNET_ARM_ServiceInfoMessage)); |
429 | |||
430 | for (unsigned int i = 0; i < rcount; i++) | ||
431 | { | ||
432 | uint16_t name_index = ntohs (ssm->name_index); | ||
433 | uint16_t binary_index = ntohs (ssm->binary_index); | ||
434 | const char *name; | ||
435 | const char *binary; | ||
436 | |||
437 | GNUNET_assert (NULL != (name = pool_get (pool_start, | ||
438 | pool_size, | ||
439 | name_index))); | ||
440 | GNUNET_assert (NULL != (binary = pool_get (pool_start, | ||
441 | pool_size, | ||
442 | binary_index))); | ||
443 | list[i] = (struct GNUNET_ARM_ServiceInfo) { | ||
444 | .name = name, | ||
445 | .binary = binary, | ||
446 | .status = ntohl (ssm->status), | ||
447 | .last_started_at = GNUNET_TIME_absolute_ntoh (ssm->last_started_at), | ||
448 | .restart_at = GNUNET_TIME_absolute_ntoh (ssm->restart_at), | ||
449 | .last_exit_status = ntohs (ssm->last_exit_status), | ||
450 | }; | ||
451 | ssm++; | ||
452 | } | ||
368 | if (NULL != op->list_cont) | 453 | if (NULL != op->list_cont) |
369 | op->list_cont(op->cont_cls, GNUNET_ARM_REQUEST_SENT_OK, rcount, list); | 454 | op->list_cont (op->cont_cls, |
370 | GNUNET_ARM_operation_cancel(op); | 455 | GNUNET_ARM_REQUEST_SENT_OK, |
456 | rcount, | ||
457 | list); | ||
458 | GNUNET_ARM_operation_cancel (op); | ||
371 | } | 459 | } |
372 | 460 | ||
373 | 461 | ||
@@ -378,18 +466,20 @@ handle_arm_list_result(void *cls, | |||
378 | * @param msg message received | 466 | * @param msg message received |
379 | */ | 467 | */ |
380 | static void | 468 | static void |
381 | handle_confirm(void *cls, const struct GNUNET_MessageHeader *msg) | 469 | handle_confirm (void *cls, |
470 | const struct GNUNET_MessageHeader *msg) | ||
382 | { | 471 | { |
383 | struct GNUNET_ARM_Handle *h = cls; | 472 | struct GNUNET_ARM_Handle *h = cls; |
384 | 473 | ||
385 | (void)msg; | 474 | (void) msg; |
386 | LOG(GNUNET_ERROR_TYPE_DEBUG, "Got confirmation from ARM that we are up!\n"); | 475 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
476 | "Got confirmation from ARM that we are up!\n"); | ||
387 | if (GNUNET_NO == h->currently_up) | 477 | if (GNUNET_NO == h->currently_up) |
388 | { | 478 | { |
389 | h->currently_up = GNUNET_YES; | 479 | h->currently_up = GNUNET_YES; |
390 | if (NULL != h->conn_status) | 480 | if (NULL != h->conn_status) |
391 | h->conn_status(h->conn_status_cls, GNUNET_YES); | 481 | h->conn_status (h->conn_status_cls, GNUNET_YES); |
392 | } | 482 | } |
393 | } | 483 | } |
394 | 484 | ||
395 | 485 | ||
@@ -402,22 +492,23 @@ handle_confirm(void *cls, const struct GNUNET_MessageHeader *msg) | |||
402 | * @param error error code | 492 | * @param error error code |
403 | */ | 493 | */ |
404 | static void | 494 | static void |
405 | mq_error_handler(void *cls, enum GNUNET_MQ_Error error) | 495 | mq_error_handler (void *cls, |
496 | enum GNUNET_MQ_Error error) | ||
406 | { | 497 | { |
407 | struct GNUNET_ARM_Handle *h = cls; | 498 | struct GNUNET_ARM_Handle *h = cls; |
408 | struct GNUNET_ARM_Operation *op; | 499 | struct GNUNET_ARM_Operation *op; |
409 | 500 | ||
410 | (void)error; | 501 | (void) error; |
411 | h->currently_up = GNUNET_NO; | 502 | h->currently_up = GNUNET_NO; |
412 | if (NULL != (op = h->thm)) | 503 | if (NULL != (op = h->thm)) |
413 | { | 504 | { |
414 | h->thm = NULL; | 505 | h->thm = NULL; |
415 | op->result_cont(op->cont_cls, | 506 | op->result_cont (op->cont_cls, |
416 | GNUNET_ARM_REQUEST_SENT_OK, | 507 | GNUNET_ARM_REQUEST_SENT_OK, |
417 | GNUNET_ARM_RESULT_STOPPED); | 508 | GNUNET_ARM_RESULT_STOPPED); |
418 | GNUNET_free(op); | 509 | GNUNET_free (op); |
419 | } | 510 | } |
420 | reconnect_arm_later(h); | 511 | reconnect_arm_later (h); |
421 | } | 512 | } |
422 | 513 | ||
423 | 514 | ||
@@ -428,39 +519,48 @@ mq_error_handler(void *cls, enum GNUNET_MQ_Error error) | |||
428 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure | 519 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure |
429 | */ | 520 | */ |
430 | static int | 521 | static int |
431 | reconnect_arm(struct GNUNET_ARM_Handle *h) | 522 | reconnect_arm (struct GNUNET_ARM_Handle *h) |
432 | { | 523 | { |
433 | struct GNUNET_MQ_MessageHandler handlers[] = | 524 | struct GNUNET_MQ_MessageHandler handlers[] = { |
434 | { GNUNET_MQ_hd_fixed_size(arm_result, | 525 | GNUNET_MQ_hd_fixed_size (arm_result, |
435 | GNUNET_MESSAGE_TYPE_ARM_RESULT, | 526 | GNUNET_MESSAGE_TYPE_ARM_RESULT, |
436 | struct GNUNET_ARM_ResultMessage, | 527 | struct GNUNET_ARM_ResultMessage, |
437 | h), | 528 | h), |
438 | GNUNET_MQ_hd_var_size(arm_list_result, | 529 | GNUNET_MQ_hd_var_size (arm_list_result, |
439 | GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT, | 530 | GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT, |
440 | struct GNUNET_ARM_ListResultMessage, | 531 | struct GNUNET_ARM_ListResultMessage, |
441 | h), | 532 | h), |
442 | GNUNET_MQ_hd_fixed_size(confirm, | 533 | GNUNET_MQ_hd_fixed_size (confirm, |
443 | GNUNET_MESSAGE_TYPE_ARM_TEST, | 534 | GNUNET_MESSAGE_TYPE_ARM_TEST, |
444 | struct GNUNET_MessageHeader, | 535 | struct GNUNET_MessageHeader, |
445 | h), | 536 | h), |
446 | GNUNET_MQ_handler_end() }; | 537 | GNUNET_MQ_handler_end () |
538 | }; | ||
447 | struct GNUNET_MessageHeader *test; | 539 | struct GNUNET_MessageHeader *test; |
448 | struct GNUNET_MQ_Envelope *env; | 540 | struct GNUNET_MQ_Envelope *env; |
449 | 541 | ||
450 | if (NULL != h->mq) | 542 | if (NULL != h->mq) |
451 | return GNUNET_OK; | 543 | return GNUNET_OK; |
452 | GNUNET_assert(GNUNET_NO == h->currently_up); | 544 | GNUNET_assert (GNUNET_NO == h->currently_up); |
453 | h->mq = GNUNET_CLIENT_connect(h->cfg, "arm", handlers, &mq_error_handler, h); | 545 | h->mq = GNUNET_CLIENT_connect (h->cfg, |
546 | "arm", | ||
547 | handlers, | ||
548 | &mq_error_handler, | ||
549 | h); | ||
454 | if (NULL == h->mq) | 550 | if (NULL == h->mq) |
455 | { | 551 | { |
456 | LOG(GNUNET_ERROR_TYPE_DEBUG, "GNUNET_CLIENT_connect returned NULL\n"); | 552 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
457 | if (NULL != h->conn_status) | 553 | "GNUNET_CLIENT_connect returned NULL\n"); |
458 | h->conn_status(h->conn_status_cls, GNUNET_SYSERR); | 554 | if (NULL != h->conn_status) |
459 | return GNUNET_SYSERR; | 555 | h->conn_status (h->conn_status_cls, |
460 | } | 556 | GNUNET_SYSERR); |
461 | LOG(GNUNET_ERROR_TYPE_DEBUG, "Sending TEST message to ARM\n"); | 557 | return GNUNET_SYSERR; |
462 | env = GNUNET_MQ_msg(test, GNUNET_MESSAGE_TYPE_ARM_TEST); | 558 | } |
463 | GNUNET_MQ_send(h->mq, env); | 559 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
560 | "Sending TEST message to ARM\n"); | ||
561 | env = GNUNET_MQ_msg (test, | ||
562 | GNUNET_MESSAGE_TYPE_ARM_TEST); | ||
563 | GNUNET_MQ_send (h->mq, env); | ||
464 | return GNUNET_OK; | 564 | return GNUNET_OK; |
465 | } | 565 | } |
466 | 566 | ||
@@ -477,21 +577,21 @@ reconnect_arm(struct GNUNET_ARM_Handle *h) | |||
477 | * @return context to use for further ARM operations, NULL on error. | 577 | * @return context to use for further ARM operations, NULL on error. |
478 | */ | 578 | */ |
479 | struct GNUNET_ARM_Handle * | 579 | struct GNUNET_ARM_Handle * |
480 | GNUNET_ARM_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, | 580 | GNUNET_ARM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, |
481 | GNUNET_ARM_ConnectionStatusCallback conn_status, | 581 | GNUNET_ARM_ConnectionStatusCallback conn_status, |
482 | void *conn_status_cls) | 582 | void *conn_status_cls) |
483 | { | 583 | { |
484 | struct GNUNET_ARM_Handle *h; | 584 | struct GNUNET_ARM_Handle *h; |
485 | 585 | ||
486 | h = GNUNET_new(struct GNUNET_ARM_Handle); | 586 | h = GNUNET_new (struct GNUNET_ARM_Handle); |
487 | h->cfg = cfg; | 587 | h->cfg = cfg; |
488 | h->conn_status = conn_status; | 588 | h->conn_status = conn_status; |
489 | h->conn_status_cls = conn_status_cls; | 589 | h->conn_status_cls = conn_status_cls; |
490 | if (GNUNET_OK != reconnect_arm(h)) | 590 | if (GNUNET_OK != reconnect_arm (h)) |
491 | { | 591 | { |
492 | GNUNET_free(h); | 592 | GNUNET_free (h); |
493 | return NULL; | 593 | return NULL; |
494 | } | 594 | } |
495 | return h; | 595 | return h; |
496 | } | 596 | } |
497 | 597 | ||
@@ -502,38 +602,43 @@ GNUNET_ARM_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
502 | * @param h the handle that was being used | 602 | * @param h the handle that was being used |
503 | */ | 603 | */ |
504 | void | 604 | void |
505 | GNUNET_ARM_disconnect(struct GNUNET_ARM_Handle *h) | 605 | GNUNET_ARM_disconnect (struct GNUNET_ARM_Handle *h) |
506 | { | 606 | { |
507 | struct GNUNET_ARM_Operation *op; | 607 | struct GNUNET_ARM_Operation *op; |
508 | 608 | ||
509 | LOG(GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from ARM service\n"); | 609 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from ARM service\n"); |
510 | while (NULL != (op = h->operation_pending_head)) | 610 | while (NULL != (op = h->operation_pending_head)) |
611 | { | ||
612 | GNUNET_CONTAINER_DLL_remove (h->operation_pending_head, | ||
613 | h->operation_pending_tail, | ||
614 | op); | ||
615 | if (NULL != op->result_cont) | ||
616 | op->result_cont (op->cont_cls, | ||
617 | GNUNET_ARM_REQUEST_DISCONNECTED, | ||
618 | 0); | ||
619 | if (NULL != op->list_cont) | ||
620 | op->list_cont (op->cont_cls, | ||
621 | GNUNET_ARM_REQUEST_DISCONNECTED, | ||
622 | 0, | ||
623 | NULL); | ||
624 | if (NULL != op->async) | ||
511 | { | 625 | { |
512 | GNUNET_CONTAINER_DLL_remove(h->operation_pending_head, | 626 | GNUNET_SCHEDULER_cancel (op->async); |
513 | h->operation_pending_tail, | 627 | op->async = NULL; |
514 | op); | ||
515 | if (NULL != op->result_cont) | ||
516 | op->result_cont(op->cont_cls, GNUNET_ARM_REQUEST_DISCONNECTED, 0); | ||
517 | if (NULL != op->list_cont) | ||
518 | op->list_cont(op->cont_cls, GNUNET_ARM_REQUEST_DISCONNECTED, 0, NULL); | ||
519 | if (NULL != op->async) | ||
520 | { | ||
521 | GNUNET_SCHEDULER_cancel(op->async); | ||
522 | op->async = NULL; | ||
523 | } | ||
524 | GNUNET_free(op); | ||
525 | } | 628 | } |
629 | GNUNET_free (op); | ||
630 | } | ||
526 | if (NULL != h->mq) | 631 | if (NULL != h->mq) |
527 | { | 632 | { |
528 | GNUNET_MQ_destroy(h->mq); | 633 | GNUNET_MQ_destroy (h->mq); |
529 | h->mq = NULL; | 634 | h->mq = NULL; |
530 | } | 635 | } |
531 | if (NULL != h->reconnect_task) | 636 | if (NULL != h->reconnect_task) |
532 | { | 637 | { |
533 | GNUNET_SCHEDULER_cancel(h->reconnect_task); | 638 | GNUNET_SCHEDULER_cancel (h->reconnect_task); |
534 | h->reconnect_task = NULL; | 639 | h->reconnect_task = NULL; |
535 | } | 640 | } |
536 | GNUNET_free(h); | 641 | GNUNET_free (h); |
537 | } | 642 | } |
538 | 643 | ||
539 | 644 | ||
@@ -543,11 +648,13 @@ GNUNET_ARM_disconnect(struct GNUNET_ARM_Handle *h) | |||
543 | * | 648 | * |
544 | * @param h the handle with configuration details | 649 | * @param h the handle with configuration details |
545 | * @param std_inheritance inheritance of std streams | 650 | * @param std_inheritance inheritance of std streams |
651 | * @param sigfd socket to pass to ARM for signalling | ||
546 | * @return operation status code | 652 | * @return operation status code |
547 | */ | 653 | */ |
548 | static enum GNUNET_ARM_Result | 654 | static enum GNUNET_ARM_Result |
549 | start_arm_service(struct GNUNET_ARM_Handle *h, | 655 | start_arm_service (struct GNUNET_ARM_Handle *h, |
550 | enum GNUNET_OS_InheritStdioFlags std_inheritance) | 656 | enum GNUNET_OS_InheritStdioFlags std_inheritance, |
657 | struct GNUNET_DISK_FileHandle *sigfd) | ||
551 | { | 658 | { |
552 | struct GNUNET_OS_Process *proc; | 659 | struct GNUNET_OS_Process *proc; |
553 | char *cbinary; | 660 | char *cbinary; |
@@ -556,99 +663,124 @@ start_arm_service(struct GNUNET_ARM_Handle *h, | |||
556 | char *config; | 663 | char *config; |
557 | char *loprefix; | 664 | char *loprefix; |
558 | char *lopostfix; | 665 | char *lopostfix; |
666 | SOCKTYPE ld[2]; | ||
667 | SOCKTYPE *lsocks; | ||
559 | 668 | ||
560 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(h->cfg, | 669 | if (NULL == sigfd) |
561 | "arm", | 670 | { |
562 | "PREFIX", | 671 | lsocks = NULL; |
563 | &loprefix)) | 672 | } |
564 | loprefix = GNUNET_strdup(""); | ||
565 | else | 673 | else |
566 | loprefix = GNUNET_CONFIGURATION_expand_dollar(h->cfg, loprefix); | 674 | { |
567 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(h->cfg, | 675 | ld[0] = sigfd->fd; |
568 | "arm", | 676 | ld[1] = -1; |
569 | "OPTIONS", | 677 | lsocks = ld; |
570 | &lopostfix)) | 678 | } |
571 | lopostfix = GNUNET_strdup(""); | 679 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (h->cfg, |
680 | "arm", | ||
681 | "PREFIX", | ||
682 | &loprefix)) | ||
683 | loprefix = GNUNET_strdup (""); | ||
572 | else | 684 | else |
573 | lopostfix = GNUNET_CONFIGURATION_expand_dollar(h->cfg, lopostfix); | 685 | loprefix = GNUNET_CONFIGURATION_expand_dollar (h->cfg, loprefix); |
686 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (h->cfg, | ||
687 | "arm", | ||
688 | "OPTIONS", | ||
689 | &lopostfix)) | ||
690 | lopostfix = GNUNET_strdup (""); | ||
691 | else | ||
692 | lopostfix = GNUNET_CONFIGURATION_expand_dollar (h->cfg, | ||
693 | lopostfix); | ||
574 | if (GNUNET_OK != | 694 | if (GNUNET_OK != |
575 | GNUNET_CONFIGURATION_get_value_string(h->cfg, "arm", "BINARY", &cbinary)) | 695 | GNUNET_CONFIGURATION_get_value_string (h->cfg, |
576 | { | 696 | "arm", |
577 | GNUNET_log_config_missing(GNUNET_ERROR_TYPE_WARNING, "arm", "BINARY"); | 697 | "BINARY", |
578 | GNUNET_free(loprefix); | 698 | &cbinary)) |
579 | GNUNET_free(lopostfix); | 699 | { |
580 | return GNUNET_ARM_RESULT_IS_NOT_KNOWN; | 700 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING, |
581 | } | 701 | "arm", |
582 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename(h->cfg, | 702 | "BINARY"); |
583 | "arm", | 703 | GNUNET_free (loprefix); |
584 | "CONFIG", | 704 | GNUNET_free (lopostfix); |
585 | &config)) | 705 | return GNUNET_ARM_RESULT_IS_NOT_KNOWN; |
706 | } | ||
707 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (h->cfg, | ||
708 | "arm", | ||
709 | "CONFIG", | ||
710 | &config)) | ||
586 | config = NULL; | 711 | config = NULL; |
587 | binary = GNUNET_OS_get_libexec_binary_path(cbinary); | 712 | binary = GNUNET_OS_get_libexec_binary_path (cbinary); |
588 | GNUNET_asprintf("edbinary, "\"%s\"", binary); | 713 | GNUNET_asprintf ("edbinary, |
589 | GNUNET_free(cbinary); | 714 | "\"%s\"", |
590 | if ((GNUNET_YES == | 715 | binary); |
591 | GNUNET_CONFIGURATION_have_value(h->cfg, "TESTING", "WEAKRANDOM")) && | 716 | GNUNET_free (cbinary); |
592 | (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno(h->cfg, | 717 | if ( (GNUNET_YES == |
593 | "TESTING", | 718 | GNUNET_CONFIGURATION_have_value (h->cfg, |
594 | "WEAKRANDOM")) && | 719 | "TESTING", |
595 | (GNUNET_NO == | 720 | "WEAKRANDOM")) && |
596 | GNUNET_CONFIGURATION_have_value(h->cfg, "TESTING", "HOSTFILE"))) | 721 | (GNUNET_YES == |
597 | { | 722 | GNUNET_CONFIGURATION_get_value_yesno (h->cfg, |
598 | /* Means we are ONLY running locally */ | 723 | "TESTING", |
599 | /* we're clearly running a test, don't daemonize */ | 724 | "WEAKRANDOM")) && |
600 | if (NULL == config) | 725 | (GNUNET_NO == |
601 | proc = GNUNET_OS_start_process_s(GNUNET_NO, | 726 | GNUNET_CONFIGURATION_have_value (h->cfg, |
602 | std_inheritance, | 727 | "TESTING", |
603 | NULL, | 728 | "HOSTFILE")) ) |
604 | loprefix, | 729 | { |
605 | quotedbinary, | 730 | /* Means we are ONLY running locally */ |
606 | /* no daemonization! */ | 731 | /* we're clearly running a test, don't daemonize */ |
607 | lopostfix, | 732 | if (NULL == config) |
608 | NULL); | 733 | proc = GNUNET_OS_start_process_s (GNUNET_NO, |
609 | else | 734 | std_inheritance, |
610 | proc = GNUNET_OS_start_process_s(GNUNET_NO, | 735 | lsocks, |
611 | std_inheritance, | 736 | loprefix, |
612 | NULL, | 737 | quotedbinary, |
613 | loprefix, | 738 | /* no daemonization! */ |
614 | quotedbinary, | 739 | lopostfix, |
615 | "-c", | 740 | NULL); |
616 | config, | 741 | else |
617 | /* no daemonization! */ | 742 | proc = GNUNET_OS_start_process_s (GNUNET_NO, |
618 | lopostfix, | 743 | std_inheritance, |
619 | NULL); | 744 | lsocks, |
620 | } | 745 | loprefix, |
746 | quotedbinary, | ||
747 | "-c", | ||
748 | config, | ||
749 | /* no daemonization! */ | ||
750 | lopostfix, | ||
751 | NULL); | ||
752 | } | ||
621 | else | 753 | else |
622 | { | 754 | { |
623 | if (NULL == config) | 755 | if (NULL == config) |
624 | proc = GNUNET_OS_start_process_s(GNUNET_NO, | 756 | proc = GNUNET_OS_start_process_s (GNUNET_NO, |
625 | std_inheritance, | 757 | std_inheritance, |
626 | NULL, | 758 | lsocks, |
627 | loprefix, | 759 | loprefix, |
628 | quotedbinary, | 760 | quotedbinary, |
629 | "-d", /* do daemonize */ | 761 | "-d", /* do daemonize */ |
630 | lopostfix, | 762 | lopostfix, |
631 | NULL); | 763 | NULL); |
632 | else | 764 | else |
633 | proc = GNUNET_OS_start_process_s(GNUNET_NO, | 765 | proc = GNUNET_OS_start_process_s (GNUNET_NO, |
634 | std_inheritance, | 766 | std_inheritance, |
635 | NULL, | 767 | lsocks, |
636 | loprefix, | 768 | loprefix, |
637 | quotedbinary, | 769 | quotedbinary, |
638 | "-c", | 770 | "-c", |
639 | config, | 771 | config, |
640 | "-d", /* do daemonize */ | 772 | "-d", /* do daemonize */ |
641 | lopostfix, | 773 | lopostfix, |
642 | NULL); | 774 | NULL); |
643 | } | 775 | } |
644 | GNUNET_free(binary); | 776 | GNUNET_free (binary); |
645 | GNUNET_free(quotedbinary); | 777 | GNUNET_free (quotedbinary); |
646 | GNUNET_free_non_null(config); | 778 | GNUNET_free_non_null (config); |
647 | GNUNET_free(loprefix); | 779 | GNUNET_free (loprefix); |
648 | GNUNET_free(lopostfix); | 780 | GNUNET_free (lopostfix); |
649 | if (NULL == proc) | 781 | if (NULL == proc) |
650 | return GNUNET_ARM_RESULT_START_FAILED; | 782 | return GNUNET_ARM_RESULT_START_FAILED; |
651 | GNUNET_OS_process_destroy(proc); | 783 | GNUNET_OS_process_destroy (proc); |
652 | return GNUNET_ARM_RESULT_STARTING; | 784 | return GNUNET_ARM_RESULT_STARTING; |
653 | } | 785 | } |
654 | 786 | ||
@@ -660,19 +792,29 @@ start_arm_service(struct GNUNET_ARM_Handle *h, | |||
660 | * @param op operation to cancel | 792 | * @param op operation to cancel |
661 | */ | 793 | */ |
662 | void | 794 | void |
663 | GNUNET_ARM_operation_cancel(struct GNUNET_ARM_Operation *op) | 795 | GNUNET_ARM_operation_cancel (struct GNUNET_ARM_Operation *op) |
664 | { | 796 | { |
665 | struct GNUNET_ARM_Handle *h = op->h; | 797 | struct GNUNET_ARM_Handle *h = op->h; |
666 | 798 | ||
799 | if (NULL != op->async) | ||
800 | { | ||
801 | GNUNET_SCHEDULER_cancel (op->async); | ||
802 | op->async = NULL; | ||
803 | } | ||
804 | if (NULL != op->rfd) | ||
805 | { | ||
806 | GNUNET_DISK_file_close (op->rfd); | ||
807 | op->rfd = NULL; | ||
808 | } | ||
667 | if (h->thm == op) | 809 | if (h->thm == op) |
668 | { | 810 | { |
669 | op->result_cont = NULL; | 811 | op->result_cont = NULL; |
670 | return; | 812 | return; |
671 | } | 813 | } |
672 | GNUNET_CONTAINER_DLL_remove(h->operation_pending_head, | 814 | GNUNET_CONTAINER_DLL_remove (h->operation_pending_head, |
673 | h->operation_pending_tail, | 815 | h->operation_pending_tail, |
674 | op); | 816 | op); |
675 | GNUNET_free(op); | 817 | GNUNET_free (op); |
676 | } | 818 | } |
677 | 819 | ||
678 | 820 | ||
@@ -687,38 +829,38 @@ GNUNET_ARM_operation_cancel(struct GNUNET_ARM_Operation *op) | |||
687 | * @return handle to queue, NULL on error | 829 | * @return handle to queue, NULL on error |
688 | */ | 830 | */ |
689 | static struct GNUNET_ARM_Operation * | 831 | static struct GNUNET_ARM_Operation * |
690 | change_service(struct GNUNET_ARM_Handle *h, | 832 | change_service (struct GNUNET_ARM_Handle *h, |
691 | const char *service_name, | 833 | const char *service_name, |
692 | GNUNET_ARM_ResultCallback cb, | 834 | GNUNET_ARM_ResultCallback cb, |
693 | void *cb_cls, | 835 | void *cb_cls, |
694 | uint16_t type) | 836 | uint16_t type) |
695 | { | 837 | { |
696 | struct GNUNET_ARM_Operation *op; | 838 | struct GNUNET_ARM_Operation *op; |
697 | size_t slen; | 839 | size_t slen; |
698 | struct GNUNET_MQ_Envelope *env; | 840 | struct GNUNET_MQ_Envelope *env; |
699 | struct GNUNET_ARM_Message *msg; | 841 | struct GNUNET_ARM_Message *msg; |
700 | 842 | ||
701 | slen = strlen(service_name) + 1; | 843 | slen = strlen (service_name) + 1; |
702 | if (slen + sizeof(struct GNUNET_ARM_Message) >= GNUNET_MAX_MESSAGE_SIZE) | 844 | if (slen + sizeof(struct GNUNET_ARM_Message) >= GNUNET_MAX_MESSAGE_SIZE) |
703 | { | 845 | { |
704 | GNUNET_break(0); | 846 | GNUNET_break (0); |
705 | return NULL; | 847 | return NULL; |
706 | } | 848 | } |
707 | if (0 == h->request_id_counter) | 849 | if (0 == h->request_id_counter) |
708 | h->request_id_counter++; | 850 | h->request_id_counter++; |
709 | op = GNUNET_new(struct GNUNET_ARM_Operation); | 851 | op = GNUNET_new (struct GNUNET_ARM_Operation); |
710 | op->h = h; | 852 | op->h = h; |
711 | op->result_cont = cb; | 853 | op->result_cont = cb; |
712 | op->cont_cls = cb_cls; | 854 | op->cont_cls = cb_cls; |
713 | op->id = h->request_id_counter++; | 855 | op->id = h->request_id_counter++; |
714 | GNUNET_CONTAINER_DLL_insert_tail(h->operation_pending_head, | 856 | GNUNET_CONTAINER_DLL_insert_tail (h->operation_pending_head, |
715 | h->operation_pending_tail, | 857 | h->operation_pending_tail, |
716 | op); | 858 | op); |
717 | env = GNUNET_MQ_msg_extra(msg, slen, type); | 859 | env = GNUNET_MQ_msg_extra (msg, slen, type); |
718 | msg->reserved = htonl(0); | 860 | msg->reserved = htonl (0); |
719 | msg->request_id = GNUNET_htonll(op->id); | 861 | msg->request_id = GNUNET_htonll (op->id); |
720 | GNUNET_memcpy(&msg[1], service_name, slen); | 862 | GNUNET_memcpy (&msg[1], service_name, slen); |
721 | GNUNET_MQ_send(h->mq, env); | 863 | GNUNET_MQ_send (h->mq, env); |
722 | return op; | 864 | return op; |
723 | } | 865 | } |
724 | 866 | ||
@@ -729,22 +871,24 @@ change_service(struct GNUNET_ARM_Handle *h, | |||
729 | * @param cls the operation that asked ARM to be started | 871 | * @param cls the operation that asked ARM to be started |
730 | */ | 872 | */ |
731 | static void | 873 | static void |
732 | notify_running(void *cls) | 874 | notify_running (void *cls) |
733 | { | 875 | { |
734 | struct GNUNET_ARM_Operation *op = cls; | 876 | struct GNUNET_ARM_Operation *op = cls; |
735 | struct GNUNET_ARM_Handle *h = op->h; | 877 | struct GNUNET_ARM_Handle *h = op->h; |
736 | 878 | ||
737 | op->async = NULL; | 879 | op->async = NULL; |
738 | GNUNET_CONTAINER_DLL_remove(h->operation_pending_head, | 880 | GNUNET_CONTAINER_DLL_remove (h->operation_pending_head, |
739 | h->operation_pending_tail, | 881 | h->operation_pending_tail, |
740 | op); | 882 | op); |
741 | if (NULL != op->result_cont) | 883 | if (NULL != op->result_cont) |
742 | op->result_cont(op->cont_cls, | 884 | op->result_cont (op->cont_cls, |
743 | GNUNET_ARM_REQUEST_SENT_OK, | 885 | GNUNET_ARM_REQUEST_SENT_OK, |
744 | GNUNET_ARM_RESULT_IS_STARTED_ALREADY); | 886 | GNUNET_ARM_RESULT_IS_STARTED_ALREADY); |
745 | if ((GNUNET_YES == h->currently_up) && (NULL != h->conn_status)) | 887 | if ( (GNUNET_YES == h->currently_up) && |
746 | h->conn_status(h->conn_status_cls, GNUNET_YES); | 888 | (NULL != h->conn_status) ) |
747 | GNUNET_free(op); | 889 | h->conn_status (h->conn_status_cls, |
890 | GNUNET_YES); | ||
891 | GNUNET_free (op); | ||
748 | } | 892 | } |
749 | 893 | ||
750 | 894 | ||
@@ -754,22 +898,22 @@ notify_running(void *cls) | |||
754 | * @param cls the operation that asked ARM to be started | 898 | * @param cls the operation that asked ARM to be started |
755 | */ | 899 | */ |
756 | static void | 900 | static void |
757 | notify_starting(void *cls) | 901 | notify_starting (void *cls) |
758 | { | 902 | { |
759 | struct GNUNET_ARM_Operation *op = cls; | 903 | struct GNUNET_ARM_Operation *op = cls; |
760 | struct GNUNET_ARM_Handle *h = op->h; | 904 | struct GNUNET_ARM_Handle *h = op->h; |
761 | 905 | ||
762 | op->async = NULL; | 906 | op->async = NULL; |
763 | LOG(GNUNET_ERROR_TYPE_DEBUG, | 907 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
764 | "Notifying client that we started the ARM service\n"); | 908 | "Notifying client that we started the ARM service\n"); |
765 | GNUNET_CONTAINER_DLL_remove(h->operation_pending_head, | 909 | GNUNET_CONTAINER_DLL_remove (h->operation_pending_head, |
766 | h->operation_pending_tail, | 910 | h->operation_pending_tail, |
767 | op); | 911 | op); |
768 | if (NULL != op->result_cont) | 912 | if (NULL != op->result_cont) |
769 | op->result_cont(op->cont_cls, | 913 | op->result_cont (op->cont_cls, |
770 | GNUNET_ARM_REQUEST_SENT_OK, | 914 | GNUNET_ARM_REQUEST_SENT_OK, |
771 | op->starting_ret); | 915 | op->starting_ret); |
772 | GNUNET_free(op); | 916 | GNUNET_free (op); |
773 | } | 917 | } |
774 | 918 | ||
775 | 919 | ||
@@ -784,23 +928,28 @@ notify_starting(void *cls) | |||
784 | * @return handle for the operation, NULL on error | 928 | * @return handle for the operation, NULL on error |
785 | */ | 929 | */ |
786 | struct GNUNET_ARM_Operation * | 930 | struct GNUNET_ARM_Operation * |
787 | GNUNET_ARM_request_service_start( | 931 | GNUNET_ARM_request_service_start (struct GNUNET_ARM_Handle *h, |
788 | struct GNUNET_ARM_Handle *h, | 932 | const char *service_name, |
789 | const char *service_name, | 933 | enum GNUNET_OS_InheritStdioFlags |
790 | enum GNUNET_OS_InheritStdioFlags std_inheritance, | 934 | std_inheritance, |
791 | GNUNET_ARM_ResultCallback cont, | 935 | GNUNET_ARM_ResultCallback cont, |
792 | void *cont_cls) | 936 | void *cont_cls) |
793 | { | 937 | { |
794 | struct GNUNET_ARM_Operation *op; | 938 | struct GNUNET_ARM_Operation *op; |
795 | enum GNUNET_ARM_Result ret; | 939 | enum GNUNET_ARM_Result ret; |
796 | 940 | struct GNUNET_DISK_PipeHandle *sig; | |
797 | LOG(GNUNET_ERROR_TYPE_DEBUG, "Starting service `%s'\n", service_name); | 941 | struct GNUNET_DISK_FileHandle *wsig; |
798 | if (0 != strcasecmp("arm", service_name)) | 942 | |
799 | return change_service(h, | 943 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
800 | service_name, | 944 | "Starting service `%s'\n", |
801 | cont, | 945 | service_name); |
802 | cont_cls, | 946 | if (0 != strcasecmp ("arm", |
803 | GNUNET_MESSAGE_TYPE_ARM_START); | 947 | service_name)) |
948 | return change_service (h, | ||
949 | service_name, | ||
950 | cont, | ||
951 | cont_cls, | ||
952 | GNUNET_MESSAGE_TYPE_ARM_START); | ||
804 | 953 | ||
805 | /* Possible cases: | 954 | /* Possible cases: |
806 | * 1) We're connected to ARM already. Invoke the callback immediately. | 955 | * 1) We're connected to ARM already. Invoke the callback immediately. |
@@ -809,37 +958,68 @@ GNUNET_ARM_request_service_start( | |||
809 | * a service test. | 958 | * a service test. |
810 | */ | 959 | */ |
811 | if (GNUNET_YES == h->currently_up) | 960 | if (GNUNET_YES == h->currently_up) |
812 | { | 961 | { |
813 | LOG(GNUNET_ERROR_TYPE_DEBUG, "ARM is already running\n"); | 962 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
814 | op = GNUNET_new(struct GNUNET_ARM_Operation); | 963 | "ARM is already running\n"); |
815 | op->h = h; | 964 | op = GNUNET_new (struct GNUNET_ARM_Operation); |
816 | op->result_cont = cont; | 965 | op->h = h; |
817 | op->cont_cls = cont_cls; | 966 | op->result_cont = cont; |
818 | GNUNET_CONTAINER_DLL_insert_tail(h->operation_pending_head, | 967 | op->cont_cls = cont_cls; |
819 | h->operation_pending_tail, | 968 | GNUNET_CONTAINER_DLL_insert_tail (h->operation_pending_head, |
820 | op); | 969 | h->operation_pending_tail, |
821 | op->async = GNUNET_SCHEDULER_add_now(¬ify_running, op); | 970 | op); |
822 | return op; | 971 | op->async = GNUNET_SCHEDULER_add_now (¬ify_running, op); |
823 | } | 972 | return op; |
973 | } | ||
824 | /* This is an inherently uncertain choice, as it is of course | 974 | /* This is an inherently uncertain choice, as it is of course |
825 | theoretically possible that ARM is up and we just did not | 975 | theoretically possible that ARM is up and we just did not |
826 | yet complete the MQ handshake. However, given that users | 976 | yet complete the MQ handshake. However, given that users |
827 | are unlikely to hammer 'gnunet-arm -s' on a busy system, | 977 | are unlikely to hammer 'gnunet-arm -s' on a busy system, |
828 | the above check should catch 99.99% of the cases where ARM | 978 | the above check should catch 99.99% of the cases where ARM |
829 | is already running. */ | 979 | is already running. */ |
830 | LOG(GNUNET_ERROR_TYPE_DEBUG, "Starting ARM service\n"); | 980 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
831 | ret = start_arm_service(h, std_inheritance); | 981 | "Starting ARM service\n"); |
982 | if (NULL == (sig = GNUNET_DISK_pipe (GNUNET_NO, | ||
983 | GNUNET_NO, | ||
984 | GNUNET_NO, | ||
985 | GNUNET_YES))) | ||
986 | { | ||
987 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, | ||
988 | "pipe"); | ||
989 | } | ||
990 | wsig = GNUNET_DISK_pipe_detach_end (sig, | ||
991 | GNUNET_DISK_PIPE_END_WRITE); | ||
992 | ret = start_arm_service (h, | ||
993 | std_inheritance, | ||
994 | wsig); | ||
995 | GNUNET_DISK_file_close (wsig); | ||
832 | if (GNUNET_ARM_RESULT_STARTING == ret) | 996 | if (GNUNET_ARM_RESULT_STARTING == ret) |
833 | reconnect_arm(h); | 997 | reconnect_arm (h); |
834 | op = GNUNET_new(struct GNUNET_ARM_Operation); | 998 | op = GNUNET_new (struct GNUNET_ARM_Operation); |
835 | op->h = h; | 999 | op->h = h; |
836 | op->result_cont = cont; | 1000 | op->result_cont = cont; |
837 | op->cont_cls = cont_cls; | 1001 | op->cont_cls = cont_cls; |
838 | GNUNET_CONTAINER_DLL_insert_tail(h->operation_pending_head, | 1002 | GNUNET_CONTAINER_DLL_insert_tail (h->operation_pending_head, |
839 | h->operation_pending_tail, | 1003 | h->operation_pending_tail, |
840 | op); | 1004 | op); |
841 | op->starting_ret = ret; | 1005 | op->starting_ret = ret; |
842 | op->async = GNUNET_SCHEDULER_add_now(¬ify_starting, op); | 1006 | if (NULL != sig) |
1007 | { | ||
1008 | op->rfd = GNUNET_DISK_pipe_detach_end (sig, | ||
1009 | GNUNET_DISK_PIPE_END_READ); | ||
1010 | /* Wait at most a minute for gnunet-service-arm to be up, as beyond | ||
1011 | that something clearly just went wrong */ | ||
1012 | op->async = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_MINUTES, | ||
1013 | op->rfd, | ||
1014 | ¬ify_starting, | ||
1015 | op); | ||
1016 | } | ||
1017 | else | ||
1018 | { | ||
1019 | op->async = GNUNET_SCHEDULER_add_now (¬ify_starting, | ||
1020 | op); | ||
1021 | } | ||
1022 | GNUNET_DISK_pipe_close (sig); | ||
843 | return op; | 1023 | return op; |
844 | } | 1024 | } |
845 | 1025 | ||
@@ -859,24 +1039,27 @@ GNUNET_ARM_request_service_start( | |||
859 | * @return handle for the operation, NULL on error | 1039 | * @return handle for the operation, NULL on error |
860 | */ | 1040 | */ |
861 | struct GNUNET_ARM_Operation * | 1041 | struct GNUNET_ARM_Operation * |
862 | GNUNET_ARM_request_service_stop(struct GNUNET_ARM_Handle *h, | 1042 | GNUNET_ARM_request_service_stop (struct GNUNET_ARM_Handle *h, |
863 | const char *service_name, | 1043 | const char *service_name, |
864 | GNUNET_ARM_ResultCallback cont, | 1044 | GNUNET_ARM_ResultCallback cont, |
865 | void *cont_cls) | 1045 | void *cont_cls) |
866 | { | 1046 | { |
867 | struct GNUNET_ARM_Operation *op; | 1047 | struct GNUNET_ARM_Operation *op; |
868 | 1048 | ||
869 | LOG(GNUNET_ERROR_TYPE_DEBUG, "Stopping service `%s'\n", service_name); | 1049 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
870 | op = change_service(h, | 1050 | "Stopping service `%s'\n", |
871 | service_name, | 1051 | service_name); |
872 | cont, | 1052 | op = change_service (h, |
873 | cont_cls, | 1053 | service_name, |
874 | GNUNET_MESSAGE_TYPE_ARM_STOP); | 1054 | cont, |
1055 | cont_cls, | ||
1056 | GNUNET_MESSAGE_TYPE_ARM_STOP); | ||
875 | if (NULL == op) | 1057 | if (NULL == op) |
876 | return NULL; | 1058 | return NULL; |
877 | /* If the service is ARM, set a flag as we will use MQ errors | 1059 | /* If the service is ARM, set a flag as we will use MQ errors |
878 | to detect that the process is really gone. */ | 1060 | to detect that the process is really gone. */ |
879 | if (0 == strcasecmp(service_name, "arm")) | 1061 | if (0 == strcasecmp (service_name, |
1062 | "arm")) | ||
880 | op->is_arm_stop = GNUNET_YES; | 1063 | op->is_arm_stop = GNUNET_YES; |
881 | return op; | 1064 | return op; |
882 | } | 1065 | } |
@@ -891,29 +1074,31 @@ GNUNET_ARM_request_service_stop(struct GNUNET_ARM_Handle *h, | |||
891 | * @return handle for the operation, NULL on error | 1074 | * @return handle for the operation, NULL on error |
892 | */ | 1075 | */ |
893 | struct GNUNET_ARM_Operation * | 1076 | struct GNUNET_ARM_Operation * |
894 | GNUNET_ARM_request_service_list(struct GNUNET_ARM_Handle *h, | 1077 | GNUNET_ARM_request_service_list (struct GNUNET_ARM_Handle *h, |
895 | GNUNET_ARM_ServiceListCallback cont, | 1078 | GNUNET_ARM_ServiceListCallback cont, |
896 | void *cont_cls) | 1079 | void *cont_cls) |
897 | { | 1080 | { |
898 | struct GNUNET_ARM_Operation *op; | 1081 | struct GNUNET_ARM_Operation *op; |
899 | struct GNUNET_MQ_Envelope *env; | 1082 | struct GNUNET_MQ_Envelope *env; |
900 | struct GNUNET_ARM_Message *msg; | 1083 | struct GNUNET_ARM_Message *msg; |
901 | 1084 | ||
902 | LOG(GNUNET_ERROR_TYPE_DEBUG, "Requesting LIST from ARM service\n"); | 1085 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1086 | "Requesting LIST from ARM service\n"); | ||
903 | if (0 == h->request_id_counter) | 1087 | if (0 == h->request_id_counter) |
904 | h->request_id_counter++; | 1088 | h->request_id_counter++; |
905 | op = GNUNET_new(struct GNUNET_ARM_Operation); | 1089 | op = GNUNET_new (struct GNUNET_ARM_Operation); |
906 | op->h = h; | 1090 | op->h = h; |
907 | op->list_cont = cont; | 1091 | op->list_cont = cont; |
908 | op->cont_cls = cont_cls; | 1092 | op->cont_cls = cont_cls; |
909 | op->id = h->request_id_counter++; | 1093 | op->id = h->request_id_counter++; |
910 | GNUNET_CONTAINER_DLL_insert_tail(h->operation_pending_head, | 1094 | GNUNET_CONTAINER_DLL_insert_tail (h->operation_pending_head, |
911 | h->operation_pending_tail, | 1095 | h->operation_pending_tail, |
912 | op); | 1096 | op); |
913 | env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_ARM_LIST); | 1097 | env = GNUNET_MQ_msg (msg, |
914 | msg->reserved = htonl(0); | 1098 | GNUNET_MESSAGE_TYPE_ARM_LIST); |
915 | msg->request_id = GNUNET_htonll(op->id); | 1099 | msg->reserved = htonl (0); |
916 | GNUNET_MQ_send(h->mq, env); | 1100 | msg->request_id = GNUNET_htonll (op->id); |
1101 | GNUNET_MQ_send (h->mq, env); | ||
917 | return op; | 1102 | return op; |
918 | } | 1103 | } |
919 | 1104 | ||