use std::io; use std::net; use super::constants::*; use super::super::packet::Packet; /*=================* * SERVER RESPONSE * *=================*/ #[derive(Debug)] pub enum ServerResponse { ConnectToPeerResponse(ConnectToPeerResponse), JoinRoomResponse(JoinRoomResponse), LoginResponse(LoginResponse), PeerAddressResponse(PeerAddressResponse), PrivilegedUsersResponse(PrivilegedUsersResponse), RoomListResponse(RoomListResponse), WishlistIntervalResponse(WishlistIntervalResponse), // Unknown purpose ParentMinSpeedResponse(ParentMinSpeedResponse), ParentSpeedRatioResponse(ParentSpeedRatioResponse), UnknownResponse(u32, Packet), } impl ServerResponse { pub fn from_packet(mut packet: Packet) -> io::Result { let code = try!(packet.read_uint()); let resp = match code { CODE_CONNECT_TO_PEER => ServerResponse::ConnectToPeerResponse( try!(ConnectToPeerResponse::from_packet(&mut packet)) ), CODE_JOIN_ROOM => ServerResponse::JoinRoomResponse( try!(JoinRoomResponse::from_packet(&mut packet)) ), CODE_LOGIN => ServerResponse::LoginResponse( try!(LoginResponse::from_packet(&mut packet)) ), CODE_PEER_ADDRESS => ServerResponse::PeerAddressResponse( try!(PeerAddressResponse::from_packet(&mut packet)) ), CODE_PRIVILEGED_USERS => ServerResponse::PrivilegedUsersResponse( try!(PrivilegedUsersResponse::from_packet(&mut packet)) ), CODE_ROOM_LIST => ServerResponse::RoomListResponse( try!(RoomListResponse::from_packet(&mut packet)) ), CODE_WISHLIST_INTERVAL => ServerResponse::WishlistIntervalResponse( try!(WishlistIntervalResponse::from_packet(&mut packet)) ), CODE_PARENT_MIN_SPEED => ServerResponse::ParentMinSpeedResponse( try!(ParentMinSpeedResponse::from_packet(&mut packet)) ), CODE_PARENT_SPEED_RATIO => ServerResponse::ParentSpeedRatioResponse( try!(ParentSpeedRatioResponse::from_packet(&mut packet)) ), code => return Ok(ServerResponse::UnknownResponse(code, packet)), }; let bytes_remaining = packet.bytes_remaining(); if bytes_remaining > 0 { warn!("Packet with code {} contains {} extra bytes", code, bytes_remaining) } Ok(resp) } } /*=================* * CONNECT TO PEER * *=================*/ #[derive(Debug)] pub struct ConnectToPeerResponse { pub username: String, pub connection_type: String, pub ip: net::Ipv4Addr, pub port: u16, pub token: u32, pub is_privileged: bool, } impl ConnectToPeerResponse { fn from_packet(packet: &mut Packet) -> io::Result { let username = try!(packet.read_str()); let connection_type = try!(packet.read_str()); let ip = try!(packet.read_ipv4_addr()); let port = try!(packet.read_port()); let token = try!(packet.read_uint()); let is_privileged = try!(packet.read_bool()); Ok(ConnectToPeerResponse { username: username, connection_type: connection_type, ip: ip, port: port, token: token, is_privileged: is_privileged, }) } } /*===========* * JOIN ROOM * *===========*/ #[derive(Debug)] pub struct JoinRoomResponse { room_name: String, user_names: Vec, user_statuses: Vec, } impl JoinRoomResponse { pub fn from_packet(packet: &mut Packet) -> io::Result { let room_name = try!(packet.read_str()); let mut user_names = Vec::new(); try!(packet.read_array(&mut user_names, Packet::read_str)); let mut user_statuses = Vec::new(); try!(packet.read_array(&mut user_statuses, Packet::read_uint)); Ok(JoinRoomResponse { room_name: room_name, user_names: user_names, user_statuses: user_statuses, }) } } /*=======* * LOGIN * *=======*/ #[derive(Debug)] pub enum LoginResponse { LoginOk { motd: String, ip: net::Ipv4Addr, password_md5_opt: Option }, LoginFail { reason: String }, } impl LoginResponse { pub fn from_packet(packet: &mut Packet) -> io::Result { let ok = try!(packet.read_bool()); if ok { let motd = try!(packet.read_str()); let ip = try!(packet.read_ipv4_addr()); match packet.read_bool() { Ok(value) => debug!("LoginResponse last field: {}", value), Err(e) => debug!("Error reading LoginResponse field: {:?}", e), } Ok(LoginResponse::LoginOk { motd: motd, ip: ip, password_md5_opt: None }) } else { Ok(LoginResponse::LoginFail { reason: try!(packet.read_str()) }) } } } /*==================* * PARENT MIN SPEED * *==================*/ #[derive(Debug)] pub struct ParentMinSpeedResponse { pub value: u32, } impl ParentMinSpeedResponse { fn from_packet(packet: &mut Packet) -> io::Result { let value = try!(packet.read_uint()); Ok(ParentMinSpeedResponse { value: value, }) } } /*====================* * PARENT SPEED RATIO * *====================*/ #[derive(Debug)] pub struct ParentSpeedRatioResponse { pub value: u32, } impl ParentSpeedRatioResponse { fn from_packet(packet: &mut Packet) -> io::Result { let value = try!(packet.read_uint()); Ok(ParentSpeedRatioResponse { value: value, }) } } /*==============* * PEER ADDRESS * *==============*/ #[derive(Debug)] pub struct PeerAddressResponse { username: String, ip: net::Ipv4Addr, port: u16, } impl PeerAddressResponse { fn from_packet(packet: &mut Packet) -> io::Result { let username = try!(packet.read_str()); let ip = try!(packet.read_ipv4_addr()); let port = try!(packet.read_port()); Ok(PeerAddressResponse { username: username, ip: ip, port: port, }) } } /*==================* * PRIVILEGED USERS * *==================*/ #[derive(Debug)] pub struct PrivilegedUsersResponse { pub users: Vec, } impl PrivilegedUsersResponse { fn from_packet(packet: &mut Packet) -> io::Result { let mut response = PrivilegedUsersResponse { users: Vec::new(), }; try!(packet.read_array(&mut response.users, Packet::read_str)); Ok(response) } } /*===========* * ROOM LIST * *===========*/ #[derive(Debug)] pub struct RoomListResponse { pub rooms: Vec<(String, u32)>, pub owned_private_rooms: Vec<(String, u32)>, pub other_private_rooms: Vec<(String, u32)>, pub operated_private_room_names: Vec, } impl RoomListResponse { fn from_packet(packet: &mut Packet) -> io::Result { let mut response = RoomListResponse { rooms: Vec::new(), owned_private_rooms: Vec::new(), other_private_rooms: Vec::new(), operated_private_room_names: Vec::new(), }; try!(Self::read_rooms(packet, &mut response.rooms)); if let Err(e) = Self::read_rooms( packet, &mut response.owned_private_rooms) { warn!("Error parsing owned_private_rooms: {}", e); return Ok(response); } if let Err(e) = Self::read_rooms( packet, &mut response.other_private_rooms) { warn!("Error parsing other_private_rooms: {}", e); return Ok(response); } if let Err(e) = packet.read_array( &mut response.operated_private_room_names, Packet::read_str) { warn!("Error parsing operated_private_rooms: {}", e); } Ok(response) } fn read_rooms(packet: &mut Packet, rooms: &mut Vec<(String, u32)>) -> io::Result<()> { let original_rooms_len = rooms.len(); let num_rooms = try!(packet.read_array(rooms, |packet| { Ok((try!(packet.read_str()), 0)) })); let num_user_counts = try!(packet.read_array_with(|packet, i| { let user_count = try!(packet.read_uint()); rooms[original_rooms_len+i].1 = user_count; Ok(()) })); if num_rooms != num_user_counts { warn!("Numbers of rooms and user counts do not match: {} != {}", num_rooms, num_user_counts); } Ok(()) } } /*===================* * WISHLIST INTERVAL * *===================*/ #[derive(Debug)] pub struct WishlistIntervalResponse { pub seconds: u32, } impl WishlistIntervalResponse { fn from_packet(packet: &mut Packet) -> io::Result { let seconds = try!(packet.read_uint()); Ok(WishlistIntervalResponse { seconds: seconds, }) } }