1use std::convert::TryInto;
2use std::io::Read;
3use std::io::Write;
4use std::net::TcpStream;
5use std::str::from_utf8;
6use std::sync::atomic::{AtomicBool, AtomicI32, Ordering::Relaxed};
7
8const HEADER_LEN: usize = 10;
9const MAX_PACKET: usize = 4110;
10
11#[repr(i32)]
12pub enum PacketType {
13 Response,
14 _None,
15 Cmd,
16 Auth,
17}
18
19#[derive(Debug)]
27pub struct Packet {
28 pub len: i32,
30 pub id: i32,
32 pub packet_type: i32,
34 pub body: String,
36}
37
38pub struct Client {
48 conn: TcpStream,
50 next: AtomicI32,
52 auth: AtomicBool,
54}
55
56impl Client {
57 pub fn new(host: &str, port: &str) -> Client {
59 let conn =
60 TcpStream::connect(format!("{}:{}", host, port)).expect("failed to open tcp stream");
61
62 Client {
63 conn,
64 next: AtomicI32::new(0),
65 auth: AtomicBool::new(false),
66 }
67 }
68
69 pub fn auth(&mut self, password: &str) -> Result<(), ()> {
71 self.send(password, Some(PacketType::Auth))?;
72 self.auth = AtomicBool::new(true);
73 let mut response = [0u8; MAX_PACKET];
74 self.conn.read(&mut response).unwrap();
75 let _ = Packet::decode(response.to_vec());
76 Ok(())
77 }
78
79 fn next_id(&mut self) -> i32 {
81 let new = self.next.load(Relaxed) + 1;
82 self.next.store(new, Relaxed);
83 new
84 }
85
86 pub fn send(&mut self, cmd: &str, msg_type: Option<PacketType>) -> Result<(), ()> {
88 let msg_type = match msg_type {
89 Some(v) => v,
90 None => PacketType::Cmd,
91 };
92 let message = Packet {
93 len: (cmd.len() + HEADER_LEN) as i32,
94 id: self.next_id(),
95 packet_type: msg_type as i32,
96 body: cmd.to_string(),
97 };
98
99 self.conn.write_all(&message.encode()).unwrap();
100 Ok(())
101 }
102}
103
104impl Packet {
105
106 pub fn encode(&self) -> Vec<u8> {
108 let mut data: Vec<u8> = Vec::new();
109
110 let p = self;
111
112 let extends = vec![
113 p.len.to_le_bytes(),
114 p.id.to_le_bytes(),
115 p.packet_type.to_le_bytes(),
116 ];
117
118 for i in extends {
119 data.extend_from_slice(&i);
120 }
121
122 data.extend_from_slice(&p.body.as_bytes());
123 data.extend_from_slice(&[0, 0]);
124
125 data
126 }
127
128 pub fn decode(data: Vec<u8>) -> Packet {
130 let len = i32::from_le_bytes(data[0..4].try_into().unwrap());
131 let id = i32::from_le_bytes(data[0..4].try_into().unwrap());
132 let packet_type = i32::from_le_bytes(data[8..12].try_into().unwrap());
133
134 let mut body = "".to_string();
135 let body_len: usize = (len - 10).try_into().unwrap();
136
137 if body_len > 0 {
138 body = from_utf8(&data[12..12 + body_len]).unwrap().to_string();
139 }
140
141 Packet {
142 len,
143 id,
144 packet_type,
145 body,
146 }
147 }
148}