aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeandro A. F. Pereira <leandro@hardinfo.org>2009-04-25 14:45:00 -0300
committerLeandro A. F. Pereira <leandro@hardinfo.org>2009-04-25 14:45:00 -0300
commit77baf70fba7d7fbdd10d677a3a0357c7337d8b12 (patch)
treea0a2a1d4f365ba65d89a72fab7d91a29a599cee9
parent77d3c49309059979067f37e62a44936e00594aa7 (diff)
Add XML-RPC server (prototype); early work on the "Open Connection" dialog
-rw-r--r--hardinfo2/Makefile.in2
-rw-r--r--hardinfo2/hardinfo.c6
-rw-r--r--hardinfo2/hardinfo.h1
-rw-r--r--hardinfo2/pixmaps/home.pngbin0 -> 920 bytes
-rw-r--r--hardinfo2/pixmaps/server-large.pngbin0 -> 1525 bytes
-rw-r--r--hardinfo2/pixmaps/server.pngbin0 -> 878 bytes
-rw-r--r--hardinfo2/remote.c83
-rw-r--r--hardinfo2/socket.c1
-rw-r--r--hardinfo2/util.c8
-rw-r--r--hardinfo2/xmlrpc-server.c143
-rw-r--r--hardinfo2/xmlrpc-server.h7
11 files changed, 228 insertions, 23 deletions
diff --git a/hardinfo2/Makefile.in b/hardinfo2/Makefile.in
index 98379ec5..3cf83329 100644
--- a/hardinfo2/Makefile.in
+++ b/hardinfo2/Makefile.in
@@ -8,7 +8,7 @@ CCSLOW = gcc -O0 -g
OBJECTS = hardinfo.o shell.o util.o iconcache.o loadgraph.o \
menu.o stock.o callbacks.o expr.o report.o binreloc.o \
- vendor.o socket.o syncmanager.o remote.o
+ vendor.o socket.o syncmanager.o remote.o xmlrpc-server.o
BENCHMARK_OBJECTS = fbench.o sha1.o blowfish.o md5.o nqueens.o fftbench.o
MODULES = computer.so devices.so benchmark.so network.so
diff --git a/hardinfo2/hardinfo.c b/hardinfo2/hardinfo.c
index 3f638a87..d8eb40a1 100644
--- a/hardinfo2/hardinfo.c
+++ b/hardinfo2/hardinfo.c
@@ -24,6 +24,7 @@
#include <iconcache.h>
#include <stock.h>
#include <vendor.h>
+#include <xmlrpc-server.h>
#include <binreloc.h>
@@ -114,7 +115,10 @@ int main(int argc, char **argv)
/* initialize vendor database */
vendor_init();
- if (params.run_benchmark) {
+ if (params.run_xmlrpc_server) {
+ xmlrpc_server_init();
+ xmlrpc_server_start();
+ } else if (params.run_benchmark) {
gchar *result;
result = module_call_method_param("benchmark::runBenchmark", params.run_benchmark);
diff --git a/hardinfo2/hardinfo.h b/hardinfo2/hardinfo.h
index 2fe955fe..030cc46a 100644
--- a/hardinfo2/hardinfo.h
+++ b/hardinfo2/hardinfo.h
@@ -33,6 +33,7 @@ struct _ProgramParameters {
gboolean gui_running;
gboolean list_modules;
gboolean autoload_deps;
+ gboolean run_xmlrpc_server;
gint report_format;
diff --git a/hardinfo2/pixmaps/home.png b/hardinfo2/pixmaps/home.png
new file mode 100644
index 00000000..9d62109a
--- /dev/null
+++ b/hardinfo2/pixmaps/home.png
Binary files differ
diff --git a/hardinfo2/pixmaps/server-large.png b/hardinfo2/pixmaps/server-large.png
new file mode 100644
index 00000000..6ada9d08
--- /dev/null
+++ b/hardinfo2/pixmaps/server-large.png
Binary files differ
diff --git a/hardinfo2/pixmaps/server.png b/hardinfo2/pixmaps/server.png
new file mode 100644
index 00000000..a0d7118d
--- /dev/null
+++ b/hardinfo2/pixmaps/server.png
Binary files differ
diff --git a/hardinfo2/remote.c b/hardinfo2/remote.c
index a8cda9b6..ae144b5d 100644
--- a/hardinfo2/remote.c
+++ b/hardinfo2/remote.c
@@ -33,7 +33,7 @@
* - IP range scan
* - mDNS
* - Allow the user to add/remove/edit a machine
- * - Use ~/.ssh/hosts as a starting point?
+ * - Use ~/.ssh/known_hosts as a starting point?
* - Different icons for different machines?
* - Make sure SSH can do port forwarding
* - Make sure the remote host has HardInfo installed, with the correct
@@ -56,7 +56,7 @@
* - Use libsoup XML-RPC support to implement the remote mode
* - Introduce a flag on the modules, stating their ability to be used locally/remotely
* (Benchmarks can't be used remotely; Displays won't work remotely [unless we use
- X forwarding, but that'll be local X11 info anyway]).
+ * X forwarding, but that'll be local X11 info anyway]).
*/
typedef struct _RemoteDialog RemoteDialog;
@@ -67,31 +67,73 @@ struct _RemoteDialog {
static RemoteDialog *remote_dialog_new(GtkWidget *parent);
+static void remote_connect(RemoteDialog *rd)
+{
+
+}
+
void remote_dialog_show(GtkWidget *parent)
{
gboolean success;
RemoteDialog *rd = remote_dialog_new(parent);
if (gtk_dialog_run(GTK_DIALOG(rd->dialog)) == GTK_RESPONSE_ACCEPT) {
- shell_status_update("Generating remote...");
gtk_widget_hide(rd->dialog);
shell_view_set_enabled(FALSE);
shell_status_set_enabled(TRUE);
-
-// success = remote_generate(rd);
-
+
+ remote_connect(rd);
shell_status_set_enabled(FALSE);
-
- if (success)
- shell_status_update("Remote saved.");
- else
- shell_status_update("Error while creating the remote.");
}
gtk_widget_destroy(rd->dialog);
g_free(rd);
}
+static void populate_store(GtkListStore * store)
+{
+ GKeyFile *remote;
+ GtkTreeIter iter;
+ gchar *path;
+
+ gtk_list_store_clear(store);
+
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ 0, icon_cache_get_pixbuf("home.png"),
+ 1, g_strdup("Local Computer"),
+ 2, GINT_TO_POINTER(-1),
+ -1);
+
+ remote = g_key_file_new();
+ path = g_build_filename(g_get_home_dir(), ".hardinfo", "remote.conf", NULL);
+ if (g_key_file_load_from_file(remote, path, 0, NULL)) {
+ gint no_hosts, i;
+
+ no_hosts = g_key_file_get_integer(remote, "$Global$", "no_hosts", NULL);
+ for (i = 0; i < no_hosts; i++) {
+ gchar *hostname;
+ gchar *hostgroup;
+
+ hostgroup = g_strdup_printf("Host%d", i);
+
+ hostname = g_key_file_get_string(remote, hostgroup, "name", NULL);
+
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ 0, icon_cache_get_pixbuf("server.png"),
+ 1, hostname,
+ 2, GINT_TO_POINTER(i),
+ -1);
+
+ g_free(hostgroup);
+ }
+ }
+
+ g_free(path);
+ g_key_file_free(remote);
+}
+
static RemoteDialog *remote_dialog_new(GtkWidget *parent)
{
RemoteDialog *rd;
@@ -110,6 +152,8 @@ static RemoteDialog *remote_dialog_new(GtkWidget *parent)
GtkTreeViewColumn *column;
GtkCellRenderer *cr_text, *cr_pbuf, *cr_toggle;
+ GtkListStore *store;
+ GtkTreeModel *model;
rd = g_new0(RemoteDialog, 1);
@@ -137,9 +181,8 @@ static RemoteDialog *remote_dialog_new(GtkWidget *parent)
gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-
gtk_box_pack_start(GTK_BOX(hbox),
- icon_cache_get_image("network.png"),
+ icon_cache_get_image("server-large.png"),
FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
gtk_widget_show_all(hbox);
@@ -159,7 +202,10 @@ static RemoteDialog *remote_dialog_new(GtkWidget *parent)
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW
(scrolledwindow2), GTK_SHADOW_IN);
- treeview2 = gtk_tree_view_new();
+ store = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_INT);
+ model = GTK_TREE_MODEL(store);
+
+ treeview2 = gtk_tree_view_new_with_model(model);
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview2), FALSE);
gtk_widget_show(treeview2);
gtk_container_add(GTK_CONTAINER(scrolledwindow2), treeview2);
@@ -167,13 +213,6 @@ static RemoteDialog *remote_dialog_new(GtkWidget *parent)
column = gtk_tree_view_column_new();
gtk_tree_view_append_column(GTK_TREE_VIEW(treeview2), column);
- cr_toggle = gtk_cell_renderer_toggle_new();
- gtk_tree_view_column_pack_start(column, cr_toggle, FALSE);
-// g_signal_connect(cr_toggle, "toggled",
-// G_CALLBACK(remote_dialog_sel_toggle), rd);
- gtk_tree_view_column_add_attribute(column, cr_toggle, "active",
- TREE_COL_SEL);
-
cr_pbuf = gtk_cell_renderer_pixbuf_new();
gtk_tree_view_column_pack_start(column, cr_pbuf, FALSE);
gtk_tree_view_column_add_attribute(column, cr_pbuf, "pixbuf",
@@ -184,6 +223,8 @@ static RemoteDialog *remote_dialog_new(GtkWidget *parent)
gtk_tree_view_column_add_attribute(column, cr_text, "markup",
TREE_COL_NAME);
+ populate_store(store);
+
vbuttonbox3 = gtk_vbutton_box_new();
gtk_widget_show(vbuttonbox3);
gtk_box_pack_start(GTK_BOX(hbox), vbuttonbox3, FALSE, TRUE, 0);
diff --git a/hardinfo2/socket.c b/hardinfo2/socket.c
index cada32b6..66d3f56d 100644
--- a/hardinfo2/socket.c
+++ b/hardinfo2/socket.c
@@ -120,6 +120,7 @@ int sock_write(Socket * s, gchar * str)
void sock_close(Socket * s)
{
+ shutdown(s->sock, 2);
close(s->sock);
g_free(s);
}
diff --git a/hardinfo2/util.c b/hardinfo2/util.c
index dd89e199..510c5d0e 100644
--- a/hardinfo2/util.c
+++ b/hardinfo2/util.c
@@ -363,6 +363,7 @@ void parameters_init(int *argc, char ***argv, ProgramParameters * param)
static gboolean show_version = FALSE;
static gboolean list_modules = FALSE;
static gboolean autoload_deps = FALSE;
+ static gboolean run_xmlrpc_server = FALSE;
static gchar *report_format = NULL;
static gchar *run_benchmark = NULL;
static gchar **use_modules = NULL;
@@ -405,6 +406,12 @@ void parameters_init(int *argc, char ***argv, ProgramParameters * param)
.arg_data = &autoload_deps,
.description = "automatically load module dependencies"},
{
+ .long_name = "xmlrpc-server",
+ .short_name = 'x',
+ .arg = G_OPTION_ARG_NONE,
+ .arg_data = &run_xmlrpc_server,
+ .description = "run in XML-RPC server mode"},
+ {
.long_name = "version",
.short_name = 'v',
.arg = G_OPTION_ARG_NONE,
@@ -436,6 +443,7 @@ void parameters_init(int *argc, char ***argv, ProgramParameters * param)
param->use_modules = use_modules;
param->run_benchmark = run_benchmark;
param->autoload_deps = autoload_deps;
+ param->run_xmlrpc_server = run_xmlrpc_server;
param->argv0 = *(argv)[0];
if (report_format && g_str_equal(report_format, "html"))
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 */
diff --git a/hardinfo2/xmlrpc-server.h b/hardinfo2/xmlrpc-server.h
new file mode 100644
index 00000000..5ecafba4
--- /dev/null
+++ b/hardinfo2/xmlrpc-server.h
@@ -0,0 +1,7 @@
+#ifndef __XMLRPC_SERVER_H__
+#define __XMLRPC_SERVER_H__
+
+void xmlrpc_server_start(void);
+void xmlrpc_server_init(void);
+
+#endif /* __XMLRPC_SERVER_H__ */ \ No newline at end of file