aboutsummaryrefslogtreecommitdiff
path: root/src/arm
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-09-24 21:21:44 +0000
committerChristian Grothoff <christian@grothoff.org>2016-09-24 21:21:44 +0000
commit31899f01bd95f66e6cfec9b53ace071648d6b663 (patch)
treef3ce0eae1093241cd1be5fa7277d262b39f93cf8 /src/arm
parentbdd2a2f82789160f7cd1d5f6d25bdcd75a90937e (diff)
downloadgnunet-31899f01bd95f66e6cfec9b53ace071648d6b663.tar.gz
gnunet-31899f01bd95f66e6cfec9b53ace071648d6b663.zip
migrate ARM to new service API
Diffstat (limited to 'src/arm')
-rw-r--r--src/arm/arm_api.c4
-rw-r--r--src/arm/gnunet-service-arm.c724
2 files changed, 403 insertions, 325 deletions
diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c
index 20ba7f9af..626d8957a 100644
--- a/src/arm/arm_api.c
+++ b/src/arm/arm_api.c
@@ -463,7 +463,7 @@ reconnect_arm (struct GNUNET_ARM_Handle *h)
463 struct GNUNET_ARM_ListResultMessage, 463 struct GNUNET_ARM_ListResultMessage,
464 h), 464 h),
465 GNUNET_MQ_hd_fixed_size (confirm, 465 GNUNET_MQ_hd_fixed_size (confirm,
466 GNUNET_MESSAGE_TYPE_TEST, 466 GNUNET_MESSAGE_TYPE_ARM_TEST,
467 struct GNUNET_MessageHeader, 467 struct GNUNET_MessageHeader,
468 h), 468 h),
469 GNUNET_MQ_handler_end () 469 GNUNET_MQ_handler_end ()
@@ -491,7 +491,7 @@ reconnect_arm (struct GNUNET_ARM_Handle *h)
491 LOG (GNUNET_ERROR_TYPE_DEBUG, 491 LOG (GNUNET_ERROR_TYPE_DEBUG,
492 "Sending TEST message to ARM\n"); 492 "Sending TEST message to ARM\n");
493 env = GNUNET_MQ_msg (test, 493 env = GNUNET_MQ_msg (test,
494 GNUNET_MESSAGE_TYPE_TEST); 494 GNUNET_MESSAGE_TYPE_ARM_TEST);
495 GNUNET_MQ_send (h->mq, 495 GNUNET_MQ_send (h->mq,
496 env); 496 env);
497 return GNUNET_OK; 497 return GNUNET_OK;
diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c
index df426bb48..995cd4489 100644
--- a/src/arm/gnunet-service-arm.c
+++ b/src/arm/gnunet-service-arm.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, 2011, 2015 GNUnet e.V. 3 Copyright (C) 2009-2011, 2015, 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
@@ -82,7 +82,7 @@ struct ServiceListeningInfo
82 struct ServiceList *sl; 82 struct ServiceList *sl;
83 83
84 /** 84 /**
85 * Number of bytes in 'service_addr' 85 * Number of bytes in @e service_addr
86 */ 86 */
87 socklen_t service_addr_len; 87 socklen_t service_addr_len;
88 88
@@ -143,7 +143,7 @@ struct ServiceList
143 * Client to notify upon kill completion (waitpid), NULL 143 * Client to notify upon kill completion (waitpid), NULL
144 * if we should simply restart the process. 144 * if we should simply restart the process.
145 */ 145 */
146 struct GNUNET_SERVER_Client *killing_client; 146 struct GNUNET_SERVICE_Client *killing_client;
147 147
148 /** 148 /**
149 * ID of the request that killed the service (for reporting back). 149 * ID of the request that killed the service (for reporting back).
@@ -242,92 +242,21 @@ static int start_user = GNUNET_YES;
242static int start_system = GNUNET_YES; 242static int start_system = GNUNET_YES;
243 243
244/** 244/**
245 * Handle to our server instance. Our server is a bit special in that 245 * Handle to our service instance. Our service is a bit special in that
246 * its service is not immediately stopped once we get a shutdown 246 * its service is not immediately stopped once we get a shutdown
247 * request (since we need to continue service until all of our child 247 * request (since we need to continue service until all of our child
248 * processes are dead). This handle is used to shut down the server 248 * processes are dead). This handle is used to shut down the service
249 * (and thus trigger process termination) once all child processes are 249 * (and thus trigger process termination) once all child processes are
250 * also dead. A special option in the ARM configuration modifies the 250 * also dead. A special option in the ARM configuration modifies the
251 * behaviour of the service implementation to not do the shutdown 251 * behaviour of the service implementation to not do the shutdown
252 * immediately. 252 * immediately.
253 */ 253 */
254static struct GNUNET_SERVER_Handle *server; 254static struct GNUNET_SERVICE_Handle *service;
255 255
256/** 256/**
257 * Context for notifications we need to send to our clients. 257 * Context for notifications we need to send to our clients.
258 */ 258 */
259static struct GNUNET_SERVER_NotificationContext *notifier; 259static struct GNUNET_NotificationContext *notifier;
260
261
262/**
263 * Transmit a status result message.
264 *
265 * @param cls a `unit16_t *` with message type
266 * @param size number of bytes available in @a buf
267 * @param buf where to copy the message, NULL on error
268 * @return number of bytes copied to @a buf
269 */
270static size_t
271write_result (void *cls, size_t size, void *buf)
272{
273 struct GNUNET_ARM_ResultMessage *msg = cls;
274 size_t msize;
275
276 if (NULL == buf)
277 {
278 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
279 _("Could not send status result to client\n"));
280 GNUNET_free (msg);
281 return 0; /* error, not much we can do */
282 }
283 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
284 "Sending status response %u to client\n",
285 (unsigned int) msg->result);
286 msize = msg->arm_msg.header.size;
287 GNUNET_assert (size >= msize);
288 msg->arm_msg.header.size = htons (msg->arm_msg.header.size);
289 msg->arm_msg.header.type = htons (msg->arm_msg.header.type);
290 msg->result = htonl (msg->result);
291 msg->arm_msg.request_id = GNUNET_htonll (msg->arm_msg.request_id);
292 GNUNET_memcpy (buf, msg, msize);
293 GNUNET_free (msg);
294 return msize;
295}
296
297
298/**
299 * Transmit the list of running services.
300 *
301 * @param cls pointer to `struct GNUNET_ARM_ListResultMessage` with the message
302 * @param size number of bytes available in @a buf
303 * @param buf where to copy the message, NULL on error
304 * @return number of bytes copied to @a buf
305 */
306static size_t
307write_list_result (void *cls, size_t size, void *buf)
308{
309 struct GNUNET_ARM_ListResultMessage *msg = cls;
310 size_t rslt_size;
311
312 if (NULL == buf)
313 {
314 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
315 _("Could not send list result to client\n"));
316 GNUNET_free (msg);
317 return 0; /* error, not much we can do */
318 }
319
320 rslt_size = msg->arm_msg.header.size;
321 GNUNET_assert (size >= rslt_size);
322 msg->arm_msg.header.size = htons (msg->arm_msg.header.size);
323 msg->arm_msg.header.type = htons (msg->arm_msg.header.type);
324 msg->arm_msg.request_id = GNUNET_htonll (msg->arm_msg.request_id);
325 msg->count = htons (msg->count);
326
327 GNUNET_memcpy (buf, msg, rslt_size);
328 GNUNET_free (msg);
329 return rslt_size;
330}
331 260
332 261
333/** 262/**
@@ -341,24 +270,20 @@ write_list_result (void *cls, size_t size, void *buf)
341 * @return NULL if it was not found 270 * @return NULL if it was not found
342 */ 271 */
343static void 272static void
344signal_result (struct GNUNET_SERVER_Client *client, 273signal_result (struct GNUNET_SERVICE_Client *client,
345 const char *name, 274 const char *name,
346 uint64_t request_id, 275 uint64_t request_id,
347 enum GNUNET_ARM_Result result) 276 enum GNUNET_ARM_Result result)
348{ 277{
278 struct GNUNET_MQ_Envelope *env;
349 struct GNUNET_ARM_ResultMessage *msg; 279 struct GNUNET_ARM_ResultMessage *msg;
350 size_t msize; 280
351 281 env = GNUNET_MQ_msg (msg,
352 msize = sizeof (struct GNUNET_ARM_ResultMessage); 282 GNUNET_MESSAGE_TYPE_ARM_RESULT);
353 msg = GNUNET_malloc (msize); 283 msg->result = htonl (result);
354 msg->arm_msg.header.size = msize; 284 msg->arm_msg.request_id = GNUNET_htonll (request_id);
355 msg->arm_msg.header.type = GNUNET_MESSAGE_TYPE_ARM_RESULT; 285 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
356 msg->result = result; 286 env);
357 msg->arm_msg.request_id = request_id;
358
359 GNUNET_SERVER_notify_transmit_ready (client, msize,
360 GNUNET_TIME_UNIT_FOREVER_REL,
361 write_result, msg);
362} 287}
363 288
364 289
@@ -373,30 +298,36 @@ signal_result (struct GNUNET_SERVER_Client *client,
373static void 298static void
374broadcast_status (const char *name, 299broadcast_status (const char *name,
375 enum GNUNET_ARM_ServiceStatus status, 300 enum GNUNET_ARM_ServiceStatus status,
376 struct GNUNET_SERVER_Client *unicast) 301 struct GNUNET_SERVICE_Client *unicast)
377{ 302{
303 struct GNUNET_MQ_Envelope *env;
378 struct GNUNET_ARM_StatusMessage *msg; 304 struct GNUNET_ARM_StatusMessage *msg;
379 size_t namelen; 305 size_t namelen;
380 306
381 if (NULL == notifier)
382 return;
383 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 307 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
384 "Sending status %u of service `%s' to client\n", 308 "Sending status %u of service `%s' to client\n",
385 (unsigned int) status, name); 309 (unsigned int) status,
386 namelen = strlen (name); 310 name);
387 msg = GNUNET_malloc (sizeof (struct GNUNET_ARM_StatusMessage) + namelen + 1); 311 namelen = strlen (name) + 1;
388 msg->header.size = htons (sizeof (struct GNUNET_ARM_StatusMessage) + namelen + 1); 312 env = GNUNET_MQ_msg_extra (msg,
389 msg->header.type = htons (GNUNET_MESSAGE_TYPE_ARM_STATUS); 313 namelen,
314 GNUNET_MESSAGE_TYPE_ARM_STATUS);
390 msg->status = htonl ((uint32_t) (status)); 315 msg->status = htonl ((uint32_t) (status));
391 GNUNET_memcpy ((char *) &msg[1], name, namelen + 1); 316 GNUNET_memcpy ((char *) &msg[1],
392 317 name,
318 namelen);
393 if (NULL == unicast) 319 if (NULL == unicast)
394 GNUNET_SERVER_notification_context_broadcast (notifier, 320 {
395 (struct GNUNET_MessageHeader *) msg, GNUNET_YES); 321 GNUNET_notification_context_broadcast (notifier,
322 &msg->header,
323 GNUNET_YES);
324 GNUNET_MQ_discard (env);
325 }
396 else 326 else
397 GNUNET_SERVER_notification_context_unicast (notifier, unicast, 327 {
398 (const struct GNUNET_MessageHeader *) msg, GNUNET_NO); 328 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (unicast),
399 GNUNET_free (msg); 329 env);
330 }
400} 331}
401 332
402 333
@@ -410,7 +341,7 @@ broadcast_status (const char *name,
410 */ 341 */
411static void 342static void
412start_process (struct ServiceList *sl, 343start_process (struct ServiceList *sl,
413 struct GNUNET_SERVER_Client *client, 344 struct GNUNET_SERVICE_Client *client,
414 uint64_t request_id) 345 uint64_t request_id)
415{ 346{
416 char *loprefix; 347 char *loprefix;
@@ -430,16 +361,20 @@ start_process (struct ServiceList *sl,
430 { 361 {
431 GNUNET_array_append (lsocks, ls, 362 GNUNET_array_append (lsocks, ls,
432 GNUNET_NETWORK_get_fd (sli->listen_socket)); 363 GNUNET_NETWORK_get_fd (sli->listen_socket));
433 if (sli->accept_task != NULL) 364 if (NULL != sli->accept_task)
434 { 365 {
435 GNUNET_SCHEDULER_cancel (sli->accept_task); 366 GNUNET_SCHEDULER_cancel (sli->accept_task);
436 sli->accept_task = NULL; 367 sli->accept_task = NULL;
437 } 368 }
438 } 369 }
439#if WINDOWS 370#if WINDOWS
440 GNUNET_array_append (lsocks, ls, INVALID_SOCKET); 371 GNUNET_array_append (lsocks,
372 ls,
373 INVALID_SOCKET);
441#else 374#else
442 GNUNET_array_append (lsocks, ls, -1); 375 GNUNET_array_append (lsocks,
376 ls,
377 -1);
443#endif 378#endif
444 379
445 /* obtain configuration */ 380 /* obtain configuration */
@@ -463,7 +398,8 @@ start_process (struct ServiceList *sl,
463 398
464 fin_options = GNUNET_strdup (final_option); 399 fin_options = GNUNET_strdup (final_option);
465 /* replace '{}' with service name */ 400 /* replace '{}' with service name */
466 while (NULL != (optpos = strstr (fin_options, "{}"))) 401 while (NULL != (optpos = strstr (fin_options,
402 "{}")))
467 { 403 {
468 /* terminate string at opening parenthesis */ 404 /* terminate string at opening parenthesis */
469 *optpos = 0; 405 *optpos = 0;
@@ -597,7 +533,7 @@ start_process (struct ServiceList *sl,
597 } 533 }
598 GNUNET_free (binary); 534 GNUNET_free (binary);
599 GNUNET_free (quotedbinary); 535 GNUNET_free (quotedbinary);
600 if (sl->proc == NULL) 536 if (NULL == sl->proc)
601 { 537 {
602 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 538 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
603 _("Failed to start service `%s'\n"), 539 _("Failed to start service `%s'\n"),
@@ -613,14 +549,21 @@ start_process (struct ServiceList *sl,
613 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 549 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
614 _("Starting service `%s'\n"), 550 _("Starting service `%s'\n"),
615 sl->name); 551 sl->name);
616 broadcast_status (sl->name, GNUNET_ARM_SERVICE_STARTING, NULL); 552 broadcast_status (sl->name,
553 GNUNET_ARM_SERVICE_STARTING,
554 NULL);
617 if (client) 555 if (client)
618 signal_result (client, sl->name, request_id, GNUNET_ARM_RESULT_STARTING); 556 signal_result (client,
557 sl->name,
558 request_id,
559 GNUNET_ARM_RESULT_STARTING);
619 } 560 }
620 /* clean up */ 561 /* clean up */
621 GNUNET_free (loprefix); 562 GNUNET_free (loprefix);
622 GNUNET_free (options); 563 GNUNET_free (options);
623 GNUNET_array_grow (lsocks, ls, 0); 564 GNUNET_array_grow (lsocks,
565 ls,
566 0);
624} 567}
625 568
626 569
@@ -689,15 +632,23 @@ create_listen_socket (struct sockaddr *sa,
689 switch (sa->sa_family) 632 switch (sa->sa_family)
690 { 633 {
691 case AF_INET: 634 case AF_INET:
692 sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0); 635 sock = GNUNET_NETWORK_socket_create (PF_INET,
636 SOCK_STREAM,
637 0);
693 break; 638 break;
694 case AF_INET6: 639 case AF_INET6:
695 sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); 640 sock = GNUNET_NETWORK_socket_create (PF_INET6,
641 SOCK_STREAM,
642 0);
696 break; 643 break;
697 case AF_UNIX: 644 case AF_UNIX:
698 if (strcmp (GNUNET_a2s (sa, addr_len), "@") == 0) /* Do not bind to blank UNIX path! */ 645 if (0 == strcmp (GNUNET_a2s (sa,
646 addr_len),
647 "@")) /* Do not bind to blank UNIX path! */
699 return; 648 return;
700 sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0); 649 sock = GNUNET_NETWORK_socket_create (PF_UNIX,
650 SOCK_STREAM,
651 0);
701 break; 652 break;
702 default: 653 default:
703 GNUNET_break (0); 654 GNUNET_break (0);
@@ -709,18 +660,27 @@ create_listen_socket (struct sockaddr *sa,
709 { 660 {
710 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 661 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
711 _("Unable to create socket for service `%s': %s\n"), 662 _("Unable to create socket for service `%s': %s\n"),
712 sl->name, STRERROR (errno)); 663 sl->name,
664 STRERROR (errno));
713 GNUNET_free (sa); 665 GNUNET_free (sa);
714 return; 666 return;
715 } 667 }
716 if (GNUNET_NETWORK_socket_setsockopt 668 if (GNUNET_OK !=
717 (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK) 669 GNUNET_NETWORK_socket_setsockopt (sock,
670 SOL_SOCKET,
671 SO_REUSEADDR,
672 &on,
673 sizeof (on)))
718 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 674 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
719 "setsockopt"); 675 "setsockopt");
720#ifdef IPV6_V6ONLY 676#ifdef IPV6_V6ONLY
721 if ((sa->sa_family == AF_INET6) && 677 if ( (sa->sa_family == AF_INET6) &&
722 (GNUNET_NETWORK_socket_setsockopt 678 (GNUNET_OK !=
723 (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK)) 679 GNUNET_NETWORK_socket_setsockopt (sock,
680 IPPROTO_IPV6,
681 IPV6_V6ONLY,
682 &on,
683 sizeof (on))) )
724 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 684 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
725 "setsockopt"); 685 "setsockopt");
726#endif 686#endif
@@ -729,14 +689,18 @@ create_listen_socket (struct sockaddr *sa,
729 GNUNET_NETWORK_unix_precheck ((struct sockaddr_un *) sa); 689 GNUNET_NETWORK_unix_precheck ((struct sockaddr_un *) sa);
730#endif 690#endif
731 if (GNUNET_OK != 691 if (GNUNET_OK !=
732 GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len)) 692 GNUNET_NETWORK_socket_bind (sock,
693 (const struct sockaddr *) sa,
694 addr_len))
733 { 695 {
734 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 696 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
735 _("Unable to bind listening socket for service `%s' to address `%s': %s\n"), 697 _("Unable to bind listening socket for service `%s' to address `%s': %s\n"),
736 sl->name, 698 sl->name,
737 GNUNET_a2s (sa, addr_len), 699 GNUNET_a2s (sa,
700 addr_len),
738 STRERROR (errno)); 701 STRERROR (errno));
739 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); 702 GNUNET_break (GNUNET_OK ==
703 GNUNET_NETWORK_socket_close (sock));
740 GNUNET_free (sa); 704 GNUNET_free (sa);
741 return; 705 return;
742 } 706 }
@@ -749,10 +713,12 @@ create_listen_socket (struct sockaddr *sa,
749 ) 713 )
750 { 714 {
751 match_uid = 715 match_uid =
752 GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, 716 GNUNET_CONFIGURATION_get_value_yesno (cfg,
717 sl->name,
753 "UNIX_MATCH_UID"); 718 "UNIX_MATCH_UID");
754 match_gid = 719 match_gid =
755 GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, 720 GNUNET_CONFIGURATION_get_value_yesno (cfg,
721 sl->name,
756 "UNIX_MATCH_GID"); 722 "UNIX_MATCH_GID");
757 GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sa)->sun_path, 723 GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sa)->sun_path,
758 match_uid, 724 match_uid,
@@ -760,24 +726,30 @@ create_listen_socket (struct sockaddr *sa,
760 726
761 } 727 }
762#endif 728#endif
763 if (GNUNET_NETWORK_socket_listen (sock, 5) != GNUNET_OK) 729 if (GNUNET_OK !=
730 GNUNET_NETWORK_socket_listen (sock, 5))
764 { 731 {
765 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen"); 732 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
766 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); 733 "listen");
734 GNUNET_break (GNUNET_OK ==
735 GNUNET_NETWORK_socket_close (sock));
767 GNUNET_free (sa); 736 GNUNET_free (sa);
768 return; 737 return;
769 } 738 }
770 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 739 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
771 _("ARM now monitors connections to service `%s' at `%s'\n"), 740 _("ARM now monitors connections to service `%s' at `%s'\n"),
772 sl->name, GNUNET_a2s (sa, addr_len)); 741 sl->name,
742 GNUNET_a2s (sa,
743 addr_len));
773 sli = GNUNET_new (struct ServiceListeningInfo); 744 sli = GNUNET_new (struct ServiceListeningInfo);
774 sli->service_addr = sa; 745 sli->service_addr = sa;
775 sli->service_addr_len = addr_len; 746 sli->service_addr_len = addr_len;
776 sli->listen_socket = sock; 747 sli->listen_socket = sock;
777 sli->sl = sl; 748 sli->sl = sl;
778 sli->accept_task = 749 sli->accept_task
779 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, sock, 750 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
780 &accept_connection, sli); 751 sock,
752 &accept_connection, sli);
781 GNUNET_CONTAINER_DLL_insert (sl->listen_head, 753 GNUNET_CONTAINER_DLL_insert (sl->listen_head,
782 sl->listen_tail, 754 sl->listen_tail,
783 sli); 755 sli);
@@ -794,7 +766,9 @@ static void
794free_service (struct ServiceList *sl) 766free_service (struct ServiceList *sl)
795{ 767{
796 GNUNET_assert (GNUNET_YES == in_shutdown); 768 GNUNET_assert (GNUNET_YES == in_shutdown);
797 GNUNET_CONTAINER_DLL_remove (running_head, running_tail, sl); 769 GNUNET_CONTAINER_DLL_remove (running_head,
770 running_tail,
771 sl);
798 GNUNET_assert (NULL == sl->listen_head); 772 GNUNET_assert (NULL == sl->listen_head);
799 GNUNET_free_non_null (sl->config); 773 GNUNET_free_non_null (sl->config);
800 GNUNET_free_non_null (sl->binary); 774 GNUNET_free_non_null (sl->binary);
@@ -804,61 +778,79 @@ free_service (struct ServiceList *sl)
804 778
805 779
806/** 780/**
807 * Handle START-message. 781 * Check START-message.
808 * 782 *
809 * @param cls closure (always NULL) 783 * @param cls identification of the client
810 * @param client identification of the client 784 * @param amsg the actual message
811 * @param message the actual message
812 * @return #GNUNET_OK to keep the connection open, 785 * @return #GNUNET_OK to keep the connection open,
813 * #GNUNET_SYSERR to close it (signal serious error) 786 * #GNUNET_SYSERR to close it (signal serious error)
814 */ 787 */
788static int
789check_start (void *cls,
790 const struct GNUNET_ARM_Message *amsg)
791{
792 uint16_t size;
793 const char *servicename;
794
795 size = ntohs (amsg->header.size) - sizeof (struct GNUNET_ARM_Message);
796 servicename = (const char *) &amsg[1];
797 if ( (0 == size) ||
798 (servicename[size - 1] != '\0') )
799 {
800 GNUNET_break (0);
801 return GNUNET_SYSERR;
802 }
803 return GNUNET_OK;
804}
805
806
807/**
808 * Handle START-message.
809 *
810 * @param cls identification of the client
811 * @param amsg the actual message
812 */
815static void 813static void
816handle_start (void *cls, 814handle_start (void *cls,
817 struct GNUNET_SERVER_Client *client, 815 const struct GNUNET_ARM_Message *amsg)
818 const struct GNUNET_MessageHeader *message)
819{ 816{
817 struct GNUNET_SERVICE_Client *client = cls;
820 const char *servicename; 818 const char *servicename;
821 struct ServiceList *sl; 819 struct ServiceList *sl;
822 uint16_t size;
823 uint64_t request_id; 820 uint64_t request_id;
824 struct GNUNET_ARM_Message *amsg;
825 821
826 amsg = (struct GNUNET_ARM_Message *) message;
827 request_id = GNUNET_ntohll (amsg->request_id); 822 request_id = GNUNET_ntohll (amsg->request_id);
828 size = ntohs (amsg->header.size);
829 size -= sizeof (struct GNUNET_ARM_Message);
830 servicename = (const char *) &amsg[1]; 823 servicename = (const char *) &amsg[1];
831 if ((size == 0) || (servicename[size - 1] != '\0')) 824 GNUNET_SERVICE_client_continue (client);
832 {
833 GNUNET_break (0);
834 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
835 return;
836 }
837 if (GNUNET_YES == in_shutdown) 825 if (GNUNET_YES == in_shutdown)
838 { 826 {
839 signal_result (client, servicename, request_id, 827 signal_result (client,
828 servicename,
829 request_id,
840 GNUNET_ARM_RESULT_IN_SHUTDOWN); 830 GNUNET_ARM_RESULT_IN_SHUTDOWN);
841 GNUNET_SERVER_receive_done (client, GNUNET_OK);
842 return; 831 return;
843 } 832 }
844 sl = find_service (servicename); 833 sl = find_service (servicename);
845 if (NULL == sl) 834 if (NULL == sl)
846 { 835 {
847 signal_result (client, servicename, request_id, 836 signal_result (client,
837 servicename,
838 request_id,
848 GNUNET_ARM_RESULT_IS_NOT_KNOWN); 839 GNUNET_ARM_RESULT_IS_NOT_KNOWN);
849 GNUNET_SERVER_receive_done (client, GNUNET_OK);
850 return; 840 return;
851 } 841 }
852 sl->force_start = GNUNET_YES; 842 sl->force_start = GNUNET_YES;
853 if (NULL != sl->proc) 843 if (NULL != sl->proc)
854 { 844 {
855 signal_result (client, servicename, request_id, 845 signal_result (client,
846 servicename,
847 request_id,
856 GNUNET_ARM_RESULT_IS_STARTED_ALREADY); 848 GNUNET_ARM_RESULT_IS_STARTED_ALREADY);
857 GNUNET_SERVER_receive_done (client, GNUNET_OK);
858 return; 849 return;
859 } 850 }
860 start_process (sl, client, request_id); 851 start_process (sl,
861 GNUNET_SERVER_receive_done (client, GNUNET_OK); 852 client,
853 request_id);
862} 854}
863 855
864 856
@@ -877,73 +869,87 @@ trigger_shutdown (void *cls)
877 869
878 870
879/** 871/**
880 * Handle STOP-message. 872 * Check STOP-message.
881 * 873 *
882 * @param cls closure (always NULL) 874 * @param cls identification of the client
883 * @param client identification of the client 875 * @param amsg the actual message
884 * @param message the actual message
885 * @return #GNUNET_OK to keep the connection open, 876 * @return #GNUNET_OK to keep the connection open,
886 * #GNUNET_SYSERR to close it (signal serious error) 877 * #GNUNET_SYSERR to close it (signal serious error)
887 */ 878 */
879static int
880check_stop (void *cls,
881 const struct GNUNET_ARM_Message *amsg)
882{
883 uint16_t size;
884 const char *servicename;
885
886 size = ntohs (amsg->header.size) - sizeof (struct GNUNET_ARM_Message);
887 servicename = (const char *) &amsg[1];
888 if ( (0 == size) ||
889 (servicename[size - 1] != '\0') )
890 {
891 GNUNET_break (0);
892 return GNUNET_SYSERR;
893 }
894 return GNUNET_OK;
895}
896
897
898/**
899 * Handle STOP-message.
900 *
901 * @param cls identification of the client
902 * @param amsg the actual message
903 */
888static void 904static void
889handle_stop (void *cls, 905handle_stop (void *cls,
890 struct GNUNET_SERVER_Client *client, 906 const struct GNUNET_ARM_Message *amsg)
891 const struct GNUNET_MessageHeader *message)
892{ 907{
908 struct GNUNET_SERVICE_Client *client = cls;
893 struct ServiceList *sl; 909 struct ServiceList *sl;
894 const char *servicename; 910 const char *servicename;
895 uint16_t size;
896 uint64_t request_id; 911 uint64_t request_id;
897 struct GNUNET_ARM_Message *amsg;
898 912
899 amsg = (struct GNUNET_ARM_Message *) message;
900 request_id = GNUNET_ntohll (amsg->request_id); 913 request_id = GNUNET_ntohll (amsg->request_id);
901 size = ntohs (amsg->header.size);
902 size -= sizeof (struct GNUNET_ARM_Message);
903 servicename = (const char *) &amsg[1]; 914 servicename = (const char *) &amsg[1];
904 if ((size == 0) || (servicename[size - 1] != '\0'))
905 {
906 GNUNET_break (0);
907 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
908 return;
909 }
910 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 915 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
911 _("Preparing to stop `%s'\n"), 916 _("Preparing to stop `%s'\n"),
912 servicename); 917 servicename);
913 if (0 == strcasecmp (servicename, "arm")) 918 GNUNET_SERVICE_client_continue (client);
919 if (0 == strcasecmp (servicename,
920 "arm"))
914 { 921 {
915 broadcast_status (servicename, 922 broadcast_status (servicename,
916 GNUNET_ARM_SERVICE_STOPPING, NULL); 923 GNUNET_ARM_SERVICE_STOPPING,
924 NULL);
917 signal_result (client, 925 signal_result (client,
918 servicename, 926 servicename,
919 request_id, 927 request_id,
920 GNUNET_ARM_RESULT_STOPPING); 928 GNUNET_ARM_RESULT_STOPPING);
921 GNUNET_SERVER_client_persist_ (client); 929 GNUNET_SERVICE_client_persist (client);
922 GNUNET_SCHEDULER_add_now (&trigger_shutdown, NULL); 930 GNUNET_SCHEDULER_add_now (&trigger_shutdown,
923 GNUNET_SERVER_receive_done (client, GNUNET_OK); 931 NULL);
924 return; 932 return;
925 } 933 }
926 sl = find_service (servicename); 934 sl = find_service (servicename);
927 if (sl == NULL) 935 if (NULL == sl)
928 { 936 {
929 signal_result (client, 937 signal_result (client,
930 servicename, 938 servicename,
931 request_id, 939 request_id,
932 GNUNET_ARM_RESULT_IS_NOT_KNOWN); 940 GNUNET_ARM_RESULT_IS_NOT_KNOWN);
933 GNUNET_SERVER_receive_done (client, GNUNET_OK); 941 return;
934 return; 942 }
935 }
936 sl->force_start = GNUNET_NO; 943 sl->force_start = GNUNET_NO;
937 if (GNUNET_YES == in_shutdown) 944 if (GNUNET_YES == in_shutdown)
938 { 945 {
939 /* shutdown in progress */ 946 /* shutdown in progress */
940 signal_result (client, 947 signal_result (client,
941 servicename, 948 servicename,
942 request_id, 949 request_id,
943 GNUNET_ARM_RESULT_IN_SHUTDOWN); 950 GNUNET_ARM_RESULT_IN_SHUTDOWN);
944 GNUNET_SERVER_receive_done (client, GNUNET_OK); 951 return;
945 return; 952 }
946 }
947 if (NULL != sl->killing_client) 953 if (NULL != sl->killing_client)
948 { 954 {
949 /* killing already in progress */ 955 /* killing already in progress */
@@ -951,7 +957,6 @@ handle_stop (void *cls,
951 servicename, 957 servicename,
952 request_id, 958 request_id,
953 GNUNET_ARM_RESULT_IS_STOPPING_ALREADY); 959 GNUNET_ARM_RESULT_IS_STOPPING_ALREADY);
954 GNUNET_SERVER_receive_done (client, GNUNET_OK);
955 return; 960 return;
956 } 961 }
957 if (NULL == sl->proc) 962 if (NULL == sl->proc)
@@ -961,7 +966,6 @@ handle_stop (void *cls,
961 servicename, 966 servicename,
962 request_id, 967 request_id,
963 GNUNET_ARM_RESULT_IS_STOPPED_ALREADY); 968 GNUNET_ARM_RESULT_IS_STOPPED_ALREADY);
964 GNUNET_SERVER_receive_done (client, GNUNET_OK);
965 return; 969 return;
966 } 970 }
967 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 971 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -972,41 +976,37 @@ handle_stop (void *cls,
972 NULL); 976 NULL);
973 /* no signal_start - only when it's STOPPED */ 977 /* no signal_start - only when it's STOPPED */
974 sl->killed_at = GNUNET_TIME_absolute_get (); 978 sl->killed_at = GNUNET_TIME_absolute_get ();
975 if (0 != GNUNET_OS_process_kill (sl->proc, GNUNET_TERM_SIG)) 979 if (0 != GNUNET_OS_process_kill (sl->proc,
976 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); 980 GNUNET_TERM_SIG))
981 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
982 "kill");
977 sl->killing_client = client; 983 sl->killing_client = client;
978 sl->killing_client_request_id = request_id; 984 sl->killing_client_request_id = request_id;
979 GNUNET_SERVER_client_keep (client);
980 GNUNET_SERVER_receive_done (client, GNUNET_OK);
981} 985}
982 986
983 987
984/** 988/**
985 * Handle LIST-message. 989 * Handle LIST-message.
986 * 990 *
987 * @param cls closure (always NULL) 991 * @param cls identification of the client
988 * @param client identification of the client
989 * @param message the actual message 992 * @param message the actual message
990 */ 993 */
991static void 994static void
992handle_list (void *cls, 995handle_list (void *cls,
993 struct GNUNET_SERVER_Client *client, 996 const struct GNUNET_ARM_Message *request)
994 const struct GNUNET_MessageHeader *message)
995{ 997{
998 struct GNUNET_SERVICE_Client *client = cls;
999 struct GNUNET_MQ_Envelope *env;
996 struct GNUNET_ARM_ListResultMessage *msg; 1000 struct GNUNET_ARM_ListResultMessage *msg;
997 struct GNUNET_ARM_Message *request;
998 size_t string_list_size; 1001 size_t string_list_size;
999 size_t total_size;
1000 struct ServiceList *sl; 1002 struct ServiceList *sl;
1001 uint16_t count; 1003 uint16_t count;
1004 char *pos;
1002 1005
1003 if (NULL == client)
1004 return;
1005
1006 request = (struct GNUNET_ARM_Message *) message;
1007 GNUNET_break (0 == ntohl (request->reserved)); 1006 GNUNET_break (0 == ntohl (request->reserved));
1008 count = 0; 1007 count = 0;
1009 string_list_size = 0; 1008 string_list_size = 0;
1009
1010 /* first count the running processes get their name's size */ 1010 /* first count the running processes get their name's size */
1011 for (sl = running_head; NULL != sl; sl = sl->next) 1011 for (sl = running_head; NULL != sl; sl = sl->next)
1012 { 1012 {
@@ -1019,30 +1019,51 @@ handle_list (void *cls,
1019 } 1019 }
1020 } 1020 }
1021 1021
1022 total_size = sizeof (struct GNUNET_ARM_ListResultMessage) 1022 env = GNUNET_MQ_msg_extra (msg,
1023 + string_list_size; 1023 string_list_size,
1024 msg = GNUNET_malloc (total_size); 1024 GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT);
1025 msg->arm_msg.header.size = total_size; 1025 msg->arm_msg.request_id = request->request_id;
1026 msg->arm_msg.header.type = GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT; 1026 msg->count = htons (count);
1027 msg->arm_msg.reserved = htonl (0);
1028 msg->arm_msg.request_id = GNUNET_ntohll (request->request_id);
1029 msg->count = count;
1030 1027
1031 char *pos = (char *)&msg[1]; 1028 pos = (char *) &msg[1];
1032 for (sl = running_head; NULL != sl; sl = sl->next) 1029 for (sl = running_head; NULL != sl; sl = sl->next)
1033 { 1030 {
1034 if (NULL != sl->proc) 1031 if (NULL != sl->proc)
1035 { 1032 {
1036 size_t s = strlen (sl->name) + strlen (sl->binary) + 4; 1033 size_t s = strlen (sl->name) + strlen (sl->binary) + 4;
1037 GNUNET_snprintf (pos, s, "%s (%s)", sl->name, sl->binary); 1034 GNUNET_snprintf (pos,
1035 s,
1036 "%s (%s)",
1037 sl->name,
1038 sl->binary);
1038 pos += s; 1039 pos += s;
1039 } 1040 }
1040 } 1041 }
1041 GNUNET_SERVER_notify_transmit_ready (client, 1042 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
1042 total_size, 1043 env);
1043 GNUNET_TIME_UNIT_FOREVER_REL, 1044 GNUNET_SERVICE_client_continue (client);
1044 &write_list_result, msg); 1045}
1045 GNUNET_SERVER_receive_done (client, GNUNET_OK); 1046
1047
1048/**
1049 * Handle TEST-message by sending back TEST.
1050 *
1051 * @param cls identification of the client
1052 * @param message the actual message
1053 */
1054static void
1055handle_test (void *cls,
1056 const struct GNUNET_MessageHeader *message)
1057{
1058 struct GNUNET_SERVICE_Client *client = cls;
1059 struct GNUNET_MQ_Envelope *env;
1060 struct GNUNET_MessageHeader *msg;
1061
1062 env = GNUNET_MQ_msg (msg,
1063 GNUNET_MESSAGE_TYPE_ARM_TEST);
1064 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
1065 env);
1066 GNUNET_SERVICE_client_continue (client);
1046} 1067}
1047 1068
1048 1069
@@ -1053,22 +1074,23 @@ handle_list (void *cls,
1053static void 1074static void
1054do_shutdown () 1075do_shutdown ()
1055{ 1076{
1056 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last shutdown phase\n"); 1077 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1078 "Last shutdown phase\n");
1057 if (NULL != notifier) 1079 if (NULL != notifier)
1058 { 1080 {
1059 GNUNET_SERVER_notification_context_destroy (notifier); 1081 GNUNET_notification_context_destroy (notifier);
1060 notifier = NULL; 1082 notifier = NULL;
1061 } 1083 }
1062 if (NULL != server) 1084 if (NULL != service)
1063 { 1085 {
1064 GNUNET_SERVER_destroy (server); 1086 GNUNET_SERVICE_shutdown (service);
1065 server = NULL; 1087 service = NULL;
1066 } 1088 }
1067 if (NULL != child_death_task) 1089 if (NULL != child_death_task)
1068 { 1090 {
1069 GNUNET_SCHEDULER_cancel (child_death_task); 1091 GNUNET_SCHEDULER_cancel (child_death_task);
1070 child_death_task = NULL; 1092 child_death_task = NULL;
1071 } 1093 }
1072} 1094}
1073 1095
1074 1096
@@ -1082,7 +1104,7 @@ static unsigned int
1082list_count (struct ServiceList *running_head) 1104list_count (struct ServiceList *running_head)
1083{ 1105{
1084 struct ServiceList *i; 1106 struct ServiceList *i;
1085 unsigned int res = 0; 1107 unsigned int res;
1086 1108
1087 for (res = 0, i = running_head; i; i = i->next, res++) 1109 for (res = 0, i = running_head; i; i = i->next, res++)
1088 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1110 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1116,20 +1138,20 @@ shutdown_task (void *cls)
1116 for (pos = running_head; NULL != pos; pos = pos->next) 1138 for (pos = running_head; NULL != pos; pos = pos->next)
1117 { 1139 {
1118 while (NULL != (sli = pos->listen_head)) 1140 while (NULL != (sli = pos->listen_head))
1141 {
1142 GNUNET_CONTAINER_DLL_remove (pos->listen_head,
1143 pos->listen_tail,
1144 sli);
1145 if (NULL != sli->accept_task)
1119 { 1146 {
1120 GNUNET_CONTAINER_DLL_remove (pos->listen_head, 1147 GNUNET_SCHEDULER_cancel (sli->accept_task);
1121 pos->listen_tail, 1148 sli->accept_task = NULL;
1122 sli);
1123 if (NULL != sli->accept_task)
1124 {
1125 GNUNET_SCHEDULER_cancel (sli->accept_task);
1126 sli->accept_task = NULL;
1127 }
1128 GNUNET_break (GNUNET_OK ==
1129 GNUNET_NETWORK_socket_close (sli->listen_socket));
1130 GNUNET_free (sli->service_addr);
1131 GNUNET_free (sli);
1132 } 1149 }
1150 GNUNET_break (GNUNET_OK ==
1151 GNUNET_NETWORK_socket_close (sli->listen_socket));
1152 GNUNET_free (sli->service_addr);
1153 GNUNET_free (sli);
1154 }
1133 } 1155 }
1134 /* then, shutdown all existing service processes */ 1156 /* then, shutdown all existing service processes */
1135 nxt = running_head; 1157 nxt = running_head;
@@ -1142,8 +1164,10 @@ shutdown_task (void *cls)
1142 "Stopping service `%s'\n", 1164 "Stopping service `%s'\n",
1143 pos->name); 1165 pos->name);
1144 pos->killed_at = GNUNET_TIME_absolute_get (); 1166 pos->killed_at = GNUNET_TIME_absolute_get ();
1145 if (0 != GNUNET_OS_process_kill (pos->proc, GNUNET_TERM_SIG)) 1167 if (0 != GNUNET_OS_process_kill (pos->proc,
1146 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); 1168 GNUNET_TERM_SIG))
1169 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1170 "kill");
1147 } 1171 }
1148 else 1172 else
1149 { 1173 {
@@ -1193,7 +1217,9 @@ delayed_restart_task (void *cls)
1193 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1217 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1194 _("Restarting service `%s'.\n"), 1218 _("Restarting service `%s'.\n"),
1195 sl->name); 1219 sl->name);
1196 start_process (sl, NULL, 0); 1220 start_process (sl,
1221 NULL,
1222 0);
1197 } 1223 }
1198 else 1224 else
1199 { 1225 {
@@ -1202,11 +1228,11 @@ delayed_restart_task (void *cls)
1202 if (NULL == sli->accept_task) 1228 if (NULL == sli->accept_task)
1203 { 1229 {
1204 /* accept was actually paused, so start it again */ 1230 /* accept was actually paused, so start it again */
1205 sli->accept_task = 1231 sli->accept_task
1206 GNUNET_SCHEDULER_add_read_net 1232 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1207 (GNUNET_TIME_UNIT_FOREVER_REL, 1233 sli->listen_socket,
1208 sli->listen_socket, 1234 &accept_connection,
1209 &accept_connection, sli); 1235 sli);
1210 } 1236 }
1211 } 1237 }
1212 } 1238 }
@@ -1223,11 +1249,13 @@ delayed_restart_task (void *cls)
1223 { 1249 {
1224 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1250 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1225 "Will restart process in %s\n", 1251 "Will restart process in %s\n",
1226 GNUNET_STRINGS_relative_time_to_string (lowestRestartDelay, GNUNET_YES)); 1252 GNUNET_STRINGS_relative_time_to_string (lowestRestartDelay,
1253 GNUNET_YES));
1227 child_restart_task = 1254 child_restart_task =
1228 GNUNET_SCHEDULER_add_delayed_with_priority (lowestRestartDelay, 1255 GNUNET_SCHEDULER_add_delayed_with_priority (lowestRestartDelay,
1229 GNUNET_SCHEDULER_PRIORITY_IDLE, 1256 GNUNET_SCHEDULER_PRIORITY_IDLE,
1230 &delayed_restart_task, NULL); 1257 &delayed_restart_task,
1258 NULL);
1231 } 1259 }
1232} 1260}
1233 1261
@@ -1256,7 +1284,9 @@ maint_child_death (void *cls)
1256 GNUNET_DISK_PIPE_END_READ); 1284 GNUNET_DISK_PIPE_END_READ);
1257 child_death_task = NULL; 1285 child_death_task = NULL;
1258 /* consume the signal */ 1286 /* consume the signal */
1259 GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c))); 1287 GNUNET_break (0 < GNUNET_DISK_file_read (pr,
1288 &c,
1289 sizeof (c)));
1260 1290
1261 /* check for services that died (WAITPID) */ 1291 /* check for services that died (WAITPID) */
1262 next = running_head; 1292 next = running_head;
@@ -1376,7 +1406,6 @@ maint_child_death (void *cls)
1376 signal_result (pos->killing_client, pos->name, 1406 signal_result (pos->killing_client, pos->name,
1377 pos->killing_client_request_id, 1407 pos->killing_client_request_id,
1378 GNUNET_ARM_RESULT_STOPPED); 1408 GNUNET_ARM_RESULT_STOPPED);
1379 GNUNET_SERVER_client_drop (pos->killing_client);
1380 pos->killing_client = NULL; 1409 pos->killing_client = NULL;
1381 pos->killing_client_request_id = 0; 1410 pos->killing_client_request_id = 0;
1382 } 1411 }
@@ -1451,9 +1480,10 @@ sighandler_child_death ()
1451 int old_errno = errno; /* back-up errno */ 1480 int old_errno = errno; /* back-up errno */
1452 1481
1453 GNUNET_break (1 == 1482 GNUNET_break (1 ==
1454 GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle 1483 GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe,
1455 (sigpipe, GNUNET_DISK_PIPE_END_WRITE), 1484 GNUNET_DISK_PIPE_END_WRITE),
1456 &c, sizeof (c))); 1485 &c,
1486 sizeof (c)));
1457 errno = old_errno; /* restore errno */ 1487 errno = old_errno; /* restore errno */
1458} 1488}
1459 1489
@@ -1479,7 +1509,8 @@ setup_service (void *cls,
1479 int ret; 1509 int ret;
1480 unsigned int i; 1510 unsigned int i;
1481 1511
1482 if (strcasecmp (section, "arm") == 0) 1512 if (0 == strcasecmp (section,
1513 "arm"))
1483 return; 1514 return;
1484 if (GNUNET_OK != 1515 if (GNUNET_OK !=
1485 GNUNET_CONFIGURATION_get_value_filename (cfg, 1516 GNUNET_CONFIGURATION_get_value_filename (cfg,
@@ -1597,46 +1628,71 @@ setup_service (void *cls,
1597 1628
1598 1629
1599/** 1630/**
1600 * A client connected, add it to the notification context. 1631 * A client connected, mark as a monitoring client.
1601 * 1632 *
1602 * @param cls closure 1633 * @param cls closure
1603 * @param client identification of the client 1634 * @param client identification of the client
1635 * @param mq queue to talk to @a client
1636 * @return @a client
1604 */ 1637 */
1605static void 1638static void *
1606handle_client_connecting (void *cls, 1639client_connect_cb (void *cls,
1607 struct GNUNET_SERVER_Client *client) 1640 struct GNUNET_SERVICE_Client *client,
1641 struct GNUNET_MQ_Handle *mq)
1608{ 1642{
1609 /* All clients are considered to be of the "monitor" kind 1643 /* All clients are considered to be of the "monitor" kind
1610 * (that is, they don't affect ARM shutdown). 1644 * (that is, they don't affect ARM shutdown).
1611 */ 1645 */
1612 if (NULL != client) 1646 GNUNET_SERVICE_client_mark_monitor (client);
1613 GNUNET_SERVER_client_mark_monitor (client); 1647 return client;
1614} 1648}
1615 1649
1616 1650
1617/** 1651/**
1618 * Handle MONITOR-message. 1652 * A client disconnected, clean up associated state.
1619 * 1653 *
1620 * @param cls closure (always NULL) 1654 * @param cls closure
1621 * @param client identification of the client 1655 * @param client identification of the client
1656 * @param app_ctx must match @a client
1657 */
1658static void
1659client_disconnect_cb (void *cls,
1660 struct GNUNET_SERVICE_Client *client,
1661 void *app_ctx)
1662{
1663 struct ServiceList *sl;
1664
1665 GNUNET_assert (client == app_ctx);
1666
1667 for (sl = running_head; NULL != sl; sl = sl->next)
1668 if (sl->killing_client == client)
1669 sl->killing_client = NULL;
1670}
1671
1672
1673/**
1674 * Handle MONITOR-message.
1675 *
1676 * @param cls identification of the client
1622 * @param message the actual message 1677 * @param message the actual message
1623 * @return #GNUNET_OK to keep the connection open, 1678 * @return #GNUNET_OK to keep the connection open,
1624 * #GNUNET_SYSERR to close it (signal serious error) 1679 * #GNUNET_SYSERR to close it (signal serious error)
1625 */ 1680 */
1626static void 1681static void
1627handle_monitor (void *cls, 1682handle_monitor (void *cls,
1628 struct GNUNET_SERVER_Client *client,
1629 const struct GNUNET_MessageHeader *message) 1683 const struct GNUNET_MessageHeader *message)
1630{ 1684{
1685 struct GNUNET_SERVICE_Client *client = cls;
1686
1631 /* FIXME: might want to start by letting monitor know about 1687 /* FIXME: might want to start by letting monitor know about
1632 services that are already running */ 1688 services that are already running */
1633 /* Removal is handled by the server implementation, internally. */ 1689 /* Removal is handled by the server implementation, internally. */
1634 if ((NULL != client) && (NULL != notifier)) 1690 GNUNET_notification_context_add (notifier,
1635 { 1691 GNUNET_SERVICE_client_get_mq (client));
1636 GNUNET_SERVER_notification_context_add (notifier, client); 1692 broadcast_status ("arm",
1637 broadcast_status ("arm", GNUNET_ARM_SERVICE_MONITORING_STARTED, client); 1693 GNUNET_ARM_SERVICE_MONITORING_STARTED,
1638 GNUNET_SERVER_receive_done (client, GNUNET_OK); 1694 client);
1639 } 1695 GNUNET_SERVICE_client_continue (client);
1640} 1696}
1641 1697
1642 1698
@@ -1644,34 +1700,26 @@ handle_monitor (void *cls,
1644 * Process arm requests. 1700 * Process arm requests.
1645 * 1701 *
1646 * @param cls closure 1702 * @param cls closure
1647 * @param serv the initialized server 1703 * @param serv the initialized service
1648 * @param c configuration to use 1704 * @param c configuration to use
1649 */ 1705 */
1650static void 1706static void
1651run (void *cls, struct GNUNET_SERVER_Handle *serv, 1707run (void *cls,
1652 const struct GNUNET_CONFIGURATION_Handle *c) 1708 const struct GNUNET_CONFIGURATION_Handle *c,
1709 struct GNUNET_SERVICE_Handle *serv)
1653{ 1710{
1654 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1655 {&handle_start, NULL, GNUNET_MESSAGE_TYPE_ARM_START, 0},
1656 {&handle_stop, NULL, GNUNET_MESSAGE_TYPE_ARM_STOP, 0},
1657 {&handle_monitor, NULL, GNUNET_MESSAGE_TYPE_ARM_MONITOR,
1658 sizeof (struct GNUNET_MessageHeader)},
1659 {&handle_list, NULL, GNUNET_MESSAGE_TYPE_ARM_LIST,
1660 sizeof (struct GNUNET_ARM_Message)},
1661 {NULL, NULL, 0, 0}
1662 };
1663 struct ServiceList *sl; 1711 struct ServiceList *sl;
1664 1712
1665 cfg = c; 1713 cfg = c;
1666 server = serv; 1714 service = serv;
1667 GNUNET_assert (NULL != serv);
1668 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, 1715 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
1669 NULL); 1716 NULL);
1670 child_death_task = 1717 child_death_task =
1671 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, 1718 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1672 GNUNET_DISK_pipe_handle (sigpipe, 1719 GNUNET_DISK_pipe_handle (sigpipe,
1673 GNUNET_DISK_PIPE_END_READ), 1720 GNUNET_DISK_PIPE_END_READ),
1674 &maint_child_death, NULL); 1721 &maint_child_death,
1722 NULL);
1675#if HAVE_WAIT4 1723#if HAVE_WAIT4
1676 if (GNUNET_OK == 1724 if (GNUNET_OK ==
1677 GNUNET_CONFIGURATION_get_value_filename (cfg, 1725 GNUNET_CONFIGURATION_get_value_filename (cfg,
@@ -1717,20 +1765,17 @@ run (void *cls, struct GNUNET_SERVER_Handle *serv,
1717 GNUNET_break (GNUNET_YES == start_system); 1765 GNUNET_break (GNUNET_YES == start_system);
1718 start_user = GNUNET_NO; 1766 start_user = GNUNET_NO;
1719 } 1767 }
1720 GNUNET_CONFIGURATION_iterate_sections (cfg, &setup_service, NULL); 1768 GNUNET_CONFIGURATION_iterate_sections (cfg,
1769 &setup_service,
1770 NULL);
1721 1771
1722 /* start default services... */ 1772 /* start default services... */
1723 for (sl = running_head; NULL != sl; sl = sl->next) 1773 for (sl = running_head; NULL != sl; sl = sl->next)
1724 if (GNUNET_YES == sl->force_start) 1774 if (GNUNET_YES == sl->force_start)
1725 start_process (sl, NULL, 0); 1775 start_process (sl,
1726 notifier 1776 NULL,
1727 = GNUNET_SERVER_notification_context_create (server, 1777 0);
1728 MAX_NOTIFY_QUEUE); 1778 notifier = GNUNET_notification_context_create (MAX_NOTIFY_QUEUE);
1729 GNUNET_SERVER_connect_notify (server,
1730 &handle_client_connecting, NULL);
1731 /* process client requests */
1732 GNUNET_SERVER_add_handlers (server,
1733 handlers);
1734} 1779}
1735 1780
1736 1781
@@ -1742,19 +1787,52 @@ run (void *cls, struct GNUNET_SERVER_Handle *serv,
1742 * @return 0 ok, 1 on error 1787 * @return 0 ok, 1 on error
1743 */ 1788 */
1744int 1789int
1745main (int argc, char *const *argv) 1790main (int argc,
1791 char *const *argv)
1746{ 1792{
1747 int ret; 1793 int ret;
1748 struct GNUNET_SIGNAL_Context *shc_chld; 1794 struct GNUNET_SIGNAL_Context *shc_chld;
1795 struct GNUNET_MQ_MessageHandler handlers[] = {
1796 GNUNET_MQ_hd_var_size (start,
1797 GNUNET_MESSAGE_TYPE_ARM_START,
1798 struct GNUNET_ARM_Message,
1799 NULL),
1800 GNUNET_MQ_hd_var_size (stop,
1801 GNUNET_MESSAGE_TYPE_ARM_STOP,
1802 struct GNUNET_ARM_Message,
1803 NULL),
1804 GNUNET_MQ_hd_fixed_size (monitor,
1805 GNUNET_MESSAGE_TYPE_ARM_MONITOR,
1806 struct GNUNET_MessageHeader,
1807 NULL),
1808 GNUNET_MQ_hd_fixed_size (list,
1809 GNUNET_MESSAGE_TYPE_ARM_LIST,
1810 struct GNUNET_ARM_Message,
1811 NULL),
1812 GNUNET_MQ_hd_fixed_size (test,
1813 GNUNET_MESSAGE_TYPE_ARM_TEST,
1814 struct GNUNET_MessageHeader,
1815 NULL),
1816 GNUNET_MQ_handler_end ()
1817 };
1749 1818
1750 sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO); 1819 sigpipe = GNUNET_DISK_pipe (GNUNET_NO,
1751 GNUNET_assert (sigpipe != NULL); 1820 GNUNET_NO,
1821 GNUNET_NO,
1822 GNUNET_NO);
1823 GNUNET_assert (NULL != sigpipe);
1752 shc_chld = 1824 shc_chld =
1753 GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); 1825 GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD,
1754 ret = 1826 &sighandler_child_death);
1755 (GNUNET_OK == 1827 ret = GNUNET_SERVICE_ruN_ (argc,
1756 GNUNET_SERVICE_run (argc, argv, "arm", 1828 argv,
1757 GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN, &run, NULL)) ? 0 : 1; 1829 "arm",
1830 GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN,
1831 &run,
1832 &client_connect_cb,
1833 &client_disconnect_cb,
1834 NULL,
1835 handlers);
1758#if HAVE_WAIT4 1836#if HAVE_WAIT4
1759 if (NULL != wait_file) 1837 if (NULL != wait_file)
1760 { 1838 {