diff --git a/src/main.rs b/src/main.rs index 8426c10..3c92a8b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,14 @@ -use std::io; -use std::sync::Arc; -use tokio::io::AsyncWriteExt; -use tokio::net::TcpListener; -use tokio::sync::RwLock; +pub mod parser; -const FLAG: u8 = 0x7e; +pub use crate::parser::*; + +use std::io; +//use std::sync::Arc; + +use tokio::net::TcpListener; +//use tokio::sync::RwLock; + +const ADDR: &'static str = "0.0.0.0:7700"; #[tokio::main] async fn main() { @@ -15,8 +19,7 @@ async fn main() { } pub async fn apiserver() -> io::Result<()> { - let addr = "0.0.0.0:7700"; - let listener = match TcpListener::bind(addr).await { + let listener = match TcpListener::bind(ADDR).await { Ok(o) => o, Err(e) => { println!("error: {e}"); @@ -27,7 +30,7 @@ pub async fn apiserver() -> io::Result<()> { tokio::spawn(async move { loop { match listener.accept().await { - Ok((mut socket, _addr)) => { + Ok((socket, _remote_addr)) => { let mut buf = vec![0; 256]; match socket.readable().await { @@ -46,8 +49,8 @@ pub async fn apiserver() -> io::Result<()> { } } - let data = buf.to_vec(); - let msg = parse_msg(data); + let mut rawdata = buf.to_vec(); + let msg = parse_inbound_msg(&mut rawdata); println!("{:X?}", msg); } Err(err) => { @@ -58,51 +61,3 @@ pub async fn apiserver() -> io::Result<()> { }); Ok(()) } - -fn parse_msg(data: Vec) -> Message { - if data[0] == FLAG { - println!("first flag ok"); - }; - - let mut msg: Message = Message::default(); - - msg.Header.Id = msg.Header.Id + (data[1] << 1) as u16 + data[2] as u16; - msg.Header.Properties = msg.Header.Properties + (data[3] << 1) as u16 + data[4] as u16; - for (i, v) in data[5..11].iter().enumerate() { - msg.Header.TerminalId[i] = *v; - } - msg.Header.SerialNumber = msg.Header.SerialNumber + (data[11] << 1) as u16 + data[12] as u16; - - let endbody = 13 + msg.Header.Properties as usize; - let range: std::ops::Range = 13..(endbody); - let check_idx = 13 + msg.Header.Properties as usize; - let endflag: u8 = check_idx as u8 + 1; - - for i in data[range].iter() { - msg.Body.push(*i); - } - - msg.Check = data[check_idx]; - - if data[endflag as usize] == FLAG { - println!("end flag ok"); - } else { - println!("error with endflag"); - } - msg -} - -#[derive(Default, Debug)] -pub struct Message { - pub Header: MessageHeader, - pub Body: Vec, - pub Check: u8, -} - -#[derive(Default, Debug)] -pub struct MessageHeader { - pub Id: u16, - pub Properties: u16, - pub TerminalId: [u8; 6], - pub SerialNumber: u16, -} diff --git a/src/parser/body.rs b/src/parser/body.rs new file mode 100644 index 0000000..17fef60 --- /dev/null +++ b/src/parser/body.rs @@ -0,0 +1,113 @@ +#[derive(Default, Debug)] +pub struct TerminalUniversalResponse { + pub answer_serial_no: u16, + pub answer_id: u16, + pub result: u8, +} + +impl BodyMessage for TerminalUniversalResponse {} + +#[derive(Default, Debug)] +pub struct PlatformUniversalResponse { + pub answer_serial_no: u16, + pub answer_id: u16, + pub result: u8, +} + +#[derive(Default, Debug)] +pub struct TerminalHeartbeat {} + +#[derive(Default, Debug)] +pub struct TerminalRegistration { + pub provincial_id: u16, + pub city_and_prefecture_id: u16, + pub manufacturer_id: [u8; 5], + pub terminal_models: [u8; 8], + pub terminal_id: [u8; 7], + pub license_plate_color: u8, + pub license_plate: String, +} + +#[derive(Default, Debug)] +pub struct TerminalRegistrationReply { + pub answer_serial_no: u16, + pub result: u8, + pub authentication_code: String, +} + +#[derive(Default, Debug)] +pub struct TerminalLogout {} + +#[derive(Default, Debug)] +pub struct TerminalAuthentication { + pub authentication_code: String, +} + +#[derive(Default, Debug)] +pub struct TerminalParameterSetting { + pub total_parameters: u8, + pub parameters: Vec, +} + +#[derive(Default, Debug)] +pub struct TerminalParameterData { + pub parameter_id: u32, + pub parameter_length: u8, + pub parameter_value: u8, +} + +#[derive(Default, Debug)] +pub struct QueryTerminalParameter {} + +#[derive(Default, Debug)] +pub struct QueryTerminalParameterResponse { + pub response_serial_no: u16, + pub response_parameter_quantity: u16, + pub parameters: Vec, +} + +#[derive(Default, Debug)] +pub struct TerminalControl { + pub command_word: u8, + pub command_parameter: String, +} + +#[derive(Default, Debug)] +pub struct LocationInformationReport { + pub alert_mark: u32, + pub status: u32, + pub latitude: u32, + pub longitude: u32, + pub height: u32, + pub speed: u32, + pub direction: u32, + pub time: u32, +} + +#[derive(Default, Debug)] +pub struct StartOfTrip {} + +#[derive(Default, Debug)] +pub struct EndOfTrip {} + +#[derive(Debug)] +pub enum BodyType { + TerminalUniversalResponse = 0x0001, + PlatformUniversalResponse = 0x8001, + TerminalHeartbeat = 0x0002, + TerminalRegistration = 0x0100, + TerminalRegistrationReply = 0x8100, + TerminalLogout = 0x0003, + TerminalAuthentication = 0x0102, + TerminalParameterSetting = 0x8103, + QueryTerminalParameter = 0x8104, + QueryTerminalParameterResponse = 0x0104, + TerminalControl = 0x8105, + LocationInformationReport = 0x0200, + StartOfTrip = 0x0202, + EndOfTrip = 0x0203, +} + +pub trait BodyMessage { + fn parse() {} +} diff --git a/src/parser/mod.rs b/src/parser/mod.rs new file mode 100644 index 0000000..f8a864b --- /dev/null +++ b/src/parser/mod.rs @@ -0,0 +1,98 @@ +mod body; + +use body::*; + +const FLAGDELIMITER: u8 = 0x7E; + +#[allow(dead_code)] +const PropsSizeMask: u16 = 0x01FF; +const PropsSubcontractMask: u16 = 0x3000; +const PropsReservedMask: u16 = 0xC000; +const PropsDataEncryptionMask: u16 = 0x0E00; + +pub fn parse_inbound_msg(rawdata: &mut Vec) -> Message { + let mut msg: Message = Message::default(); + + msg.parse_header(rawdata); + msg.check(rawdata); + + msg +} + +#[derive(Default, Debug)] +pub struct Message { + pub header: MessageHeader, + pub body: Vec, + pub checksum: u8, + valid: bool, +} + +impl Message { + pub fn parse_header(&mut self, rawdata: &mut Vec) { + let mut data = rawdata.clone().into_iter(); + let first_byte = data.next().unwrap(); + if first_byte == FLAGDELIMITER { + println!("first flag ok"); + }; + self.header.id = ((data.next().unwrap() as u16) << 8) + data.next().unwrap() as u16; + self.header.properties = ((data.next().unwrap() as u16) << 8) + data.next().unwrap() as u16; + for i in 0..self.header.terminal_id.len() { + self.header.terminal_id[i] = data.next().unwrap(); + } + self.parse_properties(); + + self.header.serial_number = + ((data.next().unwrap() as u16) << 8) + data.next().unwrap() as u16; + + for _ in 0..self.header.properties as usize { + self.body.push(data.next().unwrap()); + } + + self.checksum = data.next().unwrap(); + + if data.next().unwrap() == FLAGDELIMITER { + println!("end flag ok"); + } else { + println!("error with endflag"); + } + } + + pub fn parse_properties(&mut self) { + self.header.bodylength = (self.header.properties & PropsSizeMask) as u8; + } + + pub fn check(&mut self, rawdata: &mut Vec) { + let mut data = rawdata.into_iter(); + data.next().unwrap(); + let mut check: u8 = 0; + + loop { + let b = data.next().unwrap(); + if *b == FLAGDELIMITER { + break; + } + check = *b ^ check; + } + + self.validate(check); + } + + fn validate(&mut self, check: u8) { + println!("{}", BodyType::TerminalHeartbeat as u16); + self.valid = check == 0; + } + + pub fn is_valid(&self) -> bool { + self.valid + } +} + +#[derive(Default, Debug)] +pub struct MessageHeader { + pub id: u16, + properties: u16, + pub bodylength: u8, + pub encryption: bool, + pub terminal_id: [u8; 6], + pub serial_number: u16, +}