aboutsummaryrefslogtreecommitdiff
path: root/src/arm
diff options
context:
space:
mode:
authorMaximilian Szengel <gnunet@maxsz.de>2012-02-29 08:59:39 +0000
committerMaximilian Szengel <gnunet@maxsz.de>2012-02-29 08:59:39 +0000
commitd8b052b2dd8e0242239b14bdd06854bff21cb3d0 (patch)
tree2e9c740f97f6f81c5cc7794d495e0fa6c188c0e3 /src/arm
parentfe1e67e9cab9d7bad0211c654ec90f1ef15b7c97 (diff)
downloadgnunet-d8b052b2dd8e0242239b14bdd06854bff21cb3d0.tar.gz
gnunet-d8b052b2dd8e0242239b14bdd06854bff21cb3d0.zip
Adding arm list/info feature.
Diffstat (limited to 'src/arm')
-rw-r--r--src/arm/arm.h21
-rw-r--r--src/arm/arm_api.c153
-rw-r--r--src/arm/gnunet-arm.c55
-rw-r--r--src/arm/gnunet-service-arm.c100
4 files changed, 326 insertions, 3 deletions
diff --git a/src/arm/arm.h b/src/arm/arm.h
index 4b9da6fab..21884107c 100644
--- a/src/arm/arm.h
+++ b/src/arm/arm.h
@@ -51,6 +51,27 @@ struct GNUNET_ARM_ResultMessage
51 */ 51 */
52 uint32_t status; 52 uint32_t status;
53}; 53};
54
55/**
56 * Reply from ARM to client for the
57 * GNUNET_MESSAGE_TYPE_ARM_LIST request followed by count
58 * '\0' terminated strings. header->size contains the
59 * total size (including all strings).
60 */
61struct GNUNET_ARM_ListResultMessage
62{
63 /**
64 * Reply to client is of type GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT
65 */
66 struct GNUNET_MessageHeader header;
67
68 /**
69 * Number of '\0' terminated strings that follow
70 * this message.
71 */
72 uint16_t count;
73};
74
54GNUNET_NETWORK_STRUCT_END 75GNUNET_NETWORK_STRUCT_END
55 76
56#endif 77#endif
diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c
index 0f4ae6a4f..d0babf0ae 100644
--- a/src/arm/arm_api.c
+++ b/src/arm/arm_api.c
@@ -52,7 +52,6 @@ struct GNUNET_ARM_Handle
52 52
53}; 53};
54 54
55
56/** 55/**
57 * Context for handling the shutdown of a service. 56 * Context for handling the shutdown of a service.
58 */ 57 */
@@ -487,6 +486,94 @@ handle_response (void *cls, const struct GNUNET_MessageHeader *msg)
487 GNUNET_free (sc); 486 GNUNET_free (sc);
488} 487}
489 488
489/**
490 * Internal state for a list request with ARM.
491 */
492struct ListRequestContext
493{
494
495 /**
496 * Pointer to our handle with ARM.
497 */
498 struct GNUNET_ARM_Handle *h;
499
500 /**
501 * Function to call with a status code for the requested operation.
502 */
503 GNUNET_ARM_List_Callback callback;
504
505 /**
506 * Closure for "callback".
507 */
508 void *cls;
509
510 /**
511 * Timeout for the operation.
512 */
513 struct GNUNET_TIME_Absolute timeout;
514};
515
516/**
517 * Process a response from ARM for the list request.
518 *
519 * @param cls the list request context
520 * @param msg the response
521 */
522static void
523handle_list_response (void *cls, const struct GNUNET_MessageHeader *msg)
524{
525 struct ListRequestContext *sc = cls;
526 const struct GNUNET_ARM_ListResultMessage *res;
527 int success;
528
529 if (msg == NULL)
530 {
531 LOG (GNUNET_ERROR_TYPE_WARNING,
532 "Error receiving response to LIST request from ARM\n");
533 GNUNET_CLIENT_disconnect (sc->h->client, GNUNET_NO);
534 sc->h->client = GNUNET_CLIENT_connect ("arm", sc->h->cfg);
535 GNUNET_assert (NULL != sc->h->client);
536 if (sc->callback != NULL)
537 sc->callback (sc->cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR, 0, NULL);
538 GNUNET_free (sc);
539 return;
540 }
541
542 if (sc->callback != NULL)
543 {
544 char **list;
545 const char *pos;
546 uint16_t size_check;
547
548 size_check = 0;
549 res = (const struct GNUNET_ARM_ListResultMessage *) msg;
550 success = (ntohs (res->header.type)
551 == GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT ?
552 GNUNET_YES : GNUNET_NO);
553 list = GNUNET_malloc (ntohs (res->count) * sizeof (char *));
554 pos = (const char *)&res[1];
555
556 int i;
557 for (i=0; i<ntohs (res->count); i++)
558 {
559 list[i] = GNUNET_malloc (strlen (pos) + 1);
560 memcpy (list[i], pos, strlen (pos) + 1);
561 pos += strlen (pos) + 1;
562 size_check += strlen (pos) +1;
563
564 if (size_check > ntohs (res->header.size))
565 {
566 GNUNET_free (list);
567 GNUNET_free (sc);
568 sc->callback (sc->cls, GNUNET_NO, 0, NULL);
569 return;
570 }
571 }
572
573 sc->callback (sc->cls, success, ntohs (res->count), (const char**)list);
574 }
575 GNUNET_free (sc);
576}
490 577
491/** 578/**
492 * Start or stop a service. 579 * Start or stop a service.
@@ -677,5 +764,69 @@ GNUNET_ARM_stop_service (struct GNUNET_ARM_Handle *h,
677 GNUNET_MESSAGE_TYPE_ARM_STOP); 764 GNUNET_MESSAGE_TYPE_ARM_STOP);
678} 765}
679 766
767/**
768 * List all running services.
769 *
770 * @param h handle to ARM
771 * @param timeout how long to wait before failing for good
772 * @param cb callback to invoke when service is ready
773 * @param cb_cls closure for callback
774 */
775void
776GNUNET_ARM_list_running_services (struct GNUNET_ARM_Handle *h,
777 struct GNUNET_TIME_Relative timeout,
778 GNUNET_ARM_List_Callback cb, void *cb_cls)
779{
780 struct ListRequestContext *sctx;
781 struct GNUNET_MessageHeader *msg;
782 struct GNUNET_CLIENT_Connection *client;
783
784 if (h->client == NULL)
785 {
786 client = GNUNET_CLIENT_connect ("arm", h->cfg);
787 if (client == NULL)
788 {
789 LOG (GNUNET_ERROR_TYPE_DEBUG,
790 "arm_api, GNUNET_CLIENT_connect returned NULL\n");
791 cb (cb_cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR, 0, NULL);
792 return;
793 }
794 LOG (GNUNET_ERROR_TYPE_DEBUG,
795 "arm_api, GNUNET_CLIENT_connect returned non-NULL\n");
796 h->client = client;
797 }
798
799 sctx = GNUNET_malloc (sizeof (struct RequestContext));
800 sctx->h = h;
801 sctx->callback = cb;
802 sctx->cls = cb_cls;
803 sctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
804 msg = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader));
805 msg->size = htons (sizeof (struct GNUNET_MessageHeader));
806 msg->type = htons (GNUNET_MESSAGE_TYPE_ARM_LIST);
807
808 LOG(GNUNET_ERROR_TYPE_DEBUG,
809 "Requesting LIST from ARM service with timeout: %llu ms\n",
810 (unsigned long long)timeout.rel_value);
811
812 if (GNUNET_OK !=
813 GNUNET_CLIENT_transmit_and_get_response (sctx->h->client,
814 msg,
815 GNUNET_TIME_absolute_get_remaining
816 (sctx->timeout),
817 GNUNET_YES,
818 &handle_list_response,
819 sctx))
820 {
821 LOG (GNUNET_ERROR_TYPE_WARNING,
822 "Error while trying to transmit request to list services to ARM\n");
823 if (cb != NULL)
824 cb (cb_cls, GNUNET_SYSERR, 0, NULL);
825 GNUNET_free (sctx);
826 GNUNET_free (msg);
827 return;
828 }
829 GNUNET_free (msg);
830}
680 831
681/* end of arm_api.c */ 832/* end of arm_api.c */
diff --git a/src/arm/gnunet-arm.c b/src/arm/gnunet-arm.c
index 65700ee11..f81cefa69 100644
--- a/src/arm/gnunet-arm.c
+++ b/src/arm/gnunet-arm.c
@@ -49,6 +49,11 @@
49#define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) 49#define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
50 50
51/** 51/**
52 * Timeout for listing all running services.
53 */
54#define LIST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
55
56/**
52 * Set if we are to shutdown all services (including ARM). 57 * Set if we are to shutdown all services (including ARM).
53 */ 58 */
54static int end; 59static int end;
@@ -74,6 +79,11 @@ static int delete;
74static int quiet; 79static int quiet;
75 80
76/** 81/**
82 * Set if we should print a list of currently running services.
83 */
84static int list;
85
86/**
77 * Set to the name of a service to start. 87 * Set to the name of a service to start.
78 */ 88 */
79static char *init; 89static char *init;
@@ -193,6 +203,31 @@ confirm_cb (void *cls,
193 GNUNET_SCHEDULER_REASON_PREREQ_DONE); 203 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
194} 204}
195 205
206/**
207 * Callback invoked with the list of running services.
208 * Reports to the user and then runs the next phase in the FSM.
209 *
210 * @param cls currently not used
211 * @param result result of the operation
212 * @param count number of running services
213 * @param list copy of the list of running services
214 */
215static void
216list_cb (void *cls, int result, uint16_t count, const char **list)
217{
218 if (result == GNUNET_YES && list != NULL)
219 {
220 FPRINTF (stdout, _("Running services:\n-----------------\n"));
221 int i;
222 for (i=0; i<count; i++)
223 {
224 FPRINTF (stdout, "%s\n", list[i]);
225 }
226 GNUNET_free (list);
227 } else {
228 FPRINTF (stderr, "%s", _("Error communicating with ARM. ARM not running?\n"));
229 }
230}
196 231
197/** 232/**
198 * Main function that will be run by the scheduler. 233 * Main function that will be run by the scheduler.
@@ -328,6 +363,24 @@ cps_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
328 GNUNET_SCHEDULER_add_now (&cps_loop, NULL); 363 GNUNET_SCHEDULER_add_now (&cps_loop, NULL);
329 return; 364 return;
330 } 365 }
366 case 5:
367 if (list) {
368 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
369 "Going to list all running services controlled by ARM.\n");
370
371 if (h == NULL)
372 {
373 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
374 _("Fatal error initializing ARM API.\n"));
375 return;
376 }
377
378 GNUNET_ARM_list_running_services (h,
379 (0 ==
380 timeout.rel_value) ? LIST_TIMEOUT :
381 timeout, &list_cb, NULL);
382 return;
383 }
331 /* Fall through */ 384 /* Fall through */
332 default: /* last phase */ 385 default: /* last phase */
333 GNUNET_ARM_disconnect (h); 386 GNUNET_ARM_disconnect (h);
@@ -371,6 +424,8 @@ main (int argc, char *const *argv)
371 {'T', "timeout", NULL, 424 {'T', "timeout", NULL,
372 gettext_noop ("timeout for completing current operation"), 425 gettext_noop ("timeout for completing current operation"),
373 GNUNET_YES, &GNUNET_GETOPT_set_ulong, &temp_timeout_ms}, 426 GNUNET_YES, &GNUNET_GETOPT_set_ulong, &temp_timeout_ms},
427 {'I', "info", NULL, gettext_noop ("List currently running services"),
428 GNUNET_NO, &GNUNET_GETOPT_set_one, &list},
374 GNUNET_GETOPT_OPTION_END 429 GNUNET_GETOPT_OPTION_END
375 }; 430 };
376 431
diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c
index f4430ed0c..cfe164fa6 100644
--- a/src/arm/gnunet-service-arm.c
+++ b/src/arm/gnunet-service-arm.c
@@ -370,6 +370,43 @@ write_result (void *cls, size_t size, void *buf)
370 return sizeof (struct GNUNET_ARM_ResultMessage); 370 return sizeof (struct GNUNET_ARM_ResultMessage);
371} 371}
372 372
373/**
374 * Transmit the list of running services.
375 *
376 * @param cls pointer to struct GNUNET_ARM_ListResultMessage with the message
377 * @param size number of bytes available in buf
378 * @param buf where to copy the message, NULL on error
379 * @return number of bytes copied to buf
380 */
381static size_t
382write_list_result (void *cls, size_t size, void *buf)
383{
384 struct GNUNET_ARM_ListResultMessage *msg = cls;
385 struct GNUNET_ARM_ListResultMessage *rslt;
386 size_t rslt_size;
387
388 if (buf == NULL)
389 {
390 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
391 _("Could not send list result to client\n"));
392 return 0; /* error, not much we can do */
393 }
394
395 GNUNET_assert (size >= msg->header.size);
396 rslt = buf;
397 rslt->header.size = htons (msg->header.size);
398 rslt->header.type = htons (msg->header.type);
399 rslt->count = htons (msg->count);
400
401 size_t list_size = msg->header.size
402 - sizeof (struct GNUNET_ARM_ListResultMessage);
403 memcpy (&rslt[1], &msg[1], list_size);
404
405 rslt_size = msg->header.size;
406 GNUNET_free (msg);
407 return rslt_size;
408}
409
373 410
374/** 411/**
375 * Signal our client that we will start or stop the 412 * Signal our client that we will start or stop the
@@ -566,7 +603,7 @@ handle_start (void *cls, struct GNUNET_SERVER_Client *client,
566 const char *servicename; 603 const char *servicename;
567 struct ServiceList *sl; 604 struct ServiceList *sl;
568 uint16_t size; 605 uint16_t size;
569 606
570 size = ntohs (message->size); 607 size = ntohs (message->size);
571 size -= sizeof (struct GNUNET_MessageHeader); 608 size -= sizeof (struct GNUNET_MessageHeader);
572 servicename = (const char *) &message[1]; 609 servicename = (const char *) &message[1];
@@ -663,6 +700,64 @@ handle_stop (void *cls, struct GNUNET_SERVER_Client *client,
663 GNUNET_SERVER_client_keep (client); 700 GNUNET_SERVER_client_keep (client);
664} 701}
665 702
703/**
704 * Handle LIST-message.
705 *
706 * @param cls closure (always NULL)
707 * @param client identification of the client
708 * @param message the actual message
709 */
710static void
711handle_list (void *cls, struct GNUNET_SERVER_Client *client,
712 const struct GNUNET_MessageHeader *message)
713{
714 struct GNUNET_ARM_ListResultMessage *msg;
715 size_t string_list_size;
716 size_t total_size;
717 struct ServiceList *sl;
718 uint16_t count;
719
720 if (NULL == client)
721 return;
722
723 count = 0;
724 string_list_size = 0;
725 /* first count the running processes get their name's size */
726 for (sl = running_head; sl != NULL; sl = sl->next)
727 {
728 if (sl->proc != NULL)
729 {
730 string_list_size += strlen (sl->name);
731 string_list_size += 3;
732 string_list_size += strlen (sl->binary) + 1;
733 count++;
734 }
735 }
736 total_size = sizeof (struct GNUNET_ARM_ListResultMessage)
737 + string_list_size;
738 msg = GNUNET_malloc (total_size);
739 msg->header.size = total_size;
740 msg->header.type = GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT;
741 msg->count = count;
742
743 char *pos = (char *)&msg[1];
744 for (sl = running_head; sl != NULL; sl = sl->next)
745 {
746 if (sl->proc != NULL)
747 {
748 //memcpy (pos, sl->name, strlen (sl->name) + 1);
749 size_t s = strlen (sl->name) + strlen (sl->binary) + 4;
750 snprintf(pos, s, "%s (%s)", sl->name, sl->binary);
751 pos += s;
752 }
753 }
754
755 GNUNET_SERVER_notify_transmit_ready (client,
756 msg->header.size,
757 GNUNET_TIME_UNIT_FOREVER_REL,
758 &write_list_result, msg);
759 GNUNET_SERVER_receive_done (client, GNUNET_OK);
760}
666 761
667/** 762/**
668 * We are done with everything. Stop remaining 763 * We are done with everything. Stop remaining
@@ -1002,7 +1097,6 @@ handle_shutdown (void *cls, struct GNUNET_SERVER_Client *client,
1002 GNUNET_SERVER_client_persist_ (client); 1097 GNUNET_SERVER_client_persist_ (client);
1003} 1098}
1004 1099
1005
1006/** 1100/**
1007 * Signal handler called for SIGCHLD. Triggers the 1101 * Signal handler called for SIGCHLD. Triggers the
1008 * respective handler by writing to the trigger pipe. 1102 * respective handler by writing to the trigger pipe.
@@ -1114,6 +1208,8 @@ run (void *cls, struct GNUNET_SERVER_Handle *serv,
1114 {&handle_stop, NULL, GNUNET_MESSAGE_TYPE_ARM_STOP, 0}, 1208 {&handle_stop, NULL, GNUNET_MESSAGE_TYPE_ARM_STOP, 0},
1115 {&handle_shutdown, NULL, GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN, 1209 {&handle_shutdown, NULL, GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN,
1116 sizeof (struct GNUNET_MessageHeader)}, 1210 sizeof (struct GNUNET_MessageHeader)},
1211 {&handle_list, NULL, GNUNET_MESSAGE_TYPE_ARM_LIST,
1212 sizeof (struct GNUNET_MessageHeader)},
1117 {NULL, NULL, 0, 0} 1213 {NULL, NULL, 0, 0}
1118 }; 1214 };
1119 char *defaultservices; 1215 char *defaultservices;