json api cli working
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
use crate::command_processor::*;
|
||||
use crate::tools::*;
|
||||
use core::str::FromStr;
|
||||
use futures::stream::FuturesUnordered;
|
||||
use futures::StreamExt;
|
||||
use std::net::SocketAddr;
|
||||
@@ -23,7 +22,6 @@ struct ClientApiConnectionInner {
|
||||
comproc: CommandProcessor,
|
||||
connect_addr: Option<SocketAddr>,
|
||||
request_sender: Option<flume::Sender<String>>,
|
||||
server_settings: Option<String>,
|
||||
disconnector: Option<StopSource>,
|
||||
disconnect_requested: bool,
|
||||
reply_channels: HashMap<u32, flume::Sender<json::JsonValue>>,
|
||||
@@ -42,7 +40,6 @@ impl ClientApiConnection {
|
||||
comproc,
|
||||
connect_addr: None,
|
||||
request_sender: None,
|
||||
server_settings: None,
|
||||
disconnector: None,
|
||||
disconnect_requested: false,
|
||||
reply_channels: HashMap::new(),
|
||||
@@ -56,28 +53,19 @@ impl ClientApiConnection {
|
||||
inner.reply_channels.clear();
|
||||
}
|
||||
|
||||
// async fn process_veilid_state<'a>(
|
||||
// &'a mut self,
|
||||
// veilid_state: VeilidState,
|
||||
// ) -> Result<(), String> {
|
||||
// let mut inner = self.inner.borrow_mut();
|
||||
// inner.comproc.update_attachment(veilid_state.attachment);
|
||||
// inner.comproc.update_network_status(veilid_state.network);
|
||||
// inner.comproc.update_config(veilid_state.config);
|
||||
// Ok(())
|
||||
// }
|
||||
async fn process_veilid_state<'a>(&self, state: &json::JsonValue) {
|
||||
let comproc = self.inner.lock().comproc.clone();
|
||||
comproc.update_attachment(&state["attachment"]);
|
||||
comproc.update_network_status(&state["network"]);
|
||||
comproc.update_config(&state["config"]);
|
||||
}
|
||||
|
||||
async fn process_response(&self, response: json::JsonValue) {
|
||||
// find the operation id and send the response to the channel for it
|
||||
let Some(id_str) = response["id"].as_str() else {
|
||||
error!("missing id: {}", response);
|
||||
return;
|
||||
};
|
||||
let Ok(id) = u32::from_str(id_str) else {
|
||||
let Some(id) = response["id"].as_u32() else {
|
||||
error!("invalid id: {}", response);
|
||||
return;
|
||||
};
|
||||
|
||||
let reply_channel = {
|
||||
let mut inner = self.inner.lock();
|
||||
inner.reply_channels.remove(&id)
|
||||
@@ -92,7 +80,7 @@ impl ClientApiConnection {
|
||||
}
|
||||
}
|
||||
|
||||
async fn process_update(&self, update: json::JsonValue) {
|
||||
async fn process_veilid_update(&self, update: json::JsonValue) {
|
||||
let comproc = self.inner.lock().comproc.clone();
|
||||
let Some(kind) = update["kind"].as_str() else {
|
||||
comproc.log_message(format!("missing update kind: {}", update));
|
||||
@@ -100,29 +88,29 @@ impl ClientApiConnection {
|
||||
};
|
||||
match kind {
|
||||
"Log" => {
|
||||
comproc.update_log(update);
|
||||
comproc.update_log(&update);
|
||||
}
|
||||
"AppMessage" => {
|
||||
comproc.update_app_message(update);
|
||||
comproc.update_app_message(&update);
|
||||
}
|
||||
"AppCall" => {
|
||||
comproc.update_app_call(update);
|
||||
comproc.update_app_call(&update);
|
||||
}
|
||||
"Attachment" => {
|
||||
comproc.update_attachment(update);
|
||||
comproc.update_attachment(&update);
|
||||
}
|
||||
"Network" => {
|
||||
comproc.update_network_status(update);
|
||||
comproc.update_network_status(&update);
|
||||
}
|
||||
"Config" => {
|
||||
comproc.update_config(update);
|
||||
comproc.update_config(&update);
|
||||
}
|
||||
"RouteChange" => {
|
||||
comproc.update_route(update);
|
||||
comproc.update_route(&update);
|
||||
}
|
||||
"Shutdown" => comproc.update_shutdown(),
|
||||
"ValueChange" => {
|
||||
comproc.update_value_change(update);
|
||||
comproc.update_value_change(&update);
|
||||
}
|
||||
_ => {
|
||||
comproc.log_message(format!("unknown update kind: {}", update));
|
||||
@@ -130,97 +118,6 @@ impl ClientApiConnection {
|
||||
}
|
||||
}
|
||||
|
||||
// async fn spawn_rpc_system(
|
||||
// &self,
|
||||
// connect_addr: SocketAddr,
|
||||
// mut rpc_system: RpcSystem<rpc_twoparty_capnp::Side>,
|
||||
// ) -> Result<(), String> {
|
||||
// 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(),
|
||||
// ));
|
||||
// }
|
||||
|
||||
// let rpc_jh = spawn_local(rpc_system);
|
||||
|
||||
// let reg_res: Result<registration::Client, String> = (async {
|
||||
// // 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?;
|
||||
|
||||
// // 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());
|
||||
|
||||
// // Don't drop the registration, doing so will remove the client
|
||||
// // object mapping from the server which we need for the update backchannel
|
||||
// Ok(registration)
|
||||
// })
|
||||
// .await;
|
||||
|
||||
// let _registration = match reg_res {
|
||||
// Ok(v) => v,
|
||||
// Err(e) => {
|
||||
// rpc_jh.abort().await;
|
||||
// return Err(e);
|
||||
// }
|
||||
// };
|
||||
|
||||
// // Wait until rpc system completion or disconnect was requested
|
||||
// let res = rpc_jh.await;
|
||||
// res.map_err(|e| format!("client RPC system error: {}", e))
|
||||
// }
|
||||
|
||||
async fn handle_connection(&self, connect_addr: SocketAddr) -> Result<(), String> {
|
||||
trace!("ClientApiConnection::handle_connection");
|
||||
|
||||
@@ -251,6 +148,7 @@ impl ClientApiConnection {
|
||||
// Requests to send
|
||||
let (requests_tx, requests_rx) = flume::unbounded();
|
||||
|
||||
// Create disconnection mechanism
|
||||
let stop_token = {
|
||||
let stop_source = StopSource::new();
|
||||
let token = stop_source.token();
|
||||
@@ -267,16 +165,19 @@ impl ClientApiConnection {
|
||||
// Process lines
|
||||
let this = self.clone();
|
||||
let recv_messages_future = async move {
|
||||
let mut line = String::new();
|
||||
while let Ok(size) = reader.read_line(&mut line).await {
|
||||
let mut linebuf = String::new();
|
||||
while let Ok(size) = reader.read_line(&mut linebuf).await {
|
||||
// Exit on EOF
|
||||
if size == 0 {
|
||||
// Disconnected
|
||||
break;
|
||||
}
|
||||
|
||||
let line = linebuf.trim().to_owned();
|
||||
linebuf.clear();
|
||||
|
||||
// Unmarshal json
|
||||
let j = match json::parse(line.trim()) {
|
||||
let j = match json::parse(&line) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
error!("failed to parse server response: {}", e);
|
||||
@@ -285,7 +186,7 @@ impl ClientApiConnection {
|
||||
};
|
||||
|
||||
if j["type"] == "Update" {
|
||||
this.process_update(j).await;
|
||||
this.process_veilid_update(j).await;
|
||||
} else if j["type"] == "Response" {
|
||||
this.process_response(j).await;
|
||||
}
|
||||
@@ -306,13 +207,28 @@ impl ClientApiConnection {
|
||||
};
|
||||
unord.push(system_boxed(send_requests_future));
|
||||
|
||||
// Request initial server state
|
||||
let capi = self.clone();
|
||||
spawn_detached_local(async move {
|
||||
let mut req = json::JsonValue::new_object();
|
||||
req["op"] = "GetState".into();
|
||||
let Some(resp) = capi.perform_request(req).await else {
|
||||
error!("failed to get state");
|
||||
return;
|
||||
};
|
||||
if resp.has_key("error") {
|
||||
error!("failed to get state: {}", resp["error"]);
|
||||
return;
|
||||
}
|
||||
capi.process_veilid_state(&resp["value"]).await;
|
||||
});
|
||||
|
||||
// Send and receive until we're done or a stop is requested
|
||||
while let Ok(Some(())) = unord.next().timeout_at(stop_token.clone()).await {}
|
||||
|
||||
// // Drop the server and disconnector too (if we still have it)
|
||||
let mut inner = self.inner.lock();
|
||||
let disconnect_requested = inner.disconnect_requested;
|
||||
inner.server_settings = None;
|
||||
inner.request_sender = None;
|
||||
inner.disconnector = None;
|
||||
inner.disconnect_requested = false;
|
||||
|
@@ -387,7 +387,7 @@ reply - reply to an AppCall not handled directly by the server
|
||||
self.inner().ui_sender.add_node_event(message);
|
||||
}
|
||||
|
||||
pub fn update_attachment(&self, attachment: json::JsonValue) {
|
||||
pub fn update_attachment(&self, attachment: &json::JsonValue) {
|
||||
self.inner_mut().ui_sender.set_attachment_state(
|
||||
attachment["state"].as_str().unwrap_or_default().to_owned(),
|
||||
attachment["public_internet_ready"]
|
||||
@@ -399,7 +399,7 @@ reply - reply to an AppCall not handled directly by the server
|
||||
);
|
||||
}
|
||||
|
||||
pub fn update_network_status(&self, network: json::JsonValue) {
|
||||
pub fn update_network_status(&self, network: &json::JsonValue) {
|
||||
self.inner_mut().ui_sender.set_network_status(
|
||||
network["started"].as_bool().unwrap_or_default(),
|
||||
json_str_u64(&network["bps_down"]),
|
||||
@@ -410,10 +410,10 @@ reply - reply to an AppCall not handled directly by the server
|
||||
.collect::<Vec<json::JsonValue>>(),
|
||||
);
|
||||
}
|
||||
pub fn update_config(&self, config: json::JsonValue) {
|
||||
pub fn update_config(&self, config: &json::JsonValue) {
|
||||
self.inner_mut().ui_sender.set_config(&config["config"])
|
||||
}
|
||||
pub fn update_route(&self, route: json::JsonValue) {
|
||||
pub fn update_route(&self, route: &json::JsonValue) {
|
||||
let mut out = String::new();
|
||||
if route["dead_routes"].len() != 0 {
|
||||
out.push_str(&format!("Dead routes: {:?}", route["dead_routes"]));
|
||||
@@ -431,12 +431,12 @@ reply - reply to an AppCall not handled directly by the server
|
||||
self.inner().ui_sender.add_node_event(out);
|
||||
}
|
||||
}
|
||||
pub fn update_value_change(&self, value_change: json::JsonValue) {
|
||||
pub fn update_value_change(&self, value_change: &json::JsonValue) {
|
||||
let out = format!("Value change: {:?}", value_change.as_str().unwrap_or("???"));
|
||||
self.inner().ui_sender.add_node_event(out);
|
||||
}
|
||||
|
||||
pub fn update_log(&self, log: json::JsonValue) {
|
||||
pub fn update_log(&self, log: &json::JsonValue) {
|
||||
self.inner().ui_sender.add_node_event(format!(
|
||||
"{}: {}{}",
|
||||
log["log_level"].as_str().unwrap_or("???"),
|
||||
@@ -449,7 +449,7 @@ reply - reply to an AppCall not handled directly by the server
|
||||
));
|
||||
}
|
||||
|
||||
pub fn update_app_message(&self, msg: json::JsonValue) {
|
||||
pub fn update_app_message(&self, msg: &json::JsonValue) {
|
||||
let message = json_str_vec_u8(&msg["message"]);
|
||||
|
||||
// check is message body is ascii printable
|
||||
@@ -471,7 +471,7 @@ reply - reply to an AppCall not handled directly by the server
|
||||
.add_node_event(format!("AppMessage ({:?}): {}", msg["sender"], strmsg));
|
||||
}
|
||||
|
||||
pub fn update_app_call(&self, call: json::JsonValue) {
|
||||
pub fn update_app_call(&self, call: &json::JsonValue) {
|
||||
let message = json_str_vec_u8(&call["message"]);
|
||||
|
||||
// check is message body is ascii printable
|
||||
|
Reference in New Issue
Block a user