diff options
| -rw-r--r-- | hardinfo2/Makefile.in | 2 | ||||
| -rw-r--r-- | hardinfo2/hardinfo.c | 6 | ||||
| -rw-r--r-- | hardinfo2/hardinfo.h | 1 | ||||
| -rw-r--r-- | hardinfo2/pixmaps/home.png | bin | 0 -> 920 bytes | |||
| -rw-r--r-- | hardinfo2/pixmaps/server-large.png | bin | 0 -> 1525 bytes | |||
| -rw-r--r-- | hardinfo2/pixmaps/server.png | bin | 0 -> 878 bytes | |||
| -rw-r--r-- | hardinfo2/remote.c | 83 | ||||
| -rw-r--r-- | hardinfo2/socket.c | 1 | ||||
| -rw-r--r-- | hardinfo2/util.c | 8 | ||||
| -rw-r--r-- | hardinfo2/xmlrpc-server.c | 143 | ||||
| -rw-r--r-- | hardinfo2/xmlrpc-server.h | 7 | 
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.pngBinary files differ new file mode 100644 index 00000000..9d62109a --- /dev/null +++ b/hardinfo2/pixmaps/home.png diff --git a/hardinfo2/pixmaps/server-large.png b/hardinfo2/pixmaps/server-large.pngBinary files differ new file mode 100644 index 00000000..6ada9d08 --- /dev/null +++ b/hardinfo2/pixmaps/server-large.png diff --git a/hardinfo2/pixmaps/server.png b/hardinfo2/pixmaps/server.pngBinary files differ new file mode 100644 index 00000000..a0d7118d --- /dev/null +++ b/hardinfo2/pixmaps/server.png 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, ¶ms)) { +      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 | 
