proxy_protocol_codec/
lib.rs

1//! PROXY Protocol codec.
2//!
3//! See [HAProxy](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) for the protocol specification.
4
5#![no_std]
6#![cfg_attr(feature = "feat-nightly", feature(cold_path))]
7
8#[cfg(feature = "feat-codec-v2-uni-addr")]
9compile_error!("The `feat-codec-v2-uni-addr` feature is deprecated. Please use the `feat-uni-addr` feature instead.");
10
11#[cfg(feature = "feat-codec-v1")]
12pub mod v1;
13#[cfg(feature = "feat-codec-v2")]
14pub mod v2;
15
16#[cfg(any(test, feature = "feat-alloc"))]
17extern crate alloc;
18
19#[cfg(any(test, feature = "feat-std"))]
20extern crate std;
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23/// The supported PROXY Protocol versions.
24pub enum Version {
25    /// PROXY Protocol version 1
26    V1,
27
28    /// PROXY Protocol version 2
29    V2,
30}
31
32impl Version {
33    /// The magic bytes that indicate a PROXY Protocol v1 header.
34    pub const MAGIC_V1: &'static str = "PROXY";
35    /// The magic bytes that indicate a PROXY Protocol v2 header.
36    pub const MAGIC_V2: &'static [u8; 12] = b"\r\n\r\n\x00\r\nQUIT\n";
37
38    // #[inline]
39    /// Peeks into the given buffer to determine if it contains a valid PROXY
40    /// Protocol version magic.
41    ///
42    /// ## Behaviours
43    ///
44    /// If the buffer is too short to determine the version, `Ok(None)` is
45    /// returned. If the buffer contains a valid version magic,
46    /// `Ok(Some(Version))` is returned. Otherwise, `Err(())` is returned.
47    pub fn peek(buf: &[u8]) -> Result<Option<Self>, ()> {
48        const V1_MAGIC_LEN: usize = Version::MAGIC_V1.len();
49        const V2_MAGIC_LEN: usize = Version::MAGIC_V2.len();
50
51        match buf.len() {
52            0 => Ok(None),
53            1..V2_MAGIC_LEN if Self::MAGIC_V2.starts_with(buf) => Ok(None),
54            V2_MAGIC_LEN.. if buf.starts_with(Self::MAGIC_V2) => Ok(Some(Self::V2)),
55            1..V1_MAGIC_LEN if Self::MAGIC_V1.as_bytes().starts_with(buf) => Ok(None),
56            V1_MAGIC_LEN.. if buf.starts_with(Self::MAGIC_V1.as_bytes()) => Ok(Some(Self::V1)),
57            _ => Err(()),
58        }
59    }
60}