use std::{cell::RefCell, rc::Rc};
use crate::{
connection::preauth_hash::PreauthHashValue,
packets::smb2::*,
session::{MessageDecryptor, MessageEncryptor, MessageSigner},
};
#[derive(Debug)]
pub struct OutgoingMessage {
pub message: PlainMessage,
pub signer: Option<MessageSigner>,
pub encryptor: Option<MessageEncryptor>,
pub finalize_preauth_hash: bool,
pub compress: bool,
}
impl OutgoingMessage {
pub fn new(message: PlainMessage) -> OutgoingMessage {
OutgoingMessage {
message,
signer: None,
encryptor: None,
finalize_preauth_hash: false,
compress: true,
}
}
}
#[derive(Debug)]
pub struct SendMessageResult {
pub preauth_hash: Option<PreauthHashValue>,
}
impl SendMessageResult {
pub fn new(preauth_hash: Option<PreauthHashValue>) -> SendMessageResult {
SendMessageResult { preauth_hash }
}
}
#[derive(Debug)]
pub struct IncomingMessage {
pub message: PlainMessage,
pub raw: Vec<u8>,
pub form: MessageForm,
}
#[derive(Debug, Default)]
pub struct MessageForm {
pub compressed: bool,
pub encrypted: bool,
}
#[derive(Debug)]
pub struct ReceiveOptions {
pub status: Status,
pub cmd: Option<Command>,
pub decryptor: Option<MessageDecryptor>,
}
impl ReceiveOptions {
pub fn new() -> Self {
Self::default()
}
pub fn status(mut self, status: Status) -> Self {
self.status = status;
self
}
pub fn cmd(mut self, cmd: Option<Command>) -> Self {
self.cmd = cmd;
self
}
}
impl Default for ReceiveOptions {
fn default() -> Self {
ReceiveOptions {
status: Status::Success,
cmd: None,
decryptor: None,
}
}
}
pub trait MessageHandler {
fn hsendo(
&mut self,
msg: OutgoingMessage,
) -> Result<SendMessageResult, Box<dyn std::error::Error>>;
fn hrecvo(
&mut self,
options: ReceiveOptions,
) -> Result<IncomingMessage, Box<dyn std::error::Error>>;
}
pub struct HandlerReference<T: MessageHandler + ?Sized> {
pub handler: Rc<RefCell<T>>,
}
impl<T: MessageHandler> HandlerReference<T> {
pub fn new(handler: T) -> HandlerReference<T> {
HandlerReference {
handler: Rc::new(RefCell::new(handler)),
}
}
pub fn sendo(
&mut self,
msg: OutgoingMessage,
) -> Result<SendMessageResult, Box<dyn std::error::Error>> {
self.handler.borrow_mut().hsendo(msg)
}
pub fn send(&mut self, msg: Content) -> Result<SendMessageResult, Box<dyn std::error::Error>> {
self.sendo(OutgoingMessage::new(PlainMessage::new(msg)))
}
pub fn recvo(
&mut self,
options: ReceiveOptions,
) -> Result<IncomingMessage, Box<dyn std::error::Error>> {
self.handler.borrow_mut().hrecvo(options)
}
pub fn recv(&mut self, cmd: Command) -> Result<IncomingMessage, Box<dyn std::error::Error>> {
self.recvo(ReceiveOptions::new().cmd(Some(cmd)))
}
pub fn sendo_recvo(
&mut self,
msg: OutgoingMessage,
options: ReceiveOptions,
) -> Result<IncomingMessage, Box<dyn std::error::Error>> {
self.sendo(msg)?;
self.recvo(options)
}
pub fn send_recvo(
&mut self,
msg: Content,
options: ReceiveOptions,
) -> Result<IncomingMessage, Box<dyn std::error::Error>> {
self.send(msg)?;
self.recvo(options)
}
pub fn send_recv(
&mut self,
msg: Content,
) -> Result<IncomingMessage, Box<dyn std::error::Error>> {
let cmd = msg.associated_cmd();
self.send(msg)?;
self.recvo(ReceiveOptions::new().cmd(Some(cmd)))
}
}
impl<T: MessageHandler> std::ops::Deref for HandlerReference<T> {
type Target = RefCell<T>;
fn deref(&self) -> &Self::Target {
&self.handler
}
}
impl<T: MessageHandler> Clone for HandlerReference<T> {
fn clone(&self) -> Self {
HandlerReference {
handler: self.handler.clone(),
}
}
}