diff --git a/easytier/src/gateway/quic_proxy.rs b/easytier/src/gateway/quic_proxy.rs index 7e0767aa..9414458e 100644 --- a/easytier/src/gateway/quic_proxy.rs +++ b/easytier/src/gateway/quic_proxy.rs @@ -133,7 +133,7 @@ impl AsyncUdpSocket for QuicSocket { unsafe { copy_nonoverlapping( chunk.as_ptr(), - payload.as_mut_ptr().add(self.margins.header), + payload.chunk_mut().as_mut_ptr().add(self.margins.header), len, ); payload.advance_mut(len + self.margins.len()); @@ -1383,4 +1383,56 @@ mod tests { Ok(()) } + + #[tokio::test] + async fn test_gso() { + let margins = PacketMargins { + header: 20, + trailer: 25, + }; + let (tx, rx) = channel(10); + + let socket = QuicSocket { + addr: "127.0.0.1:0".parse().unwrap(), + rx: AtomicRefCell::new(rx), + tx, + margins, + }; + + let total_len = 3000; + let segment_size = 1000; + let mut contents = Vec::with_capacity(total_len); + + contents.extend(vec![1u8; 1000]); + contents.extend(vec![2u8; 1000]); + contents.extend(vec![3u8; 1000]); + + let transmit = Transmit { + destination: "127.0.0.1:8000".parse().unwrap(), + ecn: None, + contents: &contents, + segment_size: Some(segment_size), + src_ip: None, + }; + + socket.try_send(&transmit).unwrap(); + + let mut rx = socket.rx.into_inner(); + let packet = rx.recv().await.unwrap(); + + let actual_segment_size = segment_size + margins.len(); + let payload = packet.payload; + + let chunk1_start = margins.header; + let chunk1_data = &payload[chunk1_start..chunk1_start + segment_size]; + assert_eq!(chunk1_data[0], 1u8, "Chunk 1 corrupted"); + + let chunk2_start = actual_segment_size + margins.header; + let chunk2_data = &payload[chunk2_start..chunk2_start + segment_size]; + assert_eq!(chunk2_data[0], 2u8, "Chunk 2 corrupted"); + + let chunk3_start = actual_segment_size * 2 + margins.header; + let chunk3_data = &payload[chunk3_start..chunk3_start + segment_size]; + assert_eq!(chunk3_data[0], 3u8, "Chunk 3 corrupted"); + } }