fixes
This commit is contained in:
		| @@ -34,14 +34,17 @@ interface VeilidServer { | ||||
|  | ||||
|     register @0 (veilidClient: VeilidClient) -> (registration: Registration); | ||||
|  | ||||
|     attach @1 () -> (result: Bool); | ||||
|     detach @2 () -> (result: Bool); | ||||
|     shutdown @3 () -> (result: Bool); | ||||
|     attach @1 (); | ||||
|     detach @2 (); | ||||
|     shutdown @3 (); | ||||
|  | ||||
|     debug @4 (what: Text) -> (output: Text); | ||||
|  | ||||
| } | ||||
|  | ||||
| interface VeilidClient { | ||||
|  | ||||
|     stateChanged @0 (changed: VeilidStateChange); | ||||
|     logMessage @1 (message: Text); | ||||
|  | ||||
| } | ||||
| @@ -160,6 +160,25 @@ impl veilid_server::Server for VeilidServerImpl { | ||||
|  | ||||
|         Promise::ok(()) | ||||
|     } | ||||
|  | ||||
|     fn debug( | ||||
|         &mut self, | ||||
|         params: veilid_server::DebugParams, | ||||
|         mut results: veilid_server::DebugResults, | ||||
|     ) -> Promise<(), ::capnp::Error> { | ||||
|         trace!("VeilidServerImpl::attach"); | ||||
|         let veilid_api = self.veilid_api.clone(); | ||||
|         let what = pry!(pry!(params.get()).get_what()).to_owned(); | ||||
|  | ||||
|         Promise::from_future(async move { | ||||
|             let output = veilid_api | ||||
|                 .debug(what) | ||||
|                 .await | ||||
|                 .map_err(|e| ::capnp::Error::failed(format!("{:?}", e)))?; | ||||
|             results.get().set_output(output.as_str()); | ||||
|             Ok(()) | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| // --- Client API Server-Side --------------------------------- | ||||
| @@ -268,9 +287,11 @@ impl ClientApi { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn handle_state_change(self: Rc<Self>, changed: veilid_core::VeilidStateChange) { | ||||
|         trace!("state changed: {:?}", changed); | ||||
|  | ||||
|     fn send_request_to_all_clients<F, T>(self: Rc<Self>, request: F) | ||||
|     where | ||||
|         F: Fn(u64, &mut RegistrationHandle) -> ::capnp::capability::RemotePromise<T>, | ||||
|         T: capnp::traits::Pipelined + for<'a> capnp::traits::Owned<'a> + 'static + Unpin, | ||||
|     { | ||||
|         // Send status update to each registered client | ||||
|         let registration_map = self.inner.borrow().registration_map.clone(); | ||||
|         let registration_map1 = registration_map.clone(); | ||||
| @@ -278,17 +299,16 @@ impl ClientApi { | ||||
|         for (&id, mut registration) in regs.iter_mut() { | ||||
|             if registration.requests_in_flight > 5 { | ||||
|                 debug!( | ||||
|                     "too many requests in flight for status updates: {}", | ||||
|                     "too many requests in flight: {}", | ||||
|                     registration.requests_in_flight | ||||
|                 ); | ||||
|             } | ||||
|             registration.requests_in_flight += 1; | ||||
|             // Make a state changed request | ||||
|             let mut request = registration.client.state_changed_request(); | ||||
|             let rpc_changed = request.get().init_changed(); | ||||
|             ClientApi::convert_state_changed(&changed, rpc_changed); | ||||
|  | ||||
|             let request_promise = request(id, registration); | ||||
|  | ||||
|             let registration_map2 = registration_map1.clone(); | ||||
|             async_std::task::spawn_local(request.send().promise.map(move |r| match r { | ||||
|             async_std::task::spawn_local(request_promise.promise.map(move |r| match r { | ||||
|                 Ok(_) => { | ||||
|                     if let Some(ref mut s) = | ||||
|                         registration_map2.borrow_mut().registrations.get_mut(&id) | ||||
| @@ -304,6 +324,23 @@ impl ClientApi { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn handle_state_change(self: Rc<Self>, changed: veilid_core::VeilidStateChange) { | ||||
|         self.send_request_to_all_clients(|_id, registration| { | ||||
|             let mut request = registration.client.state_changed_request(); | ||||
|             let rpc_changed = request.get().init_changed(); | ||||
|             ClientApi::convert_state_changed(&changed, rpc_changed); | ||||
|             request.send() | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     pub fn handle_client_log(self: Rc<Self>, message: String) { | ||||
|         self.send_request_to_all_clients(|_id, registration| { | ||||
|             let mut request = registration.client.log_message_request(); | ||||
|             request.get().set_message(&message); | ||||
|             request.send() | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     pub fn run(self: Rc<Self>, bind_addrs: Vec<SocketAddr>) { | ||||
|         // Create client api VeilidServer | ||||
|         let veilid_server_impl = VeilidServerImpl::new(self.inner.borrow().veilid_api.clone()); | ||||
|   | ||||
							
								
								
									
										48
									
								
								veilid-server/src/client_log_channel.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								veilid-server/src/client_log_channel.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| use async_std::channel::{bounded, Receiver, RecvError, Sender, TrySendError}; | ||||
| use std::sync::Arc; | ||||
|  | ||||
| #[derive(Debug)] | ||||
| struct ClientLogChannelInner { | ||||
|     sender: Sender<String>, | ||||
|     receiver: Receiver<String>, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct ClientLogChannel { | ||||
|     inner: Arc<ClientLogChannelInner>, | ||||
| } | ||||
|  | ||||
| impl ClientLogChannel { | ||||
|     pub fn new() -> Self { | ||||
|         let (sender, receiver) = bounded(1); | ||||
|         Self { | ||||
|             inner: Arc::new(ClientLogChannelInner { sender, receiver }), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub async fn recv(&self) -> Result<String, RecvError> { | ||||
|         self.inner.receiver.recv().await | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl std::io::Write for ClientLogChannel { | ||||
|     fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { | ||||
|         if let Err(e) = self | ||||
|             .inner | ||||
|             .sender | ||||
|             .try_send(String::from_utf8_lossy(buf).to_string()) | ||||
|         { | ||||
|             match e { | ||||
|                 TrySendError::Full(_) => Err(std::io::Error::from(std::io::ErrorKind::WouldBlock)), | ||||
|                 TrySendError::Closed(_) => { | ||||
|                     Err(std::io::Error::from(std::io::ErrorKind::BrokenPipe)) | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             Ok(buf.len()) | ||||
|         } | ||||
|     } | ||||
|     fn flush(&mut self) -> std::io::Result<()> { | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| @@ -3,6 +3,7 @@ | ||||
| #![deny(unused_must_use)] | ||||
|  | ||||
| mod client_api; | ||||
| mod client_log_channel; | ||||
| mod settings; | ||||
|  | ||||
| #[allow(clippy::all)] | ||||
|   | ||||
| @@ -29,6 +29,9 @@ logging: | ||||
|         path: "" | ||||
|         append: true | ||||
|         level: "info" | ||||
|     client: | ||||
|         enable: false | ||||
|         level: "info" | ||||
| testing: | ||||
|     subnode_index: 0 | ||||
| core: | ||||
| @@ -283,6 +286,12 @@ pub struct File { | ||||
|     pub level: LogLevel, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Deserialize)] | ||||
| pub struct Client { | ||||
|     pub enabled: bool, | ||||
|     pub level: LogLevel, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Deserialize)] | ||||
| pub struct ClientApi { | ||||
|     pub enabled: bool, | ||||
| @@ -293,6 +302,7 @@ pub struct ClientApi { | ||||
| pub struct Logging { | ||||
|     pub terminal: Terminal, | ||||
|     pub file: File, | ||||
|     pub client: Client, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Deserialize)] | ||||
| @@ -928,6 +938,8 @@ mod tests { | ||||
|         assert_eq!(s.logging.file.path, ""); | ||||
|         assert_eq!(s.logging.file.append, true); | ||||
|         assert_eq!(s.logging.file.level, LogLevel::Info); | ||||
|         assert_eq!(s.logging.client.enabled, true); | ||||
|         assert_eq!(s.logging.client.level, LogLevel::Info); | ||||
|         assert_eq!(s.testing.subnode_index, 0); | ||||
|         assert_eq!( | ||||
|             s.core.tablestore.directory, | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| #[cfg(unix)] | ||||
| use crate::client_api; | ||||
| use crate::client_log_channel::*; | ||||
| use crate::settings; | ||||
| use async_std::channel::{bounded, Receiver, Sender}; | ||||
| use clap::{App, Arg}; | ||||
| use futures::*; | ||||
| use lazy_static::*; | ||||
| use log::*; | ||||
| use parking_lot::Mutex; | ||||
| @@ -187,7 +189,7 @@ pub async fn main() -> Result<(), String> { | ||||
|  | ||||
|     // Set up loggers | ||||
|     let mut logs: Vec<Box<dyn SharedLogger>> = Vec::new(); | ||||
|  | ||||
|     let mut client_log_channel: Option<ClientLogChannel> = None; | ||||
|     let mut cb = ConfigBuilder::new(); | ||||
|     cb.add_filter_ignore_str("async_std"); | ||||
|     cb.add_filter_ignore_str("async_io"); | ||||
| @@ -228,6 +230,15 @@ pub async fn main() -> Result<(), String> { | ||||
|             logfile, | ||||
|         )) | ||||
|     } | ||||
|     if settingsr.logging.client.enabled { | ||||
|         let clog = ClientLogChannel::new(); | ||||
|         client_log_channel = Some(clog.clone()); | ||||
|         logs.push(WriteLogger::new( | ||||
|             settings::convert_loglevel(settingsr.logging.file.level), | ||||
|             cb.build(), | ||||
|             clog, | ||||
|         )) | ||||
|     } | ||||
|     CombinedLogger::init(logs).map_err(|e| format!("failed to init logs: {}", e))?; | ||||
|  | ||||
|     // Create Veilid Core | ||||
| @@ -280,12 +291,27 @@ pub async fn main() -> Result<(), String> { | ||||
|     let capi_jh = async_std::task::spawn_local(async move { | ||||
|         trace!("state change processing started"); | ||||
|         while let Ok(change) = receiver.recv().await { | ||||
|             if let Some(c) = capi2.borrow_mut().as_mut().cloned() { | ||||
|             if let Some(c) = capi2.borrow().as_ref().cloned() { | ||||
|                 c.handle_state_change(change); | ||||
|             } | ||||
|         } | ||||
|         trace!("state change processing stopped"); | ||||
|     }); | ||||
|     // Handle log messages on main thread for capnproto rpc | ||||
|     let capi2 = capi.clone(); | ||||
|     let capi_jh2 = if let Some(client_log_channel) = client_log_channel { | ||||
|         Some(async_std::task::spawn_local(async move { | ||||
|             trace!("client logging started"); | ||||
|             while let Ok(message) = client_log_channel.recv().await { | ||||
|                 if let Some(c) = capi2.borrow().as_ref().cloned() { | ||||
|                     c.handle_client_log(message); | ||||
|                 } | ||||
|             } | ||||
|             trace!("client logging stopped") | ||||
|         })) | ||||
|     } else { | ||||
|         None | ||||
|     }; | ||||
|  | ||||
|     // Auto-attach if desired | ||||
|     if auto_attach { | ||||
| @@ -313,8 +339,11 @@ pub async fn main() -> Result<(), String> { | ||||
|     // Shut down Veilid API | ||||
|     veilid_api.shutdown().await; | ||||
|  | ||||
|     // Wait for statechanged handler to exit | ||||
|     // Wait for client api handlers to exit | ||||
|     capi_jh.await; | ||||
|     if let Some(capi_jh2) = capi_jh2 { | ||||
|         capi_jh2.await; | ||||
|     } | ||||
|  | ||||
|     Ok(()) | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user