diff options
author | Maximilian Szengel <gnunet@maxsz.de> | 2012-02-29 08:59:39 +0000 |
---|---|---|
committer | Maximilian Szengel <gnunet@maxsz.de> | 2012-02-29 08:59:39 +0000 |
commit | d8b052b2dd8e0242239b14bdd06854bff21cb3d0 (patch) | |
tree | 2e9c740f97f6f81c5cc7794d495e0fa6c188c0e3 /src/arm | |
parent | fe1e67e9cab9d7bad0211c654ec90f1ef15b7c97 (diff) | |
download | gnunet-d8b052b2dd8e0242239b14bdd06854bff21cb3d0.tar.gz gnunet-d8b052b2dd8e0242239b14bdd06854bff21cb3d0.zip |
Adding arm list/info feature.
Diffstat (limited to 'src/arm')
-rw-r--r-- | src/arm/arm.h | 21 | ||||
-rw-r--r-- | src/arm/arm_api.c | 153 | ||||
-rw-r--r-- | src/arm/gnunet-arm.c | 55 | ||||
-rw-r--r-- | src/arm/gnunet-service-arm.c | 100 |
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 | */ | ||
61 | struct 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 | |||
54 | GNUNET_NETWORK_STRUCT_END | 75 | GNUNET_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 | */ | ||
492 | struct 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 | */ | ||
522 | static void | ||
523 | handle_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 | */ | ||
775 | void | ||
776 | GNUNET_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 | */ |
54 | static int end; | 59 | static int end; |
@@ -74,6 +79,11 @@ static int delete; | |||
74 | static int quiet; | 79 | static int quiet; |
75 | 80 | ||
76 | /** | 81 | /** |
82 | * Set if we should print a list of currently running services. | ||
83 | */ | ||
84 | static 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 | */ |
79 | static char *init; | 89 | static 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 | */ | ||
215 | static void | ||
216 | list_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 | */ | ||
381 | static size_t | ||
382 | write_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 | */ | ||
710 | static void | ||
711 | handle_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; |