From 83dd157ae1995d69e856843523d838ca32ad5d06 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 27 Dec 2024 21:12:18 +0100 Subject: [PATCH] update micodus_server --- Cargo.lock | 7 ++ Cargo.toml | 1 + src/main.rs | 12 +++- src/parser/body.rs | 109 ++++++++++++++++++------------ src/parser/header.rs | 95 +++++++++++++++++++++++++++ src/parser/mod.rs | 153 +++++++++++++------------------------------ 6 files changed, 227 insertions(+), 150 deletions(-) create mode 100644 src/parser/header.rs diff --git a/Cargo.lock b/Cargo.lock index a73a93e..4550f22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -115,6 +115,12 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.169" @@ -144,6 +150,7 @@ dependencies = [ "bcd-convert", "bitvec", "encoding_rs", + "lazy_static", "rand", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index 5d4b52b..0f69f4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,5 +7,6 @@ edition = "2021" bcd-convert = { version = "0.1" } bitvec = { version = "1.0.1" } encoding_rs = { version = "0.8" } +lazy_static = { version = "1.5" } rand = { version = "0.8" } tokio = { version = "1.42", features = ["full", "sync"] } diff --git a/src/main.rs b/src/main.rs index 28e45b4..912d858 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ use tokio::net::TcpListener; //use tokio::sync::RwLock; const ADDR: &'static str = "0.0.0.0:7700"; +const BUFSIZE: usize = 1024; #[tokio::main] async fn main() { @@ -30,8 +31,9 @@ pub async fn apiserver() -> io::Result<()> { loop { let (socket, _remote_addr) = listener.accept().await?; tokio::spawn(async move { - let mut buf = vec![0; 1024]; + let mut buf = vec![0; BUFSIZE]; loop { + let mut terminal_id = 0; match socket.readable().await { Ok(_) => { match socket.try_read(&mut buf) { @@ -55,6 +57,14 @@ pub async fn apiserver() -> io::Result<()> { println!("error socket readable: {e}"); } } + match socket.writable().await { + Ok(_) => { + let msg = Message::default(); + } + Err(e) => { + println!("error socket writable: {e}") + } + } } }); } diff --git a/src/parser/body.rs b/src/parser/body.rs index a71a0ff..ecfbfcf 100644 --- a/src/parser/body.rs +++ b/src/parser/body.rs @@ -31,6 +31,7 @@ pub trait BodyMessage { fn to_raw(&self) -> Vec { vec![] } + fn parse(&mut self, rawbody: &Vec) {} } #[derive(Default, Debug, Clone)] @@ -43,11 +44,12 @@ pub struct TerminalUniversalResponse { impl TerminalUniversalResponse { pub const ID: u16 = 0x0001; - pub fn parse(&mut self, rawbody: &Vec) {} pub fn debug() {} } -impl BodyMessage for TerminalUniversalResponse {} +impl BodyMessage for TerminalUniversalResponse { + fn parse(&mut self, rawbody: &Vec) {} +} #[derive(Default, Debug, Clone)] pub struct PlatformUniversalResponse { @@ -107,7 +109,19 @@ pub struct TerminalRegistration { impl TerminalRegistration { pub const ID: u16 = 0x0100; - pub fn parse(&mut self, rawbody: &Vec) { + pub fn generate_reply(&self, terminal_id: Vec, serial: u16) -> TerminalRegistrationReply { + let mut res = TerminalRegistrationReply::default(); + res.answer_serial_no = serial; + res.result = TerminalRegistrationResult::Success as u8; + //res.authentication_code = String::from_utf8(terminal_id).unwrap(); + println!("{:?}", terminal_id); + res.authentication_code = vec![0x36, 0x31, 0x33, 0x32, 0x31, 0x31, 0x38]; + res + } +} + +impl BodyMessage for TerminalRegistration { + fn parse(&mut self, rawbody: &Vec) { let mut bd = rawbody.into_iter(); //self.body_to_iter(rawbody); self.provincial_id = u16::from_be_bytes( vec![*bd.next().unwrap(), *bd.next().unwrap()] @@ -138,16 +152,6 @@ impl TerminalRegistration { let (cow, _encoding_used, _had_errors) = GBK.decode(plate_decode); self.license_plate = cow.into(); } - - pub fn generate_reply(&self, terminal_id: Vec, serial: u16) -> TerminalRegistrationReply { - let mut res = TerminalRegistrationReply::default(); - res.answer_serial_no = serial; - res.result = TerminalRegistrationResult::Success as u8; - //res.authentication_code = String::from_utf8(terminal_id).unwrap(); - println!("{:?}", terminal_id); - res.authentication_code = vec![0x36, 0x31, 0x33, 0x32, 0x31, 0x31, 0x38]; - res - } } impl std::fmt::Display for TerminalRegistration { @@ -183,11 +187,10 @@ pub struct TerminalRegistrationReply { impl TerminalRegistrationReply { pub const ID: u16 = 0x8100; - - pub fn parse(&mut self, rawbody: &Vec) {} } impl BodyMessage for TerminalRegistrationReply { + fn parse(&mut self, rawbody: &Vec) {} fn to_raw(&self) -> Vec { let mut res: Vec = vec![]; for b in self.answer_serial_no.to_be_bytes() { @@ -208,8 +211,6 @@ pub struct TerminalLogout {} impl TerminalLogout { pub const ID: u16 = 0x0003; - pub fn parse(&mut self, rawbody: &Vec) {} - pub fn generate_reply(&self, answer_id: u16, serial: u16) -> PlatformUniversalResponse { let mut res = PlatformUniversalResponse::default(); res.answer_serial_no = serial; @@ -219,6 +220,10 @@ impl TerminalLogout { } } +impl BodyMessage for TerminalLogout { + fn parse(&mut self, rawbody: &Vec) {} +} + impl std::fmt::Display for TerminalLogout { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self) @@ -233,7 +238,17 @@ pub struct TerminalAuthentication { impl TerminalAuthentication { pub const ID: u16 = 0x0102; - pub fn parse(&mut self, rawbody: &Vec) { + pub fn generate_reply(&self, answer_id: u16, serial: u16) -> PlatformUniversalResponse { + let mut res = PlatformUniversalResponse::default(); + res.answer_serial_no = serial; + res.answer_id = answer_id; + res.result = TerminalRegistrationResult::Success as u8; + res + } +} + +impl BodyMessage for TerminalAuthentication { + fn parse(&mut self, rawbody: &Vec) { let mut bd = rawbody.into_iter(); let plate_decode: &mut Vec = &mut vec![]; while let Some(i) = bd.next() { @@ -243,14 +258,6 @@ impl TerminalAuthentication { let (cow, _encoding_used, _had_errors) = GBK.decode(plate_decode); self.authentication_code = cow.into(); } - - pub fn generate_reply(&self, answer_id: u16, serial: u16) -> PlatformUniversalResponse { - let mut res = PlatformUniversalResponse::default(); - res.answer_serial_no = serial; - res.answer_id = answer_id; - res.result = TerminalRegistrationResult::Success as u8; - res - } } #[derive(Default, Debug, Clone)] @@ -261,8 +268,10 @@ pub struct TerminalParameterSetting { impl TerminalParameterSetting { pub const ID: u16 = 0x8103; +} - pub fn parse(&mut self, rawbody: &Vec) {} +impl BodyMessage for TerminalParameterSetting { + fn parse(&mut self, rawbody: &Vec) {} } #[derive(Default, Debug, Clone)] @@ -272,16 +281,20 @@ pub struct TerminalParameterData { pub parameter_value: u8, } -impl TerminalParameterData { - pub fn parse(&mut self, rawbody: &Vec) {} +impl TerminalParameterData {} + +impl BodyMessage for TerminalParameterData { + fn parse(&mut self, rawbody: &Vec) {} } #[derive(Default, Debug, Clone)] pub struct QueryTerminalParameter {} impl QueryTerminalParameter { pub const ID: u16 = 0x8104; +} - pub fn parse(&mut self, rawbody: &Vec) {} +impl BodyMessage for QueryTerminalParameter { + fn parse(&mut self, rawbody: &Vec) {} } #[derive(Default, Debug, Clone)] @@ -293,8 +306,10 @@ pub struct QueryTerminalParameterResponse { impl QueryTerminalParameterResponse { pub const ID: u16 = 0x0104; +} - pub fn parse(&mut self, rawbody: &Vec) {} +impl BodyMessage for QueryTerminalParameterResponse { + fn parse(&mut self, rawbody: &Vec) {} } #[derive(Default, Debug, Clone)] @@ -305,8 +320,10 @@ pub struct TerminalControl { impl TerminalControl { pub const ID: u16 = 0x8105; +} - pub fn parse(&mut self, rawbody: &Vec) {} +impl BodyMessage for TerminalControl { + fn parse(&mut self, rawbody: &Vec) {} } #[derive(Default, Debug, Clone)] @@ -324,7 +341,17 @@ pub struct LocationInformationReport { impl LocationInformationReport { pub const ID: u16 = 0x0200; - pub fn parse(&mut self, rawbody: &Vec) { + pub fn generate_reply(&self, answer_id: u16, serial: u16) -> PlatformUniversalResponse { + let mut res = PlatformUniversalResponse::default(); + res.answer_serial_no = serial; + res.answer_id = answer_id; + res.result = TerminalRegistrationResult::Success as u8; + res + } +} + +impl BodyMessage for LocationInformationReport { + fn parse(&mut self, rawbody: &Vec) { let mut bd = rawbody.into_iter(); self.alert_mark = u32::from_be_bytes( vec![ @@ -388,30 +415,26 @@ impl LocationInformationReport { let code = BcdNumber::try_from(&tmptime as &[u8]).unwrap(); self.time = format!("{}", code.to_u64().unwrap()); } - - pub fn generate_reply(&self, answer_id: u16, serial: u16) -> PlatformUniversalResponse { - let mut res = PlatformUniversalResponse::default(); - res.answer_serial_no = serial; - res.answer_id = answer_id; - res.result = TerminalRegistrationResult::Success as u8; - res - } } #[derive(Default, Debug, Clone)] pub struct StartOfTrip {} impl StartOfTrip { pub const ID: u16 = 0x0202; +} - pub fn parse(&mut self, rawbody: &Vec) {} +impl BodyMessage for StartOfTrip { + fn parse(&mut self, rawbody: &Vec) {} } #[derive(Default, Debug, Clone)] pub struct EndOfTrip {} impl EndOfTrip { pub const ID: u16 = 0x0203; +} - pub fn parse(&mut self, rawbody: &Vec) {} +impl BodyMessage for EndOfTrip { + fn parse(&mut self, rawbody: &Vec) {} } struct BCDTime { diff --git a/src/parser/header.rs b/src/parser/header.rs new file mode 100644 index 0000000..8782048 --- /dev/null +++ b/src/parser/header.rs @@ -0,0 +1,95 @@ +use bcd_convert::BcdNumber; +use rand::prelude::*; + +#[allow(dead_code)] +const PROPS_SIZE_MASK: u16 = 0x01FF; +#[allow(dead_code)] +const PROPS_SUBCONTRACT_MASK: u16 = 0x3000; +#[allow(dead_code)] +const PROPS_RESERVED_MASK: u16 = 0xC000; +#[allow(dead_code)] +const PROPS_DATAENCRYPTION_MASK: u16 = 0x0E00; + +#[derive(Default, Debug)] +pub struct MessageHeader { + id: u16, + properties: u16, + pub bodylength: u8, + encryption: u8, + pub encrypted: bool, + pub subcontract: bool, + reserved: u16, + raw_terminal_id: [u8; 6], + pub terminal_id: u64, + pub serial_number: u16, +} + +impl MessageHeader { + pub fn build(&mut self, id: u16, properties: usize, raw_terminal_id: [u8; 6]) { + let mut rng = rand::thread_rng(); + self.id = id; + self.properties = properties as u16; + self.raw_terminal_id = raw_terminal_id; + self.serial_number = rng.gen(); + } + + pub fn get_id(&mut self) -> u16 { + self.id + } + + pub fn set_id(&mut self, id: u16) { + self.id = id; + } + + pub fn set_properties(&mut self, properties: u16) { + self.properties = properties; + } + + pub fn parse_properties(&mut self) { + self.bodylength = (self.properties & PROPS_SIZE_MASK) as u8; + self.encryption = ((self.properties & PROPS_DATAENCRYPTION_MASK) as u16 >> 10) as u8; + self.encrypted = self.encryption != 0; + self.subcontract = ((self.properties & PROPS_SUBCONTRACT_MASK) as u16 >> 13) == 1; + self.reserved = ((self.properties & PROPS_RESERVED_MASK) as u16 >> 14) as u16; + } + + pub fn set_raw_terminal_id(&mut self, rtid: [u8; 6]) { + self.raw_terminal_id = rtid; + } + + pub fn get_raw_terminal_id(&self) -> [u8; 6] { + self.raw_terminal_id + } + + pub fn parse_terminal_id(&mut self) { + let code = BcdNumber::try_from(&self.raw_terminal_id as &[u8]).unwrap(); + self.terminal_id = code.to_u64().unwrap(); + } + + pub fn to_raw(&self) -> Vec { + let mut r: Vec = vec![]; + for b in self.id.to_be_bytes() { + r.push(b); + } + for b in self.properties.to_be_bytes() { + r.push(b); + } + for b in self.raw_terminal_id.into_iter() { + r.push(b); + } + for b in self.serial_number.to_be_bytes() { + r.push(b); + } + r + } +} + +impl std::fmt::Display for MessageHeader { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!( + f, + "message header: id: {:X?}, length: {}, terminal id: {}, serial: {:X?}", + self.id, self.bodylength, self.terminal_id, self.serial_number + ) + } +} diff --git a/src/parser/mod.rs b/src/parser/mod.rs index d24b716..f0603b5 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,25 +1,15 @@ mod body; mod error; +mod header; use body::*; use error::*; +use header::*; use std::collections::VecDeque; -use bcd_convert::BcdNumber; -use rand::prelude::*; - const FLAGDELIMITER: u8 = 0x7E; -#[allow(dead_code)] -const PROPS_SIZE_MASK: u16 = 0x01FF; -#[allow(dead_code)] -const PROPS_SUBCONTRACT_MASK: u16 = 0x3000; -#[allow(dead_code)] -const PROPS_RESERVED_MASK: u16 = 0xC000; -#[allow(dead_code)] -const PROPS_DATAENCRYPTION_MASK: u16 = 0x0E00; - pub fn parse_inbound_msg( rawdata: &mut InboundDataWrapper, ) -> std::result::Result { @@ -98,39 +88,36 @@ pub struct Message { valid: bool, } -impl std::fmt::Display for Message { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!( - f, - "Message: (header: {}), content: {}, checksum: {}, valid: {}", - self.header, self.content, self.checksum, self.valid - ) - } -} - impl Message { + pub fn new() -> Self { + let msg = Self::default(); + return msg; + } fn parse_header( &mut self, rawdata: &mut InboundDataWrapper, ) -> std::result::Result<(), NotOurProtocolError> { let data = rawdata.into_iter(); - self.header.id = u16::from_be_bytes( + self.header.set_id(u16::from_be_bytes( vec![data.next().unwrap(), data.next().unwrap()] .try_into() .unwrap(), - ); + )); - self.header.properties = u16::from_be_bytes( + self.header.set_properties(u16::from_be_bytes( vec![data.next().unwrap(), data.next().unwrap()] .try_into() .unwrap(), - ); - self.parse_properties(); + )); + self.header.parse_properties(); - for i in 0..self.header.raw_terminal_id.len() { - self.header.raw_terminal_id[i] = data.next().unwrap(); + let mut rtid: [u8; 6] = [0; 6]; + for i in 0..rtid.len() { + rtid[i] = data.next().unwrap(); } - self.parse_terminal_id(); + self.header.set_raw_terminal_id(rtid); + + self.header.parse_terminal_id(); self.header.serial_number = u16::from_be_bytes( vec![data.next().unwrap(), data.next().unwrap()] @@ -148,21 +135,6 @@ impl Message { Ok(()) } - fn parse_properties(&mut self) { - self.header.bodylength = (self.header.properties & PROPS_SIZE_MASK) as u8; - self.header.encryption = - ((self.header.properties & PROPS_DATAENCRYPTION_MASK) as u16 >> 10) as u8; - self.header.encrypted = self.header.encryption != 0; - self.header.subcontract = - ((self.header.properties & PROPS_SUBCONTRACT_MASK) as u16 >> 13) == 1; - self.header.reserved = ((self.header.properties & PROPS_RESERVED_MASK) as u16 >> 14) as u16; - } - - fn parse_terminal_id(&mut self) { - let code = BcdNumber::try_from(&self.header.raw_terminal_id as &[u8]).unwrap(); - self.header.terminal_id = code.to_u64().unwrap(); - } - pub fn inbound_check(&mut self, rawdata: &mut InboundDataWrapper) { let data = rawdata.into_iter(); let mut check: u8 = 0; @@ -181,7 +153,7 @@ impl Message { } fn parse_body(&mut self) { - match self.header.id { + match self.header.get_id() { TerminalUniversalResponse::ID => { self.content = MessageType::TerminalUniversalResponse( TerminalUniversalResponse::new(&self.body), @@ -246,50 +218,52 @@ impl Message { pub fn set_reply(inmsg: Message) -> Option { let mut reply: Message = Message::default(); - let mut rng = rand::thread_rng(); + let terminal_id = inmsg.header.get_raw_terminal_id().clone(); match inmsg.content { MessageType::TerminalRegistration(t) => { - let cnt = t.generate_reply( - inmsg.header.raw_terminal_id.into(), - inmsg.header.serial_number, + let cnt = t.generate_reply(terminal_id.into(), inmsg.header.serial_number); + reply.header.build( + TerminalRegistrationReply::ID, + cnt.to_raw().len(), + terminal_id, ); - reply.header.id = TerminalRegistrationReply::ID; - reply.header.properties = cnt.to_raw().len() as u16; - reply.header.raw_terminal_id = inmsg.header.raw_terminal_id; - reply.header.serial_number = rng.gen(); reply.content = MessageType::TerminalRegistrationReply(cnt); } MessageType::TerminalAuthentication(t) => { let cnt = t.generate_reply(TerminalAuthentication::ID, inmsg.header.serial_number); - reply.header.id = PlatformUniversalResponse::ID; - reply.header.raw_terminal_id = inmsg.header.raw_terminal_id; - reply.header.properties = cnt.to_raw().len() as u16; - reply.header.serial_number = rng.gen(); + reply.header.build( + PlatformUniversalResponse::ID, + cnt.to_raw().len(), + terminal_id, + ); reply.content = MessageType::PlatformUniversalResponse(cnt); } MessageType::LocationInformationReport(t) => { let cnt = t.generate_reply(LocationInformationReport::ID, inmsg.header.serial_number); - reply.header.id = PlatformUniversalResponse::ID; - reply.header.raw_terminal_id = inmsg.header.raw_terminal_id; - reply.header.properties = cnt.to_raw().len() as u16; - reply.header.serial_number = rng.gen(); + reply.header.build( + PlatformUniversalResponse::ID, + cnt.to_raw().len(), + terminal_id, + ); reply.content = MessageType::PlatformUniversalResponse(cnt); } MessageType::TerminalHeartbeat(t) => { let cnt = t.generate_reply(TerminalHeartbeat::ID, inmsg.header.serial_number); - reply.header.id = PlatformUniversalResponse::ID; - reply.header.raw_terminal_id = inmsg.header.raw_terminal_id; - reply.header.properties = cnt.to_raw().len() as u16; - reply.header.serial_number = rng.gen(); + reply.header.build( + PlatformUniversalResponse::ID, + cnt.to_raw().len(), + terminal_id, + ); reply.content = MessageType::PlatformUniversalResponse(cnt); } MessageType::TerminalLogout(t) => { let cnt = t.generate_reply(TerminalHeartbeat::ID, inmsg.header.serial_number); - reply.header.id = PlatformUniversalResponse::ID; - reply.header.raw_terminal_id = inmsg.header.raw_terminal_id; - reply.header.properties = cnt.to_raw().len() as u16; - reply.header.serial_number = rng.gen(); + reply.header.build( + PlatformUniversalResponse::ID, + cnt.to_raw().len(), + terminal_id, + ); reply.content = MessageType::PlatformUniversalResponse(cnt); } _ => { @@ -342,45 +316,12 @@ impl Message { } } -#[derive(Default, Debug)] -pub struct MessageHeader { - id: u16, - properties: u16, - pub bodylength: u8, - encryption: u8, - pub encrypted: bool, - pub subcontract: bool, - reserved: u16, - raw_terminal_id: [u8; 6], - pub terminal_id: u64, - pub serial_number: u16, -} - -impl MessageHeader { - fn to_raw(&self) -> Vec { - let mut r: Vec = vec![]; - for b in self.id.to_be_bytes() { - r.push(b); - } - for b in self.properties.to_be_bytes() { - r.push(b); - } - for b in self.raw_terminal_id.into_iter() { - r.push(b); - } - for b in self.serial_number.to_be_bytes() { - r.push(b); - } - r - } -} - -impl std::fmt::Display for MessageHeader { +impl std::fmt::Display for Message { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!( f, - "message header: id: {:X?}, length: {}, terminal id: {}, serial: {:X?}", - self.id, self.bodylength, self.terminal_id, self.serial_number + "Message: (header: {}), content: {}, checksum: {}, valid: {}", + self.header, self.content, self.checksum, self.valid ) } }