Skip to main content

redevplugin_worker_sdk/
tcp.rs

1use crate::api;
2use crate::error::Result;
3use crate::resource::{Handle, MAX_IO_CHUNK_BYTES};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize)]
7pub struct TcpConnect {
8    /// Connector declared by the current method; no implicit default is used.
9    pub connector_id: String,
10    pub host: String,
11    pub port: u16,
12    #[serde(default)]
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub timeout_ms: Option<u32>,
15    #[serde(default)]
16    pub no_delay: bool,
17    #[serde(default)]
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub keep_alive_ms: Option<u32>,
20}
21
22pub type ConnectOptions = TcpConnect;
23
24#[derive(Deserialize)]
25struct HandleResult {
26    handle: u64,
27}
28
29pub struct TcpStream {
30    handle: Handle,
31}
32
33impl TcpStream {
34    pub fn connect(options: TcpConnect) -> Result<Self> {
35        let opened: HandleResult = api::call("net.tcp.connect", &options)?;
36        Ok(Self {
37            handle: Handle::new(opened.handle)?,
38        })
39    }
40
41    pub fn read(&mut self, capacity: usize) -> Result<(Vec<u8>, u32)> {
42        self.handle.read(capacity)
43    }
44
45    pub fn write_all(&mut self, bytes: &[u8]) -> Result<()> {
46        for chunk in bytes.chunks(MAX_IO_CHUNK_BYTES) {
47            self.handle.write(chunk, 0)?;
48        }
49        Ok(())
50    }
51
52    pub fn shutdown(&mut self, direction: Shutdown) -> Result<()> {
53        #[derive(Serialize)]
54        struct Arguments {
55            handle: u64,
56            direction: Shutdown,
57        }
58        let _: serde_json::Value = api::call(
59            "net.tcp.shutdown",
60            &Arguments {
61                handle: self.handle.id(),
62                direction,
63            },
64        )?;
65        Ok(())
66    }
67
68    pub fn close(mut self) -> Result<()> {
69        self.handle.close()
70    }
71}
72
73#[derive(Debug, Clone, Copy, Serialize)]
74#[serde(rename_all = "snake_case")]
75pub enum Shutdown {
76    Read,
77    Write,
78    Both,
79}
80
81#[derive(Debug, Clone, Serialize)]
82pub struct TcpListen {
83    pub host: String,
84    pub port: u16,
85}
86
87pub type ListenOptions = TcpListen;
88
89#[derive(Deserialize)]
90struct ListenResult {
91    handle: u64,
92    address: String,
93}
94
95pub struct TcpListener {
96    handle: Handle,
97    pub address: String,
98}
99
100impl TcpListener {
101    pub fn listen(options: TcpListen) -> Result<Self> {
102        let opened: ListenResult = api::call("net.tcp.listen", &options)?;
103        Ok(Self {
104            handle: Handle::new(opened.handle)?,
105            address: opened.address,
106        })
107    }
108
109    pub fn accept(&mut self, no_delay: bool, keep_alive_ms: Option<u32>) -> Result<TcpStream> {
110        #[derive(Serialize)]
111        struct Arguments {
112            handle: u64,
113            no_delay: bool,
114            #[serde(skip_serializing_if = "Option::is_none")]
115            keep_alive_ms: Option<u32>,
116        }
117        let opened: HandleResult = api::call(
118            "net.tcp.accept",
119            &Arguments {
120                handle: self.handle.id(),
121                no_delay,
122                keep_alive_ms,
123            },
124        )?;
125        Ok(TcpStream {
126            handle: Handle::new(opened.handle)?,
127        })
128    }
129
130    pub fn close(mut self) -> Result<()> {
131        self.handle.close()
132    }
133}