From 5da9aad0a81ed73ab130b217245088cb07e4ea2e Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Thu, 9 Nov 2023 15:05:20 -0800 Subject: [PATCH 1/7] refactor into a struct to prepare for tcp server --- Cargo.lock | 70 +++++++++++++++++++++++++++++----------- Cargo.toml | 2 +- src/main.rs | 93 ++++++++++++++++++++++++++++++++++++----------------- 3 files changed, 115 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ad6b329..29ed24f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,24 +2,12 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "bitflags" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - [[package]] name = "diag" version = "0.1.0" dependencies = [ "libc", - "nix", + "thiserror", ] [[package]] @@ -29,12 +17,56 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] -name = "nix" -version = "0.27.1" +name = "proc-macro2" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ - "bitflags", - "cfg-if", - "libc", + "unicode-ident", ] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/Cargo.toml b/Cargo.toml index 5fd8df4..ee5c071 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,5 +7,5 @@ edition = "2021" [dependencies] libc = "0.2.150" -nix = { version = "0.27.1", features = ["ioctl"]} +thiserror = "1.0.50" diff --git a/src/main.rs b/src/main.rs index 525bfd8..0ec7db8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,45 +1,78 @@ use std::fs::File; use std::mem; use std::os::unix::io::AsRawFd; +use thiserror::Error; -fn main() -> std::io::Result<()> { - const DIAG_IOCTL_SWITCH_LOGGING: u32 = 7; - const MEMORY_DEVICE_MODE: i32 = 2; - const DIAG_IOCTL_REMOTE_DEV: u32 = 32; +type DiagResult = Result; - let mut mode_param: [i32; 3] = [MEMORY_DEVICE_MODE, -1, 0]; // diag_logging_mode_param_t - let use_mdm: i32 = 0; +const DIAG_IOCTL_REMOTE_DEV: u32 = 32; +const MEMORY_DEVICE_MODE: i32 = 2; +const DIAG_IOCTL_SWITCH_LOGGING: u32 = 7; - println!("Initializing DIAG"); +#[derive(Error, Debug)] +enum DiagDeviceError { + #[error("IO error: {0}")] + IO(#[from] std::io::Error), + #[error("Failed to initialize /dev/diag: {0}")] + InitializationFailed(String), +} - let diag_file = File::options() - .read(true) - .write(true) - .open("/dev/diag")?; - let diag_fd = diag_file.as_raw_fd(); +struct DiagDevice { + file: File, + fd: i32, + use_mdm: i32, +} +fn enable_frame_readwrite(fd: i32, mode: i32) -> DiagResult<()> { unsafe { - if libc::ioctl(diag_fd, DIAG_IOCTL_SWITCH_LOGGING, MEMORY_DEVICE_MODE, 0, 0, 0) < 0 - && libc::ioctl( - diag_fd, + if libc::ioctl(fd, DIAG_IOCTL_SWITCH_LOGGING, mode, 0, 0, 0) < 0 { + let ret = libc::ioctl( + fd, DIAG_IOCTL_SWITCH_LOGGING, - &mut mode_param as *mut _, + &mut [mode, -1, 0] as *mut _, // diag_logging_mode_param_t mem::size_of::<[i32; 3]>(), 0, 0, 0, 0 - ) < 0 - { - println!("ioctl failed 1"); - //std::process::exit(1); + ); + if ret < 0 { + let msg = format!("DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code {}", ret); + return Err(DiagDeviceError::InitializationFailed(msg)) + } } } - - unsafe { - if libc::ioctl(diag_fd, DIAG_IOCTL_REMOTE_DEV, &use_mdm as *const i32) < 0 { - println!("ioctl failed 2"); - std::process::exit(1); - } - } - - println!("successfully opened diag device"); - + Ok(()) +} + +fn determine_use_mdm(fd: i32) -> DiagResult { + let use_mdm: i32 = 0; + unsafe { + if libc::ioctl(fd, DIAG_IOCTL_REMOTE_DEV, &use_mdm as *const i32) < 0 { + let msg = format!("DIAG_IOCTL_REMOTE_DEV ioctl failed with error code {}", 0); + return Err(DiagDeviceError::InitializationFailed(msg)) + } + } + Ok(use_mdm) +} + +impl DiagDevice { + pub fn new() -> DiagResult { + let file = File::options() + .read(true) + .write(true) + .open("/dev/diag")?; + let fd = file.as_raw_fd(); + + enable_frame_readwrite(fd, MEMORY_DEVICE_MODE)?; + let use_mdm = determine_use_mdm(fd)?; + + Ok(DiagDevice { + file, + fd, + use_mdm, + }) + } +} + +fn main() -> DiagResult<()> { + println!("Initializing DIAG"); + let dev = DiagDevice::new()?; Ok(()) } From 05cc2839ce8ec176d617e69da3f68079ea51ed0a Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Thu, 9 Nov 2023 18:43:31 -0800 Subject: [PATCH 2/7] add tokio --- Cargo.lock | 308 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + 2 files changed, 309 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 29ed24f..d038e73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,20 +2,180 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bytes" +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 = "diag" version = "0.1.0" dependencies = [ "libc", "thiserror", + "tokio", ] +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + [[package]] name = "libc" version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + [[package]] name = "proc-macro2" version = "1.0.69" @@ -34,6 +194,52 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "smallvec" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" + +[[package]] +name = "socket2" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "syn" version = "2.0.39" @@ -65,8 +271,110 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio" +version = "1.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +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" diff --git a/Cargo.toml b/Cargo.toml index ee5c071..59662a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,5 @@ edition = "2021" [dependencies] libc = "0.2.150" thiserror = "1.0.50" +tokio = { version = "1.34.0", features = ["full"] } From 508b882d45cd21d68fe7f3ea4d2f7ce1d3a91247 Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Thu, 9 Nov 2023 18:43:41 -0800 Subject: [PATCH 3/7] implement server --- src/main.rs | 122 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 111 insertions(+), 11 deletions(-) diff --git a/src/main.rs b/src/main.rs index 0ec7db8..3b1d65f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,19 @@ -use std::fs::File; +use std::io::Cursor; use std::mem; -use std::os::unix::io::AsRawFd; +use std::io; +use std::os::fd::AsRawFd; +use std::sync::Arc; use thiserror::Error; +use tokio::fs::File; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::net::TcpListener; +use tokio::net::tcp::OwnedWriteHalf; +use tokio::sync::Mutex; type DiagResult = Result; +const BUFFER_LEN: usize = 1024 * 1024 * 10; +const USER_SPACE_DATA_TYPE: i32 = 32; const DIAG_IOCTL_REMOTE_DEV: u32 = 32; const MEMORY_DEVICE_MODE: i32 = 2; const DIAG_IOCTL_SWITCH_LOGGING: u32 = 7; @@ -12,14 +21,15 @@ const DIAG_IOCTL_SWITCH_LOGGING: u32 = 7; #[derive(Error, Debug)] enum DiagDeviceError { #[error("IO error: {0}")] - IO(#[from] std::io::Error), + IO(#[from] io::Error), #[error("Failed to initialize /dev/diag: {0}")] InitializationFailed(String), + #[error("Failed to read diag device: {0}")] + DeviceReadFailed(String), } struct DiagDevice { - file: File, - fd: i32, + pub file: File, use_mdm: i32, } @@ -53,11 +63,11 @@ fn determine_use_mdm(fd: i32) -> DiagResult { } impl DiagDevice { - pub fn new() -> DiagResult { + pub async fn new() -> DiagResult { let file = File::options() .read(true) .write(true) - .open("/dev/diag")?; + .open("/dev/diag").await?; let fd = file.as_raw_fd(); enable_frame_readwrite(fd, MEMORY_DEVICE_MODE)?; @@ -65,14 +75,104 @@ impl DiagDevice { Ok(DiagDevice { file, - fd, use_mdm, }) } + + pub async fn read_response(&mut self) -> DiagResult>>> { + let mut buf = vec![0; BUFFER_LEN]; + let bytes_read = self.file.read(&mut buf).await?; + if bytes_read < 4 { + let msg = format!("read {} bytes from diag device, expected > 4", bytes_read); + return Err(DiagDeviceError::DeviceReadFailed(msg)); + } + let mut reader = Cursor::new(buf); + + // is this a USER_SPACE_DATA_TYPE? + if reader.read_i32().await? != USER_SPACE_DATA_TYPE { + return Ok(None); + } + + let num_messages = reader.read_u32().await?; + let mut messages = Vec::new(); + + for _ in 0..num_messages { + let msg_len = reader.read_u32().await? as usize; + let mut msg = vec![0; msg_len]; + reader.read_exact(&mut msg).await?; + messages.push(msg); + } + + Ok(Some(messages)) + } + + pub async fn write_request(&mut self, req: &[u8]) -> DiagResult<()> { + let mut buf: Vec = Vec::with_capacity(req.len()); + buf.write_i32(USER_SPACE_DATA_TYPE).await?; + if self.use_mdm > 0 { + buf.write_u32(0xffffffff).await?; + } + buf.extend_from_slice(req); + self.file.write_all(&buf).await?; + Ok(()) + } } -fn main() -> DiagResult<()> { +#[tokio::main] +async fn main() -> io::Result<()> { println!("Initializing DIAG"); - let dev = DiagDevice::new()?; - Ok(()) + let dev = Arc::new(Mutex::new(DiagDevice::new().await.unwrap())); + let clients: Arc>> = Arc::new(Mutex::new(Vec::new())); + + let dev_clone = dev.clone(); + let clients_clone = clients.clone(); + tokio::spawn(async move { + loop { + let mut dev_ = dev_clone.lock().await; + match dev_.read_response().await.unwrap() { + Some(msg) => { + let mut clients_ = clients_clone.lock().await; + for client in clients_.iter_mut() { + for buf in &msg { + client.write(buf).await.unwrap(); + } + } + }, + None => {}, + } + } + }); + + println!("Starting server"); + let listener = TcpListener::bind("0.0.0.0:1312").await?; + + // handle incoming clients + loop { + let (socket, _) = listener.accept().await?; + let (mut read, write) = socket.into_split(); + let client_idx: usize; + { + let mut clients_ = clients.lock().await; + clients_.push(write); + client_idx = clients_.len(); + } + let dev_clone = dev.clone(); + let clients_clone = clients.clone(); + tokio::spawn(async move { + let mut buf = vec![0; BUFFER_LEN]; + loop { + let bytes_read = read.read(&mut buf).await.unwrap(); + if bytes_read == 0 { + let mut clients_ = clients_clone.lock().await; + clients_.remove(client_idx); + println!("client {} disconnected", client_idx); + break; + } + println!("waiting to write {} byte diag request...", bytes_read); + let mut dev_ = dev_clone.lock().await; + dev_.write_request(&buf[0..bytes_read]).await.unwrap(); + println!("diag request complete"); + } + }); + } } From c02393a192ca733f76e251260790ea366f553cd2 Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Thu, 9 Nov 2023 22:37:05 -0800 Subject: [PATCH 4/7] appease clippy --- src/main.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3b1d65f..ea297cb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -129,16 +129,13 @@ async fn main() -> io::Result<()> { tokio::spawn(async move { loop { let mut dev_ = dev_clone.lock().await; - match dev_.read_response().await.unwrap() { - Some(msg) => { - let mut clients_ = clients_clone.lock().await; - for client in clients_.iter_mut() { - for buf in &msg { - client.write(buf).await.unwrap(); - } + if let Some(msg) = dev_.read_response().await.unwrap() { + let mut clients_ = clients_clone.lock().await; + for client in clients_.iter_mut() { + for buf in &msg { + let _ = client.write(buf).await.unwrap(); } - }, - None => {}, + } } } }); From f2bcda0342b4a302ebc965b237caea4c2f19c662 Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Tue, 14 Nov 2023 19:20:50 -0800 Subject: [PATCH 5/7] update deps --- Cargo.lock | 303 +---------------------------------------------------- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 303 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d038e73..9e2e35c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,180 +2,27 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bytes" 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 = "diag" version = "0.1.0" dependencies = [ + "bytes", "libc", "thiserror", - "tokio", ] -[[package]] -name = "gimli" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" - -[[package]] -name = "hermit-abi" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" - [[package]] name = "libc" version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" -dependencies = [ - "libc", - "wasi", - "windows-sys", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" -dependencies = [ - "memchr", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - [[package]] name = "proc-macro2" version = "1.0.69" @@ -194,52 +41,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "smallvec" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" - -[[package]] -name = "socket2" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" -dependencies = [ - "libc", - "windows-sys", -] - [[package]] name = "syn" version = "2.0.39" @@ -271,110 +72,8 @@ dependencies = [ "syn", ] -[[package]] -name = "tokio" -version = "1.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys", -] - -[[package]] -name = "tokio-macros" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -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" diff --git a/Cargo.toml b/Cargo.toml index 59662a7..f5346b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +bytes = "1.5.0" libc = "0.2.150" thiserror = "1.0.50" -tokio = { version = "1.34.0", features = ["full"] } From 3fc1b4d68678054d85c7570f40005a83eafd8fc6 Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Tue, 14 Nov 2023 19:20:58 -0800 Subject: [PATCH 6/7] fix server --- src/main.rs | 143 ++++++++++++++++++++++++++++------------------------ 1 file changed, 76 insertions(+), 67 deletions(-) diff --git a/src/main.rs b/src/main.rs index ea297cb..ad6af29 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,15 @@ +use std::fs::File; use std::io::Cursor; +use std::io::Read; +use std::io::Write; use std::mem; use std::io; +use std::net::TcpListener; +use std::sync::mpsc; +use bytes::{Buf, BufMut}; use std::os::fd::AsRawFd; -use std::sync::Arc; +use std::thread; use thiserror::Error; -use tokio::fs::File; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; -use tokio::net::TcpListener; -use tokio::net::tcp::OwnedWriteHalf; -use tokio::sync::Mutex; type DiagResult = Result; @@ -20,7 +21,7 @@ const DIAG_IOCTL_SWITCH_LOGGING: u32 = 7; #[derive(Error, Debug)] enum DiagDeviceError { - #[error("IO error: {0}")] + #[error("IO error {0}")] IO(#[from] io::Error), #[error("Failed to initialize /dev/diag: {0}")] InitializationFailed(String), @@ -63,11 +64,11 @@ fn determine_use_mdm(fd: i32) -> DiagResult { } impl DiagDevice { - pub async fn new() -> DiagResult { + pub fn new() -> DiagResult { let file = File::options() .read(true) .write(true) - .open("/dev/diag").await?; + .open("/dev/diag")?; let fd = file.as_raw_fd(); enable_frame_readwrite(fd, MEMORY_DEVICE_MODE)?; @@ -79,97 +80,105 @@ impl DiagDevice { }) } - pub async fn read_response(&mut self) -> DiagResult>>> { + pub fn try_clone(&self) -> DiagResult { + Ok(DiagDevice { + file: self.file.try_clone()?, + use_mdm: self.use_mdm, + }) + } + + pub fn read_response(&mut self) -> DiagResult>>> { let mut buf = vec![0; BUFFER_LEN]; - let bytes_read = self.file.read(&mut buf).await?; + let bytes_read = self.file.read(&mut buf)?; if bytes_read < 4 { let msg = format!("read {} bytes from diag device, expected > 4", bytes_read); return Err(DiagDeviceError::DeviceReadFailed(msg)); } let mut reader = Cursor::new(buf); - // is this a USER_SPACE_DATA_TYPE? - if reader.read_i32().await? != USER_SPACE_DATA_TYPE { + if reader.get_i32_le() != USER_SPACE_DATA_TYPE { return Ok(None); } - let num_messages = reader.read_u32().await?; + let num_messages = reader.get_u32_le(); let mut messages = Vec::new(); for _ in 0..num_messages { - let msg_len = reader.read_u32().await? as usize; + let msg_len = reader.get_u32_le() as usize; let mut msg = vec![0; msg_len]; - reader.read_exact(&mut msg).await?; + reader.read_exact(&mut msg)?; messages.push(msg); } Ok(Some(messages)) } - pub async fn write_request(&mut self, req: &[u8]) -> DiagResult<()> { - let mut buf: Vec = Vec::with_capacity(req.len()); - buf.write_i32(USER_SPACE_DATA_TYPE).await?; + pub fn write_request(&mut self, req: &[u8]) -> DiagResult<()> { + let mut buf: Vec = vec![]; + buf.put_i32_le(USER_SPACE_DATA_TYPE); if self.use_mdm > 0 { - buf.write_u32(0xffffffff).await?; + buf.put_i32_le(-1); } buf.extend_from_slice(req); - self.file.write_all(&buf).await?; + unsafe { + let fd = self.file.as_raw_fd(); + let buf_ptr = buf.as_ptr() as *const libc::c_void; + let ret = libc::write(fd, buf_ptr, buf.len()); + if ret < 0 { + let msg = format!("write failed with error code {}", ret); + return Err(DiagDeviceError::DeviceReadFailed(msg)); + } + } Ok(()) } } -#[tokio::main] -async fn main() -> io::Result<()> { - println!("Initializing DIAG"); - let dev = Arc::new(Mutex::new(DiagDevice::new().await.unwrap())); - let clients: Arc>> = Arc::new(Mutex::new(Vec::new())); - - let dev_clone = dev.clone(); - let clients_clone = clients.clone(); - tokio::spawn(async move { - loop { - let mut dev_ = dev_clone.lock().await; - if let Some(msg) = dev_.read_response().await.unwrap() { - let mut clients_ = clients_clone.lock().await; - for client in clients_.iter_mut() { - for buf in &msg { - let _ = client.write(buf).await.unwrap(); - } - } - } - } - }); - +fn main() -> io::Result<()> { println!("Starting server"); - let listener = TcpListener::bind("0.0.0.0:1312").await?; + let listener = TcpListener::bind("0.0.0.0:43555")?; - // handle incoming clients loop { - let (socket, _) = listener.accept().await?; - let (mut read, write) = socket.into_split(); - let client_idx: usize; - { - let mut clients_ = clients.lock().await; - clients_.push(write); - client_idx = clients_.len(); - } - let dev_clone = dev.clone(); - let clients_clone = clients.clone(); - tokio::spawn(async move { - let mut buf = vec![0; BUFFER_LEN]; + println!("waiting for client..."); + let (mut client_reader, _) = listener.accept()?; + let mut client_writer = client_reader.try_clone()?; + + println!("client connected, initializing diag device..."); + let mut dev_reader = DiagDevice::new().unwrap(); + let mut dev_writer = dev_reader.try_clone().unwrap(); + + let (reader_exit_tx, reader_exit_rx) = mpsc::channel::(); + let reader_handle = thread::spawn(move || { loop { - let bytes_read = read.read(&mut buf).await.unwrap(); - if bytes_read == 0 { - let mut clients_ = clients_clone.lock().await; - clients_.remove(client_idx); - println!("client {} disconnected", client_idx); - break; + if reader_exit_rx.try_recv().is_ok() { + return; + } + match dev_reader.read_response() { + Ok(Some(msgs)) => { + println!("writing {} messages to client...", msgs.len()); + for msg in msgs { + client_writer.write_all(&msg).unwrap(); + } + }, + Ok(None) => {}, + Err(err) => { + println!("dev reader thread err: {}", err); + return; + }, } - println!("waiting to write {} byte diag request...", bytes_read); - let mut dev_ = dev_clone.lock().await; - dev_.write_request(&buf[0..bytes_read]).await.unwrap(); - println!("diag request complete"); } }); + + let mut buf = vec![0; BUFFER_LEN]; + loop { + let bytes_read = client_reader.read(&mut buf).unwrap(); + if bytes_read == 0 { + println!("client disconnected, waiting for thread to exit..."); + reader_exit_tx.send(true).unwrap(); + reader_handle.join().unwrap(); + break; + } + println!("writing {} bytes to diag device...", bytes_read); + dev_writer.write_request(&buf[0..bytes_read]).unwrap(); + } } } From 5bd2c3f653432f792fa4438fb2bd451edf8b9737 Mon Sep 17 00:00:00 2001 From: Will Greenberg Date: Tue, 14 Nov 2023 20:22:39 -0800 Subject: [PATCH 7/7] various cleanups, fix client disconnect flow --- src/main.rs | 83 +++++++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/src/main.rs b/src/main.rs index ad6af29..9772a33 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,7 @@ use std::fs::File; -use std::io::Cursor; -use std::io::Read; -use std::io::Write; -use std::mem; -use std::io; -use std::net::TcpListener; -use std::sync::mpsc; +use std::io::{Cursor, Read, Write}; +use std::net::{TcpListener, TcpStream}; +use std::sync::{Arc, Mutex}; use bytes::{Buf, BufMut}; use std::os::fd::AsRawFd; use std::thread; @@ -22,7 +18,7 @@ const DIAG_IOCTL_SWITCH_LOGGING: u32 = 7; #[derive(Error, Debug)] enum DiagDeviceError { #[error("IO error {0}")] - IO(#[from] io::Error), + IO(#[from] std::io::Error), #[error("Failed to initialize /dev/diag: {0}")] InitializationFailed(String), #[error("Failed to read diag device: {0}")] @@ -41,7 +37,7 @@ fn enable_frame_readwrite(fd: i32, mode: i32) -> DiagResult<()> { fd, DIAG_IOCTL_SWITCH_LOGGING, &mut [mode, -1, 0] as *mut _, // diag_logging_mode_param_t - mem::size_of::<[i32; 3]>(), 0, 0, 0, 0 + std::mem::size_of::<[i32; 3]>(), 0, 0, 0, 0 ); if ret < 0 { let msg = format!("DIAG_IOCTL_SWITCH_LOGGING ioctl failed with error code {}", ret); @@ -133,51 +129,62 @@ impl DiagDevice { } } -fn main() -> io::Result<()> { +fn main() -> std::io::Result<()> { println!("Starting server"); let listener = TcpListener::bind("0.0.0.0:43555")?; - loop { - println!("waiting for client..."); - let (mut client_reader, _) = listener.accept()?; - let mut client_writer = client_reader.try_clone()?; + let client_mutex: Arc>> = Arc::new(Mutex::new(None)); - println!("client connected, initializing diag device..."); - let mut dev_reader = DiagDevice::new().unwrap(); - let mut dev_writer = dev_reader.try_clone().unwrap(); + let mut dev_reader = DiagDevice::new().unwrap(); + let mut dev_writer = dev_reader.try_clone().unwrap(); - let (reader_exit_tx, reader_exit_rx) = mpsc::channel::(); - let reader_handle = thread::spawn(move || { - loop { - if reader_exit_rx.try_recv().is_ok() { - return; - } - match dev_reader.read_response() { - Ok(Some(msgs)) => { - println!("writing {} messages to client...", msgs.len()); + let client_mutex_clone = client_mutex.clone(); + // Spawn a thread to continuously read from the diag device, sending + // messages to the client (if any) + thread::spawn(move || { + loop { + match dev_reader.read_response() { + Ok(Some(msgs)) => { + if let Some(client_writer) = client_mutex_clone.lock().unwrap().as_mut() { + println!("> Writing {} diag messages to client", msgs.len()); for msg in msgs { client_writer.write_all(&msg).unwrap(); } - }, - Ok(None) => {}, - Err(err) => { - println!("dev reader thread err: {}", err); - return; - }, - } + } + }, + Ok(None) => {}, + Err(err) => { + println!("Unable to read from /dev/diag: {}", err); + return; + }, } - }); + } + }); + + // Accept connections from clients, writing any data received to the diag device + loop { + println!("Waiting for client"); + let (mut client_reader, _) = listener.accept()?; + + println!("Client connected"); + let client_writer = client_reader.try_clone()?; + { + let mut client_writer_mutex = client_mutex.lock().unwrap(); + *client_writer_mutex = Some(client_writer); + } let mut buf = vec![0; BUFFER_LEN]; loop { let bytes_read = client_reader.read(&mut buf).unwrap(); if bytes_read == 0 { - println!("client disconnected, waiting for thread to exit..."); - reader_exit_tx.send(true).unwrap(); - reader_handle.join().unwrap(); + println!("Client disconnected"); + { + let mut client_writer_mutex = client_mutex.lock().unwrap(); + *client_writer_mutex = None; + } break; } - println!("writing {} bytes to diag device...", bytes_read); + println!("< Got {} bytes from client", bytes_read); dev_writer.write_request(&buf[0..bytes_read]).unwrap(); } }