#![forbid(unsafe_code)]
#![warn(clippy::all)]
use std::io::Read;
use gday_contact_exchange_protocol::{ClientMsg, Contact, ServerMsg, read_from, write_to};
#[tokio::test]
async fn test_integration() {
let args = gday_server::Args {
key: None,
certificate: None,
unencrypted: true,
addresses: vec!["127.0.0.1:0".parse().unwrap(), "[::1]:0".parse().unwrap()],
timeout: 3600,
request_limit: 10,
verbosity: log::LevelFilter::Off,
};
let (server_addrs, _handle) = gday_server::start_server(args).unwrap();
let server_ipv4 = *server_addrs.iter().find(|a| a.is_ipv4()).unwrap();
let server_ipv6 = *server_addrs.iter().find(|a| a.is_ipv6()).unwrap();
tokio::task::spawn_blocking(move || {
let local_contact_1 = Contact {
v4: Some("1.8.3.1:2304".parse().unwrap()),
v6: Some("[ab:41::b:43]:92".parse().unwrap()),
};
let local_contact_2 = Contact {
v4: Some("3.1.4.1:7853".parse().unwrap()),
v6: Some("[ab:41:ac::b:1]:5052".parse().unwrap()),
};
let mut stream_v4 = std::net::TcpStream::connect(server_ipv4).unwrap();
let mut stream_v6 = std::net::TcpStream::connect(server_ipv6).unwrap();
write_to(
ClientMsg::CreateRoom {
room_code: "room code 1".to_string(),
},
&mut stream_v4,
)
.unwrap();
let response: ServerMsg = read_from(&mut stream_v4).unwrap();
assert_eq!(response, ServerMsg::RoomCreated);
write_to(
ClientMsg::CreateRoom {
room_code: "room code 1".to_string(),
},
&mut stream_v4,
)
.unwrap();
let response: ServerMsg = read_from(&mut stream_v4).unwrap();
assert_eq!(response, ServerMsg::ErrorRoomTaken);
write_to(
ClientMsg::RecordPublicAddr {
room_code: "room code 2".to_string(),
is_creator: true,
},
&mut stream_v6,
)
.unwrap();
let response: ServerMsg = read_from(&mut stream_v6).unwrap();
assert_eq!(response, ServerMsg::ErrorNoSuchRoomCode);
write_to(
ClientMsg::RecordPublicAddr {
room_code: "room code 1".to_string(),
is_creator: true,
},
&mut stream_v4,
)
.unwrap();
let response: ServerMsg = read_from(&mut stream_v4).unwrap();
assert_eq!(response, ServerMsg::ReceivedAddr);
write_to(
ClientMsg::RecordPublicAddr {
room_code: "room code 1".to_string(),
is_creator: false,
},
&mut stream_v6,
)
.unwrap();
let response: ServerMsg = read_from(&mut stream_v6).unwrap();
assert_eq!(response, ServerMsg::ReceivedAddr);
write_to(
ClientMsg::ReadyToShare {
local_contact: local_contact_1,
room_code: "room code 1".to_string(),
is_creator: true,
},
&mut stream_v4,
)
.unwrap();
let response: ServerMsg = read_from(&mut stream_v4).unwrap();
let ServerMsg::ClientContact(client_contact) = response else {
panic!("Server replied with {response:?} instead of ClientContact");
};
assert_eq!(client_contact.local, local_contact_1);
write_to(
ClientMsg::RecordPublicAddr {
room_code: "room code 1".to_string(),
is_creator: true,
},
&mut stream_v6,
)
.unwrap();
let response: ServerMsg = read_from(&mut stream_v6).unwrap();
assert_eq!(response, ServerMsg::ErrorUnexpectedMsg);
write_to(
ClientMsg::CreateRoom {
room_code: "room code 2".to_string(),
},
&mut stream_v6,
)
.unwrap();
let response: ServerMsg = read_from(&mut stream_v6).unwrap();
assert_eq!(response, ServerMsg::RoomCreated);
write_to(
ClientMsg::ReadyToShare {
local_contact: local_contact_2,
room_code: "room code 1".to_string(),
is_creator: false,
},
&mut stream_v6,
)
.unwrap();
let response: ServerMsg = read_from(&mut stream_v6).unwrap();
let ServerMsg::ClientContact(client_contact) = response else {
panic!("Server replied with {response:?} instead of ClientContact");
};
assert_eq!(client_contact.local, local_contact_2);
let response: ServerMsg = read_from(&mut stream_v4).unwrap();
let ServerMsg::PeerContact(peer_contact) = response else {
panic!("Server replied with {response:?} instead of PeerContact");
};
assert_eq!(peer_contact.local, local_contact_2);
let response: ServerMsg = read_from(&mut stream_v6).unwrap();
let ServerMsg::PeerContact(peer_contact) = response else {
panic!("Server replied with {response:?} instead of PeerContact");
};
assert_eq!(peer_contact.local, local_contact_1);
write_to(
ClientMsg::CreateRoom {
room_code: "room code 1".to_string(),
},
&mut stream_v4,
)
.unwrap();
let response: ServerMsg = read_from(&mut stream_v4).unwrap();
assert_eq!(response, ServerMsg::RoomCreated);
})
.await
.unwrap();
}
#[tokio::test]
async fn test_request_limit() {
let args = gday_server::Args {
key: None,
certificate: None,
unencrypted: true,
addresses: vec!["127.0.0.1:0".parse().unwrap(), "[::1]:0".parse().unwrap()],
timeout: 3600,
request_limit: 10,
verbosity: log::LevelFilter::Off,
};
let (server_addrs, _handle) = gday_server::start_server(args).unwrap();
let server_ipv4 = *server_addrs.iter().find(|a| a.is_ipv4()).unwrap();
let server_ipv6 = *server_addrs.iter().find(|a| a.is_ipv6()).unwrap();
tokio::task::spawn_blocking(move || {
let mut stream_v4 = std::net::TcpStream::connect(server_ipv4).unwrap();
let mut stream_v6 = std::net::TcpStream::connect(server_ipv6).unwrap();
for room_code in 1..=10 {
write_to(
ClientMsg::CreateRoom {
room_code: format!("{room_code}"),
},
&mut stream_v4,
)
.unwrap();
let response: ServerMsg = read_from(&mut stream_v4).unwrap();
assert_eq!(response, ServerMsg::RoomCreated);
}
write_to(
ClientMsg::CreateRoom {
room_code: "11".to_string(),
},
&mut stream_v4,
)
.unwrap();
let response: ServerMsg = read_from(&mut stream_v4).unwrap();
assert_eq!(response, ServerMsg::ErrorTooManyRequests);
assert_eq!(stream_v4.read(&mut [0, 0]).unwrap(), 0);
write_to(
ClientMsg::CreateRoom {
room_code: "other room code".to_string(),
},
&mut stream_v6,
)
.unwrap();
let response: ServerMsg = read_from(&mut stream_v6).unwrap();
assert_eq!(response, ServerMsg::RoomCreated);
})
.await
.unwrap();
}