mirror of
https://git.mentality.rip/numas13/xash3d-master.git
synced 2025-02-02 02:04:16 +00:00
protocol: support old servers (protocol 48)
This commit is contained in:
parent
05b447a750
commit
5778bbc714
@ -252,10 +252,10 @@ impl MasterServer {
|
||||
let p = server::GetServerInfoResponse {
|
||||
map: self.update_map.as_ref(),
|
||||
host: self.update_title.as_ref(),
|
||||
protocol: 49,
|
||||
protocol: 48, // XXX: how to detect what version client will accept?
|
||||
dm: true,
|
||||
maxcl: 32,
|
||||
gamedir: "valve",
|
||||
gamedir: "valve", // XXX: probably must be specific for client...
|
||||
..Default::default()
|
||||
};
|
||||
trace!("{}: send {:?}", from, p);
|
||||
@ -334,7 +334,7 @@ impl MasterServer {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debug!("invalid packet: \"{}\"", Str(src));
|
||||
debug!("{}: invalid packet: \"{}\"", from, Str(src));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -87,23 +87,36 @@ impl<T> From<&ServerAdd<T>> for FilterFlags {
|
||||
pub struct Version {
|
||||
pub major: u8,
|
||||
pub minor: u8,
|
||||
pub patch: u8,
|
||||
}
|
||||
|
||||
impl Version {
|
||||
pub const fn new(major: u8, minor: u8) -> Self {
|
||||
Self { major, minor }
|
||||
Self::with_patch(major, minor, 0)
|
||||
}
|
||||
|
||||
pub const fn with_patch(major: u8, minor: u8, patch: u8) -> Self {
|
||||
Self {
|
||||
major,
|
||||
minor,
|
||||
patch,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Version {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{}.{}", self.major, self.minor)
|
||||
write!(fmt, "{}.{}", self.major, self.minor)?;
|
||||
if self.patch != 0 {
|
||||
write!(fmt, ".{}", self.patch)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Version {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{}.{}", self.major, self.minor)
|
||||
<Self as fmt::Debug>::fmt(self, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,8 +124,12 @@ impl FromStr for Version {
|
||||
type Err = ParseIntError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let (major, minor) = s.split_once('.').unwrap_or((s, "0"));
|
||||
Ok(Self::new(major.parse()?, minor.parse()?))
|
||||
let (major, tail) = s.split_once('.').unwrap_or((s, "0"));
|
||||
let (minor, patch) = tail.split_once('.').unwrap_or((tail, "0"));
|
||||
let major = major.parse()?;
|
||||
let minor = minor.parse()?;
|
||||
let patch = patch.parse()?;
|
||||
Ok(Self::with_patch(major, minor, patch))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,13 +9,13 @@ use super::Error;
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct ChallengeResponse {
|
||||
pub master_challenge: u32,
|
||||
pub server_challenge: u32,
|
||||
pub server_challenge: Option<u32>,
|
||||
}
|
||||
|
||||
impl ChallengeResponse {
|
||||
pub const HEADER: &'static [u8] = b"\xff\xff\xff\xffs\n";
|
||||
|
||||
pub fn new(master_challenge: u32, server_challenge: u32) -> Self {
|
||||
pub fn new(master_challenge: u32, server_challenge: Option<u32>) -> Self {
|
||||
Self {
|
||||
master_challenge,
|
||||
server_challenge,
|
||||
@ -26,7 +26,11 @@ impl ChallengeResponse {
|
||||
let mut cur = Cursor::new(src);
|
||||
cur.expect(Self::HEADER)?;
|
||||
let master_challenge = cur.get_u32_le()?;
|
||||
let server_challenge = cur.get_u32_le()?;
|
||||
let server_challenge = if cur.remaining() == 4 {
|
||||
Some(cur.get_u32_le()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
cur.expect_empty()?;
|
||||
Ok(Self {
|
||||
master_challenge,
|
||||
@ -35,11 +39,13 @@ impl ChallengeResponse {
|
||||
}
|
||||
|
||||
pub fn encode<const N: usize>(&self, buf: &mut [u8; N]) -> Result<usize, Error> {
|
||||
Ok(CursorMut::new(buf)
|
||||
.put_bytes(Self::HEADER)?
|
||||
.put_u32_le(self.master_challenge)?
|
||||
.put_u32_le(self.server_challenge)?
|
||||
.pos())
|
||||
let mut cur = CursorMut::new(buf);
|
||||
cur.put_bytes(Self::HEADER)?;
|
||||
cur.put_u32_le(self.master_challenge)?;
|
||||
if let Some(server_challenge) = self.server_challenge {
|
||||
cur.put_u32_le(server_challenge)?;
|
||||
}
|
||||
Ok(cur.pos())
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,7 +228,21 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn challenge_response() {
|
||||
let p = ChallengeResponse::new(0x12345678, 0x87654321);
|
||||
let p = ChallengeResponse::new(0x12345678, Some(0x87654321));
|
||||
let mut buf = [0; 512];
|
||||
let n = p.encode(&mut buf).unwrap();
|
||||
assert_eq!(ChallengeResponse::decode(&buf[..n]), Ok(p));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn challenge_response_old() {
|
||||
let s = b"\xff\xff\xff\xffs\n\x78\x56\x34\x12";
|
||||
assert_eq!(
|
||||
ChallengeResponse::decode(s),
|
||||
Ok(ChallengeResponse::new(0x12345678, None))
|
||||
);
|
||||
|
||||
let p = ChallengeResponse::new(0x12345678, None);
|
||||
let mut buf = [0; 512];
|
||||
let n = p.encode(&mut buf).unwrap();
|
||||
assert_eq!(ChallengeResponse::decode(&buf[..n]), Ok(p));
|
||||
|
@ -13,29 +13,35 @@ use super::Error;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Challenge {
|
||||
pub server_challenge: u32,
|
||||
pub server_challenge: Option<u32>,
|
||||
}
|
||||
|
||||
impl Challenge {
|
||||
pub const HEADER: &'static [u8] = b"q\xff";
|
||||
|
||||
pub fn new(server_challenge: u32) -> Self {
|
||||
pub fn new(server_challenge: Option<u32>) -> Self {
|
||||
Self { server_challenge }
|
||||
}
|
||||
|
||||
pub fn decode(src: &[u8]) -> Result<Self, Error> {
|
||||
let mut cur = Cursor::new(src);
|
||||
cur.expect(Self::HEADER)?;
|
||||
let server_challenge = cur.get_u32_le()?;
|
||||
let server_challenge = if cur.remaining() == 4 {
|
||||
Some(cur.get_u32_le()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
cur.expect_empty()?;
|
||||
Ok(Self { server_challenge })
|
||||
}
|
||||
|
||||
pub fn encode<const N: usize>(&self, buf: &mut [u8; N]) -> Result<usize, Error> {
|
||||
Ok(CursorMut::new(buf)
|
||||
.put_bytes(Self::HEADER)?
|
||||
.put_u32_le(self.server_challenge)?
|
||||
.pos())
|
||||
let mut cur = CursorMut::new(buf);
|
||||
cur.put_bytes(Self::HEADER)?;
|
||||
if let Some(server_challenge) = self.server_challenge {
|
||||
cur.put_u32_le(server_challenge)?;
|
||||
}
|
||||
Ok(cur.pos())
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,7 +270,15 @@ where
|
||||
b"map" => ret.map = cur.get_key_value()?,
|
||||
b"type" => ret.server_type = cur.get_key_value()?,
|
||||
b"os" => ret.os = cur.get_key_value()?,
|
||||
b"version" => ret.version = cur.get_key_value()?,
|
||||
b"version" => {
|
||||
ret.version = cur
|
||||
.get_key_value()
|
||||
.map_err(|e| {
|
||||
debug!("invalid server version");
|
||||
e
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
b"region" => ret.region = cur.get_key_value()?,
|
||||
b"product" => ret.product = cur.get_key_value()?,
|
||||
b"bots" => ret.flags.set(ServerFlags::BOTS, cur.get_key_value()?),
|
||||
@ -460,12 +474,23 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn challenge() {
|
||||
let p = Challenge::new(0x12345678);
|
||||
let p = Challenge::new(Some(0x12345678));
|
||||
let mut buf = [0; 128];
|
||||
let n = p.encode(&mut buf).unwrap();
|
||||
assert_eq!(Challenge::decode(&buf[..n]), Ok(p));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn challenge_old() {
|
||||
let s = b"q\xff";
|
||||
assert_eq!(Challenge::decode(s), Ok(Challenge::new(None)));
|
||||
|
||||
let p = Challenge::new(None);
|
||||
let mut buf = [0; 128];
|
||||
let n = p.encode(&mut buf).unwrap();
|
||||
assert_eq!(&buf[..n], b"q\xff");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn server_add() {
|
||||
let p = ServerAdd {
|
||||
|
Loading…
x
Reference in New Issue
Block a user