command.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. use futures::{AsyncRead, AsyncWrite};
  2. use log::{debug, info, warn};
  3. use darkfi::{Error, Result};
  4. use crate::{
  5. crypto::encrypt_privmsg,
  6. privmsg::{Privmsg, MAXIMUM_LENGTH_OF_NICKNAME},
  7. ChannelInfo,
  8. };
  9. use super::IrcServerConnection;
  10. const RPL_NOTOPIC: u32 = 331;
  11. const RPL_TOPIC: u32 = 332;
  12. const RPL_NAMEREPLY: u32 = 353;
  13. const RPL_ENDOFNAMES: u32 = 366;
  14. impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcServerConnection<C> {
  15. pub(super) fn on_quit(&self) -> Result<()> {
  16. // Close the connection
  17. Err(Error::NetworkServiceStopped)
  18. }
  19. pub(super) async fn on_receive_user(&mut self) -> Result<()> {
  20. // We can stuff any extra things like public keys in here.
  21. // Ignore it for now.
  22. if self.is_pass_init {
  23. self.is_user_init = true;
  24. } else {
  25. // Close the connection
  26. warn!("Password is required");
  27. return self.on_quit()
  28. }
  29. Ok(())
  30. }
  31. pub(super) async fn on_receive_pass(&mut self, password: &str) -> Result<()> {
  32. if self.password == password {
  33. self.is_pass_init = true
  34. } else {
  35. // Close the connection
  36. warn!("Password is not correct!");
  37. return self.on_quit()
  38. }
  39. Ok(())
  40. }
  41. pub(super) async fn on_receive_nick(&mut self, nickname: &str) -> Result<()> {
  42. if nickname.len() > MAXIMUM_LENGTH_OF_NICKNAME {
  43. return Ok(())
  44. }
  45. self.is_nick_init = true;
  46. let old_nick = std::mem::replace(&mut self.nickname, nickname.to_string());
  47. let nick_reply = format!(":{}!anon@dark.fi NICK {}\r\n", old_nick, self.nickname);
  48. self.reply(&nick_reply).await
  49. }
  50. pub(super) async fn on_receive_part(&mut self, channels: Vec<String>) -> Result<()> {
  51. for chan in channels.iter() {
  52. let part_reply = format!(":{}!anon@dark.fi PART {}\r\n", self.nickname, chan);
  53. self.reply(&part_reply).await?;
  54. if self.configured_chans.contains_key(chan) {
  55. let chan_info = self.configured_chans.get_mut(chan).unwrap();
  56. chan_info.joined = false;
  57. }
  58. }
  59. Ok(())
  60. }
  61. pub(super) async fn on_receive_topic(&mut self, line: &str, channel: &str) -> Result<()> {
  62. if let Some(substr_idx) = line.find(':') {
  63. // Client is setting the topic
  64. if substr_idx >= line.len() {
  65. return Err(Error::MalformedPacket)
  66. }
  67. let topic = &line[substr_idx + 1..];
  68. let chan_info = self.configured_chans.get_mut(channel).unwrap();
  69. chan_info.topic = Some(topic.to_string());
  70. let topic_reply =
  71. format!(":{}!anon@dark.fi TOPIC {} :{}\r\n", self.nickname, channel, topic);
  72. self.reply(&topic_reply).await?;
  73. } else {
  74. // Client is asking or the topic
  75. let chan_info = self.configured_chans.get(channel).unwrap();
  76. let topic_reply = if let Some(topic) = &chan_info.topic {
  77. format!("{} {} {} :{}\r\n", RPL_TOPIC, self.nickname, channel, topic)
  78. } else {
  79. const TOPIC: &str = "No topic is set";
  80. format!("{} {} {} :{}\r\n", RPL_NOTOPIC, self.nickname, channel, TOPIC)
  81. };
  82. self.reply(&topic_reply).await?;
  83. }
  84. Ok(())
  85. }
  86. pub(super) async fn on_ping(&mut self, value: &str) -> Result<()> {
  87. let pong = format!("PONG {}\r\n", value);
  88. self.reply(&pong).await
  89. }
  90. pub(super) async fn on_receive_cap(&mut self, line: &str, subcommand: &str) -> Result<()> {
  91. self.is_cap_end = false;
  92. let capabilities_keys: Vec<String> = self.capabilities.keys().cloned().collect();
  93. match subcommand {
  94. "LS" => {
  95. let cap_ls_reply = format!(
  96. ":{}!anon@dark.fi CAP * LS :{}\r\n",
  97. self.nickname,
  98. capabilities_keys.join(" ")
  99. );
  100. self.reply(&cap_ls_reply).await?;
  101. }
  102. "REQ" => {
  103. let substr_idx = line.find(':').ok_or(Error::MalformedPacket)?;
  104. if substr_idx >= line.len() {
  105. return Err(Error::MalformedPacket)
  106. }
  107. let cap: Vec<&str> = line[substr_idx + 1..].split(' ').collect();
  108. let mut ack_list = vec![];
  109. let mut nak_list = vec![];
  110. for c in cap {
  111. if self.capabilities.contains_key(c) {
  112. self.capabilities.insert(c.to_string(), true);
  113. ack_list.push(c);
  114. } else {
  115. nak_list.push(c);
  116. }
  117. }
  118. let cap_ack_reply = format!(
  119. ":{}!anon@dark.fi CAP * ACK :{}\r\n",
  120. self.nickname,
  121. ack_list.join(" ")
  122. );
  123. let cap_nak_reply = format!(
  124. ":{}!anon@dark.fi CAP * NAK :{}\r\n",
  125. self.nickname,
  126. nak_list.join(" ")
  127. );
  128. self.reply(&cap_ack_reply).await?;
  129. self.reply(&cap_nak_reply).await?;
  130. }
  131. "LIST" => {
  132. let enabled_capabilities: Vec<String> = self
  133. .capabilities
  134. .clone()
  135. .into_iter()
  136. .filter(|(_, v)| *v)
  137. .map(|(k, _)| k)
  138. .collect();
  139. let cap_list_reply = format!(
  140. ":{}!anon@dark.fi CAP * LIST :{}\r\n",
  141. self.nickname,
  142. enabled_capabilities.join(" ")
  143. );
  144. self.reply(&cap_list_reply).await?;
  145. }
  146. "END" => {
  147. self.is_cap_end = true;
  148. }
  149. _ => {}
  150. }
  151. Ok(())
  152. }
  153. pub(super) async fn on_receive_names(&mut self, channels: Vec<String>) -> Result<()> {
  154. for chan in channels.iter() {
  155. if !chan.starts_with('#') {
  156. continue
  157. }
  158. if self.configured_chans.contains_key(chan) {
  159. let chan_info = self.configured_chans.get(chan).unwrap();
  160. if chan_info.names.is_empty() {
  161. return Ok(())
  162. }
  163. let names_reply = format!(
  164. ":{}!anon@dark.fi {} = {} : {}\r\n",
  165. self.nickname,
  166. RPL_NAMEREPLY,
  167. chan,
  168. chan_info.names.join(" ")
  169. );
  170. self.reply(&names_reply).await?;
  171. let end_of_names = format!(
  172. ":DarkFi {:03} {} {} :End of NAMES list\r\n",
  173. RPL_ENDOFNAMES, self.nickname, chan
  174. );
  175. self.reply(&end_of_names).await?;
  176. }
  177. }
  178. Ok(())
  179. }
  180. pub(super) async fn on_receive_privmsg(&mut self, line: &str, target: &str) -> Result<()> {
  181. let substr_idx = line.find(':').ok_or(Error::MalformedPacket)?;
  182. if substr_idx >= line.len() {
  183. return Err(Error::MalformedPacket)
  184. }
  185. let message = line[substr_idx + 1..].to_string();
  186. info!("(Plain) PRIVMSG {} :{}", target, message);
  187. let privmsgs_buffer = self.privmsgs_buffer.lock().await;
  188. let last_term = privmsgs_buffer.last_term() + 1;
  189. drop(privmsgs_buffer);
  190. let mut privmsg = Privmsg::new(&self.nickname, target, &message, last_term);
  191. if target.starts_with('#') {
  192. if !self.configured_chans.contains_key(target) {
  193. return Ok(())
  194. }
  195. let channel_info = self.configured_chans.get(target).unwrap();
  196. if !channel_info.joined {
  197. return Ok(())
  198. }
  199. if let Some(salt_box) = &channel_info.salt_box {
  200. encrypt_privmsg(salt_box, &mut privmsg);
  201. info!("(Encrypted) PRIVMSG: {:?}", privmsg);
  202. }
  203. } else {
  204. if !self.configured_contacts.contains_key(target) {
  205. return Ok(())
  206. }
  207. let contact_info = self.configured_contacts.get(target).unwrap();
  208. if let Some(salt_box) = &contact_info.salt_box {
  209. encrypt_privmsg(salt_box, &mut privmsg);
  210. info!("(Encrypted) PRIVMSG: {:?}", privmsg);
  211. }
  212. }
  213. {
  214. (*self.seen_msg_ids.lock().await).push(privmsg.id);
  215. (*self.privmsgs_buffer.lock().await).push(&privmsg)
  216. }
  217. self.senders.notify_with_exclude(privmsg.clone(), &[self.subscriber_id]).await;
  218. debug!(target: "ircd", "PRIVMSG to be sent: {:?}", privmsg);
  219. self.p2p.broadcast(privmsg).await?;
  220. Ok(())
  221. }
  222. pub(super) async fn on_receive_join(&mut self, channels: Vec<String>) -> Result<()> {
  223. for chan in channels.iter() {
  224. if !chan.starts_with('#') {
  225. continue
  226. }
  227. if !self.configured_chans.contains_key(chan) {
  228. let mut chan_info = ChannelInfo::new()?;
  229. chan_info.topic = Some("n/a".to_string());
  230. self.configured_chans.insert(chan.to_string(), chan_info);
  231. }
  232. let chan_info = self.configured_chans.get_mut(chan).unwrap();
  233. if chan_info.joined {
  234. return Ok(())
  235. }
  236. chan_info.joined = true;
  237. let topic =
  238. if let Some(topic) = chan_info.topic.clone() { topic } else { "n/a".to_string() };
  239. chan_info.topic = Some(topic.to_string());
  240. {
  241. let j = format!(":{}!anon@dark.fi JOIN {}\r\n", self.nickname, chan);
  242. let t = format!(":DarkFi TOPIC {} :{}\r\n", chan, topic);
  243. self.reply(&j).await?;
  244. self.reply(&t).await?;
  245. }
  246. // Send messages in buffer
  247. if !self.capabilities.get("no-history").unwrap() {
  248. for msg in self.privmsgs_buffer.lock().await.iter() {
  249. if msg.target == *chan {
  250. self.senders.notify_by_id(msg.clone(), self.subscriber_id).await;
  251. }
  252. }
  253. }
  254. }
  255. self.on_receive_names(channels).await?;
  256. Ok(())
  257. }
  258. }