diff options
| author | the_jk <the_jk@yahoo.com> | 2011-11-14 21:26:42 +0100 |
|---|---|---|
| committer | the_jk <the_jk@yahoo.com> | 2011-11-14 21:26:42 +0100 |
| commit | 4e199c3693d85c0917f264d9e01ceab20b368fc2 (patch) | |
| tree | 6e490cd1677e7bb15d0481c96c4871d470e30047 /src | |
| parent | 3411ddd3e6f9ee43e4eaa0c74935f1af8f36ee9d (diff) | |
Start work on XMLRPC bit
Diffstat (limited to 'src')
| -rw-r--r-- | src/.gitignore | 2 | ||||
| -rw-r--r-- | src/Makefile | 8 | ||||
| -rw-r--r-- | src/main.c | 266 |
3 files changed, 272 insertions, 4 deletions
diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..c1753e9 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,2 @@ +/viewtorrents +*.o
\ No newline at end of file diff --git a/src/Makefile b/src/Makefile index ab842f8..022a873 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,8 +1,10 @@ CC=gcc CFLAGS=-Wall -Wextra -DDEBUG -DHAVE_CONFIG_H -g -I.. -DDATAROOTDIR='"/sw/share/"' GTK_CFLAGS=`pkg-config gtk+-2.0 --cflags` +XMLRPC_CFLAGS=`xmlrpc-c-config client --cflags` LDFLAGS= -GTK_LDFLAGS=`pkg-config gtk+-2.0 --libs` +GTK_LIBS=`pkg-config gtk+-2.0 --libs` +XMLRPC_LIBS=`xmlrpc-c-config client --libs` all: viewtorrents @@ -10,10 +12,10 @@ clean: rm -f *.o viewtorrents viewtorrents: main.o customcellrendererstate.o customcellrendererprogress.o customcellrendererrate.o customcellrendererleft.o - $(CC) $(CFLAGS) $(GTK_CFLAGS) -o $@ $^ $(LDFLAGS) $(GTK_LDFLAGS) + $(CC) $(CFLAGS) $(GTK_CFLAGS) $(XMLRPC_CFLAGS) -o $@ $^ $(LDFLAGS) $(GTK_LIBS) $(XMLRPC_LIBS) main.o: main.c customcellrendererstate.h customcellrendererprogress.h customcellrendererrate.h customcellrendererleft.h common.h - $(CC) -c $(CFLAGS) $(GTK_CFLAGS) -o $@ $< + $(CC) -c $(CFLAGS) $(GTK_CFLAGS) $(XMLRPC_CFLAGS) -o $@ $< customcellrendererstate.o: customcellrendererstate.c customcellrendererstate.h common.h $(CC) -c $(CFLAGS) $(GTK_CFLAGS) -o $@ $< @@ -1,11 +1,14 @@ #include "common.h" #include <gtk/gtk.h> +#include <xmlrpc-c/base.h> +#include <xmlrpc-c/client.h> +#include <string.h> + #include "customcellrendererstate.h" #include "customcellrendererprogress.h" #include "customcellrendererrate.h" #include "customcellrendererleft.h" -#include <string.h> typedef enum { @@ -33,6 +36,66 @@ typedef struct static void torrent_update(torrent_t* torrent, GtkListStore* store, GtkTreeIter* iter); +typedef struct +{ + GAsyncQueue* queue; +} worker_data_t; + +typedef enum +{ + MSG_CONNECT, /* main -> worker */ + MSG_CONNECTRESULT, /* worker -> main */ + MSG_DISCONNECT, /* main -> worker */ + MSG_QUIT, /* main -> worker */ + MSG_ERROR, /* worker -> main */ +} msg_type_t; + +typedef struct +{ + msg_type_t type; +} msg_t; + +typedef struct +{ + msg_t base; + gchar* url; + gchar* auth_username, * auth_password; +} msg_connect_t; + +typedef struct +{ + msg_t base; + gboolean success; + gchar* errmsg; +} msg_connectresult_t; + +typedef struct +{ + msg_t base; + gchar* msg; +} msg_error_t; + +typedef struct +{ + msg_t base; +} msg_quit_t; + +typedef struct +{ + msg_t base; +} msg_disconnect_t; + +static void msg_free(msg_t* msg); + +static msg_t* msg_connect(const gchar* url, const gchar* username, + const gchar* password); +static msg_t* msg_connectresult(gboolean success, const gchar* errfmt, ...); +static msg_t* msg_error(const gchar* format, ...); +static msg_t* msg_disconnect(void); +static msg_t* msg_quit(void); + +static gpointer worker_main(gpointer data); + int main(int argc, char** argv) { const gchar* gladefile; @@ -45,11 +108,21 @@ int main(int argc, char** argv) GtkTreeIter iter; GtkCellRenderer* cell; GtkTreeViewColumn* column; + GThread* worker; + worker_data_t worker_data; g_thread_init(NULL); gtk_init(&argc, &argv); + worker_data.queue = g_async_queue_new(); + worker = g_thread_create(worker_main, &worker_data, TRUE, NULL); + if (worker == NULL) + { + fprintf(stderr, "Unable to create thread\n"); + return EXIT_FAILURE; + } + builder = gtk_builder_new(); gladefile = DATAROOTDIR "viewtorrents/viewtorrents.glade"; ret = gtk_builder_add_from_file(builder, gladefile, &error); @@ -146,6 +219,9 @@ int main(int argc, char** argv) gtk_main(); + g_async_queue_push(worker_data.queue, msg_quit()); + g_async_queue_unref(worker_data.queue); + return EXIT_SUCCESS; } @@ -164,3 +240,191 @@ void torrent_update(torrent_t* torrent, GtkListStore* store, GtkTreeIter* iter) torrent->seeded + 1000.0f, -1); } + +gpointer worker_main(gpointer _data) +{ + worker_data_t* data = _data; + xmlrpc_env env; + xmlrpc_client* client; + xmlrpc_server_info* server = NULL; + gboolean quit = FALSE; + + data->queue = g_async_queue_ref(data->queue); + + xmlrpc_env_init(&env); + xmlrpc_client_setup_global_const(&env); + xmlrpc_client_create(&env, XMLRPC_CLIENT_NO_FLAGS, "viewtorrents", "0.1", + NULL, 0, &client); + if (env.fault_occurred) + { + g_async_queue_push(data->queue, + msg_error("Unable to create XMLRPC-C client (%d): %s", + env.fault_code, env.fault_string)); + quit = TRUE; + } + + while (!quit) + { + msg_t* msg = g_async_queue_pop(data->queue); + switch (msg->type) + { + case MSG_CONNECT: + { + const gchar* tmp; + xmlrpc_value* params, * result; + msg_connect_t* m = (msg_connect_t*)msg; + + server = xmlrpc_server_info_new(&env, m->url); + if (m->auth_username != NULL) + { + xmlrpc_server_info_set_user(&env, server, + m->auth_username, + m->auth_password); + xmlrpc_server_info_allow_auth_basic(&env, server); + } + + params = xmlrpc_array_new(&env); + xmlrpc_client_call2(&env, client, server, "system.client_version", + params, &result); + if (env.fault_occurred) + { + xmlrpc_DECREF(params); + xmlrpc_server_info_free(server); + msg_free(msg); + server = NULL; + g_async_queue_push(data->queue, + msg_connectresult(FALSE, + "Unable to get client version (%d): %s", + env.fault_code, env.fault_string)); + continue; + } + xmlrpc_DECREF(params); + xmlrpc_read_string(&env, result, &tmp); + if (env.fault_occurred) + { + xmlrpc_DECREF(result); + xmlrpc_server_info_free(server); + msg_free(msg); + server = NULL; + g_async_queue_push(data->queue, + msg_connectresult(FALSE, + "Unable to get client version (%d): %s", + env.fault_code, env.fault_string)); + continue; + } + printf("result: %s\n", tmp); + xmlrpc_DECREF(result); + g_async_queue_push(data->queue, msg_connectresult(TRUE, NULL)); + msg_free(msg); + break; + } + case MSG_DISCONNECT: + { + xmlrpc_server_info_free(server); + server = NULL; + break; + } + case MSG_QUIT: + break; + case MSG_CONNECTRESULT: + case MSG_ERROR: + g_assert(FALSE); + break; + } + } + + if (server != NULL) + { + xmlrpc_server_info_free(server); + } + xmlrpc_client_destroy(client); + xmlrpc_client_teardown_global_const(); + g_async_queue_unref(data->queue); + return NULL; +} + +void msg_free(msg_t* msg) +{ + switch (msg->type) + { + case MSG_CONNECT: + { + msg_connect_t* m = (msg_connect_t*)msg; + g_free(m->url); + g_free(m->auth_username); + g_free(m->auth_password); + break; + } + case MSG_CONNECTRESULT: + { + msg_connectresult_t* m = (msg_connectresult_t*)msg; + g_free(m->errmsg); + break; + } + case MSG_ERROR: + { + msg_error_t* m = (msg_error_t*)msg; + g_free(m->msg); + break; + } + case MSG_DISCONNECT: + case MSG_QUIT: + break; + } + g_free(msg); +} + +msg_t* msg_connect(const gchar* url, const gchar* username, + const gchar* password) +{ + msg_connect_t* msg = g_new0(msg_connect_t, 1); + msg->base.type = MSG_CONNECT; + msg->url = strdup(url); + msg->auth_username = g_strdup(username); + msg->auth_password = g_strdup(password); + return &msg->base; +} + +msg_t* msg_connectresult(gboolean success, const gchar* errfmt, ...) +{ + msg_connectresult_t* msg = g_new0(msg_connectresult_t, 1); + msg->base.type = MSG_CONNECTRESULT; + if (success) + { + msg->success = TRUE; + } + else + { + va_list args; + msg->success = FALSE; + va_start(args, errfmt); + msg->errmsg = g_strdup_vprintf(errfmt, args); + va_end(args); + } + return &msg->base; +} + +msg_t* msg_error(const gchar* format, ...) +{ + msg_error_t* msg = g_new0(msg_error_t, 1); + va_list args; + msg->base.type = MSG_ERROR; + va_start(args, format); + msg->msg = g_strdup_vprintf(format, args); + va_end(args); + return &msg->base; +} + +msg_t* msg_disconnect(void) +{ + msg_disconnect_t* msg = g_new0(msg_disconnect_t, 1); + msg->base.type = MSG_DISCONNECT; + return &msg->base; +} + +msg_t* msg_quit(void) +{ + msg_quit_t* msg = g_new0(msg_quit_t, 1); + msg->base.type = MSG_QUIT; + return &msg->base; +} |
