aboutsummaryrefslogtreecommitdiff
path: root/src/arm/arm_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/arm/arm_api.c')
-rw-r--r--src/arm/arm_api.c933
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 */
40struct GNUNET_ARM_Operation { 40struct 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 */
96struct GNUNET_ARM_Handle { 102struct 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 */
166static int 173static int
167reconnect_arm(struct GNUNET_ARM_Handle *h); 174reconnect_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 */
175static void 182static void
176reconnect_arm_task(void *cls) 183reconnect_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 */
191static void 198static void
192reconnect_arm_later(struct GNUNET_ARM_Handle *h) 199reconnect_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 */
227static struct GNUNET_ARM_Operation * 242static struct GNUNET_ARM_Operation *
228find_op_by_id(struct GNUNET_ARM_Handle *h, uint64_t id) 243find_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 */
246static void 261static void
247handle_arm_result(void *cls, const struct GNUNET_ARM_ResultMessage *res) 262handle_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 */
325static const char *
326pool_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 */
303static int 350static int
304check_arm_list_result(void *cls, 351check_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 */
335static void 399static void
336handle_arm_list_result(void *cls, 400handle_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 */
380static void 468static void
381handle_confirm(void *cls, const struct GNUNET_MessageHeader *msg) 469handle_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 */
404static void 494static void
405mq_error_handler(void *cls, enum GNUNET_MQ_Error error) 495mq_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 */
430static int 521static int
431reconnect_arm(struct GNUNET_ARM_Handle *h) 522reconnect_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 */
479struct GNUNET_ARM_Handle * 579struct GNUNET_ARM_Handle *
480GNUNET_ARM_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, 580GNUNET_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 */
504void 604void
505GNUNET_ARM_disconnect(struct GNUNET_ARM_Handle *h) 605GNUNET_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 */
548static enum GNUNET_ARM_Result 654static enum GNUNET_ARM_Result
549start_arm_service(struct GNUNET_ARM_Handle *h, 655start_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(&quotedbinary, "\"%s\"", binary); 713 GNUNET_asprintf (&quotedbinary,
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 */
662void 794void
663GNUNET_ARM_operation_cancel(struct GNUNET_ARM_Operation *op) 795GNUNET_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 */
689static struct GNUNET_ARM_Operation * 831static struct GNUNET_ARM_Operation *
690change_service(struct GNUNET_ARM_Handle *h, 832change_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 */
731static void 873static void
732notify_running(void *cls) 874notify_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 */
756static void 900static void
757notify_starting(void *cls) 901notify_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 */
786struct GNUNET_ARM_Operation * 930struct GNUNET_ARM_Operation *
787GNUNET_ARM_request_service_start( 931GNUNET_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(&notify_running, op); 970 op);
822 return op; 971 op->async = GNUNET_SCHEDULER_add_now (&notify_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(&notify_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 &notify_starting,
1015 op);
1016 }
1017 else
1018 {
1019 op->async = GNUNET_SCHEDULER_add_now (&notify_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 */
861struct GNUNET_ARM_Operation * 1041struct GNUNET_ARM_Operation *
862GNUNET_ARM_request_service_stop(struct GNUNET_ARM_Handle *h, 1042GNUNET_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 */
893struct GNUNET_ARM_Operation * 1076struct GNUNET_ARM_Operation *
894GNUNET_ARM_request_service_list(struct GNUNET_ARM_Handle *h, 1077GNUNET_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