120b6c2d64ac6cd78ea25ca847f10e681a733839
[moonshot-ui.git] / src / moonshot-msrpc-server.vala
1 using Rpc;
2 using MoonshotRpcInterface;
3
4 /* This class is the closure when we pass execution from the RPC thread
5  * to the GLib main loop thread; we need to be executing inside the main
6  * loop before we can access any state or make any Gtk+ calls.
7  */
8 /* Fixme: can you make *this* an async callback? */
9 public class IdentityRequest : Object {
10     private MainWindow main_window;
11     private Identity **result;
12     private unowned Mutex mutex;
13     private unowned Cond cond;
14
15     public IdentityRequest (Gtk.Window window,
16                             Identity **_result,
17                             Mutex _mutex,
18                             Cond _cond)
19     {
20         main_window = (MainWindow)window;
21         result = _result;
22         mutex = _mutex;
23         cond = _cond;
24     }
25
26     public bool main_loop_cb ()
27     {
28         // Execution is passed from the RPC get_identity() call to
29         // here, where we are inside the main loop thread.
30         main_window.set_callback (this.id_card_selected_cb);
31         return false;
32     }
33
34     public bool id_card_selected_cb ()
35     {
36         var id_card = this.main_window.selected_id_card_widget.id_card;
37
38         mutex.lock ();
39         *result = new Identity();
40
41         (*result)->identity = "identity";
42         (*result)->password = id_card.password;
43         (*result)->service = "certificate";
44
45         cond.signal ();
46         mutex.unlock ();
47
48         // 'result' is freed by the RPC runtime
49
50         return false;
51     }
52 }
53
54 /* This class must be a singleton, because we use a global RPC
55  * binding handle. I cannot picture a situation where more than
56  * one instance of the same interface would be needed so this
57  * shouldn't be a problem.
58  *
59  * Shutdown is automatically done by the RPC runtime when the
60  * process ends
61  */
62 public class MoonshotServer : Object {
63     private static int counter;
64     private static MainWindow main_window;
65
66     private static MoonshotServer instance = null;
67
68     public static void start (Gtk.Window window)
69     {
70         main_window = (MainWindow) window;
71         Rpc.server_start (MoonshotRpcInterface.spec, "/org/janet/Moonshot");
72     }
73
74     public static MoonshotServer get_instance ()
75     {
76         if (instance == null)
77             instance = new MoonshotServer ();
78         return instance;
79     }
80
81     /* Note that these RPC callbacks execute outside the GLib main loop,
82      * in threads owned by the RPC runtime
83      */
84
85     [CCode (cname = "moonshot_ping")]
86     public static int ping (string msg)
87     {
88         stdout.printf ("%s\n", msg);
89         return counter ++;
90     }
91
92     [CCode (cname = "moonshot_get_identity")]
93     public static void moonshot_get_identity (Rpc.AsyncCall call,
94                                               string in_identity,
95                                               string in_password,
96                                               string in_service,
97                                               Identity **result)
98     {
99         Mutex mutex = new Mutex ();
100         Cond cond = new Cond ();
101
102         mutex.lock ();
103
104         *result = null;
105         IdentityRequest request = new IdentityRequest (main_window, result, mutex, cond);
106
107         // Pass execution to the main loop thread and wait for
108         // the 'send' action to be signalled.
109         Idle.add (request.main_loop_cb);
110         while (*result == null)
111             cond.wait (mutex);
112         mutex.unlock ();
113
114         call.return (null);
115     }
116 }