pub mod body; pub mod error; use body::*; use error::*; 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 DataWrapper) -> std::result::Result<Message, MessageError> { let mut msg: Message = Message::default(); match msg.parse_header(rawdata) { Ok(_) => { msg.check(rawdata); } Err(e) => { println!("error parsing header {e}"); return Err(MessageError); } }; Ok(msg) } #[derive(Default, Debug)] pub struct DataWrapper { pub data: VecDeque<u8>, pub count: usize, } impl DataWrapper { pub fn new(data: Vec<u8>) -> DataWrapper { DataWrapper { data: data.into(), count: 0, } } } impl Iterator for DataWrapper { type Item = u8; fn next(&mut self) -> Option<Self::Item> { let res: Option<u8>; if self.count < 6 { res = self.data.pop_front() } else { res = None } self.count += 1; res } } #[derive(Default, Debug)] pub struct Message { pub header: MessageHeader, pub content: MessageType, pub body: Vec<u8>, pub checksum: u8, 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 parse_header( &mut self, rawdata: &mut DataWrapper, ) -> std::result::Result<(), NotOurProtocolError> { let mut data = rawdata.data.clone().into_iter(); let first_byte = data.next().unwrap(); if first_byte != FLAGDELIMITER { return Err(NotOurProtocolError); }; let mut tmpid = vec![]; tmpid.push(data.next().unwrap()); tmpid.push(data.next().unwrap()); self.header.id = u16::from_be_bytes(tmpid.try_into().unwrap()); //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; self.parse_properties(); for i in 0..self.header.raw_terminal_id.len() { self.header.raw_terminal_id[i] = data.next().unwrap(); } self.parse_terminal_id(); self.header.serial_number = ((data.next().unwrap() as u16) << 8) + data.next().unwrap() as u16; for _ in 0..self.header.bodylength as usize { self.body.push(data.next().unwrap()); } self.checksum = data.next().unwrap(); if data.next().unwrap() != FLAGDELIMITER { return Err(NotOurProtocolError); } self.parse_body(); Ok(()) } pub 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; } pub 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 check(&mut self, rawdata: &mut DataWrapper) { let mut data = rawdata.data.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) { self.valid = check == 0; } pub fn is_valid(&self) -> bool { self.valid } pub fn parse_body(&mut self) { match self.header.id { TerminalUniversalResponse::ID => { self.content = MessageType::TerminalUniversalResponse( TerminalUniversalResponse::new(&self.body), ) } PlatformUniversalResponse::ID => { self.content = MessageType::PlatformUniversalResponse( PlatformUniversalResponse::new(&self.body), ) } TerminalHeartbeat::ID => { self.content = MessageType::TerminalHeartbeat(TerminalHeartbeat::new(&self.body)) } TerminalRegistration::ID => { self.content = MessageType::TerminalRegistration(TerminalRegistration::new(&self.body)) } TerminalRegistrationReply::ID => { self.content = MessageType::TerminalRegistrationReply( TerminalRegistrationReply::new(&self.body), ) } TerminalLogout::ID => { self.content = MessageType::TerminalLogout(TerminalLogout::new(&self.body)) } TerminalAuthentication::ID => { self.content = MessageType::TerminalAuthentication(TerminalAuthentication::new(&self.body)) } TerminalParameterSetting::ID => { self.content = MessageType::TerminalParameterSetting(TerminalParameterSetting::new(&self.body)) } QueryTerminalParameter::ID => { self.content = MessageType::QueryTerminalParameter(QueryTerminalParameter::new(&self.body)) } QueryTerminalParameterResponse::ID => { self.content = MessageType::QueryTerminalParameterResponse( QueryTerminalParameterResponse::new(&self.body), ) } TerminalControl::ID => { self.content = MessageType::TerminalControl(TerminalControl::new(&self.body)) } LocationInformationReport::ID => { self.content = MessageType::LocationInformationReport( LocationInformationReport::new(&self.body), ) } StartOfTrip::ID => { self.content = MessageType::StartOfTrip(StartOfTrip::new(&self.body)) } EndOfTrip::ID => self.content = MessageType::EndOfTrip(EndOfTrip::new(&self.body)), _ => { self.content = MessageType::TerminalUniversalResponse( TerminalUniversalResponse::new(&self.body), ) } } } pub fn set_reply(inmsg: Message) -> Option<Message> { let mut reply: Message = Message::default(); let mut rng = rand::thread_rng(); match inmsg.content { MessageType::TerminalRegistration(t) => { let cnt = t.generate_reply( inmsg.header.raw_terminal_id.into(), inmsg.header.serial_number, ); 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.content = MessageType::PlatformUniversalResponse(cnt); } _ => { println!("no type"); return None; } } Some(reply) } pub fn to_raw(&self) -> VecDeque<u8> { let mut resp: VecDeque<u8> = vec![].into(); let mut checksum: u8 = 0; for b in self.header.to_raw() { resp.push_back(b); } for b in self.content.to_raw() { resp.push_back(b); } for b in resp.iter() { checksum = checksum ^ b; } resp.push_back(checksum); resp.push_front(FLAGDELIMITER); resp.push_back(FLAGDELIMITER); resp } } #[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<u8> { let mut r: Vec<u8> = 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 ) } } #[derive(Debug, Clone)] pub enum MessageType { None, TerminalUniversalResponse(TerminalUniversalResponse), PlatformUniversalResponse(PlatformUniversalResponse), TerminalHeartbeat(TerminalHeartbeat), TerminalRegistration(TerminalRegistration), TerminalRegistrationReply(TerminalRegistrationReply), TerminalLogout(TerminalLogout), TerminalAuthentication(TerminalAuthentication), TerminalParameterSetting(TerminalParameterSetting), QueryTerminalParameter(QueryTerminalParameter), QueryTerminalParameterResponse(QueryTerminalParameterResponse), TerminalControl(TerminalControl), LocationInformationReport(LocationInformationReport), StartOfTrip(StartOfTrip), EndOfTrip(EndOfTrip), } impl Default for MessageType { fn default() -> Self { Self::None } } impl BodyMessage for MessageType { fn to_raw(&self) -> Vec<u8> { let res = match self { MessageType::TerminalRegistrationReply(o) => o.to_raw(), MessageType::PlatformUniversalResponse(o) => o.to_raw(), //MessageType::TerminalHeartbeat(o) => o.to_raw(), _ => vec![], }; res } } impl std::fmt::Display for MessageType { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{:?}", self) } } /* macro_rules! generate_switch { ($($t:ty),*) => { $( //impl BodyMessage for $t { // fn build() {} // fn body_to_iter<'a>(&'a self, rawbody: &'a Vec<u8>) -> std::slice::Iter<'a, u8> { // rawbody.into_iter() // } //} impl $t { pub fn new(rawbody: &Vec<u8>) -> Self { let mut res = Self::default(); res.parse(rawbody); res } })* }; }*/