Solstice client.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

864 lines
21 KiB

use std::io;
use crate::proto::core::value::{
ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError,
ValueEncoder,
};
use crate::proto::packet::{MutPacket, WriteToPacket};
use crate::proto::server::constants::*;
/*================*
* SERVER REQUEST *
*================*/
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ServerRequest {
CannotConnectRequest(CannotConnectRequest),
ConnectToPeerRequest(ConnectToPeerRequest),
FileSearchRequest(FileSearchRequest),
LoginRequest(LoginRequest),
PeerAddressRequest(PeerAddressRequest),
RoomJoinRequest(RoomJoinRequest),
RoomLeaveRequest(RoomLeaveRequest),
RoomListRequest,
RoomMessageRequest(RoomMessageRequest),
SetListenPortRequest(SetListenPortRequest),
UserStatusRequest(UserStatusRequest),
}
impl From<CannotConnectRequest> for ServerRequest {
fn from(inner: CannotConnectRequest) -> ServerRequest {
ServerRequest::CannotConnectRequest(inner)
}
}
impl From<ConnectToPeerRequest> for ServerRequest {
fn from(inner: ConnectToPeerRequest) -> ServerRequest {
ServerRequest::ConnectToPeerRequest(inner)
}
}
impl From<FileSearchRequest> for ServerRequest {
fn from(inner: FileSearchRequest) -> ServerRequest {
ServerRequest::FileSearchRequest(inner)
}
}
impl From<LoginRequest> for ServerRequest {
fn from(inner: LoginRequest) -> ServerRequest {
ServerRequest::LoginRequest(inner)
}
}
impl From<PeerAddressRequest> for ServerRequest {
fn from(inner: PeerAddressRequest) -> ServerRequest {
ServerRequest::PeerAddressRequest(inner)
}
}
impl From<RoomJoinRequest> for ServerRequest {
fn from(inner: RoomJoinRequest) -> ServerRequest {
ServerRequest::RoomJoinRequest(inner)
}
}
impl From<RoomLeaveRequest> for ServerRequest {
fn from(inner: RoomLeaveRequest) -> ServerRequest {
ServerRequest::RoomLeaveRequest(inner)
}
}
impl From<RoomMessageRequest> for ServerRequest {
fn from(inner: RoomMessageRequest) -> ServerRequest {
ServerRequest::RoomMessageRequest(inner)
}
}
impl From<SetListenPortRequest> for ServerRequest {
fn from(inner: SetListenPortRequest) -> ServerRequest {
ServerRequest::SetListenPortRequest(inner)
}
}
impl From<UserStatusRequest> for ServerRequest {
fn from(inner: UserStatusRequest) -> ServerRequest {
ServerRequest::UserStatusRequest(inner)
}
}
impl WriteToPacket for ServerRequest {
fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> {
match *self {
ServerRequest::CannotConnectRequest(ref request) => {
packet.write_value(&CODE_CANNOT_CONNECT)?;
packet.write_value(request)?;
}
ServerRequest::ConnectToPeerRequest(ref request) => {
packet.write_value(&CODE_CONNECT_TO_PEER)?;
packet.write_value(request)?;
}
ServerRequest::FileSearchRequest(ref request) => {
packet.write_value(&CODE_FILE_SEARCH)?;
packet.write_value(request)?;
}
ServerRequest::LoginRequest(ref request) => {
packet.write_value(&CODE_LOGIN)?;
packet.write_value(request)?;
}
ServerRequest::PeerAddressRequest(ref request) => {
packet.write_value(&CODE_PEER_ADDRESS)?;
packet.write_value(request)?;
}
ServerRequest::RoomJoinRequest(ref request) => {
packet.write_value(&CODE_ROOM_JOIN)?;
packet.write_value(request)?;
}
ServerRequest::RoomLeaveRequest(ref request) => {
packet.write_value(&CODE_ROOM_LEAVE)?;
packet.write_value(request)?;
}
ServerRequest::RoomListRequest => {
packet.write_value(&CODE_ROOM_LIST)?;
}
ServerRequest::RoomMessageRequest(ref request) => {
packet.write_value(&CODE_ROOM_MESSAGE)?;
packet.write_value(request)?;
}
ServerRequest::SetListenPortRequest(ref request) => {
packet.write_value(&CODE_SET_LISTEN_PORT)?;
packet.write_value(request)?;
}
ServerRequest::UserStatusRequest(ref request) => {
packet.write_value(&CODE_USER_STATUS)?;
packet.write_value(request)?;
}
}
Ok(())
}
}
impl ValueEncode for ServerRequest {
fn encode_to(
&self,
encoder: &mut ValueEncoder,
) -> Result<(), ValueEncodeError> {
match *self {
ServerRequest::CannotConnectRequest(ref request) => {
encoder.encode_u32(CODE_CANNOT_CONNECT)?;
request.encode_to(encoder)?;
}
ServerRequest::ConnectToPeerRequest(ref request) => {
encoder.encode_u32(CODE_CONNECT_TO_PEER)?;
request.encode_to(encoder)?;
}
ServerRequest::FileSearchRequest(ref request) => {
encoder.encode_u32(CODE_FILE_SEARCH)?;
request.encode_to(encoder)?;
}
ServerRequest::LoginRequest(ref request) => {
encoder.encode_u32(CODE_LOGIN)?;
request.encode_to(encoder)?;
}
ServerRequest::PeerAddressRequest(ref request) => {
encoder.encode_u32(CODE_PEER_ADDRESS)?;
request.encode_to(encoder)?;
}
ServerRequest::RoomJoinRequest(ref request) => {
encoder.encode_u32(CODE_ROOM_JOIN)?;
request.encode_to(encoder)?;
}
ServerRequest::RoomLeaveRequest(ref request) => {
encoder.encode_u32(CODE_ROOM_LEAVE)?;
request.encode_to(encoder)?;
}
ServerRequest::RoomListRequest => {
encoder.encode_u32(CODE_ROOM_LIST)?;
}
ServerRequest::RoomMessageRequest(ref request) => {
encoder.encode_u32(CODE_ROOM_MESSAGE)?;
request.encode_to(encoder)?;
}
ServerRequest::SetListenPortRequest(ref request) => {
encoder.encode_u32(CODE_SET_LISTEN_PORT)?;
request.encode_to(encoder)?;
}
ServerRequest::UserStatusRequest(ref request) => {
encoder.encode_u32(CODE_USER_STATUS)?;
request.encode_to(encoder)?;
}
}
Ok(())
}
}
impl ValueDecode for ServerRequest {
fn decode_from(decoder: &mut ValueDecoder) -> Result<Self, ValueDecodeError> {
let position = decoder.position();
let code: u32 = decoder.decode()?;
let request = match code {
CODE_CANNOT_CONNECT => {
let request = decoder.decode()?;
ServerRequest::CannotConnectRequest(request)
}
CODE_CONNECT_TO_PEER => {
let request = decoder.decode()?;
ServerRequest::ConnectToPeerRequest(request)
}
CODE_FILE_SEARCH => {
let request = decoder.decode()?;
ServerRequest::FileSearchRequest(request)
}
CODE_LOGIN => {
let request = decoder.decode()?;
ServerRequest::LoginRequest(request)
}
CODE_PEER_ADDRESS => {
let request = decoder.decode()?;
ServerRequest::PeerAddressRequest(request)
}
CODE_ROOM_JOIN => {
let request = decoder.decode()?;
ServerRequest::RoomJoinRequest(request)
}
CODE_ROOM_LEAVE => {
let request = decoder.decode()?;
ServerRequest::RoomLeaveRequest(request)
}
CODE_ROOM_LIST => ServerRequest::RoomListRequest,
CODE_ROOM_MESSAGE => {
let request = decoder.decode()?;
ServerRequest::RoomMessageRequest(request)
}
CODE_SET_LISTEN_PORT => {
let request = decoder.decode()?;
ServerRequest::SetListenPortRequest(request)
}
CODE_USER_STATUS => {
let request = decoder.decode()?;
ServerRequest::UserStatusRequest(request)
}
_ => {
return Err(ValueDecodeError::InvalidData {
value_name: "server request code".to_string(),
cause: format!("unknown value {}", code),
position: position,
})
}
};
Ok(request)
}
}
/*================*
* CANNOT CONNECT *
*================*/
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CannotConnectRequest {
pub token: u32,
pub user_name: String,
}
impl WriteToPacket for CannotConnectRequest {
fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> {
packet.write_value(&self.token)?;
packet.write_value(&self.user_name)?;
Ok(())
}
}
impl ValueEncode for CannotConnectRequest {
fn encode_to(
&self,
encoder: &mut ValueEncoder,
) -> Result<(), ValueEncodeError> {
encoder.encode_u32(self.token)?;
encoder.encode_string(&self.user_name)
}
}
impl ValueDecode for CannotConnectRequest {
fn decode_from(decoder: &mut ValueDecoder) -> Result<Self, ValueDecodeError> {
let token = decoder.decode()?;
let user_name = decoder.decode()?;
Ok(CannotConnectRequest { token, user_name })
}
}
/*=================*
* CONNECT TO PEER *
*=================*/
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ConnectToPeerRequest {
pub token: u32,
pub user_name: String,
pub connection_type: String,
}
impl WriteToPacket for ConnectToPeerRequest {
fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> {
packet.write_value(&self.token)?;
packet.write_value(&self.user_name)?;
packet.write_value(&self.connection_type)?;
Ok(())
}
}
impl ValueEncode for ConnectToPeerRequest {
fn encode_to(
&self,
encoder: &mut ValueEncoder,
) -> Result<(), ValueEncodeError> {
encoder.encode_u32(self.token)?;
encoder.encode_string(&self.user_name)?;
encoder.encode_string(&self.connection_type)
}
}
impl ValueDecode for ConnectToPeerRequest {
fn decode_from(decoder: &mut ValueDecoder) -> Result<Self, ValueDecodeError> {
let token = decoder.decode()?;
let user_name = decoder.decode()?;
let connection_type = decoder.decode()?;
Ok(ConnectToPeerRequest {
token,
user_name,
connection_type,
})
}
}
/*=============*
* FILE SEARCH *
*=============*/
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct FileSearchRequest {
pub ticket: u32,
pub query: String,
}
impl WriteToPacket for FileSearchRequest {
fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> {
packet.write_value(&self.ticket)?;
packet.write_value(&self.query)?;
Ok(())
}
}
impl ValueEncode for FileSearchRequest {
fn encode_to(
&self,
encoder: &mut ValueEncoder,
) -> Result<(), ValueEncodeError> {
encoder.encode_u32(self.ticket)?;
encoder.encode_string(&self.query)
}
}
impl ValueDecode for FileSearchRequest {
fn decode_from(decoder: &mut ValueDecoder) -> Result<Self, ValueDecodeError> {
let ticket = decoder.decode()?;
let query = decoder.decode()?;
Ok(FileSearchRequest { ticket, query })
}
}
/*=======*
* LOGIN *
*=======*/
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LoginRequest {
pub user_name: String,
pub password: String,
pub digest: String,
pub major: u32,
pub minor: u32,
}
impl WriteToPacket for LoginRequest {
fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> {
packet.write_value(&self.user_name)?;
packet.write_value(&self.password)?;
packet.write_value(&self.major)?;
packet.write_value(&self.digest)?;
packet.write_value(&self.minor)?;
Ok(())
}
}
impl ValueEncode for LoginRequest {
fn encode_to(
&self,
encoder: &mut ValueEncoder,
) -> Result<(), ValueEncodeError> {
encoder.encode_string(&self.user_name)?;
encoder.encode_string(&self.password)?;
encoder.encode_u32(self.major)?;
encoder.encode_string(&self.digest)?;
encoder.encode_u32(self.minor)
}
}
impl ValueDecode for LoginRequest {
fn decode_from(decoder: &mut ValueDecoder) -> Result<Self, ValueDecodeError> {
let user_name = decoder.decode()?;
let password = decoder.decode()?;
let major = decoder.decode()?;
let digest = decoder.decode()?;
let minor = decoder.decode()?;
Ok(LoginRequest {
user_name,
password,
digest,
major,
minor,
})
}
}
/*==============*
* PEER ADDRESS *
*==============*/
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PeerAddressRequest {
pub user_name: String,
}
impl WriteToPacket for PeerAddressRequest {
fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> {
packet.write_value(&self.user_name)?;
Ok(())
}
}
impl ValueEncode for PeerAddressRequest {
fn encode_to(
&self,
encoder: &mut ValueEncoder,
) -> Result<(), ValueEncodeError> {
encoder.encode_string(&self.user_name)
}
}
impl ValueDecode for PeerAddressRequest {
fn decode_from(decoder: &mut ValueDecoder) -> Result<Self, ValueDecodeError> {
let user_name = decoder.decode()?;
Ok(PeerAddressRequest { user_name })
}
}
/*===========*
* ROOM JOIN *
*===========*/
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RoomJoinRequest {
pub room_name: String,
}
impl WriteToPacket for RoomJoinRequest {
fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> {
packet.write_value(&self.room_name)?;
Ok(())
}
}
impl ValueEncode for RoomJoinRequest {
fn encode_to(
&self,
encoder: &mut ValueEncoder,
) -> Result<(), ValueEncodeError> {
encoder.encode_string(&self.room_name)
}
}
impl ValueDecode for RoomJoinRequest {
fn decode_from(decoder: &mut ValueDecoder) -> Result<Self, ValueDecodeError> {
let room_name = decoder.decode()?;
Ok(RoomJoinRequest {
room_name: room_name,
})
}
}
/*============*
* ROOM LEAVE *
*============*/
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RoomLeaveRequest {
pub room_name: String,
}
impl WriteToPacket for RoomLeaveRequest {
fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> {
packet.write_value(&self.room_name)?;
Ok(())
}
}
impl ValueEncode for RoomLeaveRequest {
fn encode_to(
&self,
encoder: &mut ValueEncoder,
) -> Result<(), ValueEncodeError> {
encoder.encode_string(&self.room_name)
}
}
impl ValueDecode for RoomLeaveRequest {
fn decode_from(decoder: &mut ValueDecoder) -> Result<Self, ValueDecodeError> {
let room_name = decoder.decode()?;
Ok(RoomLeaveRequest {
room_name: room_name,
})
}
}
/*==============*
* ROOM MESSAGE *
*==============*/
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RoomMessageRequest {
pub room_name: String,
pub message: String,
}
impl WriteToPacket for RoomMessageRequest {
fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> {
packet.write_value(&self.room_name)?;
packet.write_value(&self.message)?;
Ok(())
}
}
impl ValueEncode for RoomMessageRequest {
fn encode_to(
&self,
encoder: &mut ValueEncoder,
) -> Result<(), ValueEncodeError> {
encoder.encode_string(&self.room_name)?;
encoder.encode_string(&self.message)
}
}
impl ValueDecode for RoomMessageRequest {
fn decode_from(decoder: &mut ValueDecoder) -> Result<Self, ValueDecodeError> {
let room_name = decoder.decode()?;
let message = decoder.decode()?;
Ok(RoomMessageRequest { room_name, message })
}
}
/*=================*
* SET LISTEN PORT *
*=================*/
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SetListenPortRequest {
pub port: u16,
}
impl WriteToPacket for SetListenPortRequest {
fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> {
packet.write_value(&self.port)?;
Ok(())
}
}
impl ValueEncode for SetListenPortRequest {
fn encode_to(
&self,
encoder: &mut ValueEncoder,
) -> Result<(), ValueEncodeError> {
encoder.encode(&self.port)
}
}
impl ValueDecode for SetListenPortRequest {
fn decode_from(decoder: &mut ValueDecoder) -> Result<Self, ValueDecodeError> {
let port = decoder.decode()?;
Ok(SetListenPortRequest { port: port })
}
}
/*=============*
* USER STATUS *
*=============*/
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct UserStatusRequest {
pub user_name: String,
}
impl WriteToPacket for UserStatusRequest {
fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> {
packet.write_value(&self.user_name)?;
Ok(())
}
}
impl ValueEncode for UserStatusRequest {
fn encode_to(
&self,
encoder: &mut ValueEncoder,
) -> Result<(), ValueEncodeError> {
encoder.encode_string(&self.user_name)
}
}
impl ValueDecode for UserStatusRequest {
fn decode_from(decoder: &mut ValueDecoder) -> Result<Self, ValueDecodeError> {
let user_name = decoder.decode()?;
Ok(UserStatusRequest {
user_name: user_name,
})
}
}
/*=======*
* TESTS *
*=======*/
#[cfg(test)]
mod tests {
use bytes::BytesMut;
use crate::proto::core::value::tests::roundtrip;
use crate::proto::core::value::{ValueDecodeError, ValueDecoder};
use super::*;
#[test]
fn invalid_code() {
let mut bytes = BytesMut::new();
bytes.extend_from_slice(&[57, 5, 0, 0]);
let result = ValueDecoder::new(&bytes).decode::<ServerRequest>();
assert_eq!(
result,
Err(ValueDecodeError::InvalidData {
value_name: "server request code".to_string(),
cause: "unknown value 1337".to_string(),
position: 0,
})
);
}
#[test]
fn from_cannot_connect_request() {
let request = CannotConnectRequest {
token: 1337,
user_name: "alice".to_string(),
};
assert_eq!(
ServerRequest::from(request.clone()),
ServerRequest::CannotConnectRequest(request)
);
}
#[test]
fn roundtrip_cannot_connect_request() {
roundtrip(ServerRequest::CannotConnectRequest(CannotConnectRequest {
token: 1337,
user_name: "alice".to_string(),
}))
}
#[test]
fn from_connect_to_peer_request() {
let request = ConnectToPeerRequest {
token: 1337,
user_name: "alice".to_string(),
connection_type: "P".to_string(),
};
assert_eq!(
ServerRequest::from(request.clone()),
ServerRequest::ConnectToPeerRequest(request)
);
}
#[test]
fn roundtrip_connect_to_peer_request() {
roundtrip(ServerRequest::ConnectToPeerRequest(ConnectToPeerRequest {
token: 1337,
user_name: "alice".to_string(),
connection_type: "P".to_string(),
}))
}
#[test]
fn from_file_search_request() {
let request = FileSearchRequest {
ticket: 1337,
query: "foo.txt".to_string(),
};
assert_eq!(
ServerRequest::from(request.clone()),
ServerRequest::FileSearchRequest(request)
);
}
#[test]
fn roundtrip_file_search_request() {
roundtrip(ServerRequest::FileSearchRequest(FileSearchRequest {
ticket: 1337,
query: "foo.txt".to_string(),
}))
}
#[test]
fn from_login_request() {
let request = LoginRequest {
user_name: "alice".to_string(),
password: "sekrit".to_string(),
digest: "abcdef".to_string(),
major: 13,
minor: 37,
};
assert_eq!(
ServerRequest::from(request.clone()),
ServerRequest::LoginRequest(request)
);
}
#[test]
fn roundtrip_login_request() {
roundtrip(ServerRequest::LoginRequest(LoginRequest {
user_name: "alice".to_string(),
password: "sekrit".to_string(),
digest: "abcdef".to_string(),
major: 13,
minor: 37,
}))
}
#[test]
fn from_peer_address_request() {
let request = PeerAddressRequest {
user_name: "alice".to_string(),
};
assert_eq!(
ServerRequest::from(request.clone()),
ServerRequest::PeerAddressRequest(request)
);
}
#[test]
fn roundtrip_peer_address_request() {
roundtrip(ServerRequest::PeerAddressRequest(PeerAddressRequest {
user_name: "alice".to_string(),
}))
}
#[test]
fn from_room_join_request() {
let request = RoomJoinRequest {
room_name: "best room ever".to_string(),
};
assert_eq!(
ServerRequest::from(request.clone()),
ServerRequest::RoomJoinRequest(request)
);
}
#[test]
fn roundtrip_room_join_request() {
roundtrip(ServerRequest::RoomJoinRequest(RoomJoinRequest {
room_name: "best room ever".to_string(),
}))
}
#[test]
fn from_room_leave_request() {
let request = RoomLeaveRequest {
room_name: "worst room ever".to_string(),
};
assert_eq!(
ServerRequest::from(request.clone()),
ServerRequest::RoomLeaveRequest(request)
);
}
#[test]
fn roundtrip_room_leave_request() {
roundtrip(ServerRequest::RoomLeaveRequest(RoomLeaveRequest {
room_name: "worst room ever".to_string(),
}))
}
#[test]
fn roundtrip_room_list_request() {
roundtrip(ServerRequest::RoomListRequest)
}
#[test]
fn from_room_message_request() {
let request = RoomMessageRequest {
room_name: "best room ever".to_string(),
message: "hello world!".to_string(),
};
assert_eq!(
ServerRequest::from(request.clone()),
ServerRequest::RoomMessageRequest(request)
);
}
#[test]
fn roundtrip_room_message_request() {
roundtrip(ServerRequest::RoomMessageRequest(RoomMessageRequest {
room_name: "best room ever".to_string(),
message: "hello world!".to_string(),
}))
}
#[test]
fn from_set_listen_port_request() {
let request = SetListenPortRequest { port: 1337 };
assert_eq!(
ServerRequest::from(request.clone()),
ServerRequest::SetListenPortRequest(request)
);
}
#[test]
fn roundtrip_set_listen_port_request() {
roundtrip(ServerRequest::SetListenPortRequest(SetListenPortRequest {
port: 1337,
}))
}
#[test]
fn from_user_status_request() {
let request = UserStatusRequest {
user_name: "alice".to_string(),
};
assert_eq!(
ServerRequest::from(request.clone()),
ServerRequest::UserStatusRequest(request)
);
}
#[test]
fn roundtrip_user_status_request() {
roundtrip(ServerRequest::UserStatusRequest(UserStatusRequest {
user_name: "alice".to_string(),
}))
}
}