Skip to main content

rama_haproxy/protocol/v2/
mod.rs

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