628 lines
16 KiB
Rust
628 lines
16 KiB
Rust
#![allow(incomplete_features)]
|
|
|
|
pub mod crypto;
|
|
pub mod packet;
|
|
pub mod character;
|
|
pub mod util;
|
|
//pub mod item;
|
|
|
|
use std::io::{Read, Seek};
|
|
#[derive(Debug, PartialEq)]
|
|
pub enum PacketParseError {
|
|
NotEnoughBytes,
|
|
WrongPacketCommand {expected: u16, got: u16},
|
|
WrongPacketForServerType(u16, Vec<u8>),
|
|
UnknownPacket(u16, Vec<u8>),
|
|
WrongPacketSize(u16, usize),
|
|
WrongMessageCommand {expected: u8, got: u8},
|
|
UnknownMessage(u8, Vec<u8>),
|
|
DataStructNotLargeEnough(u64, usize),
|
|
InvalidValue,
|
|
ReadError,
|
|
}
|
|
|
|
pub trait PSOPacketData {
|
|
//fn size(&self) -> usize;
|
|
fn from_bytes<R: Read + Seek>(cursor: &mut R) -> Result<Self, PacketParseError> where Self: Sized;
|
|
fn as_bytes(&self) -> Vec<u8>;
|
|
}
|
|
|
|
impl PSOPacketData for u8 {
|
|
fn from_bytes<R: Read>(cursor: &mut R) -> Result<u8, PacketParseError> {
|
|
let mut bytes = [0u8; 1];
|
|
let len = cursor.read(&mut bytes).map_err(|_| PacketParseError::ReadError)?;
|
|
if len == 1 {
|
|
Ok(bytes[0])
|
|
} else{
|
|
Err(PacketParseError::NotEnoughBytes)
|
|
}
|
|
}
|
|
fn as_bytes(&self) -> Vec<u8> {
|
|
vec![*self]
|
|
}
|
|
}
|
|
|
|
impl PSOPacketData for u16 {
|
|
fn from_bytes<R: Read>(cursor: &mut R) -> Result<u16, PacketParseError> {
|
|
let mut bytes = [0u8; 2];
|
|
let len = cursor.read(&mut bytes).map_err(|_| PacketParseError::ReadError)?;
|
|
if len == 2 {
|
|
Ok(u16::from_le_bytes(bytes))
|
|
}
|
|
else {
|
|
Err(PacketParseError::NotEnoughBytes)
|
|
}
|
|
}
|
|
fn as_bytes(&self) -> Vec<u8> {
|
|
u16::to_le_bytes(*self).to_vec()
|
|
}
|
|
}
|
|
|
|
impl PSOPacketData for u32 {
|
|
fn from_bytes<R: Read>(cursor: &mut R) -> Result<u32, PacketParseError> {
|
|
let mut bytes = [0u8; 4];
|
|
let len = cursor.read(&mut bytes).map_err(|_| PacketParseError::ReadError)?;
|
|
if len == 4 {
|
|
Ok(u32::from_le_bytes(bytes))
|
|
}
|
|
else {
|
|
Err(PacketParseError::NotEnoughBytes)
|
|
}
|
|
}
|
|
fn as_bytes(&self) -> Vec<u8> {
|
|
u32::to_le_bytes(*self).to_vec()
|
|
}
|
|
}
|
|
|
|
impl PSOPacketData for f32 {
|
|
fn from_bytes<R: Read>(cursor: &mut R) -> Result<f32, PacketParseError> {
|
|
let mut bytes = [0u8; 4];
|
|
let len = cursor.read(&mut bytes).map_err(|_| PacketParseError::ReadError)?;
|
|
if len == 4 {
|
|
Ok(f32::from_le_bytes(bytes))
|
|
}
|
|
else {
|
|
Err(PacketParseError::NotEnoughBytes)
|
|
}
|
|
}
|
|
fn as_bytes(&self) -> Vec<u8> {
|
|
f32::to_le_bytes(*self).to_vec()
|
|
}
|
|
}
|
|
|
|
impl PSOPacketData for String {
|
|
fn from_bytes<R: Read>(cursor: &mut R) -> Result<String, PacketParseError> {
|
|
let mut s: Vec<u8> = Vec::new();
|
|
cursor.read_to_end(&mut s).map_err(|_| PacketParseError::ReadError)?;
|
|
let mut utf16 = Vec::new();
|
|
for c in s.chunks(2) {
|
|
utf16.push(u16::from_le_bytes([c[0], c[1]]));
|
|
}
|
|
Ok(String::from_utf16_lossy(utf16.as_slice()))
|
|
}
|
|
fn as_bytes(&self) -> Vec<u8> {
|
|
let mut buf = Vec::new();
|
|
for c in self.as_str().encode_utf16() {
|
|
buf.extend_from_slice(&c.to_le_bytes());
|
|
}
|
|
buf
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, PartialEq)]
|
|
pub struct ConsumingBlob {
|
|
pub blob: Vec<u8>,
|
|
}
|
|
|
|
impl PSOPacketData for ConsumingBlob {
|
|
fn from_bytes<R: Read>(cursor: &mut R) -> Result<ConsumingBlob, PacketParseError> {
|
|
let mut blob: Vec<u8> = Vec::new();
|
|
cursor.read_to_end(&mut blob).map_err(|_| PacketParseError::ReadError)?;
|
|
Ok(ConsumingBlob {
|
|
blob,
|
|
})
|
|
}
|
|
fn as_bytes(&self) -> Vec<u8> {
|
|
self.blob.clone()
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Debug for ConsumingBlob {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
f.debug_struct("ConsumingBlob")
|
|
.field("blob", &"[...]")
|
|
.finish()
|
|
}
|
|
}
|
|
|
|
pub trait PSOPacket: std::fmt::Debug {
|
|
// const CMD: u16;
|
|
fn from_bytes(data: &[u8]) -> Result<Self, PacketParseError> where Self: Sized;
|
|
fn as_bytes(&self) -> Vec<u8>;
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
use psopacket::{pso_packet, pso_message, PSOPacketData};
|
|
use crate::packet::messages::PSOMessage;
|
|
|
|
#[test]
|
|
fn test_basic_pso_packet() {
|
|
#[pso_packet(0x23)]
|
|
struct Test {
|
|
a: u32,
|
|
b: u16,
|
|
c: u16,
|
|
}
|
|
|
|
let test = Test {
|
|
a: 123456789,
|
|
b: 54321,
|
|
c: 9999,
|
|
};
|
|
|
|
let mut bytes = test.as_bytes();
|
|
assert!(bytes == vec![16, 0, 35, 0, 0, 0, 0, 0, 21, 205, 91, 7, 49, 212, 15, 39]);
|
|
|
|
bytes[11] = 17;
|
|
let test2 = Test::from_bytes(&bytes).unwrap();
|
|
assert!(test2 == Test {
|
|
a: 291228949,
|
|
b: 54321,
|
|
c: 9999,
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn test_array_in_packet() {
|
|
#[pso_packet(0x23)]
|
|
struct Test {
|
|
a: u32,
|
|
b: u16,
|
|
c: [u16; 3],
|
|
}
|
|
|
|
let test = Test {
|
|
a: 123456789,
|
|
b: 54321,
|
|
c: [1111, 2222, 3333],
|
|
};
|
|
|
|
let mut bytes = test.as_bytes();
|
|
assert!(bytes == [20, 0, 35, 0, 0, 0, 0, 0, 21, 205, 91, 7, 49, 212, 87, 4, 174, 8, 5, 13]);
|
|
|
|
bytes[17] = 17;
|
|
let test2 = Test::from_bytes(&bytes).unwrap();
|
|
assert!(test2 == Test {
|
|
a: 123456789,
|
|
b: 54321,
|
|
c: [1111, 4526, 3333],
|
|
});
|
|
|
|
}
|
|
|
|
#[test]
|
|
fn test_custom_type_in_packet() {
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub struct MyType {
|
|
k: u8,
|
|
j: u32,
|
|
}
|
|
|
|
impl PSOPacketData for MyType {
|
|
fn from_bytes<R: std::io::Read>(cursor: &mut R) -> Result<MyType, PacketParseError> {
|
|
let mut kb = [0u8; 1];
|
|
cursor.read(&mut kb).map_err(|_| PacketParseError::ReadError)?;
|
|
let mut jb = [0u8; 4];
|
|
cursor.read(&mut jb).map_err(|_| PacketParseError::ReadError)?;
|
|
Ok(MyType {
|
|
k: kb[0],
|
|
j: u32::from_le_bytes(jb)
|
|
})
|
|
}
|
|
fn as_bytes(&self) -> Vec<u8> {
|
|
let jbytes = u32::to_le_bytes(self.j);
|
|
vec![self.k, jbytes[0], jbytes[1], jbytes[2], jbytes[3]]
|
|
}
|
|
}
|
|
|
|
#[pso_packet(0x23)]
|
|
struct Test {
|
|
a: u32,
|
|
b: u16,
|
|
c: MyType,
|
|
d: u8,
|
|
}
|
|
|
|
|
|
let test = Test {
|
|
a: 123456789,
|
|
b: 54321,
|
|
c: MyType {
|
|
k: 23,
|
|
j: 999999,
|
|
},
|
|
d: 5,
|
|
};
|
|
|
|
let mut bytes = test.as_bytes();
|
|
assert!(bytes == [20, 0, 35, 0, 0, 0, 0, 0, 21, 205, 91, 7, 49, 212, 23, 63, 66, 15, 0, 5]);
|
|
bytes[17] = 17;
|
|
let test2 = Test::from_bytes(&bytes).unwrap();
|
|
assert!(test2 == Test {
|
|
a: 123456789,
|
|
b: 54321,
|
|
c: MyType {
|
|
k: 23,
|
|
j: 1131071,
|
|
},
|
|
d: 5,
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn test_string_in_packet() {
|
|
#[pso_packet(0x23)]
|
|
struct Test {
|
|
a: u32,
|
|
b: u16,
|
|
s: String,
|
|
}
|
|
|
|
let test = Test {
|
|
a: 123456789,
|
|
b: 54321,
|
|
s: "asdf あえいおう".to_string(),
|
|
};
|
|
|
|
let mut bytes = test.as_bytes();
|
|
assert!(bytes == vec![36, 0, 35, 0, 0, 0, 0, 0, 21, 205, 91, 7, 49, 212, 97, 0, 115, 0, 100, 0,
|
|
102, 0, 32, 0, 66, 48, 72, 48, 68, 48, 74, 48, 70, 48, 0, 0]);
|
|
bytes[18] = 99;
|
|
let test2 = Test::from_bytes(&bytes).unwrap();
|
|
assert!(test2 == Test {
|
|
a: 123456789,
|
|
b: 54321,
|
|
s: "ascf あえいおう\u{0}".to_string(),
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn test_vec_in_packet() {
|
|
#[pso_packet(0x23)]
|
|
struct Test {
|
|
a: u32,
|
|
b: u16,
|
|
v: Vec<u16>,
|
|
}
|
|
|
|
let test = Test {
|
|
a: 123456789,
|
|
b: 54321,
|
|
v: vec![123,456,789],
|
|
};
|
|
|
|
let mut bytes = test.as_bytes();
|
|
assert!(bytes == vec![20, 0, 35, 0, 3, 0, 0, 0, 21, 205, 91, 7, 49, 212, 123, 0, 200, 1, 21, 3]);
|
|
bytes[18] = 99;
|
|
let test2 = Test::from_bytes(&bytes).unwrap();
|
|
assert!(test2 == Test {
|
|
a: 123456789,
|
|
b: 54321,
|
|
v: vec![123,456,867],
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn test_no_flag_packet() {
|
|
#[pso_packet(0x23, no_flag)]
|
|
struct Test {
|
|
a: u32,
|
|
b: u16,
|
|
c: u16,
|
|
}
|
|
|
|
let test = Test {
|
|
a: 123456789,
|
|
b: 54321,
|
|
c: 9999,
|
|
};
|
|
|
|
let mut bytes = test.as_bytes();
|
|
assert!(bytes == vec![12, 0, 35, 0, 21, 205, 91, 7, 49, 212, 15, 39]);
|
|
|
|
bytes[11] = 17;
|
|
let test2 = Test::from_bytes(&bytes).unwrap();
|
|
assert!(test2 == Test {
|
|
a: 123456789,
|
|
b: 54321,
|
|
c: 4367,
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn test_command_error() {
|
|
#[pso_packet(0x23)]
|
|
struct Test {
|
|
a: u32,
|
|
b: u16,
|
|
#[nodebug]
|
|
c: [u8; 0x2000],
|
|
}
|
|
|
|
let test = Test {
|
|
a: 123456789,
|
|
b: 54321,
|
|
c: [0; 0x2000],
|
|
};
|
|
|
|
let mut bytes = test.as_bytes();
|
|
bytes[2] = 17;
|
|
let test2 = Test::from_bytes(&bytes);
|
|
assert!(test2 == Err(PacketParseError::WrongPacketCommand { expected: 0x23, got: 17}));
|
|
}
|
|
|
|
#[test]
|
|
fn test_derive_pso_data_packet() {
|
|
#[derive(PSOPacketData)]
|
|
struct Test {
|
|
a: u8,
|
|
b: u32,
|
|
c: u16,
|
|
}
|
|
|
|
let test = Test {
|
|
a: 12,
|
|
b: 34567,
|
|
c: 890,
|
|
};
|
|
|
|
let mut bytes = test.as_bytes();
|
|
assert!(bytes == vec![12, 7, 135, 0, 0, 122, 3]);
|
|
bytes[2] = 17;
|
|
let mut cur = std::io::Cursor::new(bytes.clone());
|
|
let test2 = Test::from_bytes(&mut cur).unwrap();
|
|
assert!(test2 == Test {
|
|
a: 12,
|
|
b: 4359,
|
|
c: 890
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn test_derive_pso_data_packet_array() {
|
|
#[derive(PSOPacketData)]
|
|
struct Test {
|
|
a: u8,
|
|
b: u32,
|
|
c: u16,
|
|
d: [u8; 5],
|
|
}
|
|
|
|
let test = Test {
|
|
a: 12,
|
|
b: 34567,
|
|
c: 890,
|
|
d: [1,2,3,4,5],
|
|
};
|
|
|
|
let mut bytes = test.as_bytes();
|
|
assert!(bytes == vec![12, 7, 135, 0, 0, 122, 3, 1, 2, 3, 4, 5]);
|
|
bytes[10] = 17;
|
|
let mut cur = std::io::Cursor::new(bytes.clone());
|
|
let test2 = Test::from_bytes(&mut cur).unwrap();
|
|
assert!(test2 == Test {
|
|
a: 12,
|
|
b: 34567,
|
|
c: 890,
|
|
d: [1,2,3,17,5]
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn test_derive_pso_data_packet_not_enough_data() {
|
|
#[derive(PSOPacketData)]
|
|
struct Test {
|
|
a: u8,
|
|
b: u32,
|
|
c: u16,
|
|
}
|
|
|
|
let test = Test {
|
|
a: 12,
|
|
b: 34567,
|
|
c: 890,
|
|
};
|
|
|
|
let mut bytes = test.as_bytes();
|
|
bytes.extend(test.as_bytes());
|
|
|
|
let mut cur = std::io::Cursor::new(bytes.clone());
|
|
let test2 = Test::from_bytes(&mut cur).unwrap();
|
|
assert!(test2 == Test {
|
|
a: 12,
|
|
b: 34567,
|
|
c: 890,
|
|
});
|
|
|
|
let bytes2 = (0..14).collect::<Vec<_>>();
|
|
let mut cur = std::io::Cursor::new(bytes2);
|
|
let test3 = Test::from_bytes(&mut cur);
|
|
assert!(test3 == Ok(Test {
|
|
a: 0,
|
|
b: 67305985,
|
|
c: 1541,
|
|
}));
|
|
let test4 = Test::from_bytes(&mut cur);
|
|
assert!(test4 == Ok(Test {
|
|
a: 7,
|
|
b: 185207048,
|
|
c: 3340,
|
|
}));
|
|
let test5 = Test::from_bytes(&mut cur);
|
|
assert!(test5 == Err(PacketParseError::NotEnoughBytes));
|
|
}
|
|
|
|
#[test]
|
|
fn test_pso_packet_manual_flag() {
|
|
#[pso_packet(0x23, manual_flag)]
|
|
struct Test {
|
|
flag: u32,
|
|
a: u32,
|
|
b: u32,
|
|
}
|
|
|
|
let test = Test {
|
|
flag: 99,
|
|
a: 123,
|
|
b: 456,
|
|
};
|
|
|
|
let mut bytes = test.as_bytes();
|
|
assert!(bytes == vec![16, 0, 35, 0, 99, 0, 0, 0, 123, 0, 0, 0, 200, 1, 0, 0]);
|
|
|
|
bytes[6] = 2;
|
|
let test2 = Test::from_bytes(&bytes).unwrap();
|
|
assert!(test2 == Test {
|
|
flag: 131171,
|
|
a: 123,
|
|
b: 456,
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn test_pso_message() {
|
|
#[pso_message(0x23)]
|
|
struct Test {
|
|
a: u32,
|
|
b: f32,
|
|
}
|
|
|
|
let test = Test {
|
|
client: 1,
|
|
target: 2,
|
|
a: 123,
|
|
b: 4.56,
|
|
};
|
|
|
|
let mut bytes = test.as_bytes();
|
|
assert!(bytes == vec![35, 3, 1, 2, 123, 0, 0, 0, 133, 235, 145, 64]);
|
|
|
|
bytes[6] = 2;
|
|
let test2 = Test::from_bytes(&mut std::io::Cursor::new(bytes)).unwrap();
|
|
assert!(test2 == Test {
|
|
client: 1,
|
|
target: 2,
|
|
a: 131195,
|
|
b: 4.56,
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn test_pso_message_non_4_byte_size() {
|
|
#[pso_message(0x23)]
|
|
struct Test {
|
|
a: u32,
|
|
b: f32,
|
|
c: u8,
|
|
}
|
|
|
|
let test = Test {
|
|
client: 1,
|
|
target: 2,
|
|
a: 123,
|
|
b: 4.56,
|
|
c: 5,
|
|
};
|
|
|
|
let mut bytes = test.as_bytes();
|
|
assert!(bytes == vec![35, 4, 1, 2, 123, 0, 0, 0, 133, 235, 145, 64, 5, 0, 0, 0]);
|
|
|
|
bytes[6] = 2;
|
|
let test2 = Test::from_bytes(&mut std::io::Cursor::new(bytes)).unwrap();
|
|
assert!(test2 == Test {
|
|
client: 1,
|
|
target: 2,
|
|
a: 131195,
|
|
b: 4.56,
|
|
c: 5,
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn test_pso_message_overflow() {
|
|
#[pso_message(0x23)]
|
|
struct Test {
|
|
b: [u32; 100],
|
|
}
|
|
|
|
let test = Test {
|
|
client: 1,
|
|
target: 2,
|
|
b: [23; 100],
|
|
};
|
|
|
|
let bytes = test.as_bytes();
|
|
assert!(bytes[1] == 101);
|
|
}
|
|
|
|
#[test]
|
|
fn test_consuming_blob() {
|
|
#[pso_packet(0x6D, manual_flag)]
|
|
struct SixDee {
|
|
flag: u32,
|
|
blob: ConsumingBlob,
|
|
}
|
|
|
|
let pkt = vec![76, 0, 109, 0, 1, 0, 0, 0, 109, 0, 0, 0, 68, 0, 0, 0, 140, 0, 0, 0,
|
|
51, 0, 0, 0, 84, 220, 255, 254, 253, 1, 254, 240, 33, 254, 240,
|
|
65, 254, 240, 85, 97, 254, 240, 129, 254, 240, 161, 254, 240, 193,
|
|
254, 240, 169, 225, 13, 1, 16, 0, 33, 16, 0, 65, 16, 0, 97, 0, 16,
|
|
1, 64, 15, 82, 15, 100, 15, 118, 0, 0];
|
|
|
|
let data = SixDee::from_bytes(&pkt);
|
|
assert!(pkt == data.unwrap().as_bytes());
|
|
}
|
|
|
|
#[test]
|
|
fn test_message_length() {
|
|
#[pso_message(0x23)]
|
|
struct Lengths {
|
|
a: u8,
|
|
#[length_of(d)]
|
|
b: u8,
|
|
c: u8,
|
|
#[length_is(b)]
|
|
d: Vec<u8>,
|
|
}
|
|
|
|
let pkt = Lengths {
|
|
client: 1,
|
|
target: 2,
|
|
a: 12,
|
|
b: 23,
|
|
c: 34,
|
|
d: vec![9,9,9],
|
|
};
|
|
|
|
let mut data = pkt.as_bytes();
|
|
assert!(data == vec![35, 3, 1, 2, 12, 3, 34, 9, 9, 9, 0, 0]);
|
|
|
|
data[10] = 8;
|
|
data[5] = 4;
|
|
|
|
let l = Lengths::from_bytes(&mut std::io::Cursor::new(data)).unwrap();
|
|
assert!(l == Lengths {
|
|
client: 1,
|
|
target: 2,
|
|
a: 12,
|
|
b: 4,
|
|
c: 34,
|
|
d: vec![9,9,9,8],
|
|
});
|
|
}
|
|
}
|