client.rs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  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 async_std::sync::{Arc, Mutex};
  19. use std::net::SocketAddr;
  20. use futures::{
  21. io::{BufReader, ReadHalf, WriteHalf},
  22. AsyncBufReadExt, AsyncRead, AsyncWrite, AsyncWriteExt, FutureExt,
  23. };
  24. use log::{debug, error, info, warn};
  25. use darkfi::{
  26. net::P2pPtr,
  27. system::{SubscriberPtr, Subscription},
  28. Error, Result,
  29. };
  30. use crate::{
  31. buffers::SeenIds,
  32. crypto::{decrypt_privmsg, decrypt_target, encrypt_privmsg},
  33. settings,
  34. settings::RPL,
  35. ChannelInfo, Privmsg,
  36. };
  37. use super::IrcConfig;
  38. pub struct IrcClient<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> {
  39. // network stream
  40. write_stream: WriteHalf<C>,
  41. pub address: SocketAddr,
  42. // msgs buffer
  43. seen: Arc<Mutex<SeenIds>>,
  44. // irc config
  45. irc_config: IrcConfig,
  46. // p2p
  47. p2p: P2pPtr,
  48. notify_clients: SubscriberPtr<Privmsg>,
  49. subscription: Subscription<Privmsg>,
  50. }
  51. impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
  52. pub fn new(
  53. write_stream: WriteHalf<C>,
  54. address: SocketAddr,
  55. seen: Arc<Mutex<SeenIds>>,
  56. irc_config: IrcConfig,
  57. p2p: P2pPtr,
  58. notify_clients: SubscriberPtr<Privmsg>,
  59. subscription: Subscription<Privmsg>,
  60. ) -> Self {
  61. Self { write_stream, address, seen, irc_config, p2p, notify_clients, subscription }
  62. }
  63. /// Start listening for messages came from p2p network or irc client
  64. pub async fn listen(&mut self, mut reader: BufReader<ReadHalf<C>>) {
  65. loop {
  66. let mut line = String::new();
  67. futures::select! {
  68. msg = self.subscription.receive().fuse() => {
  69. if let Err(e) = self.process_msg(&msg).await {
  70. error!("[CLIENT {}] Process msg: {}", self.address, e);
  71. break
  72. }
  73. }
  74. err = reader.read_line(&mut line).fuse() => {
  75. if let Err(e) = err {
  76. error!("[CLIENT {}] Read line error: {}", self.address, e);
  77. break
  78. }
  79. if let Err(e) = self.process_line(line).await {
  80. error!("[CLIENT {}] Process line failed: {}", self.address, e);
  81. break
  82. }
  83. }
  84. }
  85. }
  86. warn!("[CLIENT {}] Close connection", self.address);
  87. self.subscription.unsubscribe().await;
  88. }
  89. pub async fn process_msg(&mut self, msg: &Privmsg) -> Result<()> {
  90. info!("[P2P] Received: {:?}", msg);
  91. let mut msg = msg.clone();
  92. let mut contact = String::new();
  93. decrypt_target(
  94. &mut contact,
  95. &mut msg,
  96. self.irc_config.configured_chans.clone(),
  97. self.irc_config.configured_contacts.clone(),
  98. );
  99. if msg.target.starts_with('#') {
  100. // Try to potentially decrypt the incoming message.
  101. if !self.irc_config.configured_chans.contains_key(&msg.target) {
  102. return Ok(())
  103. }
  104. let chan_info = self.irc_config.configured_chans.get_mut(&msg.target).unwrap();
  105. if !chan_info.joined {
  106. return Ok(())
  107. }
  108. if let Some(salt_box) = &chan_info.salt_box {
  109. decrypt_privmsg(salt_box, &mut msg);
  110. info!("Decrypted received message: {:?}", msg);
  111. }
  112. // add the nickname to the channel's names
  113. if !chan_info.names.contains(&msg.nickname) {
  114. chan_info.names.push(msg.nickname.clone());
  115. }
  116. self.reply(&msg.to_string()).await?;
  117. } else if self.irc_config.is_cap_end && self.irc_config.is_nick_init {
  118. if !self.irc_config.configured_contacts.contains_key(&contact) {
  119. return Ok(())
  120. }
  121. let contact_info = self.irc_config.configured_contacts.get(&contact).unwrap();
  122. if let Some(salt_box) = &contact_info.salt_box {
  123. decrypt_privmsg(salt_box, &mut msg);
  124. // This is for /query
  125. msg.nickname = contact;
  126. info!("[P2P] Decrypted received message: {:?}", msg);
  127. }
  128. self.reply(&msg.to_string()).await?;
  129. }
  130. Ok(())
  131. }
  132. pub async fn process_line(&mut self, line: String) -> Result<()> {
  133. let irc_msg = match clean_input_line(line) {
  134. Ok(msg) => msg,
  135. Err(e) => {
  136. warn!("[CLIENT {}] Connection error: {}", self.address, e);
  137. return Err(Error::ChannelStopped)
  138. }
  139. };
  140. info!("[CLIENT {}] Msg: {}", self.address, irc_msg);
  141. if let Err(e) = self.update(irc_msg).await {
  142. warn!("[CLIENT {}] Connection error: {}", self.address, e);
  143. return Err(Error::ChannelStopped)
  144. }
  145. Ok(())
  146. }
  147. async fn update(&mut self, line: String) -> Result<()> {
  148. if line.len() > settings::MAXIMUM_LENGTH_OF_MESSAGE {
  149. return Err(Error::MalformedPacket)
  150. }
  151. if self.irc_config.password.is_empty() {
  152. self.irc_config.is_pass_init = true
  153. }
  154. let (command, value) = parse_line(&line)?;
  155. let (command, value) = (command.as_str(), value.as_str());
  156. match command {
  157. "PASS" => self.on_receive_pass(value).await?,
  158. "USER" => self.on_receive_user().await?,
  159. "NAMES" => self.on_receive_names(value.split(',').map(String::from).collect()).await?,
  160. "NICK" => self.on_receive_nick(value).await?,
  161. "JOIN" => self.on_receive_join(value.split(',').map(String::from).collect()).await?,
  162. "PART" => self.on_receive_part(value.split(',').map(String::from).collect()).await?,
  163. "TOPIC" => self.on_receive_topic(&line, value).await?,
  164. "PING" => self.on_ping(value).await?,
  165. "PRIVMSG" => self.on_receive_privmsg(&line, value).await?,
  166. "CAP" => self.on_receive_cap(&line, &value.to_uppercase()).await?,
  167. "QUIT" => self.on_quit()?,
  168. _ => warn!("[CLIENT {}] Unimplemented `{}` command", self.address, command),
  169. }
  170. self.registre().await?;
  171. Ok(())
  172. }
  173. async fn registre(&mut self) -> Result<()> {
  174. if !self.irc_config.is_registered &&
  175. self.irc_config.is_cap_end &&
  176. self.irc_config.is_nick_init &&
  177. self.irc_config.is_user_init
  178. {
  179. debug!("Initializing peer connection");
  180. let register_reply =
  181. format!(":darkfi 001 {} :Let there be dark\r\n", self.irc_config.nickname);
  182. self.reply(&register_reply).await?;
  183. self.irc_config.is_registered = true;
  184. // join all channels
  185. self.on_receive_join(self.irc_config.auto_channels.clone()).await?;
  186. self.on_receive_join(self.irc_config.configured_chans.keys().cloned().collect())
  187. .await?;
  188. if *self.irc_config.capabilities.get("no-history").unwrap() {
  189. return Ok(())
  190. }
  191. }
  192. Ok(())
  193. }
  194. async fn reply(&mut self, message: &str) -> Result<()> {
  195. self.write_stream.write_all(message.as_bytes()).await?;
  196. debug!("Sent {}", message.trim_end());
  197. Ok(())
  198. }
  199. fn on_quit(&self) -> Result<()> {
  200. // Close the connection
  201. Err(Error::NetworkServiceStopped)
  202. }
  203. async fn on_receive_user(&mut self) -> Result<()> {
  204. // We can stuff any extra things like public keys in here.
  205. // Ignore it for now.
  206. if self.irc_config.is_pass_init {
  207. self.irc_config.is_user_init = true;
  208. } else {
  209. // Close the connection
  210. warn!("[CLIENT {}] Password is required", self.address);
  211. return self.on_quit()
  212. }
  213. Ok(())
  214. }
  215. async fn on_receive_pass(&mut self, password: &str) -> Result<()> {
  216. if self.irc_config.password == password {
  217. self.irc_config.is_pass_init = true
  218. } else {
  219. // Close the connection
  220. warn!("[CLIENT {}] Password is not correct!", self.address);
  221. return self.on_quit()
  222. }
  223. Ok(())
  224. }
  225. async fn on_receive_nick(&mut self, nickname: &str) -> Result<()> {
  226. if nickname.len() > settings::MAXIMUM_LENGTH_OF_NICKNAME {
  227. return Ok(())
  228. }
  229. self.irc_config.is_nick_init = true;
  230. let old_nick = std::mem::replace(&mut self.irc_config.nickname, nickname.to_string());
  231. let nick_reply =
  232. format!(":{}!anon@dark.fi NICK {}\r\n", old_nick, self.irc_config.nickname);
  233. self.reply(&nick_reply).await
  234. }
  235. async fn on_receive_part(&mut self, channels: Vec<String>) -> Result<()> {
  236. for chan in channels.iter() {
  237. let part_reply =
  238. format!(":{}!anon@dark.fi PART {}\r\n", self.irc_config.nickname, chan);
  239. self.reply(&part_reply).await?;
  240. if self.irc_config.configured_chans.contains_key(chan) {
  241. let chan_info = self.irc_config.configured_chans.get_mut(chan).unwrap();
  242. chan_info.joined = false;
  243. }
  244. }
  245. Ok(())
  246. }
  247. async fn on_receive_topic(&mut self, line: &str, channel: &str) -> Result<()> {
  248. if let Some(substr_idx) = line.find(':') {
  249. // Client is setting the topic
  250. if substr_idx >= line.len() {
  251. return Err(Error::MalformedPacket)
  252. }
  253. let topic = &line[substr_idx + 1..];
  254. let chan_info = self.irc_config.configured_chans.get_mut(channel).unwrap();
  255. chan_info.topic = Some(topic.to_string());
  256. let topic_reply = format!(
  257. ":{}!anon@dark.fi TOPIC {} :{}\r\n",
  258. self.irc_config.nickname, channel, topic
  259. );
  260. self.reply(&topic_reply).await?;
  261. } else {
  262. // Client is asking or the topic
  263. let chan_info = self.irc_config.configured_chans.get(channel).unwrap();
  264. let topic_reply = if let Some(topic) = &chan_info.topic {
  265. format!(
  266. "{} {} {} :{}\r\n",
  267. RPL::Topic as u32,
  268. self.irc_config.nickname,
  269. channel,
  270. topic
  271. )
  272. } else {
  273. const TOPIC: &str = "No topic is set";
  274. format!(
  275. "{} {} {} :{}\r\n",
  276. RPL::NoTopic as u32,
  277. self.irc_config.nickname,
  278. channel,
  279. TOPIC
  280. )
  281. };
  282. self.reply(&topic_reply).await?;
  283. }
  284. Ok(())
  285. }
  286. async fn on_ping(&mut self, value: &str) -> Result<()> {
  287. let pong = format!("PONG {}\r\n", value);
  288. self.reply(&pong).await
  289. }
  290. async fn on_receive_cap(&mut self, line: &str, subcommand: &str) -> Result<()> {
  291. self.irc_config.is_cap_end = false;
  292. let capabilities_keys: Vec<String> = self.irc_config.capabilities.keys().cloned().collect();
  293. match subcommand {
  294. "LS" => {
  295. let cap_ls_reply = format!(
  296. ":{}!anon@dark.fi CAP * LS :{}\r\n",
  297. self.irc_config.nickname,
  298. capabilities_keys.join(" ")
  299. );
  300. self.reply(&cap_ls_reply).await?;
  301. }
  302. "REQ" => {
  303. let substr_idx = line.find(':').ok_or(Error::MalformedPacket)?;
  304. if substr_idx >= line.len() {
  305. return Err(Error::MalformedPacket)
  306. }
  307. let cap: Vec<&str> = line[substr_idx + 1..].split(' ').collect();
  308. let mut ack_list = vec![];
  309. let mut nak_list = vec![];
  310. for c in cap {
  311. if self.irc_config.capabilities.contains_key(c) {
  312. self.irc_config.capabilities.insert(c.to_string(), true);
  313. ack_list.push(c);
  314. } else {
  315. nak_list.push(c);
  316. }
  317. }
  318. let cap_ack_reply = format!(
  319. ":{}!anon@dark.fi CAP * ACK :{}\r\n",
  320. self.irc_config.nickname,
  321. ack_list.join(" ")
  322. );
  323. let cap_nak_reply = format!(
  324. ":{}!anon@dark.fi CAP * NAK :{}\r\n",
  325. self.irc_config.nickname,
  326. nak_list.join(" ")
  327. );
  328. self.reply(&cap_ack_reply).await?;
  329. self.reply(&cap_nak_reply).await?;
  330. }
  331. "LIST" => {
  332. let enabled_capabilities: Vec<String> = self
  333. .irc_config
  334. .capabilities
  335. .clone()
  336. .into_iter()
  337. .filter(|(_, v)| *v)
  338. .map(|(k, _)| k)
  339. .collect();
  340. let cap_list_reply = format!(
  341. ":{}!anon@dark.fi CAP * LIST :{}\r\n",
  342. self.irc_config.nickname,
  343. enabled_capabilities.join(" ")
  344. );
  345. self.reply(&cap_list_reply).await?;
  346. }
  347. "END" => {
  348. self.irc_config.is_cap_end = true;
  349. }
  350. _ => {}
  351. }
  352. Ok(())
  353. }
  354. async fn on_receive_names(&mut self, channels: Vec<String>) -> Result<()> {
  355. for chan in channels.iter() {
  356. if !chan.starts_with('#') {
  357. continue
  358. }
  359. if self.irc_config.configured_chans.contains_key(chan) {
  360. let chan_info = self.irc_config.configured_chans.get(chan).unwrap();
  361. if chan_info.names.is_empty() {
  362. return Ok(())
  363. }
  364. let names_reply = format!(
  365. ":{}!anon@dark.fi {} = {} : {}\r\n",
  366. self.irc_config.nickname,
  367. RPL::NameReply as u32,
  368. chan,
  369. chan_info.names.join(" ")
  370. );
  371. self.reply(&names_reply).await?;
  372. let end_of_names = format!(
  373. ":DarkFi {:03} {} {} :End of NAMES list\r\n",
  374. RPL::EndOfNames as u32,
  375. self.irc_config.nickname,
  376. chan
  377. );
  378. self.reply(&end_of_names).await?;
  379. }
  380. }
  381. Ok(())
  382. }
  383. async fn on_receive_privmsg(&mut self, line: &str, target: &str) -> Result<()> {
  384. let substr_idx = line.find(':').ok_or(Error::MalformedPacket)?;
  385. if substr_idx >= line.len() {
  386. return Err(Error::MalformedPacket)
  387. }
  388. let message = line[substr_idx + 1..].to_string();
  389. info!("[CLIENT {}] (Plain) PRIVMSG {} :{}", self.address, target, message,);
  390. let mut privmsg = Privmsg::new(&self.irc_config.nickname, target, &message, 0);
  391. if target.starts_with('#') {
  392. if !self.irc_config.configured_chans.contains_key(target) {
  393. return Ok(())
  394. }
  395. let channel_info = self.irc_config.configured_chans.get(target).unwrap();
  396. if !channel_info.joined {
  397. return Ok(())
  398. }
  399. if let Some(salt_box) = &channel_info.salt_box {
  400. encrypt_privmsg(salt_box, &mut privmsg);
  401. info!("[CLIENT {}] (Encrypted) PRIVMSG: {:?}", self.address, privmsg);
  402. }
  403. } else {
  404. if !self.irc_config.configured_contacts.contains_key(target) {
  405. return Ok(())
  406. }
  407. let contact_info = self.irc_config.configured_contacts.get(target).unwrap();
  408. if let Some(salt_box) = &contact_info.salt_box {
  409. encrypt_privmsg(salt_box, &mut privmsg);
  410. info!("[CLIENT {}] (Encrypted) PRIVMSG: {:?}", self.address, privmsg);
  411. }
  412. }
  413. {
  414. let ids = &mut self.seen.lock().await;
  415. ids.push(privmsg.id);
  416. }
  417. self.notify_clients
  418. .notify_with_exclude(privmsg.clone(), &[self.subscription.get_id()])
  419. .await;
  420. info!("[P2P] Broadcast: {:?}", privmsg);
  421. self.p2p.broadcast(privmsg).await?;
  422. Ok(())
  423. }
  424. async fn on_receive_join(&mut self, channels: Vec<String>) -> Result<()> {
  425. for chan in channels.iter() {
  426. if !chan.starts_with('#') {
  427. continue
  428. }
  429. if !self.irc_config.configured_chans.contains_key(chan) {
  430. let mut chan_info = ChannelInfo::new()?;
  431. chan_info.topic = Some("n/a".to_string());
  432. self.irc_config.configured_chans.insert(chan.to_string(), chan_info);
  433. }
  434. let chan_info = self.irc_config.configured_chans.get_mut(chan).unwrap();
  435. if chan_info.joined {
  436. return Ok(())
  437. }
  438. chan_info.joined = true;
  439. let topic =
  440. if let Some(topic) = chan_info.topic.clone() { topic } else { "n/a".to_string() };
  441. chan_info.topic = Some(topic.to_string());
  442. {
  443. let j = format!(":{}!anon@dark.fi JOIN {}\r\n", self.irc_config.nickname, chan);
  444. let t = format!(":DarkFi TOPIC {} :{}\r\n", chan, topic);
  445. self.reply(&j).await?;
  446. self.reply(&t).await?;
  447. }
  448. }
  449. Ok(())
  450. }
  451. }
  452. //
  453. // Helper functions
  454. //
  455. fn clean_input_line(mut line: String) -> Result<String> {
  456. if line.is_empty() {
  457. return Err(Error::ChannelStopped)
  458. }
  459. if line == "\n" || line == "\r\n" {
  460. return Err(Error::ChannelStopped)
  461. }
  462. if &line[(line.len() - 2)..] == "\r\n" {
  463. // Remove CRLF
  464. line.pop();
  465. line.pop();
  466. } else if &line[(line.len() - 1)..] == "\n" {
  467. line.pop();
  468. } else {
  469. return Err(Error::ChannelStopped)
  470. }
  471. Ok(line.clone())
  472. }
  473. fn parse_line(line: &str) -> Result<(String, String)> {
  474. let mut tokens = line.split_ascii_whitespace();
  475. // Commands can begin with :garbage but we will reject clients doing
  476. // that for now to keep the protocol simple and focused.
  477. let command = tokens.next().ok_or(Error::MalformedPacket)?.to_uppercase();
  478. let value = tokens.next().ok_or(Error::MalformedPacket)?;
  479. Ok((command, value.to_owned()))
  480. }