server.rs 4.9 KB

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