Implement SMB Oplocks Phase 3+5
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled

Phase 3: NotificationQueue
- Add notification_tx to Connection struct
- Modify writer.rs to use tokio::select! for response + notification
- Add write_to_bytes() to OplockBreakNotification
- Support server→client async messages

Phase 5: WRITE Handler oplock break
- Get path/share_access before write
- Trigger OplockManager.break_oplock()
- Send OPLOCK_BREAK_NOTIFICATION to affected clients
- Encode and send via notification channel

All 229 tests pass.
This commit is contained in:
Warren
2026-06-21 00:35:48 +08:00
parent be9fe72742
commit 2dd50e4cb6
5 changed files with 90 additions and 14 deletions

View File

@@ -13,7 +13,7 @@ use crate::ntstatus;
use crate::server::ServerState;
pub async fn handle(
_server: &Arc<ServerState>,
server: &Arc<ServerState>,
conn: &Arc<Connection>,
hdr: &Smb2Header,
body: &[u8],
@@ -41,6 +41,34 @@ pub async fn handle(
Some(o) => o,
None => return HandlerResponse::err(ntstatus::STATUS_FILE_CLOSED),
};
// Phase 5: Get path and trigger oplock break before write
let (path, share_access) = {
let open = open_arc.read().await;
(open.last_path.clone(), open.share_access)
};
// Trigger oplock break for conflicting clients
let notifications = server.oplock_manager.break_oplock(
&path,
share_access,
granted,
).await;
// Send notifications to affected clients
for notification in notifications {
// Build SMB2 frame for notification
use crate::proto::framing::encode_frame;
let notification_bytes = notification.write_to_bytes();
let mut frame = Vec::with_capacity(notification_bytes.len() + 4);
encode_frame(&notification_bytes, &mut frame);
// Send via notification channel (if available)
if let Some(tx) = conn.notification_tx.read().await.as_ref() {
let _ = tx.send(frame).await;
}
}
let result = {
let open = open_arc.read().await;
match open.handle.as_ref() {