Skip to main content

microsandbox_protocol/
tcp.rs

1//! TCP stream protocol message payloads.
2
3use serde::{Deserialize, Serialize};
4
5use crate::bulk::BulkOffer;
6
7//--------------------------------------------------------------------------------------------------
8// Types
9//--------------------------------------------------------------------------------------------------
10
11/// Request to open a TCP connection from inside the guest.
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct TcpConnect {
14    /// Destination host name or address as seen by the guest.
15    pub host: String,
16
17    /// Destination TCP port.
18    pub port: u16,
19
20    /// Generation-8 bidirectional raw-bulk offer.
21    #[serde(default, skip_serializing_if = "Option::is_none")]
22    pub bulk: Option<BulkOffer>,
23}
24
25/// Confirmation that a TCP connection was opened.
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct TcpConnected {}
28
29/// TCP stream data.
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct TcpData {
32    /// The raw stream bytes.
33    #[serde(with = "serde_bytes")]
34    pub data: Vec<u8>,
35}
36
37/// Notification that one side has closed its write half.
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct TcpEof {}
40
41/// Request to close the TCP session.
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct TcpClose {}
44
45/// Terminal notification that the TCP session is closed.
46#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct TcpClosed {}
48
49/// Terminal notification that the TCP session failed.
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct TcpFailed {
52    /// Human-readable failure description.
53    pub error: String,
54}
55
56//--------------------------------------------------------------------------------------------------
57// Tests
58//--------------------------------------------------------------------------------------------------
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn tcp_payloads_roundtrip() {
66        let connect = TcpConnect {
67            host: "127.0.0.1".to_string(),
68            port: 8080,
69            bulk: None,
70        };
71        let mut buf = Vec::new();
72        ciborium::into_writer(&connect, &mut buf).unwrap();
73        let decoded: TcpConnect = ciborium::from_reader(&buf[..]).unwrap();
74        assert_eq!(decoded.host, connect.host);
75        assert_eq!(decoded.port, connect.port);
76
77        let data = TcpData {
78            data: b"hello".to_vec(),
79        };
80        buf.clear();
81        ciborium::into_writer(&data, &mut buf).unwrap();
82        let decoded: TcpData = ciborium::from_reader(&buf[..]).unwrap();
83        assert_eq!(decoded.data, data.data);
84
85        let failed = TcpFailed {
86            error: "connection refused".to_string(),
87        };
88        buf.clear();
89        ciborium::into_writer(&failed, &mut buf).unwrap();
90        let decoded: TcpFailed = ciborium::from_reader(&buf[..]).unwrap();
91        assert_eq!(decoded.error, failed.error);
92    }
93}