master: announce client to servers behind NAT

This commit is contained in:
Denis Drakhnia 2023-10-23 07:46:55 +03:00
parent e6b1d866eb
commit d1693d41aa
2 changed files with 59 additions and 2 deletions

View File

@ -11,7 +11,7 @@ use blake2b_simd::Params;
use fastrand::Rng;
use log::{error, info, trace, warn};
use thiserror::Error;
use xash3d_protocol::filter::{Filter, Version};
use xash3d_protocol::filter::{Filter, FilterFlags, Version};
use xash3d_protocol::server::Region;
use xash3d_protocol::{admin, game, master, server, Error as ProtocolError, ServerInfo};
@ -240,7 +240,12 @@ impl MasterServer {
.filter(|i| i.1.is_valid(now, self.timeout.server))
.filter(|i| i.1.matches(*i.0, p.region, &p.filter))
.map(|i| *i.0);
self.send_server_list(from, p.filter.key, iter)?;
self.send_server_list(from, p.filter.key, iter.clone())?;
if p.filter.flags.contains(FilterFlags::NAT) {
self.send_client_to_nat_servers(from, iter)?;
}
}
}
game::Packet::GetServerInfo(p) => {
@ -416,6 +421,19 @@ impl MasterServer {
Ok(())
}
fn send_client_to_nat_servers<I>(&self, to: SocketAddrV4, iter: I) -> Result<(), Error>
where
I: Iterator<Item = SocketAddrV4>,
{
let mut buf = [0; 64];
let n = master::ClientAnnounce::new(to).encode(&mut buf)?;
let buf = &buf[..n];
for i in iter {
self.sock.send_to(buf, i)?;
}
Ok(())
}
#[inline]
fn is_blocked(&self, ip: &Ipv4Addr) -> bool {
self.blocklist.contains(ip)

View File

@ -123,6 +123,37 @@ where
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct ClientAnnounce {
pub addr: SocketAddrV4,
}
impl ClientAnnounce {
pub const HEADER: &'static [u8] = b"\xff\xff\xff\xffc ";
pub fn new(addr: SocketAddrV4) -> Self {
Self { addr }
}
pub fn decode(src: &[u8]) -> Result<Self, Error> {
let mut cur = Cursor::new(src);
cur.expect(Self::HEADER)?;
let addr = cur
.get_str(cur.remaining())?
.parse()
.map_err(|_| Error::InvalidPacket)?;
cur.expect_empty()?;
Ok(Self { addr })
}
pub fn encode(&self, buf: &mut [u8]) -> Result<usize, Error> {
Ok(CursorMut::new(buf)
.put_bytes(Self::HEADER)?
.put_as_str(self.addr)?
.pos())
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct AdminChallengeResponse {
pub master_challenge: u32,
@ -212,6 +243,14 @@ mod tests {
assert_eq!(e.iter().collect::<Vec<_>>(), servers);
}
#[test]
fn client_announce() {
let p = ClientAnnounce::new("1.2.3.4:12345".parse().unwrap());
let mut buf = [0; 512];
let n = p.encode(&mut buf).unwrap();
assert_eq!(ClientAnnounce::decode(&buf[..n]), Ok(p));
}
#[test]
fn admin_challenge_response() {
let p = AdminChallengeResponse::new(0x12345678, 0x87654321);