veilid/veilid-cli/src/client_api_connection.rs

499 lines
16 KiB
Rust
Raw Normal View History

2021-11-22 16:28:30 +00:00
use crate::command_processor::*;
2022-06-28 03:46:29 +00:00
use crate::tools::*;
2021-11-22 16:28:30 +00:00
use crate::veilid_client_capnp::*;
use capnp::capability::Promise;
use capnp_rpc::{pry, rpc_twoparty_capnp, twoparty, Disconnector, RpcSystem};
2022-11-03 15:28:29 +00:00
use futures::future::FutureExt;
2022-07-01 16:13:52 +00:00
use serde::de::DeserializeOwned;
2021-11-22 16:28:30 +00:00
use std::cell::RefCell;
use std::net::SocketAddr;
use std::rc::Rc;
2022-12-01 22:38:43 +00:00
use veilid_core::tools::*;
2022-06-08 13:33:41 +00:00
use veilid_core::*;
2021-11-22 16:28:30 +00:00
2022-05-18 14:17:04 +00:00
macro_rules! capnp_failed {
($ex:expr) => {{
let msg = format!("Capnp Error: {}", $ex);
error!("{}", msg);
Promise::err(capnp::Error::failed(msg))
}};
}
2022-06-08 13:33:41 +00:00
macro_rules! pry_result {
($ex:expr) => {
match $ex {
Ok(v) => v,
Err(e) => {
return capnp_failed!(e);
}
}
};
}
2022-07-01 16:13:52 +00:00
fn map_to_internal_error<T: ToString>(e: T) -> VeilidAPIError {
VeilidAPIError::Internal {
message: e.to_string(),
}
}
fn decode_api_result<T: DeserializeOwned + fmt::Debug>(
reader: &api_result::Reader,
) -> Result<T, VeilidAPIError> {
match reader.which().map_err(map_to_internal_error)? {
api_result::Which::Ok(v) => {
let ok_val = v.map_err(map_to_internal_error)?;
let res: T = veilid_core::deserialize_json(ok_val).map_err(map_to_internal_error)?;
Ok(res)
}
api_result::Which::Err(e) => {
let err_val = e.map_err(map_to_internal_error)?;
let res: VeilidAPIError =
veilid_core::deserialize_json(err_val).map_err(map_to_internal_error)?;
Err(res)
}
}
}
2021-11-22 16:28:30 +00:00
struct VeilidClientImpl {
comproc: CommandProcessor,
}
impl VeilidClientImpl {
pub fn new(comproc: CommandProcessor) -> Self {
2021-11-28 02:31:01 +00:00
Self { comproc }
2021-11-22 16:28:30 +00:00
}
}
impl veilid_client::Server for VeilidClientImpl {
fn update(
2021-11-22 16:28:30 +00:00
&mut self,
params: veilid_client::UpdateParams,
_results: veilid_client::UpdateResults,
2021-11-22 16:28:30 +00:00
) -> Promise<(), ::capnp::Error> {
let veilid_update = pry!(pry!(params.get()).get_veilid_update());
2022-06-08 13:33:41 +00:00
let veilid_update: VeilidUpdate = pry_result!(deserialize_json(veilid_update));
2022-06-08 13:33:41 +00:00
match veilid_update {
VeilidUpdate::Log(log) => {
self.comproc.update_log(log);
2022-05-18 14:17:04 +00:00
}
2022-10-01 02:37:55 +00:00
VeilidUpdate::AppMessage(msg) => {
self.comproc.update_app_message(msg);
}
VeilidUpdate::AppCall(call) => {
self.comproc.update_app_call(call);
}
2022-06-08 13:33:41 +00:00
VeilidUpdate::Attachment(attachment) => {
self.comproc.update_attachment(attachment);
2022-05-18 14:17:04 +00:00
}
2022-06-08 13:33:41 +00:00
VeilidUpdate::Network(network) => {
self.comproc.update_network_status(network);
}
2022-11-16 17:49:53 +00:00
VeilidUpdate::Config(config) => {
self.comproc.update_config(config);
}
2022-11-25 01:17:54 +00:00
VeilidUpdate::Route(route) => {
self.comproc.update_route(route);
}
2022-06-08 13:33:41 +00:00
VeilidUpdate::Shutdown => self.comproc.update_shutdown(),
2021-11-22 16:28:30 +00:00
}
Promise::ok(())
}
}
struct ClientApiConnectionInner {
comproc: CommandProcessor,
connect_addr: Option<SocketAddr>,
disconnector: Option<Disconnector<rpc_twoparty_capnp::Side>>,
server: Option<Rc<RefCell<veilid_server::Client>>>,
2022-11-16 17:49:53 +00:00
server_settings: Option<String>,
2021-11-22 16:28:30 +00:00
disconnect_requested: bool,
2022-11-03 15:28:29 +00:00
cancel_eventual: Eventual,
2021-11-22 16:28:30 +00:00
}
type Handle<T> = Rc<RefCell<T>>;
#[derive(Clone)]
pub struct ClientApiConnection {
inner: Handle<ClientApiConnectionInner>,
}
impl ClientApiConnection {
pub fn new(comproc: CommandProcessor) -> Self {
Self {
inner: Rc::new(RefCell::new(ClientApiConnectionInner {
2021-11-28 02:31:01 +00:00
comproc,
2021-11-22 16:28:30 +00:00
connect_addr: None,
disconnector: None,
server: None,
2022-11-16 17:49:53 +00:00
server_settings: None,
2021-11-22 16:28:30 +00:00
disconnect_requested: false,
2022-11-03 15:28:29 +00:00
cancel_eventual: Eventual::new(),
2021-11-22 16:28:30 +00:00
})),
}
}
2022-11-03 15:28:29 +00:00
pub fn cancel(&self) {
let eventual = {
let inner = self.inner.borrow();
inner.cancel_eventual.clone()
};
eventual.resolve(); // don't need to await this
}
2022-01-18 23:28:22 +00:00
async fn process_veilid_state<'a>(
&'a mut self,
2022-06-08 13:33:41 +00:00
veilid_state: VeilidState,
2022-01-18 23:28:22 +00:00
) -> Result<(), String> {
let mut inner = self.inner.borrow_mut();
2022-06-08 13:33:41 +00:00
inner.comproc.update_attachment(veilid_state.attachment);
inner.comproc.update_network_status(veilid_state.network);
2022-11-16 17:49:53 +00:00
inner.comproc.update_config(veilid_state.config);
2022-01-18 23:28:22 +00:00
Ok(())
}
2021-11-22 16:28:30 +00:00
2022-06-08 13:33:41 +00:00
async fn spawn_rpc_system(
&mut self,
connect_addr: SocketAddr,
mut rpc_system: RpcSystem<rpc_twoparty_capnp::Side>,
) -> Result<(), String> {
2021-11-22 16:28:30 +00:00
let mut request;
{
let mut inner = self.inner.borrow_mut();
// Get the bootstrap server connection object
inner.server = Some(Rc::new(RefCell::new(
rpc_system.bootstrap(rpc_twoparty_capnp::Side::Server),
)));
// Store our disconnector future for later (must happen after bootstrap, contrary to documentation)
inner.disconnector = Some(rpc_system.get_disconnector());
// Get a client object to pass to the server for status update callbacks
let client = capnp_rpc::new_client(VeilidClientImpl::new(inner.comproc.clone()));
// Register our client and get a registration object back
request = inner
.server
.as_ref()
.unwrap()
.borrow_mut()
.register_request();
request.get().set_veilid_client(client);
inner
.comproc
.set_connection_state(ConnectionState::Connected(
connect_addr,
std::time::SystemTime::now(),
));
}
2022-06-28 03:46:29 +00:00
let rpc_jh = spawn_local(rpc_system);
2022-06-08 13:33:41 +00:00
// Send the request and get the state object and the registration object
let response = request
.send()
.promise
.await
.map_err(|e| format!("failed to send register request: {}", e))?;
let response = response
.get()
.map_err(|e| format!("failed to get register response: {}", e))?;
// Get the registration object, which drops our connection when it is dropped
let _registration = response
.get_registration()
.map_err(|e| format!("failed to get registration object: {}", e))?;
// Get the initial veilid state
let veilid_state = response
.get_state()
.map_err(|e| format!("failed to get initial veilid state: {}", e))?;
// Set up our state for the first time
let veilid_state: VeilidState = deserialize_json(veilid_state)
.map_err(|e| format!("failed to get deserialize veilid state: {}", e))?;
self.process_veilid_state(veilid_state).await?;
2022-11-16 17:49:53 +00:00
// Save server settings
let server_settings = response
.get_settings()
.map_err(|e| format!("failed to get initial veilid server settings: {}", e))?
.to_owned();
self.inner.borrow_mut().server_settings = Some(server_settings.clone());
2022-06-08 13:33:41 +00:00
// Don't drop the registration, doing so will remove the client
// object mapping from the server which we need for the update backchannel
// Wait until rpc system completion or disconnect was requested
2022-07-12 16:45:54 +00:00
let res = rpc_jh.await;
2022-11-27 02:37:23 +00:00
// #[cfg(feature = "rt-tokio")]
// let res = res.map_err(|e| format!("join error: {}", e))?;
res.map_err(|e| format!("client RPC system error: {}", e))
2022-06-08 13:33:41 +00:00
}
2022-11-16 17:49:53 +00:00
async fn handle_connection(&mut self, connect_addr: SocketAddr) -> Result<(), String> {
2022-06-08 13:33:41 +00:00
trace!("ClientApiConnection::handle_connection");
2022-11-16 17:49:53 +00:00
self.inner.borrow_mut().connect_addr = Some(connect_addr);
2022-06-08 13:33:41 +00:00
// Connect the TCP socket
2022-06-28 03:46:29 +00:00
let stream = TcpStream::connect(connect_addr)
2022-06-08 13:33:41 +00:00
.await
.map_err(map_to_string)?;
// If it succeed, disable nagle algorithm
stream.set_nodelay(true).map_err(map_to_string)?;
// Create the VAT network
2022-06-28 03:46:29 +00:00
cfg_if! {
if #[cfg(feature="rt-async-std")] {
2022-06-29 14:34:23 +00:00
use futures::AsyncReadExt;
2022-06-28 03:46:29 +00:00
let (reader, writer) = stream.split();
} else if #[cfg(feature="rt-tokio")] {
2022-06-29 14:34:23 +00:00
pub use tokio_util::compat::*;
2022-06-28 03:46:29 +00:00
let (reader, writer) = stream.into_split();
let reader = reader.compat();
let writer = writer.compat_write();
}
}
2022-06-08 13:33:41 +00:00
let rpc_network = Box::new(twoparty::VatNetwork::new(
reader,
writer,
rpc_twoparty_capnp::Side::Client,
Default::default(),
));
// Create the rpc system
let rpc_system = RpcSystem::new(rpc_network, None);
2022-01-19 02:21:11 +00:00
// Process the rpc system until we decide we're done
2022-06-08 13:33:41 +00:00
match self.spawn_rpc_system(connect_addr, rpc_system).await {
Ok(()) => {}
Err(e) => {
error!("Failed to spawn client RPC system: {}", e);
2022-01-18 23:28:22 +00:00
}
}
2021-11-22 16:28:30 +00:00
// Drop the server and disconnector too (if we still have it)
let mut inner = self.inner.borrow_mut();
let disconnect_requested = inner.disconnect_requested;
2022-11-16 17:49:53 +00:00
inner.server_settings = None;
2021-11-22 16:28:30 +00:00
inner.server = None;
inner.disconnector = None;
inner.disconnect_requested = false;
2022-11-16 17:49:53 +00:00
inner.connect_addr = None;
2021-11-22 16:28:30 +00:00
if !disconnect_requested {
// Connection lost
Err("Connection lost".to_owned())
2021-11-22 16:28:30 +00:00
} else {
// Connection finished
Ok(())
}
}
2022-11-03 15:28:29 +00:00
pub fn cancellable<T>(&mut self, p: Promise<T, capnp::Error>) -> Promise<T, capnp::Error>
where
T: 'static,
{
let (mut cancel_instance, cancel_eventual) = {
let inner = self.inner.borrow();
(
inner.cancel_eventual.instance_empty().fuse(),
inner.cancel_eventual.clone(),
)
};
let mut p = p.fuse();
Promise::from_future(async move {
let out = select! {
a = p => {
a
},
_ = cancel_instance => {
Err(capnp::Error::failed("cancelled".into()))
}
};
drop(cancel_instance);
cancel_eventual.reset();
out
})
}
pub async fn server_attach(&mut self) -> Result<(), String> {
2021-11-22 16:28:30 +00:00
trace!("ClientApiConnection::server_attach");
let server = {
let inner = self.inner.borrow();
inner
.server
.as_ref()
2022-01-18 23:28:22 +00:00
.ok_or_else(|| "Not connected, ignoring attach request".to_owned())?
2021-11-22 16:28:30 +00:00
.clone()
};
let request = server.borrow().attach_request();
2022-11-03 15:28:29 +00:00
let response = self
.cancellable(request.send().promise)
.await
.map_err(map_to_string)?;
2022-07-01 16:13:52 +00:00
let reader = response
.get()
.map_err(map_to_string)?
.get_result()
.map_err(map_to_string)?;
let res: Result<(), VeilidAPIError> = decode_api_result(&reader);
res.map_err(map_to_string)
2021-11-22 16:28:30 +00:00
}
pub async fn server_detach(&mut self) -> Result<(), String> {
2021-11-22 16:28:30 +00:00
trace!("ClientApiConnection::server_detach");
let server = {
let inner = self.inner.borrow();
inner
.server
.as_ref()
2022-01-18 23:28:22 +00:00
.ok_or_else(|| "Not connected, ignoring detach request".to_owned())?
2021-11-22 16:28:30 +00:00
.clone()
};
let request = server.borrow().detach_request();
2022-11-03 15:28:29 +00:00
let response = self
.cancellable(request.send().promise)
.await
.map_err(map_to_string)?;
2022-07-01 16:13:52 +00:00
let reader = response
.get()
.map_err(map_to_string)?
.get_result()
.map_err(map_to_string)?;
let res: Result<(), VeilidAPIError> = decode_api_result(&reader);
res.map_err(map_to_string)
2021-11-22 16:28:30 +00:00
}
pub async fn server_shutdown(&mut self) -> Result<(), String> {
2021-11-22 16:28:30 +00:00
trace!("ClientApiConnection::server_shutdown");
let server = {
let inner = self.inner.borrow();
inner
.server
.as_ref()
2022-01-18 23:28:22 +00:00
.ok_or_else(|| "Not connected, ignoring attach request".to_owned())?
2021-11-22 16:28:30 +00:00
.clone()
};
let request = server.borrow().shutdown_request();
2022-11-03 15:28:29 +00:00
let response = self
.cancellable(request.send().promise)
.await
.map_err(map_to_string)?;
response.get().map(drop).map_err(map_to_string)
2021-12-11 01:14:33 +00:00
}
pub async fn server_debug(&mut self, what: String) -> Result<String, String> {
2021-12-11 01:14:33 +00:00
trace!("ClientApiConnection::server_debug");
let server = {
let inner = self.inner.borrow();
inner
.server
.as_ref()
2022-07-01 16:13:52 +00:00
.ok_or_else(|| "Not connected, ignoring debug request".to_owned())?
2021-12-11 01:14:33 +00:00
.clone()
};
let mut request = server.borrow().debug_request();
2022-07-01 16:13:52 +00:00
request.get().set_command(&what);
2022-11-03 15:28:29 +00:00
let response = self
.cancellable(request.send().promise)
.await
.map_err(map_to_string)?;
2022-07-01 16:13:52 +00:00
let reader = response
.get()
.map_err(map_to_string)?
2022-07-01 16:13:52 +00:00
.get_result()
.map_err(map_to_string)?;
let res: Result<String, VeilidAPIError> = decode_api_result(&reader);
res.map_err(map_to_string)
}
pub async fn server_change_log_level(
&mut self,
layer: String,
log_level: VeilidConfigLogLevel,
) -> Result<(), String> {
trace!("ClientApiConnection::change_log_level");
let server = {
let inner = self.inner.borrow();
inner
.server
.as_ref()
.ok_or_else(|| "Not connected, ignoring change_log_level request".to_owned())?
.clone()
};
let mut request = server.borrow().change_log_level_request();
request.get().set_layer(&layer);
let log_level_json = veilid_core::serialize_json(&log_level);
request.get().set_log_level(&log_level_json);
2022-11-03 15:28:29 +00:00
let response = self
.cancellable(request.send().promise)
.await
.map_err(map_to_string)?;
2022-07-01 16:13:52 +00:00
let reader = response
.get()
.map_err(map_to_string)?
.get_result()
2022-10-01 02:37:55 +00:00
.map_err(map_to_string)?;
let res: Result<(), VeilidAPIError> = decode_api_result(&reader);
res.map_err(map_to_string)
}
2022-12-17 02:55:03 +00:00
pub async fn server_appcall_reply(
&mut self,
id: OperationId,
msg: Vec<u8>,
) -> Result<(), String> {
2022-10-01 02:37:55 +00:00
trace!("ClientApiConnection::appcall_reply");
let server = {
let inner = self.inner.borrow();
inner
.server
.as_ref()
.ok_or_else(|| "Not connected, ignoring change_log_level request".to_owned())?
.clone()
};
let mut request = server.borrow().app_call_reply_request();
2022-12-17 02:55:03 +00:00
request.get().set_id(id.as_u64());
2022-10-01 02:37:55 +00:00
request.get().set_message(&msg);
2022-11-03 15:28:29 +00:00
let response = self
.cancellable(request.send().promise)
.await
.map_err(map_to_string)?;
2022-10-01 02:37:55 +00:00
let reader = response
.get()
.map_err(map_to_string)?
.get_result()
2022-07-01 16:13:52 +00:00
.map_err(map_to_string)?;
let res: Result<(), VeilidAPIError> = decode_api_result(&reader);
res.map_err(map_to_string)
2021-11-22 16:28:30 +00:00
}
// Start Client API connection
pub async fn connect(&mut self, connect_addr: SocketAddr) -> Result<(), String> {
2021-11-22 16:28:30 +00:00
trace!("ClientApiConnection::connect");
// Save the address to connect to
2022-11-16 17:49:53 +00:00
self.handle_connection(connect_addr).await
2021-11-22 16:28:30 +00:00
}
// End Client API connection
pub async fn disconnect(&mut self) {
trace!("ClientApiConnection::disconnect");
let disconnector = self.inner.borrow_mut().disconnector.take();
match disconnector {
Some(d) => {
self.inner.borrow_mut().disconnect_requested = true;
d.await.unwrap();
}
None => {
debug!("disconnector doesn't exist");
}
}
}
}