mirror of
https://github.com/RustySamovar/RustySamovar.git
synced 2024-11-25 11:36:46 +00:00
First working attempt
This commit is contained in:
parent
346afbee3a
commit
518b68cf25
6
.gitignore
vendored
6
.gitignore
vendored
@ -8,3 +8,9 @@ Cargo.lock
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
|
||||
# *.proto files
|
||||
/protobuf/
|
||||
|
||||
# keys
|
||||
/keys/
|
||||
|
15
Cargo.toml
Normal file
15
Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "RustySamovar"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
kcp = { path = "../kcp" }
|
||||
mhycrypt = { path = "../mhycrypt" }
|
||||
prost = "0.8"
|
||||
bytes = "1.1.0"
|
||||
|
||||
[build-dependencies]
|
||||
prost-build = { version = "0.8.0" }
|
5
build.rs
Normal file
5
build.rs
Normal file
@ -0,0 +1,5 @@
|
||||
use std::io::Result;
|
||||
fn main() -> Result<()> {
|
||||
prost_build::compile_protos(&["protobuf/packet_header.proto"], &["protobuf/"])?;
|
||||
Ok(())
|
||||
}
|
13
src/main.rs
Normal file
13
src/main.rs
Normal file
@ -0,0 +1,13 @@
|
||||
mod server;
|
||||
mod utils;
|
||||
|
||||
pub mod proto {
|
||||
include!(concat!(env!("OUT_DIR"), "/proto.rs"));
|
||||
}
|
||||
|
||||
use server::NetworkServer;
|
||||
|
||||
fn main() {
|
||||
let mut ns = NetworkServer::new("0.0.0.0", 9696).unwrap();
|
||||
ns.run().expect("Failed to serve!");
|
||||
}
|
101
src/server/client_connection.rs
Normal file
101
src/server/client_connection.rs
Normal file
@ -0,0 +1,101 @@
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::fs;
|
||||
use std::net::SocketAddr;
|
||||
use std::net::UdpSocket;
|
||||
use std::io::Write;
|
||||
use std::time::SystemTime;
|
||||
use std::convert::TryInto;
|
||||
|
||||
extern crate kcp;
|
||||
extern crate mhycrypt;
|
||||
|
||||
use kcp::Kcp;
|
||||
|
||||
pub struct ClientConnection {
|
||||
conv: u32,
|
||||
token: u32,
|
||||
ikcp: Kcp<Source>,
|
||||
established_time: SystemTime,
|
||||
key: [u8; 0x1000],
|
||||
}
|
||||
|
||||
pub struct Source
|
||||
{
|
||||
address: Option<SocketAddr>,
|
||||
socket: UdpSocket,
|
||||
}
|
||||
|
||||
impl Write for Source {
|
||||
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
|
||||
return self.socket.send_to(data, self.address.expect("Unknown destination address!"));
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientConnection {
|
||||
pub fn new(socket: UdpSocket, conv: u32, token: u32) -> ClientConnection {
|
||||
let s = Source {
|
||||
address: None,
|
||||
socket: socket,
|
||||
};
|
||||
|
||||
return ClientConnection {
|
||||
conv: conv,
|
||||
token: token,
|
||||
ikcp: Kcp::new(conv, token, s),
|
||||
established_time: SystemTime::now(),
|
||||
key: ClientConnection::read_key("master").try_into().expect("Incorrect master key"),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn update_source(&mut self, new_source: SocketAddr) {
|
||||
self.ikcp.output.0.address = Some(new_source);
|
||||
}
|
||||
|
||||
pub fn process_udp_packet(&mut self, data: &[u8]) -> Vec<Vec<u8>> {
|
||||
let mut packets: Vec<Vec<u8>> = Vec::new();
|
||||
self.ikcp.input(data).unwrap();
|
||||
self.ikcp.update(self.elapsed_time_millis()).unwrap();
|
||||
self.ikcp.flush().unwrap();
|
||||
loop {
|
||||
let mut buf = [0u8; 0x20000];
|
||||
match self.ikcp.recv(&mut buf) {
|
||||
Err(_) => break,
|
||||
Ok(size) => {
|
||||
mhycrypt::mhy_xor(&mut buf[..size], &self.key);
|
||||
let data = buf[..size].to_owned();
|
||||
packets.push(data);
|
||||
},
|
||||
}
|
||||
}
|
||||
self.ikcp.update(self.elapsed_time_millis()).unwrap();
|
||||
return packets;
|
||||
}
|
||||
|
||||
pub fn update_key(&mut self, seed: u64) {
|
||||
mhycrypt::mhy_generate_key(&mut self.key, seed, false);
|
||||
}
|
||||
|
||||
fn read_key(key_name: &str) -> Vec<u8> {
|
||||
let filename = format!("{}/{}.key", "keys", key_name);
|
||||
let mut f = fs::File::open(&filename).expect("no file found");
|
||||
let metadata = fs::metadata(&filename).expect("unable to read metadata");
|
||||
let mut buffer = vec![0; metadata.len() as usize];
|
||||
f.read(&mut buffer).expect("buffer overflow");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
fn elapsed_time_millis(&self) -> u32 {
|
||||
return SystemTime::now().duration_since(self.established_time).unwrap().as_millis().try_into().unwrap();
|
||||
}
|
||||
|
||||
pub fn send_udp_packet(&mut self, data: &[u8]) {
|
||||
let mut buf = data.to_owned();
|
||||
mhycrypt::mhy_xor(&mut buf, &self.key);
|
||||
self.ikcp.send(&buf).expect("Failed to send data!");
|
||||
}
|
||||
}
|
65
src/server/game_server.rs
Normal file
65
src/server/game_server.rs
Normal file
@ -0,0 +1,65 @@
|
||||
use std::sync::mpsc;
|
||||
use std::thread;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
|
||||
use crate::server::IpcMessage;
|
||||
|
||||
pub struct GameWorld {
|
||||
packets_to_send_tx: mpsc::Sender<IpcMessage>,
|
||||
}
|
||||
|
||||
impl GameWorld {
|
||||
pub fn new(packets_to_send_tx: mpsc::Sender<IpcMessage>) -> GameWorld {
|
||||
let gm = GameWorld {
|
||||
packets_to_send_tx: packets_to_send_tx,
|
||||
};
|
||||
|
||||
return gm;
|
||||
}
|
||||
|
||||
pub fn process_packet(&mut self, conv: u32, packet_id: u16, metadata: Vec<u8>, data: Vec<u8>) {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GameServer {
|
||||
packets_to_process_rx: mpsc::Receiver<IpcMessage>,
|
||||
packets_to_send_tx: mpsc::Sender<IpcMessage>,
|
||||
worlds: HashMap<u32, GameWorld>,
|
||||
}
|
||||
|
||||
impl GameServer {
|
||||
pub fn new(packets_to_process_rx: mpsc::Receiver<IpcMessage>, packets_to_send_tx: mpsc::Sender<IpcMessage>) -> GameServer {
|
||||
let gs = GameServer {
|
||||
packets_to_process_rx: packets_to_process_rx,
|
||||
packets_to_send_tx: packets_to_send_tx,
|
||||
worlds: HashMap::new(),
|
||||
};
|
||||
|
||||
return gs;
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
let world_processor = thread::spawn(move || {
|
||||
println!("Starting world processor");
|
||||
// TODO: Load worlds!
|
||||
loop {
|
||||
}
|
||||
});
|
||||
|
||||
loop {
|
||||
let IpcMessage(conv, packet_id, metadata, data) = self.packets_to_process_rx.recv().unwrap();
|
||||
|
||||
// TODO: each conv will have a distinct world!
|
||||
let world = match self.worlds.entry(conv) {
|
||||
Occupied(world) => world.into_mut(),
|
||||
Vacant(entry) => {
|
||||
let mut world = GameWorld::new(self.packets_to_send_tx.clone());
|
||||
entry.insert(world)
|
||||
},
|
||||
};
|
||||
|
||||
world.process_packet(conv, packet_id, metadata, data);
|
||||
}
|
||||
}
|
||||
}
|
1
src/server/ipc_message.rs
Normal file
1
src/server/ipc_message.rs
Normal file
@ -0,0 +1 @@
|
||||
pub struct IpcMessage(pub u32, pub u16, pub Vec<u8>, pub Vec<u8>);
|
9
src/server/mod.rs
Normal file
9
src/server/mod.rs
Normal file
@ -0,0 +1,9 @@
|
||||
mod network_server;
|
||||
mod game_server;
|
||||
mod client_connection;
|
||||
mod ipc_message;
|
||||
|
||||
pub use self::network_server::NetworkServer;
|
||||
pub use self::game_server::GameServer;
|
||||
pub use self::client_connection::ClientConnection;
|
||||
pub use self::ipc_message::IpcMessage;
|
168
src/server/network_server.rs
Normal file
168
src/server/network_server.rs
Normal file
@ -0,0 +1,168 @@
|
||||
use std::fmt;
|
||||
use std::net::UdpSocket;
|
||||
use std::net::SocketAddr;
|
||||
use std::collections::HashMap;
|
||||
use std::io::Cursor;
|
||||
use std::thread;
|
||||
use std::sync::mpsc;
|
||||
use std::sync::{Arc, RwLock, Mutex};
|
||||
|
||||
use crate::utils::HandshakePacket;
|
||||
use crate::utils::DataPacket;
|
||||
use crate::server::ClientConnection;
|
||||
use crate::server::IpcMessage;
|
||||
|
||||
use crate::proto::PacketHead;
|
||||
|
||||
use prost::Message;
|
||||
|
||||
extern crate kcp;
|
||||
|
||||
pub struct NetworkServer {
|
||||
socket: UdpSocket,
|
||||
clients: Arc<Mutex<HashMap<u32,ClientConnection>>>,
|
||||
packets_to_process_tx: Option<mpsc::Sender<IpcMessage>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NetworkServerError {
|
||||
reason: String,
|
||||
}
|
||||
|
||||
impl NetworkServerError {
|
||||
pub fn new(reason: &str) -> NetworkServerError {
|
||||
return NetworkServerError {reason: reason.to_string()};
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for NetworkServerError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "NetworkServerError: {}", self.reason)
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkServer {
|
||||
pub fn new(host: &str, port: i16) -> Result<NetworkServer, NetworkServerError> {
|
||||
let gs = NetworkServer {
|
||||
socket: match UdpSocket::bind(format!("{}:{}", host, port).to_string()) {
|
||||
Ok(socket) => socket,
|
||||
Err(e) => return Err(NetworkServerError::new(format!("Failed to bind socket: {}", e).as_str())),
|
||||
},
|
||||
clients: Arc::new(Mutex::new(HashMap::new())),
|
||||
packets_to_process_tx: None,
|
||||
};
|
||||
|
||||
print!("Connection established\n");
|
||||
|
||||
return Ok(gs);
|
||||
}
|
||||
|
||||
pub fn run(&mut self) -> Result<i16, NetworkServerError> {
|
||||
print!("Starting server\n");
|
||||
|
||||
// Channel for relaying packets from network thread to processing thread
|
||||
let (packets_to_process_tx, packets_to_process_rx) = mpsc::channel();
|
||||
|
||||
// Channel for relaying packets from network thread to processing thread
|
||||
let (packets_to_send_tx, packets_to_send_rx) = mpsc::channel();
|
||||
|
||||
self.packets_to_process_tx = Some(packets_to_process_tx);
|
||||
|
||||
let clients = self.clients.clone();
|
||||
|
||||
let packet_relaying_thread = thread::spawn(move || {
|
||||
loop {
|
||||
let IpcMessage(conv, packet_id, metadata, data) = packets_to_send_rx.recv().unwrap();
|
||||
|
||||
let data = DataPacket::new(packet_id, metadata, data);
|
||||
|
||||
match clients.lock().unwrap().get_mut(&conv) {
|
||||
Some(client) => {
|
||||
client.send_udp_packet(&data.to_bytes());
|
||||
|
||||
// TODO: here, if encryption key was changed, do so
|
||||
},
|
||||
None => panic!("Unknown client conv: {}", conv),
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
let mut buffer = [0u8; 65536];
|
||||
|
||||
loop {
|
||||
match self.socket.recv_from(&mut buffer) {
|
||||
Ok( (bytes_number, source_address) ) => self.process_udp_packet(source_address, &buffer[..bytes_number]),
|
||||
Err(e) => panic!("Failed to receive data: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
//packet_relaying_thread.join().unwrap();
|
||||
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
fn process_udp_packet(&mut self, source_address: SocketAddr, packet_bytes: &[u8]) {
|
||||
print!("Received packet! Len = {}\n", packet_bytes.len());
|
||||
|
||||
let hs_packet = HandshakePacket::new(packet_bytes);
|
||||
|
||||
match hs_packet {
|
||||
Ok(hs_packet) => {
|
||||
print!("Received handshake packet: {:#?}\n", hs_packet);
|
||||
if hs_packet.is_connect() {
|
||||
print!("Sending reply to CONNECT\n");
|
||||
// TODO: assign conv and token!
|
||||
let conv = 0x96969696u32;
|
||||
let token = 0x42424242u32;
|
||||
|
||||
let reply = HandshakePacket::new_conv(conv, token);
|
||||
|
||||
let mut client = ClientConnection::new(self.socket.try_clone().unwrap(), conv, token);
|
||||
client.update_source(source_address);
|
||||
|
||||
self.clients.lock().unwrap().insert(conv, client);
|
||||
|
||||
self.socket.send_to(&reply.to_bytes(), source_address).expect("Failed to send data!");
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
print!("Error constructing handshake: {:#?}", e);
|
||||
let conv = kcp::get_conv(packet_bytes);
|
||||
|
||||
let packets = match self.clients.lock().unwrap().get_mut(&conv) {
|
||||
Some(client) => {
|
||||
client.update_source(source_address);
|
||||
|
||||
client.process_udp_packet(packet_bytes)
|
||||
}
|
||||
None => panic!("Unknown client conv: {}", conv),
|
||||
};
|
||||
|
||||
for packet in packets.iter() {
|
||||
self.process_game_packet(conv, packet);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn process_game_packet(&mut self, conv: u32, packet: &[u8]) {
|
||||
let data = match DataPacket::new_from_bytes(packet) {
|
||||
Ok(data) => data,
|
||||
Err(e) => panic!("Malformed data packet: {:#?}!", e),
|
||||
};
|
||||
|
||||
let head = match PacketHead::decode(&mut Cursor::new(&data.metadata)) {
|
||||
Ok(head) => head,
|
||||
Err(e) => panic!("Malformed packet header: {:#?}!", e),
|
||||
};
|
||||
|
||||
print!("Got packet with header: {:#?} and ID {}\n", head, data.packet_id);
|
||||
|
||||
let sender = match &self.packets_to_process_tx {
|
||||
Some(sender) => sender,
|
||||
None => panic!("Processing queue wasn't set up!"),
|
||||
};
|
||||
|
||||
sender.send( IpcMessage(conv, data.packet_id, data.metadata, data.data) ).unwrap();
|
||||
}
|
||||
}
|
90
src/utils/data_packet.rs
Normal file
90
src/utils/data_packet.rs
Normal file
@ -0,0 +1,90 @@
|
||||
use std::fmt;
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DataDecError {
|
||||
reason: String,
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct DataPacketSmallest // Not actually used, just represents the general structure
|
||||
{
|
||||
start_magic: u16,
|
||||
packet_id: u16,
|
||||
metadata_size: u16,
|
||||
data_size: u32,
|
||||
//metadata: [0u8; metadata_size],
|
||||
//data: [0u8; data_size],
|
||||
end_magic: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DataPacket
|
||||
{
|
||||
pub packet_id: u16,
|
||||
pub metadata: Vec<u8>,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl DataPacket {
|
||||
const DATA_MAGIC_START: u16 = 0x4567;
|
||||
const DATA_MAGIC_END: u16 = 0x89AB;
|
||||
|
||||
pub fn new(packet_id: u16, metadata: Vec<u8>, data: Vec<u8>) -> DataPacket {
|
||||
return DataPacket {
|
||||
packet_id: packet_id,
|
||||
data: data,
|
||||
metadata: metadata,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn new_from_bytes(raw_data: &[u8]) -> Result<DataPacket, DataDecError> {
|
||||
if raw_data.len() < std::mem::size_of::<DataPacketSmallest>() {
|
||||
return Err(DataDecError {reason: "Size is too small!".to_string()});
|
||||
}
|
||||
|
||||
// unwrap() here are valid as we're cutting exactly 4 bytes of data
|
||||
let start_magic = u16::from_be_bytes(raw_data[0..2].try_into().unwrap());
|
||||
let end_magic = u16::from_be_bytes(raw_data[raw_data.len()-2..].try_into().unwrap());
|
||||
|
||||
if (start_magic == DataPacket::DATA_MAGIC_START) && (end_magic == DataPacket::DATA_MAGIC_END) {
|
||||
let packet_id = u16::from_be_bytes(raw_data[2..4].try_into().unwrap());
|
||||
let metadata_size = u16::from_be_bytes(raw_data[4..6].try_into().unwrap()) as usize;
|
||||
let data_size = u32::from_be_bytes(raw_data[6..10].try_into().unwrap()) as usize;
|
||||
|
||||
let expected_size = std::mem::size_of::<DataPacketSmallest>() + metadata_size + data_size;
|
||||
|
||||
if raw_data.len() != expected_size {
|
||||
return Err(DataDecError {reason: format!("Wrong packet size: expected {}, got {} (header {}, payload {})!", expected_size, raw_data.len(), std::mem::size_of::<DataPacketSmallest>(), metadata_size + data_size)});
|
||||
}
|
||||
|
||||
return Ok(DataPacket {
|
||||
packet_id: packet_id,
|
||||
metadata: raw_data[10..metadata_size+10].to_owned(),
|
||||
data: raw_data[metadata_size+10..metadata_size+data_size+10].to_owned(),
|
||||
});
|
||||
} else {
|
||||
return Err(DataDecError {reason: format!("Unknown magic: 0x{:x} 0x{:x}", start_magic, end_magic),});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut ret = Vec::with_capacity(std::mem::size_of::<DataPacketSmallest>() + self.data.len() + self.metadata.len());
|
||||
|
||||
ret.extend_from_slice(&DataPacket::DATA_MAGIC_START.to_be_bytes());
|
||||
ret.extend_from_slice(&self.packet_id.to_be_bytes());
|
||||
ret.extend_from_slice(&(self.metadata.len() as u16).to_be_bytes());
|
||||
ret.extend_from_slice(&(self.data.len() as u32).to_be_bytes());
|
||||
ret.extend_from_slice(&self.metadata);
|
||||
ret.extend_from_slice(&self.data);
|
||||
ret.extend_from_slice(&DataPacket::DATA_MAGIC_END.to_be_bytes());
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for DataPacket {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "packet")
|
||||
}
|
||||
}
|
91
src/utils/handshake_packet.rs
Normal file
91
src/utils/handshake_packet.rs
Normal file
@ -0,0 +1,91 @@
|
||||
use std::fmt;
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HandshakeDecError {
|
||||
reason: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct HandshakePacket
|
||||
{
|
||||
start_magic: u32,
|
||||
param1: u32,
|
||||
param2: u32,
|
||||
data: u32,
|
||||
end_magic: u32,
|
||||
}
|
||||
|
||||
impl HandshakePacket {
|
||||
const HS_MAGIC_CONNECT_START: u32 = 0x000000FF;
|
||||
const HS_MAGIC_CONNECT_END: u32 = 0xFFFFFFFF;
|
||||
const HS_MAGIC_SEND_CONV_START: u32 = 0x00000145;
|
||||
const HS_MAGIC_SEND_CONV_END: u32 = 0x14514545;
|
||||
const HS_MAGIC_DISCONNECT_START: u32 = 0x00000194;
|
||||
const HS_MAGIC_DISCONNECT_END: u32 = 0x19419494;
|
||||
|
||||
const HS_CONNECTION_DATA: u32 = 1234567890;
|
||||
|
||||
pub fn new(raw_data: &[u8]) -> Result<HandshakePacket, HandshakeDecError> {
|
||||
if raw_data.len() != std::mem::size_of::<HandshakePacket>() {
|
||||
return Err(HandshakeDecError {reason: "Size mismatch!".to_string()});
|
||||
}
|
||||
|
||||
// unwrap() here are valid as we're cutting exactly 4 bytes of data
|
||||
let start_magic = u32::from_be_bytes(raw_data[0..4].try_into().unwrap());
|
||||
let param1 = u32::from_be_bytes(raw_data[4..8].try_into().unwrap());
|
||||
let param2 = u32::from_be_bytes(raw_data[8..12].try_into().unwrap());
|
||||
let data = u32::from_be_bytes(raw_data[12..16].try_into().unwrap());
|
||||
let end_magic = u32::from_be_bytes(raw_data[16..20].try_into().unwrap());
|
||||
|
||||
if (start_magic == HandshakePacket::HS_MAGIC_CONNECT_START) && (end_magic == HandshakePacket::HS_MAGIC_CONNECT_END) ||
|
||||
(start_magic == HandshakePacket::HS_MAGIC_SEND_CONV_START) && (end_magic == HandshakePacket::HS_MAGIC_SEND_CONV_END) ||
|
||||
(start_magic == HandshakePacket::HS_MAGIC_DISCONNECT_START) && (end_magic == HandshakePacket::HS_MAGIC_DISCONNECT_END) {
|
||||
|
||||
return Ok(HandshakePacket {
|
||||
start_magic: start_magic,
|
||||
param1: param1,
|
||||
param2: param2,
|
||||
data: data,
|
||||
end_magic: end_magic,
|
||||
});
|
||||
} else {
|
||||
return Err(HandshakeDecError {reason: format!("Unknown magic: 0x{:x} 0x{:x}", start_magic, end_magic),});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_connect(&self) -> bool {
|
||||
return (self.start_magic == HandshakePacket::HS_MAGIC_CONNECT_START) &&
|
||||
(self.end_magic == HandshakePacket::HS_MAGIC_CONNECT_END) &&
|
||||
(self.data == HandshakePacket::HS_CONNECTION_DATA);
|
||||
}
|
||||
|
||||
pub fn new_conv(conv: u32, token: u32) -> HandshakePacket {
|
||||
HandshakePacket {
|
||||
start_magic: HandshakePacket::HS_MAGIC_SEND_CONV_START,
|
||||
param1: conv,
|
||||
param2: token,
|
||||
data: HandshakePacket::HS_CONNECTION_DATA,
|
||||
end_magic: HandshakePacket::HS_MAGIC_SEND_CONV_END,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut ret = Vec::with_capacity(std::mem::size_of::<HandshakePacket>());
|
||||
|
||||
ret.extend_from_slice(&self.start_magic.to_be_bytes());
|
||||
ret.extend_from_slice(&self.param1.to_be_bytes());
|
||||
ret.extend_from_slice(&self.param2.to_be_bytes());
|
||||
ret.extend_from_slice(&self.data.to_be_bytes());
|
||||
ret.extend_from_slice(&self.end_magic.to_be_bytes());
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for HandshakePacket {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "packet")
|
||||
}
|
||||
}
|
5
src/utils/mod.rs
Normal file
5
src/utils/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
mod handshake_packet;
|
||||
mod data_packet;
|
||||
|
||||
pub use self::handshake_packet::HandshakePacket;
|
||||
pub use self::data_packet::DataPacket;
|
Loading…
Reference in New Issue
Block a user