aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/man/gnunet-arm.13
-rw-r--r--src/arm/arm_api.c77
-rw-r--r--src/arm/gnunet-arm.c330
3 files changed, 283 insertions, 127 deletions
diff --git a/doc/man/gnunet-arm.1 b/doc/man/gnunet-arm.1
index 1fbfa4142..0d144b53f 100644
--- a/doc/man/gnunet-arm.1
+++ b/doc/man/gnunet-arm.1
@@ -31,6 +31,9 @@ Starts the specified SERVICE if it is not already running. More specifically, t
31.IP "\-k SERVICE, \-\-kill=SERVICE" 31.IP "\-k SERVICE, \-\-kill=SERVICE"
32Stop the specified SERVICE if it is running. While this will kill the service right now, the service may be restarted immediately if other services depend on it (service is then started 'on-demand'). If the service used to be a 'default' service, its default-service status will be revoked. If the service was not a default service, it will just be (temporarily) stopped, but could be re-started on-demand at any time. 32Stop the specified SERVICE if it is running. While this will kill the service right now, the service may be restarted immediately if other services depend on it (service is then started 'on-demand'). If the service used to be a 'default' service, its default-service status will be revoked. If the service was not a default service, it will just be (temporarily) stopped, but could be re-started on-demand at any time.
33.B 33.B
34.IP "\-m, \-\-monitor"
35Monitor service activity of ARM. In this mode, the command will not terminate until the user presses CTRL-C.
36.B
34.IP "\-s, \-\-start" 37.IP "\-s, \-\-start"
35Start all GNUnet default services on this system (and also ARM). Naturally, if a service is demanded by a default service, it will then also be started. Running "gnunet-arm \-s" is the usual way to start a GNUnet peer. 38Start all GNUnet default services on this system (and also ARM). Naturally, if a service is demanded by a default service, it will then also be started. Running "gnunet-arm \-s" is the usual way to start a GNUnet peer.
36.B 39.B
diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c
index eb9194eec..8cdcfdeb5 100644
--- a/src/arm/arm_api.c
+++ b/src/arm/arm_api.c
@@ -83,6 +83,12 @@ struct GNUNET_ARM_Handle
83 void *conn_status_cls; 83 void *conn_status_cls;
84 84
85 /** 85 /**
86 * ARM control message for the 'arm_termination_handler'
87 * with the continuation to call once the ARM shutdown is done.
88 */
89 struct ARMControlMessage *thm;
90
91 /**
86 * ID of the reconnect task (if any). 92 * ID of the reconnect task (if any).
87 */ 93 */
88 GNUNET_SCHEDULER_TaskIdentifier reconnect_task; 94 GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
@@ -266,6 +272,40 @@ find_cm_by_id (struct GNUNET_ARM_Handle *h, uint64_t id)
266 272
267 273
268/** 274/**
275 * Handler for ARM 'termination' reply (failure to receive).
276 *
277 * @param cls our "struct GNUNET_ARM_Handle"
278 * @param msg expected to be NULL
279 */
280static void
281arm_termination_handler (void *cls, const struct GNUNET_MessageHeader *msg)
282{
283 struct GNUNET_ARM_Handle *h = cls;
284 struct ARMControlMessage *cm;
285
286 if (NULL != msg)
287 {
288 GNUNET_break (0);
289 GNUNET_CLIENT_receive (h->client, &arm_termination_handler, h,
290 GNUNET_TIME_UNIT_FOREVER_REL);
291 return;
292 }
293 cm = h->thm;
294 h->thm = NULL;
295 h->currently_down = GNUNET_YES;
296 GNUNET_CLIENT_disconnect (h->client);
297 h->client = NULL;
298 if (NULL != cm->result_cont)
299 cm->result_cont (cm->cont_cls,
300 GNUNET_ARM_REQUEST_SENT_OK,
301 (const char *) &cm->msg[1],
302 GNUNET_ARM_RESULT_STOPPED);
303 GNUNET_free (cm->msg);
304 GNUNET_free (cm);
305}
306
307
308/**
269 * Handler for ARM replies. 309 * Handler for ARM replies.
270 * 310 *
271 * @param cls our "struct GNUNET_ARM_Handle" 311 * @param cls our "struct GNUNET_ARM_Handle"
@@ -374,6 +414,32 @@ client_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg)
374 GNUNET_free (cm); 414 GNUNET_free (cm);
375 return; 415 return;
376 } 416 }
417 if ( (GNUNET_MESSAGE_TYPE_ARM_RESULT == ntohs (msg->type)) &&
418 (0 == strcasecmp ((const char *) &cm->msg[1],
419 "arm")) &&
420 (NULL != (res = (const struct GNUNET_ARM_ResultMessage *) msg)) &&
421 (GNUNET_ARM_RESULT_STOPPING == ntohl (res->result)) )
422 {
423 /* special case: if we are stopping 'gnunet-service-arm', we do not just
424 wait for the result message, but also wait for the service to close
425 the connection (and then we have to close our client handle as well);
426 this is done by installing a different receive handler, waiting for
427 the connection to go down */
428 if (NULL != h->thm)
429 {
430 GNUNET_break (0);
431 cm->result_cont (h->thm->cont_cls,
432 GNUNET_ARM_REQUEST_SENT_OK,
433 (const char *) &h->thm->msg[1],
434 GNUNET_ARM_RESULT_IS_NOT_KNOWN);
435 GNUNET_free (h->thm->msg);
436 GNUNET_free (h->thm);
437 }
438 h->thm = cm;
439 GNUNET_CLIENT_receive (h->client, &arm_termination_handler, h,
440 GNUNET_TIME_UNIT_FOREVER_REL);
441 return;
442 }
377 GNUNET_CLIENT_receive (h->client, &client_notify_handler, h, 443 GNUNET_CLIENT_receive (h->client, &client_notify_handler, h,
378 GNUNET_TIME_UNIT_FOREVER_REL); 444 GNUNET_TIME_UNIT_FOREVER_REL);
379 switch (ntohs (msg->type)) 445 switch (ntohs (msg->type))
@@ -845,8 +911,9 @@ change_service (struct GNUNET_ARM_Handle *h, const char *service_name,
845 memcpy (&msg[1], service_name, slen); 911 memcpy (&msg[1], service_name, slen);
846 cm->msg = msg; 912 cm->msg = msg;
847 LOG (GNUNET_ERROR_TYPE_DEBUG, 913 LOG (GNUNET_ERROR_TYPE_DEBUG,
848 "Inserting a control message into the queue. Timeout is %llu\n", 914 "Inserting a control message into the queue. Timeout is %s\n",
849 GNUNET_TIME_absolute_get_remaining (cm->timeout).rel_value); 915 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (cm->timeout),
916 GNUNET_NO));
850 GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head, 917 GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head,
851 h->control_pending_tail, cm); 918 h->control_pending_tail, cm);
852 cm->timeout_task_id = 919 cm->timeout_task_id =
@@ -959,8 +1026,10 @@ GNUNET_ARM_request_service_start (struct GNUNET_ARM_Handle *h,
959 */ 1026 */
960void 1027void
961GNUNET_ARM_request_service_stop (struct GNUNET_ARM_Handle *h, 1028GNUNET_ARM_request_service_stop (struct GNUNET_ARM_Handle *h,
962 const char *service_name, struct GNUNET_TIME_Relative timeout, 1029 const char *service_name,
963 GNUNET_ARM_ResultCallback cont, void *cont_cls) 1030 struct GNUNET_TIME_Relative timeout,
1031 GNUNET_ARM_ResultCallback cont,
1032 void *cont_cls)
964{ 1033{
965 LOG (GNUNET_ERROR_TYPE_DEBUG, 1034 LOG (GNUNET_ERROR_TYPE_DEBUG,
966 "Stopping service `%s' within %s\n", 1035 "Stopping service `%s' within %s\n",
diff --git a/src/arm/gnunet-arm.c b/src/arm/gnunet-arm.c
index c1928b6e7..4a68a97ea 100644
--- a/src/arm/gnunet-arm.c
+++ b/src/arm/gnunet-arm.c
@@ -76,6 +76,11 @@ static int delete;
76static int quiet; 76static int quiet;
77 77
78/** 78/**
79 * Monitor ARM activity.
80 */
81static int monitor;
82
83/**
79 * Set if we should print a list of currently running services. 84 * Set if we should print a list of currently running services.
80 */ 85 */
81static int list; 86static int list;
@@ -143,7 +148,7 @@ static unsigned int no_stderr;
143 148
144/** 149/**
145 * Attempts to delete configuration file and SERVICEHOME 150 * Attempts to delete configuration file and SERVICEHOME
146 * on arm shutdown provided the end and delete options 151 * on ARM shutdown provided the end and delete options
147 * were specified when gnunet-arm was run. 152 * were specified when gnunet-arm was run.
148 */ 153 */
149static void 154static void
@@ -154,17 +159,16 @@ delete_files ()
154 config_file, dir); 159 config_file, dir);
155 160
156 if (UNLINK (config_file) != 0) 161 if (UNLINK (config_file) != 0)
157 { 162 {
158 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 163 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
159 _("Failed to remove configuration file %s\n"), config_file); 164 _("Failed to remove configuration file %s\n"), config_file);
160 } 165 }
161
162 if (GNUNET_DISK_directory_remove (dir) != GNUNET_OK) 166 if (GNUNET_DISK_directory_remove (dir) != GNUNET_OK)
163 { 167 {
164 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 168 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
165 _("Failed to remove servicehome directory %s\n"), dir); 169 _("Failed to remove servicehome directory %s\n"), dir);
166 170
167 } 171 }
168} 172}
169 173
170 174
@@ -178,10 +182,16 @@ delete_files ()
178static void 182static void
179shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 183shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
180{ 184{
181 GNUNET_ARM_disconnect_and_free (h); 185 if (NULL != h)
182 GNUNET_ARM_monitor_disconnect_and_free (m); 186 {
183 h = NULL; 187 GNUNET_ARM_disconnect_and_free (h);
184 m = NULL; 188 h = NULL;
189 }
190 if (NULL != m)
191 {
192 GNUNET_ARM_monitor_disconnect_and_free (m);
193 m = NULL;
194 }
185 if ((end == GNUNET_YES) && (delete == GNUNET_YES)) 195 if ((end == GNUNET_YES) && (delete == GNUNET_YES))
186 delete_files (); 196 delete_files ();
187 GNUNET_CONFIGURATION_destroy (cfg); 197 GNUNET_CONFIGURATION_destroy (cfg);
@@ -203,13 +213,13 @@ req_string (enum GNUNET_ARM_RequestStatus rs)
203 case GNUNET_ARM_REQUEST_SENT_OK: 213 case GNUNET_ARM_REQUEST_SENT_OK:
204 return _("Message was sent successfully"); 214 return _("Message was sent successfully");
205 case GNUNET_ARM_REQUEST_CONFIGURATION_ERROR: 215 case GNUNET_ARM_REQUEST_CONFIGURATION_ERROR:
206 return _("Misconfiguration (can't connect to the ARM service)"); 216 return _("Misconfiguration (can not connect to the ARM service)");
207 case GNUNET_ARM_REQUEST_DISCONNECTED: 217 case GNUNET_ARM_REQUEST_DISCONNECTED:
208 return _("We disconnected from ARM before we could send a request"); 218 return _("We disconnected from ARM before we could send a request");
209 case GNUNET_ARM_REQUEST_BUSY: 219 case GNUNET_ARM_REQUEST_BUSY:
210 return _("ARM API is busy"); 220 return _("ARM API is busy");
211 case GNUNET_ARM_REQUEST_TOO_LONG: 221 case GNUNET_ARM_REQUEST_TOO_LONG:
212 return _("Request doesn't fit into a message"); 222 return _("Request does not fit into a message");
213 case GNUNET_ARM_REQUEST_TIMEOUT: 223 case GNUNET_ARM_REQUEST_TIMEOUT:
214 return _("Request timed out"); 224 return _("Request timed out");
215 } 225 }
@@ -247,7 +257,7 @@ ret_string (enum GNUNET_ARM_Result result)
247 case GNUNET_ARM_RESULT_START_FAILED: 257 case GNUNET_ARM_RESULT_START_FAILED:
248 return _("%s service failed to start"); 258 return _("%s service failed to start");
249 case GNUNET_ARM_RESULT_IN_SHUTDOWN: 259 case GNUNET_ARM_RESULT_IN_SHUTDOWN:
250 return _("%s service can't be started because ARM is shutting down"); 260 return _("%s service cannot be started because ARM is shutting down");
251 } 261 }
252 return _("%.s Unknown result code."); 262 return _("%.s Unknown result code.");
253} 263}
@@ -265,6 +275,8 @@ action_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
265 275
266/** 276/**
267 * Function called whenever we connect to or disconnect from ARM. 277 * Function called whenever we connect to or disconnect from ARM.
278 * Termiantes the process if we fail to connect to the service on
279 * our first attempt.
268 * 280 *
269 * @param cls closure 281 * @param cls closure
270 * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected, 282 * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected,
@@ -274,162 +286,227 @@ static void
274conn_status (void *cls, 286conn_status (void *cls,
275 int connected) 287 int connected)
276{ 288{
277 if (GNUNET_SYSERR == connected) 289 static int once;
290
291 if ( (GNUNET_SYSERR == connected) &&
292 (0 == once) )
278 { 293 {
279 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 294 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
280 _("Fatal error initializing ARM API.\n")); 295 _("Fatal error initializing ARM API.\n"));
281 GNUNET_SCHEDULER_shutdown (); 296 GNUNET_SCHEDULER_shutdown ();
282 return; 297 return;
283 } 298 }
299 once = 1;
284} 300}
285 301
286 302
303/**
304 * We have requested ARM to be started, this function
305 * is called with the result of the operation. Informs the
306 * use of the result; on success, we continue with the event
307 * loop, on failure we terminate the process.
308 *
309 * @param cls closure unused
310 * @param rs what happened to our request
311 * @param service name of the service we tried to start ("arm")
312 * @param result if the request was processed, this is the result
313 * according to ARM
314 */
287static void 315static void
288term_callback (void *cls, 316start_callback (void *cls,
289 enum GNUNET_ARM_RequestStatus rs, const char *service, 317 enum GNUNET_ARM_RequestStatus rs, const char *service,
290 enum GNUNET_ARM_Result result) 318 enum GNUNET_ARM_Result result)
291{ 319{
320 char *msg;
321
292 if (GNUNET_ARM_REQUEST_SENT_OK != rs) 322 if (GNUNET_ARM_REQUEST_SENT_OK != rs)
293 { 323 {
294 char *msg; 324 GNUNET_asprintf (&msg, "%s", _("Failed to start the ARM service: %s\n"));
295 GNUNET_asprintf (&msg,
296 _("Failed to send a request to kill the `%s' service: %%s\n"),
297 term);
298 FPRINTF (stdout, msg, req_string (rs)); 325 FPRINTF (stdout, msg, req_string (rs));
299 GNUNET_free (msg); 326 GNUNET_free (msg);
300 GNUNET_SCHEDULER_shutdown (); 327 GNUNET_SCHEDULER_shutdown ();
328 return;
301 } 329 }
302 if ((GNUNET_ARM_RESULT_STOPPED == result) || 330 if ( (GNUNET_ARM_RESULT_STARTING != result) &&
303 (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY == result)) 331 (GNUNET_ARM_RESULT_IS_STARTED_ALREADY != result) )
304 {
305 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service %s shutdown successful\n", term);
306 term = NULL;
307 GNUNET_SCHEDULER_add_now (action_loop, NULL);
308 }
309 else
310 { 332 {
311 char *msg; 333 GNUNET_asprintf (&msg, "%s", _("Failed to start the ARM service: %s\n"));
312 GNUNET_asprintf (&msg, _("Failed to kill the `%s' service: %s\n"), 334 FPRINTF (stdout, msg, ret_string (result));
313 term, ret_string (result));
314 FPRINTF (stdout, msg, service);
315 GNUNET_free (msg); 335 GNUNET_free (msg);
316 GNUNET_SCHEDULER_shutdown (); 336 GNUNET_SCHEDULER_shutdown ();
317 } 337 return;
338 }
339 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM service [re]start successful\n");
340 start = 0;
341 GNUNET_SCHEDULER_add_now (action_loop, NULL);
318} 342}
319 343
320 344
345/**
346 * We have requested ARM to be stopped, this function
347 * is called with the result of the operation. Informs the
348 * use of the result; on success, we continue with the event
349 * loop, on failure we terminate the process.
350 *
351 * @param cls closure unused
352 * @param rs what happened to our request
353 * @param service name of the service we tried to start ("arm")
354 * @param result if the request was processed, this is the result
355 * according to ARM
356 */
321static void 357static void
322end_callback (void *cls, 358stop_callback (void *cls,
323 enum GNUNET_ARM_RequestStatus rs, const char *service, 359 enum GNUNET_ARM_RequestStatus rs, const char *service,
324 enum GNUNET_ARM_Result result) 360 enum GNUNET_ARM_Result result)
325{ 361{
362 char *msg;
363
326 if (GNUNET_ARM_REQUEST_SENT_OK != rs) 364 if (GNUNET_ARM_REQUEST_SENT_OK != rs)
327 { 365 {
328 char *msg;
329
330 GNUNET_asprintf (&msg, "%s", 366 GNUNET_asprintf (&msg, "%s",
331 _("Failed to send a stop request to the ARM service: %s\n")); 367 _("Failed to send a stop request to the ARM service: %s\n"));
332 FPRINTF (stdout, msg, req_string (rs)); 368 FPRINTF (stdout, msg, req_string (rs));
333 GNUNET_free (msg); 369 GNUNET_free (msg);
334 GNUNET_SCHEDULER_shutdown (); 370 GNUNET_SCHEDULER_shutdown ();
371 return;
335 } 372 }
336 if ((GNUNET_ARM_RESULT_STOPPING == result) || 373 if ((GNUNET_ARM_RESULT_STOPPING != result) &&
337 (GNUNET_ARM_RESULT_STOPPED == result) || 374 (GNUNET_ARM_RESULT_STOPPED != result) &&
338 (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY == result)) 375 (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY != result))
339 {
340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM service shutdown successful\n");
341 end = 0;
342 if (restart)
343 {
344 restart = 0;
345 start = 1;
346 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initiating an ARM restart\n");
347 }
348 GNUNET_SCHEDULER_add_now (action_loop, NULL);
349 }
350 else
351 { 376 {
352 char *msg;
353
354 GNUNET_asprintf (&msg, "%s", _("Failed to stop the ARM service: %s\n")); 377 GNUNET_asprintf (&msg, "%s", _("Failed to stop the ARM service: %s\n"));
355 FPRINTF (stdout, msg, ret_string (result)); 378 FPRINTF (stdout, msg, ret_string (result));
356 GNUNET_free (msg); 379 GNUNET_free (msg);
357 GNUNET_SCHEDULER_shutdown (); 380 GNUNET_SCHEDULER_shutdown ();
381 return;
382 }
383 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
384 "ARM service shutdown successful\n");
385 end = 0;
386 if (restart)
387 {
388 restart = 0;
389 start = 1;
390 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
391 "Initiating an ARM restart\n");
358 } 392 }
393 GNUNET_SCHEDULER_add_now (&action_loop, NULL);
359} 394}
360 395
361 396
397/**
398 * We have requested a service to be started, this function
399 * is called with the result of the operation. Informs the
400 * use of the result; on success, we continue with the event
401 * loop, on failure we terminate the process.
402 *
403 * @param cls closure unused
404 * @param rs what happened to our request
405 * @param service name of the service we tried to start
406 * @param result if the request was processed, this is the result
407 * according to ARM
408 */
362static void 409static void
363start_callback (void *cls, 410init_callback (void *cls,
364 enum GNUNET_ARM_RequestStatus rs, const char *service, 411 enum GNUNET_ARM_RequestStatus rs, const char *service,
365 enum GNUNET_ARM_Result result) 412 enum GNUNET_ARM_Result result)
366{ 413{
367 char *msg; 414 char *msg;
368 415
369 if (GNUNET_ARM_REQUEST_SENT_OK != rs) 416 if (GNUNET_ARM_REQUEST_SENT_OK != rs)
370 { 417 {
371 GNUNET_asprintf (&msg, "%s", _("Failed to start the ARM service: %s\n")); 418 GNUNET_asprintf (&msg, _("Failed to send a request to start the `%s' service: %%s\n"), init);
372 FPRINTF (stdout, msg, req_string (rs)); 419 FPRINTF (stdout, msg, req_string (rs));
373 GNUNET_free (msg); 420 GNUNET_free (msg);
374 GNUNET_SCHEDULER_shutdown (); 421 GNUNET_SCHEDULER_shutdown ();
375 return; 422 return;
376 } 423 }
377 if (! ((GNUNET_ARM_RESULT_STARTING == result) || 424 if ((GNUNET_ARM_RESULT_STARTING != result) &&
378 (GNUNET_ARM_RESULT_IS_STARTED_ALREADY == result)) ) 425 (GNUNET_ARM_RESULT_IS_STARTED_ALREADY != result))
379 { 426 {
380 GNUNET_asprintf (&msg, "%s", _("Failed to start the ARM service: %s\n")); 427 GNUNET_asprintf (&msg, _("Failed to start the `%s' service: %s\n"),
381 FPRINTF (stdout, msg, ret_string (result)); 428 init, ret_string (result));
429 FPRINTF (stdout, msg, service);
382 GNUNET_free (msg); 430 GNUNET_free (msg);
383 GNUNET_SCHEDULER_shutdown (); 431 GNUNET_SCHEDULER_shutdown ();
384 } 432 return;
385 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM service [re]start successful\n"); 433 }
386 start = 0; 434 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
387 GNUNET_SCHEDULER_add_now (action_loop, NULL); 435 "Service %s [re]started successfully\n",
436 init);
437 init = NULL;
438 GNUNET_SCHEDULER_add_now (&action_loop, NULL);
388} 439}
389 440
390 441
442/**
443 * We have requested a service to be stopped, this function
444 * is called with the result of the operation. Informs the
445 * use of the result; on success, we continue with the event
446 * loop, on failure we terminate the process.
447 *
448 * @param cls closure unused
449 * @param rs what happened to our request
450 * @param service name of the service we tried to start
451 * @param result if the request was processed, this is the result
452 * according to ARM
453 */
391static void 454static void
392init_callback (void *cls, 455term_callback (void *cls,
393 enum GNUNET_ARM_RequestStatus rs, const char *service, 456 enum GNUNET_ARM_RequestStatus rs, const char *service,
394 enum GNUNET_ARM_Result result) 457 enum GNUNET_ARM_Result result)
395{ 458{
459 char *msg;
396 if (GNUNET_ARM_REQUEST_SENT_OK != rs) 460 if (GNUNET_ARM_REQUEST_SENT_OK != rs)
397 { 461 {
398 char *msg; 462 GNUNET_asprintf (&msg,
399 463 _("Failed to send a request to kill the `%s' service: %%s\n"),
400 GNUNET_asprintf (&msg, _("Failed to send a request to start the `%s' service: %%s\n"), init); 464 term);
401 FPRINTF (stdout, msg, req_string (rs)); 465 FPRINTF (stdout, msg, req_string (rs));
402 GNUNET_free (msg); 466 GNUNET_free (msg);
403 GNUNET_SCHEDULER_shutdown (); 467 GNUNET_SCHEDULER_shutdown ();
468 return;
404 } 469 }
405 if ((GNUNET_ARM_RESULT_STARTING == result) || 470 if ((GNUNET_ARM_RESULT_STOPPED != result) &&
406 (GNUNET_ARM_RESULT_IS_STARTED_ALREADY == result)) 471 (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY != result))
407 {
408 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service %s [re]start successful\n", init);
409 init = NULL;
410 GNUNET_SCHEDULER_add_now (action_loop, NULL);
411 }
412 else
413 { 472 {
414 char *msg; 473 GNUNET_asprintf (&msg,
415 GNUNET_asprintf (&msg, _("Failed to start the `%s' service: %s\n"), 474 _("Failed to kill the `%s' service: %s\n"),
416 init, ret_string (result)); 475 term, ret_string (result));
417 FPRINTF (stdout, msg, service); 476 FPRINTF (stdout, msg, service);
418 GNUNET_free (msg); 477 GNUNET_free (msg);
419 GNUNET_SCHEDULER_shutdown (); 478 GNUNET_SCHEDULER_shutdown ();
479 return;
420 } 480 }
481
482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
483 "Service %s stopped successfully\n", term);
484 term = NULL;
485 GNUNET_SCHEDULER_add_now (&action_loop, NULL);
421} 486}
422 487
423 488
489/**
490 * Function called with the list of running services. Prints
491 * the list to stdout, then starts the event loop again.
492 * Prints an error message and terminates the process on errors.
493 *
494 * @param cls closure (unused)
495 * @param rs request status (success, failure, etc.)
496 * @param count number of services in the list
497 * @param list list of services that are running
498 */
424static void 499static void
425list_callback (void *cls, 500list_callback (void *cls,
426 enum GNUNET_ARM_RequestStatus rs, unsigned int count, 501 enum GNUNET_ARM_RequestStatus rs, unsigned int count,
427 const char *const*list) 502 const char *const*list)
428{ 503{
429 unsigned int i; 504 unsigned int i;
505
430 if (GNUNET_ARM_REQUEST_SENT_OK != rs) 506 if (GNUNET_ARM_REQUEST_SENT_OK != rs)
431 { 507 {
432 char *msg; 508 char *msg;
509
433 GNUNET_asprintf (&msg, "%s", _("Failed to request a list of services: %s\n")); 510 GNUNET_asprintf (&msg, "%s", _("Failed to request a list of services: %s\n"));
434 FPRINTF (stdout, msg, req_string (rs)); 511 FPRINTF (stdout, msg, req_string (rs));
435 GNUNET_free (msg); 512 GNUNET_free (msg);
@@ -438,18 +515,19 @@ list_callback (void *cls,
438 if (NULL == list) 515 if (NULL == list)
439 { 516 {
440 FPRINTF (stderr, "%s", _("Error communicating with ARM. ARM not running?\n")); 517 FPRINTF (stderr, "%s", _("Error communicating with ARM. ARM not running?\n"));
518 GNUNET_SCHEDULER_shutdown ();
441 return; 519 return;
442 } 520 }
443 FPRINTF (stdout, "%s", _("Running services:\n")); 521 FPRINTF (stdout, "%s", _("Running services:\n"));
444 for (i = 0; i < count; i++) 522 for (i = 0; i < count; i++)
445 FPRINTF (stdout, "%s\n", list[i]); 523 FPRINTF (stdout, "%s\n", list[i]);
446 GNUNET_SCHEDULER_add_now (action_loop, NULL); 524 GNUNET_SCHEDULER_add_now (&action_loop, NULL);
447} 525}
448 526
449 527
450/** 528/**
451 * Main action loop. Runs the various 529 * Main action loop. Runs the various jobs that we've been asked to
452 * jobs that we've been asked to do in order. 530 * do, in order.
453 * 531 *
454 * @param cls closure, unused 532 * @param cls closure, unused
455 * @param tc context, unused 533 * @param tc context, unused
@@ -468,9 +546,9 @@ action_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
468 if (NULL != term) 546 if (NULL != term)
469 { 547 {
470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Termination action\n"); 548 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Termination action\n");
471 GNUNET_ARM_request_service_stop (h, term, (0 == 549 GNUNET_ARM_request_service_stop (h, term,
472 timeout.rel_value) ? STOP_TIMEOUT : timeout, 550 (0 == timeout.rel_value) ? STOP_TIMEOUT : timeout,
473 term_callback, NULL); 551 &term_callback, NULL);
474 return; 552 return;
475 } 553 }
476 break; 554 break;
@@ -478,9 +556,9 @@ action_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
478 if (end || restart) 556 if (end || restart)
479 { 557 {
480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "End action\n"); 558 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "End action\n");
481 GNUNET_ARM_request_service_stop (h, "arm", (0 == 559 GNUNET_ARM_request_service_stop (h, "arm",
482 timeout.rel_value) ? STOP_TIMEOUT_ARM : timeout, 560 (0 == timeout.rel_value) ? STOP_TIMEOUT_ARM : timeout,
483 end_callback, NULL); 561 &stop_callback, NULL);
484 return; 562 return;
485 } 563 }
486 break; 564 break;
@@ -501,8 +579,8 @@ action_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
501 { 579 {
502 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initialization action\n"); 580 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initialization action\n");
503 GNUNET_ARM_request_service_start (h, init, GNUNET_OS_INHERIT_STD_NONE, 581 GNUNET_ARM_request_service_start (h, init, GNUNET_OS_INHERIT_STD_NONE,
504 (0 == timeout.rel_value) ? STOP_TIMEOUT : timeout, 582 (0 == timeout.rel_value) ? STOP_TIMEOUT : timeout,
505 init_callback, NULL); 583 &init_callback, NULL);
506 return; 584 return;
507 } 585 }
508 break; 586 break;
@@ -510,14 +588,23 @@ action_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
510 if (list) 588 if (list)
511 { 589 {
512 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 590 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
513 "Going to list all running services controlled by ARM.\n"); 591 "Going to list all running services controlled by ARM.\n");
514
515 GNUNET_ARM_request_service_list (h, 592 GNUNET_ARM_request_service_list (h,
516 (0 == timeout.rel_value) ? LIST_TIMEOUT : timeout, 593 (0 == timeout.rel_value) ? LIST_TIMEOUT : timeout,
517 list_callback, &list); 594 &list_callback, &list);
518 return; 595 return;
519 } 596 }
520 /* Fall through */ 597 break;
598 case 5:
599 if (monitor)
600 {
601 if (! quiet)
602 fprintf (stderr,
603 _("Now only monitoring, press CTRL-C to stop.\n"));
604 quiet = 0; /* does not make sense to stay quiet in monitor mode at this time */
605 return; /* done with tasks, just monitor */
606 }
607 break;
521 default: /* last phase */ 608 default: /* last phase */
522 GNUNET_SCHEDULER_shutdown (); 609 GNUNET_SCHEDULER_shutdown ();
523 return; 610 return;
@@ -538,6 +625,7 @@ srv_status (void *cls,
538 const char *service, enum GNUNET_ARM_ServiceStatus status) 625 const char *service, enum GNUNET_ARM_ServiceStatus status)
539{ 626{
540 const char *msg; 627 const char *msg;
628
541 switch (status) 629 switch (status)
542 { 630 {
543 case GNUNET_ARM_SERVICE_MONITORING_STARTED: 631 case GNUNET_ARM_SERVICE_MONITORING_STARTED:
@@ -562,7 +650,7 @@ srv_status (void *cls,
562 else 650 else
563 FPRINTF (stderr, _("Unknown status %u for service %s.\n"), status, service); 651 FPRINTF (stderr, _("Unknown status %u for service %s.\n"), status, service);
564 } 652 }
565 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got service %s status %u\n", service, status); 653 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got service %s status %d\n", service, (int) status);
566} 654}
567 655
568 656
@@ -575,7 +663,9 @@ srv_status (void *cls,
575 * @param c configuration 663 * @param c configuration
576 */ 664 */
577static void 665static void
578run (void *cls, char *const *args, const char *cfgfile, 666run (void *cls,
667 char *const *args,
668 const char *cfgfile,
579 const struct GNUNET_CONFIGURATION_Handle *c) 669 const struct GNUNET_CONFIGURATION_Handle *c)
580{ 670{
581 char *armconfig; 671 char *armconfig;
@@ -601,22 +691,13 @@ run (void *cls, char *const *args, const char *cfgfile,
601 else 691 else
602 GNUNET_free (armconfig); 692 GNUNET_free (armconfig);
603 } 693 }
604 h = GNUNET_ARM_connect (cfg, &conn_status, NULL); 694 if (NULL == (h = GNUNET_ARM_connect (cfg, &conn_status, NULL)))
605 if (NULL != h) 695 return;
606 { 696 if (monitor)
607 m = GNUNET_ARM_monitor (cfg, &srv_status, NULL); 697 m = GNUNET_ARM_monitor (cfg, &srv_status, NULL);
608 if (NULL != m) 698 GNUNET_SCHEDULER_add_now (&action_loop, NULL);
609 { 699 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
610 GNUNET_SCHEDULER_add_now (&action_loop, NULL); 700 &shutdown_task, NULL);
611 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
612 shutdown_task, NULL);
613 }
614 else
615 {
616 GNUNET_ARM_disconnect_and_free (h);
617 h = NULL;
618 }
619 }
620} 701}
621 702
622 703
@@ -645,6 +726,9 @@ main (int argc, char *const *argv)
645 {'d', "delete", NULL, 726 {'d', "delete", NULL,
646 gettext_noop ("delete config file and directory on exit"), 727 gettext_noop ("delete config file and directory on exit"),
647 GNUNET_NO, &GNUNET_GETOPT_set_one, &delete}, 728 GNUNET_NO, &GNUNET_GETOPT_set_one, &delete},
729 {'m', "monitor", NULL,
730 gettext_noop ("monitor ARM activities"),
731 GNUNET_NO, &GNUNET_GETOPT_set_one, &monitor},
648 {'q', "quiet", NULL, gettext_noop ("don't print status messages"), 732 {'q', "quiet", NULL, gettext_noop ("don't print status messages"),
649 GNUNET_NO, &GNUNET_GETOPT_set_one, &quiet}, 733 GNUNET_NO, &GNUNET_GETOPT_set_one, &quiet},
650 {'T', "timeout", "MSECS", 734 {'T', "timeout", "MSECS",