Skip to main content

stackforge_core/layer/ssh/
builder.rs

1//! SSH layer builder.
2//!
3//! Provides a minimal builder for SSH version exchange messages.
4//! Full SSH binary packet construction is not supported since SSH
5//! requires encryption context for most operations.
6
7/// Builder for SSH layer data.
8///
9/// Currently supports building SSH version exchange messages.
10/// Binary SSH packets require encryption and are not constructable.
11#[derive(Debug, Clone)]
12pub struct SshBuilder {
13    /// Version string (e.g., "`OpenSSH_9.2p1`")
14    version: String,
15}
16
17impl Default for SshBuilder {
18    fn default() -> Self {
19        Self {
20            version: "stackforge".to_string(),
21        }
22    }
23}
24
25impl SshBuilder {
26    /// Create a new SSH builder with default version string.
27    #[must_use]
28    pub fn new() -> Self {
29        Self::default()
30    }
31
32    /// Create an SSH version exchange message.
33    ///
34    /// Generates `SSH-2.0-{version}\r\n`.
35    #[must_use]
36    pub fn version_exchange(version: &str) -> Self {
37        Self {
38            version: version.to_string(),
39        }
40    }
41
42    /// Set the version string.
43    #[must_use]
44    pub fn version(mut self, version: &str) -> Self {
45        self.version = version.to_string();
46        self
47    }
48
49    /// Get the header size (the full version exchange message length).
50    #[must_use]
51    pub fn header_size(&self) -> usize {
52        // "SSH-2.0-" + version + "\r\n"
53        8 + self.version.len() + 2
54    }
55
56    /// Build the SSH version exchange into bytes.
57    #[must_use]
58    pub fn build(&self) -> Vec<u8> {
59        format!("SSH-2.0-{}\r\n", self.version).into_bytes()
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn test_version_exchange_build() {
69        let builder = SshBuilder::version_exchange("OpenSSH_9.2p1");
70        let bytes = builder.build();
71        assert_eq!(bytes, b"SSH-2.0-OpenSSH_9.2p1\r\n");
72    }
73
74    #[test]
75    fn test_default_version() {
76        let builder = SshBuilder::new();
77        let bytes = builder.build();
78        assert_eq!(bytes, b"SSH-2.0-stackforge\r\n");
79    }
80
81    #[test]
82    fn test_header_size() {
83        let builder = SshBuilder::version_exchange("test");
84        assert_eq!(builder.header_size(), builder.build().len());
85    }
86}