Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add traits that enable object like parsing/serializing of game query packets #148

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
79 changes: 79 additions & 0 deletions examples/unreal2server.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/// ! Pretend to be an unreal 2 server by using the ToPacket/FromPacket trait.
use std::fmt::Debug;
use std::net::{SocketAddr, UdpSocket};

use gamedig::protocols::types::{FromPacket, ToPacket};
use gamedig::protocols::unreal2::{
MutatorsAndRules,
PacketKind,
PacketRequest,
PacketResponse,
Player,
Players,
ServerInfo,
};

type GResult<T> = Result<T, Box<dyn std::error::Error>>;

fn send_response<T: Into<PacketResponse<I>>, I: ToPacket + Debug>(
socket: &UdpSocket,
client: SocketAddr,
response: T,
) -> GResult<()> {
let response = response.into();

println!("Sending: {:?}", response);

socket.send_to(&response.as_packet()?, client)?;

Ok(())
}

fn main() -> GResult<()> {
let socket = UdpSocket::bind("0.0.0.0:7777")?;

let mut buf = [0; 100];

loop {
let (size, client) = socket.recv_from(&mut buf)?;
let request = PacketRequest::from_packet(&buf[.. size])?;
println!("Recieved {:?}", request);

match request.packet_type {
PacketKind::ServerInfo => {
send_response(
&socket,
client,
ServerInfo {
server_id: 69,
ip: String::from("test.server"),
game_port: 7776,
query_port: 7777,
name: String::from("Test server"),
map: String::from("No map"),
game_type: String::from("None"),
num_players: 1,
max_players: 5,
},
)
}
PacketKind::MutatorsAndRules => send_response(&socket, client, MutatorsAndRules::default()),
PacketKind::Players => {
send_response(
&socket,
client,
Players {
players: vec![Player {
id: 6,
name: String::from("Tom"),
ping: u32::MAX,
score: -1,
stats_id: 1,
}],
bots: vec![],
},
)
}
}?;
}
}
2 changes: 2 additions & 0 deletions src/errors/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ pub enum GDErrorKind {
JsonParse,
/// Couldn't parse a value.
TypeParse,
/// Out of memory.
OutOfMemory,
}

impl GDErrorKind {
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub mod services;
mod buffer;
mod socket;
mod utils;
mod wbuffer;

pub use errors::*;
#[cfg(feature = "games")]
Expand Down
26 changes: 26 additions & 0 deletions src/protocols/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,3 +366,29 @@ mod tests {
let _: valve::GatheringSettings = settings.into();
}
}

/// Allows a type to be represented as a u8 slice, and sent over the network as
/// a packet.
pub trait ToPacket: Sized {
/// Encode self as raw bytes to be sent as a packet.
fn as_packet(&self) -> GDResult<Vec<u8>>;
}

/// Allow creating a type from raw u8 bytes (a packet).
pub trait FromPacket: Sized {
/// Parse the packet bytes to create a new value.
fn from_packet(packet: &[u8]) -> GDResult<Self>;
}

/// Allow extending a pre-existing value using raw u8 bytes (a packet).
pub trait ExtendFromPacket<'a> {
/// The type of the value to be extended (without &mut).
type Input;
/// The type the extend function will return, mainly for use with types
/// where an inner value is being extended, otherwise unit type can be
/// returned.
type Output: Sized;
/// Extend the input value using the packet's bytes and return the an Output
/// value.
fn extend_from_packet(packet: &[u8], input: &'a mut Self::Input) -> GDResult<Self::Output>;
}
3 changes: 3 additions & 0 deletions src/protocols/unreal2/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
/// Raw packet types used by the implementation.
pub mod packets;
/// The implementation.
pub mod protocol;
/// All types used by the implementation.
pub mod types;

pub use packets::*;
pub use protocol::*;
pub use types::*;

Expand Down
Loading