ferogram_connect/
transport_intermediate.rs1use crate::ConnectError;
14use tokio::io::{AsyncReadExt, AsyncWriteExt};
15use tokio::net::TcpStream;
16
17pub struct IntermediateTransport {
26 stream: TcpStream,
27 init_sent: bool,
28}
29
30impl IntermediateTransport {
31 pub async fn connect(addr: &str) -> Result<Self, ConnectError> {
33 let stream = TcpStream::connect(addr).await?;
34 Ok(Self {
35 stream,
36 init_sent: false,
37 })
38 }
39
40 pub fn from_stream(stream: TcpStream) -> Self {
42 Self {
43 stream,
44 init_sent: false,
45 }
46 }
47
48 pub async fn send(&mut self, data: &[u8]) -> Result<(), ConnectError> {
50 if !self.init_sent {
51 self.stream.write_all(&[0xee, 0xee, 0xee, 0xee]).await?;
52 self.init_sent = true;
53 }
54 let len = (data.len() as u32).to_le_bytes();
55 self.stream.write_all(&len).await?;
56 self.stream.write_all(data).await?;
57 Ok(())
58 }
59
60 pub async fn recv(&mut self) -> Result<Vec<u8>, ConnectError> {
62 let mut len_buf = [0u8; 4];
63 self.stream.read_exact(&mut len_buf).await?;
64 let raw = i32::from_le_bytes(len_buf);
65 if raw < 0 {
66 return Err(ConnectError::Io(std::io::Error::new(
67 std::io::ErrorKind::ConnectionRefused,
68 format!("transport error: {raw}"),
69 )));
70 }
71 let len = raw as usize;
72 let mut buf = vec![0u8; len];
73 self.stream.read_exact(&mut buf).await?;
74 Ok(buf)
75 }
76
77 pub fn into_inner(self) -> TcpStream {
78 self.stream
79 }
80}
81
82pub struct PaddedIntermediateTransport {
93 stream: TcpStream,
94 init_sent: bool,
95}
96
97impl PaddedIntermediateTransport {
98 pub async fn connect(addr: &str) -> Result<Self, ConnectError> {
100 let stream = TcpStream::connect(addr).await?;
101 Ok(Self {
102 stream,
103 init_sent: false,
104 })
105 }
106
107 pub fn from_stream(stream: TcpStream) -> Self {
109 Self {
110 stream,
111 init_sent: false,
112 }
113 }
114
115 pub async fn send(&mut self, data: &[u8]) -> Result<(), ConnectError> {
120 if !self.init_sent {
121 self.stream.write_all(&[0xdd, 0xdd, 0xdd, 0xdd]).await?;
122 self.init_sent = true;
123 }
124 let mut pad_len_buf = [0u8; 1];
125 ferogram_crypto::fill_random(&mut pad_len_buf);
126 let pad_len = (pad_len_buf[0] & 0x0f) as usize;
127 let total_len = (data.len() + pad_len) as u32;
128 self.stream.write_all(&total_len.to_le_bytes()).await?;
129 self.stream.write_all(data).await?;
130 if pad_len > 0 {
131 let mut pad = vec![0u8; pad_len];
132 ferogram_crypto::fill_random(&mut pad);
133 self.stream.write_all(&pad).await?;
134 }
135 Ok(())
136 }
137
138 pub async fn recv(&mut self) -> Result<Vec<u8>, ConnectError> {
140 let mut len_buf = [0u8; 4];
141 self.stream.read_exact(&mut len_buf).await?;
142 let raw = i32::from_le_bytes(len_buf);
143 if raw < 0 {
144 return Err(ConnectError::Io(std::io::Error::new(
145 std::io::ErrorKind::ConnectionRefused,
146 format!("transport error: {raw}"),
147 )));
148 }
149 let total_len = raw as usize;
150 let mut buf = vec![0u8; total_len];
151 self.stream.read_exact(&mut buf).await?;
152 if buf.len() >= 24 {
155 let pad = (buf.len() - 24) % 16;
156 buf.truncate(buf.len() - pad);
157 }
158 Ok(buf)
159 }
160
161 pub fn into_inner(self) -> TcpStream {
162 self.stream
163 }
164}
165
166pub struct FullTransport {
180 stream: TcpStream,
181 send_seqno: u32,
182 recv_seqno: u32,
183}
184
185impl FullTransport {
186 pub async fn connect(addr: &str) -> Result<Self, ConnectError> {
187 let stream = TcpStream::connect(addr).await?;
188 Ok(Self {
189 stream,
190 send_seqno: 0,
191 recv_seqno: 0,
192 })
193 }
194
195 pub fn from_stream(stream: TcpStream) -> Self {
196 Self {
197 stream,
198 send_seqno: 0,
199 recv_seqno: 0,
200 }
201 }
202
203 pub async fn send(&mut self, data: &[u8]) -> Result<(), ConnectError> {
205 let total_len = (data.len() + 12) as u32; let seq = self.send_seqno;
207 self.send_seqno = self.send_seqno.wrapping_add(1);
208
209 let mut packet = Vec::with_capacity(total_len as usize);
210 packet.extend_from_slice(&total_len.to_le_bytes());
211 packet.extend_from_slice(&seq.to_le_bytes());
212 packet.extend_from_slice(data);
213
214 let crc = crate::crc32_ieee(&packet);
215 packet.extend_from_slice(&crc.to_le_bytes());
216
217 self.stream.write_all(&packet).await?;
218 Ok(())
219 }
220
221 pub async fn recv(&mut self) -> Result<Vec<u8>, ConnectError> {
223 let mut len_buf = [0u8; 4];
224 self.stream.read_exact(&mut len_buf).await?;
225 let raw = i32::from_le_bytes(len_buf);
227 if raw < 0 {
228 return Err(ConnectError::TransportCode(raw));
229 }
230 let total_len = raw as usize;
231 if total_len < 12 {
232 return Err(ConnectError::Other(
233 "Full transport: packet too short".into(),
234 ));
235 }
236 let mut rest = vec![0u8; total_len - 4];
237 self.stream.read_exact(&mut rest).await?;
238
239 let (body, crc_bytes) = rest.split_at(rest.len() - 4);
241 let expected_crc = u32::from_le_bytes(crc_bytes.try_into().unwrap());
242 let mut check_input = len_buf.to_vec();
243 check_input.extend_from_slice(body);
244 let actual_crc = crate::crc32_ieee(&check_input);
245 if actual_crc != expected_crc {
246 return Err(ConnectError::Other(format!(
247 "Full transport: CRC mismatch (got {actual_crc:#010x}, expected {expected_crc:#010x})"
248 )));
249 }
250
251 let recv_seq = u32::from_le_bytes(body[..4].try_into().unwrap());
253 if recv_seq != self.recv_seqno {
254 return Err(ConnectError::Other(format!(
255 "Full transport: seq_no mismatch (got {recv_seq}, expected {})",
256 self.recv_seqno
257 )));
258 }
259 self.recv_seqno = self.recv_seqno.wrapping_add(1);
260
261 Ok(body[4..].to_vec())
262 }
263
264 pub fn into_inner(self) -> TcpStream {
265 self.stream
266 }
267}