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 {
|
let p = server::GetServerInfoResponse {
|
||||||
map: self.update_map.as_ref(),
|
map: self.update_map.as_ref(),
|
||||||
host: self.update_title.as_ref(),
|
host: self.update_title.as_ref(),
|
||||||
protocol: 49,
|
protocol: 48, // XXX: how to detect what version client will accept?
|
||||||
dm: true,
|
dm: true,
|
||||||
maxcl: 32,
|
maxcl: 32,
|
||||||
gamedir: "valve",
|
gamedir: "valve", // XXX: probably must be specific for client...
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
trace!("{}: send {:?}", from, p);
|
trace!("{}: send {:?}", from, p);
|
||||||
@ -334,7 +334,7 @@ impl MasterServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debug!("invalid packet: \"{}\"", Str(src));
|
debug!("{}: invalid packet: \"{}\"", from, Str(src));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -87,23 +87,36 @@ impl<T> From<&ServerAdd<T>> for FilterFlags {
|
|||||||
pub struct Version {
|
pub struct Version {
|
||||||
pub major: u8,
|
pub major: u8,
|
||||||
pub minor: u8,
|
pub minor: u8,
|
||||||
|
pub patch: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Version {
|
impl Version {
|
||||||
pub const fn new(major: u8, minor: u8) -> Self {
|
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 {
|
impl fmt::Debug for Version {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
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 {
|
impl fmt::Display for Version {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
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;
|
type Err = ParseIntError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
let (major, minor) = s.split_once('.').unwrap_or((s, "0"));
|
let (major, tail) = s.split_once('.').unwrap_or((s, "0"));
|
||||||
Ok(Self::new(major.parse()?, minor.parse()?))
|
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)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct ChallengeResponse {
|
pub struct ChallengeResponse {
|
||||||
pub master_challenge: u32,
|
pub master_challenge: u32,
|
||||||
pub server_challenge: u32,
|
pub server_challenge: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChallengeResponse {
|
impl ChallengeResponse {
|
||||||
pub const HEADER: &'static [u8] = b"\xff\xff\xff\xffs\n";
|
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 {
|
Self {
|
||||||
master_challenge,
|
master_challenge,
|
||||||
server_challenge,
|
server_challenge,
|
||||||
@ -26,7 +26,11 @@ impl ChallengeResponse {
|
|||||||
let mut cur = Cursor::new(src);
|
let mut cur = Cursor::new(src);
|
||||||
cur.expect(Self::HEADER)?;
|
cur.expect(Self::HEADER)?;
|
||||||
let master_challenge = cur.get_u32_le()?;
|
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()?;
|
cur.expect_empty()?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
master_challenge,
|
master_challenge,
|
||||||
@ -35,11 +39,13 @@ impl ChallengeResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode<const N: usize>(&self, buf: &mut [u8; N]) -> Result<usize, Error> {
|
pub fn encode<const N: usize>(&self, buf: &mut [u8; N]) -> Result<usize, Error> {
|
||||||
Ok(CursorMut::new(buf)
|
let mut cur = CursorMut::new(buf);
|
||||||
.put_bytes(Self::HEADER)?
|
cur.put_bytes(Self::HEADER)?;
|
||||||
.put_u32_le(self.master_challenge)?
|
cur.put_u32_le(self.master_challenge)?;
|
||||||
.put_u32_le(self.server_challenge)?
|
if let Some(server_challenge) = self.server_challenge {
|
||||||
.pos())
|
cur.put_u32_le(server_challenge)?;
|
||||||
|
}
|
||||||
|
Ok(cur.pos())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +228,21 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn challenge_response() {
|
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 mut buf = [0; 512];
|
||||||
let n = p.encode(&mut buf).unwrap();
|
let n = p.encode(&mut buf).unwrap();
|
||||||
assert_eq!(ChallengeResponse::decode(&buf[..n]), Ok(p));
|
assert_eq!(ChallengeResponse::decode(&buf[..n]), Ok(p));
|
||||||
|
@ -13,29 +13,35 @@ use super::Error;
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Challenge {
|
pub struct Challenge {
|
||||||
pub server_challenge: u32,
|
pub server_challenge: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Challenge {
|
impl Challenge {
|
||||||
pub const HEADER: &'static [u8] = b"q\xff";
|
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 }
|
Self { server_challenge }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode(src: &[u8]) -> Result<Self, Error> {
|
pub fn decode(src: &[u8]) -> Result<Self, Error> {
|
||||||
let mut cur = Cursor::new(src);
|
let mut cur = Cursor::new(src);
|
||||||
cur.expect(Self::HEADER)?;
|
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()?;
|
cur.expect_empty()?;
|
||||||
Ok(Self { server_challenge })
|
Ok(Self { server_challenge })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode<const N: usize>(&self, buf: &mut [u8; N]) -> Result<usize, Error> {
|
pub fn encode<const N: usize>(&self, buf: &mut [u8; N]) -> Result<usize, Error> {
|
||||||
Ok(CursorMut::new(buf)
|
let mut cur = CursorMut::new(buf);
|
||||||
.put_bytes(Self::HEADER)?
|
cur.put_bytes(Self::HEADER)?;
|
||||||
.put_u32_le(self.server_challenge)?
|
if let Some(server_challenge) = self.server_challenge {
|
||||||
.pos())
|
cur.put_u32_le(server_challenge)?;
|
||||||
|
}
|
||||||
|
Ok(cur.pos())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +270,15 @@ where
|
|||||||
b"map" => ret.map = cur.get_key_value()?,
|
b"map" => ret.map = cur.get_key_value()?,
|
||||||
b"type" => ret.server_type = cur.get_key_value()?,
|
b"type" => ret.server_type = cur.get_key_value()?,
|
||||||
b"os" => ret.os = 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"region" => ret.region = cur.get_key_value()?,
|
||||||
b"product" => ret.product = cur.get_key_value()?,
|
b"product" => ret.product = cur.get_key_value()?,
|
||||||
b"bots" => ret.flags.set(ServerFlags::BOTS, cur.get_key_value()?),
|
b"bots" => ret.flags.set(ServerFlags::BOTS, cur.get_key_value()?),
|
||||||
@ -460,12 +474,23 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn challenge() {
|
fn challenge() {
|
||||||
let p = Challenge::new(0x12345678);
|
let p = Challenge::new(Some(0x12345678));
|
||||||
let mut buf = [0; 128];
|
let mut buf = [0; 128];
|
||||||
let n = p.encode(&mut buf).unwrap();
|
let n = p.encode(&mut buf).unwrap();
|
||||||
assert_eq!(Challenge::decode(&buf[..n]), Ok(p));
|
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]
|
#[test]
|
||||||
fn server_add() {
|
fn server_add() {
|
||||||
let p = ServerAdd {
|
let p = ServerAdd {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user