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