/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ppp-2.3.0/src/lib.rs
Line | Count | Source |
1 | | //! A Proxy Protocol Parser written in Rust. |
2 | | //! Supports both text and binary versions of the header protocol. |
3 | | |
4 | | mod ip; |
5 | | |
6 | | pub mod v1; |
7 | | pub mod v2; |
8 | | |
9 | | /// The canonical way to determine when a streamed header should be retried in a streaming context. |
10 | | /// The protocol states that servers may choose to support partial headers or to close the connection if the header is not present all at once. |
11 | | pub trait PartialResult { |
12 | | /// Tests whether this `Result` is successful or whether the error is terminal. |
13 | | /// A terminal error will not result in a success even with more bytes. |
14 | | /// Retrying with the same -- or more -- input will not change the result. |
15 | 0 | fn is_complete(&self) -> bool { |
16 | 0 | !self.is_incomplete() |
17 | 0 | } |
18 | | |
19 | | /// Tests whether this `Result` is incomplete. |
20 | | /// An action that leads to an incomplete result may have a different result with more bytes. |
21 | | /// Retrying with the same input will not change the result. |
22 | | fn is_incomplete(&self) -> bool; |
23 | | } |
24 | | |
25 | | impl<'a, T, E: PartialResult> PartialResult for Result<T, E> { |
26 | 0 | fn is_incomplete(&self) -> bool { |
27 | 0 | match self { |
28 | 0 | Ok(_) => false, |
29 | 0 | Err(error) => error.is_incomplete(), |
30 | | } |
31 | 0 | } Unexecuted instantiation: <core::result::Result<ppp::v1::model::Header, ppp::v1::error::BinaryParseError> as ppp::PartialResult>::is_incomplete Unexecuted instantiation: <core::result::Result<ppp::v2::model::Header, ppp::v2::error::ParseError> as ppp::PartialResult>::is_incomplete |
32 | | } |
33 | | |
34 | | impl<'a> PartialResult for v1::ParseError { |
35 | 0 | fn is_incomplete(&self) -> bool { |
36 | 0 | matches!( |
37 | 0 | self, |
38 | | v1::ParseError::Partial |
39 | | | v1::ParseError::MissingPrefix |
40 | | | v1::ParseError::MissingProtocol |
41 | | | v1::ParseError::MissingSourceAddress |
42 | | | v1::ParseError::MissingDestinationAddress |
43 | | | v1::ParseError::MissingSourcePort |
44 | | | v1::ParseError::MissingDestinationPort |
45 | | | v1::ParseError::MissingNewLine |
46 | | ) |
47 | 0 | } |
48 | | } |
49 | | |
50 | | impl<'a> PartialResult for v1::BinaryParseError { |
51 | 0 | fn is_incomplete(&self) -> bool { |
52 | 0 | match self { |
53 | 0 | v1::BinaryParseError::Parse(error) => error.is_incomplete(), |
54 | 0 | _ => false, |
55 | | } |
56 | 0 | } |
57 | | } |
58 | | |
59 | | impl<'a> PartialResult for v2::ParseError { |
60 | 0 | fn is_incomplete(&self) -> bool { |
61 | 0 | matches!( |
62 | 0 | self, |
63 | | v2::ParseError::Incomplete(..) | v2::ParseError::Partial(..) |
64 | | ) |
65 | 0 | } |
66 | | } |
67 | | |
68 | | /// An enumeration of the supported header version's parse results. |
69 | | /// Useful for parsing either version 1 or version 2 of the PROXY protocol. |
70 | | /// |
71 | | /// ## Examples |
72 | | /// ```rust |
73 | | /// use ppp::{HeaderResult, PartialResult, v1, v2}; |
74 | | /// |
75 | | /// let input = "PROXY UNKNOWN\r\n"; |
76 | | /// let header = HeaderResult::parse(input.as_bytes()); |
77 | | /// |
78 | | /// assert_eq!(header, Ok(v1::Header::new(input, v1::Addresses::Unknown)).into()); |
79 | | /// ``` |
80 | | #[derive(Debug, PartialEq)] |
81 | | #[must_use = "this `HeaderResult` may contain a V1 or V2 `Err` variant, which should be handled"] |
82 | | pub enum HeaderResult<'a> { |
83 | | V1(Result<v1::Header<'a>, v1::BinaryParseError>), |
84 | | V2(Result<v2::Header<'a>, v2::ParseError>), |
85 | | } |
86 | | |
87 | | impl<'a> From<Result<v1::Header<'a>, v1::BinaryParseError>> for HeaderResult<'a> { |
88 | 0 | fn from(result: Result<v1::Header<'a>, v1::BinaryParseError>) -> Self { |
89 | 0 | HeaderResult::V1(result) |
90 | 0 | } |
91 | | } |
92 | | |
93 | | impl<'a> From<Result<v2::Header<'a>, v2::ParseError>> for HeaderResult<'a> { |
94 | 0 | fn from(result: Result<v2::Header<'a>, v2::ParseError>) -> Self { |
95 | 0 | HeaderResult::V2(result) |
96 | 0 | } |
97 | | } |
98 | | |
99 | | impl<'a> PartialResult for HeaderResult<'a> { |
100 | 0 | fn is_incomplete(&self) -> bool { |
101 | 0 | match self { |
102 | 0 | Self::V1(result) => result.is_incomplete(), |
103 | 0 | Self::V2(result) => result.is_incomplete(), |
104 | | } |
105 | 0 | } |
106 | | } |
107 | | |
108 | | impl<'a> HeaderResult<'a> { |
109 | | /// Parses a PROXY protocol version 2 `Header`. |
110 | | /// If the input is not a valid version 2 `Header`, attempts to parse a version 1 `Header`. |
111 | 0 | pub fn parse(input: &'a [u8]) -> HeaderResult<'a> { |
112 | 0 | let header = v2::Header::try_from(input); |
113 | | |
114 | 0 | if header.is_complete() && header.is_err() { |
115 | 0 | v1::Header::try_from(input).into() |
116 | | } else { |
117 | 0 | header.into() |
118 | | } |
119 | 0 | } |
120 | | } |