diff options
Diffstat (limited to 'where-shared/src/lib.rs')
-rw-r--r-- | where-shared/src/lib.rs | 136 |
1 files changed, 35 insertions, 101 deletions
diff --git a/where-shared/src/lib.rs b/where-shared/src/lib.rs index 06cc5ba..774e2fd 100644 --- a/where-shared/src/lib.rs +++ b/where-shared/src/lib.rs @@ -1,8 +1,9 @@ use std::io::Cursor; use coreutils_core::os::utmpx::*; -use std::io::Read; -use crate::error::{EncodeDecodeError, EncodeDecodeResult}; +use crate::error::{WhereResult, EncodeDecodeResult, EncodeDecodeError}; + +mod parse; pub mod error; pub const WHERED_MAGIC: [u8; 4] = *b"WHRD"; @@ -12,15 +13,18 @@ pub const MAX_ENTRY_LENGTH: usize = MAX_REMOTE_LENGTH + MAX_USER_TTY_LENGTH * 2 pub const MAX_PAYLOAD_LENGTH: usize = 65501; pub const MAX_PAYLOAD_ENTRIES: usize = MAX_PAYLOAD_LENGTH / MAX_ENTRY_LENGTH; +type Payload = [u8; MAX_PAYLOAD_LENGTH]; +type PayloadCursor = Cursor<Payload>; + #[derive(Debug)] pub struct Session { pub host: Option<String>, - pub user: String, pub pid: i32, + pub login_time: i64, + pub user: String, pub tty: String, pub remote: Option<String>, pub active: bool, - pub login_time: i64 } #[derive(Debug)] @@ -71,26 +75,23 @@ impl SessionCollection { } } - pub fn from_udp_payload(buffer: [u8; MAX_PAYLOAD_LENGTH], host: &str) -> EncodeDecodeResult<Self> { - let mut buf = Cursor::new(buffer); + pub fn from_udp_payload(buffer: Payload, host: &str) -> WhereResult<Self> { + let mut cursor = Cursor::new(buffer); let mut inner = vec![]; - let mut magic = [0u8; 4]; - let mut length = [0u8; 2]; - Session::read_field(&mut buf, &mut magic)?; - Session::read_field(&mut buf, &mut length)?; - let entry_count = u16::from_be_bytes(length); + // Check magic + parse::read_field(&mut cursor, |buf| { + if buf != WHERED_MAGIC { + Err(EncodeDecodeError::BadMagic(buf))? + } else { + Ok(()) + } + })?; - if magic != WHERED_MAGIC { - return Err(EncodeDecodeError::BadMagic(magic)); - } + let entry_count = parse::read_field(&mut cursor, |buf| Ok(u32::from_be_bytes(buf)))?; for _ in 0..entry_count { - inner.push(Session::from_udp_payload(&mut buf, &host)?); - } - - if inner.len() != entry_count as usize { - return Err(EncodeDecodeError::IncorrectEntryCount); + inner.push(Session::from_udp_payload(&mut cursor, &host)?); } Ok(Self { @@ -100,103 +101,36 @@ impl SessionCollection { } impl Session { - pub fn from_udp_payload(cursor: &mut Cursor<[u8; MAX_PAYLOAD_LENGTH]>, host: &str) -> EncodeDecodeResult<Self> { - let mut username_length = [0u8; 4]; - let mut pid = [0u8; 4]; - let mut tty_length = [0u8; 4]; - let mut remote_tag = [0u8; 1]; - let mut remote_length = [0u8; 4]; - let mut active = [0u8; 1]; - let mut login_time = [0u8; 8]; - - Session::read_field(cursor, &mut pid)?; - Session::read_field(cursor, &mut login_time)?; - - Session::read_field(cursor, &mut username_length)?; - let username_length = u32::from_be_bytes(username_length); - if username_length as usize > MAX_USER_TTY_LENGTH { - return Err(EncodeDecodeError::StringSizeLimitExceeded(username_length, MAX_USER_TTY_LENGTH)); - } - - let mut user = vec![0u8; username_length as usize]; - Session::read_field(cursor, &mut user)?; - - Session::read_field(cursor, &mut tty_length)?; - let tty_length = u32::from_be_bytes(tty_length); - if tty_length as usize > MAX_USER_TTY_LENGTH { - return Err(EncodeDecodeError::StringSizeLimitExceeded(tty_length, MAX_USER_TTY_LENGTH)); - } - - let mut tty = vec![0u8; tty_length as usize]; - Session::read_field(cursor, &mut tty)?; - - Session::read_field(cursor, &mut remote_tag)?; - if remote_tag[0] > 1 { - return Err(EncodeDecodeError::NonbinaryBoolean); - } - - let has_remote_tag = remote_tag[0] == 1; - - let remote = if has_remote_tag { - Session::read_field(cursor, &mut remote_length)?; - let remote_length = u32::from_be_bytes(remote_length); - if remote_length as usize > MAX_USER_TTY_LENGTH { - return Err(EncodeDecodeError::StringSizeLimitExceeded(username_length, MAX_USER_TTY_LENGTH)); - } - - if remote_length == 0 { - return Err(EncodeDecodeError::EmptyRemote); + pub fn from_udp_payload(cursor: &mut PayloadCursor, host: &str) -> WhereResult<Self> { + let pid = parse::read_field(cursor, |buf| Ok(i32::from_be_bytes(buf)))?; + let login_time = parse::read_field(cursor, |buf| Ok(i64::from_be_bytes(buf)))?; + let user = parse::read_string_field(cursor)?; + let tty = parse::read_string_field(cursor)?; + + let remote = { + let has_remote_tag = parse::read_bool_field(cursor)?; + if has_remote_tag { + Some(parse::read_string_field(cursor)?) + } else { + None } - - let mut remote = vec![0u8; remote_length as usize]; - Session::read_field(cursor, &mut remote)?; - - Some(String::from_utf8_lossy(&remote).to_string()) - } else { - None }; - Session::read_field(cursor, &mut active)?; - if active[0] > 1 { - return Err(EncodeDecodeError::NonbinaryBoolean); - } - - let user = String::from_utf8_lossy(&user).to_string(); - let pid = i32::from_be_bytes(pid); - let tty = String::from_utf8_lossy(&tty).to_string(); - let active = active[0] == 1; - let login_time = i64::from_be_bytes(login_time); + let active = parse::read_bool_field(cursor)?; let host = Some(host.to_string()); Ok(Self { host, - user, pid, + login_time, + user, tty, remote, active, - login_time }) } - fn read_field(cursor: &mut Cursor<[u8; MAX_PAYLOAD_LENGTH]>, buffer: &mut [u8]) -> EncodeDecodeResult<()> { - cursor.read_exact(buffer)?; - Ok(()) - } - - /*fn read_field<T, F>(cursor: &mut Cursor<&[u8]>, convert_func: F) -> WhereResult<T> - where - N: const usize, - F: FnOnce([u8; N]) -> EncodeDecodeError, - { - let mut buf = [0u8; N]; - cursor.read_exact(&mut buf)?; - - let value = convert_func(buf)?; - Ok(value) - }*/ - pub fn to_udp_payload(self) -> Vec<u8> { let mut bytes: Vec<u8> = vec![]; |