rustirc/
client.rs

1use super::event_handler::EventHandler;
2use super::event_manager;
3use super::message_parser;
4use std::error::Error;
5use std::sync::Arc;
6use tokio::io::BufReader;
7use tokio::net::TcpStream;
8use tokio::prelude::*;
9use tokio::sync::Mutex;
10// use tokio::net::tcp::{ReadHalf, WriteHalf};
11
12#[derive(Clone)]
13pub enum ClientState {
14    Uninit,
15    Connecting,
16    Registering,
17    InServer, // Won't add a string since it's known by the connection method and should really get more attention
18    InChannel(String),
19}
20
21pub struct Client {
22    ip: String,
23    port: u16,
24    event_handler: Option<Arc<dyn EventHandler>>,
25    pub state: ClientState,
26    pub stream: Option<Arc<Mutex<IrcStream<TcpStream>>>>,
27}
28
29impl Client {
30    pub fn new(ip: &str, port: u16) -> Client {
31        Client {
32            ip: ip.to_string(),
33            port,
34            event_handler: None,
35            state: ClientState::Uninit,
36            stream: None,
37        }
38    }
39
40    pub fn handler<H: EventHandler + 'static>(mut self, event_handler: H) -> Self {
41        self.event_handler = Some(Arc::new(event_handler));
42        self
43    }
44
45    pub async fn connect(mut self) -> Result<Self, Box<dyn Error>> {
46        self.stream = Some(Arc::new(Mutex::new(
47            IrcStream::connect(&self.ip, self.port).await?,
48        )));
49        self.state = ClientState::Connecting;
50        Ok(self)
51    }
52
53    pub async fn start(&mut self) -> Result<(), Box<dyn Error>> {
54        let event_handler = self.event_handler.take().unwrap();
55
56        loop {
57            let stream = Arc::clone(&self.stream.as_ref().unwrap());
58            let mut s = stream.try_lock().unwrap();
59            let message = s.consume_message().await.unwrap();
60            std::mem::drop(s); // Drop the lock on the stream
61
62            let message = message_parser::parse_message(&message.0).unwrap();
63            if let Err(e) = event_manager::handle_event(self, message, &event_handler).await {
64                eprintln!("Error: {}", e);
65                break;
66            }
67        }
68
69        Ok(())
70    }
71
72    pub async fn register(&mut self, username: &str) -> Result<(), Box<dyn Error>> {
73        send_socket_message(self, &format!("PASS {}", username)).await?;
74        send_socket_message(self, &format!("NICK {}", username)).await?;
75        send_socket_message(self, &format!("USER guest * 0 :{}", username)).await?;
76        Ok(())
77    }
78    pub async fn join_channel(&mut self, name: &str) -> Result<(), Box<dyn Error>> {
79        send_socket_message(self, &format!("JOIN #{}", name)).await?;
80        Ok(())
81    }
82
83    pub async fn send_message(&mut self, msg: String) -> Result<(), Box<dyn Error>> {
84        match self.state.clone() {
85            ClientState::InChannel(name) => {
86                send_socket_message(self, &format!("PRIVMSG #{} {}", &name, msg)).await?;
87            },
88            _ => {
89                panic!("Can't send a message when not in channel!");
90            }
91        }
92        Ok(())
93    }
94
95    pub async fn send_pong(&mut self) -> Result<(), Box<dyn Error>> {
96        send_socket_message(self, "PONG").await?;
97        Ok(())
98    }
99}
100
101pub struct IrcStream<S> {
102    reader: BufReader<S>,
103}
104
105impl IrcStream<TcpStream> {
106    pub async fn connect(peer: &str, port: u16) -> Result<Self, Box<dyn Error>> {
107        let connection = TcpStream::connect(&format!("{}:{}", peer, port)).await?;
108        Ok(IrcStream::new(connection))
109    }
110}
111
112impl<S: AsyncRead + AsyncWrite + Unpin> IrcStream<S> {
113    pub fn new(stream: S) -> Self {
114        IrcStream {
115            reader: BufReader::new(stream),
116        }
117    }
118
119    pub async fn consume_message(&mut self) -> Result<(Vec<u8>, usize), Box<dyn Error>> {
120        let mut buf = Vec::new();
121        let test = self.reader.read_until(b'\n', &mut buf).await?;
122        Ok((buf, test))
123    }
124
125    pub async fn write_all(&mut self, test: &str) -> Result<(), Box<dyn Error>> {
126        self.reader
127            .write(&format!("{}\r\n", test)[..].as_bytes())
128            .await?;
129        Ok(())
130    }
131}
132
133pub async fn send_socket_message(client: &mut Client, msg: &str) -> Result<(), Box<dyn Error>> {
134    let stream = Arc::clone(client.stream.as_ref().unwrap());
135    let mut s = stream.try_lock().unwrap();
136
137    s.write_all(msg).await?;
138    Ok(())
139}