diff --git a/markbase-core/src/ssh_server/channel.rs b/markbase-core/src/ssh_server/channel.rs index c631391..2be1513 100644 --- a/markbase-core/src/ssh_server/channel.rs +++ b/markbase-core/src/ssh_server/channel.rs @@ -460,7 +460,15 @@ impl ChannelManager { // Phase 7: 初始化SFTP handler let root_dir = PathBuf::from("/Users/accusys/markbase"); // 默认root目录 - let sftp_handler = SftpHandler::new(root_dir); + + // ⭐⭐⭐⭐⭐ Phase 4: 获取 client maxpack 限制(从 Channel 中获取) + let maxpacket = if let Some(ch) = self.channels.get(&channel) { + ch.remote_maxpacket // 来自 SSH_MSG_CHANNEL_OPEN 的 maximum_packet_size + } else { + 32768 // OpenSSH 默认值(32KB) + }; + + let sftp_handler = SftpHandler::new(root_dir, maxpacket); // ⭐⭐⭐⭐⭐ Phase 4: 传入 maxpack // 存储到channel if let Some(ch) = self.channels.get_mut(&channel) { diff --git a/markbase-core/src/ssh_server/sftp_handler.rs b/markbase-core/src/ssh_server/sftp_handler.rs index 1a9a023..69aeffb 100644 --- a/markbase-core/src/ssh_server/sftp_handler.rs +++ b/markbase-core/src/ssh_server/sftp_handler.rs @@ -256,15 +256,19 @@ pub struct SftpHandler { root_dir: PathBuf, next_handle_id: u32, handles: std::collections::HashMap, + // ⭐⭐⭐⭐⭐ Phase 4: 添加 client maxpack 限制(参考OpenSSH sftp-server.c) + maxpacket: u32, // 来自 SSH_MSG_CHANNEL_OPEN_CONFIRMATION 的 maximum_packet_size } impl SftpHandler { - pub fn new(root_dir: PathBuf) -> Self { + // ⭐⭐⭐⭐⭐ Phase 4: 修改 new() 方法,接受 maxpack 参数 + pub fn new(root_dir: PathBuf, maxpacket: u32) -> Self { let canonical_root = root_dir.canonicalize().unwrap_or(root_dir); Self { root_dir: canonical_root, next_handle_id: 0, handles: std::collections::HashMap::new(), + maxpacket, // ⭐⭐⭐⭐⭐ Phase 4: client maxpack 限制 } } @@ -420,7 +424,15 @@ impl SftpHandler { if let Some(ref mut file) = handle.file { file.seek(SeekFrom::Start(offset))?; - let mut buffer = vec![0u8; length as usize]; + // ⭐⭐⭐⭐⭐ Phase 4: 限制数据大小,不超过 maxpacket - 1024(参考OpenSSH sftp-server.c) + // OpenSSH sftp-server.c: process_read() 中限制数据大小为 maxpacket - 1024 bytes + // SSH packet overhead: ~1024 bytes (SSH header + SSH_FXP_DATA header) + let max_data_size = self.maxpacket - 1024; + let actual_length = std::cmp::min(length, max_data_size); + + info!("SSH_FXP_READ limited: requested={}, actual={}", length, actual_length); + + let mut buffer = vec![0u8; actual_length as usize]; match file.read(&mut buffer) { Ok(0) => { self.build_status_response(id, SftpStatus::SSH_FX_EOF, "End of file")