1use crate::prelude::{asserted_short_name, cross_os_fd, ConId, Framer};
45use bytes::{Bytes, BytesMut};
46use byteserde::utils::hex::to_hex_pretty;
47use log::{debug, log_enabled};
48use std::fmt::Display;
49use std::io::{ErrorKind, Read, Write};
50use std::mem::MaybeUninit;
51use std::net::Shutdown;
52use std::{io::Error, net::TcpStream};
53
54const EOF: usize = 0;
55
56#[derive(Debug)]
67pub struct FrameReader<F: Framer, const MAX_MSG_SIZE: usize> {
68 pub(crate) con_id: ConId,
69 pub(crate) stream_reader: TcpStream,
70 buffer: BytesMut,
71 phantom: std::marker::PhantomData<F>,
72}
73impl<F: Framer, const MAX_MSG_SIZE: usize> FrameReader<F, MAX_MSG_SIZE> {
74 pub fn new(con_id: ConId, reader: TcpStream) -> FrameReader<F, MAX_MSG_SIZE> {
79 Self {
80 con_id,
81 stream_reader: reader,
82 buffer: BytesMut::with_capacity(MAX_MSG_SIZE),
83 phantom: std::marker::PhantomData,
84 }
85 }
86
87 #[inline]
92 pub fn read_frame(&mut self) -> Result<Option<Bytes>, Error> {
93 loop {
94 if let Some(bytes) = F::get_frame(&mut self.buffer) {
95 return Ok(Some(bytes));
96 } else {
97 #[allow(clippy::uninit_assumed_init)]
98 let mut buf: [u8; MAX_MSG_SIZE] = unsafe { MaybeUninit::uninit().assume_init() };
99 match self.stream_reader.read(&mut buf) {
100 Ok(EOF) => {
101 self.shutdown(Shutdown::Write, "read_frame EOF");
102 if self.buffer.is_empty() {
103 return Ok(None);
104 } else {
105 let msg = format!(
106 "{} {}::read_frame connection reset by peer, residual buf:\n{}",
107 self.con_id,
108 asserted_short_name!("FrameReader", Self),
109 to_hex_pretty(&self.buffer[..])
110 );
111 return Err(Error::new(std::io::ErrorKind::ConnectionReset, msg));
112 }
113 }
114 Ok(len) => {
115 self.buffer.extend_from_slice(&buf[..len]);
116 continue; }
118 Err(e) => {
119 self.shutdown(Shutdown::Write, "read_frame error");
120 let msg = format!("{} {}::read_frame caused by: [{}] residual buf:\n{}", self.con_id, asserted_short_name!("FrameReader", Self), e, to_hex_pretty(&self.buffer[..]));
121 return Err(Error::new(e.kind(), msg));
122 }
123 }
124 }
125 }
126 }
127 #[inline]
128 fn shutdown(&mut self, how: Shutdown, reason: &str) {
129 match self.stream_reader.shutdown(how) {
130 Ok(_) => {
131 if log_enabled!(log::Level::Debug) {
132 debug!("{}::shutdown how: {:?}, reason: {}", self, how, reason);
133 }
134 }
135 Err(e) if e.kind() == ErrorKind::NotConnected => {
136 if log_enabled!(log::Level::Debug) {
137 debug!("{}::shutdown while disconnected how: {:?}, reason: {}", self, how, reason);
138 }
139 }
140 Err(e) => {
141 panic!("{}::shutdown how: {:?}, reason: {}, caused by: [{}]", self, how, reason, e);
142 }
143 }
144 }
145}
146impl<F: Framer, const MAX_MSG_SIZE: usize> Drop for FrameReader<F, MAX_MSG_SIZE> {
147 fn drop(&mut self) {
151 self.shutdown(Shutdown::Both, "drop")
152 }
153}
154impl<F: Framer, const MAX_MSG_SIZE: usize> Display for FrameReader<F, MAX_MSG_SIZE> {
155 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
156 write!(
157 f,
158 "FrameReader<{}> {{ {}, addr: {}, peer: {}, fd: {} }}",
159 std::any::type_name::<F>().split("::").last().unwrap_or("Unknown"),
160 self.con_id,
161 match self.stream_reader.local_addr() {
162 Ok(_) => "connected",
163 Err(_) => "disconnected",
164 },
165 match self.stream_reader.peer_addr() {
166 Ok(_) => "connected",
167 Err(_) => "disconnected",
168 },
169 cross_os_fd!(&self.stream_reader),
170 )
171 }
172}
173
174#[derive(Debug)]
176pub struct FrameWriter {
177 pub(crate) con_id: ConId,
178 pub(crate) stream_writer: TcpStream,
179}
180impl FrameWriter {
181 pub fn new(con_id: ConId, stream: TcpStream) -> Self {
186 Self { con_id, stream_writer: stream }
187 }
188 #[inline]
193 pub fn write_frame(&mut self, bytes: &[u8]) -> Result<(), Error> {
194 match self.stream_writer.write_all(bytes) {
195 Ok(_) => Ok(()),
196 Err(e) => {
197 self.shutdown(Shutdown::Write, "write_frame error");
198 let msg = format!("{} FrameWriter::write_frame caused by: [{}]", self.con_id, e);
199 Err(Error::new(e.kind(), msg))
200 }
201 }
202 }
203
204 fn shutdown(&mut self, how: Shutdown, reason: &str) {
206 match self.stream_writer.shutdown(how) {
207 Ok(_) => {
208 if log_enabled!(log::Level::Debug) {
209 debug!("{}::shutdown how: {:?}, reason: {}", self, how, reason);
210 }
211 }
212 Err(e) if e.kind() == ErrorKind::NotConnected => {
213 if log_enabled!(log::Level::Debug) {
214 debug!("{}::shutdown while disconnected how: {:?}, reason: {}", self, how, reason);
215 }
216 }
217 Err(e) => {
218 panic!("{}::shutdown how: {:?}, reason: {}, caused by: [{}]", self, how, reason, e);
219 }
220 }
221 }
222}
223impl Drop for FrameWriter {
224 fn drop(&mut self) {
226 self.shutdown(Shutdown::Both, "drop")
227 }
228}
229impl Display for FrameWriter {
230 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
231 write!(
232 f,
233 "FrameWriter {{ {}, addr: {}, peer: {}, fd: {} }}",
234 self.con_id,
235 match self.stream_writer.local_addr() {
236 Ok(_) => "connected",
237 Err(_) => "disconnected",
238 },
239 match self.stream_writer.peer_addr() {
240 Ok(_) => "connected",
241 Err(_) => "disconnected",
242 },
243 cross_os_fd!(&self.stream_writer),
244 )
245 }
246}
247
248type FrameProcessor<F, const MAX_MSG_SIZE: usize> = (FrameReader<F, MAX_MSG_SIZE>, FrameWriter);
249
250pub fn into_split_framer<F: Framer, const MAX_MSG_SIZE: usize>(mut con_id: ConId, stream: TcpStream) -> FrameProcessor<F, MAX_MSG_SIZE> {
259 con_id.set_local(stream.local_addr().unwrap());
260 con_id.set_peer(stream.peer_addr().unwrap());
261 let (reader, writer) = (stream.try_clone().expect("Failed to try_clone TcpStream for FrameReader"), stream);
262 (FrameReader::<F, MAX_MSG_SIZE>::new(con_id.clone(), reader), FrameWriter::new(con_id, writer))
263}
264
265#[cfg(test)]
266mod test {
267
268 use crate::prelude::*;
269 use byteserde::utils::hex::to_hex_pretty;
270 use links_core::{assert_error_kind_on_target_family, fmt_num, prelude::ConId, unittest::setup};
271 use log::{error, info};
272 use rand::Rng;
273 use std::{
274 net::{TcpListener, TcpStream},
275 thread::{self, sleep},
276 time::{Duration, Instant},
277 };
278
279 #[test]
292 fn test_reader() {
293 setup::log::configure_level(log::LevelFilter::Info);
294 const TEST_SEND_FRAME_SIZE: usize = 128;
295 const WRITE_N_TIMES: usize = 100_000;
296 pub type MsgFramer = FixedSizeFramer<TEST_SEND_FRAME_SIZE>;
297
298 let send_frame = setup::data::random_bytes(TEST_SEND_FRAME_SIZE);
299 info!("send_frame: \n{}", to_hex_pretty(send_frame));
300
301 let addr = setup::net::rand_avail_addr_port();
302
303 let svc = thread::Builder::new()
305 .name("Thread-Svc".to_owned())
306 .spawn({
307 move || {
308 let listener = TcpListener::bind(addr).unwrap();
309 let (stream, _) = listener.accept().unwrap();
310 let (mut svc_reader, _svc_writer) = into_split_framer::<MsgFramer, TEST_SEND_FRAME_SIZE>(ConId::svc(Some("unittest"), addr, None), stream);
311 info!("svc: reader: {}", svc_reader);
312 let mut frame_recv_count = 0_usize;
313 loop {
314 let res = svc_reader.read_frame();
315 match res {
316 Ok(frame) => {
317 if let None = frame {
318 info!("svc: read_frame is None, client closed connection");
319 break;
320 } else {
321 frame_recv_count += 1;
322 }
323 }
324 Err(e) => {
325 error!("Svc read_frame error: {}", e.to_string());
326 break;
327 }
328 }
329 }
330 frame_recv_count
331 }
332 })
333 .unwrap();
334
335 sleep(Duration::from_millis(100)); let (mut clt_reader, mut clt_writer) = into_split_framer::<MsgFramer, TEST_SEND_FRAME_SIZE>(ConId::clt(Some("unittest"), None, addr), TcpStream::connect(addr).unwrap());
338
339 info!("clt: {}", clt_writer);
340
341 let mut frame_send_count = 0_usize;
342 let start = Instant::now();
343 for _ in 0..WRITE_N_TIMES {
344 clt_writer.write_frame(send_frame).unwrap();
345 frame_send_count += 1;
346 }
347 let elapsed = start.elapsed();
348
349 if rand::thread_rng().gen_range(1..=2) % 2 == 0 {
351 info!("dropping clt_writer");
352 drop(clt_writer);
353 let opt = clt_reader.read_frame().unwrap();
354 info!("clt_reader.read_frame() opt: {:?}", opt);
355 assert_eq!(opt, None);
356 } else {
357 info!("dropping clt_reader");
358 drop(clt_reader);
359 let err = clt_writer.write_frame(send_frame).unwrap_err();
360 info!("clt_writer.write_frame() err: {}", err);
361 assert_error_kind_on_target_family!(err, std::io::ErrorKind::BrokenPipe);
362 }
363 let frame_recv_count = svc.join().unwrap();
364
365 info!("frame_send_count: {}, frame_recv_count: {}", fmt_num!(frame_send_count), fmt_num!(frame_recv_count));
366 info!("per send elapsed: {:?}, total elapsed: {:?} ", elapsed / WRITE_N_TIMES as u32, elapsed);
367 assert_eq!(frame_send_count, frame_recv_count);
368 assert_eq!(frame_send_count, WRITE_N_TIMES);
369 }
370}