aboutsummaryrefslogtreecommitdiff
path: root/src/arm
diff options
context:
space:
mode:
authorszengel <szengel@140774ce-b5e7-0310-ab8b-a85725594a96>2012-02-29 08:59:39 +0000
committerszengel <szengel@140774ce-b5e7-0310-ab8b-a85725594a96>2012-02-29 08:59:39 +0000
commitea96e3284daecbd0b37c06682b68e1c8ffc8dfa8 (patch)
tree2e9c740f97f6f81c5cc7794d495e0fa6c188c0e3 /src/arm
parentdd21594b1ded031fe9d663f2c0e94e3d416e2237 (diff)
Adding arm list/info feature.
git-svn-id: https://gnunet.org/svn/gnunet@20135 140774ce-b5e7-0310-ab8b-a85725594a96
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 4b9da6faba..21884107c5 100644
--- a/src/arm/arm.h
+++ b/src/arm/arm.h
@@ -51,6 +51,27 @@ struct GNUNET_ARM_ResultMessage
*/
uint32_t status;
};
+
+/**
+ * Reply from ARM to client for the
+ * GNUNET_MESSAGE_TYPE_ARM_LIST request followed by count
+ * '\0' terminated strings. header->size contains the
+ * total size (including all strings).
+ */
+struct GNUNET_ARM_ListResultMessage
+{
+ /**
+ * Reply to client is of type GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Number of '\0' terminated strings that follow
+ * this message.
+ */
+ uint16_t count;
+};
+
GNUNET_NETWORK_STRUCT_END
#endif
diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c
index 0f4ae6a4f0..d0babf0ae7 100644
--- a/src/arm/arm_api.c
+++ b/src/arm/arm_api.c
@@ -52,7 +52,6 @@ struct GNUNET_ARM_Handle
};
-
/**
* Context for handling the shutdown of a service.
*/
@@ -487,6 +486,94 @@ handle_response (void *cls, const struct GNUNET_MessageHeader *msg)
GNUNET_free (sc);
}
+/**
+ * Internal state for a list request with ARM.
+ */
+struct ListRequestContext
+{
+
+ /**
+ * Pointer to our handle with ARM.
+ */
+ struct GNUNET_ARM_Handle *h;
+
+ /**
+ * Function to call with a status code for the requested operation.
+ */
+ GNUNET_ARM_List_Callback callback;
+
+ /**
+ * Closure for "callback".
+ */
+ void *cls;
+
+ /**
+ * Timeout for the operation.
+ */
+ struct GNUNET_TIME_Absolute timeout;
+};
+
+/**
+ * Process a response from ARM for the list request.
+ *
+ * @param cls the list request context
+ * @param msg the response
+ */
+static void
+handle_list_response (void *cls, const struct GNUNET_MessageHeader *msg)
+{
+ struct ListRequestContext *sc = cls;
+ const struct GNUNET_ARM_ListResultMessage *res;
+ int success;
+
+ if (msg == NULL)
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Error receiving response to LIST request from ARM\n");
+ GNUNET_CLIENT_disconnect (sc->h->client, GNUNET_NO);
+ sc->h->client = GNUNET_CLIENT_connect ("arm", sc->h->cfg);
+ GNUNET_assert (NULL != sc->h->client);
+ if (sc->callback != NULL)
+ sc->callback (sc->cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR, 0, NULL);
+ GNUNET_free (sc);
+ return;
+ }
+
+ if (sc->callback != NULL)
+ {
+ char **list;
+ const char *pos;
+ uint16_t size_check;
+
+ size_check = 0;
+ res = (const struct GNUNET_ARM_ListResultMessage *) msg;
+ success = (ntohs (res->header.type)
+ == GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT ?
+ GNUNET_YES : GNUNET_NO);
+ list = GNUNET_malloc (ntohs (res->count) * sizeof (char *));
+ pos = (const char *)&res[1];
+
+ int i;
+ for (i=0; i<ntohs (res->count); i++)
+ {
+ list[i] = GNUNET_malloc (strlen (pos) + 1);
+ memcpy (list[i], pos, strlen (pos) + 1);
+ pos += strlen (pos) + 1;
+ size_check += strlen (pos) +1;
+
+ if (size_check > ntohs (res->header.size))
+ {
+ GNUNET_free (list);
+ GNUNET_free (sc);
+ sc->callback (sc->cls, GNUNET_NO, 0, NULL);
+ return;
+ }
+ }
+
+ sc->callback (sc->cls, success, ntohs (res->count), (const char**)list);
+ }
+ GNUNET_free (sc);
+}
/**
* Start or stop a service.
@@ -677,5 +764,69 @@ GNUNET_ARM_stop_service (struct GNUNET_ARM_Handle *h,
GNUNET_MESSAGE_TYPE_ARM_STOP);
}
+/**
+ * List all running services.
+ *
+ * @param h handle to ARM
+ * @param timeout how long to wait before failing for good
+ * @param cb callback to invoke when service is ready
+ * @param cb_cls closure for callback
+ */
+void
+GNUNET_ARM_list_running_services (struct GNUNET_ARM_Handle *h,
+ struct GNUNET_TIME_Relative timeout,
+ GNUNET_ARM_List_Callback cb, void *cb_cls)
+{
+ struct ListRequestContext *sctx;
+ struct GNUNET_MessageHeader *msg;
+ struct GNUNET_CLIENT_Connection *client;
+
+ if (h->client == NULL)
+ {
+ client = GNUNET_CLIENT_connect ("arm", h->cfg);
+ if (client == NULL)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "arm_api, GNUNET_CLIENT_connect returned NULL\n");
+ cb (cb_cls, GNUNET_ARM_PROCESS_COMMUNICATION_ERROR, 0, NULL);
+ return;
+ }
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "arm_api, GNUNET_CLIENT_connect returned non-NULL\n");
+ h->client = client;
+ }
+
+ sctx = GNUNET_malloc (sizeof (struct RequestContext));
+ sctx->h = h;
+ sctx->callback = cb;
+ sctx->cls = cb_cls;
+ sctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
+ msg = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader));
+ msg->size = htons (sizeof (struct GNUNET_MessageHeader));
+ msg->type = htons (GNUNET_MESSAGE_TYPE_ARM_LIST);
+
+ LOG(GNUNET_ERROR_TYPE_DEBUG,
+ "Requesting LIST from ARM service with timeout: %llu ms\n",
+ (unsigned long long)timeout.rel_value);
+
+ if (GNUNET_OK !=
+ GNUNET_CLIENT_transmit_and_get_response (sctx->h->client,
+ msg,
+ GNUNET_TIME_absolute_get_remaining
+ (sctx->timeout),
+ GNUNET_YES,
+ &handle_list_response,
+ sctx))
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Error while trying to transmit request to list services to ARM\n");
+ if (cb != NULL)
+ cb (cb_cls, GNUNET_SYSERR, 0, NULL);
+ GNUNET_free (sctx);
+ GNUNET_free (msg);
+ return;
+ }
+ GNUNET_free (msg);
+}
/* end of arm_api.c */
diff --git a/src/arm/gnunet-arm.c b/src/arm/gnunet-arm.c
index 65700ee11c..f81cefa696 100644
--- a/src/arm/gnunet-arm.c
+++ b/src/arm/gnunet-arm.c
@@ -49,6 +49,11 @@
#define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
/**
+ * Timeout for listing all running services.
+ */
+#define LIST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
+
+/**
* Set if we are to shutdown all services (including ARM).
*/
static int end;
@@ -74,6 +79,11 @@ static int delete;
static int quiet;
/**
+ * Set if we should print a list of currently running services.
+ */
+static int list;
+
+/**
* Set to the name of a service to start.
*/
static char *init;
@@ -193,6 +203,31 @@ confirm_cb (void *cls,
GNUNET_SCHEDULER_REASON_PREREQ_DONE);
}
+/**
+ * Callback invoked with the list of running services.
+ * Reports to the user and then runs the next phase in the FSM.
+ *
+ * @param cls currently not used
+ * @param result result of the operation
+ * @param count number of running services
+ * @param list copy of the list of running services
+ */
+static void
+list_cb (void *cls, int result, uint16_t count, const char **list)
+{
+ if (result == GNUNET_YES && list != NULL)
+ {
+ FPRINTF (stdout, _("Running services:\n-----------------\n"));
+ int i;
+ for (i=0; i<count; i++)
+ {
+ FPRINTF (stdout, "%s\n", list[i]);
+ }
+ GNUNET_free (list);
+ } else {
+ FPRINTF (stderr, "%s", _("Error communicating with ARM. ARM not running?\n"));
+ }
+}
/**
* Main function that will be run by the scheduler.
@@ -328,6 +363,24 @@ cps_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
GNUNET_SCHEDULER_add_now (&cps_loop, NULL);
return;
}
+ case 5:
+ if (list) {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Going to list all running services controlled by ARM.\n");
+
+ if (h == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Fatal error initializing ARM API.\n"));
+ return;
+ }
+
+ GNUNET_ARM_list_running_services (h,
+ (0 ==
+ timeout.rel_value) ? LIST_TIMEOUT :
+ timeout, &list_cb, NULL);
+ return;
+ }
/* Fall through */
default: /* last phase */
GNUNET_ARM_disconnect (h);
@@ -371,6 +424,8 @@ main (int argc, char *const *argv)
{'T', "timeout", NULL,
gettext_noop ("timeout for completing current operation"),
GNUNET_YES, &GNUNET_GETOPT_set_ulong, &temp_timeout_ms},
+ {'I', "info", NULL, gettext_noop ("List currently running services"),
+ GNUNET_NO, &GNUNET_GETOPT_set_one, &list},
GNUNET_GETOPT_OPTION_END
};
diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c
index f4430ed0c8..cfe164fa6b 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)
return sizeof (struct GNUNET_ARM_ResultMessage);
}
+/**
+ * Transmit the list of running services.
+ *
+ * @param cls pointer to struct GNUNET_ARM_ListResultMessage with the message
+ * @param size number of bytes available in buf
+ * @param buf where to copy the message, NULL on error
+ * @return number of bytes copied to buf
+ */
+static size_t
+write_list_result (void *cls, size_t size, void *buf)
+{
+ struct GNUNET_ARM_ListResultMessage *msg = cls;
+ struct GNUNET_ARM_ListResultMessage *rslt;
+ size_t rslt_size;
+
+ if (buf == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Could not send list result to client\n"));
+ return 0; /* error, not much we can do */
+ }
+
+ GNUNET_assert (size >= msg->header.size);
+ rslt = buf;
+ rslt->header.size = htons (msg->header.size);
+ rslt->header.type = htons (msg->header.type);
+ rslt->count = htons (msg->count);
+
+ size_t list_size = msg->header.size
+ - sizeof (struct GNUNET_ARM_ListResultMessage);
+ memcpy (&rslt[1], &msg[1], list_size);
+
+ rslt_size = msg->header.size;
+ GNUNET_free (msg);
+ return rslt_size;
+}
+
/**
* Signal our client that we will start or stop the
@@ -566,7 +603,7 @@ handle_start (void *cls, struct GNUNET_SERVER_Client *client,
const char *servicename;
struct ServiceList *sl;
uint16_t size;
-
+
size = ntohs (message->size);
size -= sizeof (struct GNUNET_MessageHeader);
servicename = (const char *) &message[1];
@@ -663,6 +700,64 @@ handle_stop (void *cls, struct GNUNET_SERVER_Client *client,
GNUNET_SERVER_client_keep (client);
}
+/**
+ * Handle LIST-message.
+ *
+ * @param cls closure (always NULL)
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_list (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ struct GNUNET_ARM_ListResultMessage *msg;
+ size_t string_list_size;
+ size_t total_size;
+ struct ServiceList *sl;
+ uint16_t count;
+
+ if (NULL == client)
+ return;
+
+ count = 0;
+ string_list_size = 0;
+ /* first count the running processes get their name's size */
+ for (sl = running_head; sl != NULL; sl = sl->next)
+ {
+ if (sl->proc != NULL)
+ {
+ string_list_size += strlen (sl->name);
+ string_list_size += 3;
+ string_list_size += strlen (sl->binary) + 1;
+ count++;
+ }
+ }
+ total_size = sizeof (struct GNUNET_ARM_ListResultMessage)
+ + string_list_size;
+ msg = GNUNET_malloc (total_size);
+ msg->header.size = total_size;
+ msg->header.type = GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT;
+ msg->count = count;
+
+ char *pos = (char *)&msg[1];
+ for (sl = running_head; sl != NULL; sl = sl->next)
+ {
+ if (sl->proc != NULL)
+ {
+ //memcpy (pos, sl->name, strlen (sl->name) + 1);
+ size_t s = strlen (sl->name) + strlen (sl->binary) + 4;
+ snprintf(pos, s, "%s (%s)", sl->name, sl->binary);
+ pos += s;
+ }
+ }
+
+ GNUNET_SERVER_notify_transmit_ready (client,
+ msg->header.size,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ &write_list_result, msg);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
/**
* We are done with everything. Stop remaining
@@ -1002,7 +1097,6 @@ handle_shutdown (void *cls, struct GNUNET_SERVER_Client *client,
GNUNET_SERVER_client_persist_ (client);
}
-
/**
* Signal handler called for SIGCHLD. Triggers the
* respective handler by writing to the trigger pipe.
@@ -1114,6 +1208,8 @@ run (void *cls, struct GNUNET_SERVER_Handle *serv,
{&handle_stop, NULL, GNUNET_MESSAGE_TYPE_ARM_STOP, 0},
{&handle_shutdown, NULL, GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN,
sizeof (struct GNUNET_MessageHeader)},
+ {&handle_list, NULL, GNUNET_MESSAGE_TYPE_ARM_LIST,
+ sizeof (struct GNUNET_MessageHeader)},
{NULL, NULL, 0, 0}
};
char *defaultservices;