mod.rs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2022 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::{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 fxhash::FxHashMap;
  26. use log::{error, info};
  27. use smol::Executor;
  28. use darkfi::{
  29. net::P2pPtr,
  30. system::SubscriberPtr,
  31. util::path::{expand_path, get_config_path},
  32. Error, Result,
  33. };
  34. use crate::{
  35. buffers::SeenIds,
  36. settings::{
  37. parse_configured_channels, parse_configured_contacts, Args, ChannelInfo, ContactInfo,
  38. CONFIG_FILE,
  39. },
  40. Privmsg,
  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 capabilities: FxHashMap<String, bool>,
  56. // channels and contacts
  57. pub auto_channels: Vec<String>,
  58. pub configured_chans: FxHashMap<String, ChannelInfo>,
  59. pub configured_contacts: FxHashMap<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 auto_channels = settings.autojoin.clone();
  65. // Pick up channel settings from the TOML configuration
  66. let cfg_path = get_config_path(settings.config.clone(), CONFIG_FILE)?;
  67. let toml_contents = std::fs::read_to_string(cfg_path)?;
  68. let configured_chans = parse_configured_channels(&toml_contents)?;
  69. let configured_contacts = parse_configured_contacts(&toml_contents)?;
  70. let mut capabilities = FxHashMap::default();
  71. capabilities.insert("no-history".to_string(), false);
  72. Ok(Self {
  73. is_nick_init: false,
  74. is_user_init: false,
  75. is_registered: false,
  76. is_cap_end: true,
  77. is_pass_init: false,
  78. nickname: "anon".to_string(),
  79. password,
  80. auto_channels,
  81. configured_chans,
  82. configured_contacts,
  83. capabilities,
  84. })
  85. }
  86. }
  87. pub struct IrcServer {
  88. settings: Args,
  89. irc_config: IrcConfig,
  90. seen: Arc<Mutex<SeenIds>>,
  91. p2p: P2pPtr,
  92. notify_clients: SubscriberPtr<Privmsg>,
  93. }
  94. impl IrcServer {
  95. pub async fn new(
  96. settings: Args,
  97. seen: Arc<Mutex<SeenIds>>,
  98. p2p: P2pPtr,
  99. notify_clients: SubscriberPtr<Privmsg>,
  100. ) -> Result<Self> {
  101. let irc_config = IrcConfig::new(&settings)?;
  102. Ok(Self { settings, irc_config, seen, p2p, notify_clients })
  103. }
  104. /// Start listening to new irc clients connecting to the irc server address
  105. /// then spawn new connections
  106. pub async fn start(&self, executor: Arc<Executor<'_>>) -> Result<()> {
  107. let (listener, acceptor) = self.setup_listener().await?;
  108. info!("[IRC SERVER] listening on {}", self.settings.irc_listen);
  109. loop {
  110. let (stream, peer_addr) = match listener.accept().await {
  111. Ok((s, a)) => (s, a),
  112. Err(e) => {
  113. error!("[IRC SERVER] Failed accepting new connections: {}", e);
  114. continue
  115. }
  116. };
  117. let result = if let Some(acceptor) = acceptor.clone() {
  118. let stream = match acceptor.accept(stream).await {
  119. Ok(s) => s,
  120. Err(e) => {
  121. error!("[IRC SERVER] Failed accepting TLS connection: {}", e);
  122. continue
  123. }
  124. };
  125. self.process_connection(executor.clone(), stream, peer_addr).await
  126. } else {
  127. self.process_connection(executor.clone(), stream, peer_addr).await
  128. };
  129. if let Err(e) = result {
  130. error!("[IRC SERVER] Failed processing connection {}: {}", peer_addr, e);
  131. continue
  132. };
  133. info!("[IRC SERVER] Accept new connection: {}", peer_addr);
  134. }
  135. }
  136. /// On every new connection create new IrcClient which will process the messages
  137. async fn process_connection<C: AsyncRead + AsyncWrite + Send + Unpin + 'static>(
  138. &self,
  139. executor: Arc<Executor<'_>>,
  140. stream: C,
  141. peer_addr: SocketAddr,
  142. ) -> Result<()> {
  143. let (reader, writer) = stream.split();
  144. let reader = BufReader::new(reader);
  145. // New subscription
  146. let client_subscription = self.notify_clients.clone().subscribe().await;
  147. // New irc connection
  148. let mut client = IrcClient::new(
  149. writer,
  150. peer_addr,
  151. self.seen.clone(),
  152. self.irc_config.clone(),
  153. self.p2p.clone(),
  154. self.notify_clients.clone(),
  155. client_subscription,
  156. );
  157. executor
  158. .spawn(async move {
  159. client.listen(reader).await;
  160. })
  161. .detach();
  162. Ok(())
  163. }
  164. /// Setup a listener for irc server
  165. async fn setup_listener(&self) -> Result<(TcpListener, Option<TlsAcceptor>)> {
  166. let listenaddr = self.settings.irc_listen.socket_addrs(|| None)?[0];
  167. let listener = TcpListener::bind(listenaddr).await?;
  168. let acceptor = match self.settings.irc_listen.scheme() {
  169. "tls" => {
  170. // openssl genpkey -algorithm ED25519 > example.com.key
  171. // openssl req -new -out example.com.csr -key example.com.key
  172. // openssl x509 -req -days 700 -in example.com.csr -signkey example.com.key -out example.com.crt
  173. if self.settings.irc_tls_secret.is_none() || self.settings.irc_tls_cert.is_none() {
  174. error!("[IRC SERVER] To listen using TLS, please set irc_tls_secret and irc_tls_cert in your config file.");
  175. return Err(Error::KeypairPathNotFound)
  176. }
  177. let file =
  178. File::open(expand_path(self.settings.irc_tls_secret.as_ref().unwrap())?)?;
  179. let mut reader = std::io::BufReader::new(file);
  180. let secret = &rustls_pemfile::pkcs8_private_keys(&mut reader)?[0];
  181. let secret = rustls::PrivateKey(secret.clone());
  182. let file = File::open(expand_path(self.settings.irc_tls_cert.as_ref().unwrap())?)?;
  183. let mut reader = std::io::BufReader::new(file);
  184. let certificate = &rustls_pemfile::certs(&mut reader)?[0];
  185. let certificate = rustls::Certificate(certificate.clone());
  186. let config = rustls::ServerConfig::builder()
  187. .with_safe_defaults()
  188. .with_no_client_auth()
  189. .with_single_cert(vec![certificate], secret)?;
  190. let acceptor = TlsAcceptor::from(Arc::new(config));
  191. Some(acceptor)
  192. }
  193. _ => None,
  194. };
  195. Ok((listener, acceptor))
  196. }
  197. }