using Rpc;
using MoonshotRpcInterface;
-/* This class is the closure when we pass execution from the RPC thread
- * to the GLib main loop thread; we need to be executing inside the main
- * loop before we can access any state or make any Gtk+ calls.
- */
-/* Fixme: can you make *this* an async callback? */
-public class IdentityRequest : Object {
- private MainWindow main_window;
- private Identity **result;
- private unowned Mutex mutex;
- private unowned Cond cond;
-
- public IdentityRequest (Gtk.Window window,
- Identity **_result,
- Mutex _mutex,
- Cond _cond)
- {
- main_window = (MainWindow)window;
- result = _result;
- mutex = _mutex;
- cond = _cond;
- }
-
- public bool main_loop_cb ()
- {
- // Execution is passed from the RPC get_identity() call to
- // here, where we are inside the main loop thread.
- main_window.set_callback (this.id_card_selected_cb);
- return false;
- }
-
- public bool id_card_selected_cb ()
- {
- var id_card = this.main_window.selected_id_card_widget.id_card;
-
- mutex.lock ();
- *result = new Identity();
-
- (*result)->identity = "identity";
- (*result)->password = id_card.password;
- (*result)->service = "certificate";
-
- cond.signal ();
- mutex.unlock ();
-
- // 'result' is freed by the RPC runtime
-
- return false;
- }
-}
-
/* This class must be a singleton, because we use a global RPC
* binding handle. I cannot picture a situation where more than
* one instance of the same interface would be needed so this
* process ends
*/
public class MoonshotServer : Object {
- private static int counter;
private static MainWindow main_window;
private static MoonshotServer instance = null;
return instance;
}
- /* Note that these RPC callbacks execute outside the GLib main loop,
- * in threads owned by the RPC runtime
- */
-
- [CCode (cname = "moonshot_ping")]
- public static int ping (string msg)
- {
- stdout.printf ("%s\n", msg);
- return counter ++;
- }
-
[CCode (cname = "moonshot_get_identity")]
public static void moonshot_get_identity (Rpc.AsyncCall call,
- string in_identity,
- string in_password,
- string in_service,
- Identity **result)
+ string nai,
+ string password,
+ string service,
+ ref string nai_out,
+ ref string password_out,
+ ref string certificate_out)
{
+ bool result = false;
Mutex mutex = new Mutex ();
Cond cond = new Cond ();
mutex.lock ();
- *result = null;
- IdentityRequest request = new IdentityRequest (main_window, result, mutex, cond);
+ var request = new IdentityRequest (main_window,
+ nai,
+ password,
+ service);
+
+ // Pass execution to the main loop and block the RPC thread
+ request.set_data ("mutex", mutex);
+ request.set_data ("cond", cond);
+ request.set_return_identity_callback (this.return_identity_cb);
+ Idle.add (request.execute);
- // Pass execution to the main loop thread and wait for
- // the 'send' action to be signalled.
- Idle.add (request.main_loop_cb);
- while (*result == null)
+ while (request.complete == false)
cond.wait (mutex);
+
+ nai_out = "";
+ password_out = "";
+ certificate_out = "";
+
+ var id_card = request.id_card;
+
+ if (id_card == null) {
+ foreach (string id_card_service in id_card.services)
+ {
+ if (id_card_service == service)
+ has_service = true;
+ }
+
+ if (has_service)
+ {
+ // The strings are freed by the RPC runtime
+ nai_out = id_card.nai;
+ password_out = id_card.password;
+ certificate_out = "certificate";
+
+ result = true;
+ }
+ }
+
+ // The outputs must be set before this function is called. For this
+ // reason they are 'ref' not 'out' parameters - Vala assigns to the
+ // 'out' parameters only at the end of the function, which is too
+ // late.
+ call.return (&result);
+
+ cond.signal ();
mutex.unlock ();
+ }
+
+ // Called from the main loop thread when an identity has
+ // been selected
+ public void return_identity_cb (IdentityRequest request) {
+ Mutex mutex = request.get_data ("mutex");
+ Cond cond = request.get_data ("cond");
- call.return (null);
+ // Notify the RPC thread that the request is complete
+ mutex.lock ();
+ cond.signal ();
+
+ // Block the main loop until the RPC call has returned
+ // to avoid any races
+ cond.wait (mutex);
+ mutex.unlock ();
}
}