Merge branch 'master' of origin
[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                 return true;
66             }
67         }
68
69         return false;
70     }
71 }
72
73 #elif IPC_MSRPC
74
75 using Rpc;
76 using MoonshotRpcInterface;
77
78 /* This class must be a singleton, because we use a global RPC
79  * binding handle. I cannot picture a situation where more than
80  * one instance of the same interface would be needed so this
81  * shouldn't be a problem.
82  *
83  * Shutdown is automatically done by the RPC runtime when the
84  * process ends
85  */
86 public class MoonshotServer : Object {
87     private static MainWindow main_window;
88
89     private static MoonshotServer instance = null;
90
91     public static void start (Gtk.Window window)
92     {
93         main_window = (MainWindow) window;
94         Rpc.server_start (MoonshotRpcInterface.spec, "/org/janet/Moonshot", Rpc.Flags.PER_USER);
95     }
96
97     public static MoonshotServer get_instance ()
98     {
99         if (instance == null)
100             instance = new MoonshotServer ();
101         return instance;
102     }
103
104     [CCode (cname = "moonshot_get_identity")]
105     public static void moonshot_get_identity (Rpc.AsyncCall call,
106                                               string nai,
107                                               string password,
108                                               string service,
109                                               ref string nai_out,
110                                               ref string password_out,
111                                               ref string certificate_out)
112     {
113         bool result = false;
114
115         var request = new IdentityRequest (main_window,
116                                            nai,
117                                            password,
118                                            service);
119
120         // Pass execution to the main loop and block the RPC thread
121         request.mutex = new Mutex ();
122         request.cond = new Cond ();
123         request.set_callback (return_identity_cb);
124
125         request.mutex.lock ();
126         Idle.add (request.execute);
127
128         while (request.complete == false)
129             request.cond.wait (request.mutex);
130
131         nai_out = "";
132         password_out = "";
133         certificate_out = "";
134
135         var id_card = request.id_card;
136         bool has_service = false;
137
138         if (id_card == null) {
139             foreach (string id_card_service in id_card.services)
140             {
141                 if (id_card_service == service)
142                     has_service = true;
143             }
144
145             if (has_service)
146             {
147                 // The strings are freed by the RPC runtime
148                 nai_out = id_card.nai;
149                 password_out = id_card.password;
150                 certificate_out = "certificate";
151
152                 result = true;
153             }
154         }
155
156         // The outputs must be set before this function is called. For this
157         // reason they are 'ref' not 'out' parameters - Vala assigns to the
158         // 'out' parameters only at the end of the function, which is too
159         // late.
160         call.return (&result);
161
162         request.cond.signal ();
163         request.mutex.unlock ();
164     }
165
166     [CCode (cname = "moonshot_get_default_identity")]
167     public static void get_default_identity (Rpc.AsyncCall call,
168                                              ref string nai_out,
169                                              ref string password_out)
170     {
171         bool result = false;
172
173         var request = new IdentityRequest.default (main_window);
174
175         // This is really a lot of work to get a default identity.
176         // However, it's really best to do so in the main loop to avoid
177         // races (the alternative is add a mutex to the ID card data,
178         // but this is the only place it would be used).
179         request.mutex = new Mutex ();
180         request.cond = new Cond ();
181         request.set_callback (return_identity_cb);
182
183         request.mutex.lock ();
184         Idle.add (request.execute);
185
186         while (request.complete == false)
187             request.cond.wait (request.mutex);
188
189         nai_out = "";
190         password_out = "";
191         certificate_out = "";
192
193         var id_card = request.id_card;
194         bool has_service = false;
195
196         if (id_card == null) {
197             foreach (string id_card_service in id_card.services)
198             {
199                 if (id_card_service == service)
200                     has_service = true;
201             }
202
203             if (has_service)
204             {
205                 // The strings are freed by the RPC runtime
206                 nai_out = id_card.nai;
207                 password_out = id_card.password;
208                 certificate_out = "certificate";
209
210                 result = true;
211             }
212         }
213
214         // The outputs must be set before this function is called. For this
215         // reason they are 'ref' not 'out' parameters - Vala assigns to the
216         // 'out' parameters only at the end of the function, which is too
217         // late.
218         call.return (&result);
219
220         request.cond.signal ();
221         request.mutex.unlock ();
222     }
223
224     // Called from the main loop thread when an identity has
225     // been selected
226     static void return_identity_cb (IdentityRequest request) {
227         // Notify the RPC thread that the request is complete
228         request.mutex.lock ();
229         request.cond.signal ();
230
231         // Block the main loop until the RPC call has returned
232         // to avoid any races
233         request.cond.wait (request.mutex);
234         request.mutex.unlock ();
235     }
236 }
237
238 #endif