server.rs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. use std::sync::atomic::Ordering;
  2. use async_std::net::TcpStream;
  3. use futures::{io::WriteHalf, AsyncWriteExt};
  4. use fxhash::FxHashMap;
  5. use log::{debug, info, warn};
  6. use rand::{rngs::OsRng, RngCore};
  7. use ringbuffer::RingBufferWrite;
  8. use darkfi::{net::P2pPtr, Error, Result};
  9. use crate::{
  10. crypto::encrypt_message,
  11. privmsg::{Privmsg, PrivmsgsBuffer, SeenMsgIds},
  12. ChannelInfo,
  13. };
  14. const RPL_NOTOPIC: u32 = 331;
  15. const RPL_TOPIC: u32 = 332;
  16. pub struct IrcServerConnection {
  17. // server stream
  18. write_stream: WriteHalf<TcpStream>,
  19. // msg ids
  20. seen_msg_ids: SeenMsgIds,
  21. privmsgs_buffer: PrivmsgsBuffer,
  22. // user & channels
  23. is_nick_init: bool,
  24. is_user_init: bool,
  25. is_registered: bool,
  26. nickname: String,
  27. auto_channels: Vec<String>,
  28. pub configured_chans: FxHashMap<String, ChannelInfo>,
  29. // p2p
  30. p2p: P2pPtr,
  31. }
  32. impl IrcServerConnection {
  33. pub fn new(
  34. write_stream: WriteHalf<TcpStream>,
  35. seen_msg_ids: SeenMsgIds,
  36. privmsgs_buffer: PrivmsgsBuffer,
  37. auto_channels: Vec<String>,
  38. configured_chans: FxHashMap<String, ChannelInfo>,
  39. p2p: P2pPtr,
  40. ) -> Self {
  41. Self {
  42. write_stream,
  43. seen_msg_ids,
  44. privmsgs_buffer,
  45. is_nick_init: false,
  46. is_user_init: false,
  47. is_registered: false,
  48. nickname: "anon".to_string(),
  49. auto_channels,
  50. configured_chans,
  51. p2p,
  52. }
  53. }
  54. pub async fn update(&mut self, line: String) -> Result<()> {
  55. let mut tokens = line.split_ascii_whitespace();
  56. // Commands can begin with :garbage but we will reject clients doing
  57. // that for now to keep the protocol simple and focused.
  58. let command = tokens.next().ok_or(Error::MalformedPacket)?;
  59. info!("IRC server received command: {}", command.to_uppercase());
  60. match command.to_uppercase().as_str() {
  61. "USER" => {
  62. // We can stuff any extra things like public keys in here.
  63. // Ignore it for now.
  64. self.is_user_init = true;
  65. }
  66. "NICK" => {
  67. let nickname = tokens.next().ok_or(Error::MalformedPacket)?;
  68. self.is_nick_init = true;
  69. let old_nick = std::mem::replace(&mut self.nickname, nickname.to_string());
  70. let nick_reply = format!(":{}!anon@dark.fi NICK {}\r\n", old_nick, self.nickname);
  71. self.reply(&nick_reply).await?;
  72. }
  73. "JOIN" => {
  74. let channels = tokens.next().ok_or(Error::MalformedPacket)?;
  75. for chan in channels.split(',') {
  76. if !chan.starts_with('#') {
  77. warn!("{} is not a valid name for channel", chan);
  78. continue
  79. }
  80. let join_reply = format!(":{}!anon@dark.fi JOIN {}\r\n", self.nickname, chan);
  81. self.reply(&join_reply).await?;
  82. if !self.configured_chans.contains_key(chan) {
  83. self.configured_chans.insert(chan.to_string(), ChannelInfo::new()?);
  84. } else {
  85. let chan_info = self.configured_chans.get_mut(chan).unwrap();
  86. chan_info.joined.store(true, Ordering::Relaxed);
  87. }
  88. }
  89. }
  90. "PART" => {
  91. let channels = tokens.next().ok_or(Error::MalformedPacket)?;
  92. for chan in channels.split(',') {
  93. let part_reply = format!(":{}!anon@dark.fi PART {}\r\n", self.nickname, chan);
  94. self.reply(&part_reply).await?;
  95. if self.configured_chans.contains_key(chan) {
  96. let chan_info = self.configured_chans.get_mut(chan).unwrap();
  97. chan_info.joined.store(false, Ordering::Relaxed);
  98. }
  99. }
  100. }
  101. "TOPIC" => {
  102. let channel = tokens.next().ok_or(Error::MalformedPacket)?;
  103. if let Some(substr_idx) = line.find(':') {
  104. // Client is setting the topic
  105. if substr_idx >= line.len() {
  106. return Err(Error::MalformedPacket)
  107. }
  108. let topic = &line[substr_idx + 1..];
  109. let chan_info = self.configured_chans.get_mut(channel).unwrap();
  110. chan_info.topic = Some(topic.to_string());
  111. let topic_reply =
  112. format!(":{}!anon@dark.fi TOPIC {} :{}\r\n", self.nickname, channel, topic);
  113. self.reply(&topic_reply).await?;
  114. } else {
  115. // Client is asking or the topic
  116. let chan_info = self.configured_chans.get(channel).unwrap();
  117. let topic_reply = if let Some(topic) = &chan_info.topic {
  118. format!("{} {} {} :{}\r\n", RPL_TOPIC, self.nickname, channel, topic)
  119. } else {
  120. const TOPIC: &str = "No topic is set";
  121. format!("{} {} {} :{}\r\n", RPL_NOTOPIC, self.nickname, channel, TOPIC)
  122. };
  123. self.reply(&topic_reply).await?;
  124. }
  125. }
  126. "PING" => {
  127. let line_clone = line.clone();
  128. let split_line: Vec<&str> = line_clone.split_whitespace().collect();
  129. if split_line.len() > 1 {
  130. let pong = format!("PONG {}\r\n", split_line[1]);
  131. self.reply(&pong).await?;
  132. }
  133. }
  134. "PRIVMSG" => {
  135. let channel = tokens.next().ok_or(Error::MalformedPacket)?;
  136. let substr_idx = line.find(':').ok_or(Error::MalformedPacket)?;
  137. if substr_idx >= line.len() {
  138. return Err(Error::MalformedPacket)
  139. }
  140. let message = &line[substr_idx + 1..];
  141. info!("(Plain) PRIVMSG {} :{}", channel, message);
  142. if self.configured_chans.contains_key(channel) {
  143. let channel_info = self.configured_chans.get(channel).unwrap();
  144. if channel_info.joined.load(Ordering::Relaxed) {
  145. let message = if let Some(salt_box) = &channel_info.salt_box {
  146. let encrypted = encrypt_message(salt_box, message);
  147. info!("(Encrypted) PRIVMSG {} :{}", channel, encrypted);
  148. encrypted
  149. } else {
  150. message.to_string()
  151. };
  152. let random_id = OsRng.next_u64();
  153. let protocol_msg = Privmsg {
  154. id: random_id,
  155. nickname: self.nickname.clone(),
  156. channel: channel.to_string(),
  157. message,
  158. };
  159. {
  160. (*self.seen_msg_ids.lock().await).push(random_id);
  161. (*self.privmsgs_buffer.lock().await).push(protocol_msg.clone())
  162. }
  163. debug!(target: "ircd", "PRIVMSG to be sent: {:?}", protocol_msg);
  164. self.p2p.broadcast(protocol_msg).await?;
  165. }
  166. }
  167. }
  168. "QUIT" => {
  169. // Close the connection
  170. return Err(Error::ServiceStopped)
  171. }
  172. _ => {
  173. warn!("Unimplemented `{}` command", command);
  174. }
  175. }
  176. if !self.is_registered && self.is_nick_init && self.is_user_init {
  177. debug!("Initializing peer connection");
  178. let register_reply = format!(":darkfi 001 {} :Let there be dark\r\n", self.nickname);
  179. self.reply(&register_reply).await?;
  180. self.is_registered = true;
  181. // Auto-joins
  182. macro_rules! autojoin {
  183. ($channel:expr,$topic:expr) => {
  184. let j = format!(":{}!anon@dark.fi JOIN {}\r\n", self.nickname, $channel);
  185. let t = format!(":DarkFi TOPIC {} :{}\r\n", $channel, $topic);
  186. self.reply(&j).await?;
  187. self.reply(&t).await?;
  188. };
  189. }
  190. for chan in self.auto_channels.clone() {
  191. if self.configured_chans.contains_key(&chan) {
  192. let chan_info = self.configured_chans.get_mut(&chan).unwrap();
  193. let topic = if let Some(topic) = chan_info.topic.clone() {
  194. topic
  195. } else {
  196. "n/a".to_string()
  197. };
  198. chan_info.topic = Some(topic.to_string());
  199. autojoin!(chan, topic);
  200. } else {
  201. let mut chan_info = ChannelInfo::new()?;
  202. chan_info.topic = Some("n/a".to_string());
  203. self.configured_chans.insert(chan.clone(), chan_info);
  204. autojoin!(chan, "n/a");
  205. }
  206. }
  207. }
  208. Ok(())
  209. }
  210. pub async fn reply(&mut self, message: &str) -> Result<()> {
  211. self.write_stream.write_all(message.as_bytes()).await?;
  212. debug!("Sent {}", message);
  213. Ok(())
  214. }
  215. }