1
0
Fork 0
mirror of https://codeberg.org/demostf/parser.git synced 2026-06-04 02:24:12 +02:00

packet parsers

This commit is contained in:
Robin Appelman 2019-02-25 23:20:51 +01:00
commit b41bb56822
19 changed files with 626 additions and 64 deletions

View file

@ -20,4 +20,4 @@ impl<'a> Parse<'a> for ConsoleCmdPacket {
let len = stream.read(32)?;
stream.skip(len).map_err(ParseError::from)
}
}
}

View file

@ -0,0 +1,91 @@
use crate::{Parse, ParseError, ParserState, Result, Stream};
use crate::demo::sendprop::{SendPropDefinition, SendPropFlag, SendPropType};
pub struct ServerClass {
id: u32,
name: String,
data_table: String,
}
pub struct SendTable {
name: String,
props: Vec<SendPropDefinition>,
needs_decoder: bool,
flattened_props: Option<Vec<SendPropDefinition>>,
}
pub struct DataTablePacket {
tick: u32,
tables: Vec<SendTable>,
server_classes: Vec<ServerClass>,
}
impl<'a> Parse<'a> for DataTablePacket {
fn parse(stream: &mut Stream<'a>, state: &ParserState<'a>) -> Result<Self> {
let tick = stream.read(32)?;
let _len = stream.read::<u32>(32)?;
let mut tables = vec![];
while stream.read_bool()? {
let needs_decoder = stream.read_bool()?;
let name = stream.read_string(None)?;
let prop_count = stream.read(10)?;
let mut array_element_prop = None;
let mut props = Vec::with_capacity(prop_count);
for i in 0..prop_count {
let prop: SendPropDefinition = SendPropDefinition::parse(stream, state, name.clone())?;
if prop.flags.contains(SendPropFlag::InsideArray) {
if array_element_prop.is_some() || prop.flags.contains(SendPropFlag::ChangesOften) {
return Err(ParseError::InvalidSendPropArray);
}
array_element_prop = Some(prop);
} else if let Some(array_element) = array_element_prop {
if prop.prop_type == SendPropType::Array {
return Err(ParseError::InvalidSendPropArray);
}
array_element_prop = None;
props.push(prop.with_array_property(array_element));
} else {
props.push(prop);
}
}
let table = SendTable {
name,
flattened_props: None,
needs_decoder,
props,
};
tables.push(table);
}
// TODO linked tables?
let server_class_count = stream.read(16)?;
let mut server_classes = Vec::with_capacity(server_class_count);
for i in 0..server_class_count {
let id = stream.read(16)?;
let name = stream.read_string(None)?;
let data_table = stream.read_string(None)?;
server_classes.push(ServerClass {
id,
name,
data_table,
});
}
Ok(DataTablePacket {
tick,
tables,
server_classes,
})
}
fn skip(stream: &mut Stream) -> Result<()> {
let _ = stream.skip(32)?;
let len = stream.read(32)?;
stream.skip(len).map_err(ParseError::from)
}
}

View file

@ -0,0 +1,59 @@
use crate::{Parse, ParseError, ParserState, Result, Stream};
use crate::demo::vector::Vector;
pub struct Message;
pub struct MessagePacket {
tick: u32,
messages: Vec<Message>,
view_origin: (Vector, Vector),
view_angles: (Vector, Vector),
local_view_angles: (Vector, Vector),
sequence_in: u32,
sequence_out: u32,
flags: u32, // TODO
}
impl<'a> Parse<'a> for MessagePacket {
fn parse(stream: &mut Stream<'a>, state: &ParserState<'a>) -> Result<Self> {
let tick = stream.read(32)?;
let flags = stream.read(32)?;
let view_origin_1 = Vector::parse(stream, state)?;
let view_angle_1 = Vector::parse(stream, state)?;
let local_view_angle_1 = Vector::parse(stream, state)?;
let view_origin = (Vector::parse(stream, state)?, view_origin_1);
let view_angles = (Vector::parse(stream, state)?, view_angle_1);
let local_view_angles = (Vector::parse(stream, state)?, local_view_angle_1);
let sequence_in = stream.read(32)?;
let sequence_out = stream.read(32)?;
let length: usize = stream.read(32)?;
let _ = stream.skip(length).map_err(ParseError::from);
let mut messages = vec![];
Ok(MessagePacket {
tick,
messages,
view_origin,
view_angles,
local_view_angles,
sequence_in,
sequence_out,
flags,
})
}
fn skip(stream: &mut Stream) -> Result<()> {
let _ = stream.skip(32 * 2)?;
for i in 0..6 {
Vector::skip(stream)?;
}
let _ = stream.skip(32 * 2)?;
let length: usize = stream.read(32)?;
stream.skip(length).map_err(ParseError::from)
}
}

View file

@ -1,21 +1,39 @@
use crate::{Parse, ParseError, ParserState, Result, Stream};
use enum_primitive_derive::Primitive;
use num_traits::FromPrimitive;
use self::stop::Stop;
mod stop;
mod synctick;
mod consolecmd;
mod usercmd;
mod stringtable;
use crate::{Parse, ParseError, ParserState, Result, Stream};
pub enum Packet {
Stop(Stop)
use self::consolecmd::ConsoleCmdPacket;
use self::datatable::DataTablePacket;
use self::message::MessagePacket;
use self::stop::StopPacket;
use self::stringtable::StringTablePacket;
use self::synctick::SyncTickPacket;
use self::usercmd::UserCmdPacket;
pub mod consolecmd;
pub mod stop;
pub mod stringtable;
pub mod synctick;
pub mod usercmd;
pub mod datatable;
pub mod message;
pub enum Packet<'a> {
Sigon(MessagePacket),
Message(MessagePacket),
SyncTick(SyncTickPacket),
ConsoleCmd(ConsoleCmdPacket),
UserCmd(UserCmdPacket),
DataTables(DataTablePacket),
Stop(StopPacket),
StringTables(StringTablePacket<'a>),
}
#[derive(Primitive)]
pub enum PacketType {
Sigon = 1,
Packet = 2,
Message = 2,
SyncTick = 3,
ConsoleCmd = 4,
UserCmd = 5,
@ -24,23 +42,44 @@ pub enum PacketType {
StringTables = 8,
}
impl Packet {
fn read_type(stream: &mut Stream) -> Result<PacketType> {
impl Parse<'_> for PacketType {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
let raw = stream.read(8)?;
let packet_type: Option<PacketType> = PacketType::from_u8(raw);
packet_type.ok_or(ParseError::InvalidPacketType(raw))
let prop_type: Option<PacketType> = PacketType::from_u8(raw);
prop_type.ok_or(ParseError::InvalidPacketType(raw))
}
fn skip(stream: &mut Stream) -> Result<()> {
stream.skip(8).map_err(ParseError::from)
}
}
//impl Parse for Packet {
// fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
// let packet_type = Packet::read_type(stream);
// match packet_type {
// Sigon => {}
// }
// }
//
// fn skip(stream: &mut Stream) -> Result<()> {
// Ok(())
// }
//}
impl<'a> Parse<'a> for Packet<'a> {
fn parse(stream: &mut Stream<'a>, state: &ParserState<'a>) -> Result<Self> {
let packet_type = PacketType::parse(stream, state)?;
Ok(match packet_type {
PacketType::Sigon => Packet::Sigon(MessagePacket::parse(stream, state)?),
PacketType::Message => Packet::Message(MessagePacket::parse(stream, state)?),
PacketType::SyncTick => Packet::SyncTick(SyncTickPacket::parse(stream, state)?),
PacketType::ConsoleCmd => Packet::ConsoleCmd(ConsoleCmdPacket::parse(stream, state)?),
PacketType::UserCmd => Packet::UserCmd(UserCmdPacket::parse(stream, state)?),
PacketType::DataTables => Packet::DataTables(DataTablePacket::parse(stream, state)?),
PacketType::Stop => Packet::Stop(StopPacket::parse(stream, state)?),
PacketType::StringTables => Packet::StringTables(StringTablePacket::parse(stream, state)?),
})
}
fn skip(stream: &mut Stream) -> Result<()> {
let packet_type = PacketType::parse(stream, &ParserState::new(&stream))?;
match packet_type {
PacketType::Sigon => MessagePacket::skip(stream),
PacketType::Message => MessagePacket::skip(stream),
PacketType::SyncTick => SyncTickPacket::skip(stream),
PacketType::ConsoleCmd => ConsoleCmdPacket::skip(stream),
PacketType::UserCmd => UserCmdPacket::skip(stream),
PacketType::DataTables => DataTablePacket::skip(stream),
PacketType::Stop => StopPacket::skip(stream),
PacketType::StringTables => StringTablePacket::skip(stream),
}
}
}

View file

@ -1,13 +1,13 @@
use crate::{Parse, ParserState, Result, Stream};
pub struct Stop;
pub struct StopPacket;
impl<'a> Parse<'a> for Stop {
impl<'a> Parse<'a> for StopPacket {
fn parse(_stream: &mut Stream, _state: &ParserState) -> Result<Self> {
Ok(Stop)
Ok(StopPacket)
}
fn skip(_stream: &mut Stream) -> Result<()> {
Ok(())
}
}
}

View file

@ -56,10 +56,7 @@ impl<'a> StringTableEntry<'a> {
} else {
None
};
Ok(StringTableEntry {
text,
extra_data,
})
Ok(StringTableEntry { text, extra_data })
}
}
@ -77,10 +74,7 @@ impl<'a> Parse<'a> for StringTablePacket<'a> {
for _ in 0..count {
tables.push(StringTable::parse(stream)?);
}
Ok(StringTablePacket {
tick,
tables,
})
Ok(StringTablePacket { tick, tables })
}
fn skip(stream: &mut Stream) -> Result<()> {
@ -88,4 +82,4 @@ impl<'a> Parse<'a> for StringTablePacket<'a> {
let length = stream.read(32)?;
stream.skip(length).map_err(ParseError::from)
}
}
}

View file

@ -1,17 +1,17 @@
use crate::{Parse, ParseError, ParserState, Result, Stream};
pub struct SyncTickPacket {
tick: u32
tick: u32,
}
impl<'a> Parse<'a> for SyncTickPacket {
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
Ok(SyncTickPacket {
tick: stream.read(32)?
tick: stream.read(32)?,
})
}
fn skip(stream: &mut Stream) -> Result<()> {
stream.skip(32).map_err(ParseError::from)
}
}
}

View file

@ -3,7 +3,7 @@ use crate::{Parse, ParseError, ParserState, Result, Stream};
pub struct UserCmdPacket {
tick: u32,
command: String,
sequence_out: u32
sequence_out: u32,
}
impl<'a> Parse<'a> for UserCmdPacket {
@ -23,4 +23,4 @@ impl<'a> Parse<'a> for UserCmdPacket {
let len = stream.read(32)?;
stream.skip(len).map_err(ParseError::from)
}
}
}