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