X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=wui_thread.c;fp=wui_thread.c;h=8079f7504508d36c16b2f2a241d4642018c54b11;hb=06576813e9eee9338ade91bb2486a52af9507471;hp=0db43c8829a41ba06a239ad0eddfe6917597be81;hpb=7e9794277b619bb232ffc874ee7efa4ead8ddb8e;p=ovirt-viewer.git diff --git a/wui_thread.c b/wui_thread.c index 0db43c8..8079f75 100644 --- a/wui_thread.c +++ b/wui_thread.c @@ -25,11 +25,14 @@ #include +#include + #include "internal.h" /* Private functions. */ static gpointer wui_thread (gpointer data); static void wui_thread_send_quit (void); +static void do_curl_init (void); static gboolean do_connect (void); static gboolean do_login (void); static void refresh_vm_list (void); @@ -174,6 +177,8 @@ static void set_busy (gboolean); /* The private state of the WUI thread. */ static int secs_between_refresh = 60; +static CURL *curl = NULL; +static char curl_error_buffer[CURL_ERROR_SIZE]; static char *uri = NULL; static char *username = NULL; static char *password = NULL; @@ -215,7 +220,7 @@ wui_thread (gpointer _queue) msg = (struct message *) _msg; if (msg) { - DEBUG ("received message %d", msg->type); + DEBUG ("received message with msg->type = %d", msg->type); quit = process_message (msg); /* Don't free any strings in the message - we've saved them. */ g_free (msg); @@ -306,6 +311,7 @@ process_message (struct message *msg) { switch (msg->type) { case QUIT: + if (curl) curl_easy_cleanup (curl); if (uri) g_free (uri); if (username) g_free (username); if (password) g_free (password); @@ -314,6 +320,8 @@ process_message (struct message *msg) return 1; case CONNECT: + if (curl) curl_easy_cleanup (curl); + do_curl_init (); if (uri) g_free (uri); uri = msg->str1; @@ -327,9 +335,14 @@ process_message (struct message *msg) case DISCONNECT: /* This just forgets the state. REST is connectionless. */ + if (curl) curl_easy_cleanup (curl); + curl = NULL; if (uri) g_free (uri); + uri = NULL; if (username) g_free (username); + username = NULL; if (password) g_free (password); + password = NULL; set_connected (FALSE); set_logged_in (FALSE); break; @@ -340,6 +353,10 @@ process_message (struct message *msg) if (password) g_free (password); password = msg->str2; + /* If we're not connected, this message just updates the + * username and password. Otherwise if we are connected, + * try to login and grab the initial list of VMs. + */ if (connected) { if (do_login ()) { set_logged_in (TRUE); @@ -351,8 +368,10 @@ process_message (struct message *msg) break; case REFRESH_VM_LIST: - refresh_vm_list (); - secs_between_refresh = 60; + if (connected && logged_in) { + refresh_vm_list (); + secs_between_refresh = 60; + } break; default: @@ -363,16 +382,90 @@ process_message (struct message *msg) return 0; } -/* Try to connect to the current URI. Returns true on success. */ +/* Macro for easy handling of CURL errors. */ +#define CURL_CHECK_ERROR(fn, args) \ + ({ \ + CURLcode __r = fn args; \ + if (__r != CURLE_OK) { \ + fprintf (stderr, "%s: %s\n", #fn, curl_easy_strerror (__r)); \ + } \ + __r; \ + }) + +static size_t +write_fn (void *ptr, size_t size, size_t nmemb, void *stream) +{ + int bytes = size * nmemb; + return bytes; +} + +static size_t +header_fn (void *ptr, size_t size, size_t nmemb, void *stream) +{ + int bytes = size * nmemb; + return bytes; +} + +/* Called from the message loop to initialize the CURL handle. */ +static void +do_curl_init (void) +{ + DEBUG ("initializing libcurl"); + + curl = curl_easy_init (); + if (!curl) { /* This is probably quite bad, so abort. */ + DEBUG ("curl_easy_init failed"); + abort (); + } + + CURL_CHECK_ERROR (curl_easy_setopt, + (curl, CURLOPT_CAINFO, cainfo)); + CURL_CHECK_ERROR (curl_easy_setopt, + (curl, CURLOPT_SSL_VERIFYHOST, check_cert ? 2 : 0)); + CURL_CHECK_ERROR (curl_easy_setopt, + (curl, CURLOPT_SSL_VERIFYPEER, check_cert ? 1 : 0)); + + CURL_CHECK_ERROR (curl_easy_setopt, + (curl, CURLOPT_WRITEFUNCTION, write_fn)); + CURL_CHECK_ERROR (curl_easy_setopt, + (curl, CURLOPT_HEADERFUNCTION, header_fn)); + + /* This enables error messages in curl_easy_perform. */ + CURL_CHECK_ERROR (curl_easy_setopt, + (curl, CURLOPT_ERRORBUFFER, curl_error_buffer)); + + /* This enables cookie handling, using an internal cookiejar. */ + CURL_CHECK_ERROR (curl_easy_setopt, + (curl, CURLOPT_COOKIEFILE, "")); +} + +/* Called from the message loop. Try to connect to the current URI. + * Returns true on success. + */ static gboolean do_connect (void) { + long code = 0; + DEBUG ("connecting to uri %s", uri); - return FALSE; + + /* Set the URI for libcurl. */ + CURL_CHECK_ERROR (curl_easy_setopt, (curl, CURLOPT_URL, uri)); + + /* Try to fetch the URI. */ + if (CURL_CHECK_ERROR (curl_easy_perform, (curl)) != CURLE_OK) + return FALSE; + + CURL_CHECK_ERROR (curl_easy_getinfo, (curl, CURLINFO_RESPONSE_CODE, &code)); + DEBUG ("HTTP return code is %ld", code); + if (code != 200 || code != 302 || code != 401) + return FALSE; + + return TRUE; } -/* Try to login to URI/login with the username and password given. - * Returns true on success. +/* Called from the message loop. Try to login to 'URI/login' with the + * current username and password. Returns true on success. */ static gboolean do_login (void) @@ -381,7 +474,7 @@ do_login (void) return FALSE; } -/* Refresh the list of VMs. */ +/* Called from the message loop. Refresh the list of VMs. */ static void refresh_vm_list (void) {