main.rs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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::{error, fs::File, io::stdin};
  19. // ANCHOR: daemon_deps
  20. use async_std::sync::{Arc, Mutex};
  21. use easy_parallel::Parallel;
  22. use smol::Executor;
  23. // ANCHOR_END: daemon_deps
  24. use log::debug;
  25. use simplelog::WriteLogger;
  26. use url::Url;
  27. use darkfi::{net, net::Settings, rpc::server::listen_and_serve};
  28. use crate::{
  29. dchat_error::ErrorMissingSpecifier,
  30. dchatmsg::{DchatMsg, DchatMsgsBuffer},
  31. protocol_dchat::ProtocolDchat,
  32. rpc::JsonRpcInterface,
  33. };
  34. pub mod dchat_error;
  35. pub mod dchatmsg;
  36. pub mod protocol_dchat;
  37. pub mod rpc;
  38. // ANCHOR: error
  39. pub type Error = Box<dyn error::Error>;
  40. pub type Result<T> = std::result::Result<T, Error>;
  41. // ANCHOR_END: error
  42. // ANCHOR: dchat
  43. struct Dchat {
  44. p2p: net::P2pPtr,
  45. recv_msgs: DchatMsgsBuffer,
  46. }
  47. // ANCHOR_END: dchat
  48. impl Dchat {
  49. fn new(p2p: net::P2pPtr, recv_msgs: DchatMsgsBuffer) -> Self {
  50. Self { p2p, recv_msgs }
  51. }
  52. // ANCHOR: menu
  53. async fn menu(&self) -> Result<()> {
  54. let mut buffer = String::new();
  55. let stdin = stdin();
  56. loop {
  57. println!(
  58. "Welcome to dchat.
  59. s: send message
  60. i: inbox
  61. q: quit "
  62. );
  63. stdin.read_line(&mut buffer)?;
  64. // Remove trailing \n
  65. buffer.pop();
  66. match buffer.as_str() {
  67. "q" => return Ok(()),
  68. "s" => {
  69. // Remove trailing s
  70. buffer.pop();
  71. stdin.read_line(&mut buffer)?;
  72. match self.send(buffer.clone()).await {
  73. Ok(_) => {
  74. println!("you sent: {}", buffer);
  75. }
  76. Err(e) => {
  77. println!("send failed for reason: {}", e);
  78. }
  79. }
  80. buffer.clear();
  81. }
  82. "i" => {
  83. let msgs = self.recv_msgs.lock().await;
  84. if msgs.is_empty() {
  85. println!("inbox is empty")
  86. } else {
  87. println!("received:");
  88. for i in msgs.iter() {
  89. if !i.msg.is_empty() {
  90. println!("{}", i.msg);
  91. }
  92. }
  93. }
  94. buffer.clear();
  95. }
  96. _ => {}
  97. }
  98. }
  99. }
  100. // ANCHOR_END: menu
  101. // ANCHOR: register_protocol
  102. async fn register_protocol(&self, msgs: DchatMsgsBuffer) -> Result<()> {
  103. debug!(target: "dchat", "Dchat::register_protocol() [START]");
  104. let registry = self.p2p.protocol_registry();
  105. registry
  106. .register(!net::session::SESSION_SEED, move |channel, _p2p| {
  107. let msgs2 = msgs.clone();
  108. async move { ProtocolDchat::init(channel, msgs2).await }
  109. })
  110. .await;
  111. debug!(target: "dchat", "Dchat::register_protocol() [STOP]");
  112. Ok(())
  113. }
  114. // ANCHOR_END: register_protocol
  115. // ANCHOR: start
  116. async fn start(&mut self, ex: Arc<Executor<'_>>) -> Result<()> {
  117. debug!(target: "dchat", "Dchat::start() [START]");
  118. let ex2 = ex.clone();
  119. self.register_protocol(self.recv_msgs.clone()).await?;
  120. self.p2p.clone().start(ex.clone()).await?;
  121. ex2.spawn(self.p2p.clone().run(ex.clone())).detach();
  122. self.menu().await?;
  123. self.p2p.stop().await;
  124. debug!(target: "dchat", "Dchat::start() [STOP]");
  125. Ok(())
  126. }
  127. // ANCHOR_END: start
  128. // ANCHOR: send
  129. async fn send(&self, msg: String) -> Result<()> {
  130. let dchatmsg = DchatMsg { msg };
  131. self.p2p.broadcast(&dchatmsg).await;
  132. Ok(())
  133. }
  134. // ANCHOR_END: send
  135. }
  136. // ANCHOR: app_settings
  137. #[derive(Clone, Debug)]
  138. struct AppSettings {
  139. accept_addr: Url,
  140. net: Settings,
  141. }
  142. impl AppSettings {
  143. pub fn new(accept_addr: Url, net: Settings) -> Self {
  144. Self { accept_addr, net }
  145. }
  146. }
  147. // ANCHOR_END: app_settings
  148. // ANCHOR: alice
  149. fn alice() -> Result<AppSettings> {
  150. let log_level = simplelog::LevelFilter::Debug;
  151. let log_config = simplelog::Config::default();
  152. let log_path = "/tmp/alice.log";
  153. let file = File::create(log_path).unwrap();
  154. WriteLogger::init(log_level, log_config, file)?;
  155. let seed = Url::parse("tcp://127.0.0.1:50515").unwrap();
  156. let inbound = Url::parse("tcp://127.0.0.1:51554").unwrap();
  157. let ext_addr = Url::parse("tcp://127.0.0.1:51554").unwrap();
  158. let net = Settings {
  159. inbound_addrs: vec![inbound],
  160. external_addrs: vec![ext_addr],
  161. seeds: vec![seed],
  162. localnet: true,
  163. ..Default::default()
  164. };
  165. let accept_addr = Url::parse("tcp://127.0.0.1:55054").unwrap();
  166. let settings = AppSettings::new(accept_addr, net);
  167. Ok(settings)
  168. }
  169. // ANCHOR_END: alice
  170. // ANCHOR: bob
  171. fn bob() -> Result<AppSettings> {
  172. let log_level = simplelog::LevelFilter::Debug;
  173. let log_config = simplelog::Config::default();
  174. let log_path = "/tmp/bob.log";
  175. let file = File::create(log_path).unwrap();
  176. WriteLogger::init(log_level, log_config, file)?;
  177. let seed = Url::parse("tcp://127.0.0.1:50515").unwrap();
  178. let net = Settings {
  179. inbound_addrs: vec![],
  180. outbound_connections: 5,
  181. seeds: vec![seed],
  182. localnet: true,
  183. ..Default::default()
  184. };
  185. let accept_addr = Url::parse("tcp://127.0.0.1:51054").unwrap();
  186. let settings = AppSettings::new(accept_addr, net);
  187. Ok(settings)
  188. }
  189. // ANCHOR_END: bob
  190. // ANCHOR: main
  191. #[async_std::main]
  192. async fn main() -> Result<()> {
  193. let settings: Result<AppSettings> = match std::env::args().nth(1) {
  194. Some(id) => match id.as_str() {
  195. "a" => alice(),
  196. "b" => bob(),
  197. _ => Err(ErrorMissingSpecifier.into()),
  198. },
  199. None => Err(ErrorMissingSpecifier.into()),
  200. };
  201. let settings = settings?.clone();
  202. let p2p = net::P2p::new(settings.net).await;
  203. let ex = Arc::new(Executor::new());
  204. let ex2 = ex.clone();
  205. let ex3 = ex2.clone();
  206. let msgs: DchatMsgsBuffer = Arc::new(Mutex::new(vec![DchatMsg { msg: String::new() }]));
  207. let mut dchat = Dchat::new(p2p.clone(), msgs);
  208. // ANCHOR: json_init
  209. let accept_addr = settings.accept_addr.clone();
  210. let rpc = Arc::new(JsonRpcInterface { addr: accept_addr.clone(), p2p });
  211. let _ex = ex.clone();
  212. ex.spawn(async move { listen_and_serve(accept_addr.clone(), rpc, _ex).await }).detach();
  213. // ANCHOR_END: json_init
  214. let nthreads = std::thread::available_parallelism().unwrap().get();
  215. let (signal, shutdown) = smol::channel::unbounded::<()>();
  216. let (_, result) = Parallel::new()
  217. .each(0..nthreads, |_| smol::future::block_on(ex2.run(shutdown.recv())))
  218. .finish(|| {
  219. smol::future::block_on(async move {
  220. dchat.start(ex3).await?;
  221. drop(signal);
  222. Ok(())
  223. })
  224. });
  225. result
  226. }
  227. // ANCHOR_END: main