client library: Use local exception handling; correct API
authorSam Thursfield <samthursfield@codethink.co.uk>
Wed, 6 Jul 2011 01:01:40 +0000 (02:01 +0100)
committerSam Thursfield <samthursfield@codethink.co.uk>
Wed, 6 Jul 2011 01:01:40 +0000 (02:01 +0100)
libmoonshot/libmoonshot-msrpc.c
libmoonshot/moonshot-msrpc.idl
src/moonshot-server.vala
tests/basic.c

index 73185d4..df29b2f 100644 (file)
 #include "libmoonshot-common.h"
 #include "moonshot-msrpc.h"
 
+#include <stdio.h>
+
 #define MOONSHOT_ENDPOINT_NAME "/org/janet/Moonshot"
 #define MOONSHOT_INSTALL_PATH_KEY "Software\\Moonshot"
 
 
+static MoonshotError *moonshot_error_new_from_status (MoonshotErrorCode code,
+                                                      DWORD             status)
+{
+    MoonshotError *error = malloc (sizeof (MoonshotError));
+    error->code = code;
+    error->message = malloc (256);
+
+    FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, status, 0, (LPSTR)error->message, 255, NULL);
+
+    return error;
+}
+
 static void launch_server (MoonshotError **error) {
     HKEY key = NULL;
     STARTUPINFO startup_info = { 0 };
@@ -102,51 +116,79 @@ static void launch_server (MoonshotError **error) {
     }
 }
 
-/*static void dbus_call_complete_cb (DBusGProxy     *proxy,
-                                   DBusGProxyCall *call_id,
-                                   void           *user_data)
+static void bind_rpc (MoonshotError **error)
 {
-    GError *error = NULL;
-    GSimpleAsyncResult   *token;
-    MoonshotIdentityData *identity_data;
-    gboolean              success;
-
-    token = G_SIMPLE_ASYNC_RESULT (user_data);
-    identity_data = moonshot_identity_data_new ();
-
-    dbus_g_proxy_end_call (moonshot_dbus_proxy,
-                           call_id,
-                           &error,
-                           G_TYPE_STRING, &identity_data->nai,
-                           G_TYPE_STRING, &identity_data->password,
-                           G_TYPE_STRING, &identity_data->server_certificate_hash,
-                           G_TYPE_STRING, &identity_data->ca_certificate,
-                           G_TYPE_STRING, &identity_data->subject_name_constraint,
-                           G_TYPE_STRING, &identity_data->subject_alt_name_constraint,
-                           G_TYPE_BOOLEAN, &success,
-                           G_TYPE_INVALID);
-
-    if (error != NULL) {
-        g_simple_async_result_set_from_error (token, error);
-    }
-    else
-    if (success == FALSE) {
-        error = g_error_new (MOONSHOT_ERROR,
-                             MOONSHOT_ERROR_NO_IDENTITY_SELECTED,
-                             "No matching identity was available");
-        g_simple_async_result_set_from_error (token, error);
-        g_error_free (error);
+    DWORD status;
+    int   i;
+
+    status = rpc_client_bind (&moonshot_binding_handle,
+                              MOONSHOT_ENDPOINT_NAME,
+                              RPC_PER_USER);
+
+    if (status != RPC_S_OK) {
+        *error = moonshot_error_new_from_status (MOONSHOT_ERROR_IPC_ERROR,
+                                                 status);
+        return;
     }
-    else {        
-        g_simple_async_result_set_op_res_gpointer (token,
-                                                   identity_data,
-                                                   moonshot_identity_data_free);
+
+    status = RpcMgmtIsServerListening (moonshot_binding_handle);
+
+    if (status == RPC_S_NOT_LISTENING) {
+        //launch_server (error);
+
+        /* Allow 5 seconds for the server to launch before we time out */
+        //for (i=0; i<50; i++) {
+           // Sleep (100); /* ms */
+/*
+            status = RpcMgmtIsServerListening (moonshot_binding_handle);
+
+            if (status == RPC_S_OK)
+                return;
+
+            if (status != RPC_S_NOT_LISTENING)
+                break;
+        }*/
     }
 
-    g_simple_async_result_complete (token);
-    g_object_unref (token);
+    if (status != RPC_S_OK)
+        *error = moonshot_error_new_from_status (MOONSHOT_ERROR_IPC_ERROR,
+                                                 status);
+}
+
+static void init_rpc (MoonshotError **error)
+{
+    static volatile LONG binding_init_flag = 2;
+    int status;
+
+    /* Hack to avoid requiring a moonshot_init() function. Windows does not
+     * provide any synchronisation primitives that can be statically init'ed,
+     * but we can use its atomic variable access functions to achieve the same.
+     * See: http://msdn.microsoft.com/en-us/library/ms684122%28v=vs.85%29.aspx
+     */
+
+    if (binding_init_flag == 0)
+        return;
+
+    if (InterlockedCompareExchange (&binding_init_flag, 1, 2) == 2) {
+        bind_rpc (error);
+
+        /* We'll handle all exceptions locally to avoid interfering with any
+         * other RPC/other exception handling that goes on in the process,
+         * and so we can store the problem in a MooshotError instead of
+         * aborting.
+         */
+        rpc_set_global_exception_handler_enable (FALSE);
+
+        if (InterlockedCompareExchange (&binding_init_flag, 0, 1) != 1) {
+            /* This should never happen */
+            fprintf (stderr, "moonshot: Internal synchronisation error");
+        }
+    } else {
+        while (binding_init_flag != 0)
+            Sleep (100); /* ms */
+    }
 }
-*/
+
 
 int moonshot_get_identity (const char     *nai,
                            const char     *password,
@@ -159,78 +201,55 @@ int moonshot_get_identity (const char     *nai,
                            char          **subject_alt_name_constraint_out,
                            MoonshotError **error)
 {
-    int status;
-
-    status = rpc_client_bind (&moonshot_binding_handle,
-                              MOONSHOT_ENDPOINT_NAME,
-                              RPC_PER_USER);
-
-    printf ("RPC status: %i\n", status);
+    int success;
+    RpcAsyncCall call;
 
-    /*DBusGProxyCall     *call_id;
-    GSimpleAsyncResult *result; 
-    GError *error = NULL;
+    init_rpc (error);
 
-    if (moonshot_dbus_proxy == NULL)
-        moonshot_dbus_proxy = dbus_connect (&error);
+    if (*error != NULL)
+        return FALSE;
 
-    if (moonshot_dbus_proxy == NULL) {
-        result = g_simple_async_result_new (NULL,
-                                            callback,
-                                            user_data,
-                                            moonshot_get_identity);
-        g_simple_async_result_set_from_error (result, error);
-        g_simple_async_result_complete_in_idle (result);
-        g_error_free (error);
-        return;
+    rpc_async_call_init (&call);
+
+    nai_out = NULL;
+    password_out = NULL;
+    server_certificate_hash_out = NULL;
+    ca_certificate_out = NULL;
+    subject_name_constraint_out = NULL;
+    subject_alt_name_constraint_out = NULL;
+
+    RPC_TRY_EXCEPT {
+        moonshot_get_identity_rpc (&call,
+                                   nai,
+                                   password,
+                                   service,
+                                   nai_out,
+                                   password_out,
+                                   server_certificate_hash_out,
+                                   ca_certificate_out,
+                                   subject_name_constraint_out,
+                                   subject_alt_name_constraint_out);
+
+        success = rpc_async_call_complete_int (&call);
     }
+    RPC_EXCEPT {
+        *error = moonshot_error_new_from_status (MOONSHOT_ERROR_IPC_ERROR,
+                                                 RPC_GET_EXCEPTION_CODE ());
+    }
+    RPC_END_EXCEPT
 
-    g_return_if_fail (DBUS_IS_G_PROXY (moonshot_dbus_proxy));
-
-    result = g_simple_async_result_new (NULL,
-                                        callback,
-                                        user_data,
-                                        moonshot_get_identity);
-
-    call_id = dbus_g_proxy_begin_call (moonshot_dbus_proxy,
-                                       "GetIdentity",
-                                       dbus_call_complete_cb,
-                                       result, NULL,
-                                       G_TYPE_STRING, nai,
-                                       G_TYPE_STRING, password,
-                                       G_TYPE_STRING, service);*/
-}
-
-/*gboolean moonshot_get_identity_finish (GAsyncResult  *result,
-                                       char         **nai,
-                                       char         **password,
-                                       char         **server_certificate_hash,
-                                       char         **ca_certificate,
-                                       char         **subject_name_constraint,
-                                       char         **subject_alt_name_constraint,
-                                       GError       **error)
-{
-    MoonshotIdentityData *identity;
-
-    g_return_val_if_fail (g_simple_async_result_is_valid (result,
-                                                          NULL,
-                                                          moonshot_get_identity),
-                          FALSE);
-
-    if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+    if (*error != NULL)
         return FALSE;
 
-    identity = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
-
-    *nai = identity->nai;
-    *password = identity->password;
-    *server_certificate_hash = identity->server_certificate_hash;
-    *ca_certificate = identity->ca_certificate;
-    *subject_name_constraint = identity->subject_name_constraint;
-    *subject_alt_name_constraint = identity->subject_alt_name_constraint;
+    if (success == FALSE) {
+        *error = moonshot_error_new (MOONSHOT_ERROR_NO_IDENTITY_SELECTED,
+                                     "No identity was returned by the Moonshot "
+                                     "user interface.");
+        return FALSE;
+    }
 
     return TRUE;
-}*/
+}
 
 
 int moonshot_get_default_identity (char          **nai_out,
@@ -241,11 +260,49 @@ int moonshot_get_default_identity (char          **nai_out,
                                    char          **subject_alt_name_constraint_out,
                                    MoonshotError **error)
 {
-    int status;
+    int success;
+    RpcAsyncCall call;
 
-    status = rpc_client_bind (&moonshot_binding_handle,
-                              MOONSHOT_ENDPOINT_NAME,
-                              RPC_PER_USER);
+    init_rpc (error);
+
+    if (*error != NULL)
+        return FALSE;
+
+    rpc_async_call_init (&call);
+
+    nai_out = NULL;
+    password_out = NULL;
+    server_certificate_hash_out = NULL;
+    ca_certificate_out = NULL;
+    subject_name_constraint_out = NULL;
+    subject_alt_name_constraint_out = NULL;
+
+    RPC_TRY_EXCEPT {
+        moonshot_get_default_identity_rpc (&call,
+                                           nai_out,
+                                           password_out,
+                                           server_certificate_hash_out,
+                                           ca_certificate_out,
+                                           subject_name_constraint_out,
+                                           subject_alt_name_constraint_out);
+
+        success = rpc_async_call_complete_int (&call);
+    }
+    RPC_EXCEPT {
+        *error = moonshot_error_new_from_status (MOONSHOT_ERROR_IPC_ERROR,
+                                                 RPC_GET_EXCEPTION_CODE ());
+    }
+    RPC_END_EXCEPT
+
+    if (*error != NULL)
+        return FALSE;
+
+    if (success == FALSE) {
+        *error = moonshot_error_new (MOONSHOT_ERROR_NO_IDENTITY_SELECTED,
+                                     "No identity was returned by the Moonshot "
+                                     "user interface.");
+        return FALSE;
+    }
 
-    printf ("RPC status: %i\n", status);
+    return TRUE;
 };
index 8055713..e02ff2c 100644 (file)
@@ -15,6 +15,10 @@ interface moonshot
                                    [out, string] char **subject_alt_name_constraint);
 
     int moonshot_get_default_identity_rpc ([out, string] char **nai_out,
-                                           [out, string] char **password_out);
+                                           [out, string] char **password_out,
+                                           [out, string] char **server_certificate_hash,
+                                           [out, string] char **ca_certificate,
+                                           [out, string] char **subject_name_constraint,
+                                           [out, string] char **subject_alt_name_constraint);
 }
 
index 145d6bf..02d9edf 100644 (file)
@@ -185,7 +185,11 @@ public class MoonshotServer : Object {
     [CCode (cname = "moonshot_get_default_identity_rpc")]
     public static void get_default_identity (Rpc.AsyncCall call,
                                              ref string nai_out,
-                                             ref string password_out)
+                                             ref string password_out,
+                                             ref string server_certificate_hash,
+                                             ref string ca_certificate,
+                                             ref string subject_name_constraint,
+                                             ref string subject_alt_name_constraint)
     {
         bool result;
 
@@ -202,11 +206,16 @@ public class MoonshotServer : Object {
 
         nai_out = "";
         password_out = "";
+        server_certificate_hash = "";
+        ca_certificate = "";
+        subject_name_constraint = "";
+        subject_alt_name_constraint = "";
 
         if (request.id_card != null)
         {
             nai_out = request.id_card.nai;
             password_out = request.id_card.password;
+            server_certificate_hash = "certificate";
 
             return_if_fail (nai_out != null);
             return_if_fail (password_out != null);
index 0d1e127..25a4945 100644 (file)
@@ -27,7 +27,8 @@ gpointer test_func (gpointer data)
                                              &subject_alt_name_constraint,
                                              error);
 
-    g_print ("Got id: %s %s\n", nai, password);
+    if (success)
+        g_print ("Got id: %s %s\n", nai, password);
 
     return GINT_TO_POINTER (success);
 }
@@ -91,7 +92,7 @@ int main (int argc, char *argv[])
     g_test_init (&argc, &argv, NULL);
 
     g_test_add_func ("/basic/connect", test_connect);
-    g_test_add_func ("/basic/multithread", test_multithread);
+    //g_test_add_func ("/basic/multithread", test_multithread);
 
     g_test_run ();
 }