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