server.rs 4.7 KB

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