//! OPLOCK_BREAK handler — acknowledge breaks and update oplock state. use std::sync::Arc; use crate::proto::header::Smb2Header; use crate::proto::messages::{FileId, OplockBreakAck}; use crate::conn::state::Connection; use crate::dispatch::HandlerResponse; use crate::handlers::shared::lookup_session_tree; use crate::ntstatus; use crate::server::ServerState; pub async fn handle( server: &Arc, conn: &Arc, hdr: &Smb2Header, body: &[u8], ) -> HandlerResponse { // Parse client's ACK (MS-SMB2 §2.2.24) let ack = match OplockBreakAck::parse(body) { Ok(a) => a, Err(_) => return HandlerResponse::err(ntstatus::STATUS_INVALID_PARAMETER), }; // Lookup tree to get path for oplock manager let tree_arc = match lookup_session_tree(conn, hdr).await { Ok(t) => t, Err(s) => return HandlerResponse::err(s), }; // Update oplock level in the open let path = { // Find the open by file_id let tree = tree_arc.read().await; let opens = tree.opens.read().await; if let Some(open_arc) = opens.get(&ack.file_id) { let mut open = open_arc.write().await; open.oplock_level = ack.oplock_level; open.last_path.clone() } else { return HandlerResponse::err(ntstatus::STATUS_FILE_CLOSED); } }; // Update OplockManager entry server.oplock_manager.update_oplock_level( &path, ack.file_id, ack.oplock_level, ).await; // Echo back the ACK as confirmation (MS-SMB2 §2.2.24) let mut buf = Vec::new(); ack.write_to(&mut buf).expect("encode ack response"); HandlerResponse::ok(buf) }