gveditor_core/
server.rs

1use crate::handlers::TransportHandler;
2use crate::Configuration;
3use gveditor_core_api::filesystems::{DirItemInfo, FileInfo, FilesystemErrors};
4use gveditor_core_api::messaging::{ExtensionMessages, Messages};
5use gveditor_core_api::state::{StateData, StatesList};
6use gveditor_core_api::{Errors, LanguageServer, ManifestInfo, Mutex, State};
7use jsonrpc_core::BoxFuture;
8use jsonrpc_derive::rpc;
9
10use std::sync::Arc;
11
12pub struct Server {
13    states: Arc<Mutex<StatesList>>,
14    config: Configuration,
15}
16
17/// Graviton Server entry point
18///
19/// # Example
20/// ```rust
21/// # use std::sync::Arc;
22/// # use gveditor_core::{
23///     # handlers::HTTPHandler,
24///     # Configuration,
25///     # Server,
26/// # };
27///  # use gveditor_core_api::{
28///     # extensions::manager::ExtensionsManager,
29///     # messaging::Messages,
30///     # state::{
31///     #    StatesList,
32///     #    TokenFlags,
33///     #    MemoryPersistor,
34///     # },
35///     # State
36///  # };
37/// # use tokio::sync::{
38///    # mpsc::channel,
39///    # Mutex
40/// # };
41///  # tokio_test::block_on(async {
42///  let (to_core, from_core) = channel::<Messages>(1);
43///
44///  // A pointer to a StatesList
45///  let states = {
46///     // A basic State with ID '1' and no extensions
47///     let sample_state = State::new(1, ExtensionsManager::new(to_core.clone(), None), Box::new(MemoryPersistor::new()));
48///
49///     // A StatesList with the previous state
50///     let states = StatesList::new()
51///         .with_state(sample_state);
52///
53///     Arc::new(Mutex::new(states))
54///  };
55///  
56///  // Crate a HTTP TransportHandler and a configuration
57///  let http_handler = HTTPHandler::builder().build();
58///
59///  // Create the configuration
60///  let config = Configuration::new(Box::new(http_handler), to_core, from_core);
61///
62///  // Create a Core
63///  let core = Server::new(config, states);
64///
65///  // Run the core
66///  core.run();
67///  # })
68/// ```
69///
70impl Server {
71    /// Create a new Server
72    ///
73    /// # Arguments
74    ///
75    /// * `config`   - The Core configuration
76    /// * `states`   - The States list the Core will launch with
77    ///
78    pub fn new(mut config: Configuration, states: Arc<Mutex<StatesList>>) -> Self {
79        let receiver = config.receiver.take();
80        let handler = config.handler.clone();
81        let states_list = states.clone();
82
83        tokio::spawn(async move {
84            if let Some(mut receiver) = receiver {
85                loop {
86                    if let Some(message) = receiver.recv().await {
87                        Self::process_message(states_list.clone(), message, handler.clone()).await;
88                    }
89                }
90            }
91        });
92
93        Self { config, states }
94    }
95
96    /// Run the configured handler
97    pub async fn run(&self) {
98        let states = self.states.clone();
99        let mut handler = self.config.handler.lock().await;
100
101        handler
102            .run(states.clone(), self.config.sender.clone())
103            .await;
104    }
105
106    /// Process every message
107    pub async fn process_message(
108        states: Arc<Mutex<StatesList>>,
109        msg: Messages,
110        handler: Arc<Mutex<Box<dyn TransportHandler + Send + Sync>>>,
111    ) {
112        match msg {
113            Messages::ListenToState {
114                state_id,
115                trigger: _,
116            } => {
117                // Make sure if there is already an existing state
118                let state = {
119                    let states = states.lock().await;
120                    states.get_state_by_id(state_id)
121                };
122
123                if let Some(state) = state {
124                    let handler = handler.lock().await;
125                    // Send the loaded state to the handler
126                    let message = Messages::StateUpdated {
127                        state_data: state.lock().await.data.clone(),
128                    };
129                    handler.send(message).await;
130
131                    state.lock().await.run_extensions().await;
132                }
133            }
134            Messages::StateUpdated { .. } => {
135                let states = states.lock().await;
136                states
137                    .notify_extensions(ExtensionMessages::CoreMessage(msg))
138                    .await;
139            }
140            Messages::RegisterLanguageServers {
141                state_id,
142                languages,
143                ..
144            } => {
145                let state = {
146                    let states = states.lock().await;
147                    states.get_state_by_id(state_id)
148                };
149
150                if let Some(state) = state {
151                    state
152                        .lock()
153                        .await
154                        .register_language_servers(languages)
155                        .await;
156                }
157            }
158            Messages::NotifyLanguageServers {
159                state_id, message, ..
160            } => {
161                let state = {
162                    let states = states.lock().await;
163                    states.get_state_by_id(state_id)
164                };
165
166                if let Some(state) = state {
167                    state
168                        .lock()
169                        .await
170                        .notify_extensions(ExtensionMessages::CoreMessage(
171                            Messages::NotifyLanguageServers { state_id, message },
172                        ));
173                }
174            }
175            _ => {
176                // Forward to the handler messages not handled here
177                let handler = handler.lock().await;
178                handler.send(msg).await;
179            }
180        }
181    }
182}
183
184pub type RPCResult<T> = jsonrpc_core::Result<T>;
185
186/// Definition of all JSON RPC Methods
187#[rpc]
188pub trait RpcMethods {
189    #[rpc(name = "get_state_data_by_id")]
190    fn get_state_by_id(
191        &self,
192        state_id: u8,
193        token: String,
194    ) -> BoxFuture<RPCResult<Result<Option<StateData>, Errors>>>;
195
196    #[rpc(name = "set_state_data_by_id")]
197    fn set_state_by_id(
198        &self,
199        state_id: u8,
200        state: StateData,
201        token: String,
202    ) -> BoxFuture<RPCResult<Result<(), Errors>>>;
203
204    #[rpc(name = "read_file_by_path")]
205    fn read_file_by_path(
206        &self,
207        path: String,
208        filesystem_name: String,
209        state_id: u8,
210        token: String,
211    ) -> BoxFuture<RPCResult<Result<FileInfo, Errors>>>;
212
213    #[rpc(name = "write_file_by_path")]
214    fn write_file_by_path(
215        &self,
216        path: String,
217        content: String,
218        filesystem_name: String,
219        state_id: u8,
220        token: String,
221    ) -> BoxFuture<RPCResult<Result<(), Errors>>>;
222
223    #[rpc(name = "list_dir_by_path")]
224    fn list_dir_by_path(
225        &self,
226        path: String,
227        filesystem_name: String,
228        state_id: u8,
229        token: String,
230    ) -> BoxFuture<RPCResult<Result<Vec<DirItemInfo>, Errors>>>;
231
232    #[rpc(name = "get_ext_info_by_id")]
233    fn get_ext_info_by_id(
234        &self,
235        extension_id: String,
236        state_id: u8,
237        token: String,
238    ) -> BoxFuture<RPCResult<Result<ManifestInfo, Errors>>>;
239
240    #[rpc(name = "get_ext_list_by_id")]
241    fn get_ext_list_by_id(
242        &self,
243        state_id: u8,
244        token: String,
245    ) -> BoxFuture<RPCResult<Result<Vec<String>, Errors>>>;
246
247    #[rpc(name = "get_all_language_servers")]
248    fn get_all_language_servers(
249        &self,
250        state_id: u8,
251        token: String,
252    ) -> BoxFuture<RPCResult<Result<Vec<LanguageServer>, Errors>>>;
253
254    #[rpc(name = "get_all_language_servers")]
255    fn notify_extension(
256        &self,
257        state_id: u8,
258        token: String,
259        message: ExtensionMessages,
260    ) -> BoxFuture<RPCResult<Result<(), Errors>>>;
261}
262
263async fn verify_state(
264    states: Arc<Mutex<StatesList>>,
265    state_id: u8,
266    token: String,
267) -> Result<Arc<Mutex<State>>, Errors> {
268    let states = states.lock().await;
269    // Try to get the requested state
270    if let Some(state) = states.get_state_by_id(state_id) {
271        let state_g = state.lock().await;
272        // Make sure the token is valid
273        if state_g.has_token(&token) {
274            drop(state_g);
275            Ok(state)
276        } else {
277            Err(Errors::BadToken)
278        }
279    } else {
280        Err(Errors::StateNotFound)
281    }
282}
283
284/// JSON RPC manager
285pub struct RpcManager {
286    pub states: Arc<Mutex<StatesList>>,
287}
288
289/// Implementation of all JSON RPC methods
290impl RpcMethods for RpcManager {
291    /// Return the state by the given ID if found
292    fn get_state_by_id(
293        &self,
294        state_id: u8,
295        token: String,
296    ) -> BoxFuture<RPCResult<Result<Option<StateData>, Errors>>> {
297        let states = self.states.clone();
298        Box::pin(async move {
299            Ok({
300                let state = verify_state(states, state_id, token).await;
301                if let Ok(state) = state {
302                    let state = state.lock().await;
303                    Ok(Some(state.data.clone()))
304                } else {
305                    Err(state.unwrap_err())
306                }
307            })
308        })
309    }
310
311    /// Update an state
312    fn set_state_by_id(
313        &self,
314        state_id: u8,
315        new_state_data: StateData,
316        token: String,
317    ) -> BoxFuture<RPCResult<Result<(), Errors>>> {
318        let states = self.states.clone();
319        Box::pin(async move {
320            Ok({
321                let state = verify_state(states, state_id, token).await;
322
323                if let Ok(state) = state {
324                    let mut state = state.lock().await;
325
326                    tracing::info!("Updated state by id <{}>", state.data.id);
327                    state.update(new_state_data).await;
328
329                    Ok(())
330                } else {
331                    Err(state.unwrap_err())
332                }
333            })
334        })
335    }
336
337    /// Returns the content of a file
338    /// Internally implemented by the given filesystem
339    fn read_file_by_path(
340        &self,
341        path: String,
342        filesystem_name: String,
343        state_id: u8,
344        token: String,
345    ) -> BoxFuture<RPCResult<Result<FileInfo, Errors>>> {
346        let states = self.states.clone();
347        Box::pin(async move {
348            Ok({
349                let state = verify_state(states, state_id, token).await;
350
351                if let Ok(state) = state {
352                    let state = state.lock().await;
353
354                    if let Some(filesystem) = state.get_fs_by_name(&filesystem_name) {
355                        let filesystem = filesystem.lock().await;
356                        let result = filesystem.read_file_by_path(&path);
357                        let result = result.await;
358
359                        state.notify_extensions(ExtensionMessages::ReadFile(
360                            state_id,
361                            filesystem_name,
362                            result.clone(),
363                        ));
364
365                        result
366                    } else {
367                        Err(Errors::Fs(FilesystemErrors::FilesystemNotFound))
368                    }
369                } else {
370                    Err(state.unwrap_err())
371                }
372            })
373        })
374    }
375
376    /// Writes new content to the specified path
377    fn write_file_by_path(
378        &self,
379        path: String,
380        content: String,
381        filesystem_name: String,
382        state_id: u8,
383        token: String,
384    ) -> BoxFuture<RPCResult<Result<(), Errors>>> {
385        let states = self.states.clone();
386
387        Box::pin(async move {
388            Ok({
389                let state = verify_state(states, state_id, token).await;
390
391                if let Ok(state) = state {
392                    let state = state.lock().await;
393
394                    if let Some(filesystem) = state.get_fs_by_name(&filesystem_name) {
395                        let filesystem = filesystem.lock().await;
396                        let result = filesystem.write_file_by_path(&path, &content);
397                        let result = result.await;
398
399                        state.notify_extensions(ExtensionMessages::WriteFile(
400                            state_id,
401                            filesystem_name,
402                            content,
403                            result.clone(),
404                        ));
405
406                        result
407                    } else {
408                        Err(Errors::Fs(FilesystemErrors::FilesystemNotFound))
409                    }
410                } else {
411                    Err(state.unwrap_err())
412                }
413            })
414        })
415    }
416
417    /// Returns the list of items inside the given directory
418    /// Internally implemented by the given filesystem
419    fn list_dir_by_path(
420        &self,
421        path: String,
422        filesystem_name: String,
423        state_id: u8,
424        token: String,
425    ) -> BoxFuture<RPCResult<Result<Vec<DirItemInfo>, Errors>>> {
426        let states = self.states.clone();
427
428        Box::pin(async move {
429            Ok({
430                let state = verify_state(states, state_id, token).await;
431
432                if let Ok(state) = state {
433                    let state = state.lock().await;
434
435                    if let Some(filesystem) = state.get_fs_by_name(&filesystem_name) {
436                        let filesystem = filesystem.lock().await;
437                        let result = filesystem.list_dir_by_path(&path);
438                        let result = result.await;
439
440                        state.notify_extensions(ExtensionMessages::ListDir(
441                            state_id,
442                            filesystem_name,
443                            path,
444                            result.clone(),
445                        ));
446
447                        result
448                    } else {
449                        Err(Errors::Fs(FilesystemErrors::FilesystemNotFound))
450                    }
451                } else {
452                    Err(state.unwrap_err())
453                }
454            })
455        })
456    }
457
458    /// Returns the information about a extension
459    fn get_ext_info_by_id(
460        &self,
461        extension_id: String,
462        state_id: u8,
463        token: String,
464    ) -> BoxFuture<RPCResult<Result<ManifestInfo, Errors>>> {
465        let states = self.states.clone();
466
467        Box::pin(async move {
468            Ok({
469                let state = verify_state(states, state_id, token).await;
470
471                if let Ok(state) = state {
472                    let state = state.lock().await;
473
474                    state.get_ext_info_by_id(&extension_id)
475                } else {
476                    Err(state.unwrap_err())
477                }
478            })
479        })
480    }
481    /// Returns the list of extensions in the specified state
482    fn get_ext_list_by_id(
483        &self,
484        state_id: u8,
485        token: String,
486    ) -> BoxFuture<RPCResult<Result<Vec<String>, Errors>>> {
487        let states = self.states.clone();
488        Box::pin(async move {
489            Ok({
490                let state = verify_state(states, state_id, token).await;
491
492                if let Ok(state) = state {
493                    let state = state.lock().await;
494
495                    Ok(state.get_ext_list_by_id())
496                } else {
497                    Err(state.unwrap_err())
498                }
499            })
500        })
501    }
502
503    /// Returns the list of language servers services in the specified state
504    fn get_all_language_servers(
505        &self,
506        state_id: u8,
507        token: String,
508    ) -> BoxFuture<RPCResult<Result<Vec<LanguageServer>, Errors>>> {
509        let states = self.states.clone();
510        Box::pin(async move {
511            Ok({
512                let state = verify_state(states, state_id, token).await;
513
514                if let Ok(state) = state {
515                    let state = state.lock().await;
516
517                    Ok(state.get_all_language_servers().await)
518                } else {
519                    Err(state.unwrap_err())
520                }
521            })
522        })
523    }
524
525    fn notify_extension(
526        &self,
527        state_id: u8,
528        token: String,
529        message: ExtensionMessages,
530    ) -> BoxFuture<RPCResult<Result<(), Errors>>> {
531        let states = self.states.clone();
532        Box::pin(async move {
533            Ok({
534                let state = verify_state(states, state_id, token).await;
535
536                if let Ok(state) = state {
537                    let state = state.lock().await;
538
539                    state.notify_extensions(message);
540
541                    Ok(())
542                } else {
543                    Err(state.unwrap_err())
544                }
545            })
546        })
547    }
548}