Merge branch 'windows'
[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 public class IdentityRequest : Object {
9     private MainWindow main_window;
10     private unowned Mutex mutex;
11     private unowned Cond cond;
12
13     internal IdCard? id_card = null;
14
15     public IdentityRequest (Gtk.Window window,
16                             Mutex _mutex,
17                             Cond _cond)
18     {
19         main_window = (MainWindow)window;
20         mutex = _mutex;
21         cond = _cond;
22     }
23
24     public bool main_loop_cb ()
25     {
26         // Execution is passed from the RPC get_identity() call to
27         // here, where we are inside the main loop thread.
28         main_window.set_callback (this.id_card_selected_cb);
29         return false;
30     }
31
32     public bool id_card_selected_cb ()
33     {
34         this.id_card = this.main_window.selected_id_card_widget.id_card;
35
36         mutex.lock ();
37         cond.signal ();
38
39         // Block the mainloop until the ID card details have been read and
40         // sent, to prevent races
41         cond.wait (mutex);
42         mutex.unlock ();
43
44         return false;
45     }
46 }
47
48 /* This class must be a singleton, because we use a global RPC
49  * binding handle. I cannot picture a situation where more than
50  * one instance of the same interface would be needed so this
51  * shouldn't be a problem.
52  *
53  * Shutdown is automatically done by the RPC runtime when the
54  * process ends
55  */
56 public class MoonshotServer : Object {
57     private static MainWindow main_window;
58
59     private static MoonshotServer instance = null;
60
61     public static void start (Gtk.Window window)
62     {
63         main_window = (MainWindow) window;
64         Rpc.server_start (MoonshotRpcInterface.spec, "/org/janet/Moonshot");
65     }
66
67     public static MoonshotServer get_instance ()
68     {
69         if (instance == null)
70             instance = new MoonshotServer ();
71         return instance;
72     }
73
74     [CCode (cname = "moonshot_get_identity")]
75     public static void moonshot_get_identity (Rpc.AsyncCall call,
76                                               string nai,
77                                               string password,
78                                               string service,
79                                               ref string nai_out,
80                                               ref string password_out,
81                                               ref string certificate_out)
82     {
83         Mutex mutex = new Mutex ();
84         Cond cond = new Cond ();
85         bool result;
86
87         mutex.lock ();
88
89         IdentityRequest request = new IdentityRequest (main_window, mutex, cond);
90
91         // Pass execution to the main loop thread and wait for
92         // the 'send' action to be signalled.
93         Idle.add (request.main_loop_cb);
94         while (request.id_card == null)
95             cond.wait (mutex);
96
97         // Send back the results. Memory is freed by the RPC runtime.
98         if (request.id_card.nai == nai || request.id_card.password == password)
99         {
100             nai_out = request.id_card.nai;
101             password_out = request.id_card.password;
102             certificate_out = "certificate";
103             result = true;
104         }
105         else
106         {
107             result = false;
108         }
109
110         // The outputs must be set before this function is called. For this
111         // reason they are 'ref' not 'out' parameters - Vala assigns to the
112         // 'out' parameters only at the end of the function, which is too
113         // late.
114         call.return (&result);
115
116         cond.signal ();
117         mutex.unlock ();
118     }
119 }