server.rs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. use async_std::net::TcpStream;
  2. use futures::{io::WriteHalf, AsyncWriteExt};
  3. use log::{debug, info, warn};
  4. use rand::{rngs::OsRng, RngCore};
  5. use darkfi::{Error, Result};
  6. use crate::{privmsg::Privmsg, SeenMsgIds};
  7. pub struct IrcServerConnection {
  8. write_stream: WriteHalf<TcpStream>,
  9. is_nick_init: bool,
  10. is_user_init: bool,
  11. is_registered: bool,
  12. nickname: String,
  13. _channels: Vec<String>,
  14. seen_msg_id: SeenMsgIds,
  15. p2p_sender: async_channel::Sender<Privmsg>,
  16. }
  17. impl IrcServerConnection {
  18. pub fn new(
  19. write_stream: WriteHalf<TcpStream>,
  20. seen_msg_id: SeenMsgIds,
  21. p2p_sender: async_channel::Sender<Privmsg>,
  22. ) -> Self {
  23. Self {
  24. write_stream,
  25. is_nick_init: false,
  26. is_user_init: false,
  27. is_registered: false,
  28. nickname: "".to_string(),
  29. _channels: vec![],
  30. seen_msg_id,
  31. p2p_sender,
  32. }
  33. }
  34. pub async fn update(&mut self, line: String) -> Result<()> {
  35. let mut tokens = line.split_ascii_whitespace();
  36. // Commands can begin with :garbage but we will reject clients doing
  37. // that for now to keep the protocol simple and focused.
  38. let command = tokens.next().ok_or(Error::MalformedPacket)?;
  39. info!("Received command: {}", command);
  40. match command {
  41. "USER" => {
  42. // We can stuff any extra things like public keys in here.
  43. // Ignore it for now.
  44. self.is_user_init = true;
  45. }
  46. "NICK" => {
  47. let nickname = tokens.next().ok_or(Error::MalformedPacket)?;
  48. self.is_nick_init = true;
  49. let old_nick = std::mem::replace(&mut self.nickname, nickname.to_string());
  50. let nick_reply = format!(":{}!anon@dark.fi NICK {}\r\n", old_nick, self.nickname);
  51. self.reply(&nick_reply).await?;
  52. }
  53. "JOIN" => {
  54. // Ignore since channels are all autojoin
  55. // let channel = tokens.next().ok_or(Error::MalformedPacket)?;
  56. // self.channels.push(channel.to_string());
  57. // let join_reply = format!(":{}!anon@dark.fi JOIN {}\r\n", self.nickname, channel);
  58. // self.reply(&join_reply).await?;
  59. // self.write_stream.write_all(b":f00!f00@127.0.01 PRIVMSG #dev :y0\r\n").await?;
  60. }
  61. "PING" => {
  62. let line_clone = line.clone();
  63. let split_line: Vec<&str> = line_clone.split_whitespace().collect();
  64. if split_line.len() > 1 && split_line[0] == "PING" {
  65. let pong = format!("PONG {}\r\n", split_line[1]);
  66. self.reply(&pong).await?;
  67. }
  68. }
  69. "PRIVMSG" => {
  70. let channel = tokens.next().ok_or(Error::MalformedPacket)?;
  71. let substr_idx = line.find(':').ok_or(Error::MalformedPacket)?;
  72. if substr_idx >= line.len() {
  73. return Err(Error::MalformedPacket)
  74. }
  75. let message = &line[substr_idx + 1..];
  76. info!("Message {}: {}", channel, message);
  77. let random_id = OsRng.next_u32();
  78. let protocol_msg = Privmsg {
  79. id: random_id,
  80. nickname: self.nickname.clone(),
  81. channel: channel.to_string(),
  82. message: message.to_string(),
  83. };
  84. let mut smi = self.seen_msg_id.lock().await;
  85. smi.push(random_id);
  86. drop(smi);
  87. self.p2p_sender.send(protocol_msg).await?;
  88. }
  89. "QUIT" => {
  90. // Close the connection
  91. return Err(Error::ServiceStopped)
  92. }
  93. _ => {
  94. warn!("Unimplemented `{}` command", command);
  95. }
  96. }
  97. if !self.is_registered && self.is_nick_init && self.is_user_init {
  98. debug!("Initializing peer connection");
  99. let register_reply = format!(":darkfi 001 {} :Let there be dark\r\n", self.nickname);
  100. self.reply(&register_reply).await?;
  101. self.is_registered = true;
  102. // Auto-joins
  103. macro_rules! autojoin {
  104. ($channel:expr,$topic:expr) => {
  105. let j = format!(":{}!anon@dark.fi JOIN {}\r\n", self.nickname, $channel);
  106. let t = format!(":DarkFi TOPIC {} :{}\r\n", $channel, $topic);
  107. self.reply(&j).await?;
  108. self.reply(&t).await?;
  109. };
  110. }
  111. autojoin!("#dev", "Development of DarkFi");
  112. autojoin!("#markets", "Markets, trading, DeFi, algo, biz, finance, and economics");
  113. autojoin!("#memes", "Memetic engineering");
  114. }
  115. Ok(())
  116. }
  117. pub async fn reply(&mut self, message: &str) -> Result<()> {
  118. self.write_stream.write_all(message.as_bytes()).await?;
  119. debug!("Sent {}", message);
  120. Ok(())
  121. }
  122. }