use std::sync::mpsc; use mio; use config; use control::{ControlRequest, ControlResponse}; use proto::{Response, Request}; use proto::server::*; pub enum IncomingMessage { ProtoResponse(Response), ControlRequest(ControlRequest), } #[derive(Debug, Clone, Copy)] enum State { NotLoggedIn, LoggingIn, LoggedIn, } pub struct Client { state: State, rx: mpsc::Receiver, proto_tx: mio::Sender, control_tx: mpsc::Sender, } impl Client { pub fn new( rx: mpsc::Receiver, proto_tx: mio::Sender, control_tx: mpsc::Sender) -> Self { Client { state: State::NotLoggedIn, rx: rx, proto_tx: proto_tx, control_tx: control_tx, } } pub fn run(&mut self) { info!("Logging in..."); self.state = State::LoggingIn; let server_request = ServerRequest::LoginRequest(LoginRequest::new( config::USERNAME, config::PASSWORD, config::VER_MAJOR, config::VER_MINOR, ).unwrap()); self.proto_tx.send(Request::ServerRequest(server_request)).unwrap(); loop { match self.rx.recv() { Ok(IncomingMessage::ProtoResponse( Response::ServerResponse(server_response))) => { self.handle_server_response(server_response); }, Ok(IncomingMessage::ControlRequest(control_request)) => { warn!("Unhandled control request: {:?}", control_request); }, Err(e) => { error!("Error receiving response: {}", e); }, } } } fn handle_server_response(&mut self, response: ServerResponse) { match response { ServerResponse::LoginResponse(response) => self.handle_login_response(response), ServerResponse::PrivilegedUsersResponse(response) => self.handle_privileged_users_response(response), ServerResponse::RoomListResponse(response) => self.handle_room_list_response(response), ServerResponse::UnknownResponse(code, packet) => warn!("Unknown response: code {}, size {}", code, packet.bytes_remaining()), response => warn!("Unhandled response: {:?}", response), } } fn handle_login_response(&mut self, login: LoginResponse) { match self.state { State::LoggingIn => { match login { LoginResponse::LoginOk { motd, ip, password_md5_opt } => { self.state = State::LoggedIn; info!("Login successful!"); info!("MOTD: \"{}\"", motd); info!("External IP address: {}", ip); match password_md5_opt { Some(_) => { info!(concat!( "Connected to official server ", "as official client")); }, None => info!(concat!( "Connected to official server ", "as unofficial client")), } }, LoginResponse::LoginFail { reason } => { self.state = State::NotLoggedIn; error!("Login failed: \"{}\"", reason); } } }, _ => unimplemented!(), } } fn handle_room_list_response( &mut self, response: RoomListResponse) { info!("Received room list: {} rooms total", response.rooms.len()); } fn handle_privileged_users_response( &mut self, response: PrivilegedUsersResponse) { info!("Received privileged users list: {} privileged users total", response.users.len()); } }