Browse Source

protocol: support old servers (protocol 48)

ipv6
Denis Drakhnia 1 year ago
parent
commit
5778bbc714
  1. 6
      master/src/master_server.rs
  2. 27
      protocol/src/filter.rs
  3. 38
      protocol/src/master.rs
  4. 43
      protocol/src/server.rs

6
master/src/master_server.rs

@ -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(())

27
protocol/src/filter.rs

@ -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))
} }
} }

38
protocol/src/master.rs

@ -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));

43
protocol/src/server.rs

@ -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…
Cancel
Save