use std::net::UdpSocket;
use std::thread;
use std::time::Duration;
use ssq::Client;
fn single_packet(payload: &[u8]) -> Vec<u8> {
let mut pkt = vec![0xFF, 0xFF, 0xFF, 0xFF];
pkt.extend_from_slice(payload);
pkt
}
fn challenge_response(challenge: i32) -> Vec<u8> {
let mut payload = vec![b'A'];
payload.extend_from_slice(&challenge.to_le_bytes());
single_packet(&payload)
}
fn empty_player_response() -> Vec<u8> {
single_packet(&[b'D', 0x00])
}
#[test]
fn challenge_retry_on_double_challenge() {
let server = UdpSocket::bind("127.0.0.1:0").unwrap();
let server_addr = server.local_addr().unwrap();
server
.set_read_timeout(Some(Duration::from_secs(5)))
.unwrap();
let handle = thread::spawn(move || {
let mut buf = [0u8; 1400];
let (n, client_addr) = server.recv_from(&mut buf).unwrap();
assert!(n >= 9, "initial request too short");
server
.send_to(&challenge_response(1000), client_addr)
.unwrap();
let (n, client_addr) = server.recv_from(&mut buf).unwrap();
assert!(n >= 9, "first retry too short");
let challenge = i32::from_le_bytes(buf[5..9].try_into().unwrap());
assert_eq!(challenge, 1000, "client should echo back challenge 1000");
server
.send_to(&challenge_response(2000), client_addr)
.unwrap();
let (n, client_addr) = server.recv_from(&mut buf).unwrap();
assert!(n >= 9, "second retry too short");
let challenge = i32::from_le_bytes(buf[5..9].try_into().unwrap());
assert_eq!(challenge, 2000, "client should echo back challenge 2000");
server
.send_to(&empty_player_response(), client_addr)
.unwrap();
});
let client = Client::new(Duration::from_secs(5)).unwrap();
let players = client.players(server_addr).unwrap();
assert!(players.is_empty());
handle.join().unwrap();
}