feat(ssh): Add SCP subsystem packet processing framework (Phase 8 partial)
This commit is contained in:
BIN
data/auth.sqlite
BIN
data/auth.sqlite
Binary file not shown.
@@ -762,6 +762,66 @@ impl ChannelManager {
|
||||
data.len()
|
||||
);
|
||||
|
||||
// ⭐⭐⭐⭐⭐ Phase 8: SCP handler (subsystem)
|
||||
if let Some(scp_handler) = &mut channel.scp_handler {
|
||||
info!(
|
||||
"⭐⭐⭐⭐⭐ [SCP_DATA] Feeding {} bytes to ScpHandler",
|
||||
data.len()
|
||||
);
|
||||
|
||||
// Window Control - decrease local_window
|
||||
channel.local_window -= data.len() as u32;
|
||||
channel.local_consumed += data.len() as u32;
|
||||
|
||||
// ⭐⭐⭐⭐⭐ Phase 14.4: SCP packet accumulation
|
||||
channel.scp_input_buffer.extend_from_slice(&data);
|
||||
info!(
|
||||
"SCP buffer accumulated: {} bytes total",
|
||||
channel.scp_input_buffer.len()
|
||||
);
|
||||
|
||||
// Process SCP packets (line-based protocol)
|
||||
// SCP uses newline-terminated commands: C0644, D0755, E, T
|
||||
// Reference: OpenSSH scp.c
|
||||
|
||||
// Find complete lines in buffer
|
||||
let mut responses: Vec<Vec<u8>> = Vec::new();
|
||||
while let Some(newline_pos) = channel.scp_input_buffer.iter().position(|&b| b == b'\n') {
|
||||
let line = channel.scp_input_buffer[..newline_pos].to_vec();
|
||||
channel.scp_input_buffer = channel.scp_input_buffer[newline_pos + 1..].to_vec();
|
||||
|
||||
info!("SCP command: {}", String::from_utf8_lossy(&line));
|
||||
|
||||
// Process SCP command
|
||||
// TODO: Full implementation requires ScpHandler.handle_scp() with ReadWrite trait
|
||||
// Current implementation: basic ACK (0 byte)
|
||||
responses.push(vec![0]); // SCP ACK
|
||||
}
|
||||
|
||||
// Check for window adjust
|
||||
if let Some(window_adjust_packet) =
|
||||
channel_check_window(recipient_channel, &mut self.channels)
|
||||
{
|
||||
return Ok(Some(window_adjust_packet));
|
||||
}
|
||||
|
||||
// Send SCP responses
|
||||
if !responses.is_empty() {
|
||||
// All responses except last go to pending_packets
|
||||
for i in 0..responses.len().saturating_sub(1) {
|
||||
let pending = self.build_channel_data(recipient_channel, &responses[i])?;
|
||||
self.pending_packets.push_back(pending);
|
||||
}
|
||||
|
||||
// Last response is returned
|
||||
if let Some(last_response) = responses.into_iter().last() {
|
||||
return Ok(Some(self.build_channel_data(recipient_channel, &last_response)?));
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
// ⭐⭐⭐⭐⭐ Phase 16.5: rsync in-process handler (no child process)
|
||||
if let Some(rsync_handler) = &mut channel.rsync_handler {
|
||||
info!(
|
||||
|
||||
Reference in New Issue
Block a user