1#[cfg(any(feature = "feat-codec-decode", feature = "feat-codec-encode"))]
4pub mod codec;
5pub mod model;
6
7#[cfg(any(feature = "feat-codec-decode", feature = "feat-codec-encode"))]
8pub use codec::*;
9pub use model::{AddressPair, Command, ExtensionRef, ExtensionType, Protocol, HEADER_SIZE};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct Header {
17 command: Command,
19
20 protocol: Protocol,
22
23 address_pair: AddressPair,
25}
26
27impl Header {
28 pub const MAGIC: &'static [u8; 12] = b"\r\n\r\n\x00\r\nQUIT\n";
30
31 #[inline]
32 pub const fn new_local() -> Self {
34 Self {
35 command: Command::Local,
36 protocol: Protocol::Unspecified,
37 address_pair: AddressPair::Unspecified,
38 }
39 }
40
41 #[inline]
42 pub const fn new_proxy(protocol: Protocol, address_pair: AddressPair) -> Self {
44 Self {
45 command: Command::Proxy,
46 protocol,
47 address_pair,
48 }
49 }
50
51 #[inline]
52 pub const fn command(&self) -> &Command {
54 &self.command
55 }
56
57 #[inline]
58 pub const fn protocol(&self) -> &Protocol {
60 &self.protocol
61 }
62
63 #[inline]
64 pub const fn address_pair(&self) -> &AddressPair {
66 &self.address_pair
67 }
68
69 #[cfg(feature = "feat-codec-encode")]
70 #[inline]
71 pub fn encode(&self) -> Encoded {
73 HeaderEncoder::encode(self)
74 }
75
76 #[cfg(feature = "feat-codec-decode")]
77 #[inline]
78 pub fn decode<'a>(encoded: &'a [u8]) -> Result<Decoded<'a>, DecodeError> {
80 HeaderDecoder::decode(encoded)
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use alloc::vec;
87
88 use super::*;
89
90 #[test]
91 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
92 fn encode_decode_header_no_extension_local() {
93 let header = Header::new_local();
94
95 _encode_decode_header_no_extension(header);
96 }
97
98 #[test]
99 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
100 fn encode_decode_header_no_extension_proxy_unspec_unspec() {
101 let header = Header::new_proxy(Protocol::Unspecified, AddressPair::Unspecified);
102
103 _encode_decode_header_no_extension(header);
104 }
105
106 #[test]
107 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
108 fn encode_decode_header_no_extension_proxy_stream_unspec() {
109 let header = Header::new_proxy(Protocol::Stream, AddressPair::Unspecified);
110
111 _encode_decode_header_no_extension(header);
112 }
113
114 #[test]
115 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
116 fn encode_decode_header_no_extension_proxy_dgram_unspec() {
117 let header = Header::new_proxy(Protocol::Dgram, AddressPair::Unspecified);
118
119 _encode_decode_header_no_extension(header);
120 }
121
122 #[test]
123 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
124 fn encode_decode_header_no_extension_proxy_unspec_inet() {
125 let header = Header::new_proxy(
126 Protocol::Unspecified,
127 AddressPair::Inet {
128 src_ip: "127.0.0.1".parse().unwrap(),
129 dst_ip: "127.0.0.2".parse().unwrap(),
130 src_port: 8080,
131 dst_port: 80,
132 },
133 );
134
135 _encode_decode_header_no_extension(header);
136 }
137
138 #[test]
139 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
140 fn encode_decode_header_no_extension_proxy_stream_inet() {
141 let header = Header::new_proxy(
142 Protocol::Stream,
143 AddressPair::Inet {
144 src_ip: "127.0.0.1".parse().unwrap(),
145 dst_ip: "127.0.0.2".parse().unwrap(),
146 src_port: 8080,
147 dst_port: 80,
148 },
149 );
150
151 _encode_decode_header_no_extension(header);
152 }
153
154 #[test]
155 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
156 fn encode_decode_header_no_extension_proxy_dgram_inet() {
157 let header = Header::new_proxy(
158 Protocol::Dgram,
159 AddressPair::Inet {
160 src_ip: "127.0.0.1".parse().unwrap(),
161 dst_ip: "127.0.0.2".parse().unwrap(),
162 src_port: 8080,
163 dst_port: 80,
164 },
165 );
166
167 _encode_decode_header_no_extension(header);
168 }
169
170 #[test]
171 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
172 fn encode_decode_header_no_extension_proxy_unspec_inet6() {
173 let header = Header::new_proxy(
174 Protocol::Unspecified,
175 AddressPair::Inet6 {
176 src_ip: "::1".parse().unwrap(),
177 dst_ip: "::2".parse().unwrap(),
178 src_port: 8080,
179 dst_port: 80,
180 },
181 );
182
183 _encode_decode_header_no_extension(header);
184 }
185
186 #[test]
187 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
188 fn encode_decode_header_no_extension_proxy_stream_inet6() {
189 let header = Header::new_proxy(
190 Protocol::Stream,
191 AddressPair::Inet6 {
192 src_ip: "::1".parse().unwrap(),
193 dst_ip: "::2".parse().unwrap(),
194 src_port: 8080,
195 dst_port: 80,
196 },
197 );
198
199 _encode_decode_header_no_extension(header);
200 }
201
202 #[test]
203 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
204 fn encode_decode_header_no_extension_proxy_dgram_inet6() {
205 let header = Header::new_proxy(
206 Protocol::Dgram,
207 AddressPair::Inet6 {
208 src_ip: "::1".parse().unwrap(),
209 dst_ip: "::2".parse().unwrap(),
210 src_port: 8080,
211 dst_port: 80,
212 },
213 );
214
215 _encode_decode_header_no_extension(header);
216 }
217
218 #[test]
219 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
220 fn encode_decode_header_no_extension_proxy_unspec_unix() {
221 let header = Header::new_proxy(
222 Protocol::Unspecified,
223 AddressPair::Unix {
224 src_addr: [b'S'; 108],
225 dst_addr: [b'D'; 108],
226 },
227 );
228
229 _encode_decode_header_no_extension(header);
230 }
231
232 #[test]
233 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
234 fn encode_decode_header_no_extension_proxy_stream_unix() {
235 let header = Header::new_proxy(
236 Protocol::Stream,
237 AddressPair::Unix {
238 src_addr: [b'S'; 108],
239 dst_addr: [b'D'; 108],
240 },
241 );
242
243 _encode_decode_header_no_extension(header);
244 }
245
246 #[test]
247 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
248 fn encode_decode_header_no_extension_proxy_dgram_unix() {
249 let header = Header::new_proxy(
250 Protocol::Dgram,
251 AddressPair::Unix {
252 src_addr: [b'S'; 108],
253 dst_addr: [b'D'; 108],
254 },
255 );
256
257 _encode_decode_header_no_extension(header);
258 }
259
260 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
261 fn _encode_decode_header_no_extension(header: Header) {
262 let encoded = codec::HeaderEncoder::encode(&header).finish().unwrap();
263
264 let decoded = codec::HeaderDecoder::decode(&encoded).unwrap();
265 if let codec::Decoded::Some(codec::DecodedHeader {
266 header: decoded_header,
267 extensions,
268 }) = decoded
269 {
270 assert_eq!(decoded_header, header);
271 let mut extensions_iter = extensions.into_iter();
272 assert!(extensions_iter.next().is_none());
273 } else {
274 panic!("Expected decoded header");
275 }
276 }
277
278 #[test]
280 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
281 fn encode_decode_header_with_extension_local_alpn() {
282 let header = Header::new_local();
283 let alpn_data = b"http/1.1";
284
285 _encode_decode_header_with_extension(
286 header,
287 |encoder| encoder.write_ext_alpn(alpn_data),
288 |mut extensions| {
289 let ext = extensions.next().unwrap().unwrap();
290 assert_eq!(ext.typ().unwrap(), ExtensionType::ALPN);
291 assert_eq!(ext.payload(), alpn_data);
292 assert!(extensions.next().is_none());
293 },
294 );
295 }
296
297 #[test]
298 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
299 fn encode_decode_header_with_extension_proxy_authority() {
300 let header = Header::new_proxy(
301 Protocol::Stream,
302 AddressPair::Inet {
303 src_ip: "127.0.0.1".parse().unwrap(),
304 dst_ip: "127.0.0.2".parse().unwrap(),
305 src_port: 8080,
306 dst_port: 80,
307 },
308 );
309 let authority_data = b"example.com";
310
311 _encode_decode_header_with_extension(
312 header,
313 |encoder| encoder.write_ext_authority(authority_data),
314 |mut extensions| {
315 let ext = extensions.next().unwrap().unwrap();
316 assert_eq!(ext.typ().unwrap(), ExtensionType::Authority);
317 assert_eq!(ext.payload(), authority_data);
318 assert!(extensions.next().is_none());
319 },
320 );
321 }
322
323 #[test]
324 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
325 fn encode_decode_header_with_extension_proxy_unique_id() {
326 let header = Header::new_proxy(
327 Protocol::Stream,
328 AddressPair::Inet6 {
329 src_ip: "::1".parse().unwrap(),
330 dst_ip: "::2".parse().unwrap(),
331 src_port: 8080,
332 dst_port: 80,
333 },
334 );
335 let unique_id = b"unique-connection-id-12345";
336
337 _encode_decode_header_with_extension(
338 header,
339 |encoder| encoder.write_ext_unique_id(unique_id),
340 |mut extensions| {
341 let ext = extensions.next().unwrap().unwrap();
342 assert_eq!(ext.typ().unwrap(), ExtensionType::NetworkNamespace); assert_eq!(ext.payload(), unique_id);
344 assert!(extensions.next().is_none());
345 },
346 );
347 }
348
349 #[test]
350 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
351 fn encode_decode_header_with_extension_proxy_network_namespace() {
352 let header = Header::new_proxy(
353 Protocol::Dgram,
354 AddressPair::Unix {
355 src_addr: [b'S'; 108],
356 dst_addr: [b'D'; 108],
357 },
358 );
359 let netns_data = b"my-namespace";
360
361 _encode_decode_header_with_extension(
362 header,
363 |encoder| encoder.write_ext_network_namespace(netns_data),
364 |mut extensions| {
365 let ext = extensions.next().unwrap().unwrap();
366 assert_eq!(ext.typ().unwrap(), ExtensionType::NetworkNamespace);
367 assert_eq!(ext.payload(), netns_data);
368 assert!(extensions.next().is_none());
369 },
370 );
371 }
372
373 #[test]
374 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
375 fn encode_decode_header_with_extension_proxy_no_op() {
376 let header = Header::new_proxy(
377 Protocol::Stream,
378 AddressPair::Inet {
379 src_ip: "127.0.0.1".parse().unwrap(),
380 dst_ip: "127.0.0.2".parse().unwrap(),
381 src_port: 8080,
382 dst_port: 80,
383 },
384 );
385 let padding_size = 5u16;
386
387 _encode_decode_header_with_extension(
388 header,
389 |encoder| encoder.write_ext_no_op(padding_size),
390 |mut extensions| {
391 let ext = extensions.next().unwrap().unwrap();
392 assert_eq!(ext.typ().unwrap(), ExtensionType::NoOp);
393 assert_eq!(ext.payload().len(), padding_size as usize);
394 assert_eq!(ext.payload(), &vec![0u8; padding_size as usize]);
395 assert!(extensions.next().is_none());
396 },
397 );
398 }
399
400 #[test]
401 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
402 fn encode_decode_header_with_multiple_extensions() {
403 let header = Header::new_proxy(
404 Protocol::Stream,
405 AddressPair::Inet {
406 src_ip: "127.0.0.1".parse().unwrap(),
407 dst_ip: "127.0.0.2".parse().unwrap(),
408 src_port: 8080,
409 dst_port: 80,
410 },
411 );
412 let alpn_data = b"h2";
413 let authority_data = b"test.example.org";
414 let padding_size = 3u16;
415
416 let encoded = codec::HeaderEncoder::encode(&header)
417 .write_ext_alpn(alpn_data)
418 .unwrap()
419 .write_ext_authority(authority_data)
420 .unwrap()
421 .write_ext_no_op(padding_size)
422 .unwrap()
423 .finish()
424 .unwrap();
425
426 let decoded = codec::HeaderDecoder::decode(&encoded).unwrap();
427 if let codec::Decoded::Some(codec::DecodedHeader {
428 header: decoded_header,
429 extensions,
430 }) = decoded
431 {
432 assert_eq!(decoded_header, header);
433
434 let mut extensions_iter = extensions.into_iter();
435
436 let ext1 = extensions_iter.next().unwrap().unwrap();
438 assert_eq!(ext1.typ().unwrap(), ExtensionType::ALPN);
439 assert_eq!(ext1.payload(), alpn_data);
440
441 let ext2 = extensions_iter.next().unwrap().unwrap();
443 assert_eq!(ext2.typ().unwrap(), ExtensionType::Authority);
444 assert_eq!(ext2.payload(), authority_data);
445
446 let ext3 = extensions_iter.next().unwrap().unwrap();
448 assert_eq!(ext3.typ().unwrap(), ExtensionType::NoOp);
449 assert_eq!(ext3.payload().len(), padding_size as usize);
450 assert_eq!(ext3.payload(), &vec![0u8; padding_size as usize]);
451
452 assert!(extensions_iter.next().is_none());
454 } else {
455 panic!("Expected decoded header");
456 }
457 }
458
459 #[test]
460 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
461 fn encode_decode_header_with_custom_extension() {
462 let header = Header::new_local();
463 let custom_type = 0x80u8; let custom_data = b"custom-extension-data";
465
466 let extension = ExtensionRef::new_custom(custom_type, custom_data).unwrap();
467 let encoded = codec::HeaderEncoder::encode(&header)
468 .write_ext_custom(extension)
469 .finish()
470 .unwrap();
471
472 let decoded = codec::HeaderDecoder::decode(&encoded).unwrap();
473 if let codec::Decoded::Some(codec::DecodedHeader {
474 header: decoded_header,
475 extensions,
476 }) = decoded
477 {
478 assert_eq!(decoded_header, header);
479
480 let mut extensions_iter = extensions.into_iter();
481 let ext = extensions_iter.next().unwrap().unwrap();
482 assert_eq!(ext.typ().unwrap_err(), custom_type); assert_eq!(ext.payload(), custom_data);
484 assert!(extensions_iter.next().is_none());
485 } else {
486 panic!("Expected decoded header");
487 }
488 }
489
490 #[test]
491 #[cfg(all(
492 feature = "feat-codec-encode",
493 feature = "feat-codec-decode",
494 feature = "feat-codec-v2-crc32c"
495 ))]
496 fn encode_decode_header_with_crc32c() {
497 let header = Header::new_proxy(
498 Protocol::Stream,
499 AddressPair::Inet {
500 src_ip: "127.0.0.1".parse().unwrap(),
501 dst_ip: "127.0.0.2".parse().unwrap(),
502 src_port: 8080,
503 dst_port: 80,
504 },
505 );
506
507 let encoded = codec::HeaderEncoder::encode(&header).finish_with_crc32c().unwrap();
508
509 let decoded = codec::HeaderDecoder::decode(&encoded).unwrap();
510 if let codec::Decoded::Some(codec::DecodedHeader {
511 header: decoded_header,
512 extensions,
513 }) = decoded
514 {
515 assert_eq!(decoded_header, header);
516
517 let mut extensions_iter = extensions.into_iter();
518 let ext = extensions_iter.next().unwrap().unwrap();
519 assert_eq!(ext.typ().unwrap(), ExtensionType::CRC32C);
520 assert_eq!(ext.payload().len(), 4); assert!(extensions_iter.next().is_none());
522 } else {
523 panic!("Expected decoded header");
524 }
525 }
526
527 #[cfg(all(feature = "feat-codec-encode", feature = "feat-codec-decode"))]
528 fn _encode_decode_header_with_extension<F, V>(header: Header, add_extension: F, verify_extension: V)
529 where
530 F: FnOnce(
531 codec::HeaderEncoder<codec::encode::stage::Finished>,
532 ) -> Result<codec::HeaderEncoder<codec::encode::stage::Finished>, codec::EncodeError>,
533 V: FnOnce(codec::DecodedExtensionsIter<'_>),
534 {
535 let encoded = add_extension(codec::HeaderEncoder::encode(&header))
536 .unwrap()
537 .finish()
538 .unwrap();
539
540 let decoded = codec::HeaderDecoder::decode(&encoded).unwrap();
541 if let codec::Decoded::Some(codec::DecodedHeader {
542 header: decoded_header,
543 extensions,
544 }) = decoded
545 {
546 assert_eq!(decoded_header, header);
547 verify_extension(extensions.into_iter());
548 } else {
549 panic!("Expected decoded header");
550 }
551 }
552
553 #[test]
554 #[cfg(feature = "feat-codec-decode")]
555 fn decode_peek_insufficient_data() {
556 for size in 1..16 {
559 let mut buffer = vec![0u8; size];
560 let magic = b"\r\n\r\n\x00\r\nQUIT\n";
562 let copy_len = size.min(magic.len());
563 buffer[..copy_len].copy_from_slice(&magic[..copy_len]);
564
565 let result = codec::HeaderDecoder::decode(&buffer).unwrap();
566 assert!(matches!(result, codec::Decoded::Partial(_)));
568 }
569
570 let buffer = vec![0u8; 8];
572 let result = codec::HeaderDecoder::decode(&buffer).unwrap();
573 assert!(matches!(result, codec::Decoded::None));
574 }
575
576 #[test]
577 #[cfg(feature = "feat-codec-decode")]
578 fn decode_peek_not_proxy_protocol() {
579 let buffer = vec![0u8; 16];
581 let result = codec::HeaderDecoder::decode(&buffer).unwrap();
582 assert!(matches!(result, codec::Decoded::None));
583
584 let mut buffer = vec![0u8; 16];
586 buffer[0..12].copy_from_slice(b"wrong_magic\x00");
587 let result = codec::HeaderDecoder::decode(&buffer).unwrap();
588 assert!(matches!(result, codec::Decoded::None));
589 }
590
591 #[test]
592 #[cfg(feature = "feat-codec-decode")]
593 fn decode_malformed_data() {
594 let header = Header::new_proxy(
596 Protocol::Stream,
597 AddressPair::Inet {
598 src_ip: "127.0.0.1".parse().unwrap(),
599 dst_ip: "127.0.0.2".parse().unwrap(),
600 src_port: 8080,
601 dst_port: 80,
602 },
603 );
604 let encoded = codec::HeaderEncoder::encode(&header).finish().unwrap();
605
606 let truncated = &encoded[..16]; let result = codec::HeaderDecoder::decode(truncated).unwrap();
609 assert!(matches!(result, codec::Decoded::Partial(_)));
610
611 let partial = &encoded[..20]; let result = codec::HeaderDecoder::decode(partial).unwrap();
614 assert!(matches!(result, codec::Decoded::Partial(_)));
615 }
616
617 #[test]
618 #[cfg(feature = "feat-codec-decode")]
619 fn decode_total_length_overflow() {
620 let mut buffer = vec![0u8; 16];
622 buffer[0..12].copy_from_slice(b"\r\n\r\n\x00\r\nQUIT\n");
623 buffer[12] = 0x21; buffer[13] = 0x11; buffer[14] = 0xFF;
628 buffer[15] = 0xFF;
629
630 let result = codec::HeaderDecoder::decode(&buffer).unwrap();
632 assert!(matches!(result, codec::Decoded::Partial(_)));
633 }
634
635 #[test]
636 #[cfg(feature = "feat-codec-decode")]
637 fn decode_invalid_version_variants() {
638 let mut buffer = vec![0u8; 16];
639 buffer[0..12].copy_from_slice(b"\r\n\r\n\x00\r\nQUIT\n");
640 buffer[13] = 0x11; buffer[14] = 0x00; buffer[15] = 0x00; let invalid_versions = [
646 0x00, 0x10, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
647 ];
648 for &invalid_version in &invalid_versions {
649 buffer[12] = invalid_version | 0x01; let err = codec::HeaderDecoder::decode(&buffer).unwrap_err();
651 assert!(matches!(err, codec::DecodeError::InvalidVersion(v) if v == invalid_version));
652 }
653 }
654
655 #[test]
656 #[cfg(feature = "feat-codec-decode")]
657 fn decode_invalid_command_variants() {
658 let mut buffer = vec![0u8; 16];
659 buffer[0..12].copy_from_slice(b"\r\n\r\n\x00\r\nQUIT\n");
660 buffer[12] = 0x20; buffer[13] = 0x11; buffer[14] = 0x00; buffer[15] = 0x00; let invalid_commands = [
667 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
668 ];
669 for &invalid_command in &invalid_commands {
670 buffer[12] = 0x20 | invalid_command;
671 let err = codec::HeaderDecoder::decode(&buffer).unwrap_err();
672 assert!(matches!(err, codec::DecodeError::InvalidCommand(c) if c == invalid_command));
673 }
674 }
675
676 #[test]
677 #[cfg(feature = "feat-codec-decode")]
678 fn decode_invalid_family_variants() {
679 let mut buffer = vec![0u8; 16];
680 buffer[0..12].copy_from_slice(b"\r\n\r\n\x00\r\nQUIT\n");
681 buffer[12] = 0x21; buffer[14] = 0x00; buffer[15] = 0x00; let invalid_families = [0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0];
687 for &invalid_family in &invalid_families {
688 buffer[13] = invalid_family | 0x01; let err = codec::HeaderDecoder::decode(&buffer).unwrap_err();
690 assert!(matches!(err, codec::DecodeError::InvalidFamily(f) if f == invalid_family));
691 }
692 }
693
694 #[test]
695 #[cfg(feature = "feat-codec-decode")]
696 fn decode_invalid_protocol_variants() {
697 let mut buffer = vec![0u8; 16];
698 buffer[0..12].copy_from_slice(b"\r\n\r\n\x00\r\nQUIT\n");
699 buffer[12] = 0x21; buffer[13] = 0x10; buffer[14] = 0x00; buffer[15] = 0x00; let invalid_protocols = [
706 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
707 ];
708 for &invalid_protocol in &invalid_protocols {
709 buffer[13] = 0x10 | invalid_protocol;
710 let err = codec::HeaderDecoder::decode(&buffer).unwrap_err();
711 assert!(matches!(err, codec::DecodeError::InvalidProtocol(p) if p == invalid_protocol));
712 }
713 }
714
715 #[test]
716 #[cfg(feature = "feat-codec-decode")]
717 fn decode_trailing_data_variants() {
718 let header = Header::new_local();
720 let encoded = codec::HeaderEncoder::encode(&header).finish().unwrap();
721
722 for extra_bytes in 1..=10 {
724 let mut with_trailing = encoded.clone();
725 with_trailing.extend(vec![0xAA; extra_bytes]);
726
727 let err = codec::HeaderDecoder::decode(&with_trailing).unwrap_err();
729 assert!(matches!(err, codec::DecodeError::TrailingData));
730 }
731 }
732
733 #[test]
734 #[cfg(feature = "feat-codec-decode")]
735 fn decode_inet6_malformed() {
736 let mut buffer = vec![0u8; 16];
738 buffer[0..12].copy_from_slice(b"\r\n\r\n\x00\r\nQUIT\n");
739 buffer[12] = 0x21; buffer[13] = 0x21; buffer[14] = 0x00; buffer[15] = 0x24; let mut insufficient_data = buffer.clone();
746 insufficient_data.extend(vec![0u8; 20]); let result = codec::HeaderDecoder::decode(&insufficient_data).unwrap();
749 assert!(matches!(result, codec::Decoded::Partial(_)));
750 }
751
752 #[test]
753 #[cfg(feature = "feat-codec-decode")]
754 fn decode_unix_malformed() {
755 let mut buffer = vec![0u8; 16];
757 buffer[0..12].copy_from_slice(b"\r\n\r\n\x00\r\nQUIT\n");
758 buffer[12] = 0x21; buffer[13] = 0x31; buffer[14] = 0x00; buffer[15] = 0xD8; let mut insufficient_data = buffer.clone();
765 insufficient_data.extend(vec![0u8; 100]); let result = codec::HeaderDecoder::decode(&insufficient_data).unwrap();
768 assert!(matches!(result, codec::Decoded::Partial(_)));
769 }
770
771 #[test]
772 #[cfg(feature = "feat-codec-decode")]
773 fn decode_zero_length_but_with_address_family() {
774 let families_and_protocols = [
776 (0x10, 0x01), (0x20, 0x01), (0x30, 0x01), ];
780
781 for (family, protocol) in families_and_protocols {
782 let mut buffer = vec![0u8; 16];
783 buffer[0..12].copy_from_slice(b"\r\n\r\n\x00\r\nQUIT\n");
784 buffer[12] = 0x21; buffer[13] = family | protocol;
786 buffer[14] = 0x00; buffer[15] = 0x00; let err = codec::HeaderDecoder::decode(&buffer).unwrap_err();
790 assert!(matches!(err, codec::DecodeError::MalformedData));
791 }
792 }
793}