aboutsummaryrefslogtreecommitdiff
path: root/src/arm
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-06-23 14:22:34 +0000
committerChristian Grothoff <christian@grothoff.org>2016-06-23 14:22:34 +0000
commit5742938289524f4c5fba7883742e4dd69cccf11d (patch)
treee16fea8b9d778f9825f897237b0c1880305776a0 /src/arm
parentf3edb5a8d6ba6f43f5df18f2e98bc1dae90c9d7a (diff)
downloadgnunet-5742938289524f4c5fba7883742e4dd69cccf11d.tar.gz
gnunet-5742938289524f4c5fba7883742e4dd69cccf11d.zip
refactoring ARM api to use new MQ
Diffstat (limited to 'src/arm')
-rw-r--r--src/arm/arm_api.c1219
-rw-r--r--src/arm/arm_monitor_api.c13
-rw-r--r--src/arm/gnunet-arm.c159
-rw-r--r--src/arm/test_arm_api.c109
-rw-r--r--src/arm/test_exponential_backoff.c70
-rw-r--r--src/arm/test_gnunet_service_arm.c36
6 files changed, 734 insertions, 872 deletions
diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c
index a89d423ec..ed36c61cd 100644
--- a/src/arm/arm_api.c
+++ b/src/arm/arm_api.c
@@ -32,151 +32,131 @@
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 * Handle for interacting with ARM. 37 * Entry in a doubly-linked list of operations awaiting for replies
38 * (in-order) from the ARM service.
37 */ 39 */
38struct GNUNET_ARM_Handle 40struct GNUNET_ARM_Operation
39{ 41{
40 /** 42 /**
41 * Our control connection to the ARM service. 43 * This is a doubly-linked list.
42 */
43 struct GNUNET_CLIENT_Connection *client;
44
45 /**
46 * The configuration that we are using.
47 */
48 struct GNUNET_CONFIGURATION_Handle *cfg;
49
50 /**
51 * Handle for our current transmission request.
52 */
53 struct GNUNET_CLIENT_TransmitHandle *cth;
54
55 /**
56 * Head of doubly-linked list of pending requests.
57 */
58 struct ARMControlMessage *control_pending_head;
59
60 /**
61 * Tail of doubly-linked list of pending requests.
62 */
63 struct ARMControlMessage *control_pending_tail;
64
65 /**
66 * Head of doubly-linked list of sent requests.
67 */ 44 */
68 struct ARMControlMessage *control_sent_head; 45 struct GNUNET_ARM_Operation *next;
69 46
70 /** 47 /**
71 * Tail of doubly-linked list of sent requests. 48 * This is a doubly-linked list.
72 */ 49 */
73 struct ARMControlMessage *control_sent_tail; 50 struct GNUNET_ARM_Operation *prev;
74 51
75 /** 52 /**
76 * Callback to invoke on connection/disconnection. 53 * ARM handle.
77 */ 54 */
78 GNUNET_ARM_ConnectionStatusCallback conn_status; 55 struct GNUNET_ARM_Handle *h;
79 56
80 /** 57 /**
81 * Closure for conn_status. 58 * Callback for service state change requests.
82 */ 59 */
83 void *conn_status_cls; 60 GNUNET_ARM_ResultCallback result_cont;
84 61
85 /** 62 /**
86 * ARM control message for the 'arm_termination_handler' 63 * Callback for service list requests.
87 * with the continuation to call once the ARM shutdown is done.
88 */ 64 */
89 struct ARMControlMessage *thm; 65 GNUNET_ARM_ServiceListCallback list_cont;
90 66
91 /** 67 /**
92 * ID of the reconnect task (if any). 68 * Closure for @e result_cont or @e list_cont.
93 */ 69 */
94 struct GNUNET_SCHEDULER_Task *reconnect_task; 70 void *cont_cls;
95 71
96 /** 72 /**
97 * Current delay we use for re-trying to connect to core. 73 * Task for async completion.
98 */ 74 */
99 struct GNUNET_TIME_Relative retry_backoff; 75 struct GNUNET_SCHEDULER_Task *async;
100 76
101 /** 77 /**
102 * Counter for request identifiers 78 * Unique ID for the request.
103 */ 79 */
104 uint64_t request_id_counter; 80 uint64_t id;
105 81
106 /** 82 /**
107 * Are we currently disconnected and hence unable to send? 83 * Result of this operation for #notify_starting().
108 */ 84 */
109 unsigned char currently_down; 85 enum GNUNET_ARM_Result starting_ret;
110 86
111 /** 87 /**
112 * #GNUNET_YES if we're running a service test. 88 * Is this an operation to stop the ARM service?
113 */ 89 */
114 unsigned char service_test_is_active; 90 int is_arm_stop;
115}; 91};
116 92
117 93
118/** 94/**
119 * Entry in a doubly-linked list of control messages to be transmitted 95 * Handle for interacting with ARM.
120 * to the arm service.
121 *
122 * The actual message is allocated at the end of this struct.
123 */ 96 */
124struct ARMControlMessage 97struct GNUNET_ARM_Handle
125{ 98{
126 /** 99 /**
127 * This is a doubly-linked list. 100 * Our connection to the ARM service.
128 */ 101 */
129 struct ARMControlMessage *next; 102 struct GNUNET_MQ_Handle *mq;
130 103
131 /** 104 /**
132 * This is a doubly-linked list. 105 * The configuration that we are using.
133 */ 106 */
134 struct ARMControlMessage *prev; 107 const struct GNUNET_CONFIGURATION_Handle *cfg;
135 108
136 /** 109 /**
137 * ARM handle. 110 * Head of doubly-linked list of pending operations.
138 */ 111 */
139 struct GNUNET_ARM_Handle *h; 112 struct GNUNET_ARM_Operation *operation_pending_head;
140 113
141 /** 114 /**
142 * Message to send. 115 * Tail of doubly-linked list of pending operations.
143 */ 116 */
144 struct GNUNET_ARM_Message *msg; 117 struct GNUNET_ARM_Operation *operation_pending_tail;
145 118
146 /** 119 /**
147 * Callback for service state change requests. 120 * Callback to invoke on connection/disconnection.
148 */ 121 */
149 GNUNET_ARM_ResultCallback result_cont; 122 GNUNET_ARM_ConnectionStatusCallback conn_status;
150 123
151 /** 124 /**
152 * Callback for service list requests. 125 * Closure for @e conn_status.
153 */ 126 */
154 GNUNET_ARM_ServiceListCallback list_cont; 127 void *conn_status_cls;
155 128
156 /** 129 /**
157 * Closure for @e result_cont or @e list_cont. 130 * ARM operation where the goal is to wait for ARM shutdown to
131 * complete. This operation is special in that it waits for an
132 * error on the @e mq. So we complete it by calling the
133 * continuation in the #mq_error_handler(). Note that the operation
134 * is no longer in the @e operation_pending_head DLL once it is
135 * referenced from this field.
158 */ 136 */
159 void *cont_cls; 137 struct GNUNET_ARM_Operation *thm;
160 138
161 /** 139 /**
162 * Timeout for the operation. 140 * ID of the reconnect task (if any).
163 */ 141 */
164 struct GNUNET_TIME_Absolute timeout; 142 struct GNUNET_SCHEDULER_Task *reconnect_task;
165 143
166 /** 144 /**
167 * Task to run when request times out. 145 * Current delay we use for re-trying to connect to core.
168 */ 146 */
169 struct GNUNET_SCHEDULER_Task *timeout_task_id; 147 struct GNUNET_TIME_Relative retry_backoff;
170 148
171 /** 149 /**
172 * Flags for passing std descriptors to ARM (when starting ARM). 150 * Counter for request identifiers. They are used to match replies
151 * from ARM to operations in the @e operation_pending_head DLL.
173 */ 152 */
174 enum GNUNET_OS_InheritStdioFlags std_inheritance; 153 uint64_t request_id_counter;
175 154
176 /** 155 /**
177 * Type of the request expressed as a message type (start, stop or list). 156 * Have we detected that ARM is up?
178 */ 157 */
179 uint16_t type; 158 int currently_up;
159
180}; 160};
181 161
182 162
@@ -191,18 +171,6 @@ reconnect_arm (struct GNUNET_ARM_Handle *h);
191 171
192 172
193/** 173/**
194 * Check the list of pending requests, send the next
195 * one to the arm.
196 *
197 * @param h arm handle
198 * @param ignore_currently_down transmit message even if not initialized?
199 */
200static void
201trigger_next_request (struct GNUNET_ARM_Handle *h,
202 int ignore_currently_down);
203
204
205/**
206 * Task scheduled to try to re-connect to arm. 174 * Task scheduled to try to re-connect to arm.
207 * 175 *
208 * @param cls the `struct GNUNET_ARM_Handle` 176 * @param cls the `struct GNUNET_ARM_Handle`
@@ -213,8 +181,6 @@ reconnect_arm_task (void *cls)
213 struct GNUNET_ARM_Handle *h = cls; 181 struct GNUNET_ARM_Handle *h = cls;
214 182
215 h->reconnect_task = NULL; 183 h->reconnect_task = NULL;
216 LOG (GNUNET_ERROR_TYPE_DEBUG,
217 "Connecting to ARM service after delay\n");
218 reconnect_arm (h); 184 reconnect_arm (h);
219} 185}
220 186
@@ -228,28 +194,33 @@ reconnect_arm_task (void *cls)
228static void 194static void
229reconnect_arm_later (struct GNUNET_ARM_Handle *h) 195reconnect_arm_later (struct GNUNET_ARM_Handle *h)
230{ 196{
231 if (GNUNET_NO != h->currently_down) 197 struct GNUNET_ARM_Operation *op;
232 return; 198
233 if (NULL != h->cth) 199 if (NULL != h->mq)
234 {
235 GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth);
236 h->cth = NULL;
237 }
238 if (NULL != h->client)
239 { 200 {
240 GNUNET_CLIENT_disconnect (h->client); 201 GNUNET_MQ_destroy (h->mq);
241 h->client = NULL; 202 h->mq = NULL;
242 } 203 }
243 h->currently_down = GNUNET_YES; 204 h->currently_up = GNUNET_NO;
244 GNUNET_assert (NULL == h->reconnect_task); 205 GNUNET_assert (NULL == h->reconnect_task);
245 h->reconnect_task = 206 h->reconnect_task =
246 GNUNET_SCHEDULER_add_delayed (h->retry_backoff, 207 GNUNET_SCHEDULER_add_delayed (h->retry_backoff,
247 &reconnect_arm_task, 208 &reconnect_arm_task,
248 h); 209 h);
249 /* Don't clear pending messages on disconnection, deliver them later 210 while (NULL != (op = h->operation_pending_head))
250 clear_pending_messages (h, GNUNET_ARM_REQUEST_DISCONNECTED); 211 {
251 GNUNET_assert (NULL == h->control_pending_head); 212 if (NULL != op->result_cont)
252 */ 213 op->result_cont (op->cont_cls,
214 GNUNET_ARM_REQUEST_DISCONNECTED,
215 0);
216 if (NULL != op->list_cont)
217 op->list_cont (op->cont_cls,
218 GNUNET_ARM_REQUEST_DISCONNECTED,
219 0,
220 NULL);
221 GNUNET_ARM_operation_cancel (op);
222 }
223 GNUNET_assert (NULL == h->operation_pending_head);
253 h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff); 224 h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff);
254 if (NULL != h->conn_status) 225 if (NULL != h->conn_status)
255 h->conn_status (h->conn_status_cls, 226 h->conn_status (h->conn_status_cls,
@@ -264,176 +235,50 @@ reconnect_arm_later (struct GNUNET_ARM_Handle *h)
264 * @param id unique message ID to use for the lookup 235 * @param id unique message ID to use for the lookup
265 * @return NULL if not found 236 * @return NULL if not found
266 */ 237 */
267static struct ARMControlMessage * 238static struct GNUNET_ARM_Operation *
268find_cm_by_id (struct GNUNET_ARM_Handle *h, 239find_op_by_id (struct GNUNET_ARM_Handle *h,
269 uint64_t id) 240 uint64_t id)
270{ 241{
271 struct ARMControlMessage *result; 242 struct GNUNET_ARM_Operation *result;
272 243
273 for (result = h->control_sent_head; NULL != result; result = result->next) 244 for (result = h->operation_pending_head; NULL != result; result = result->next)
274 if (id == result->msg->request_id) 245 if (id == result->id)
275 return result; 246 return result;
276 return NULL; 247 return NULL;
277} 248}
278 249
279 250
280/** 251/**
281 * Handler for ARM 'termination' reply (failure to receive).
282 *
283 * @param cls our `struct GNUNET_ARM_Handle`
284 * @param msg expected to be NULL
285 */
286static void
287arm_termination_handler (void *cls,
288 const struct GNUNET_MessageHeader *msg)
289{
290 struct GNUNET_ARM_Handle *h = cls;
291 struct ARMControlMessage *cm;
292
293 if (NULL != msg)
294 {
295 GNUNET_break (0);
296 GNUNET_CLIENT_receive (h->client,
297 &arm_termination_handler,
298 h,
299 GNUNET_TIME_UNIT_FOREVER_REL);
300 return;
301 }
302 cm = h->thm;
303 h->thm = NULL;
304 h->currently_down = GNUNET_YES;
305 GNUNET_CLIENT_disconnect (h->client);
306 h->client = NULL;
307 if (NULL != cm->result_cont)
308 cm->result_cont (cm->cont_cls,
309 GNUNET_ARM_REQUEST_SENT_OK,
310 (const char *) &cm->msg[1],
311 GNUNET_ARM_RESULT_STOPPED);
312 GNUNET_free (cm->msg);
313 GNUNET_free (cm);
314}
315
316
317/**
318 * Handler for ARM replies. 252 * Handler for ARM replies.
319 * 253 *
320 * @param cls our `struct GNUNET_ARM_Handle` 254 * @param cls our `struct GNUNET_ARM_Handle`
321 * @param msg the message received from the arm service 255 * @param res the message received from the arm service
322 */ 256 */
323static void 257static void
324client_notify_handler (void *cls, 258handle_arm_result (void *cls,
325 const struct GNUNET_MessageHeader *msg) 259 const struct GNUNET_ARM_ResultMessage *res)
326{ 260{
327 struct GNUNET_ARM_Handle *h = cls; 261 struct GNUNET_ARM_Handle *h = cls;
328 const struct GNUNET_ARM_Message *arm_msg; 262 struct GNUNET_ARM_Operation *op;
329 const struct GNUNET_ARM_ResultMessage *res;
330 const struct GNUNET_ARM_ListResultMessage *lres;
331 struct ARMControlMessage *cm;
332 const char **list;
333 const char *pos;
334 uint64_t id; 263 uint64_t id;
335 enum GNUNET_ARM_Result result; 264 enum GNUNET_ARM_Result result;
336 uint16_t size_check; 265 GNUNET_ARM_ResultCallback result_cont;
337 uint16_t rcount; 266 void *result_cont_cls;
338 uint16_t msize;
339 unsigned char fail;
340 267
341 list = NULL; 268 id = GNUNET_ntohll (res->arm_msg.request_id);
342 rcount = 0; 269 op = find_op_by_id (h,
343 if (NULL == msg) 270 id);
344 { 271 if (NULL == op)
345 LOG (GNUNET_ERROR_TYPE_INFO,
346 _("Client was disconnected from arm service, trying to reconnect.\n"));
347 reconnect_arm_later (h);
348 return;
349 }
350 msize = ntohs (msg->size);
351 LOG (GNUNET_ERROR_TYPE_DEBUG,
352 "Processing message of type %u and size %u from arm service\n",
353 ntohs (msg->type), msize);
354 if (msize < sizeof (struct GNUNET_ARM_Message))
355 {
356 GNUNET_break (0);
357 reconnect_arm_later (h);
358 return;
359 }
360 arm_msg = (const struct GNUNET_ARM_Message *) msg;
361 GNUNET_break (0 == ntohl (arm_msg->reserved));
362 id = GNUNET_ntohll (arm_msg->request_id);
363 cm = find_cm_by_id (h, id);
364 if (NULL == cm)
365 { 272 {
366 LOG (GNUNET_ERROR_TYPE_DEBUG, 273 LOG (GNUNET_ERROR_TYPE_DEBUG,
367 "Message with unknown id %llu\n", 274 "Message with unknown id %llu\n",
368 id); 275 (unsigned long long) id);
369 return;
370 }
371 fail = GNUNET_NO;
372 switch (ntohs (msg->type))
373 {
374 case GNUNET_MESSAGE_TYPE_ARM_RESULT:
375 if (msize < sizeof (struct GNUNET_ARM_ResultMessage))
376 {
377 GNUNET_assert (0);
378 fail = GNUNET_YES;
379 }
380 break;
381 case GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT:
382 if (msize < sizeof (struct GNUNET_ARM_ListResultMessage))
383 {
384 GNUNET_break (0);
385 fail = GNUNET_YES;
386 break;
387 }
388 size_check = 0;
389 lres = (const struct GNUNET_ARM_ListResultMessage *) msg;
390 rcount = ntohs (lres->count);
391 {
392 unsigned int i;
393
394 list = GNUNET_malloc (sizeof (const char *) * rcount);
395 pos = (const char *)&lres[1];
396 for (i = 0; i < rcount; i++)
397 {
398 const char *end = memchr (pos, 0, msize - size_check);
399 if (NULL == end)
400 {
401 GNUNET_break (0);
402 fail = GNUNET_YES;
403 break;
404 }
405 list[i] = pos;
406 size_check += (end - pos) + 1;
407 pos = end + 1;
408 }
409 if (GNUNET_YES == fail)
410 {
411 GNUNET_free (list);
412 list = NULL;
413 }
414 }
415 break;
416 default:
417 fail = GNUNET_YES;
418 break;
419 }
420 GNUNET_assert (NULL != cm->timeout_task_id);
421 GNUNET_SCHEDULER_cancel (cm->timeout_task_id);
422 GNUNET_CONTAINER_DLL_remove (h->control_sent_head,
423 h->control_sent_tail,
424 cm);
425 if (GNUNET_YES == fail)
426 {
427 reconnect_arm_later (h);
428 GNUNET_free (cm->msg);
429 GNUNET_free (cm);
430 return; 276 return;
431 } 277 }
432 if ( (GNUNET_MESSAGE_TYPE_ARM_RESULT == ntohs (msg->type)) && 278
433 (0 == strcasecmp ((const char *) &cm->msg[1], 279 result = (enum GNUNET_ARM_Result) ntohl (res->result);
434 "arm")) && 280 if ( (GNUNET_YES == op->is_arm_stop) &&
435 (NULL != (res = (const struct GNUNET_ARM_ResultMessage *) msg)) && 281 (GNUNET_ARM_RESULT_STOPPING == result) )
436 (GNUNET_ARM_RESULT_STOPPING == ntohl (res->result)) )
437 { 282 {
438 /* special case: if we are stopping 'gnunet-service-arm', we do not just 283 /* special case: if we are stopping 'gnunet-service-arm', we do not just
439 wait for the result message, but also wait for the service to close 284 wait for the result message, but also wait for the service to close
@@ -443,184 +288,159 @@ client_notify_handler (void *cls,
443 if (NULL != h->thm) 288 if (NULL != h->thm)
444 { 289 {
445 GNUNET_break (0); 290 GNUNET_break (0);
446 cm->result_cont (h->thm->cont_cls, 291 op->result_cont (h->thm->cont_cls,
447 GNUNET_ARM_REQUEST_SENT_OK, 292 GNUNET_ARM_REQUEST_SENT_OK,
448 (const char *) &h->thm->msg[1],
449 GNUNET_ARM_RESULT_IS_NOT_KNOWN); 293 GNUNET_ARM_RESULT_IS_NOT_KNOWN);
450 GNUNET_free (h->thm->msg);
451 GNUNET_free (h->thm); 294 GNUNET_free (h->thm);
452 } 295 }
453 h->thm = cm; 296 GNUNET_CONTAINER_DLL_remove (h->operation_pending_head,
454 GNUNET_CLIENT_receive (h->client, 297 h->operation_pending_tail,
455 &arm_termination_handler, 298 op);
456 h, 299 h->thm = op;
457 GNUNET_TIME_UNIT_FOREVER_REL);
458 return; 300 return;
459 } 301 }
460 GNUNET_CLIENT_receive (h->client, 302 result_cont = op->result_cont;
461 &client_notify_handler, 303 result_cont_cls = op->cont_cls;
462 h, 304 GNUNET_ARM_operation_cancel (op);
463 GNUNET_TIME_UNIT_FOREVER_REL); 305 if (NULL != result_cont)
464 switch (ntohs (msg->type)) 306 result_cont (result_cont_cls,
465 { 307 GNUNET_ARM_REQUEST_SENT_OK,
466 case GNUNET_MESSAGE_TYPE_ARM_RESULT: 308 result);
467 res = (const struct GNUNET_ARM_ResultMessage *) msg;
468 LOG (GNUNET_ERROR_TYPE_DEBUG,
469 "Received response from ARM for service `%s': %u\n",
470 (const char *) &cm->msg[1], ntohs (msg->type));
471 result = (enum GNUNET_ARM_Result) ntohl (res->result);
472 if (NULL != cm->result_cont)
473 cm->result_cont (cm->cont_cls,
474 GNUNET_ARM_REQUEST_SENT_OK,
475 (const char *) &cm->msg[1],
476 result);
477 break;
478 case GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT:
479 if (NULL != cm->list_cont)
480 cm->list_cont (cm->cont_cls,
481 GNUNET_ARM_REQUEST_SENT_OK,
482 rcount,
483 list);
484 GNUNET_free_non_null (list);
485 break;
486 }
487 GNUNET_free (cm->msg);
488 GNUNET_free (cm);
489} 309}
490 310
491 311
492/** 312/**
493 * Transmit the next message to the arm service. 313 * Checked that list result message is well-formed.
494 * 314 *
495 * @param cls closure with the `struct GNUNET_ARM_Handle` 315 * @param cls our `struct GNUNET_ARM_Handle`
496 * @param size number of bytes available in @a buf 316 * @param lres the message received from the arm service
497 * @param buf where the callee should write the message 317 * @return #GNUNET_OK if message is well-formed
498 * @return number of bytes written to @a buf
499 */ 318 */
500static size_t 319static int
501transmit_arm_message (void *cls, 320check_arm_list_result (void *cls,
502 size_t size, 321 const struct GNUNET_ARM_ListResultMessage *lres)
503 void *buf)
504{ 322{
505 struct GNUNET_ARM_Handle *h = cls; 323 const char *pos = (const char *) &lres[1];
506 struct ARMControlMessage *cm; 324 uint16_t rcount = ntohs (lres->count);
507 struct GNUNET_ARM_Message *arm_msg; 325 uint16_t msize = ntohs (lres->arm_msg.header.size);
508 uint64_t request_id; 326 uint16_t size_check;
509 int notify_connection;
510 uint16_t msize;
511 327
512 notify_connection = GNUNET_NO; 328 size_check = 0;
513 LOG (GNUNET_ERROR_TYPE_DEBUG, 329 for (unsigned int i = 0; i < rcount; i++)
514 "transmit_arm_message is running with %p buffer of size %lu. ARM is known to be %s\n",
515 buf, size, h->currently_down ? "unconnected" : "connected");
516 GNUNET_assert (NULL == h->reconnect_task);
517 h->cth = NULL;
518 if ((GNUNET_YES == h->currently_down) && (NULL != buf))
519 {
520 h->currently_down = GNUNET_NO;
521 notify_connection = GNUNET_YES;
522 h->retry_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
523 GNUNET_CLIENT_receive (h->client, &client_notify_handler, h,
524 GNUNET_TIME_UNIT_FOREVER_REL);
525 }
526 if (NULL == buf)
527 { 330 {
528 LOG (GNUNET_ERROR_TYPE_DEBUG, 331 const char *end = memchr (pos, 0, msize - size_check);
529 "Transmission failed, initiating reconnect\n"); 332 if (NULL == end)
530 reconnect_arm_later (h); 333 {
531 return 0; 334 GNUNET_break (0);
532 } 335 return GNUNET_SYSERR;
533 if (NULL == (cm = h->control_pending_head)) 336 }
534 { 337 size_check += (end - pos) + 1;
535 LOG (GNUNET_ERROR_TYPE_DEBUG, 338 pos = end + 1;
536 "Queue is empty, not sending anything\n");
537 msize = 0;
538 goto end;
539 }
540 GNUNET_assert (NULL != cm->msg);
541 msize = ntohs (cm->msg->header.size);
542 if (size < msize)
543 {
544 LOG (GNUNET_ERROR_TYPE_DEBUG,
545 "Request is too big (%u < %u), not sending it\n", size, msize);
546 trigger_next_request (h, GNUNET_NO);
547 msize = 0;
548 goto end;
549 } 339 }
550 arm_msg = cm->msg; 340 return GNUNET_OK;
551 if (0 == h->request_id_counter)
552 h->request_id_counter++;
553 request_id = h->request_id_counter++;
554 LOG (GNUNET_ERROR_TYPE_DEBUG,
555 "Transmitting control message with %u bytes of type %u to arm with id %llu\n",
556 (unsigned int) msize,
557 (unsigned int) ntohs (cm->msg->header.type),
558 request_id);
559 arm_msg->reserved = htonl (0);
560 arm_msg->request_id = GNUNET_htonll (request_id);
561 memcpy (buf, cm->msg, msize);
562 /* Otherwise we won't be able to find it later! */
563 arm_msg->request_id = request_id;
564 GNUNET_CONTAINER_DLL_remove (h->control_pending_head,
565 h->control_pending_tail,
566 cm);
567 GNUNET_CONTAINER_DLL_insert_tail (h->control_sent_head,
568 h->control_sent_tail,
569 cm);
570 /* Don't free msg, keep it around (kind of wasteful, but then we don't
571 * really have many messages to handle, and it'll be freed when it times
572 * out anyway.
573 */
574 trigger_next_request (h, GNUNET_NO);
575
576 end:
577 if ((GNUNET_YES == notify_connection) && (NULL != h->conn_status))
578 h->conn_status (h->conn_status_cls, GNUNET_YES);
579 return msize;
580} 341}
581 342
582 343
583/** 344/**
584 * Check the list of pending requests, send the next 345 * Handler for ARM list replies.
585 * one to the arm.
586 * 346 *
587 * @param h arm handle 347 * @param cls our `struct GNUNET_ARM_Handle`
588 * @param ignore_currently_down transmit message even if not initialized? 348 * @param lres the message received from the arm service
589 */ 349 */
590static void 350static void
591trigger_next_request (struct GNUNET_ARM_Handle *h, 351handle_arm_list_result (void *cls,
592 int ignore_currently_down) 352 const struct GNUNET_ARM_ListResultMessage *lres)
593{ 353{
594 uint16_t msize; 354 struct GNUNET_ARM_Handle *h = cls;
355 uint16_t rcount = ntohs (lres->count);
356 const char *list[rcount];
357 const char *pos = (const char *) &lres[1];
358 uint16_t msize = ntohs (lres->arm_msg.header.size);
359 struct GNUNET_ARM_Operation *op;
360 uint16_t size_check;
361 uint64_t id;
595 362
596 msize = sizeof (struct GNUNET_MessageHeader); 363 id = GNUNET_ntohll (lres->arm_msg.request_id);
597 if ((GNUNET_YES == h->currently_down) && (ignore_currently_down == GNUNET_NO)) 364 op = find_op_by_id (h,
365 id);
366 if (NULL == op)
598 { 367 {
599 LOG (GNUNET_ERROR_TYPE_DEBUG, 368 LOG (GNUNET_ERROR_TYPE_DEBUG,
600 "ARM connection down, not processing queue\n"); 369 "Message with unknown id %llu\n",
370 (unsigned long long) id);
601 return; 371 return;
602 } 372 }
603 if (NULL != h->cth) 373 size_check = 0;
374 for (unsigned int i = 0; i < rcount; i++)
375 {
376 const char *end = memchr (pos,
377 0,
378 msize - size_check);
379
380 /* Assert, as this was already checked in #check_arm_list_result() */
381 GNUNET_assert (NULL != end);
382 list[i] = pos;
383 size_check += (end - pos) + 1;
384 pos = end + 1;
385 }
386 if (NULL != op->list_cont)
387 op->list_cont (op->cont_cls,
388 GNUNET_ARM_REQUEST_SENT_OK,
389 rcount,
390 list);
391 GNUNET_ARM_operation_cancel (op);
392}
393
394
395/**
396 * Receive confirmation from test, ARM service is up.
397 *
398 * @param cls closure with the `struct GNUNET_ARM_Handle`
399 * @param msg message received
400 */
401static void
402handle_confirm (void *cls,
403 const struct GNUNET_MessageHeader *msg)
404{
405 struct GNUNET_ARM_Handle *h = cls;
406
407 LOG (GNUNET_ERROR_TYPE_DEBUG,
408 "Got confirmation from ARM that we are up!\n");
409 if (GNUNET_NO == h->currently_up)
604 { 410 {
605 LOG (GNUNET_ERROR_TYPE_DEBUG, 411 h->currently_up = GNUNET_YES;
606 "Request pending, not processing queue\n"); 412 if (NULL != h->conn_status)
607 return; 413 h->conn_status (h->conn_status_cls,
414 GNUNET_YES);
608 } 415 }
609 if (NULL != h->control_pending_head) 416}
610 msize = 417
611 ntohs (h->control_pending_head->msg->header.size); 418
612 else if (GNUNET_NO == ignore_currently_down) 419/**
420 * Generic error handler, called with the appropriate error code and
421 * the same closure specified at the creation of the message queue.
422 * Not every message queue implementation supports an error handler.
423 *
424 * @param cls closure with the `struct GNUNET_ARM_Handle *`
425 * @param error error code
426 */
427static void
428mq_error_handler (void *cls,
429 enum GNUNET_MQ_Error error)
430{
431 struct GNUNET_ARM_Handle *h = cls;
432 struct GNUNET_ARM_Operation *op;
433
434 h->currently_up = GNUNET_NO;
435 if (NULL != (op = h->thm))
613 { 436 {
614 LOG (GNUNET_ERROR_TYPE_DEBUG, 437 h->thm = NULL;
615 "Request queue empty, not processing queue\n"); 438 op->result_cont (op->cont_cls,
616 return; /* no pending message */ 439 GNUNET_ARM_REQUEST_SENT_OK,
440 GNUNET_ARM_RESULT_STOPPED);
441 GNUNET_free (op);
617 } 442 }
618 h->cth = 443 reconnect_arm_later (h);
619 GNUNET_CLIENT_notify_transmit_ready (h->client,
620 msize,
621 GNUNET_TIME_UNIT_FOREVER_REL,
622 GNUNET_NO,
623 &transmit_arm_message, h);
624} 444}
625 445
626 446
@@ -633,22 +453,47 @@ trigger_next_request (struct GNUNET_ARM_Handle *h,
633static int 453static int
634reconnect_arm (struct GNUNET_ARM_Handle *h) 454reconnect_arm (struct GNUNET_ARM_Handle *h)
635{ 455{
636 GNUNET_assert (NULL == h->client); 456 GNUNET_MQ_hd_fixed_size (arm_result,
637 GNUNET_assert (GNUNET_YES == h->currently_down); 457 GNUNET_MESSAGE_TYPE_ARM_RESULT,
638 h->client = GNUNET_CLIENT_connect ("arm", h->cfg); 458 struct GNUNET_ARM_ResultMessage);
639 if (NULL == h->client) 459 GNUNET_MQ_hd_var_size (arm_list_result,
460 GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT,
461 struct GNUNET_ARM_ListResultMessage);
462 GNUNET_MQ_hd_fixed_size (confirm,
463 GNUNET_MESSAGE_TYPE_TEST,
464 struct GNUNET_MessageHeader);
465 struct GNUNET_MQ_MessageHandler handlers[] = {
466 make_arm_result_handler (h),
467 make_arm_list_result_handler (h),
468 make_confirm_handler (h),
469 GNUNET_MQ_handler_end ()
470 };
471 struct GNUNET_MessageHeader *test;
472 struct GNUNET_MQ_Envelope *env;
473
474 if (NULL != h->mq)
475 return GNUNET_OK;
476 GNUNET_assert (GNUNET_NO == h->currently_up);
477 h->mq = GNUNET_CLIENT_connecT (h->cfg,
478 "arm",
479 handlers,
480 &mq_error_handler,
481 h);
482 if (NULL == h->mq)
640 { 483 {
641 LOG (GNUNET_ERROR_TYPE_DEBUG, 484 LOG (GNUNET_ERROR_TYPE_DEBUG,
642 "arm_api, GNUNET_CLIENT_connect returned NULL\n"); 485 "GNUNET_CLIENT_connect returned NULL\n");
643 if (NULL != h->conn_status) 486 if (NULL != h->conn_status)
644 h->conn_status (h->conn_status_cls, 487 h->conn_status (h->conn_status_cls,
645 GNUNET_SYSERR); 488 GNUNET_SYSERR);
646 return GNUNET_SYSERR; 489 return GNUNET_SYSERR;
647 } 490 }
648 LOG (GNUNET_ERROR_TYPE_DEBUG, 491 LOG (GNUNET_ERROR_TYPE_DEBUG,
649 "arm_api, GNUNET_CLIENT_connect returned non-NULL\n"); 492 "Sending TEST message to ARM\n");
650 trigger_next_request (h, 493 env = GNUNET_MQ_msg (test,
651 GNUNET_YES); 494 GNUNET_MESSAGE_TYPE_TEST);
495 GNUNET_MQ_send (h->mq,
496 env);
652 return GNUNET_OK; 497 return GNUNET_OK;
653} 498}
654 499
@@ -661,22 +506,20 @@ reconnect_arm (struct GNUNET_ARM_Handle *h)
661 * the ARM service may internally use a different 506 * the ARM service may internally use a different
662 * configuration to determine how to start the service). 507 * configuration to determine how to start the service).
663 * @param conn_status will be called when connecting/disconnecting 508 * @param conn_status will be called when connecting/disconnecting
664 * @param cls closure for conn_status 509 * @param conn_status_cls closure for @a conn_status
665 * @return context to use for further ARM operations, NULL on error. 510 * @return context to use for further ARM operations, NULL on error.
666 */ 511 */
667struct GNUNET_ARM_Handle * 512struct GNUNET_ARM_Handle *
668GNUNET_ARM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, 513GNUNET_ARM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
669 GNUNET_ARM_ConnectionStatusCallback conn_status, 514 GNUNET_ARM_ConnectionStatusCallback conn_status,
670 void *cls) 515 void *conn_status_cls)
671{ 516{
672 struct GNUNET_ARM_Handle *h; 517 struct GNUNET_ARM_Handle *h;
673 518
674 h = GNUNET_new (struct GNUNET_ARM_Handle); 519 h = GNUNET_new (struct GNUNET_ARM_Handle);
675 h->cfg = GNUNET_CONFIGURATION_dup (cfg); 520 h->cfg = cfg;
676 h->currently_down = GNUNET_YES;
677 h->reconnect_task = NULL;
678 h->conn_status = conn_status; 521 h->conn_status = conn_status;
679 h->conn_status_cls = cls; 522 h->conn_status_cls = conn_status_cls;
680 if (GNUNET_OK != reconnect_arm (h)) 523 if (GNUNET_OK != reconnect_arm (h))
681 { 524 {
682 GNUNET_free (h); 525 GNUNET_free (h);
@@ -692,113 +535,60 @@ GNUNET_ARM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
692 * @param h the handle that was being used 535 * @param h the handle that was being used
693 */ 536 */
694void 537void
695GNUNET_ARM_disconnect_and_free (struct GNUNET_ARM_Handle *h) 538GNUNET_ARM_disconnect (struct GNUNET_ARM_Handle *h)
696{ 539{
697 struct ARMControlMessage *cm; 540 struct GNUNET_ARM_Operation *op;
698 541
699 LOG (GNUNET_ERROR_TYPE_DEBUG, 542 LOG (GNUNET_ERROR_TYPE_DEBUG,
700 "Disconnecting from ARM service\n"); 543 "Disconnecting from ARM service\n");
701 if (NULL != h->cth) 544 while (NULL != (op = h->operation_pending_head))
702 { 545 {
703 GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth); 546 GNUNET_CONTAINER_DLL_remove (h->operation_pending_head,
704 h->cth = NULL; 547 h->operation_pending_tail,
705 } 548 op);
706 while ((NULL != (cm = h->control_pending_head)) 549 if (NULL != op->result_cont)
707 || (NULL != (cm = h->control_sent_head)) ) 550 op->result_cont (op->cont_cls,
708 {
709 if (NULL != h->control_pending_head)
710 GNUNET_CONTAINER_DLL_remove (h->control_pending_head,
711 h->control_pending_tail,
712 cm);
713 else
714 GNUNET_CONTAINER_DLL_remove (h->control_sent_head,
715 h->control_sent_tail,
716 cm);
717 GNUNET_assert (NULL != cm->timeout_task_id);
718 GNUNET_SCHEDULER_cancel (cm->timeout_task_id);
719 if (NULL != cm->result_cont)
720 cm->result_cont (cm->cont_cls,
721 GNUNET_ARM_REQUEST_DISCONNECTED, 551 GNUNET_ARM_REQUEST_DISCONNECTED,
722 NULL,
723 0); 552 0);
724 /* FIXME: What about list callback? */ 553 if (NULL != op->list_cont)
725 GNUNET_free_non_null (cm->msg); 554 op->list_cont (op->cont_cls,
726 GNUNET_free (cm); 555 GNUNET_ARM_REQUEST_DISCONNECTED,
556 0,
557 NULL);
558 if (NULL != op->async)
559 {
560 GNUNET_SCHEDULER_cancel (op->async);
561 op->async = NULL;
562 }
563 GNUNET_free (op);
727 } 564 }
728 if (NULL != h->client) 565 if (NULL != h->mq)
729 { 566 {
730 GNUNET_CLIENT_disconnect (h->client); 567 GNUNET_MQ_destroy (h->mq);
731 h->client = NULL; 568 h->mq = NULL;
732 } 569 }
733 if (NULL != h->reconnect_task) 570 if (NULL != h->reconnect_task)
734 { 571 {
735 GNUNET_SCHEDULER_cancel (h->reconnect_task); 572 GNUNET_SCHEDULER_cancel (h->reconnect_task);
736 h->reconnect_task = NULL; 573 h->reconnect_task = NULL;
737 } 574 }
738 if (GNUNET_NO == h->service_test_is_active) 575 GNUNET_free (h);
739 {
740 GNUNET_CONFIGURATION_destroy (h->cfg);
741 GNUNET_free (h);
742 }
743}
744
745
746/**
747 * Message timed out. Remove it from the queue.
748 *
749 * @param cls the message (struct ARMControlMessage *)
750 */
751static void
752control_message_timeout (void *cls)
753{
754 struct ARMControlMessage *cm = cls;
755 struct GNUNET_ARM_Message *arm_msg;
756
757 LOG (GNUNET_ERROR_TYPE_DEBUG,
758 "Control message timed out\n");
759 arm_msg = cm->msg;
760 if ((NULL == arm_msg) || (0 == arm_msg->request_id))
761 {
762 GNUNET_CONTAINER_DLL_remove (cm->h->control_pending_head,
763 cm->h->control_pending_tail,
764 cm);
765 }
766 else
767 {
768 GNUNET_CONTAINER_DLL_remove (cm->h->control_sent_head,
769 cm->h->control_sent_tail,
770 cm);
771 }
772 if (NULL != cm->result_cont)
773 cm->result_cont (cm->cont_cls,
774 GNUNET_ARM_REQUEST_TIMEOUT,
775 NULL, 0);
776 else if (NULL != cm->list_cont)
777 cm->list_cont (cm->cont_cls,
778 GNUNET_ARM_REQUEST_TIMEOUT,
779 0, NULL);
780 GNUNET_free_non_null (cm->msg);
781 GNUNET_free (cm);
782} 576}
783 577
784 578
785/** 579/**
786 * A client specifically requested starting of ARM itself. 580 * A client specifically requested starting of ARM itself.
787 * This function is called with information about whether 581 * Starts the ARM service.
788 * or not ARM is running; if it is, report success. If
789 * it is not, start the ARM process.
790 * 582 *
791 * @param cls the context for the request that we will report on (struct ARMControlMessage *) 583 * @param h the handle with configuration details
792 * @param result #GNUNET_YES if ARM is running 584 * @param std_inheritance inheritance of std streams
585 * @return operation status code
793 */ 586 */
794static void 587static enum GNUNET_ARM_Result
795arm_service_report (void *cls, 588start_arm_service (struct GNUNET_ARM_Handle *h,
796 int result) 589 enum GNUNET_OS_InheritStdioFlags std_inheritance)
797{ 590{
798 struct ARMControlMessage *cm = cls;
799 struct GNUNET_ARM_Handle *h;
800 struct GNUNET_OS_Process *proc; 591 struct GNUNET_OS_Process *proc;
801 unsigned char test_is_active;
802 char *cbinary; 592 char *cbinary;
803 char *binary; 593 char *binary;
804 char *quotedbinary; 594 char *quotedbinary;
@@ -806,51 +596,20 @@ arm_service_report (void *cls,
806 char *loprefix; 596 char *loprefix;
807 char *lopostfix; 597 char *lopostfix;
808 598
809 test_is_active = cm->h->service_test_is_active;
810 if ((GNUNET_YES == test_is_active) &&
811 (GNUNET_YES == result))
812 {
813 LOG (GNUNET_ERROR_TYPE_DEBUG,
814 "Looks like `%s' is already running.\n",
815 "gnunet-service-arm");
816 /* arm is running! */
817 if (cm->result_cont)
818 cm->result_cont (cm->cont_cls,
819 GNUNET_ARM_REQUEST_SENT_OK, "arm",
820 GNUNET_ARM_RESULT_IS_STARTED_ALREADY);
821 }
822 if (GNUNET_NO == test_is_active)
823 {
824 /* User disconnected & destroyed ARM handle in the middle of
825 * the service test, so we kept the handle around until now.
826 */
827 GNUNET_CONFIGURATION_destroy (cm->h->cfg);
828 GNUNET_free (cm->h);
829 }
830 if ((GNUNET_YES == result) ||
831 (GNUNET_NO == test_is_active))
832 {
833 GNUNET_free (cm);
834 return;
835 }
836 cm->h->service_test_is_active = GNUNET_NO;
837 LOG (GNUNET_ERROR_TYPE_DEBUG,
838 "Looks like `%s' is not running, will start it.\n",
839 "gnunet-service-arm");
840 if (GNUNET_OK != 599 if (GNUNET_OK !=
841 GNUNET_CONFIGURATION_get_value_string (cm->h->cfg, 600 GNUNET_CONFIGURATION_get_value_string (h->cfg,
842 "arm", 601 "arm",
843 "PREFIX", 602 "PREFIX",
844 &loprefix)) 603 &loprefix))
845 loprefix = GNUNET_strdup (""); 604 loprefix = GNUNET_strdup ("");
846 if (GNUNET_OK != 605 if (GNUNET_OK !=
847 GNUNET_CONFIGURATION_get_value_string (cm->h->cfg, 606 GNUNET_CONFIGURATION_get_value_string (h->cfg,
848 "arm", 607 "arm",
849 "OPTIONS", 608 "OPTIONS",
850 &lopostfix)) 609 &lopostfix))
851 lopostfix = GNUNET_strdup (""); 610 lopostfix = GNUNET_strdup ("");
852 if (GNUNET_OK != 611 if (GNUNET_OK !=
853 GNUNET_CONFIGURATION_get_value_string (cm->h->cfg, 612 GNUNET_CONFIGURATION_get_value_string (h->cfg,
854 "arm", 613 "arm",
855 "BINARY", 614 "BINARY",
856 &cbinary)) 615 &cbinary))
@@ -858,18 +617,14 @@ arm_service_report (void *cls,
858 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING, 617 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
859 "arm", 618 "arm",
860 "BINARY"); 619 "BINARY");
861 if (cm->result_cont)
862 cm->result_cont (cm->cont_cls,
863 GNUNET_ARM_REQUEST_SENT_OK, "arm",
864 GNUNET_ARM_RESULT_IS_NOT_KNOWN);
865 GNUNET_free (cm);
866 GNUNET_free (loprefix); 620 GNUNET_free (loprefix);
867 GNUNET_free (lopostfix); 621 GNUNET_free (lopostfix);
868 return; 622 return GNUNET_ARM_RESULT_IS_NOT_KNOWN;
869 } 623 }
870 if (GNUNET_OK != 624 if (GNUNET_OK !=
871 GNUNET_CONFIGURATION_get_value_filename (cm->h->cfg, 625 GNUNET_CONFIGURATION_get_value_filename (h->cfg,
872 "arm", "CONFIG", 626 "arm",
627 "CONFIG",
873 &config)) 628 &config))
874 config = NULL; 629 config = NULL;
875 binary = GNUNET_OS_get_libexec_binary_path (cbinary); 630 binary = GNUNET_OS_get_libexec_binary_path (cbinary);
@@ -878,15 +633,15 @@ arm_service_report (void *cls,
878 binary); 633 binary);
879 GNUNET_free (cbinary); 634 GNUNET_free (cbinary);
880 if ( (GNUNET_YES == 635 if ( (GNUNET_YES ==
881 GNUNET_CONFIGURATION_have_value (cm->h->cfg, 636 GNUNET_CONFIGURATION_have_value (h->cfg,
882 "TESTING", 637 "TESTING",
883 "WEAKRANDOM")) && 638 "WEAKRANDOM")) &&
884 (GNUNET_YES == 639 (GNUNET_YES ==
885 GNUNET_CONFIGURATION_get_value_yesno (cm->h->cfg, 640 GNUNET_CONFIGURATION_get_value_yesno (h->cfg,
886 "TESTING", 641 "TESTING",
887 "WEAKRANDOM")) && 642 "WEAKRANDOM")) &&
888 (GNUNET_NO == 643 (GNUNET_NO ==
889 GNUNET_CONFIGURATION_have_value (cm->h->cfg, 644 GNUNET_CONFIGURATION_have_value (h->cfg,
890 "TESTING", 645 "TESTING",
891 "HOSTFILE"))) 646 "HOSTFILE")))
892 { 647 {
@@ -894,39 +649,43 @@ arm_service_report (void *cls,
894 /* we're clearly running a test, don't daemonize */ 649 /* we're clearly running a test, don't daemonize */
895 if (NULL == config) 650 if (NULL == config)
896 proc = GNUNET_OS_start_process_s (GNUNET_NO, 651 proc = GNUNET_OS_start_process_s (GNUNET_NO,
897 cm->std_inheritance, 652 std_inheritance,
898 NULL, 653 NULL,
899 loprefix, 654 loprefix,
900 quotedbinary, 655 quotedbinary,
901 /* no daemonization! */ 656 /* no daemonization! */
902 lopostfix, NULL); 657 lopostfix,
658 NULL);
903 else 659 else
904 proc = GNUNET_OS_start_process_s (GNUNET_NO, 660 proc = GNUNET_OS_start_process_s (GNUNET_NO,
905 cm->std_inheritance, 661 std_inheritance,
906 NULL, 662 NULL,
907 loprefix, 663 loprefix,
908 quotedbinary, 664 quotedbinary,
909 "-c", config, 665 "-c", config,
910 /* no daemonization! */ 666 /* no daemonization! */
911 lopostfix, NULL); 667 lopostfix,
668 NULL);
912 } 669 }
913 else 670 else
914 { 671 {
915 if (NULL == config) 672 if (NULL == config)
916 proc = GNUNET_OS_start_process_s (GNUNET_NO, 673 proc = GNUNET_OS_start_process_s (GNUNET_NO,
917 cm->std_inheritance, 674 std_inheritance,
918 NULL, 675 NULL,
919 loprefix, 676 loprefix,
920 quotedbinary, 677 quotedbinary,
921 "-d", lopostfix, NULL); 678 "-d", /* do daemonize */
679 lopostfix, NULL);
922 else 680 else
923 proc = GNUNET_OS_start_process_s (GNUNET_NO, 681 proc = GNUNET_OS_start_process_s (GNUNET_NO,
924 cm->std_inheritance, 682 std_inheritance,
925 NULL, 683 NULL,
926 loprefix, 684 loprefix,
927 quotedbinary, 685 quotedbinary,
928 "-c", config, 686 "-c", config,
929 "-d", lopostfix, 687 "-d", /* do daemonize */
688 lopostfix,
930 NULL); 689 NULL);
931 } 690 }
932 GNUNET_free (binary); 691 GNUNET_free (binary);
@@ -935,22 +694,32 @@ arm_service_report (void *cls,
935 GNUNET_free (loprefix); 694 GNUNET_free (loprefix);
936 GNUNET_free (lopostfix); 695 GNUNET_free (lopostfix);
937 if (NULL == proc) 696 if (NULL == proc)
697 return GNUNET_ARM_RESULT_START_FAILED;
698 GNUNET_OS_process_destroy (proc);
699 return GNUNET_ARM_RESULT_STARTING;
700}
701
702
703/**
704 * Abort an operation. Only prevents the callback from being
705 * called, the operation may still complete.
706 *
707 * @param op operation to cancel
708 */
709void
710GNUNET_ARM_operation_cancel (struct GNUNET_ARM_Operation *op)
711{
712 struct GNUNET_ARM_Handle *h = op->h;
713
714 if (h->thm == op)
938 { 715 {
939 if (cm->result_cont) 716 op->result_cont = NULL;
940 cm->result_cont (cm->cont_cls,
941 GNUNET_ARM_REQUEST_SENT_OK, "arm",
942 GNUNET_ARM_RESULT_START_FAILED);
943 GNUNET_free (cm);
944 return; 717 return;
945 } 718 }
946 if (cm->result_cont) 719 GNUNET_CONTAINER_DLL_remove (h->operation_pending_head,
947 cm->result_cont (cm->cont_cls, 720 h->operation_pending_tail,
948 GNUNET_ARM_REQUEST_SENT_OK, "arm", 721 op);
949 GNUNET_ARM_RESULT_STARTING); 722 GNUNET_free (op);
950 GNUNET_OS_process_destroy (proc);
951 h = cm->h;
952 GNUNET_free (cm);
953 reconnect_arm (h);
954} 723}
955 724
956 725
@@ -959,21 +728,21 @@ arm_service_report (void *cls,
959 * 728 *
960 * @param h handle to ARM 729 * @param h handle to ARM
961 * @param service_name name of the service 730 * @param service_name name of the service
962 * @param timeout how long to wait before failing for good
963 * @param cb callback to invoke when service is ready 731 * @param cb callback to invoke when service is ready
964 * @param cb_cls closure for @a cb 732 * @param cb_cls closure for @a cb
965 * @param type type of the request 733 * @param type type of the request
734 * @return handle to queue, NULL on error
966 */ 735 */
967static void 736static struct GNUNET_ARM_Operation *
968change_service (struct GNUNET_ARM_Handle *h, 737change_service (struct GNUNET_ARM_Handle *h,
969 const char *service_name, 738 const char *service_name,
970 struct GNUNET_TIME_Relative timeout,
971 GNUNET_ARM_ResultCallback cb, 739 GNUNET_ARM_ResultCallback cb,
972 void *cb_cls, 740 void *cb_cls,
973 uint16_t type) 741 uint16_t type)
974{ 742{
975 struct ARMControlMessage *cm; 743 struct GNUNET_ARM_Operation *op;
976 size_t slen; 744 size_t slen;
745 struct GNUNET_MQ_Envelope *env;
977 struct GNUNET_ARM_Message *msg; 746 struct GNUNET_ARM_Message *msg;
978 747
979 slen = strlen (service_name) + 1; 748 slen = strlen (service_name) + 1;
@@ -981,38 +750,81 @@ change_service (struct GNUNET_ARM_Handle *h,
981 GNUNET_SERVER_MAX_MESSAGE_SIZE) 750 GNUNET_SERVER_MAX_MESSAGE_SIZE)
982 { 751 {
983 GNUNET_break (0); 752 GNUNET_break (0);
984 if (cb != NULL) 753 return NULL;
985 cb (cb_cls, GNUNET_ARM_REQUEST_TOO_LONG, NULL, 0);
986 return;
987 } 754 }
988 LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting %s of service `%s'.\n", 755 if (0 == h->request_id_counter)
989 (GNUNET_MESSAGE_TYPE_ARM_START == type) ? "start" : "termination", 756 h->request_id_counter++;
990 service_name); 757 op = GNUNET_new (struct GNUNET_ARM_Operation);
991 cm = GNUNET_malloc (sizeof (struct ARMControlMessage) + slen); 758 op->h = h;
992 cm->h = h; 759 op->result_cont = cb;
993 cm->result_cont = cb; 760 op->cont_cls = cb_cls;
994 cm->cont_cls = cb_cls; 761 op->id = h->request_id_counter++;
995 cm->timeout = GNUNET_TIME_relative_to_absolute (timeout); 762 GNUNET_CONTAINER_DLL_insert_tail (h->operation_pending_head,
996 memcpy (&cm[1], service_name, slen); 763 h->operation_pending_tail,
997 msg = GNUNET_malloc (sizeof (struct GNUNET_ARM_Message) + slen); 764 op);
998 msg->header.size = htons (sizeof (struct GNUNET_ARM_Message) + slen); 765 env = GNUNET_MQ_msg_extra (msg,
999 msg->header.type = htons (type); 766 slen,
767 type);
1000 msg->reserved = htonl (0); 768 msg->reserved = htonl (0);
1001 memcpy (&msg[1], service_name, slen); 769 msg->request_id = GNUNET_htonll (op->id);
1002 cm->msg = msg; 770 memcpy (&msg[1],
771 service_name,
772 slen);
773 GNUNET_MQ_send (h->mq,
774 env);
775 return op;
776}
777
778
779/**
780 * Task run to notify application that ARM is already up.
781 *
782 * @param cls the operation that asked ARM to be started
783 */
784static void
785notify_running (void *cls)
786{
787 struct GNUNET_ARM_Operation *op = cls;
788 struct GNUNET_ARM_Handle *h = op->h;
789
790 op->async = NULL;
791 GNUNET_CONTAINER_DLL_remove (h->operation_pending_head,
792 h->operation_pending_tail,
793 op);
794 if (NULL != op->result_cont)
795 op->result_cont (op->cont_cls,
796 GNUNET_ARM_REQUEST_SENT_OK,
797 GNUNET_ARM_RESULT_IS_STARTED_ALREADY);
798 if ( (GNUNET_YES == h->currently_up) &&
799 (NULL != h->conn_status) )
800 h->conn_status (h->conn_status_cls,
801 GNUNET_YES);
802 GNUNET_free (op);
803}
804
805
806/**
807 * Task run to notify application that ARM is being started.
808 *
809 * @param cls the operation that asked ARM to be started
810 */
811static void
812notify_starting (void *cls)
813{
814 struct GNUNET_ARM_Operation *op = cls;
815 struct GNUNET_ARM_Handle *h = op->h;
816
817 op->async = NULL;
1003 LOG (GNUNET_ERROR_TYPE_DEBUG, 818 LOG (GNUNET_ERROR_TYPE_DEBUG,
1004 "Inserting a control message into the queue. Timeout is %s\n", 819 "Notifying client that we started the ARM service\n");
1005 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (cm->timeout), 820 GNUNET_CONTAINER_DLL_remove (h->operation_pending_head,
1006 GNUNET_NO)); 821 h->operation_pending_tail,
1007 GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head, 822 op);
1008 h->control_pending_tail, 823 if (NULL != op->result_cont)
1009 cm); 824 op->result_cont (op->cont_cls,
1010 cm->timeout_task_id = 825 GNUNET_ARM_REQUEST_SENT_OK,
1011 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining 826 op->starting_ret);
1012 (cm->timeout), 827 GNUNET_free (op);
1013 &control_message_timeout,
1014 cm);
1015 trigger_next_request (h, GNUNET_NO);
1016} 828}
1017 829
1018 830
@@ -1022,132 +834,116 @@ change_service (struct GNUNET_ARM_Handle *h,
1022 * @param h handle to ARM 834 * @param h handle to ARM
1023 * @param service_name name of the service 835 * @param service_name name of the service
1024 * @param std_inheritance inheritance of std streams 836 * @param std_inheritance inheritance of std streams
1025 * @param timeout how long to wait before failing for good
1026 * @param cont callback to invoke after request is sent or not sent 837 * @param cont callback to invoke after request is sent or not sent
1027 * @param cont_cls closure for @a cont 838 * @param cont_cls closure for @a cont
839 * @return handle for the operation, NULL on error
1028 */ 840 */
1029void 841struct GNUNET_ARM_Operation *
1030GNUNET_ARM_request_service_start (struct GNUNET_ARM_Handle *h, 842GNUNET_ARM_request_service_start (struct GNUNET_ARM_Handle *h,
1031 const char *service_name, 843 const char *service_name,
1032 enum GNUNET_OS_InheritStdioFlags std_inheritance, 844 enum GNUNET_OS_InheritStdioFlags std_inheritance,
1033 struct GNUNET_TIME_Relative timeout,
1034 GNUNET_ARM_ResultCallback cont, 845 GNUNET_ARM_ResultCallback cont,
1035 void *cont_cls) 846 void *cont_cls)
1036{ 847{
1037 struct ARMControlMessage *cm; 848 struct GNUNET_ARM_Operation *op;
1038 size_t slen; 849 enum GNUNET_ARM_Result ret;
1039 850
1040 LOG (GNUNET_ERROR_TYPE_DEBUG, 851 LOG (GNUNET_ERROR_TYPE_DEBUG,
1041 "Asked to start service `%s' within %s\n", service_name, 852 "Starting service `%s'\n",
1042 GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_NO)); 853 service_name);
1043 if (0 == strcasecmp ("arm", service_name)) 854 if (0 != strcasecmp ("arm",
855 service_name))
856 return change_service (h,
857 service_name,
858 cont,
859 cont_cls,
860 GNUNET_MESSAGE_TYPE_ARM_START);
861
862 /* Possible cases:
863 * 1) We're connected to ARM already. Invoke the callback immediately.
864 * 2) We're not connected to ARM.
865 * Cancel any reconnection attempts temporarily, then perform
866 * a service test.
867 */
868 if (GNUNET_YES == h->currently_up)
1044 { 869 {
1045 /* Possible cases: 870 LOG (GNUNET_ERROR_TYPE_DEBUG,
1046 * 1) We're connected to ARM already. Invoke the callback immediately. 871 "ARM is already running\n");
1047 * 2) We're not connected to ARM. 872 op = GNUNET_new (struct GNUNET_ARM_Operation);
1048 * Cancel any reconnection attempts temporarily, then perform 873 op->h = h;
1049 * a service test. 874 op->result_cont = cont;
1050 */ 875 op->cont_cls = cont_cls;
1051 if (GNUNET_NO == h->currently_down) 876 GNUNET_CONTAINER_DLL_insert_tail (h->operation_pending_head,
1052 { 877 h->operation_pending_tail,
1053 LOG (GNUNET_ERROR_TYPE_DEBUG, 878 op);
1054 "ARM is already running\n"); 879 op->async = GNUNET_SCHEDULER_add_now (&notify_running,
1055 if (NULL != cont) 880 op);
1056 cont (cont_cls, 881 return op;
1057 GNUNET_ARM_REQUEST_SENT_OK, 882 }
1058 "arm", 883 /* This is an inherently uncertain choice, as it is of course
1059 GNUNET_ARM_RESULT_IS_STARTED_ALREADY); 884 theoretically possible that ARM is up and we just did not
1060 } 885 yet complete the MQ handshake. However, given that users
1061 else if (GNUNET_NO == h->service_test_is_active) 886 are unlikely to hammer 'gnunet-arm -s' on a busy system,
1062 { 887 the above check should catch 99.99% of the cases where ARM
1063 if (NULL != h->cth) 888 is already running. */
1064 { 889 LOG (GNUNET_ERROR_TYPE_DEBUG,
1065 GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth); 890 "Starting ARM service\n");
1066 h->cth = NULL; 891 ret = start_arm_service (h,
1067 } 892 std_inheritance);
1068 if (NULL != h->client) 893 if (GNUNET_ARM_RESULT_STARTING == ret)
1069 { 894 reconnect_arm (h);
1070 GNUNET_CLIENT_disconnect (h->client); 895 op = GNUNET_new (struct GNUNET_ARM_Operation);
1071 h->client = NULL; 896 op->h = h;
1072 } 897 op->result_cont = cont;
1073 if (NULL != h->reconnect_task) 898 op->cont_cls = cont_cls;
1074 { 899 GNUNET_CONTAINER_DLL_insert_tail (h->operation_pending_head,
1075 GNUNET_SCHEDULER_cancel (h->reconnect_task); 900 h->operation_pending_tail,
1076 h->reconnect_task = NULL; 901 op);
1077 } 902 op->starting_ret = ret;
1078 903 op->async = GNUNET_SCHEDULER_add_now (&notify_starting,
1079 LOG (GNUNET_ERROR_TYPE_DEBUG, 904 op);
1080 "Not connected to ARM, will do a service test\n"); 905 return op;
1081
1082 slen = strlen ("arm") + 1;
1083 cm = GNUNET_malloc (sizeof (struct ARMControlMessage) + slen);
1084 cm->h = h;
1085 cm->result_cont = cont;
1086 cm->cont_cls = cont_cls;
1087 cm->timeout = GNUNET_TIME_relative_to_absolute (timeout);
1088 cm->std_inheritance = std_inheritance;
1089 memcpy (&cm[1], service_name, slen);
1090 h->service_test_is_active = GNUNET_YES;
1091 GNUNET_CLIENT_service_test ("arm",
1092 h->cfg,
1093 timeout,
1094 &arm_service_report,
1095 cm);
1096 }
1097 else
1098 {
1099 /* Service test is already running - tell user to chill out and try
1100 * again later.
1101 */
1102 LOG (GNUNET_ERROR_TYPE_DEBUG,
1103 "Service test is already in progress, we're busy\n");
1104 if (NULL != cont)
1105 cont (cont_cls,
1106 GNUNET_ARM_REQUEST_BUSY,
1107 NULL, 0);
1108 }
1109 return;
1110 }
1111 change_service (h,
1112 service_name,
1113 timeout,
1114 cont, cont_cls,
1115 GNUNET_MESSAGE_TYPE_ARM_START);
1116} 906}
1117 907
1118 908
1119/** 909/**
1120 * Request a service to be stopped. 910 * Request a service to be stopped. Stopping arm itself will not
1121 * Stopping arm itself will not invalidate its handle, and 911 * invalidate its handle, and ARM API will try to restore connection
1122 * ARM API will try to restore connection to the ARM service, 912 * to the ARM service, even if ARM connection was lost because you
1123 * even if ARM connection was lost because you asked for ARM to be stopped. 913 * asked for ARM to be stopped. Call
1124 * Call #GNUNET_ARM_disconnect_and_free() to free the handle and prevent 914 * #GNUNET_ARM_disconnect() to free the handle and prevent
1125 * further connection attempts. 915 * further connection attempts.
1126 * 916 *
1127 * @param h handle to ARM 917 * @param h handle to ARM
1128 * @param service_name name of the service 918 * @param service_name name of the service
1129 * @param timeout how long to wait before failing for good
1130 * @param cont callback to invoke after request is sent or is not sent 919 * @param cont callback to invoke after request is sent or is not sent
1131 * @param cont_cls closure for @a cont 920 * @param cont_cls closure for @a cont
921 * @return handle for the operation, NULL on error
1132 */ 922 */
1133void 923struct GNUNET_ARM_Operation *
1134GNUNET_ARM_request_service_stop (struct GNUNET_ARM_Handle *h, 924GNUNET_ARM_request_service_stop (struct GNUNET_ARM_Handle *h,
1135 const char *service_name, 925 const char *service_name,
1136 struct GNUNET_TIME_Relative timeout,
1137 GNUNET_ARM_ResultCallback cont, 926 GNUNET_ARM_ResultCallback cont,
1138 void *cont_cls) 927 void *cont_cls)
1139{ 928{
929 struct GNUNET_ARM_Operation *op;
930
1140 LOG (GNUNET_ERROR_TYPE_DEBUG, 931 LOG (GNUNET_ERROR_TYPE_DEBUG,
1141 "Stopping service `%s' within %s\n", 932 "Stopping service `%s'\n",
1142 service_name, 933 service_name);
1143 GNUNET_STRINGS_relative_time_to_string (timeout, 934 op = change_service (h,
1144 GNUNET_NO)); 935 service_name,
1145 change_service (h, 936 cont,
1146 service_name, 937 cont_cls,
1147 timeout, 938 GNUNET_MESSAGE_TYPE_ARM_STOP);
1148 cont, 939 if (NULL == op)
1149 cont_cls, 940 return NULL;
1150 GNUNET_MESSAGE_TYPE_ARM_STOP); 941 /* If the service is ARM, set a flag as we will use MQ errors
942 to detect that the process is really gone. */
943 if (0 == strcasecmp (service_name,
944 "arm"))
945 op->is_arm_stop = GNUNET_YES;
946 return op;
1151} 947}
1152 948
1153 949
@@ -1155,43 +951,38 @@ GNUNET_ARM_request_service_stop (struct GNUNET_ARM_Handle *h,
1155 * Request a list of running services. 951 * Request a list of running services.
1156 * 952 *
1157 * @param h handle to ARM 953 * @param h handle to ARM
1158 * @param timeout how long to wait before failing for good
1159 * @param cont callback to invoke after request is sent or is not sent 954 * @param cont callback to invoke after request is sent or is not sent
1160 * @param cont_cls closure for @a cont 955 * @param cont_cls closure for @a cont
956 * @return handle for the operation, NULL on error
1161 */ 957 */
1162void 958struct GNUNET_ARM_Operation *
1163GNUNET_ARM_request_service_list (struct GNUNET_ARM_Handle *h, 959GNUNET_ARM_request_service_list (struct GNUNET_ARM_Handle *h,
1164 struct GNUNET_TIME_Relative timeout,
1165 GNUNET_ARM_ServiceListCallback cont, 960 GNUNET_ARM_ServiceListCallback cont,
1166 void *cont_cls) 961 void *cont_cls)
1167{ 962{
1168 struct ARMControlMessage *cm; 963 struct GNUNET_ARM_Operation *op;
964 struct GNUNET_MQ_Envelope *env;
1169 struct GNUNET_ARM_Message *msg; 965 struct GNUNET_ARM_Message *msg;
1170 966
1171 LOG (GNUNET_ERROR_TYPE_DEBUG, 967 LOG (GNUNET_ERROR_TYPE_DEBUG,
1172 "Requesting LIST from ARM service with timeout: %s\n", 968 "Requesting LIST from ARM service\n");
1173 GNUNET_STRINGS_relative_time_to_string (timeout, 969 if (0 == h->request_id_counter)
1174 GNUNET_YES)); 970 h->request_id_counter++;
1175 cm = GNUNET_new (struct ARMControlMessage); 971 op = GNUNET_new (struct GNUNET_ARM_Operation);
1176 cm->h = h; 972 op->h = h;
1177 cm->list_cont = cont; 973 op->list_cont = cont;
1178 cm->cont_cls = cont_cls; 974 op->cont_cls = cont_cls;
1179 cm->timeout = GNUNET_TIME_relative_to_absolute (timeout); 975 op->id = h->request_id_counter++;
1180 msg = GNUNET_malloc (sizeof (struct GNUNET_ARM_Message)); 976 GNUNET_CONTAINER_DLL_insert_tail (h->operation_pending_head,
1181 msg->header.size = htons (sizeof (struct GNUNET_ARM_Message)); 977 h->operation_pending_tail,
1182 msg->header.type = htons (GNUNET_MESSAGE_TYPE_ARM_LIST); 978 op);
979 env = GNUNET_MQ_msg (msg,
980 GNUNET_MESSAGE_TYPE_ARM_LIST);
1183 msg->reserved = htonl (0); 981 msg->reserved = htonl (0);
1184 cm->msg = msg; 982 msg->request_id = GNUNET_htonll (op->id);
1185 GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head, 983 GNUNET_MQ_send (h->mq,
1186 h->control_pending_tail, 984 env);
1187 cm); 985 return op;
1188 cm->timeout_task_id =
1189 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
1190 (cm->timeout),
1191 &control_message_timeout,
1192 cm);
1193 trigger_next_request (h,
1194 GNUNET_NO);
1195} 986}
1196 987
1197 988
diff --git a/src/arm/arm_monitor_api.c b/src/arm/arm_monitor_api.c
index 6d4129928..1f23c1dc5 100644
--- a/src/arm/arm_monitor_api.c
+++ b/src/arm/arm_monitor_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 GNUnet e.V. 3 Copyright (C) 2009, 2010, 2012, 2013, 2016 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -21,7 +21,8 @@
21/** 21/**
22 * @file arm/arm_monitor_api.c 22 * @file arm/arm_monitor_api.c
23 * @brief API for monitoring the ARM service 23 * @brief API for monitoring the ARM service
24 * @author Christian Grothoff, LRN 24 * @author Christian Grothoff
25 * @author LRN
25 */ 26 */
26#include "platform.h" 27#include "platform.h"
27#include "gnunet_arm_service.h" 28#include "gnunet_arm_service.h"
@@ -241,9 +242,9 @@ reconnect_arm_monitor (struct GNUNET_ARM_MonitorHandle *h)
241 * @return context to use for further ARM monitor operations, NULL on error. 242 * @return context to use for further ARM monitor operations, NULL on error.
242 */ 243 */
243struct GNUNET_ARM_MonitorHandle * 244struct GNUNET_ARM_MonitorHandle *
244GNUNET_ARM_monitor (const struct GNUNET_CONFIGURATION_Handle *cfg, 245GNUNET_ARM_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
245 GNUNET_ARM_ServiceStatusCallback cont, 246 GNUNET_ARM_ServiceStatusCallback cont,
246 void *cont_cls) 247 void *cont_cls)
247{ 248{
248 struct GNUNET_ARM_MonitorHandle *h; 249 struct GNUNET_ARM_MonitorHandle *h;
249 250
@@ -266,7 +267,7 @@ GNUNET_ARM_monitor (const struct GNUNET_CONFIGURATION_Handle *cfg,
266 * @param h the handle that was being used 267 * @param h the handle that was being used
267 */ 268 */
268void 269void
269GNUNET_ARM_monitor_disconnect_and_free (struct GNUNET_ARM_MonitorHandle *h) 270GNUNET_ARM_monitor_stop (struct GNUNET_ARM_MonitorHandle *h)
270{ 271{
271 if (NULL != h->mq) 272 if (NULL != h->mq)
272 { 273 {
diff --git a/src/arm/gnunet-arm.c b/src/arm/gnunet-arm.c
index 75ade59da..3b024ea93 100644
--- a/src/arm/gnunet-arm.c
+++ b/src/arm/gnunet-arm.c
@@ -29,28 +29,6 @@
29#include "gnunet_util_lib.h" 29#include "gnunet_util_lib.h"
30 30
31/** 31/**
32 * Timeout for stopping services. Long to give some services a real chance.
33 */
34#define STOP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
35
36/**
37 * Timeout for stopping ARM. Extra-long since ARM needs to stop everyone else.
38 */
39#define STOP_TIMEOUT_ARM GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
40
41/**
42 * Timeout for starting services, very short because of the strange way start works
43 * (by checking if running before starting, so really this time is always waited on
44 * startup (annoying)).
45 */
46#define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
47
48/**
49 * Timeout for listing all running services.
50 */
51#define LIST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
52
53/**
54 * Set if we are to shutdown all services (including ARM). 32 * Set if we are to shutdown all services (including ARM).
55 */ 33 */
56static int end; 34static int end;
@@ -132,6 +110,7 @@ static unsigned int phase;
132 110
133/** 111/**
134 * User defined timestamp for completing operations. 112 * User defined timestamp for completing operations.
113 * FIXME: to be implemented!
135 */ 114 */
136static struct GNUNET_TIME_Relative timeout; 115static struct GNUNET_TIME_Relative timeout;
137 116
@@ -150,6 +129,10 @@ static unsigned int no_stderr;
150 */ 129 */
151static struct GNUNET_SCHEDULER_Task *al_task; 130static struct GNUNET_SCHEDULER_Task *al_task;
152 131
132/**
133 * Current operation.
134 */
135static struct GNUNET_ARM_Operation *op;
153 136
154/** 137/**
155 * Attempts to delete configuration file and GNUNET_HOME 138 * Attempts to delete configuration file and GNUNET_HOME
@@ -193,14 +176,19 @@ shutdown_task (void *cls)
193 GNUNET_SCHEDULER_cancel (al_task); 176 GNUNET_SCHEDULER_cancel (al_task);
194 al_task = NULL; 177 al_task = NULL;
195 } 178 }
179 if (NULL != op)
180 {
181 GNUNET_ARM_operation_cancel (op);
182 op = NULL;
183 }
196 if (NULL != h) 184 if (NULL != h)
197 { 185 {
198 GNUNET_ARM_disconnect_and_free (h); 186 GNUNET_ARM_disconnect (h);
199 h = NULL; 187 h = NULL;
200 } 188 }
201 if (NULL != m) 189 if (NULL != m)
202 { 190 {
203 GNUNET_ARM_monitor_disconnect_and_free (m); 191 GNUNET_ARM_monitor_stop (m);
204 m = NULL; 192 m = NULL;
205 } 193 }
206 if ((GNUNET_YES == end) && (GNUNET_YES == delete)) 194 if ((GNUNET_YES == end) && (GNUNET_YES == delete))
@@ -229,8 +217,6 @@ req_string (enum GNUNET_ARM_RequestStatus rs)
229 return _("We disconnected from ARM before we could send a request"); 217 return _("We disconnected from ARM before we could send a request");
230 case GNUNET_ARM_REQUEST_BUSY: 218 case GNUNET_ARM_REQUEST_BUSY:
231 return _("ARM API is busy"); 219 return _("ARM API is busy");
232 case GNUNET_ARM_REQUEST_TOO_LONG:
233 return _("Request does not fit into a message");
234 case GNUNET_ARM_REQUEST_TIMEOUT: 220 case GNUNET_ARM_REQUEST_TIMEOUT:
235 return _("Request timed out"); 221 return _("Request timed out");
236 } 222 }
@@ -289,8 +275,8 @@ action_loop (void *cls);
289 * our first attempt. 275 * our first attempt.
290 * 276 *
291 * @param cls closure 277 * @param cls closure
292 * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected, 278 * @param connected #GNUNET_YES if connected, #GNUNET_NO if disconnected,
293 * GNUNET_SYSERR on error. 279 * #GNUNET_SYSERR on error.
294 */ 280 */
295static void 281static void
296conn_status (void *cls, 282conn_status (void *cls,
@@ -318,18 +304,17 @@ conn_status (void *cls,
318 * 304 *
319 * @param cls closure unused 305 * @param cls closure unused
320 * @param rs what happened to our request 306 * @param rs what happened to our request
321 * @param service name of the service we tried to start ("arm")
322 * @param result if the request was processed, this is the result 307 * @param result if the request was processed, this is the result
323 * according to ARM 308 * according to ARM
324 */ 309 */
325static void 310static void
326start_callback (void *cls, 311start_callback (void *cls,
327 enum GNUNET_ARM_RequestStatus rs, 312 enum GNUNET_ARM_RequestStatus rs,
328 const char *service,
329 enum GNUNET_ARM_Result result) 313 enum GNUNET_ARM_Result result)
330{ 314{
331 char *msg; 315 char *msg;
332 316
317 op = NULL;
333 if (GNUNET_ARM_REQUEST_SENT_OK != rs) 318 if (GNUNET_ARM_REQUEST_SENT_OK != rs)
334 { 319 {
335 GNUNET_asprintf (&msg, "%s", _("Failed to start the ARM service: %s\n")); 320 GNUNET_asprintf (&msg, "%s", _("Failed to start the ARM service: %s\n"));
@@ -362,18 +347,17 @@ start_callback (void *cls,
362 * 347 *
363 * @param cls closure unused 348 * @param cls closure unused
364 * @param rs what happened to our request 349 * @param rs what happened to our request
365 * @param service name of the service we tried to start ("arm")
366 * @param result if the request was processed, this is the result 350 * @param result if the request was processed, this is the result
367 * according to ARM 351 * according to ARM
368 */ 352 */
369static void 353static void
370stop_callback (void *cls, 354stop_callback (void *cls,
371 enum GNUNET_ARM_RequestStatus rs, 355 enum GNUNET_ARM_RequestStatus rs,
372 const char *service,
373 enum GNUNET_ARM_Result result) 356 enum GNUNET_ARM_Result result)
374{ 357{
375 char *msg; 358 char *msg;
376 359
360 op = NULL;
377 if (GNUNET_ARM_REQUEST_SENT_OK != rs) 361 if (GNUNET_ARM_REQUEST_SENT_OK != rs)
378 { 362 {
379 GNUNET_asprintf (&msg, "%s", 363 GNUNET_asprintf (&msg, "%s",
@@ -416,18 +400,17 @@ stop_callback (void *cls,
416 * 400 *
417 * @param cls closure unused 401 * @param cls closure unused
418 * @param rs what happened to our request 402 * @param rs what happened to our request
419 * @param service name of the service we tried to start
420 * @param result if the request was processed, this is the result 403 * @param result if the request was processed, this is the result
421 * according to ARM 404 * according to ARM
422 */ 405 */
423static void 406static void
424init_callback (void *cls, 407init_callback (void *cls,
425 enum GNUNET_ARM_RequestStatus rs, 408 enum GNUNET_ARM_RequestStatus rs,
426 const char *service,
427 enum GNUNET_ARM_Result result) 409 enum GNUNET_ARM_Result result)
428{ 410{
429 char *msg; 411 char *msg;
430 412
413 op = NULL;
431 if (GNUNET_ARM_REQUEST_SENT_OK != rs) 414 if (GNUNET_ARM_REQUEST_SENT_OK != rs)
432 { 415 {
433 GNUNET_asprintf (&msg, 416 GNUNET_asprintf (&msg,
@@ -441,9 +424,11 @@ init_callback (void *cls,
441 if ((GNUNET_ARM_RESULT_STARTING != result) && 424 if ((GNUNET_ARM_RESULT_STARTING != result) &&
442 (GNUNET_ARM_RESULT_IS_STARTED_ALREADY != result)) 425 (GNUNET_ARM_RESULT_IS_STARTED_ALREADY != result))
443 { 426 {
444 GNUNET_asprintf (&msg, _("Failed to start the `%s' service: %s\n"), 427 GNUNET_asprintf (&msg,
445 init, ret_string (result)); 428 _("Failed to start the `%s' service: %s\n"),
446 FPRINTF (stdout, msg, service); 429 init,
430 ret_string (result));
431 FPRINTF (stdout, "%s", msg);
447 GNUNET_free (msg); 432 GNUNET_free (msg);
448 GNUNET_SCHEDULER_shutdown (); 433 GNUNET_SCHEDULER_shutdown ();
449 return; 434 return;
@@ -465,17 +450,17 @@ init_callback (void *cls,
465 * 450 *
466 * @param cls closure unused 451 * @param cls closure unused
467 * @param rs what happened to our request 452 * @param rs what happened to our request
468 * @param service name of the service we tried to start
469 * @param result if the request was processed, this is the result 453 * @param result if the request was processed, this is the result
470 * according to ARM 454 * according to ARM
471 */ 455 */
472static void 456static void
473term_callback (void *cls, 457term_callback (void *cls,
474 enum GNUNET_ARM_RequestStatus rs, 458 enum GNUNET_ARM_RequestStatus rs,
475 const char *service,
476 enum GNUNET_ARM_Result result) 459 enum GNUNET_ARM_Result result)
477{ 460{
478 char *msg; 461 char *msg;
462
463 op = NULL;
479 if (GNUNET_ARM_REQUEST_SENT_OK != rs) 464 if (GNUNET_ARM_REQUEST_SENT_OK != rs)
480 { 465 {
481 GNUNET_asprintf (&msg, 466 GNUNET_asprintf (&msg,
@@ -492,7 +477,7 @@ term_callback (void *cls,
492 GNUNET_asprintf (&msg, 477 GNUNET_asprintf (&msg,
493 _("Failed to kill the `%s' service: %s\n"), 478 _("Failed to kill the `%s' service: %s\n"),
494 term, ret_string (result)); 479 term, ret_string (result));
495 FPRINTF (stdout, msg, service); 480 FPRINTF (stdout, "%s", msg);
496 GNUNET_free (msg); 481 GNUNET_free (msg);
497 GNUNET_SCHEDULER_shutdown (); 482 GNUNET_SCHEDULER_shutdown ();
498 return; 483 return;
@@ -525,6 +510,7 @@ list_callback (void *cls,
525{ 510{
526 unsigned int i; 511 unsigned int i;
527 512
513 op = NULL;
528 if (GNUNET_ARM_REQUEST_SENT_OK != rs) 514 if (GNUNET_ARM_REQUEST_SENT_OK != rs)
529 { 515 {
530 char *msg; 516 char *msg;
@@ -573,9 +559,10 @@ action_loop (void *cls)
573 { 559 {
574 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 560 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
575 "Termination action\n"); 561 "Termination action\n");
576 GNUNET_ARM_request_service_stop (h, term, 562 op = GNUNET_ARM_request_service_stop (h,
577 (0 == timeout.rel_value_us) ? STOP_TIMEOUT : timeout, 563 term,
578 &term_callback, NULL); 564 &term_callback,
565 NULL);
579 return; 566 return;
580 } 567 }
581 break; 568 break;
@@ -584,9 +571,10 @@ action_loop (void *cls)
584 { 571 {
585 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 572 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
586 "End action\n"); 573 "End action\n");
587 GNUNET_ARM_request_service_stop (h, "arm", 574 op = GNUNET_ARM_request_service_stop (h,
588 (0 == timeout.rel_value_us) ? STOP_TIMEOUT_ARM : timeout, 575 "arm",
589 &stop_callback, NULL); 576 &stop_callback,
577 NULL);
590 return; 578 return;
591 } 579 }
592 break; 580 break;
@@ -595,11 +583,11 @@ action_loop (void *cls)
595 { 583 {
596 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 584 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
597 "Start action\n"); 585 "Start action\n");
598 GNUNET_ARM_request_service_start (h, "arm", 586 op = GNUNET_ARM_request_service_start (h, "arm",
599 (no_stdout ? 0 : GNUNET_OS_INHERIT_STD_OUT) | 587 (no_stdout ? 0 : GNUNET_OS_INHERIT_STD_OUT) |
600 (no_stderr ? 0 : GNUNET_OS_INHERIT_STD_ERR), 588 (no_stderr ? 0 : GNUNET_OS_INHERIT_STD_ERR),
601 (0 == timeout.rel_value_us) ? START_TIMEOUT: timeout, 589 &start_callback,
602 start_callback, NULL); 590 NULL);
603 return; 591 return;
604 } 592 }
605 break; 593 break;
@@ -608,10 +596,10 @@ action_loop (void *cls)
608 { 596 {
609 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 597 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
610 "Initialization action\n"); 598 "Initialization action\n");
611 GNUNET_ARM_request_service_start (h, init, 599 op = GNUNET_ARM_request_service_start (h, init,
612 GNUNET_OS_INHERIT_STD_NONE, 600 GNUNET_OS_INHERIT_STD_NONE,
613 (0 == timeout.rel_value_us) ? STOP_TIMEOUT : timeout, 601 &init_callback,
614 &init_callback, NULL); 602 NULL);
615 return; 603 return;
616 } 604 }
617 break; 605 break;
@@ -620,9 +608,9 @@ action_loop (void *cls)
620 { 608 {
621 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 609 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
622 "Going to list all running services controlled by ARM.\n"); 610 "Going to list all running services controlled by ARM.\n");
623 GNUNET_ARM_request_service_list (h, 611 op = GNUNET_ARM_request_service_list (h,
624 (0 == timeout.rel_value_us) ? LIST_TIMEOUT : timeout, 612 &list_callback,
625 &list_callback, &list); 613 &list);
626 return; 614 return;
627 } 615 }
628 break; 616 break;
@@ -676,13 +664,21 @@ srv_status (void *cls,
676 break; 664 break;
677 } 665 }
678 if (! quiet) 666 if (! quiet)
679 { 667 {
680 if (NULL != msg) 668 if (NULL != msg)
681 FPRINTF (stderr, msg, service); 669 FPRINTF (stderr,
682 else 670 msg,
683 FPRINTF (stderr, _("Unknown status %u for service %s.\n"), status, service); 671 service);
684 } 672 else
685 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got service %s status %d\n", service, (int) status); 673 FPRINTF (stderr,
674 _("Unknown status %u for service %s.\n"),
675 status,
676 service);
677 }
678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
679 "Got service %s status %d\n",
680 service, (int)
681 status);
686} 682}
687 683
688 684
@@ -705,30 +701,44 @@ run (void *cls,
705 cfg = GNUNET_CONFIGURATION_dup (c); 701 cfg = GNUNET_CONFIGURATION_dup (c);
706 config_file = cfgfile; 702 config_file = cfgfile;
707 if (GNUNET_OK != 703 if (GNUNET_OK !=
708 GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "GNUNET_HOME", &dir)) 704 GNUNET_CONFIGURATION_get_value_string (cfg,
705 "PATHS",
706 "GNUNET_HOME",
707 &dir))
709 { 708 {
710 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, 709 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
711 "PATHS", "GNUNET_HOME"); 710 "PATHS",
711 "GNUNET_HOME");
712 return; 712 return;
713 } 713 }
714 if (NULL != cfgfile) 714 if (NULL != cfgfile)
715 { 715 {
716 if (GNUNET_OK != 716 if (GNUNET_OK !=
717 GNUNET_CONFIGURATION_get_value_filename (cfg, "arm", "CONFIG", 717 GNUNET_CONFIGURATION_get_value_filename (cfg,
718 "arm",
719 "CONFIG",
718 &armconfig)) 720 &armconfig))
719 { 721 {
720 GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG", 722 GNUNET_CONFIGURATION_set_value_string (cfg,
723 "arm",
724 "CONFIG",
721 cfgfile); 725 cfgfile);
722 } 726 }
723 else 727 else
724 GNUNET_free (armconfig); 728 GNUNET_free (armconfig);
725 } 729 }
726 if (NULL == (h = GNUNET_ARM_connect (cfg, &conn_status, NULL))) 730 if (NULL == (h = GNUNET_ARM_connect (cfg,
731 &conn_status,
732 NULL)))
727 return; 733 return;
728 if (monitor) 734 if (monitor)
729 m = GNUNET_ARM_monitor (cfg, &srv_status, NULL); 735 m = GNUNET_ARM_monitor_start (cfg,
730 al_task = GNUNET_SCHEDULER_add_now (&action_loop, NULL); 736 &srv_status,
731 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); 737 NULL);
738 al_task = GNUNET_SCHEDULER_add_now (&action_loop,
739 NULL);
740 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
741 NULL);
732} 742}
733 743
734 744
@@ -774,7 +784,8 @@ main (int argc, char *const *argv)
774 GNUNET_GETOPT_OPTION_END 784 GNUNET_GETOPT_OPTION_END
775 }; 785 };
776 786
777 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 787 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv,
788 &argc, &argv))
778 return 2; 789 return 2;
779 790
780 if (GNUNET_OK == 791 if (GNUNET_OK ==
diff --git a/src/arm/test_arm_api.c b/src/arm/test_arm_api.c
index f5283d714..0449c41d4 100644
--- a/src/arm/test_arm_api.c
+++ b/src/arm/test_arm_api.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2009, 2011 GNUnet e.V. 3 Copyright (C) 2009, 2011, 2016 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -28,60 +28,64 @@
28 28
29#define LOG(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) 29#define LOG(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
30 30
31#define START_ARM GNUNET_YES
32
33#define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 1500)
34
35#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) 31#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
36 32
37static const struct GNUNET_CONFIGURATION_Handle *cfg; 33static const struct GNUNET_CONFIGURATION_Handle *cfg;
38 34
39static struct GNUNET_ARM_Handle *arm; 35static struct GNUNET_ARM_Handle *arm;
40 36
37static struct GNUNET_ARM_Operation *op;
38
41static int ok = 1; 39static int ok = 1;
42 40
43static int phase = 0; 41static int phase = 0;
44 42
43
45static void 44static void
46arm_stop_cb (void *cls, 45arm_stop_cb (void *cls,
47 enum GNUNET_ARM_RequestStatus status, 46 enum GNUNET_ARM_RequestStatus status,
48 const char *servicename,
49 enum GNUNET_ARM_Result result) 47 enum GNUNET_ARM_Result result)
50{ 48{
49 op = NULL;
51 /* (6), a stop request should be sent to ARM successfully */ 50 /* (6), a stop request should be sent to ARM successfully */
52 /* ARM should report that it is stopping */ 51 /* ARM should report that it is stopping */
53 GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK); 52 GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK);
54 GNUNET_break (result == GNUNET_ARM_RESULT_STOPPED); 53 GNUNET_break (result == GNUNET_ARM_RESULT_STOPPED);
55 GNUNET_break (phase == 6); 54 GNUNET_break (phase == 6);
56 phase++; 55 phase++;
57 LOG ("Sent 'STOP' request for arm to ARM %s\n", (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully"); 56 LOG ("Sent 'STOP' request for arm to ARM %s\n",
57 (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully");
58 GNUNET_SCHEDULER_shutdown ();
58} 59}
59 60
60 61
61static void 62static void
62resolver_stop_cb (void *cls, 63resolver_stop_cb (void *cls,
63 enum GNUNET_ARM_RequestStatus status, 64 enum GNUNET_ARM_RequestStatus status,
64 const char *servicename, enum GNUNET_ARM_Result result) 65 enum GNUNET_ARM_Result result)
65{ 66{
67 op = NULL;
66 /* (5), a stop request should be sent to ARM successfully. 68 /* (5), a stop request should be sent to ARM successfully.
67 * ARM should report that resolver is stopped. 69 * ARM should report that resolver is stopped.
68 */ 70 */
69 GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK); 71 GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK);
70 GNUNET_break (result == GNUNET_ARM_RESULT_STOPPED); 72 GNUNET_break (result == GNUNET_ARM_RESULT_STOPPED);
71 GNUNET_break (phase == 5); 73 GNUNET_break (phase == 5);
72 LOG ("Sent 'STOP' request for resolver to ARM %s\n", (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully"); 74 LOG ("Sent 'STOP' request for resolver to ARM %s\n",
75 (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully");
73 phase++; 76 phase++;
74#if START_ARM 77 GNUNET_assert (NULL == op);
75 GNUNET_ARM_request_service_stop (arm, "arm", TIMEOUT, arm_stop_cb, NULL); 78 op = GNUNET_ARM_request_service_stop (arm,
76#else 79 "arm",
77 arm_stop_cb (NULL, GNUNET_ARM_STATUS_SENT_OK, "arm", GNUNET_ARM_SERVICE_STOPPING); 80 &arm_stop_cb,
78 arm_conn (NULL, GNUNET_NO); 81 NULL);
79#endif
80} 82}
81 83
82 84
83static void 85static void
84dns_notify (void *cls, const struct sockaddr *addr, socklen_t addrlen) 86dns_notify (void *cls,
87 const struct sockaddr *addr,
88 socklen_t addrlen)
85{ 89{
86 if (addr == NULL) 90 if (addr == NULL)
87 { 91 {
@@ -91,7 +95,11 @@ dns_notify (void *cls, const struct sockaddr *addr, socklen_t addrlen)
91 LOG ("Finished resolving localhost\n"); 95 LOG ("Finished resolving localhost\n");
92 if (ok != 0) 96 if (ok != 0)
93 ok = 2; 97 ok = 2;
94 GNUNET_ARM_request_service_stop (arm, "resolver", TIMEOUT, resolver_stop_cb, NULL); 98 GNUNET_assert (NULL == op);
99 op = GNUNET_ARM_request_service_stop (arm,
100 "resolver",
101 &resolver_stop_cb,
102 NULL);
95 return; 103 return;
96 } 104 }
97 /* (3), resolver should resolve localhost */ 105 /* (3), resolver should resolve localhost */
@@ -106,25 +114,22 @@ dns_notify (void *cls, const struct sockaddr *addr, socklen_t addrlen)
106static void 114static void
107resolver_start_cb (void *cls, 115resolver_start_cb (void *cls,
108 enum GNUNET_ARM_RequestStatus status, 116 enum GNUNET_ARM_RequestStatus status,
109 const char *servicename,
110 enum GNUNET_ARM_Result result) 117 enum GNUNET_ARM_Result result)
111{ 118{
119 op = NULL;
112 /* (2), the start request for resolver should be sent successfully 120 /* (2), the start request for resolver should be sent successfully
113 * ARM should report that resolver service is starting. 121 * ARM should report that resolver service is starting.
114 */ 122 */
115 GNUNET_assert (status == GNUNET_ARM_REQUEST_SENT_OK); 123 GNUNET_assert (status == GNUNET_ARM_REQUEST_SENT_OK);
116 GNUNET_break (phase == 2); 124 GNUNET_break (phase == 2);
117 GNUNET_break (result == GNUNET_ARM_RESULT_STARTING); 125 GNUNET_break (result == GNUNET_ARM_RESULT_STARTING);
118 LOG ("Sent 'START' request for resolver to ARM %s\n", (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully"); 126 LOG ("Sent 'START' request for resolver to ARM %s\n",
127 (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully");
119 phase++; 128 phase++;
120 GNUNET_RESOLVER_ip_get ("localhost", AF_INET, TIMEOUT, &dns_notify, NULL); 129 GNUNET_RESOLVER_ip_get ("localhost",
121} 130 AF_INET,
122 131 TIMEOUT,
123 132 &dns_notify, NULL);
124static void
125trigger_disconnect (void *cls)
126{
127 GNUNET_ARM_disconnect_and_free ((struct GNUNET_ARM_Handle *) cls);
128} 133}
129 134
130 135
@@ -146,7 +151,12 @@ arm_conn (void *cls,
146 LOG ("Connected to ARM\n"); 151 LOG ("Connected to ARM\n");
147 GNUNET_break (phase == 1); 152 GNUNET_break (phase == 1);
148 phase++; 153 phase++;
149 GNUNET_ARM_request_service_start (arm, "resolver", GNUNET_OS_INHERIT_STD_OUT_AND_ERR, START_TIMEOUT, resolver_start_cb, NULL); 154 GNUNET_assert (NULL == op);
155 op = GNUNET_ARM_request_service_start (arm,
156 "resolver",
157 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
158 &resolver_start_cb,
159 NULL);
150 } 160 }
151 else 161 else
152 { 162 {
@@ -157,7 +167,6 @@ arm_conn (void *cls,
157 ok = 3; 167 ok = 3;
158 else if (ok == 1) 168 else if (ok == 1)
159 ok = 0; 169 ok = 0;
160 GNUNET_SCHEDULER_add_now (&trigger_disconnect, arm);
161 } 170 }
162} 171}
163 172
@@ -165,9 +174,9 @@ arm_conn (void *cls,
165static void 174static void
166arm_start_cb (void *cls, 175arm_start_cb (void *cls,
167 enum GNUNET_ARM_RequestStatus status, 176 enum GNUNET_ARM_RequestStatus status,
168 const char *servicename,
169 enum GNUNET_ARM_Result result) 177 enum GNUNET_ARM_Result result)
170{ 178{
179 op = NULL;
171 /* (0) The request should be "sent" successfully 180 /* (0) The request should be "sent" successfully
172 * ("sent", because it isn't going anywhere, ARM API starts ARM service 181 * ("sent", because it isn't going anywhere, ARM API starts ARM service
173 * by itself). 182 * by itself).
@@ -175,26 +184,48 @@ arm_start_cb (void *cls,
175 */ 184 */
176 GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK); 185 GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK);
177 GNUNET_break (phase == 0); 186 GNUNET_break (phase == 0);
178 LOG ("Sent 'START' request for arm to ARM %s\n", (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully"); 187 LOG ("Sent 'START' request for arm to ARM %s\n",
188 (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully");
179 GNUNET_break (result == GNUNET_ARM_RESULT_STARTING); 189 GNUNET_break (result == GNUNET_ARM_RESULT_STARTING);
180 phase++; 190 phase++;
181} 191}
182 192
183 193
184static void 194static void
185task (void *cls, char *const *args, const char *cfgfile, 195do_shutdown (void *cls)
196{
197 if (NULL != op)
198 {
199 GNUNET_ARM_operation_cancel (op);
200 op = NULL;
201 }
202 if (NULL != arm)
203 {
204 GNUNET_ARM_disconnect (arm);
205 arm = NULL;
206 }
207}
208
209
210static void
211task (void *cls,
212 char *const *args,
213 const char *cfgfile,
186 const struct GNUNET_CONFIGURATION_Handle *c) 214 const struct GNUNET_CONFIGURATION_Handle *c)
187{ 215{
188 cfg = c; 216 cfg = c;
189 arm = GNUNET_ARM_connect (cfg, &arm_conn, NULL); 217 arm = GNUNET_ARM_connect (cfg,
218 &arm_conn,
219 NULL);
190 if (NULL == arm) 220 if (NULL == arm)
191 return; 221 return;
192#if START_ARM 222 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
193 GNUNET_ARM_request_service_start (arm, "arm", GNUNET_OS_INHERIT_STD_OUT_AND_ERR, START_TIMEOUT, arm_start_cb, NULL); 223 NULL);
194#else 224 op = GNUNET_ARM_request_service_start (arm,
195 arm_start_cb (NULL, arm, GNUNET_ARM_REQUEST_SENT_OK, "arm", GNUNET_ARM_RESULT_STARTING); 225 "arm",
196 arm_conn (NULL, arm, GNUNET_YES); 226 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
197#endif 227 &arm_start_cb,
228 NULL);
198} 229}
199 230
200 231
diff --git a/src/arm/test_exponential_backoff.c b/src/arm/test_exponential_backoff.c
index 3f33c91e6..8135f5157 100644
--- a/src/arm/test_exponential_backoff.c
+++ b/src/arm/test_exponential_backoff.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 GNUnet e.V. 3 Copyright (C) 2009, 2016 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -70,7 +70,9 @@ static char *killLogFileName;
70#endif 70#endif
71 71
72 72
73typedef void (*GNUNET_CLIENT_ShutdownTask) (void *cls, int reason); 73typedef void
74(*GNUNET_CLIENT_ShutdownTask) (void *cls, int reason);
75
74 76
75/** 77/**
76 * Context for handling the shutdown of a service. 78 * Context for handling the shutdown of a service.
@@ -118,7 +120,8 @@ struct ShutdownContext
118 * @param msg NULL, indicating socket closure. 120 * @param msg NULL, indicating socket closure.
119 */ 121 */
120static void 122static void
121service_shutdown_handler (void *cls, const struct GNUNET_MessageHeader *msg) 123service_shutdown_handler (void *cls,
124 const struct GNUNET_MessageHeader *msg)
122{ 125{
123 struct ShutdownContext *shutdown_ctx = cls; 126 struct ShutdownContext *shutdown_ctx = cls;
124 127
@@ -147,7 +150,8 @@ service_shutdown_cancel (void *cls)
147{ 150{
148 struct ShutdownContext *shutdown_ctx = cls; 151 struct ShutdownContext *shutdown_ctx = cls;
149 152
150 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "service_shutdown_cancel called!\n"); 153 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
154 "service_shutdown_cancel called!\n");
151 shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR); 155 shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR);
152 GNUNET_CLIENT_disconnect (shutdown_ctx->sock); 156 GNUNET_CLIENT_disconnect (shutdown_ctx->sock);
153 GNUNET_free (shutdown_ctx); 157 GNUNET_free (shutdown_ctx);
@@ -207,8 +211,9 @@ write_shutdown (void *cls, size_t size, void *buf)
207 */ 211 */
208static void 212static void
209do_nothing_service_shutdown (struct GNUNET_CLIENT_Connection *sock, 213do_nothing_service_shutdown (struct GNUNET_CLIENT_Connection *sock,
210 struct GNUNET_TIME_Relative timeout, 214 struct GNUNET_TIME_Relative timeout,
211 GNUNET_CLIENT_ShutdownTask cont, void *cont_cls) 215 GNUNET_CLIENT_ShutdownTask cont,
216 void *cont_cls)
212{ 217{
213 struct ShutdownContext *shutdown_ctx; 218 struct ShutdownContext *shutdown_ctx;
214 219
@@ -266,7 +271,10 @@ kill_task (void *cbData)
266 else if (trialCount == 13) 271 else if (trialCount == 13)
267 { 272 {
268 GNUNET_CLIENT_disconnect (doNothingConnection); 273 GNUNET_CLIENT_disconnect (doNothingConnection);
269 GNUNET_ARM_request_service_stop (arm, SERVICE, TIMEOUT, NULL, NULL); 274 GNUNET_ARM_request_service_stop (arm,
275 SERVICE,
276 NULL,
277 NULL);
270 if (waitedFor_prev.rel_value_us >= waitedFor.rel_value_us) 278 if (waitedFor_prev.rel_value_us >= waitedFor.rel_value_us)
271 ok = 9; 279 ok = 9;
272 else 280 else
@@ -284,15 +292,14 @@ kill_task (void *cbData)
284static void 292static void
285trigger_disconnect (void *cls) 293trigger_disconnect (void *cls)
286{ 294{
287 GNUNET_ARM_disconnect_and_free (arm); 295 GNUNET_ARM_disconnect (arm);
288 GNUNET_ARM_monitor_disconnect_and_free (mon); 296 GNUNET_ARM_monitor_stop (mon);
289} 297}
290 298
291 299
292static void 300static void
293arm_stop_cb (void *cls, 301arm_stop_cb (void *cls,
294 enum GNUNET_ARM_RequestStatus status, 302 enum GNUNET_ARM_RequestStatus status,
295 const char *servicename,
296 enum GNUNET_ARM_Result result) 303 enum GNUNET_ARM_Result result)
297{ 304{
298 GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK); 305 GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK);
@@ -303,14 +310,19 @@ arm_stop_cb (void *cls,
303 310
304 311
305static void 312static void
306srv_status (void *cls, const char *service, enum GNUNET_ARM_ServiceStatus status) 313srv_status (void *cls,
314 const char *service,
315 enum GNUNET_ARM_ServiceStatus status)
307{ 316{
308 LOG ("Service %s is %u, phase %u\n", service, status, phase); 317 LOG ("Service %s is %u, phase %u\n", service, status, phase);
309 if (status == GNUNET_ARM_SERVICE_MONITORING_STARTED) 318 if (status == GNUNET_ARM_SERVICE_MONITORING_STARTED)
310 { 319 {
311 phase++; 320 phase++;
312 GNUNET_ARM_request_service_start (arm, SERVICE, 321 GNUNET_ARM_request_service_start (arm,
313 GNUNET_OS_INHERIT_STD_OUT_AND_ERR, TIMEOUT, NULL, NULL); 322 SERVICE,
323 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
324 NULL,
325 NULL);
314 return; 326 return;
315 } 327 }
316 if (phase == 1) 328 if (phase == 1)
@@ -322,7 +334,8 @@ srv_status (void *cls, const char *service, enum GNUNET_ARM_ServiceStatus status
322 phase++; 334 phase++;
323 ok = 1; 335 ok = 1;
324 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, 336 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
325 &kill_task, NULL); 337 &kill_task,
338 NULL);
326 } 339 }
327 else if ((phase == 2) && (strcasecmp (SERVICE, service) == 0)) 340 else if ((phase == 2) && (strcasecmp (SERVICE, service) == 0))
328 { 341 {
@@ -337,14 +350,19 @@ srv_status (void *cls, const char *service, enum GNUNET_ARM_ServiceStatus status
337 else if ((status == GNUNET_ARM_SERVICE_STOPPED) && (trialCount == 14)) 350 else if ((status == GNUNET_ARM_SERVICE_STOPPED) && (trialCount == 14))
338 { 351 {
339 phase++; 352 phase++;
340 GNUNET_ARM_request_service_stop (arm, "arm", TIMEOUT, arm_stop_cb, NULL); 353 GNUNET_ARM_request_service_stop (arm,
354 "arm",
355 &arm_stop_cb,
356 NULL);
341 } 357 }
342 } 358 }
343} 359}
344 360
345 361
346static void 362static void
347arm_start_cb (void *cls, enum GNUNET_ARM_RequestStatus status, const char *servicename, enum GNUNET_ARM_Result result) 363arm_start_cb (void *cls,
364 enum GNUNET_ARM_RequestStatus status,
365 enum GNUNET_ARM_Result result)
348{ 366{
349 GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK); 367 GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK);
350 GNUNET_break (result == GNUNET_ARM_RESULT_STARTING); 368 GNUNET_break (result == GNUNET_ARM_RESULT_STARTING);
@@ -355,26 +373,34 @@ arm_start_cb (void *cls, enum GNUNET_ARM_RequestStatus status, const char *servi
355 373
356 374
357static void 375static void
358task (void *cls, char *const *args, const char *cfgfile, 376task (void *cls,
377 char *const *args,
378 const char *cfgfile,
359 const struct GNUNET_CONFIGURATION_Handle *c) 379 const struct GNUNET_CONFIGURATION_Handle *c)
360{ 380{
361 cfg = c; 381 cfg = c;
362 arm = GNUNET_ARM_connect (cfg, NULL, NULL); 382 arm = GNUNET_ARM_connect (cfg, NULL, NULL);
363 if (NULL != arm) 383 if (NULL != arm)
364 { 384 {
365 mon = GNUNET_ARM_monitor (cfg, &srv_status, NULL); 385 mon = GNUNET_ARM_monitor_start (cfg, &srv_status, NULL);
366 if (NULL != mon) 386 if (NULL != mon)
367 { 387 {
368#if START_ARM 388#if START_ARM
369 GNUNET_ARM_request_service_start (arm, "arm", 389 GNUNET_ARM_request_service_start (arm,
370 GNUNET_OS_INHERIT_STD_OUT_AND_ERR, GNUNET_TIME_UNIT_ZERO, arm_start_cb, NULL); 390 "arm",
391 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
392 &arm_start_cb,
393 NULL);
371#else 394#else
372 arm_start_cb (NULL, arm, GNUNET_ARM_REQUEST_SENT_OK, "arm", GNUNET_ARM_SERVICE_STARTING); 395 arm_start_cb (NULL,
396 arm,
397 GNUNET_ARM_REQUEST_SENT_OK,
398 GNUNET_ARM_SERVICE_STARTING);
373#endif 399#endif
374 } 400 }
375 else 401 else
376 { 402 {
377 GNUNET_ARM_disconnect_and_free (arm); 403 GNUNET_ARM_disconnect (arm);
378 arm = NULL; 404 arm = NULL;
379 } 405 }
380 } 406 }
diff --git a/src/arm/test_gnunet_service_arm.c b/src/arm/test_gnunet_service_arm.c
index 33662e579..71bf55084 100644
--- a/src/arm/test_gnunet_service_arm.c
+++ b/src/arm/test_gnunet_service_arm.c
@@ -51,7 +51,7 @@ static struct GNUNET_ARM_Handle *arm;
51static void 51static void
52trigger_disconnect (void *cls) 52trigger_disconnect (void *cls)
53{ 53{
54 GNUNET_ARM_disconnect_and_free (arm); 54 GNUNET_ARM_disconnect (arm);
55 arm = NULL; 55 arm = NULL;
56} 56}
57 57
@@ -59,7 +59,6 @@ trigger_disconnect (void *cls)
59static void 59static void
60arm_stop_cb (void *cls, 60arm_stop_cb (void *cls,
61 enum GNUNET_ARM_RequestStatus status, 61 enum GNUNET_ARM_RequestStatus status,
62 const char *servicename,
63 enum GNUNET_ARM_Result result) 62 enum GNUNET_ARM_Result result)
64{ 63{
65 GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK); 64 GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK);
@@ -100,15 +99,15 @@ service_list (void *cls,
100 stop_arm: 99 stop_arm:
101 GNUNET_ARM_request_service_stop (arm, 100 GNUNET_ARM_request_service_stop (arm,
102 "arm", 101 "arm",
103 TIMEOUT, 102 &arm_stop_cb,
104 &arm_stop_cb, NULL); 103 NULL);
105} 104}
106 105
107 106
108static void 107static void
109hostname_resolve_cb (void *cls, 108hostname_resolve_cb (void *cls,
110 const struct sockaddr *addr, 109 const struct sockaddr *addr,
111 socklen_t addrlen) 110 socklen_t addrlen)
112{ 111{
113 if ((0 == ret) || (4 == ret) || (1 == resolved_ok)) 112 if ((0 == ret) || (4 == ret) || (1 == resolved_ok))
114 return; 113 return;
@@ -120,8 +119,8 @@ hostname_resolve_cb (void *cls,
120 ret = 3; 119 ret = 3;
121 GNUNET_ARM_request_service_stop (arm, 120 GNUNET_ARM_request_service_stop (arm,
122 "arm", 121 "arm",
123 TIMEOUT, 122 &arm_stop_cb,
124 &arm_stop_cb, NULL); 123 NULL);
125 return; 124 return;
126 } 125 }
127 if (0 == asked_for_a_list) 126 if (0 == asked_for_a_list)
@@ -129,7 +128,6 @@ hostname_resolve_cb (void *cls,
129 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 128 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
130 "Resolved hostname, now checking the service list\n"); 129 "Resolved hostname, now checking the service list\n");
131 GNUNET_ARM_request_service_list (arm, 130 GNUNET_ARM_request_service_list (arm,
132 TIMEOUT,
133 &service_list, 131 &service_list,
134 NULL); 132 NULL);
135 asked_for_a_list = 1; 133 asked_for_a_list = 1;
@@ -141,7 +139,6 @@ hostname_resolve_cb (void *cls,
141static void 139static void
142arm_start_cb (void *cls, 140arm_start_cb (void *cls,
143 enum GNUNET_ARM_RequestStatus status, 141 enum GNUNET_ARM_RequestStatus status,
144 const char *servicename,
145 enum GNUNET_ARM_Result result) 142 enum GNUNET_ARM_Result result)
146{ 143{
147 GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK); 144 GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK);
@@ -150,7 +147,8 @@ arm_start_cb (void *cls,
150 "Trying to resolve our own hostname!\n"); 147 "Trying to resolve our own hostname!\n");
151 /* connect to the resolver service */ 148 /* connect to the resolver service */
152 if (NULL == 149 if (NULL ==
153 GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC, TIMEOUT, 150 GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC,
151 TIMEOUT,
154 &hostname_resolve_cb, 152 &hostname_resolve_cb,
155 NULL)) 153 NULL))
156 { 154 {
@@ -159,8 +157,9 @@ arm_start_cb (void *cls,
159 GNUNET_break (0); 157 GNUNET_break (0);
160 ret = 2; 158 ret = 2;
161 GNUNET_ARM_request_service_stop (arm, 159 GNUNET_ARM_request_service_stop (arm,
162 "arm", TIMEOUT, 160 "arm",
163 &arm_stop_cb, NULL); 161 &arm_stop_cb,
162 NULL);
164 } 163 }
165} 164}
166 165
@@ -171,11 +170,14 @@ run (void *cls,
171 const char *cfgfile, 170 const char *cfgfile,
172 const struct GNUNET_CONFIGURATION_Handle *c) 171 const struct GNUNET_CONFIGURATION_Handle *c)
173{ 172{
174 arm = GNUNET_ARM_connect (c, NULL, NULL); 173 arm = GNUNET_ARM_connect (c,
175 GNUNET_ARM_request_service_start (arm, "arm", 174 NULL,
175 NULL);
176 GNUNET_ARM_request_service_start (arm,
177 "arm",
176 GNUNET_OS_INHERIT_STD_OUT_AND_ERR, 178 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
177 START_TIMEOUT, 179 &arm_start_cb,
178 &arm_start_cb, NULL); 180 NULL);
179} 181}
180 182
181 183