diff --git a/bin/dnetview/src/model.rs b/bin/dnetview/src/model.rs index 911ec5c21..d24c3317d 100644 --- a/bin/dnetview/src/model.rs +++ b/bin/dnetview/src/model.rs @@ -29,7 +29,7 @@ type MsgMap = Mutex>; pub enum Session { Inbound, Outbound, - Manual, + //Manual, Offline, } @@ -39,7 +39,7 @@ pub enum SelectableObject { Lilith(LilithInfo), Network(NetworkInfo), Session(SessionInfo), - Connect(SlotInfo), + Slot(SlotInfo), } #[derive(Debug)] @@ -88,6 +88,7 @@ pub struct SessionInfo { pub addr: String, pub state: Option, pub info: SlotInfo, + pub sort: Session, pub is_empty: bool, } @@ -98,9 +99,10 @@ impl SessionInfo { addr: String, state: Option, info: SlotInfo, + sort: Session, is_empty: bool, ) -> Self { - Self { dnet_id, node_id, addr, state, info, is_empty } + Self { dnet_id, node_id, addr, state, info, sort, is_empty } } } diff --git a/bin/dnetview/src/parser.rs b/bin/dnetview/src/parser.rs index d58ab769c..39ce9db4e 100644 --- a/bin/dnetview/src/parser.rs +++ b/bin/dnetview/src/parser.rs @@ -33,7 +33,7 @@ use crate::{ LilithInfo, Model, NetworkInfo, NodeInfo, SelectableObject, Session, SessionInfo, SlotInfo, }, rpc::RpcConnect, - util::{make_empty_id, make_info_id, make_node_id, make_session_id}, + util::{make_empty_id, make_info_id, make_network_id, make_node_id, make_session_id}, }; pub struct DataParser { @@ -93,7 +93,6 @@ impl DataParser { // Parse response match response { Ok(reply) => { - debug!("dnetview:: poll() reply {:?}", reply); if reply.as_object().is_none() || reply.as_object().unwrap().is_empty() { return Err(DnetViewError::EmptyRpcReply) } @@ -121,13 +120,13 @@ impl DataParser { async fn parse_offline(&self, node_name: String) -> DnetViewResult<()> { debug!(target: "dnetview", "parse_offline() START"); let name = "Offline".to_string(); - let session_type = Session::Offline; + let sort = Session::Offline; let mut sessions: Vec = Vec::new(); let hosts = Vec::new(); let node_id = make_node_id(&node_name)?; - let dnet_id = make_empty_id(&node_id, &session_type, 0)?; + let dnet_id = make_empty_id(&node_id, &sort, 0)?; let addr = "Null".to_string(); let state = None; let random_id = 0; @@ -148,10 +147,10 @@ impl DataParser { let session_info = SessionInfo::new( dnet_id, node_id.clone(), - //name.clone(), addr.clone(), state, slot, + sort.clone(), is_empty, ); sessions.push(session_info); @@ -204,7 +203,7 @@ impl DataParser { let mut networks = vec![]; for spawn in spawns { let name = spawn.get("name").unwrap().as_str().unwrap().to_string(); - let id = make_node_id(&name)?; + let id = make_network_id(&name)?; let urls: Vec = serde_json::from_value(spawn.get("urls").unwrap().clone()).unwrap(); let nodes: Vec = @@ -293,7 +292,7 @@ impl DataParser { .lock() .await .insert(inbound.clone().dnet_id, inbound_obj.clone()); - let info_obj = SelectableObject::Connect(inbound.info.clone()); + let info_obj = SelectableObject::Slot(inbound.info.clone()); self.model .selectables .lock() @@ -309,7 +308,7 @@ impl DataParser { .lock() .await .insert(outbound.clone().dnet_id, outbound_obj.clone()); - let info_obj = SelectableObject::Connect(outbound.info.clone()); + let info_obj = SelectableObject::Slot(outbound.info.clone()); self.model .selectables .lock() @@ -325,9 +324,9 @@ impl DataParser { &self, reply: &Value, node_id: &String, - prefix: Session, + sort: Session, ) -> DnetViewResult> { - let session_id = make_session_id(&node_id, &prefix)?; + let session_id = make_session_id(&node_id, &sort)?; let mut session_info: Vec = Vec::new(); // TODO: improve this ugly hack. @@ -335,15 +334,14 @@ impl DataParser { // Dnetview is not enabled. if reply.is_null() { - debug!(target: "dnetview", "parse_outbound() reply.is_null() == True"); slot_count += 1; - let info_id = make_empty_id(&node_id, &prefix, slot_count)?; + let info_id = make_empty_id(&node_id, &sort, slot_count)?; let node_id = node_id.to_string(); let addr = "Null".to_string(); let random_id = 0; let remote_id = "Null".to_string(); let log = Vec::new(); - let is_empty = false; + let is_empty = true; let slot = SlotInfo::new( info_id.clone(), @@ -358,94 +356,106 @@ impl DataParser { let addr = "Null".to_string(); let state = None; - let session = - SessionInfo::new(session_id.clone(), node_id.clone(), addr, state, slot, is_empty); + let session = SessionInfo::new( + session_id.clone(), + node_id.clone(), + addr, + state, + slot, + sort.clone(), + is_empty, + ); session_info.push(session); return Ok(session_info) } let sessions = reply.as_array().unwrap(); - debug!(target: "dnetview", "parse_outbound() len session{:?}", sessions.len()); for session in sessions { - match session.as_object() { - Some(obj) => { - debug!(target: "dnetview", "parse_outbound() obj {:?}", session); - let addr = obj.get("addr").unwrap().as_str().unwrap().to_string(); + // TODO: display empty sessions? + if !session.is_null() { + match session.as_object() { + Some(obj) => { + debug!(target: "dnetview", "parse_outbound() OBJ {:?}", obj); + let addr = obj.get("addr").unwrap().as_str().unwrap().to_string(); - let state: Option = match obj.get("state") { - Some(state) => Some(state.as_str().unwrap().to_string()), - None => None, - }; + let state: Option = match obj.get("state") { + Some(state) => Some(state.as_str().unwrap().to_string()), + None => None, + }; - let info: serde_json::Map = - serde_json::from_value(obj.get("info").unwrap().clone()).unwrap(); + let info: serde_json::Map = + serde_json::from_value(obj.get("info").unwrap().clone()).unwrap(); - let slot_addr = info.get("addr").unwrap().as_str().unwrap().to_string(); - let random_id = info.get("random_id").unwrap().as_u64().unwrap(); - let remote_id = info.get("remote_id").unwrap().as_str().unwrap().to_string(); - let info_id = make_info_id(&random_id)?; + let slot_addr = info.get("addr").unwrap().as_str().unwrap().to_string(); + let random_id = info.get("random_id").unwrap().as_u64().unwrap(); + let remote_id = + info.get("remote_id").unwrap().as_str().unwrap().to_string(); + let info_id = make_info_id(&random_id)?; - let log: Vec<(NanoTimestamp, String, String)> = - serde_json::from_value(info.get("log").unwrap().clone()).unwrap(); + let log: Vec<(NanoTimestamp, String, String)> = + serde_json::from_value(info.get("log").unwrap().clone()).unwrap(); - // ... - let node_id = node_id.to_string(); - let is_empty = false; + // ... + let node_id = node_id.to_string(); + let is_empty = false; - let slot = SlotInfo::new( - info_id.clone(), - node_id.clone(), - slot_addr, - random_id, - remote_id, - log, - is_empty, - ); + let slot = SlotInfo::new( + info_id.clone(), + node_id.clone(), + slot_addr, + random_id, + remote_id, + log, + is_empty, + ); - let session = SessionInfo::new( - session_id.clone(), - node_id.clone(), - addr.clone(), - state, - slot, - is_empty, - ); - session_info.push(session); - } - None => { - // TODO: clean up empty info boilerplate. - slot_count += 1; - let info_id = make_empty_id(node_id, &prefix, slot_count)?; - let node_id = node_id.to_string(); - let addr = "Null".to_string(); - let random_id = 0; - let remote_id = "Null".to_string(); - let log = Vec::new(); - let is_empty = true; + let session = SessionInfo::new( + session_id.clone(), + node_id.clone(), + addr.clone(), + state, + slot.clone(), + sort.clone(), + is_empty, + ); + session_info.push(session); + } + None => { + // TODO: clean up empty info boilerplate. + slot_count += 1; + let info_id = make_empty_id(node_id, &sort, slot_count)?; + let node_id = node_id.to_string(); + let addr = "Null".to_string(); + let random_id = 0; + let remote_id = "Null".to_string(); + let log = Vec::new(); + let is_empty = true; - let slot = SlotInfo::new( - info_id.clone(), - node_id.clone(), - addr.clone(), - random_id, - remote_id, - log, - is_empty, - ); - let is_empty = true; + let slot = SlotInfo::new( + info_id.clone(), + node_id.clone(), + addr.clone(), + random_id, + remote_id, + log, + is_empty, + ); + let is_empty = true; - let state = None; - let session = SessionInfo::new( - session_id.clone(), - node_id.clone(), - addr.clone(), - state, - slot, - is_empty, - ); - session_info.push(session); + let state = None; + let session = SessionInfo::new( + session_id.clone(), + node_id.clone(), + addr.clone(), + state, + slot.clone(), + sort.clone(), + is_empty, + ); + session_info.push(session); + } } } } @@ -470,7 +480,6 @@ impl DataParser { let h = Vec::new(); return Ok(h) } - debug!("dnetview::parse_hosts() hosts returns None and !is_null() {}", hosts); Err(DnetViewError::ValueIsNotObject) } } diff --git a/bin/dnetview/src/util.rs b/bin/dnetview/src/util.rs index fb414eed7..666ee7f02 100644 --- a/bin/dnetview/src/util.rs +++ b/bin/dnetview/src/util.rs @@ -26,13 +26,19 @@ pub fn make_node_id(node_name: &String) -> Result { Ok(id) } +pub fn make_network_id(node_name: &String) -> Result { + let mut id = hex::encode(node_name); + id.insert_str(0, "NETWORK"); + Ok(id) +} + pub fn make_session_id(node_id: &str, session: &Session) -> Result { let mut num = 0_u64; let session_chars = match session { Session::Inbound => vec!['i', 'n'], Session::Outbound => vec!['o', 'u', 't'], - Session::Manual => vec!['m', 'a', 'n'], + //Session::Manual => vec!['m', 'a', 'n'], Session::Offline => vec!['o', 'f', 'f'], }; @@ -87,19 +93,19 @@ pub fn make_empty_id(node_id: &str, session: &Session, count: u64) -> Result { - let session_chars = vec!['m', 'a', 'n']; - for i in session_chars { - num += i as u64 - } - for i in node_id.chars() { - num += i as u64 - } - num += count; - let mut id = hex::encode(num.to_ne_bytes()); - id.insert_str(0, "EMPTYMAN"); - id - } + //Session::Manual => { + // let session_chars = vec!['m', 'a', 'n']; + // for i in session_chars { + // num += i as u64 + // } + // for i in node_id.chars() { + // num += i as u64 + // } + // num += count; + // let mut id = hex::encode(num.to_ne_bytes()); + // id.insert_str(0, "EMPTYMAN"); + // id + //} Session::Offline => { let session_chars = vec!['o', 'f', 'f']; for i in session_chars { diff --git a/bin/dnetview/src/view.rs b/bin/dnetview/src/view.rs index e2c0f842d..bb61896a4 100644 --- a/bin/dnetview/src/view.rs +++ b/bin/dnetview/src/view.rs @@ -16,8 +16,8 @@ * along with this program. If not, see . */ +use log::debug; use std::collections::HashMap; -//use log::debug; use tui::{ backend::Backend, @@ -85,6 +85,9 @@ impl<'a> View { } } + // The order of the ordered_list created here must match the order + // of the Vec created in render_left(). + // This is used to render_right() correctly. fn make_ordered_list(&mut self) { for obj in self.selectables.values() { match obj { @@ -98,11 +101,9 @@ impl<'a> View { if !self.ordered_list.iter().any(|i| i == &inbound.dnet_id) { self.ordered_list.push(inbound.dnet_id.clone()); } - //for info in &inbound.info { if !self.ordered_list.iter().any(|i| i == &inbound.info.dnet_id) { self.ordered_list.push(inbound.info.dnet_id.clone()); } - //} } } for outbound in &node.outbound { @@ -110,11 +111,9 @@ impl<'a> View { if !self.ordered_list.iter().any(|i| i == &outbound.dnet_id) { self.ordered_list.push(outbound.dnet_id.clone()); } - //for info in &outbound.info { if !self.ordered_list.iter().any(|i| i == &outbound.info.dnet_id) { self.ordered_list.push(outbound.info.dnet_id.clone()); } - //} } } } @@ -132,12 +131,10 @@ impl<'a> View { _ => (), } } - //debug!(target: "dnetview", "render_ids()::ordered_list: {:?}", self.ordered_list); } - // TODO: this function is dynamically resizing the msgs index - // according to what set of msgs is selected. - // it's ugly. would prefer something more simple + // TODO: this function displays msgs according to what id is + // selected. It's ugly, would prefer something more simple. fn update_msg_index(&mut self) { if let Some(sel) = self.id_menu.state.selected() { if let Some(ord) = self.ordered_list.get(sel) { @@ -165,31 +162,28 @@ impl<'a> View { .constraints(cnstrnts) .split(f.size()); - self.render_ids(f, slice.clone())?; + self.render_left(f, slice.clone())?; if self.ordered_list.is_empty() { // we have not received any data Ok(()) } else { // get the id at the current index match self.id_menu.state.selected() { - Some(i) => { - //debug!(target: "dnetview", "render()::selected index: {}", i); - match self.ordered_list.get(i) { - Some(i) => { - let id = i.clone(); - self.render_info(f, slice, id)?; - Ok(()) - } - None => Err(DnetViewError::NoIdAtIndex), + Some(i) => match self.ordered_list.get(i) { + Some(i) => { + let id = i.clone(); + self.render_right(f, slice, id)?; + Ok(()) } - } + None => Err(DnetViewError::NoIdAtIndex), + }, // nothing is selected right now None => Ok(()), } } } - fn render_ids( + fn render_left( &mut self, f: &mut Frame<'_, B>, slice: Vec, @@ -215,13 +209,13 @@ impl<'a> View { let names = ListItem::new(lines); nodes.push(names); - for inbound in &node.inbound { - if !inbound.is_empty { - let name = Span::styled(format!(" Inbound"), style); - let lines = vec![Spans::from(name)]; - let names = ListItem::new(lines); - nodes.push(names); - //for info in &inbound.info { + if !node.inbound.is_empty() { + let name = Span::styled(format!(" Inbound"), style); + let lines = vec![Spans::from(name)]; + let names = ListItem::new(lines); + nodes.push(names); + + for inbound in &node.inbound { let mut infos = Vec::new(); match inbound.info.addr.as_str() { "Null" => { @@ -246,21 +240,19 @@ impl<'a> View { } } } - let lines = vec![Spans::from(infos)]; let names = ListItem::new(lines); nodes.push(names); - //} } } - for outbound in &node.outbound { - if !outbound.is_empty { - let name = Span::styled(format!(" Outbound"), style); - let lines = vec![Spans::from(name)]; - let names = ListItem::new(lines); - nodes.push(names); - //for info in &outbound.info { + if !&node.outbound.is_empty() { + let name = Span::styled(format!(" Outbound"), style); + let lines = vec![Spans::from(name)]; + let names = ListItem::new(lines); + nodes.push(names); + + for outbound in &node.outbound { let mut infos = Vec::new(); match outbound.info.addr.as_str() { "Null" => { @@ -285,11 +277,9 @@ impl<'a> View { } } } - let lines = vec![Spans::from(infos)]; let names = ListItem::new(lines); nodes.push(names); - //} } } } @@ -349,12 +339,13 @@ impl<'a> View { Ok(msg_list) } - fn render_info( + fn render_right( &mut self, f: &mut Frame<'_, B>, slice: Vec, selected: String, ) -> DnetViewResult<()> { + debug!(target: "dnetview", "render_right() selected ID: {}", selected.clone()); let style = Style::default(); let mut lines = Vec::new(); @@ -363,11 +354,9 @@ impl<'a> View { return Ok(()) } else { let info = self.selectables.get(&selected); - //debug!(target: "dnetview", "render_info()::selected {}", selected); match info { Some(SelectableObject::Node(node)) => { - //debug!(target: "dnetview", "render_info()::SelectableObject::Node"); lines.push(Spans::from(Span::styled("Type: Normal", style))); lines.push(Spans::from(Span::styled("Hosts:", style))); for host in &node.hosts { @@ -375,7 +364,6 @@ impl<'a> View { } } Some(SelectableObject::Session(session)) => { - //debug!(target: "dnetview", "render_info()::SelectableObject::Session"); let addr = Span::styled(format!("Addr: {}", session.addr), style); lines.push(Spans::from(addr)); @@ -387,16 +375,8 @@ impl<'a> View { lines.push(Spans::from(addr)); } } - Some(SelectableObject::Connect(connect)) => { - // TODO: this renders in the top right and overwrites the msg log - //let addr = Span::styled(format!("Addr: {}", connect.addr), style); - //let random_id = Span::styled(format!("Random id: {}", connect.random_id), style); - //let remote_id = Span::styled(format!("Remote id: {}", connect.remote_id), style); - //lines.push(Spans::from(addr)); - //lines.push(Spans::from(random_id)); - //lines.push(Spans::from(remote_id)); - //debug!(target: "dnetview", "render_info()::SelectableObject::Connect"); - let text = self.parse_msg_list(connect.dnet_id.clone())?; + Some(SelectableObject::Slot(slot)) => { + let text = self.parse_msg_list(slot.dnet_id.clone())?; f.render_stateful_widget(text, slice[1], &mut self.msg_list.state); } Some(SelectableObject::Lilith(_lilith)) => {