mod.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  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::HashMap, fs::File, net::SocketAddr};
  19. use async_std::{
  20. net::TcpListener,
  21. sync::{Arc, Mutex},
  22. };
  23. use futures::{io::BufReader, AsyncRead, AsyncReadExt, AsyncWrite};
  24. use futures_rustls::{rustls, TlsAcceptor};
  25. use log::{error, info};
  26. use darkfi::{
  27. event_graph::{
  28. get_current_time,
  29. model::{Event, EventId, ModelPtr},
  30. protocol_event::{Seen, SeenPtr, UnreadEventsPtr},
  31. view::ViewPtr,
  32. },
  33. net::P2pPtr,
  34. system::SubscriberPtr,
  35. util::path::expand_path,
  36. Error, Result,
  37. };
  38. use crate::{
  39. settings::{Args, ChannelInfo, ContactInfo},
  40. PrivMsgEvent,
  41. };
  42. mod client;
  43. pub use client::IrcClient;
  44. #[derive(Clone)]
  45. pub struct IrcConfig {
  46. // init bool
  47. pub is_nick_init: bool,
  48. pub is_user_init: bool,
  49. pub is_registered: bool,
  50. pub is_cap_end: bool,
  51. pub is_pass_init: bool,
  52. // user config
  53. pub nickname: String,
  54. pub password: String,
  55. pub private_key: Option<String>,
  56. pub capabilities: HashMap<String, bool>,
  57. // channels and contacts
  58. pub channels: HashMap<String, ChannelInfo>,
  59. pub contacts: HashMap<String, ContactInfo>,
  60. }
  61. impl IrcConfig {
  62. pub fn new(settings: &Args) -> Result<Self> {
  63. let password = settings.password.as_ref().unwrap_or(&String::new()).clone();
  64. let private_key = settings.private_key.clone();
  65. let mut channels = settings.channels.clone();
  66. for chan in settings.autojoin.iter() {
  67. if !channels.contains_key(chan) {
  68. channels.insert(chan.clone(), ChannelInfo::new());
  69. }
  70. }
  71. let contacts = settings.contacts.clone();
  72. let mut capabilities = HashMap::new();
  73. capabilities.insert("no-history".to_string(), false);
  74. Ok(Self {
  75. is_nick_init: false,
  76. is_user_init: false,
  77. is_registered: false,
  78. is_cap_end: true,
  79. is_pass_init: false,
  80. nickname: "anon".to_string(),
  81. password,
  82. channels,
  83. contacts,
  84. private_key,
  85. capabilities,
  86. })
  87. }
  88. }
  89. #[derive(Clone)]
  90. pub enum ClientSubMsg {
  91. Privmsg(PrivMsgEvent),
  92. Config(IrcConfig),
  93. }
  94. #[derive(Clone)]
  95. pub enum NotifierMsg {
  96. Privmsg(PrivMsgEvent),
  97. UpdateConfig,
  98. }
  99. pub struct IrcServer {
  100. settings: Args,
  101. p2p: P2pPtr,
  102. model: ModelPtr<PrivMsgEvent>,
  103. view: ViewPtr<PrivMsgEvent>,
  104. unread_events: UnreadEventsPtr<PrivMsgEvent>,
  105. clients_subscriptions: SubscriberPtr<ClientSubMsg>,
  106. seen: SeenPtr<EventId>,
  107. missed_events: Arc<Mutex<Vec<Event<PrivMsgEvent>>>>,
  108. }
  109. impl IrcServer {
  110. pub async fn new(
  111. settings: Args,
  112. p2p: P2pPtr,
  113. model: ModelPtr<PrivMsgEvent>,
  114. view: ViewPtr<PrivMsgEvent>,
  115. unread_events: UnreadEventsPtr<PrivMsgEvent>,
  116. clients_subscriptions: SubscriberPtr<ClientSubMsg>,
  117. ) -> Result<Self> {
  118. let seen = Seen::new();
  119. let missed_events = Arc::new(Mutex::new(vec![]));
  120. Ok(Self {
  121. settings,
  122. p2p,
  123. model,
  124. view,
  125. unread_events,
  126. clients_subscriptions,
  127. seen,
  128. missed_events,
  129. })
  130. }
  131. pub async fn start(&self, executor: Arc<smol::Executor<'_>>) -> Result<()> {
  132. let (msg_notifier, msg_recv) = smol::channel::unbounded();
  133. // Listen to msgs from clients
  134. executor
  135. .clone()
  136. .spawn(Self::listen_to_msgs(
  137. self.p2p.clone(),
  138. self.model.clone(),
  139. self.seen.clone(),
  140. self.unread_events.clone(),
  141. msg_recv,
  142. self.clients_subscriptions.clone(),
  143. ))
  144. .detach();
  145. executor
  146. .clone()
  147. .spawn(Self::listen_to_view(
  148. self.view.clone(),
  149. self.seen.clone(),
  150. self.missed_events.clone(),
  151. self.clients_subscriptions.clone(),
  152. ))
  153. .detach();
  154. // Start listening for new connections
  155. self.listen(msg_notifier, executor.clone()).await?;
  156. Ok(())
  157. }
  158. async fn listen_to_view(
  159. view: ViewPtr<PrivMsgEvent>,
  160. seen: SeenPtr<EventId>,
  161. missed_events: Arc<Mutex<Vec<Event<PrivMsgEvent>>>>,
  162. clients_subscriptions: SubscriberPtr<ClientSubMsg>,
  163. ) -> Result<()> {
  164. loop {
  165. let event = view.lock().await.process().await?;
  166. if !seen.push(&event.hash()).await {
  167. continue
  168. }
  169. missed_events.lock().await.push(event.clone());
  170. let msg = event.action.clone();
  171. clients_subscriptions.notify(ClientSubMsg::Privmsg(msg)).await;
  172. }
  173. }
  174. /// Start listening to msgs from irc clients
  175. pub async fn listen_to_msgs(
  176. p2p: P2pPtr,
  177. model: ModelPtr<PrivMsgEvent>,
  178. seen: SeenPtr<EventId>,
  179. unread_events: UnreadEventsPtr<PrivMsgEvent>,
  180. recv: smol::channel::Receiver<(NotifierMsg, u64)>,
  181. clients_subscriptions: SubscriberPtr<ClientSubMsg>,
  182. ) -> Result<()> {
  183. loop {
  184. let (msg, subscription_id) = recv.recv().await?;
  185. match msg {
  186. NotifierMsg::Privmsg(msg) => {
  187. let event = Event {
  188. previous_event_hash: model.lock().await.get_head_hash(),
  189. action: msg.clone(),
  190. timestamp: get_current_time(),
  191. read_confirms: 0,
  192. };
  193. // Since this will be added to the View directly, other clients connected to irc
  194. // server must get informed about this new msg
  195. clients_subscriptions
  196. .notify_with_exclude(ClientSubMsg::Privmsg(msg), &[subscription_id])
  197. .await;
  198. if !seen.push(&event.hash()).await {
  199. continue
  200. }
  201. unread_events.lock().await.insert(&event);
  202. p2p.broadcast(event).await?;
  203. }
  204. NotifierMsg::UpdateConfig => {
  205. //
  206. // load and parse the new settings from configuration file and pass it to all
  207. // irc clients
  208. //
  209. // let new_config = IrcConfig::new()?;
  210. // clients_subscriptions.notify(ClientSubMsg::Config(new_config)).await;
  211. }
  212. }
  213. }
  214. }
  215. /// Start listening to new connections from irc clients
  216. pub async fn listen(
  217. &self,
  218. notifier: smol::channel::Sender<(NotifierMsg, u64)>,
  219. executor: Arc<smol::Executor<'_>>,
  220. ) -> Result<()> {
  221. let (listener, acceptor) = self.setup_listener().await?;
  222. info!("[IRC SERVER] listening on {}", self.settings.irc_listen);
  223. loop {
  224. let (stream, peer_addr) = match listener.accept().await {
  225. Ok((s, a)) => (s, a),
  226. Err(e) => {
  227. error!("[IRC SERVER] Failed accepting new connections: {}", e);
  228. continue
  229. }
  230. };
  231. let result = if let Some(acceptor) = acceptor.clone() {
  232. // TLS connection
  233. let stream = match acceptor.accept(stream).await {
  234. Ok(s) => s,
  235. Err(e) => {
  236. error!("[IRC SERVER] Failed accepting TLS connection: {}", e);
  237. continue
  238. }
  239. };
  240. self.process_connection(stream, peer_addr, notifier.clone(), executor.clone()).await
  241. } else {
  242. // TCP connection
  243. self.process_connection(stream, peer_addr, notifier.clone(), executor.clone()).await
  244. };
  245. if let Err(e) = result {
  246. error!("[IRC SERVER] Failed processing connection {}: {}", peer_addr, e);
  247. continue
  248. };
  249. info!("[IRC SERVER] Accept new connection: {}", peer_addr);
  250. }
  251. }
  252. /// On every new connection create new IrcClient
  253. async fn process_connection<C: AsyncRead + AsyncWrite + Send + Unpin + 'static>(
  254. &self,
  255. stream: C,
  256. peer_addr: SocketAddr,
  257. notifier: smol::channel::Sender<(NotifierMsg, u64)>,
  258. executor: Arc<smol::Executor<'_>>,
  259. ) -> Result<()> {
  260. let (reader, writer) = stream.split();
  261. let reader = BufReader::new(reader);
  262. // Subscription for the new client
  263. let client_subscription = self.clients_subscriptions.clone().subscribe().await;
  264. // new irc configuration
  265. let irc_config = IrcConfig::new(&self.settings)?;
  266. // New irc client
  267. let mut client = IrcClient::new(
  268. writer,
  269. reader,
  270. peer_addr,
  271. irc_config,
  272. notifier,
  273. client_subscription,
  274. self.missed_events.clone(),
  275. );
  276. // Start listening and detach
  277. executor
  278. .spawn(async move {
  279. client.listen().await;
  280. })
  281. .detach();
  282. Ok(())
  283. }
  284. /// Setup a listener for irc server
  285. async fn setup_listener(&self) -> Result<(TcpListener, Option<TlsAcceptor>)> {
  286. let listenaddr = self.settings.irc_listen.socket_addrs(|| None)?[0];
  287. let listener = TcpListener::bind(listenaddr).await?;
  288. let acceptor = match self.settings.irc_listen.scheme() {
  289. "tls" => {
  290. // openssl genpkey -algorithm ED25519 > example.com.key
  291. // openssl req -new -out example.com.csr -key example.com.key
  292. // openssl x509 -req -days 700 -in example.com.csr -signkey example.com.key -out example.com.crt
  293. if self.settings.irc_tls_secret.is_none() || self.settings.irc_tls_cert.is_none() {
  294. error!("[IRC SERVER] To listen using TLS, please set irc_tls_secret and irc_tls_cert in your config file.");
  295. return Err(Error::KeypairPathNotFound)
  296. }
  297. let file =
  298. File::open(expand_path(self.settings.irc_tls_secret.as_ref().unwrap())?)?;
  299. let mut reader = std::io::BufReader::new(file);
  300. let secret = &rustls_pemfile::pkcs8_private_keys(&mut reader)?[0];
  301. let secret = rustls::PrivateKey(secret.clone());
  302. let file = File::open(expand_path(self.settings.irc_tls_cert.as_ref().unwrap())?)?;
  303. let mut reader = std::io::BufReader::new(file);
  304. let certificate = &rustls_pemfile::certs(&mut reader)?[0];
  305. let certificate = rustls::Certificate(certificate.clone());
  306. let config = rustls::ServerConfig::builder()
  307. .with_safe_defaults()
  308. .with_no_client_auth()
  309. .with_single_cert(vec![certificate], secret)?;
  310. let acceptor = TlsAcceptor::from(Arc::new(config));
  311. Some(acceptor)
  312. }
  313. _ => None,
  314. };
  315. Ok((listener, acceptor))
  316. }
  317. }