Add get_default_identity()
[moonshot-ui.git] / src / moonshot-server.vala
1 #if IPC_DBUS
2
3 [DBus (name = "org.janet.Moonshot")]
4 public class MoonshotServer : Object {
5
6     private MainWindow main_window;
7
8     public MoonshotServer (Gtk.Window window)
9     {
10         this.main_window = (MainWindow) window;
11     }
12
13     /**
14      * This is the function used by the GSS mechanism to get the NAI,
15      * password and certificate of the ID card for the specificated service.
16      *
17      * The function will block until the user choose the ID card.
18      *
19      * @param nai NAI of the ID Card (optional)
20      * @param password Password of the ID Card (optional)
21      * @param service Service application request an ID Card for
22      * @param nai_out NAI stored in the ID Card
23      * @param password_out Password stored in the ID Card
24      * @param certificate Certificate stored in th ID Card
25      *
26      * @return true if the user choose a correct ID card for that service,
27      *         false otherwise.
28      */
29     public async bool get_identity (string nai,
30                                     string password,
31                                     string service,
32                                     out string nai_out,
33                                     out string password_out,
34                                     out string certificate_out)
35     {
36         bool has_service = false;
37
38         var request = new IdentityRequest (main_window,
39                                            nai,
40                                            password,
41                                            service);
42         request.set_callback ((IdentityRequest) => get_identity.callback());
43         request.execute ();
44         yield;
45
46         nai_out = "";
47         password_out = "";
48         certificate_out = "";
49
50         var id_card = request.id_card;
51
52         if (id_card != null) {
53             foreach (string id_card_service in id_card.services)
54             {
55                 if (id_card_service == service)
56                     has_service = true;
57             }
58
59             if (has_service)
60             {
61                 nai_out = id_card.nai;
62                 password_out = id_card.password;
63                 certificate_out = "certificate";
64
65                 // User should have been prompted if there was no p/w.
66                 return_if_fail (nai_out != null);
67                 return_if_fail (password_out != null);
68
69                 return true;
70             }
71         }
72
73         return false;
74     }
75
76     /**
77      * Returns the default identity - most recently used.
78      *
79      * @param nai_out NAI stored in the ID card
80      * @param password_out Password stored in the ID card
81      *
82      * @return true on success, false if no identities are stored
83      */
84     public async bool get_default_identity (out string nai_out,
85                                             out string password_out)
86     {
87         var request = new IdentityRequest.default (main_window);
88         request.set_callback ((IdentityRequest) => get_default_identity.callback());
89         request.execute ();
90         yield;
91
92         nai_out = "";
93         password_out = "";
94
95         if (request.id_card != null)
96         {
97             nai_out = request.id_card.nai;
98             password_out = request.id_card.password;
99
100             // User should have been prompted if there was no p/w.
101             return_val_if_fail (nai_out != null, false);
102             return_val_if_fail (password_out != null, false);
103
104             return true;
105         }
106
107         return false;
108     }
109 }
110
111 #elif IPC_MSRPC
112
113 using Rpc;
114 using MoonshotRpcInterface;
115
116 /* This class must be a singleton, because we use a global RPC
117  * binding handle. I cannot picture a situation where more than
118  * one instance of the same interface would be needed so this
119  * shouldn't be a problem.
120  *
121  * Shutdown is automatically done by the RPC runtime when the
122  * process ends
123  */
124 public class MoonshotServer : Object {
125     private static MainWindow main_window;
126
127     private static MoonshotServer instance = null;
128
129     public static void start (Gtk.Window window)
130     {
131         main_window = (MainWindow) window;
132         Rpc.server_start (MoonshotRpcInterface.spec, "/org/janet/Moonshot", Rpc.Flags.PER_USER);
133     }
134
135     public static MoonshotServer get_instance ()
136     {
137         if (instance == null)
138             instance = new MoonshotServer ();
139         return instance;
140     }
141
142     [CCode (cname = "moonshot_get_identity")]
143     public static void get_identity (Rpc.AsyncCall call,
144                                      string nai,
145                                      string password,
146                                      string service,
147                                      ref string nai_out,
148                                      ref string password_out,
149                                      ref string certificate_out)
150     {
151         bool result = false;
152
153         var request = new IdentityRequest (main_window,
154                                            nai,
155                                            password,
156                                            service);
157
158         // Pass execution to the main loop and block the RPC thread
159         request.mutex = new Mutex ();
160         request.cond = new Cond ();
161         request.set_callback (return_identity_cb);
162
163         request.mutex.lock ();
164         Idle.add (request.execute);
165
166         while (request.complete == false)
167             request.cond.wait (request.mutex);
168
169         nai_out = "";
170         password_out = "";
171         certificate_out = "";
172
173         var id_card = request.id_card;
174         bool has_service = false;
175
176         if (id_card == null) {
177             foreach (string id_card_service in id_card.services)
178             {
179                 if (id_card_service == service)
180                     has_service = true;
181             }
182
183             if (has_service)
184             {
185                 // The strings are freed by the RPC runtime
186                 nai_out = id_card.nai;
187                 password_out = id_card.password;
188                 certificate_out = "certificate";
189
190                 return_if_fail (nai_out != null);
191                 return_if_fail (password_out != null);
192
193                 result = true;
194             }
195         }
196
197         // The outputs must be set before this function is called. For this
198         // reason they are 'ref' not 'out' parameters - Vala assigns to the
199         // 'out' parameters only at the end of the function, which is too
200         // late.
201         call.return (&result);
202
203         request.cond.signal ();
204         request.mutex.unlock ();
205     }
206
207     [CCode (cname = "moonshot_get_default_identity")]
208     public static void get_default_identity (Rpc.AsyncCall call,
209                                              ref string nai_out,
210                                              ref string password_out)
211     {
212         bool result;
213
214         var request = new IdentityRequest.default (main_window);
215         request.mutex = new Mutex ();
216         request.cond = new Cond ();
217         request.set_callback (return_identity_cb);
218
219         request.mutex.lock ();
220         Idle.add (request.execute);
221
222         while (request.complete == false)
223             request.cond.wait (request.mutex);
224
225         nai_out = "";
226         password_out = "";
227
228         if (request.id_card != null)
229         {
230             nai_out = request.id_card.nai;
231             password_out = request.id_card.password;
232
233             return_if_fail (nai_out != null);
234             return_if_fail (password_out != null);
235
236             result = true;
237         }
238         else
239         {
240             result = false;
241         }
242
243         call.return (&result);
244
245         request.cond.signal ();
246         request.mutex.unlock ();
247     }
248
249     // Called from the main loop thread when an identity has
250     // been selected
251     static void return_identity_cb (IdentityRequest request) {
252         // Notify the RPC thread that the request is complete
253         request.mutex.lock ();
254         request.cond.signal ();
255
256         // Block the main loop until the RPC call has returned
257         // to avoid any races
258         request.cond.wait (request.mutex);
259         request.mutex.unlock ();
260     }
261 }
262
263 #endif