summaryrefslogtreecommitdiff
path: root/where-shared/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'where-shared/src/lib.rs')
-rw-r--r--where-shared/src/lib.rs136
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![];