rama_haproxy/protocol/v2/
mod.rs

1//! Version 2 of the HAProxy protocol (binary version).
2//!
3//! See <https://haproxy.org/download/1.8/doc/proxy-protocol.txt>
4
5mod builder;
6mod error;
7mod model;
8
9pub use crate::protocol::ip::{IPv4, IPv6};
10pub use builder::{Builder, WriteToHeader, Writer};
11pub use error::ParseError;
12pub use model::{
13    AddressFamily, Addresses, Command, Header, PROTOCOL_PREFIX, Protocol, Type, TypeLengthValue,
14    TypeLengthValues, Unix, Version,
15};
16use model::{MINIMUM_LENGTH, MINIMUM_TLV_LENGTH};
17use std::borrow::Cow;
18use std::net::{Ipv4Addr, Ipv6Addr};
19
20/// Masks the right 4-bits so only the left 4-bits are present.
21const LEFT_MASK: u8 = 0xF0;
22/// Masks the left 4-bits so only the right 4-bits are present.
23const RIGHT_MASK: u8 = 0x0F;
24/// The index of the version-command byte.
25const VERSION_COMMAND: usize = PROTOCOL_PREFIX.len();
26/// The index of the address family-protocol byte.
27const ADDRESS_FAMILY_PROTOCOL: usize = VERSION_COMMAND + 1;
28/// The index of the start of the big-endian u16 length.
29const LENGTH: usize = ADDRESS_FAMILY_PROTOCOL + 1;
30
31/// Parses the addresses from the header payload.
32fn parse_addresses(address_family: AddressFamily, bytes: &[u8]) -> Addresses {
33    match address_family {
34        AddressFamily::Unspecified => Addresses::Unspecified,
35        AddressFamily::IPv4 => {
36            let source_address = Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3]);
37            let destination_address = Ipv4Addr::new(bytes[4], bytes[5], bytes[6], bytes[7]);
38            let source_port = u16::from_be_bytes([bytes[8], bytes[9]]);
39            let destination_port = u16::from_be_bytes([bytes[10], bytes[11]]);
40
41            Addresses::IPv4(IPv4 {
42                source_address,
43                destination_address,
44                source_port,
45                destination_port,
46            })
47        }
48        AddressFamily::IPv6 => {
49            let mut address = [0; 16];
50
51            address[..].copy_from_slice(&bytes[..16]);
52            let source_address = Ipv6Addr::from(address);
53
54            address[..].copy_from_slice(&bytes[16..32]);
55            let destination_address = Ipv6Addr::from(address);
56
57            let source_port = u16::from_be_bytes([bytes[32], bytes[33]]);
58            let destination_port = u16::from_be_bytes([bytes[34], bytes[35]]);
59
60            Addresses::IPv6(IPv6 {
61                source_address,
62                destination_address,
63                source_port,
64                destination_port,
65            })
66        }
67        AddressFamily::Unix => {
68            let mut source = [0; 108];
69            let mut destination = [0; 108];
70
71            source[..].copy_from_slice(&bytes[..108]);
72            destination[..].copy_from_slice(&bytes[108..]);
73
74            Addresses::Unix(Unix {
75                source,
76                destination,
77            })
78        }
79    }
80}
81
82impl<'a> TryFrom<&'a [u8]> for Header<'a> {
83    type Error = ParseError;
84
85    fn try_from(input: &'a [u8]) -> Result<Self, Self::Error> {
86        if input.len() < PROTOCOL_PREFIX.len() {
87            if PROTOCOL_PREFIX.starts_with(input) {
88                return Err(ParseError::Incomplete(input.len()));
89            } else {
90                return Err(ParseError::Prefix);
91            }
92        }
93
94        if &input[..VERSION_COMMAND] != PROTOCOL_PREFIX {
95            return Err(ParseError::Prefix);
96        }
97
98        if input.len() < MINIMUM_LENGTH {
99            return Err(ParseError::Incomplete(input.len()));
100        }
101
102        let version = match input[VERSION_COMMAND] & LEFT_MASK {
103            0x20 => Version::Two,
104            v => return Err(ParseError::Version(v)),
105        };
106        let command = match input[VERSION_COMMAND] & RIGHT_MASK {
107            0x00 => Command::Local,
108            0x01 => Command::Proxy,
109            c => return Err(ParseError::Command(c)),
110        };
111
112        let address_family = match input[ADDRESS_FAMILY_PROTOCOL] & LEFT_MASK {
113            0x00 => AddressFamily::Unspecified,
114            0x10 => AddressFamily::IPv4,
115            0x20 => AddressFamily::IPv6,
116            0x30 => AddressFamily::Unix,
117            a => return Err(ParseError::AddressFamily(a)),
118        };
119        let protocol = match input[ADDRESS_FAMILY_PROTOCOL] & RIGHT_MASK {
120            0x00 => Protocol::Unspecified,
121            0x01 => Protocol::Stream,
122            0x02 => Protocol::Datagram,
123            p => return Err(ParseError::Protocol(p)),
124        };
125
126        let length = u16::from_be_bytes([input[LENGTH], input[LENGTH + 1]]) as usize;
127        let address_family_bytes = address_family.byte_length().unwrap_or_default();
128
129        if length < address_family_bytes {
130            return Err(ParseError::InvalidAddresses(length, address_family_bytes));
131        }
132
133        let full_length = MINIMUM_LENGTH + length;
134
135        if input.len() < full_length {
136            return Err(ParseError::Partial(input.len() - MINIMUM_LENGTH, length));
137        }
138
139        let header = &input[..full_length];
140        let addresses = parse_addresses(
141            address_family,
142            &header[MINIMUM_LENGTH..MINIMUM_LENGTH + address_family_bytes],
143        );
144
145        Ok(Header {
146            header: Cow::Borrowed(header),
147            version,
148            command,
149            protocol,
150            addresses,
151        })
152    }
153}
154
155#[cfg(test)]
156mod tests {
157    use super::*;
158    use model::{Type, TypeLengthValue};
159
160    #[test]
161    fn no_tlvs() {
162        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
163
164        input.extend_from_slice(PROTOCOL_PREFIX);
165        input.push(0x21);
166        input.push(0x11);
167        input.extend([0, 12]);
168        input.extend([127, 0, 0, 1]);
169        input.extend([127, 0, 0, 2]);
170        input.extend([0, 80]);
171        input.extend([1, 187]);
172
173        let expected = Header {
174            header: Cow::Borrowed(input.as_slice()),
175            version: Version::Two,
176            command: Command::Proxy,
177            protocol: Protocol::Stream,
178            addresses: IPv4::new([127, 0, 0, 1], [127, 0, 0, 2], 80, 443).into(),
179        };
180        let actual = Header::try_from(input.as_slice()).unwrap();
181
182        assert_eq!(actual, expected);
183        assert!(actual.tlvs().next().is_none());
184        assert_eq!(actual.length(), 12);
185        assert_eq!(actual.address_family(), AddressFamily::IPv4);
186        assert_eq!(
187            actual.address_bytes(),
188            &[127, 0, 0, 1, 127, 0, 0, 2, 0, 80, 1, 187]
189        );
190        assert!(actual.tlv_bytes().is_empty());
191        assert_eq!(actual.as_bytes(), input.as_slice());
192    }
193
194    #[test]
195    fn no_tlvs_unspec() {
196        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
197
198        input.extend_from_slice(PROTOCOL_PREFIX);
199        input.push(0x21);
200        input.push(0x00);
201        input.extend([0, 12]);
202        input.extend([127, 0, 0, 1]);
203        input.extend([127, 0, 0, 2]);
204        input.extend([0, 80]);
205        input.extend([1, 187]);
206
207        let expected = Header {
208            header: input.as_slice().into(),
209            version: Version::Two,
210            command: Command::Proxy,
211            protocol: Protocol::Unspecified,
212            addresses: Addresses::Unspecified,
213        };
214        let actual = Header::try_from(input.as_slice()).unwrap();
215
216        assert_eq!(actual, expected);
217        assert!(actual.tlvs().next().is_none());
218        assert_eq!(actual.length(), 12);
219        assert_eq!(actual.address_family(), AddressFamily::Unspecified);
220        assert_eq!(
221            actual.address_bytes(),
222            &[127, 0, 0, 1, 127, 0, 0, 2, 0, 80, 1, 187]
223        );
224        assert!(actual.tlv_bytes().is_empty());
225        assert_eq!(actual.as_bytes(), input.as_slice());
226    }
227
228    #[test]
229    fn no_tlvs_unspec_stream() {
230        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
231
232        input.extend_from_slice(PROTOCOL_PREFIX);
233        input.push(0x21);
234        input.push(0x01);
235        input.extend([0, 8]);
236        input.extend([127, 0, 0, 1]);
237        input.extend([127, 0, 0, 2]);
238
239        let expected = Header {
240            header: Cow::Borrowed(input.as_slice()),
241            version: Version::Two,
242            command: Command::Proxy,
243            protocol: Protocol::Stream,
244            addresses: Addresses::Unspecified,
245        };
246        let actual = Header::try_from(input.as_slice()).unwrap();
247
248        assert_eq!(actual, expected);
249        assert!(actual.tlvs().next().is_none());
250        assert_eq!(actual.length(), 8);
251        assert_eq!(actual.address_family(), AddressFamily::Unspecified);
252        assert_eq!(actual.address_bytes(), &[127, 0, 0, 1, 127, 0, 0, 2]);
253        assert!(actual.tlv_bytes().is_empty());
254        assert_eq!(actual.as_bytes(), input.as_slice());
255    }
256
257    #[test]
258    fn no_tlvs_unspec_ipv4() {
259        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
260
261        input.extend_from_slice(PROTOCOL_PREFIX);
262        input.push(0x21);
263        input.push(0x10);
264        input.extend([0, 8]);
265        input.extend([127, 0, 0, 1]);
266        input.extend([127, 0, 0, 2]);
267
268        let actual = Header::try_from(input.as_slice()).unwrap_err();
269
270        assert_eq!(actual, ParseError::InvalidAddresses(8, 12));
271    }
272
273    #[test]
274    fn invalid_version() {
275        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
276
277        input.extend_from_slice(PROTOCOL_PREFIX);
278        input.push(0x11);
279        input.push(0x11);
280        input.extend([0, 12]);
281        input.extend([127, 0, 0, 1]);
282        input.extend([127, 0, 0, 2]);
283        input.extend([0, 80]);
284        input.extend([1, 187]);
285
286        let actual = Header::try_from(input.as_slice()).unwrap_err();
287
288        assert_eq!(actual, ParseError::Version(0x10));
289    }
290
291    #[test]
292    fn invalid_address_family() {
293        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
294
295        input.extend_from_slice(PROTOCOL_PREFIX);
296        input.push(0x21);
297        input.push(0x51);
298        input.extend([0, 12]);
299        input.extend([127, 0, 0, 1]);
300        input.extend([127, 0, 0, 2]);
301        input.extend([0, 80]);
302        input.extend([1, 187]);
303
304        let actual = Header::try_from(input.as_slice()).unwrap_err();
305
306        assert_eq!(actual, ParseError::AddressFamily(0x50));
307    }
308
309    #[test]
310    fn invalid_command() {
311        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
312
313        input.extend_from_slice(PROTOCOL_PREFIX);
314        input.push(0x23);
315        input.push(0x11);
316        input.extend([0, 12]);
317        input.extend([127, 0, 0, 1]);
318        input.extend([127, 0, 0, 2]);
319        input.extend([0, 80]);
320        input.extend([1, 187]);
321
322        let actual = Header::try_from(input.as_slice()).unwrap_err();
323
324        assert_eq!(actual, ParseError::Command(0x03));
325    }
326
327    #[test]
328    fn invalid_protocol() {
329        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
330
331        input.extend_from_slice(PROTOCOL_PREFIX);
332        input.push(0x20);
333        input.push(0x17);
334        input.extend([0, 12]);
335        input.extend([127, 0, 0, 1]);
336        input.extend([127, 0, 0, 2]);
337        input.extend([0, 80]);
338        input.extend([1, 187]);
339
340        let actual = Header::try_from(input.as_slice()).unwrap_err();
341
342        assert_eq!(actual, ParseError::Protocol(0x07));
343    }
344
345    #[test]
346    fn proxy_with_extra() {
347        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
348
349        input.extend_from_slice(PROTOCOL_PREFIX);
350        input.push(0x21);
351        input.push(0x11);
352        input.extend([0, 12]);
353        input.extend([127, 0, 0, 1]);
354        input.extend([127, 0, 0, 2]);
355        input.extend([0, 80]);
356        input.extend([1, 187]);
357        input.extend([42]);
358
359        let header = &input[..input.len() - 1];
360        let expected = Header {
361            header: header.into(),
362            version: Version::Two,
363            command: Command::Proxy,
364            protocol: Protocol::Stream,
365            addresses: IPv4::new([127, 0, 0, 1], [127, 0, 0, 2], 80, 443).into(),
366        };
367        let actual = Header::try_from(input.as_slice()).unwrap();
368
369        assert_eq!(actual, expected);
370        assert!(actual.tlvs().next().is_none());
371        assert_eq!(actual.length(), 12);
372        assert_eq!(actual.address_family(), AddressFamily::IPv4);
373        assert_eq!(
374            actual.address_bytes(),
375            &[127, 0, 0, 1, 127, 0, 0, 2, 0, 80, 1, 187]
376        );
377        assert!(actual.tlv_bytes().is_empty());
378        assert_eq!(actual.as_bytes(), header);
379    }
380
381    #[test]
382    fn with_tlvs() {
383        let source_address = [
384            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
385            0xFF, 0xF2,
386        ];
387        let destination_address = [
388            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
389            0xFF, 0xF1,
390        ];
391        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
392
393        input.extend_from_slice(PROTOCOL_PREFIX);
394        input.push(0x21);
395        input.push(0x21);
396        input.extend([0, 45]);
397        input.extend(source_address);
398        input.extend(destination_address);
399        input.extend([0, 80]);
400        input.extend([1, 187]);
401        input.extend([1, 0, 1, 5]);
402        input.extend([3, 0, 2, 5, 5]);
403
404        let expected = Header {
405            header: input.as_slice().into(),
406            version: Version::Two,
407            command: Command::Proxy,
408            protocol: Protocol::Stream,
409            addresses: IPv6::new(source_address, destination_address, 80, 443).into(),
410        };
411        let expected_tlvs = vec![
412            Ok(TypeLengthValue::new(Type::ALPN, &[5])),
413            Ok(TypeLengthValue::new(Type::CRC32C, &[5, 5])),
414        ];
415
416        let actual = Header::try_from(input.as_slice()).unwrap();
417        let actual_tlvs: Vec<Result<TypeLengthValue<'_>, ParseError>> = actual.tlvs().collect();
418
419        assert_eq!(actual, expected);
420        assert_eq!(actual_tlvs, expected_tlvs);
421        assert_eq!(actual.length(), 45);
422        assert_eq!(actual.address_family(), AddressFamily::IPv6);
423        assert_eq!(
424            actual.address_bytes(),
425            &[
426                0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
427                0xFF, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
428                0xFF, 0xFF, 0xFF, 0xF1, 0, 80, 1, 187
429            ]
430        );
431        assert_eq!(actual.tlv_bytes(), &[1, 0, 1, 5, 3, 0, 2, 5, 5]);
432        assert_eq!(actual.as_bytes(), input.as_slice());
433    }
434
435    #[test]
436    fn tlvs_with_extra() {
437        let source_address = [
438            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
439            0xFF, 0xFF,
440        ];
441        let destination_address = [
442            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
443            0xFF, 0xF1,
444        ];
445        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
446
447        input.extend_from_slice(PROTOCOL_PREFIX);
448        input.push(0x21);
449        input.push(0x21);
450        input.extend([0, 45]);
451        input.extend(source_address);
452        input.extend(destination_address);
453        input.extend([0, 80]);
454        input.extend([1, 187]);
455        input.extend([1, 0, 1, 5]);
456        input.extend([4, 0, 2, 5, 5]);
457        input.extend([2, 0, 2, 5, 5]);
458
459        let header = &input[..input.len() - 5];
460        let expected = Header {
461            header: header.into(),
462            version: Version::Two,
463            command: Command::Proxy,
464            protocol: Protocol::Stream,
465            addresses: IPv6::new(source_address, destination_address, 80, 443).into(),
466        };
467        let expected_tlvs = vec![
468            Ok(TypeLengthValue::new(Type::ALPN, &[5])),
469            Ok(TypeLengthValue::new(Type::NoOp, &[5, 5])),
470        ];
471
472        let actual = Header::try_from(input.as_slice()).unwrap();
473        let actual_tlvs: Vec<Result<TypeLengthValue<'_>, ParseError>> = actual.tlvs().collect();
474
475        assert_eq!(actual, expected);
476        assert_eq!(actual_tlvs, expected_tlvs);
477        assert_eq!(actual.length(), 45);
478        assert_eq!(actual.address_family(), AddressFamily::IPv6);
479        assert_eq!(
480            actual.address_bytes(),
481            &[
482                0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
483                0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
484                0xFF, 0xFF, 0xFF, 0xF1, 0, 80, 1, 187
485            ]
486        );
487        assert_eq!(actual.tlv_bytes(), &[1, 0, 1, 5, 4, 0, 2, 5, 5]);
488        assert_eq!(actual.as_bytes(), header);
489    }
490
491    #[test]
492    fn unix_tlvs_with_extra() {
493        let source_address = [0xFFu8; 108];
494        let destination_address = [0xAAu8; 108];
495        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
496
497        input.extend_from_slice(PROTOCOL_PREFIX);
498        input.push(0x21);
499        input.push(0x30);
500        input.extend([0, 225]);
501        input.extend(source_address);
502        input.extend(destination_address);
503        input.extend([2, 0, 2, 5, 5]);
504        input.extend([48, 0, 1, 5]);
505        input.extend([1, 0, 2, 5, 5]);
506
507        let header = &input[..input.len() - 5];
508        let expected = Header {
509            header: header.into(),
510            version: Version::Two,
511            command: Command::Proxy,
512            protocol: Protocol::Unspecified,
513            addresses: Unix::new(source_address, destination_address).into(),
514        };
515        let mut expected_address_bytes =
516            Vec::with_capacity(source_address.len() + destination_address.len());
517        expected_address_bytes.extend(source_address);
518        expected_address_bytes.extend(destination_address);
519
520        let expected_tlvs = vec![
521            Ok(TypeLengthValue::new(Type::Authority, &[5, 5])),
522            Ok(TypeLengthValue::new(Type::NetworkNamespace, &[5])),
523        ];
524
525        let actual = Header::try_from(input.as_slice()).unwrap();
526        let actual_tlvs: Vec<Result<TypeLengthValue<'_>, ParseError>> = actual.tlvs().collect();
527
528        assert_eq!(actual, expected);
529        assert_eq!(actual_tlvs, expected_tlvs);
530        assert_eq!(actual.length(), 225);
531        assert_eq!(actual.address_family(), AddressFamily::Unix);
532        assert_eq!(actual.address_bytes(), expected_address_bytes.as_slice());
533        assert_eq!(actual.tlv_bytes(), &[2, 0, 2, 5, 5, 48, 0, 1, 5]);
534        assert_eq!(actual.as_bytes(), header);
535    }
536
537    #[test]
538    fn with_tlvs_without_ports() {
539        let source_address = [
540            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
541            0xFF, 0xFF,
542        ];
543        let destination_address = [
544            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
545            0xFF, 0xF1,
546        ];
547        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
548
549        input.extend_from_slice(PROTOCOL_PREFIX);
550        input.push(0x21);
551        input.push(0x20);
552        input.extend([0, 41]);
553        input.extend(source_address);
554        input.extend(destination_address);
555        input.extend([1, 0, 1, 5]);
556        input.extend([3, 0, 2, 5, 5]);
557
558        let expected = Header {
559            header: input.as_slice().into(),
560            version: Version::Two,
561            command: Command::Proxy,
562            protocol: Protocol::Unspecified,
563            addresses: IPv6::new(source_address, destination_address, 256, 261).into(),
564        };
565        let expected_tlvs = vec![Ok(TypeLengthValue::new(Type::CRC32C, &[5, 5]))];
566
567        let actual = Header::try_from(input.as_slice()).unwrap();
568        let actual_tlvs: Vec<Result<TypeLengthValue<'_>, ParseError>> = actual.tlvs().collect();
569
570        assert_eq!(actual, expected);
571        assert_eq!(actual_tlvs, expected_tlvs);
572        assert_eq!(actual.length(), 41);
573        assert_eq!(actual.address_family(), AddressFamily::IPv6);
574        assert_eq!(
575            actual.address_bytes(),
576            &[
577                0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
578                0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
579                0xFF, 0xFF, 0xFF, 0xF1, 1, 0, 1, 5
580            ]
581        );
582        assert_eq!(actual.tlv_bytes(), &[3, 0, 2, 5, 5]);
583        assert_eq!(actual.as_bytes(), input.as_slice());
584    }
585
586    #[test]
587    fn partial_tlv() {
588        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
589
590        input.extend_from_slice(PROTOCOL_PREFIX);
591        input.push(0x21);
592        input.push(0x11);
593        input.extend([0, 15]);
594        input.extend([127, 0, 0, 1]);
595        input.extend([127, 0, 0, 2]);
596        input.extend([0, 80]);
597        input.extend([1, 187]);
598        input.extend([1, 0, 1]);
599
600        let header = Header::try_from(input.as_slice()).unwrap();
601        let mut tlvs = header.tlvs();
602
603        assert_eq!(tlvs.next().unwrap(), Err(ParseError::InvalidTLV(1, 1)));
604        assert_eq!(tlvs.next(), None);
605    }
606
607    #[test]
608    fn missing_tlvs() {
609        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
610
611        input.extend_from_slice(PROTOCOL_PREFIX);
612        input.push(0x21);
613        input.push(0x11);
614        input.extend([0, 17]);
615        input.extend([127, 0, 0, 1]);
616        input.extend([127, 0, 0, 2]);
617        input.extend([0, 80]);
618        input.extend([1, 187]);
619        input.extend([1, 0, 1]);
620
621        assert_eq!(
622            Header::try_from(&input[..]).unwrap_err(),
623            ParseError::Partial(15, 17)
624        );
625    }
626
627    #[test]
628    fn partial_address() {
629        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
630
631        input.extend_from_slice(PROTOCOL_PREFIX);
632        input.push(0x21);
633        input.push(0x11);
634        input.extend([0, 12]);
635        input.extend([127, 0, 0, 1]);
636        input.extend([127, 0, 0, 2]);
637        input.extend([0, 80]);
638
639        assert_eq!(
640            Header::try_from(&input[..]).unwrap_err(),
641            ParseError::Partial(10, 12)
642        );
643    }
644
645    #[test]
646    fn no_address() {
647        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
648
649        input.extend_from_slice(PROTOCOL_PREFIX);
650        input.push(0x20);
651        input.push(0x02);
652        input.extend([0, 0]);
653        input.extend([0, 80]);
654
655        let header = &input[..input.len() - 2];
656        let expected = Header {
657            header: header.into(),
658            version: Version::Two,
659            command: Command::Local,
660            protocol: Protocol::Datagram,
661            addresses: Addresses::Unspecified,
662        };
663
664        let actual = Header::try_from(input.as_slice()).unwrap();
665        let actual_tlvs: Vec<Result<TypeLengthValue<'_>, ParseError>> = actual.tlvs().collect();
666
667        assert_eq!(actual, expected);
668        assert_eq!(actual_tlvs, vec![]);
669        assert_eq!(actual.length(), 0);
670        assert_eq!(actual.address_family(), AddressFamily::Unspecified);
671        assert!(actual.address_bytes().is_empty());
672        assert!(actual.tlv_bytes().is_empty());
673        assert_eq!(actual.as_bytes(), header);
674    }
675
676    #[test]
677    fn unspecified_address_family() {
678        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
679
680        input.extend_from_slice(PROTOCOL_PREFIX);
681        input.push(0x20);
682        input.push(0x02);
683        input.extend([0, 12]);
684        input.extend([127, 0, 0, 1]);
685        input.extend([127, 0, 0, 2]);
686        input.extend([0, 80]);
687        input.extend([0xbb, 1]);
688
689        let expected = Header {
690            header: input.as_slice().into(),
691            version: Version::Two,
692            command: Command::Local,
693            protocol: Protocol::Datagram,
694            addresses: Addresses::Unspecified,
695        };
696        let actual = Header::try_from(input.as_slice()).unwrap();
697
698        assert_eq!(actual, expected);
699        assert!(actual.tlvs().next().is_none());
700        assert_eq!(actual.length(), 12);
701        assert_eq!(actual.address_family(), AddressFamily::Unspecified);
702        assert_eq!(
703            actual.address_bytes(),
704            &[127, 0, 0, 1, 127, 0, 0, 2, 0, 80, 0xbb, 1]
705        );
706        assert!(actual.tlv_bytes().is_empty());
707        assert_eq!(actual.as_bytes(), input.as_slice());
708    }
709
710    #[test]
711    fn missing_address() {
712        let mut input: Vec<u8> = Vec::with_capacity(PROTOCOL_PREFIX.len());
713
714        input.extend_from_slice(PROTOCOL_PREFIX);
715        input.push(0x20);
716        input.push(0x22);
717        input.extend([0, 0]);
718        input.extend([0, 80]);
719
720        assert_eq!(
721            Header::try_from(&input[..]).unwrap_err(),
722            ParseError::InvalidAddresses(0, AddressFamily::IPv6.byte_length().unwrap_or_default())
723        );
724    }
725
726    #[test]
727    fn not_prefixed() {
728        assert_eq!(
729            Header::try_from(b"\r\n\r\n\x01\r\nQUIT\n".as_slice()).unwrap_err(),
730            ParseError::Prefix
731        );
732        assert_eq!(
733            Header::try_from(b"\r\n\r\n\x01".as_slice()).unwrap_err(),
734            ParseError::Prefix
735        );
736    }
737
738    #[test]
739    fn incomplete() {
740        assert_eq!(
741            Header::try_from([0x0D, 0x0A, 0x0D, 0x0A, 0x00].as_slice()).unwrap_err(),
742            ParseError::Incomplete(5)
743        );
744        assert_eq!(
745            Header::try_from(PROTOCOL_PREFIX).unwrap_err(),
746            ParseError::Incomplete(PROTOCOL_PREFIX.len())
747        );
748    }
749}