Advertisement
Guest User

Untitled

a guest
Oct 14th, 2019
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.72 KB | None | 0 0
  1. use std::io::{Read, Write};
  2. use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener, TcpStream};
  3. use std::str;
  4. use std::sync::{Arc, Mutex};
  5. use std::thread;
  6. use std::vec::Vec;
  7.  
  8. const VERSION: &str = "FC1";
  9.  
  10. fn data_parser(data: String) -> (String, String) {
  11. let mut words = data.split_whitespace();
  12. let command = words.next().unwrap().to_string();
  13. let mut chars = data.chars();
  14. for character in chars.by_ref() {
  15. if character.is_whitespace() {
  16. break;
  17. }
  18. }
  19. let options = chars.as_str().to_string();
  20. return (command, options);
  21. }
  22.  
  23. fn send_parser(options: String) -> (String, String) {
  24. let mut words = options.split(":");
  25. let userid = words.next().unwrap().to_string();
  26. let mut chars = options.chars();
  27. for character in chars.by_ref() {
  28. if character == ':' {
  29. break;
  30. }
  31. }
  32. let message = chars.as_str().to_string();
  33. return (userid, message);
  34. }
  35.  
  36. fn send_message(
  37. client: &ClientHandler,
  38. userid: String,
  39. message: String,
  40. clients: Arc<Mutex<Vec<Client>>>,
  41. ) -> Result<(), ()> {
  42. let clients_lock = clients.lock().unwrap();
  43. let from = clients_lock.get_client_by_ip(client.socket_addr).unwrap();
  44. let to = match clients_lock.get_client_by_userid(userid.clone()) {
  45. Some(to) => Some(to),
  46. None => match clients_lock.get_client_by_username(userid.clone()) {
  47. Some(to) => Some(to),
  48. None => None,
  49. },
  50. };
  51. match to {
  52. Some(to) => {
  53. // println!("{:#?}", message);
  54. let send = format!("RECV {}:{}", from.id, message);
  55. if to.id == 0 {
  56. for c in clients_lock.iter() {
  57. match c.stream.try_clone().unwrap().write(send.as_bytes()) {
  58. Ok(_) => {} // do nothing
  59. Err(_) => println!("error, message failed to send to {:#?}", c),
  60. }
  61. }
  62. }
  63. let _ = to.stream.try_clone().unwrap().write(send.as_bytes());
  64. Ok(())
  65. }
  66. None => Err(()),
  67. }
  68. }
  69.  
  70. fn whoo(mut stream: TcpStream, clients: Arc<Mutex<Vec<Client>>>) -> Result<(), ()> {
  71. let client_lock = clients.lock().unwrap();
  72. for c in client_lock.iter() {
  73. let send = format!("CONN {}:{}\n", c.id, c.username);
  74. let _ = stream.write(send.as_bytes());
  75. }
  76. Err(())
  77. }
  78.  
  79. fn handle_client(
  80. mut stream: TcpStream,
  81. clients: Arc<Mutex<Vec<Client>>>,
  82. id: Arc<Mutex<Vec<usize>>>, // stack to keep track of user ids
  83. ) {
  84. let mut data = [0 as u8; 256]; // using 256 byte buffer
  85. let client = ClientHandler {
  86. client_list: clients.clone(),
  87. socket_addr: stream.peer_addr().unwrap(),
  88. };
  89. 'connection: while match stream.read(&mut data) {
  90. // close connection when the client disconnects
  91. Ok(0) => {
  92. println!("closing connection. client disconnected");
  93. break 'connection;
  94. }
  95. Ok(_) => {
  96. let (command, options_string) = data_parser(str::from_utf8(&data).unwrap().to_string());
  97. // println!("{:#?}", str::from_utf8(&data).unwrap().to_string());
  98. let command = &*command;
  99. // let options = &*options_string;
  100. // deref our strings
  101.  
  102. let mut words = options_string.split_whitespace();
  103.  
  104. let connected = clients.lock().unwrap().connected(client.socket_addr);
  105. if connected {
  106. match command {
  107. "GDBY" => break 'connection, // graceful disconnect
  108. "SEND" => {
  109. let (userid, message) = send_parser(options_string);
  110. let _ = send_message(&client, userid, message, clients.clone());
  111. }
  112. "WHOO" => {
  113. let _ = whoo(stream.try_clone().unwrap(), clients.clone());
  114. }
  115. _ => break 'connection,
  116. }
  117. } else {
  118. match command {
  119. "LOGN" => {
  120. let mut c = Client {
  121. stream: stream.try_clone().unwrap(),
  122. ip: client.socket_addr,
  123. username: words.next().unwrap().to_string(),
  124. id: 999,
  125. version: words.next().unwrap().to_string(),
  126. };
  127. if VERSION == c.version {
  128. let user_id = match id.lock() {
  129. Ok(mut id) => id.pop().unwrap(),
  130. Err(_) => 999,
  131. // default user id is 999
  132. };
  133. c.id = user_id;
  134.  
  135. // set the correct user id if we're letting the client connect
  136.  
  137. println!("client authenticated: {:#?}", c);
  138. clients.lock().unwrap().add_client(c);
  139.  
  140. stream
  141. .write(format!("SUCC {}\n", user_id).as_bytes())
  142. .unwrap();
  143. } else {
  144. println!("closing connection. client has different version");
  145. break 'connection;
  146. } // only accept client if they're using the same version as us
  147. } // client authentication
  148. _ => {
  149. println!("closing connection. invalid command");
  150. break 'connection;
  151. }
  152. }
  153. } // don't allow clients to authenticate more than once
  154.  
  155. // println!("{}", str::from_utf8(&data).unwrap());
  156. // println!("clients: {:#?}", clients);
  157. // debug
  158. data = [0 as u8; 256]; // clear the buffer on each iteration
  159. true
  160. }
  161. Err(_) => {
  162. println!(
  163. "An error occurred, terminating connection with {}",
  164. client.socket_addr
  165. );
  166. break 'connection;
  167. }
  168. } {}
  169. }
  170.  
  171. #[derive(Debug)]
  172. struct Client {
  173. ip: SocketAddr,
  174. stream: TcpStream,
  175. username: String,
  176. id: usize,
  177. version: String,
  178. }
  179.  
  180. struct ClientHandler {
  181. client_list: Arc<Mutex<Vec<Client>>>,
  182. socket_addr: SocketAddr,
  183. }
  184.  
  185. impl Drop for ClientHandler {
  186. fn drop(&mut self) {
  187. match self.client_list.lock() {
  188. Ok(mut client_list_lock) => {
  189. match client_list_lock.get_client_by_ip(self.socket_addr) {
  190. Some(c) => client_list_lock.remove_client(c),
  191. None => {}
  192. }
  193. // so we can remove it
  194. }
  195. Err(_) => (),
  196. }
  197. }
  198. } // automatically drop connections when clients go out of scope
  199.  
  200. impl PartialEq for Client {
  201. fn eq(&self, other: &Self) -> bool {
  202. self.ip == other.ip
  203. }
  204. }
  205.  
  206. trait ClientMethods {
  207. fn connected(&self, ip: SocketAddr) -> bool;
  208. fn get_client_by_username(&self, username: String) -> Option<&Client>;
  209. fn get_client_by_userid(&self, username: String) -> Option<&Client>;
  210. fn get_client_by_ip(&self, ip: SocketAddr) -> Option<&Client>;
  211. fn add_client(&mut self, client: Client);
  212. fn send_conn(&self, client: &Client);
  213. fn remove_client(&mut self, client: &Client);
  214. fn send_disc(&self, client: &Client);
  215. fn get_client_index(&self, client: &Client) -> Option<usize>;
  216. }
  217.  
  218. impl ClientMethods for Vec<Client> {
  219. fn get_client_by_ip(&self, ip: SocketAddr) -> Option<&Client> {
  220. for c in self.iter() {
  221. if c.ip == ip {
  222. return Some(c);
  223. } // client found
  224. }
  225. None
  226. }
  227.  
  228. fn connected(&self, ip: SocketAddr) -> bool {
  229. match self.get_client_by_ip(ip) {
  230. Some(_) => true,
  231. None => false,
  232. }
  233. }
  234. fn get_client_by_username(&self, username: String) -> Option<&Client> {
  235. for c in self.iter() {
  236. if c.username == username {
  237. return Some(c);
  238. }
  239. }
  240. None
  241. }
  242. fn get_client_by_userid(&self, user_id: String) -> Option<&Client> {
  243. for c in self.iter() {
  244. if c.id.to_string() == user_id {
  245. return Some(c);
  246. }
  247. }
  248. None
  249. }
  250.  
  251. fn add_client(&mut self, client: Client) {
  252. &self.send_conn(&client);
  253. &self.push(client);
  254. }
  255.  
  256. fn send_conn(&self, client: &Client) {
  257. let send = format!("CONN {}:{}\n", client.id, client.username);
  258. for c in self.iter() {
  259. if c.id != client.id {
  260. c.stream
  261. .try_clone()
  262. .unwrap()
  263. .write(send.as_bytes())
  264. .unwrap();
  265. }
  266. } // only send to clients other than the connecting client
  267. }
  268.  
  269. fn get_client_index(&self, client: &Client) -> Option<usize> {
  270. self.iter()
  271. .position(|client_list| client_list.id == client.id)
  272. }
  273.  
  274. fn remove_client(&mut self, client: &Client) {
  275. match self.get_client_index(&client) {
  276. Some(i) => {
  277. &self.send_disc(&client);
  278. &self.remove(i);
  279. }
  280. None => {}
  281. } // remove the client and tell other clients they disconnected
  282. }
  283.  
  284. fn send_disc(&self, client: &Client) {
  285. let id = client.id;
  286. let send = format!("DISC {}\n", client.id);
  287. for c in self.iter() {
  288. c.stream
  289. .try_clone()
  290. .unwrap()
  291. .write(send.as_bytes())
  292. .unwrap();
  293. }
  294. }
  295. }
  296.  
  297. fn main() {
  298. let listener = TcpListener::bind("127.0.0.1:3333").unwrap();
  299. let clients = Arc::new(Mutex::new(vec![Client {
  300. stream: TcpStream::connect("127.0.0.1:3333").unwrap(),
  301. ip: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 0),
  302. id: 0,
  303. username: "root".to_string(),
  304. version: VERSION.to_string(),
  305. }]));
  306. let max_id = 100;
  307. let user_id = Arc::new(Mutex::new((1..max_id).rev().collect()));
  308. // accept connections and process them, spawning a new thread for each one
  309. println!("Server listening on port 3333");
  310. for stream in listener.incoming() {
  311. match stream {
  312. Ok(stream) => {
  313. let clients = clients.clone();
  314. let user_id = user_id.clone();
  315. println!("New connection: {}", stream.peer_addr().unwrap());
  316. thread::spawn(move || {
  317. // connection succeeded
  318. handle_client(stream, clients, user_id)
  319. });
  320. }
  321. Err(e) => {
  322. println!("Error: {}", e);
  323. /* connection failed */
  324. }
  325. }
  326. }
  327. // close the socket server
  328. drop(listener);
  329. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement