mod.rs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. use std::{collections::HashMap, fs::File, net::SocketAddr};
  2. use async_std::{net::TcpListener, sync::Arc};
  3. use futures::{io::BufReader, AsyncRead, AsyncReadExt, AsyncWrite};
  4. use futures_rustls::{rustls, TlsAcceptor};
  5. use log::{error, info};
  6. use darkfi::{system::SubscriberPtr, util::path::expand_path, Error, Result};
  7. use crate::{
  8. privmsg::PrivMsgEvent,
  9. settings::{Args, ChannelInfo, ContactInfo},
  10. };
  11. mod client;
  12. pub use client::IrcClient;
  13. #[derive(Clone)]
  14. pub struct IrcConfig {
  15. // init bool
  16. pub is_nick_init: bool,
  17. pub is_user_init: bool,
  18. pub is_registered: bool,
  19. pub is_cap_end: bool,
  20. pub is_pass_init: bool,
  21. // user config
  22. pub nickname: String,
  23. pub password: String,
  24. pub private_key: Option<String>,
  25. pub capabilities: HashMap<String, bool>,
  26. // channels and contacts
  27. pub channels: HashMap<String, ChannelInfo>,
  28. pub contacts: HashMap<String, ContactInfo>,
  29. }
  30. impl IrcConfig {
  31. pub fn new(settings: &Args) -> Result<Self> {
  32. let password = settings.password.as_ref().unwrap_or(&String::new()).clone();
  33. let private_key = settings.private_key.clone();
  34. let mut channels = settings.channels.clone();
  35. for chan in settings.autojoin.iter() {
  36. if !channels.contains_key(chan) {
  37. channels.insert(chan.clone(), ChannelInfo::new());
  38. }
  39. }
  40. let contacts = settings.contacts.clone();
  41. let mut capabilities = HashMap::new();
  42. capabilities.insert("no-history".to_string(), false);
  43. Ok(Self {
  44. is_nick_init: false,
  45. is_user_init: false,
  46. is_registered: false,
  47. is_cap_end: true,
  48. is_pass_init: false,
  49. nickname: "anon".to_string(),
  50. password,
  51. channels,
  52. contacts,
  53. private_key,
  54. capabilities,
  55. })
  56. }
  57. }
  58. #[derive(Clone)]
  59. pub enum ClientSubMsg {
  60. Privmsg(PrivMsgEvent),
  61. Config(IrcConfig),
  62. }
  63. #[derive(Clone)]
  64. pub enum NotifierMsg {
  65. Privmsg(PrivMsgEvent),
  66. UpdateConfig,
  67. }
  68. pub struct IrcServer {
  69. settings: Args,
  70. clients_subscriptions: SubscriberPtr<ClientSubMsg>,
  71. }
  72. impl IrcServer {
  73. pub async fn new(
  74. settings: Args,
  75. clients_subscriptions: SubscriberPtr<ClientSubMsg>,
  76. ) -> Result<Self> {
  77. Ok(Self { settings, clients_subscriptions })
  78. }
  79. pub async fn start(&self, executor: Arc<smol::Executor<'_>>) -> Result<()> {
  80. let (msg_notifier, msg_recv) = smol::channel::unbounded();
  81. // Listen to msgs from clients
  82. executor.spawn(Self::listen_to_msgs(msg_recv, self.clients_subscriptions.clone())).detach();
  83. // Start listening for new connections
  84. self.listen(msg_notifier, executor.clone()).await?;
  85. Ok(())
  86. }
  87. /// Start listening to msgs from irc clients
  88. pub async fn listen_to_msgs(
  89. recv: smol::channel::Receiver<(NotifierMsg, u64)>,
  90. clients_subscriptions: SubscriberPtr<ClientSubMsg>,
  91. ) -> Result<()> {
  92. loop {
  93. let (msg, subscription_id) = recv.recv().await?;
  94. match msg {
  95. NotifierMsg::Privmsg(msg) => {
  96. // TODO Add to View to prevent duplicate msg, since a client may has already added the
  97. // msg to its buffer
  98. // Since this will be added to the View directly, other clients connected to irc
  99. // server must get informed about this new msg
  100. clients_subscriptions
  101. .notify_with_exclude(ClientSubMsg::Privmsg(msg), &[subscription_id])
  102. .await;
  103. // TODO broadcast to the p2p network
  104. }
  105. NotifierMsg::UpdateConfig => {
  106. //
  107. // load and parse the new settings from configuration file and pass it to all
  108. // irc clients
  109. //
  110. // let new_config = IrcConfig::new()?;
  111. // clients_subscriptions.notify(ClientSubMsg::Config(new_config)).await;
  112. }
  113. }
  114. }
  115. }
  116. /// Start listening to new connections from irc clients
  117. pub async fn listen(
  118. &self,
  119. notifier: smol::channel::Sender<(NotifierMsg, u64)>,
  120. executor: Arc<smol::Executor<'_>>,
  121. ) -> Result<()> {
  122. let (listener, acceptor) = self.setup_listener().await?;
  123. info!("[IRC SERVER] listening on {}", self.settings.irc_listen);
  124. loop {
  125. let (stream, peer_addr) = match listener.accept().await {
  126. Ok((s, a)) => (s, a),
  127. Err(e) => {
  128. error!("[IRC SERVER] Failed accepting new connections: {}", e);
  129. continue
  130. }
  131. };
  132. let result = if let Some(acceptor) = acceptor.clone() {
  133. // TLS connection
  134. let stream = match acceptor.accept(stream).await {
  135. Ok(s) => s,
  136. Err(e) => {
  137. error!("[IRC SERVER] Failed accepting TLS connection: {}", e);
  138. continue
  139. }
  140. };
  141. self.process_connection(stream, peer_addr, notifier.clone(), executor.clone()).await
  142. } else {
  143. // TCP connection
  144. self.process_connection(stream, peer_addr, notifier.clone(), executor.clone()).await
  145. };
  146. if let Err(e) = result {
  147. error!("[IRC SERVER] Failed processing connection {}: {}", peer_addr, e);
  148. continue
  149. };
  150. info!("[IRC SERVER] Accept new connection: {}", peer_addr);
  151. }
  152. }
  153. /// On every new connection create new IrcClient
  154. async fn process_connection<C: AsyncRead + AsyncWrite + Send + Unpin + 'static>(
  155. &self,
  156. stream: C,
  157. peer_addr: SocketAddr,
  158. notifier: smol::channel::Sender<(NotifierMsg, u64)>,
  159. executor: Arc<smol::Executor<'_>>,
  160. ) -> Result<()> {
  161. let (reader, writer) = stream.split();
  162. let reader = BufReader::new(reader);
  163. // Subscription for the new client
  164. let client_subscription = self.clients_subscriptions.clone().subscribe().await;
  165. // new irc configuration
  166. let irc_config = IrcConfig::new(&self.settings)?;
  167. // New irc client
  168. let mut client =
  169. IrcClient::new(writer, reader, peer_addr, irc_config, notifier, client_subscription);
  170. // Start listening and detach
  171. executor
  172. .spawn(async move {
  173. client.listen().await;
  174. })
  175. .detach();
  176. Ok(())
  177. }
  178. /// Setup a listener for irc server
  179. async fn setup_listener(&self) -> Result<(TcpListener, Option<TlsAcceptor>)> {
  180. let listenaddr = self.settings.irc_listen.socket_addrs(|| None)?[0];
  181. let listener = TcpListener::bind(listenaddr).await?;
  182. let acceptor = match self.settings.irc_listen.scheme() {
  183. "tls" => {
  184. // openssl genpkey -algorithm ED25519 > example.com.key
  185. // openssl req -new -out example.com.csr -key example.com.key
  186. // openssl x509 -req -days 700 -in example.com.csr -signkey example.com.key -out example.com.crt
  187. if self.settings.irc_tls_secret.is_none() || self.settings.irc_tls_cert.is_none() {
  188. error!("[IRC SERVER] To listen using TLS, please set irc_tls_secret and irc_tls_cert in your config file.");
  189. return Err(Error::KeypairPathNotFound)
  190. }
  191. let file =
  192. File::open(expand_path(self.settings.irc_tls_secret.as_ref().unwrap())?)?;
  193. let mut reader = std::io::BufReader::new(file);
  194. let secret = &rustls_pemfile::pkcs8_private_keys(&mut reader)?[0];
  195. let secret = rustls::PrivateKey(secret.clone());
  196. let file = File::open(expand_path(self.settings.irc_tls_cert.as_ref().unwrap())?)?;
  197. let mut reader = std::io::BufReader::new(file);
  198. let certificate = &rustls_pemfile::certs(&mut reader)?[0];
  199. let certificate = rustls::Certificate(certificate.clone());
  200. let config = rustls::ServerConfig::builder()
  201. .with_safe_defaults()
  202. .with_no_client_auth()
  203. .with_single_cert(vec![certificate], secret)?;
  204. let acceptor = TlsAcceptor::from(Arc::new(config));
  205. Some(acceptor)
  206. }
  207. _ => None,
  208. };
  209. Ok((listener, acceptor))
  210. }
  211. }