mirror of
https://github.com/EFForg/rayhunter.git
synced 2026-06-20 03:14:19 -07:00
log parsing
This commit is contained in:
Generated
+230
@@ -2,6 +2,27 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
version = "1.0.1"
|
||||
@@ -14,6 +35,12 @@ dependencies = [
|
||||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
@@ -35,6 +62,41 @@ version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"wasm-bindgen",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "3.0.1"
|
||||
@@ -124,6 +186,7 @@ name = "diag"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"chrono",
|
||||
"crc",
|
||||
"deku",
|
||||
"libc",
|
||||
@@ -155,6 +218,29 @@ version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
@@ -171,18 +257,42 @@ dependencies = [
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.150"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
@@ -311,6 +421,126 @@ version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.39",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.39",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.51.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.5.19"
|
||||
|
||||
@@ -7,6 +7,7 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
bytes = "1.5.0"
|
||||
chrono = "0.4.31"
|
||||
crc = "3.0.1"
|
||||
deku = "0.16.0"
|
||||
libc = "0.2.150"
|
||||
|
||||
+65
-13
@@ -1,5 +1,6 @@
|
||||
//! Diag protocol serialization/deserialization
|
||||
|
||||
use chrono::{DateTime, Local, FixedOffset};
|
||||
use deku::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone, DekuWrite)]
|
||||
@@ -43,31 +44,66 @@ pub enum DataType {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, DekuRead)]
|
||||
pub struct ResponseContainer {
|
||||
pub struct MessagesContainer {
|
||||
pub data_type: DataType,
|
||||
pub num_responses: u32,
|
||||
#[deku(count = "num_responses")]
|
||||
pub responses: Vec<HdlcEncapsulatedResponse>,
|
||||
pub messages: Vec<HdlcEncapsulatedMessage>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, DekuRead)]
|
||||
pub struct HdlcEncapsulatedResponse {
|
||||
pub struct HdlcEncapsulatedMessage {
|
||||
pub len: u32,
|
||||
#[deku(count = "len")]
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
// kinda unpleasant deku hackery here. deku expects an enum's variant to be
|
||||
// right before its data, but in this case, a status value comes between the
|
||||
// variants and the data. so we need to use deku's context (ctx) feature to pass
|
||||
// those opcodes down to their respective parsers.
|
||||
#[derive(Debug, Clone, DekuRead)]
|
||||
pub struct Response {
|
||||
opcode: u32,
|
||||
subopcode: u32,
|
||||
pub status: u32,
|
||||
#[deku(ctx = "*opcode, *subopcode")]
|
||||
pub payload: ResponsePayload,
|
||||
#[deku(type = "u8")]
|
||||
pub enum Message {
|
||||
#[deku(id = "16")]
|
||||
Log {
|
||||
pending_msgs: u8,
|
||||
outer_length: u16,
|
||||
inner_length: u16,
|
||||
log_type: u16,
|
||||
timestamp: Timestamp,
|
||||
#[deku(count = "inner_length - 12")]
|
||||
payload: Vec<u8>,
|
||||
},
|
||||
|
||||
// kinda unpleasant deku hackery here. deku expects an enum's variant to be
|
||||
// right before its data, but in this case, a status value comes between the
|
||||
// variants and the data. so we need to use deku's context (ctx) feature to
|
||||
// pass those opcodes down to their respective parsers.
|
||||
#[deku(id_pat = "_")]
|
||||
Response {
|
||||
opcode: u32,
|
||||
subopcode: u32,
|
||||
status: u32,
|
||||
#[deku(ctx = "*opcode, *subopcode")]
|
||||
payload: ResponsePayload,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, DekuRead)]
|
||||
#[deku(endian = "little")]
|
||||
pub struct Timestamp {
|
||||
pub ts: u64,
|
||||
}
|
||||
|
||||
impl Timestamp {
|
||||
pub fn to_datetime(&self) -> DateTime<FixedOffset> {
|
||||
// Upper 48 bits: epoch at 1980-01-06 00:00:00, incremented by 1 for 1/800s
|
||||
// Lower 16 bits: time since last 1/800s tick in 1/32 chip units
|
||||
let ts_upper = self.ts >> 16;
|
||||
let ts_lower = self.ts & 0xffff;
|
||||
let epoch = chrono::DateTime::parse_from_rfc3339("1980-01-06T00:00:00-00:00").unwrap();
|
||||
let mut delta_seconds = ts_upper as f64 * 1.25;
|
||||
delta_seconds += ts_lower as f64 / 40960.0;
|
||||
let ts_delta = chrono::Duration::milliseconds(delta_seconds as i64);
|
||||
epoch + ts_delta
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, DekuRead)]
|
||||
@@ -177,4 +213,20 @@ mod test {
|
||||
1, 2, 3, 4,
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_parsing() {
|
||||
let msg_bytes = vec![16, 0, 26, 0, 26, 0, 167, 24, 38, 161, 72, 107, 146, 30, 2, 1, 1, 1, 0, 0, 0, 0, 0, 140, 10, 0, 0, 220, 5, 0];
|
||||
match Message::from_bytes((msg_bytes.as_slice(), 0)) {
|
||||
Ok((_, Message::Log { pending_msgs, outer_length, inner_length, log_type, timestamp, payload })) => {
|
||||
assert_eq!(pending_msgs, 0);
|
||||
assert_eq!(outer_length, 26);
|
||||
assert_eq!(inner_length, 26);
|
||||
assert_eq!(log_type, 6311);
|
||||
assert_eq!(timestamp.to_datetime().date_naive(), chrono::NaiveDate::from_ymd_opt(2023, 12, 4).unwrap());
|
||||
assert_eq!(payload, vec![1, 1, 0, 0, 0, 0, 0, 140, 10, 0, 0, 220, 5, 0]);
|
||||
},
|
||||
_ => panic!("failed to parse message"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+42
-31
@@ -1,5 +1,5 @@
|
||||
use crate::hdlc::{hdlc_encapsulate, hdlc_decapsulate, HdlcError};
|
||||
use crate::diag::{Response, ResponsePayload, Request, LogConfigRequest, LogConfigResponse, build_log_mask_request, RequestContainer, DataType, ResponseContainer};
|
||||
use crate::diag::{Message, ResponsePayload, Request, LogConfigRequest, LogConfigResponse, build_log_mask_request, RequestContainer, DataType, MessagesContainer};
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{Cursor, Read, Write};
|
||||
@@ -72,32 +72,35 @@ impl DiagDevice {
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_response_container(&self, container: ResponseContainer) -> DiagResult<Vec<Response>> {
|
||||
fn parse_response_container(&self, container: MessagesContainer) -> DiagResult<Vec<Message>> {
|
||||
let mut result = Vec::new();
|
||||
for msg in container.responses {
|
||||
let data = hdlc_decapsulate(msg.data, &self.crc)?;
|
||||
match Response::from_bytes((&data, 0)) {
|
||||
Ok(((_, leftover_bytes), res)) => {
|
||||
if leftover_bytes > 0 {
|
||||
println!("warning: {} leftover bytes when Response", leftover_bytes);
|
||||
}
|
||||
result.push(res);
|
||||
},
|
||||
Err(e) => {
|
||||
println!("{:?}", data);
|
||||
println!("error parsing response: {:?}", e);
|
||||
for msg in container.messages {
|
||||
match hdlc_decapsulate(msg.data, &self.crc) {
|
||||
Ok(data) => match Message::from_bytes((&data, 0)) {
|
||||
Ok(((_, leftover_bytes), res)) => {
|
||||
if leftover_bytes > 0 {
|
||||
println!("warning: {} leftover bytes when Response", leftover_bytes);
|
||||
}
|
||||
result.push(res);
|
||||
},
|
||||
Err(e) => {
|
||||
println!("error parsing response: {:?}", e);
|
||||
},
|
||||
},
|
||||
Err(err) => {
|
||||
println!("error decapsulating response: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn read_response(&mut self) -> DiagResult<Vec<Response>> {
|
||||
pub fn read_response(&mut self) -> DiagResult<Vec<Message>> {
|
||||
let mut buf = vec![0; BUFFER_LEN];
|
||||
|
||||
loop {
|
||||
let _ = self.file.read(&mut buf)?;
|
||||
let ((_, leftover_bytes), res_container) = ResponseContainer::from_bytes((&buf, 0))?;
|
||||
let ((_, leftover_bytes), res_container) = MessagesContainer::from_bytes((&buf, 0))?;
|
||||
if leftover_bytes > 0 {
|
||||
println!("warning: {} leftover bytes when parsing ResponseContainer", leftover_bytes);
|
||||
}
|
||||
@@ -124,7 +127,7 @@ impl DiagDevice {
|
||||
let msg = format!("write failed with error code {}", ret);
|
||||
return Err(DiagDeviceError::DeviceReadFailed(msg));
|
||||
}
|
||||
println!("{}. wrote {} bytes to device", buf.len(), ret);
|
||||
println!("wrote {} bytes to device", ret);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -133,15 +136,18 @@ impl DiagDevice {
|
||||
let req = Request::LogConfig(LogConfigRequest::RetrieveIdRanges);
|
||||
self.write_request(&req)?;
|
||||
|
||||
for res in self.read_response()? {
|
||||
match res.payload {
|
||||
ResponsePayload::LogConfig(LogConfigResponse::RetrieveIdRanges { log_mask_sizes }) => {
|
||||
if res.status != 0 {
|
||||
return Err(DiagDeviceError::RequestFailed(res.status, req));
|
||||
}
|
||||
return Ok(log_mask_sizes);
|
||||
for msg in self.read_response()? {
|
||||
match msg {
|
||||
Message::Log { .. } => println!("skipping log response..."),
|
||||
Message::Response { payload, status, .. } => match payload {
|
||||
ResponsePayload::LogConfig(LogConfigResponse::RetrieveIdRanges { log_mask_sizes }) => {
|
||||
if status != 0 {
|
||||
return Err(DiagDeviceError::RequestFailed(status, req));
|
||||
}
|
||||
return Ok(log_mask_sizes);
|
||||
},
|
||||
_ => println!("skipping non-LogConfigResponse response..."),
|
||||
},
|
||||
_ => println!("skipping non-LogConfigResponse response..."),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,12 +159,17 @@ impl DiagDevice {
|
||||
let req = build_log_mask_request(log_type, log_mask_bitsize);
|
||||
self.write_request(&req)?;
|
||||
|
||||
for res in self.read_response()? {
|
||||
if let ResponsePayload::LogConfig(LogConfigResponse::SetMask) = res.payload {
|
||||
if res.status != 0 {
|
||||
return Err(DiagDeviceError::RequestFailed(res.status, req));
|
||||
}
|
||||
return Ok(());
|
||||
for msg in self.read_response()? {
|
||||
match msg {
|
||||
Message::Log { .. } => println!("skipping log response..."),
|
||||
Message::Response { payload, status, .. } => {
|
||||
if let ResponsePayload::LogConfig(LogConfigResponse::SetMask) = payload {
|
||||
if status != 0 {
|
||||
return Err(DiagDeviceError::RequestFailed(status, req));
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user