Push daily update.
[ovirt-viewer.git] / wui_thread.c
index 0db43c8..8079f75 100644 (file)
 
 #include <glib.h>
 
+#include <curl/curl.h>
+
 #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)
 {