parser.rs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::collections::hash_map::Entry;
  19. use async_std::sync::Arc;
  20. use log::{debug, error, info};
  21. use serde_json::Value;
  22. use smol::Executor;
  23. use url::Url;
  24. use darkfi::util::{async_util, time::NanoTimestamp};
  25. use crate::{
  26. config::{DnvConfig, Node, NodeType},
  27. error::{DnetViewError, DnetViewResult},
  28. model::{
  29. LilithInfo, Model, NetworkInfo, NodeInfo, SelectableObject, Session, SessionInfo, SlotInfo,
  30. },
  31. rpc::RpcConnect,
  32. util::{
  33. make_empty_id, make_info_id, make_network_id, make_node_id, make_null_id, make_session_id,
  34. },
  35. };
  36. pub struct DataParser {
  37. model: Arc<Model>,
  38. config: DnvConfig,
  39. }
  40. impl DataParser {
  41. pub fn new(model: Arc<Model>, config: DnvConfig) -> Arc<Self> {
  42. Arc::new(Self { model, config })
  43. }
  44. pub async fn start_connect_slots(self: Arc<Self>, ex: Arc<Executor<'_>>) -> DnetViewResult<()> {
  45. debug!(target: "dnetview", "start_connect_slots() START");
  46. for node in &self.config.nodes {
  47. debug!(target: "dnetview", "attempting to spawn...");
  48. ex.clone().spawn(self.clone().try_connect(node.clone())).detach();
  49. }
  50. Ok(())
  51. }
  52. async fn try_connect(self: Arc<Self>, node: Node) -> DnetViewResult<()> {
  53. debug!(target: "dnetview", "try_connect() START");
  54. loop {
  55. info!("Attempting to poll {}, RPC URL: {}", node.name, node.rpc_url);
  56. // Parse node config and execute poll.
  57. // On any failure, sleep and retry.
  58. match RpcConnect::new(Url::parse(&node.rpc_url)?, node.name.clone()).await {
  59. Ok(client) => {
  60. // We start by enabling dnet
  61. if let Err(e) = client.dnet_enable(true).await {
  62. error!("dnet_enable error: {:?}", e);
  63. }
  64. if let Err(e) = self.poll(&node, client).await {
  65. error!("Poll execution error: {:?}", e);
  66. }
  67. }
  68. Err(e) => {
  69. error!("RPC client creation error: {:?}", e);
  70. }
  71. }
  72. self.parse_offline(node.name.clone()).await?;
  73. async_util::sleep(2).await;
  74. }
  75. }
  76. async fn poll(&self, node: &Node, client: RpcConnect) -> DnetViewResult<()> {
  77. loop {
  78. // Ping the node to verify if its online.
  79. if let Err(e) = client.ping().await {
  80. return Err(DnetViewError::Darkfi(e))
  81. }
  82. // Retrieve node info, based on its type
  83. let response = match &node.node_type {
  84. NodeType::LILITH => client.lilith_spawns().await,
  85. NodeType::NORMAL => client.dnet_info().await,
  86. NodeType::CONSENSUS => client.get_consensus_info().await,
  87. };
  88. // Parse response
  89. match response {
  90. Ok(reply) => {
  91. if reply.as_object().is_none() || reply.as_object().unwrap().is_empty() {
  92. return Err(DnetViewError::EmptyRpcReply)
  93. }
  94. match &node.node_type {
  95. NodeType::LILITH => {
  96. self.parse_lilith_data(
  97. reply.as_object().unwrap().clone(),
  98. node.name.clone(),
  99. )
  100. .await?
  101. }
  102. _ => self.parse_data(reply.as_object().unwrap(), node.name.clone()).await?,
  103. };
  104. }
  105. Err(e) => return Err(e),
  106. }
  107. // Sleep until next poll
  108. async_util::sleep(2).await;
  109. }
  110. }
  111. // If poll times out, inititalize data structures with empty values.
  112. async fn parse_offline(&self, node_name: String) -> DnetViewResult<()> {
  113. debug!(target: "dnetview", "parse_offline() START");
  114. let sort = Session::Offline;
  115. let mut sessions: Vec<SessionInfo> = Vec::new();
  116. let hosts = Vec::new();
  117. let node_id = make_node_id(&node_name)?;
  118. let dnet_id = make_empty_id(&node_id, &sort, 0)?;
  119. let addr = "Null".to_string();
  120. let state = None;
  121. let random_id = 0;
  122. let remote_id = "Null".to_string();
  123. let log = Vec::new();
  124. let is_empty = true;
  125. let slot = SlotInfo::new(
  126. dnet_id.clone(),
  127. node_id.clone(),
  128. addr.clone(),
  129. random_id,
  130. remote_id,
  131. log,
  132. is_empty,
  133. );
  134. let session_info = SessionInfo::new(
  135. dnet_id,
  136. node_id.clone(),
  137. addr.clone(),
  138. state,
  139. slot,
  140. sort.clone(),
  141. is_empty,
  142. );
  143. sessions.push(session_info);
  144. // TODO: clean this up
  145. let node = NodeInfo::new(
  146. node_id.clone(),
  147. node_name.clone(),
  148. hosts,
  149. sessions.clone(),
  150. sessions.clone(),
  151. is_empty,
  152. true,
  153. );
  154. self.update_selectables(node).await?;
  155. Ok(())
  156. }
  157. async fn parse_data(
  158. &self,
  159. reply: &serde_json::Map<String, Value>,
  160. name: String,
  161. ) -> DnetViewResult<()> {
  162. let hosts = &reply["hosts"];
  163. let inbound = &reply["inbound"];
  164. let outbound = &reply["outbound"];
  165. let node_id = make_node_id(&name)?;
  166. let dnet_enabled: bool = {
  167. if hosts.is_null() && inbound.is_null() && outbound.is_null() {
  168. false
  169. } else {
  170. true
  171. }
  172. };
  173. let hosts = self.parse_hosts(hosts).await?;
  174. let inbound = self.parse_session(inbound, &node_id, Session::Inbound).await?;
  175. let outbound = self.parse_session(outbound, &node_id, Session::Outbound).await?;
  176. let node = NodeInfo::new(
  177. node_id,
  178. name,
  179. hosts,
  180. inbound.clone(),
  181. outbound.clone(),
  182. false,
  183. dnet_enabled,
  184. );
  185. self.update_selectables(node).await?;
  186. self.update_msgs(inbound.clone(), outbound.clone()).await?;
  187. Ok(())
  188. }
  189. async fn parse_lilith_data(
  190. &self,
  191. reply: serde_json::Map<String, Value>,
  192. name: String,
  193. ) -> DnetViewResult<()> {
  194. let spawns: Vec<serde_json::Map<String, Value>> =
  195. serde_json::from_value(reply.get("spawns").unwrap().clone()).unwrap();
  196. let mut networks = vec![];
  197. for spawn in spawns {
  198. let name = spawn.get("name").unwrap().as_str().unwrap().to_string();
  199. let id = make_network_id(&name)?;
  200. let urls: Vec<String> =
  201. serde_json::from_value(spawn.get("urls").unwrap().clone()).unwrap();
  202. let nodes: Vec<String> =
  203. serde_json::from_value(spawn.get("hosts").unwrap().clone()).unwrap();
  204. let network = NetworkInfo::new(id, name, urls, nodes);
  205. networks.push(network);
  206. }
  207. let id = make_node_id(&name)?;
  208. let lilith = LilithInfo::new(id.clone(), name, networks);
  209. let lilith_obj = SelectableObject::Lilith(lilith.clone());
  210. self.model.selectables.lock().await.insert(id, lilith_obj);
  211. for network in lilith.networks {
  212. let network_obj = SelectableObject::Network(network.clone());
  213. self.model.selectables.lock().await.insert(network.id, network_obj);
  214. }
  215. Ok(())
  216. }
  217. async fn update_msgs(
  218. &self,
  219. inbounds: Vec<SessionInfo>,
  220. outbounds: Vec<SessionInfo>,
  221. ) -> DnetViewResult<()> {
  222. for inbound in inbounds {
  223. if !self.model.msg_map.lock().await.contains_key(&inbound.info.dnet_id) {
  224. // we don't have this ID: it is a new node
  225. self.model
  226. .msg_map
  227. .lock()
  228. .await
  229. .insert(inbound.info.dnet_id, inbound.info.log.clone());
  230. } else {
  231. // we have this id: append the msg values
  232. match self.model.msg_map.lock().await.entry(inbound.info.dnet_id) {
  233. Entry::Vacant(e) => {
  234. e.insert(inbound.info.log);
  235. }
  236. Entry::Occupied(mut e) => {
  237. for msg in inbound.info.log {
  238. e.get_mut().push(msg);
  239. }
  240. }
  241. }
  242. }
  243. }
  244. for outbound in outbounds {
  245. if !self.model.msg_map.lock().await.contains_key(&outbound.info.dnet_id) {
  246. // we don't have this ID: it is a new node
  247. self.model
  248. .msg_map
  249. .lock()
  250. .await
  251. .insert(outbound.info.dnet_id, outbound.info.log.clone());
  252. } else {
  253. // we have this id: append the msg values
  254. match self.model.msg_map.lock().await.entry(outbound.info.dnet_id) {
  255. Entry::Vacant(e) => {
  256. e.insert(outbound.info.log);
  257. }
  258. Entry::Occupied(mut e) => {
  259. for msg in outbound.info.log {
  260. e.get_mut().push(msg);
  261. }
  262. }
  263. }
  264. }
  265. }
  266. Ok(())
  267. }
  268. async fn update_selectables(&self, node: NodeInfo) -> DnetViewResult<()> {
  269. if node.is_offline && !node.dnet_enabled {
  270. let node_obj = SelectableObject::Node(node.clone());
  271. self.model.selectables.lock().await.insert(node.dnet_id.clone(), node_obj.clone());
  272. } else {
  273. let node_obj = SelectableObject::Node(node.clone());
  274. self.model.selectables.lock().await.insert(node.dnet_id.clone(), node_obj.clone());
  275. for inbound in node.inbound {
  276. if !inbound.is_empty {
  277. let inbound_obj = SelectableObject::Session(inbound.clone());
  278. self.model
  279. .selectables
  280. .lock()
  281. .await
  282. .insert(inbound.clone().dnet_id, inbound_obj.clone());
  283. let info_obj = SelectableObject::Slot(inbound.info.clone());
  284. self.model
  285. .selectables
  286. .lock()
  287. .await
  288. .insert(inbound.info.clone().dnet_id, info_obj.clone());
  289. }
  290. }
  291. for outbound in node.outbound {
  292. if !outbound.is_empty {
  293. let outbound_obj = SelectableObject::Session(outbound.clone());
  294. self.model
  295. .selectables
  296. .lock()
  297. .await
  298. .insert(outbound.clone().dnet_id, outbound_obj.clone());
  299. let info_obj = SelectableObject::Slot(outbound.info.clone());
  300. self.model
  301. .selectables
  302. .lock()
  303. .await
  304. .insert(outbound.info.clone().dnet_id, info_obj.clone());
  305. }
  306. }
  307. }
  308. Ok(())
  309. }
  310. async fn parse_session(
  311. &self,
  312. reply: &Value,
  313. node_id: &String,
  314. sort: Session,
  315. ) -> DnetViewResult<Vec<SessionInfo>> {
  316. let session_id = make_session_id(&node_id, &sort)?;
  317. let mut session_info: Vec<SessionInfo> = Vec::new();
  318. // Dnetview is not enabled.
  319. if reply.is_null() {
  320. let sort2 = Session::Null;
  321. let info_id = make_null_id(&node_id)?;
  322. let node_id = node_id.to_string();
  323. let addr = "Null".to_string();
  324. let random_id = 0;
  325. let remote_id = "Null".to_string();
  326. let log = Vec::new();
  327. let is_empty = true;
  328. let slot = SlotInfo::new(
  329. info_id.clone(),
  330. node_id.clone(),
  331. addr,
  332. random_id,
  333. remote_id,
  334. log,
  335. is_empty,
  336. );
  337. let is_empty = true;
  338. let addr = "Null".to_string();
  339. let state = None;
  340. let session = SessionInfo::new(
  341. // ..
  342. info_id.clone(),
  343. node_id.clone(),
  344. addr,
  345. state,
  346. slot,
  347. sort2.clone(),
  348. is_empty,
  349. );
  350. session_info.push(session);
  351. return Ok(session_info)
  352. }
  353. let sessions = reply.as_array().unwrap();
  354. for session in sessions {
  355. // TODO: display empty sessions?
  356. if !session.is_null() {
  357. match session.as_object() {
  358. Some(obj) => {
  359. let addr = obj.get("addr").unwrap().as_str().unwrap().to_string();
  360. let state: Option<String> = match obj.get("state") {
  361. Some(state) => Some(state.as_str().unwrap().to_string()),
  362. None => None,
  363. };
  364. let info: serde_json::Map<String, Value> =
  365. serde_json::from_value(obj.get("info").unwrap().clone()).unwrap();
  366. let slot_addr = info.get("addr").unwrap().as_str().unwrap().to_string();
  367. let random_id = info.get("random_id").unwrap().as_u64().unwrap();
  368. let remote_id =
  369. info.get("remote_id").unwrap().as_str().unwrap().to_string();
  370. let info_id = make_info_id(&random_id)?;
  371. let log: Vec<(NanoTimestamp, String, String)> =
  372. serde_json::from_value(info.get("log").unwrap().clone()).unwrap();
  373. // ...
  374. let node_id = node_id.to_string();
  375. let is_empty = false;
  376. let slot = SlotInfo::new(
  377. info_id.clone(),
  378. node_id.clone(),
  379. slot_addr,
  380. random_id,
  381. remote_id,
  382. log,
  383. is_empty,
  384. );
  385. let session = SessionInfo::new(
  386. session_id.clone(),
  387. node_id.clone(),
  388. addr.clone(),
  389. state,
  390. slot.clone(),
  391. sort.clone(),
  392. is_empty,
  393. );
  394. session_info.push(session);
  395. }
  396. None => return Err(DnetViewError::ValueIsNotObject),
  397. }
  398. }
  399. }
  400. Ok(session_info)
  401. }
  402. async fn parse_hosts(&self, hosts: &Value) -> DnetViewResult<Vec<String>> {
  403. match hosts.as_array() {
  404. Some(h) => match h.is_empty() {
  405. true => Ok(Vec::new()),
  406. false => {
  407. let hosts: Vec<String> =
  408. h.iter().map(|addr| addr.as_str().unwrap().to_string()).collect();
  409. Ok(hosts)
  410. }
  411. },
  412. None => {
  413. if hosts.is_null() {
  414. // TODO: this should probs just say null
  415. let h = Vec::new();
  416. return Ok(h)
  417. }
  418. Err(DnetViewError::ValueIsNotObject)
  419. }
  420. }
  421. }
  422. }