diff --git a/src/stream/tcp.rs b/src/stream/tcp.rs index 28e06b2..4ab00d0 100644 --- a/src/stream/tcp.rs +++ b/src/stream/tcp.rs @@ -247,7 +247,7 @@ impl IpStackTcpStream { let sessions = SESSION_COUNTER.fetch_add(1, std::sync::atomic::Ordering::SeqCst).saturating_add(1); let (seq, ack, state) = { (tcb.get_seq().0, tcb.get_ack().0, tcb.get_state()) }; - let l_info = format!("local {{ seq: {seq}, ack: {ack} }}"); + let l_info = LocalInfo(seq, ack); log::debug!("{tuple} {state:?}: {l_info} session begins, total TCP sessions: {sessions}"); stream.spawn_tasks()?; @@ -330,7 +330,7 @@ impl AsyncRead for IpStackTcpStream { { let mut tcb = self.tcb.lock().unwrap(); let (seq, ack) = (tcb.get_seq().0, tcb.get_ack().0); - let l_info = format!("local {{ seq: {seq}, ack: {ack} }}"); + let l_info = LocalInfo(seq, ack); log::debug!("{network_tuple} {state:?}: [poll_read] {l_info}, session timeout reached, closing forcefully..."); let sender = &self.up_packet_sender; write_packet_to_device(sender, network_tuple, &tcb, None, ACK | RST, None, None)?; @@ -386,8 +386,9 @@ impl AsyncWrite for IpStackTcpStream { if send_window == 0 || is_full { self.write_notify.lock().unwrap().replace(cx.waker().clone()); - let info = format!("current send window: {send_window}, send buffer full: {is_full}"); - log::trace!("{nt} {state:?}: [poll_write] {info}, waiting for the other side to send ACK..."); + log::trace!( + "{nt} {state:?}: [poll_write] current send window: {send_window}, send buffer full: {is_full}, waiting for the other side to send ACK..." + ); return Poll::Pending; } @@ -402,7 +403,7 @@ impl AsyncWrite for IpStackTcpStream { } let (state, seq, ack) = (tcb.get_state(), tcb.get_seq(), tcb.get_ack()); - let l_info = format!("local {{ seq: {seq}, ack: {ack} }}"); + let l_info = LocalInfo(seq, ack); log::trace!("{nt} {state:?}: [poll_write] {l_info} upstream data written to device, len = {payload_len}"); Poll::Ready(Ok(payload_len)) @@ -569,7 +570,7 @@ async fn tcp_main_logic_loop( tcb.increase_ack(); let (seq, ack) = (tcb.get_seq().0, tcb.get_ack().0); - let l_info = format!("local {{ seq: {seq}, ack: {ack} }}"); + let l_info = LocalInfo(seq, ack); log::trace!("{network_tuple} {state:?}: {l_info} session begins"); write_packet_to_device( &up_packet_sender, @@ -763,9 +764,12 @@ async fn tcp_main_logic_loop( let pkt_type = tcb.check_pkt_type(tcp_header, &payload); let (state, seq, ack) = { (tcb.get_state(), tcb.get_seq(), tcb.get_ack()) }; - let (info, len) = (tcp_header_fmt(tcp_header), payload.len()); - let l_info = format!("local {{ seq: {seq}, ack: {ack} }}"); - log::trace!("{network_tuple} {state:?}: {l_info} {info}, {pkt_type:?}, len = {len}"); + let len = payload.len(); + let l_info = LocalInfo(seq, ack); + if log::log_enabled!(log::Level::Trace) { + let info = tcp_header_fmt(tcp_header); + log::trace!("{network_tuple} {state:?}: {l_info} {info}, {pkt_type:?}, len = {len}"); + } if pkt_type == PacketType::Invalid { continue; } @@ -999,7 +1003,7 @@ fn extract_data_n_write_upstream( read_notify: &std::sync::Arc>>, ) -> std::io::Result<()> { let (state, seq, ack) = (tcb.get_state(), tcb.get_seq(), tcb.get_ack()); - let l_info = format!("local {{ seq: {seq}, ack: {ack} }}"); + let l_info = LocalInfo(seq, ack); if state == TcpState::Closed { log::debug!("{network_tuple} {state:?}: {l_info} session closed, exiting \"data extraction task\"..."); return Ok(()); @@ -1030,6 +1034,16 @@ fn extract_data_n_write_upstream( } /// Send a TCP packet to the downstream device, with the specified flags, sequence number, and payload. +/// `local { seq, ack }` for log lines, formatted only when a line is actually emitted: the session +/// loop builds one for every packet, whether or not anything is logged. +struct LocalInfo(S, A); + +impl std::fmt::Display for LocalInfo { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "local {{ seq: {}, ack: {} }}", self.0, self.1) + } +} + /// The returned value is the length of the `payload` sent, it may be shorter than the length of the incoming parameter `payload`. pub(crate) fn write_packet_to_device( up_packet_sender: &PacketSender,