mirror of
https://git.mentality.rip/numas13/xash3d-master.git
synced 2025-02-02 18:24:23 +00:00
master: announce client to servers behind NAT
This commit is contained in:
parent
e6b1d866eb
commit
d1693d41aa
@ -11,7 +11,7 @@ use blake2b_simd::Params;
|
|||||||
use fastrand::Rng;
|
use fastrand::Rng;
|
||||||
use log::{error, info, trace, warn};
|
use log::{error, info, trace, warn};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use xash3d_protocol::filter::{Filter, Version};
|
use xash3d_protocol::filter::{Filter, FilterFlags, Version};
|
||||||
use xash3d_protocol::server::Region;
|
use xash3d_protocol::server::Region;
|
||||||
use xash3d_protocol::{admin, game, master, server, Error as ProtocolError, ServerInfo};
|
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.is_valid(now, self.timeout.server))
|
||||||
.filter(|i| i.1.matches(*i.0, p.region, &p.filter))
|
.filter(|i| i.1.matches(*i.0, p.region, &p.filter))
|
||||||
.map(|i| *i.0);
|
.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) => {
|
game::Packet::GetServerInfo(p) => {
|
||||||
@ -416,6 +421,19 @@ impl MasterServer {
|
|||||||
Ok(())
|
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]
|
#[inline]
|
||||||
fn is_blocked(&self, ip: &Ipv4Addr) -> bool {
|
fn is_blocked(&self, ip: &Ipv4Addr) -> bool {
|
||||||
self.blocklist.contains(ip)
|
self.blocklist.contains(ip)
|
||||||
|
@ -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)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct AdminChallengeResponse {
|
pub struct AdminChallengeResponse {
|
||||||
pub master_challenge: u32,
|
pub master_challenge: u32,
|
||||||
@ -212,6 +243,14 @@ mod tests {
|
|||||||
assert_eq!(e.iter().collect::<Vec<_>>(), servers);
|
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]
|
#[test]
|
||||||
fn admin_challenge_response() {
|
fn admin_challenge_response() {
|
||||||
let p = AdminChallengeResponse::new(0x12345678, 0x87654321);
|
let p = AdminChallengeResponse::new(0x12345678, 0x87654321);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user