Coverage Report

Created: 2025-11-16 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ppp-2.3.0/src/v2/mod.rs
Line
Count
Source
1
//! Version 2 of the HAProxy protocol (binary version).
2
//!
3
//! See <https://haproxy.org/download/1.8/doc/proxy-protocol.txt>
4
5
mod builder;
6
mod error;
7
mod model;
8
9
pub use crate::ip::{IPv4, IPv6};
10
pub use builder::{Builder, WriteToHeader, Writer};
11
pub use error::ParseError;
12
pub use model::{
13
    AddressFamily, Addresses, Command, Header, Protocol, Type, TypeLengthValue, TypeLengthValues,
14
    Unix, Version, PROTOCOL_PREFIX,
15
};
16
use model::{MINIMUM_LENGTH, MINIMUM_TLV_LENGTH};
17
use std::borrow::Cow;
18
use std::net::{Ipv4Addr, Ipv6Addr};
19
20
/// Masks the right 4-bits so only the left 4-bits are present.
21
const LEFT_MASK: u8 = 0xF0;
22
/// Masks the left 4-bits so only the right 4-bits are present.
23
const RIGHT_MASK: u8 = 0x0F;
24
/// The index of the version-command byte.
25
const VERSION_COMMAND: usize = PROTOCOL_PREFIX.len();
26
/// The index of the address family-protocol byte.
27
const ADDRESS_FAMILY_PROTOCOL: usize = VERSION_COMMAND + 1;
28
/// The index of the start of the big-endian u16 length.
29
const LENGTH: usize = ADDRESS_FAMILY_PROTOCOL + 1;
30
31
/// Parses the addresses from the header payload.
32
0
fn parse_addresses(address_family: AddressFamily, bytes: &[u8]) -> Addresses {
33
0
    match address_family {
34
0
        AddressFamily::Unspecified => Addresses::Unspecified,
35
        AddressFamily::IPv4 => {
36
0
            let source_address = Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3]);
37
0
            let destination_address = Ipv4Addr::new(bytes[4], bytes[5], bytes[6], bytes[7]);
38
0
            let source_port = u16::from_be_bytes([bytes[8], bytes[9]]);
39
0
            let destination_port = u16::from_be_bytes([bytes[10], bytes[11]]);
40
41
0
            Addresses::IPv4(IPv4 {
42
0
                source_address,
43
0
                destination_address,
44
0
                source_port,
45
0
                destination_port,
46
0
            })
47
        }
48
        AddressFamily::IPv6 => {
49
0
            let mut address = [0; 16];
50
51
0
            address[..].copy_from_slice(&bytes[..16]);
52
0
            let source_address = Ipv6Addr::from(address);
53
54
0
            address[..].copy_from_slice(&bytes[16..32]);
55
0
            let destination_address = Ipv6Addr::from(address);
56
57
0
            let source_port = u16::from_be_bytes([bytes[32], bytes[33]]);
58
0
            let destination_port = u16::from_be_bytes([bytes[34], bytes[35]]);
59
60
0
            Addresses::IPv6(IPv6 {
61
0
                source_address,
62
0
                destination_address,
63
0
                source_port,
64
0
                destination_port,
65
0
            })
66
        }
67
        AddressFamily::Unix => {
68
0
            let mut source = [0; 108];
69
0
            let mut destination = [0; 108];
70
71
0
            source[..].copy_from_slice(&bytes[..108]);
72
0
            destination[..].copy_from_slice(&bytes[108..]);
73
74
0
            Addresses::Unix(Unix {
75
0
                source,
76
0
                destination,
77
0
            })
78
        }
79
    }
80
0
}
81
82
impl<'a> TryFrom<&'a [u8]> for Header<'a> {
83
    type Error = ParseError;
84
85
0
    fn try_from(input: &'a [u8]) -> Result<Self, Self::Error> {
86
0
        if input.len() < PROTOCOL_PREFIX.len() {
87
0
            if PROTOCOL_PREFIX.starts_with(input) {
88
0
                return Err(ParseError::Incomplete(input.len()));
89
            } else {
90
0
                return Err(ParseError::Prefix);
91
            }
92
0
        }
93
94
0
        if &input[..VERSION_COMMAND] != PROTOCOL_PREFIX {
95
0
            return Err(ParseError::Prefix);
96
0
        }
97
98
0
        if input.len() < MINIMUM_LENGTH {
99
0
            return Err(ParseError::Incomplete(input.len()));
100
0
        }
101
102
0
        let version = match input[VERSION_COMMAND] & LEFT_MASK {
103
0
            0x20 => Version::Two,
104
0
            v => return Err(ParseError::Version(v)),
105
        };
106
0
        let command = match input[VERSION_COMMAND] & RIGHT_MASK {
107
0
            0x00 => Command::Local,
108
0
            0x01 => Command::Proxy,
109
0
            c => return Err(ParseError::Command(c)),
110
        };
111
112
0
        let address_family = match input[ADDRESS_FAMILY_PROTOCOL] & LEFT_MASK {
113
0
            0x00 => AddressFamily::Unspecified,
114
0
            0x10 => AddressFamily::IPv4,
115
0
            0x20 => AddressFamily::IPv6,
116
0
            0x30 => AddressFamily::Unix,
117
0
            a => return Err(ParseError::AddressFamily(a)),
118
        };
119
0
        let protocol = match input[ADDRESS_FAMILY_PROTOCOL] & RIGHT_MASK {
120
0
            0x00 => Protocol::Unspecified,
121
0
            0x01 => Protocol::Stream,
122
0
            0x02 => Protocol::Datagram,
123
0
            p => return Err(ParseError::Protocol(p)),
124
        };
125
126
0
        let length = u16::from_be_bytes([input[LENGTH], input[LENGTH + 1]]) as usize;
127
0
        let address_family_bytes = address_family.byte_length().unwrap_or_default();
128
129
0
        if length < address_family_bytes {
130
0
            return Err(ParseError::InvalidAddresses(length, address_family_bytes));
131
0
        }
132
133
0
        let full_length = MINIMUM_LENGTH + length;
134
135
0
        if input.len() < full_length {
136
0
            return Err(ParseError::Partial(input.len() - MINIMUM_LENGTH, length));
137
0
        }
138
139
0
        let header = &input[..full_length];
140
0
        let addresses = parse_addresses(
141
0
            address_family,
142
0
            &header[MINIMUM_LENGTH..MINIMUM_LENGTH + address_family_bytes],
143
        );
144
145
0
        Ok(Header {
146
0
            header: Cow::Borrowed(header),
147
0
            version,
148
0
            command,
149
0
            protocol,
150
0
            addresses,
151
0
        })
152
0
    }
153
}
154
155
#[cfg(test)]
156
mod 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_eq!(actual.tlv_bytes(), &[]);
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_eq!(actual.tlv_bytes(), &[]);
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_eq!(actual.tlv_bytes(), &[]);
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_eq!(actual.tlv_bytes(), &[]);
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_eq!(actual.address_bytes(), &[]);
672
        assert_eq!(actual.tlv_bytes(), &[]);
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_eq!(actual.tlv_bytes(), &[]);
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
}