aboutsummaryrefslogtreecommitdiff
path: root/hardinfo2/xmlrpc-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'hardinfo2/xmlrpc-server.c')
-rw-r--r--hardinfo2/xmlrpc-server.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/hardinfo2/xmlrpc-server.c b/hardinfo2/xmlrpc-server.c
new file mode 100644
index 00000000..519eef81
--- /dev/null
+++ b/hardinfo2/xmlrpc-server.c
@@ -0,0 +1,143 @@
+#include <stdio.h>
+#include <libsoup/soup.h>
+
+#include "config.h"
+
+#define XMLRPC_SERVER_VERSION 1
+
+static void method_get_api_version(SoupMessage *msg, GValueArray *params);
+static void method_shutdown_server(SoupMessage *msg, GValueArray *params);
+
+static const struct {
+ gchar *method_name;
+ void *callback;
+} handler_table[] = {
+ { "getAPIVersion", method_get_api_version },
+ { "shutdownServer", method_shutdown_server },
+ { NULL }
+};
+
+static GHashTable *handlers = NULL;
+static GMainLoop *loop = NULL;
+
+static void method_get_api_version(SoupMessage *msg, GValueArray *params)
+{
+ soup_xmlrpc_set_response(msg, G_TYPE_INT, 1);
+}
+
+static void method_shutdown_server(SoupMessage *msg, GValueArray *params)
+{
+ soup_xmlrpc_set_response(msg, G_TYPE_BOOLEAN, TRUE);
+
+ g_main_loop_quit(loop);
+}
+
+void xmlrpc_server_init(void)
+{
+ if (!loop) {
+ loop = g_main_loop_new(NULL, FALSE);
+ }
+
+ if (!handlers) {
+ int i;
+ handlers = g_hash_table_new(g_str_hash, g_str_equal);
+
+ for (i = 0; handler_table[i].method_name; i++) {
+ g_hash_table_insert(handlers,
+ handler_table[i].method_name, handler_table[i].callback);
+ }
+ }
+}
+
+static SoupServer *xmlrpc_server_new(void)
+{
+ SoupServer *server;
+
+ DEBUG("creating server");
+ server = soup_server_new(SOUP_SERVER_SSL_CERT_FILE, NULL,
+ SOUP_SERVER_SSL_KEY_FILE, NULL,
+ SOUP_SERVER_ASYNC_CONTEXT, NULL,
+ NULL);
+ if (!server) {
+ return NULL;
+ }
+
+ soup_server_run_async(server);
+
+ return server;
+}
+
+static void xmlrpc_server_callback(SoupServer *server,
+ SoupMessage *msg,
+ const char *path,
+ GHashTable *query,
+ SoupClientContext *context,
+ gpointer data)
+{
+ if (msg->method == SOUP_METHOD_POST) {
+ gchar *method_name;
+ GValueArray *params;
+ void (*callback)(SoupMessage *msg, GValueArray *params);
+
+ DEBUG("received POST request");
+
+ if (!soup_xmlrpc_parse_method_call(msg->request_body->data,
+ msg->request_body->length,
+ &method_name, &params)) {
+ soup_message_set_status(msg, SOUP_STATUS_BAD_REQUEST);
+ return;
+ }
+
+ DEBUG("method: %s", method_name);
+
+ if ((callback = g_hash_table_lookup(handlers, method_name))) {
+ soup_message_set_status(msg, SOUP_STATUS_OK);
+
+ DEBUG("found callback: %p", callback);
+ callback(msg, params);
+ } else {
+ DEBUG("callback not found");
+ soup_message_set_status(msg, SOUP_STATUS_NOT_ACCEPTABLE);
+ }
+
+ g_free(method_name);
+ g_value_array_free(params);
+ } else {
+ DEBUG("received request of unknown method");
+ soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED);
+ }
+}
+
+void xmlrpc_server_start(void)
+{
+ SoupServer *server;
+
+ if (!loop || !handlers) {
+ xmlrpc_server_init();
+ }
+
+ server = xmlrpc_server_new();
+ if (!server) {
+ g_error("Cannot create XML-RPC server. Aborting");
+ }
+
+ soup_server_add_handler(server, "/xmlrpc", xmlrpc_server_callback, NULL, NULL);
+
+ g_print("XML-RPC server listening on port: %d\n", soup_server_get_port(server));
+
+ DEBUG("starting server");
+ g_main_loop_run(loop);
+ DEBUG("shutting down server");
+ g_main_loop_unref(loop);
+}
+
+#ifdef XMLRPC_SERVER_TEST
+int main(void)
+{
+ g_type_init();
+ g_thread_init(NULL);
+
+ xmlrpc_server_init();
+ xmlrpc_server_start();
+}
+#endif /* XMLRPC_SERVER_TEST */