update micodus_server

This commit is contained in:
Paul 2024-12-22 15:28:12 +01:00
parent 99b779c5f7
commit c52556eb2e
6 changed files with 336 additions and 40 deletions

30
Cargo.lock generated
View File

@ -38,6 +38,15 @@ dependencies = [
"windows-targets",
]
[[package]]
name = "bcd-convert"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71a18a98ca044380fc93aa29f45577996d8aee9b689176b56327f3080280d798"
dependencies = [
"thiserror",
]
[[package]]
name = "bitflags"
version = "2.6.0"
@ -88,6 +97,7 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
name = "micodus_server"
version = "0.1.0"
dependencies = [
"bcd-convert",
"tokio",
]
@ -224,6 +234,26 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tokio"
version = "1.42.0"

View File

@ -4,4 +4,5 @@ version = "0.1.0"
edition = "2021"
[dependencies]
bcd-convert = "0.1.0"
tokio = { version = "1.42", features = ["full", "sync"] }

25
README.md Normal file
View File

@ -0,0 +1,25 @@
# micodus_server
Micodus platform server
## Build
```cargo b -r```
## License
```
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
```

View File

@ -31,12 +31,12 @@ pub async fn apiserver() -> io::Result<()> {
loop {
match listener.accept().await {
Ok((socket, _remote_addr)) => {
let mut buf = vec![0; 256];
let mut buf = vec![0; 1024];
match socket.readable().await {
Ok(_) => {
match socket.try_read(&mut buf) {
Ok(_) => {}
Ok(_) => handle(&buf),
Err(e) => {
println!("error: {e}");
continue;
@ -48,10 +48,6 @@ pub async fn apiserver() -> io::Result<()> {
continue;
}
}
let mut rawdata = buf.to_vec();
let msg = parse_inbound_msg(&mut rawdata);
println!("{:X?}", msg);
}
Err(err) => {
println!("error: {err}");
@ -61,3 +57,9 @@ pub async fn apiserver() -> io::Result<()> {
});
Ok(())
}
pub fn handle(buf: &Vec<u8>) {
let mut rawdata = buf.to_vec();
let msg = parse_inbound_msg(&mut rawdata);
println!("{}", msg);
}

View File

@ -1,3 +1,26 @@
pub trait BodyMessage {
fn build() {}
fn print(&mut self, body: &Vec<u8>) {
println!("{:?}", body);
}
}
macro_rules! generate_impl {
($($t:ty),*) => {
$(
impl BodyMessage for $t {
fn build() {}
}
impl $t {
pub fn new(body: &Vec<u8>) -> Self {
let mut res = Self::default();
res.parse(body);
res
}
})*
};
}
#[derive(Default, Debug)]
pub struct TerminalUniversalResponse {
pub answer_serial_no: u16,
@ -5,7 +28,11 @@ pub struct TerminalUniversalResponse {
pub result: u8,
}
impl BodyMessage for TerminalUniversalResponse {}
impl TerminalUniversalResponse {
const ID: u16 = 0x100;
pub fn parse(&mut self, body: &Vec<u8>) {}
pub fn debug() {}
}
#[derive(Default, Debug)]
pub struct PlatformUniversalResponse {
@ -14,9 +41,17 @@ pub struct PlatformUniversalResponse {
pub result: u8,
}
impl PlatformUniversalResponse {
pub fn parse(&mut self, body: &Vec<u8>) {}
}
#[derive(Default, Debug)]
pub struct TerminalHeartbeat {}
impl TerminalHeartbeat {
pub fn parse(&mut self, body: &Vec<u8>) {}
}
#[derive(Default, Debug)]
pub struct TerminalRegistration {
pub provincial_id: u16,
@ -28,6 +63,24 @@ pub struct TerminalRegistration {
pub license_plate: String,
}
impl TerminalRegistration {
pub fn parse(&mut self, body: &Vec<u8>) {}
pub fn generate_reply(&self, serial: u16) -> TerminalRegistrationReply {
let mut res = TerminalRegistrationReply::default();
res.answer_serial_no = serial;
res.result = TerminalRegistrationResult::Success as u8;
res
}
}
enum TerminalRegistrationResult {
Success = 0x00,
VehicleRegistered,
VehicleNotInDatabase,
TerminalRegistered,
VehicleNotInDatabase2,
}
#[derive(Default, Debug)]
pub struct TerminalRegistrationReply {
pub answer_serial_no: u16,
@ -35,20 +88,47 @@ pub struct TerminalRegistrationReply {
pub authentication_code: String,
}
impl TerminalRegistrationReply {
pub fn parse(&mut self, body: &Vec<u8>) {}
pub fn body_to_vec(&self) -> Vec<u8> {
let mut res: Vec<u8> = vec![];
for b in self.answer_serial_no.to_be_bytes() {
res.push(b);
}
res.push(self.result);
for b in self.authentication_code.as_bytes() {
res.push(*b);
}
res
}
}
#[derive(Default, Debug)]
pub struct TerminalLogout {}
impl TerminalLogout {
pub fn parse(&mut self, body: &Vec<u8>) {}
}
#[derive(Default, Debug)]
pub struct TerminalAuthentication {
pub authentication_code: String,
}
impl TerminalAuthentication {
pub fn parse(&mut self, body: &Vec<u8>) {}
}
#[derive(Default, Debug)]
pub struct TerminalParameterSetting {
pub total_parameters: u8,
pub parameters: Vec<TerminalParameterData>,
}
impl TerminalParameterSetting {
pub fn parse(&mut self, body: &Vec<u8>) {}
}
#[derive(Default, Debug)]
pub struct TerminalParameterData {
pub parameter_id: u32,
@ -56,8 +136,15 @@ pub struct TerminalParameterData {
pub parameter_value: u8,
}
impl TerminalParameterData {
pub fn parse(&mut self, body: &Vec<u8>) {}
}
#[derive(Default, Debug)]
pub struct QueryTerminalParameter {}
impl QueryTerminalParameter {
pub fn parse(&mut self, body: &Vec<u8>) {}
}
#[derive(Default, Debug)]
pub struct QueryTerminalParameterResponse {
@ -66,12 +153,20 @@ pub struct QueryTerminalParameterResponse {
pub parameters: Vec<TerminalParameterData>,
}
impl QueryTerminalParameterResponse {
pub fn parse(&mut self, body: &Vec<u8>) {}
}
#[derive(Default, Debug)]
pub struct TerminalControl {
pub command_word: u8,
pub command_parameter: String,
}
impl TerminalControl {
pub fn parse(&mut self, body: &Vec<u8>) {}
}
#[derive(Default, Debug)]
pub struct LocationInformationReport {
pub alert_mark: u32,
@ -84,30 +179,36 @@ pub struct LocationInformationReport {
pub time: u32,
}
impl LocationInformationReport {
pub fn parse(&mut self, body: &Vec<u8>) {}
}
#[derive(Default, Debug)]
pub struct StartOfTrip {}
impl StartOfTrip {
pub fn parse(&mut self, body: &Vec<u8>) {}
}
#[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,
impl EndOfTrip {
pub fn parse(&mut self, body: &Vec<u8>) {}
}
pub trait BodyMessage {
fn parse() {}
}
generate_impl!(
TerminalUniversalResponse,
PlatformUniversalResponse,
TerminalHeartbeat,
TerminalRegistration,
TerminalRegistrationReply,
TerminalLogout,
TerminalAuthentication,
TerminalParameterSetting,
TerminalParameterData,
QueryTerminalParameter,
QueryTerminalParameterResponse,
TerminalControl,
LocationInformationReport,
StartOfTrip,
EndOfTrip
);

View File

@ -1,14 +1,20 @@
mod body;
use body::*;
use std::fmt::*;
use bcd_convert::BcdNumber;
const FLAGDELIMITER: u8 = 0x7E;
#[allow(dead_code)]
const PropsSizeMask: u16 = 0x01FF;
const PropsSubcontractMask: u16 = 0x3000;
const PropsReservedMask: u16 = 0xC000;
const PropsDataEncryptionMask: u16 = 0x0E00;
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 Vec<u8>) -> Message {
let mut msg: Message = Message::default();
@ -22,11 +28,22 @@ pub fn parse_inbound_msg(rawdata: &mut Vec<u8>) -> Message {
#[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 Vec<u8>) {
let mut data = rawdata.clone().into_iter();
@ -34,17 +51,24 @@ impl Message {
if first_byte == FLAGDELIMITER {
println!("first flag ok");
};
self.header.id = ((data.next().unwrap() as u16) << 8) + data.next().unwrap() as u16;
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;
for i in 0..self.header.terminal_id.len() {
self.header.terminal_id[i] = data.next().unwrap();
}
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.properties as usize {
for _ in 0..self.header.bodylength as usize {
self.body.push(data.next().unwrap());
}
@ -55,10 +79,16 @@ impl Message {
} else {
println!("error with endflag");
}
self.parse_body();
}
pub fn parse_properties(&mut self) {
self.header.bodylength = (self.header.properties & PropsSizeMask) as u8;
self.header.bodylength = (self.header.properties & PROPS_SIZE_MASK) as u8;
}
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 Vec<u8>) {
@ -78,21 +108,128 @@ impl Message {
}
fn validate(&mut self, check: u8) {
println!("{}", BodyType::TerminalHeartbeat as u16);
self.valid = check == 0;
}
pub fn is_valid(&self) -> bool {
self.valid
}
pub fn parse_body(&mut self) {
match self.header.id {
0x0001 => {
self.content = MessageType::TerminalUniversalResponse(
TerminalUniversalResponse::new(&self.body),
)
}
0x8001 => {
self.content = MessageType::PlatformUniversalResponse(
PlatformUniversalResponse::new(&self.body),
)
}
0x0002 => {
self.content = MessageType::TerminalHeartbeat(TerminalHeartbeat::new(&self.body))
}
0x0100 => {
self.content =
MessageType::TerminalRegistration(TerminalRegistration::new(&self.body))
}
0x8100 => {
self.content = MessageType::TerminalRegistrationReply(
TerminalRegistrationReply::new(&self.body),
)
}
0x0003 => self.content = MessageType::TerminalLogout(TerminalLogout::new(&self.body)),
0x0102 => {
self.content =
MessageType::TerminalAuthentication(TerminalAuthentication::new(&self.body))
}
0x8103 => {
self.content =
MessageType::TerminalParameterSetting(TerminalParameterSetting::new(&self.body))
}
0x8104 => {
self.content =
MessageType::QueryTerminalParameter(QueryTerminalParameter::new(&self.body))
}
0x0104 => {
self.content = MessageType::QueryTerminalParameterResponse(
QueryTerminalParameterResponse::new(&self.body),
)
}
0x8105 => self.content = MessageType::TerminalControl(TerminalControl::new(&self.body)),
0x0200 => {
self.content = MessageType::LocationInformationReport(
LocationInformationReport::new(&self.body),
)
}
0x0202 => self.content = MessageType::StartOfTrip(StartOfTrip::new(&self.body)),
0x0203 => self.content = MessageType::EndOfTrip(EndOfTrip::new(&self.body)),
_ => self.content = MessageType::None,
}
}
pub fn set_reply(msg: Message) -> Message {
let mut reply = Message::default();
match msg.content {
MessageType::TerminalRegistration(t) => {
reply.content = MessageType::TerminalRegistrationReply(
t.generate_reply(msg.header.serial_number),
);
}
_ => {}
}
reply
}
}
#[derive(Default, Debug)]
pub struct MessageHeader {
pub id: u16,
id: u16,
properties: u16,
pub bodylength: u8,
pub encryption: bool,
pub terminal_id: [u8; 6],
raw_terminal_id: [u8; 6],
pub terminal_id: u64,
pub serial_number: u16,
}
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: {}",
self.id, self.bodylength, self.terminal_id, self.serial_number
)
}
}
#[derive(Debug)]
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 std::fmt::Display for MessageType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}