update micodus_server
This commit is contained in:
parent
bcd452c117
commit
65461f6f9e
69
src/main.rs
69
src/main.rs
@ -1,6 +1,5 @@
|
||||
pub mod parser;
|
||||
|
||||
pub use crate::parser::body::*;
|
||||
pub use crate::parser::*;
|
||||
|
||||
use std::io;
|
||||
@ -28,48 +27,46 @@ pub async fn apiserver() -> io::Result<()> {
|
||||
}
|
||||
};
|
||||
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
match listener.accept().await {
|
||||
Ok((socket, _remote_addr)) => {
|
||||
let mut buf = vec![0; 1024];
|
||||
|
||||
match socket.readable().await {
|
||||
Ok(_) => {
|
||||
match socket.try_read(&mut buf) {
|
||||
Ok(_) => match handle(&buf) {
|
||||
Some(o) => {
|
||||
let _ = socket.try_write(&o).unwrap();
|
||||
}
|
||||
None => {}
|
||||
},
|
||||
Err(e) => {
|
||||
println!("error: {e}");
|
||||
continue;
|
||||
loop {
|
||||
let (socket, _remote_addr) = listener.accept().await?;
|
||||
tokio::spawn(async move {
|
||||
let mut buf = vec![0; 1024];
|
||||
loop {
|
||||
match socket.readable().await {
|
||||
Ok(_) => {
|
||||
match socket.try_read(&mut buf) {
|
||||
Ok(_) => match handle(&buf) {
|
||||
Some(o) => {
|
||||
let _ = socket.try_write(&o).unwrap();
|
||||
}
|
||||
};
|
||||
}
|
||||
Err(e) => {
|
||||
println!("error: {e}");
|
||||
continue;
|
||||
}
|
||||
None => {
|
||||
break;
|
||||
}
|
||||
},
|
||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
|
||||
continue;
|
||||
}
|
||||
Err(e) => {
|
||||
println!("error read: {e}");
|
||||
}
|
||||
};
|
||||
}
|
||||
Err(e) => {
|
||||
println!("error socket readable: {e}");
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("error: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle(buf: &Vec<u8>) -> Option<Vec<u8>> {
|
||||
let mut rawdata = DataWrapper::new(buf.to_vec());
|
||||
let mut rawdata = InboundDataWrapper::new(buf.to_vec());
|
||||
let reply = match parse_inbound_msg(&mut rawdata) {
|
||||
Ok(o) => {
|
||||
Ok(mut o) => {
|
||||
println!("query: {}", o);
|
||||
println!("raw query: {:?}", o.to_raw());
|
||||
println!("raw query: {:X?}", o.to_raw());
|
||||
Message::store(&o);
|
||||
Message::set_reply(o)
|
||||
}
|
||||
Err(e) => {
|
||||
@ -79,9 +76,9 @@ pub fn handle(buf: &Vec<u8>) -> Option<Vec<u8>> {
|
||||
};
|
||||
|
||||
match reply {
|
||||
Some(o) => {
|
||||
Some(mut o) => {
|
||||
println!("reply: {}", o);
|
||||
println!("raw reply {:?}", o.to_raw());
|
||||
println!("raw reply {:X?}", o.to_raw());
|
||||
return Some(o.to_raw().into());
|
||||
}
|
||||
None => {
|
||||
|
@ -1,3 +1,4 @@
|
||||
use bcd_convert::BcdNumber;
|
||||
use encoding_rs::*;
|
||||
|
||||
macro_rules! generate_impl {
|
||||
@ -80,7 +81,16 @@ pub struct TerminalHeartbeat {}
|
||||
|
||||
impl TerminalHeartbeat {
|
||||
pub const ID: u16 = 0x0002;
|
||||
|
||||
pub fn parse(&mut self, rawbody: &Vec<u8>) {}
|
||||
|
||||
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)]
|
||||
@ -296,15 +306,87 @@ pub struct LocationInformationReport {
|
||||
pub status: u32,
|
||||
pub latitude: u32,
|
||||
pub longitude: u32,
|
||||
pub height: u32,
|
||||
pub speed: u32,
|
||||
pub direction: u32,
|
||||
pub time: u32,
|
||||
pub height: u16,
|
||||
pub speed: u16,
|
||||
pub direction: u16,
|
||||
pub time: u64,
|
||||
}
|
||||
|
||||
impl LocationInformationReport {
|
||||
pub const ID: u16 = 0x0200;
|
||||
pub fn parse(&mut self, rawbody: &Vec<u8>) {}
|
||||
|
||||
pub fn parse(&mut self, rawbody: &Vec<u8>) {
|
||||
let mut bd = rawbody.into_iter();
|
||||
self.alert_mark = u32::from_be_bytes(
|
||||
vec![
|
||||
*bd.next().unwrap(),
|
||||
*bd.next().unwrap(),
|
||||
*bd.next().unwrap(),
|
||||
*bd.next().unwrap(),
|
||||
]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
);
|
||||
self.status = u32::from_be_bytes(
|
||||
vec![
|
||||
*bd.next().unwrap(),
|
||||
*bd.next().unwrap(),
|
||||
*bd.next().unwrap(),
|
||||
*bd.next().unwrap(),
|
||||
]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
);
|
||||
self.latitude = u32::from_be_bytes(
|
||||
vec![
|
||||
*bd.next().unwrap(),
|
||||
*bd.next().unwrap(),
|
||||
*bd.next().unwrap(),
|
||||
*bd.next().unwrap(),
|
||||
]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
);
|
||||
self.longitude = u32::from_be_bytes(
|
||||
vec![
|
||||
*bd.next().unwrap(),
|
||||
*bd.next().unwrap(),
|
||||
*bd.next().unwrap(),
|
||||
*bd.next().unwrap(),
|
||||
]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
);
|
||||
self.height = u16::from_be_bytes(
|
||||
vec![*bd.next().unwrap(), *bd.next().unwrap()]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
);
|
||||
self.speed = u16::from_be_bytes(
|
||||
vec![*bd.next().unwrap(), *bd.next().unwrap()]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
);
|
||||
self.direction = u16::from_be_bytes(
|
||||
vec![*bd.next().unwrap(), *bd.next().unwrap()]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
);
|
||||
let mut tmptime: [u8; 6] = [0; 6];
|
||||
for i in 0..tmptime.len() {
|
||||
tmptime[i] = *bd.next().unwrap();
|
||||
}
|
||||
let code = BcdNumber::try_from(&tmptime as &[u8]).unwrap();
|
||||
self.time = 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)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
pub mod body;
|
||||
pub mod error;
|
||||
mod body;
|
||||
mod error;
|
||||
|
||||
use body::*;
|
||||
use error::*;
|
||||
@ -20,12 +20,14 @@ 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> {
|
||||
pub fn parse_inbound_msg(
|
||||
rawdata: &mut InboundDataWrapper,
|
||||
) -> std::result::Result<Message, MessageError> {
|
||||
let mut msg: Message = Message::default();
|
||||
|
||||
match msg.parse_header(rawdata) {
|
||||
Ok(_) => {
|
||||
msg.check(rawdata);
|
||||
msg.inbound_check(rawdata);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("error parsing header {e}");
|
||||
@ -37,30 +39,49 @@ pub fn parse_inbound_msg(rawdata: &mut DataWrapper) -> std::result::Result<Messa
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct DataWrapper {
|
||||
pub struct InboundDataWrapper {
|
||||
pub data: VecDeque<u8>,
|
||||
pub count: usize,
|
||||
pub start: bool,
|
||||
pub end: bool,
|
||||
}
|
||||
|
||||
impl DataWrapper {
|
||||
pub fn new(data: Vec<u8>) -> DataWrapper {
|
||||
DataWrapper {
|
||||
impl InboundDataWrapper {
|
||||
pub fn new(data: Vec<u8>) -> InboundDataWrapper {
|
||||
InboundDataWrapper {
|
||||
data: data.into(),
|
||||
count: 0,
|
||||
start: false,
|
||||
end: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for DataWrapper {
|
||||
impl Iterator for InboundDataWrapper {
|
||||
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
|
||||
loop {
|
||||
match self.data.pop_front() {
|
||||
Some(o) => {
|
||||
if o == FLAGDELIMITER {
|
||||
if self.start {
|
||||
self.end = true;
|
||||
res = None;
|
||||
break;
|
||||
}
|
||||
self.start = true;
|
||||
continue;
|
||||
}
|
||||
res = Some(o);
|
||||
}
|
||||
None => {
|
||||
res = None;
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
self.count += 1;
|
||||
|
||||
@ -88,22 +109,22 @@ impl std::fmt::Display for Message {
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn parse_header(
|
||||
fn parse_header(
|
||||
&mut self,
|
||||
rawdata: &mut DataWrapper,
|
||||
rawdata: &mut InboundDataWrapper,
|
||||
) -> 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;
|
||||
let data = rawdata.into_iter();
|
||||
self.header.id = u16::from_be_bytes(
|
||||
vec![data.next().unwrap(), data.next().unwrap()]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
self.header.properties = ((data.next().unwrap() as u16) << 8) + data.next().unwrap() as u16;
|
||||
self.header.properties = u16::from_be_bytes(
|
||||
vec![data.next().unwrap(), data.next().unwrap()]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
);
|
||||
self.parse_properties();
|
||||
|
||||
for i in 0..self.header.raw_terminal_id.len() {
|
||||
@ -111,8 +132,11 @@ impl Message {
|
||||
}
|
||||
self.parse_terminal_id();
|
||||
|
||||
self.header.serial_number =
|
||||
((data.next().unwrap() as u16) << 8) + data.next().unwrap() as u16;
|
||||
self.header.serial_number = u16::from_be_bytes(
|
||||
vec![data.next().unwrap(), data.next().unwrap()]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
for _ in 0..self.header.bodylength as usize {
|
||||
self.body.push(data.next().unwrap());
|
||||
@ -120,14 +144,11 @@ impl Message {
|
||||
|
||||
self.checksum = data.next().unwrap();
|
||||
|
||||
if data.next().unwrap() != FLAGDELIMITER {
|
||||
return Err(NotOurProtocolError);
|
||||
}
|
||||
self.parse_body();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn parse_properties(&mut self) {
|
||||
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;
|
||||
@ -137,36 +158,29 @@ impl Message {
|
||||
self.header.reserved = ((self.header.properties & PROPS_RESERVED_MASK) as u16 >> 14) as u16;
|
||||
}
|
||||
|
||||
pub fn parse_terminal_id(&mut self) {
|
||||
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();
|
||||
pub fn inbound_check(&mut self, rawdata: &mut InboundDataWrapper) {
|
||||
let data = rawdata.into_iter();
|
||||
let mut check: u8 = 0;
|
||||
|
||||
loop {
|
||||
let b = data.next().unwrap();
|
||||
if *b == FLAGDELIMITER {
|
||||
break;
|
||||
}
|
||||
check = *b ^ check;
|
||||
}
|
||||
let _ = data.map(|b| check ^= b);
|
||||
|
||||
self.validate(check);
|
||||
self.inbound_validate(check);
|
||||
}
|
||||
|
||||
fn validate(&mut self, check: u8) {
|
||||
fn inbound_validate(&mut self, check: u8) {
|
||||
self.valid = check == 0;
|
||||
}
|
||||
|
||||
pub fn is_valid(&self) -> bool {
|
||||
fn _is_valid(&self) -> bool {
|
||||
self.valid
|
||||
}
|
||||
|
||||
pub fn parse_body(&mut self) {
|
||||
fn parse_body(&mut self) {
|
||||
match self.header.id {
|
||||
TerminalUniversalResponse::ID => {
|
||||
self.content = MessageType::TerminalUniversalResponse(
|
||||
@ -253,19 +267,57 @@ impl Message {
|
||||
reply.header.serial_number = rng.gen();
|
||||
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.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.content = MessageType::PlatformUniversalResponse(cnt);
|
||||
}
|
||||
_ => {
|
||||
println!("no type");
|
||||
return None;
|
||||
}
|
||||
}
|
||||
reply.outbound_finalize();
|
||||
Some(reply)
|
||||
}
|
||||
|
||||
pub fn to_raw(&self) -> VecDeque<u8> {
|
||||
let mut resp: VecDeque<u8> = vec![].into();
|
||||
pub fn store(inmsg: &Message) {
|
||||
match inmsg.content {
|
||||
MessageType::LocationInformationReport(ref t) => {
|
||||
println!("{:?}", t);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn outbound_finalize(&mut self) {
|
||||
let mut checksum: u8 = 0;
|
||||
|
||||
for v in vec![self.header.to_raw(), self.content.to_raw()] {
|
||||
for b in v {
|
||||
checksum = checksum ^ b;
|
||||
}
|
||||
}
|
||||
|
||||
self.checksum = checksum;
|
||||
self.valid = true;
|
||||
}
|
||||
|
||||
pub fn to_raw(&mut self) -> VecDeque<u8> {
|
||||
let mut resp: VecDeque<u8> = vec![].into();
|
||||
|
||||
for b in self.header.to_raw() {
|
||||
resp.push_back(b);
|
||||
}
|
||||
@ -274,11 +326,7 @@ impl Message {
|
||||
resp.push_back(b);
|
||||
}
|
||||
|
||||
for b in resp.iter() {
|
||||
checksum = checksum ^ b;
|
||||
}
|
||||
|
||||
resp.push_back(checksum);
|
||||
resp.push_back(self.checksum);
|
||||
|
||||
resp.push_front(FLAGDELIMITER);
|
||||
resp.push_back(FLAGDELIMITER);
|
||||
@ -371,23 +419,3 @@ impl std::fmt::Display for MessageType {
|
||||
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
|
||||
}
|
||||
})*
|
||||
};
|
||||
}*/
|
||||
|
Loading…
Reference in New Issue
Block a user