1
- use std:: { borrow:: Cow , convert:: TryFrom } ;
1
+ use std:: { borrow:: Cow , convert:: TryFrom , str} ;
2
+
3
+ const PP2_TYPE_ALPN : u8 = 0x01 ;
4
+ const PP2_TYPE_AUTHORITY : u8 = 0x02 ;
5
+ const PP2_TYPE_CRC32C : u8 = 0x03 ; // done
6
+ const PP2_TYPE_NOOP : u8 = 0x04 ; // done
7
+ const PP2_TYPE_UNIQUE_ID : u8 = 0x05 ; // done
8
+ const PP2_TYPE_SSL : u8 = 0x20 ;
9
+ const PP2_SUBTYPE_SSL_VERSION : u8 = 0x21 ;
10
+ const PP2_SUBTYPE_SSL_CN : u8 = 0x22 ;
11
+ const PP2_SUBTYPE_SSL_CIPHER : u8 = 0x23 ;
12
+ const PP2_SUBTYPE_SSL_SIG_ALG : u8 = 0x24 ;
13
+ const PP2_SUBTYPE_SSL_KEY_ALG : u8 = 0x25 ;
14
+ const PP2_TYPE_NETNS : u8 = 0x30 ;
2
15
3
16
pub trait Tlv : Sized {
4
17
const TYPE : u8 ;
@@ -16,13 +29,90 @@ pub trait Tlv: Sized {
16
29
}
17
30
}
18
31
32
+ /// Application-Layer Protocol Negotiation (ALPN). It is a byte sequence defining
33
+ /// the upper layer protocol in use over the connection. The most common use case
34
+ /// will be to pass the exact copy of the ALPN extension of the Transport Layer
35
+ /// Security (TLS) protocol as defined by RFC7301 [9].
36
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
37
+ pub struct Alpn {
38
+ alpn : Vec < u8 > ,
39
+ }
40
+
41
+ impl Alpn {
42
+ ///
43
+ ///
44
+ /// # Panics
45
+ /// Panics if `alpn` is empty (i.e., has length of 0).
46
+ pub fn new ( alpn : impl Into < Vec < u8 > > ) -> Self {
47
+ let alpn = alpn. into ( ) ;
48
+
49
+ assert ! ( !alpn. is_empty( ) , "ALPN TLV value cannot be empty" ) ;
50
+
51
+ Self { alpn }
52
+ }
53
+ }
54
+
55
+ impl Tlv for Alpn {
56
+ const TYPE : u8 = PP2_TYPE_ALPN ;
57
+
58
+ fn try_from_value ( value : & [ u8 ] ) -> Option < Self > {
59
+ Some ( Self {
60
+ alpn : value. to_owned ( ) ,
61
+ } )
62
+ }
63
+
64
+ fn value_bytes ( & self ) -> Cow < ' _ , [ u8 ] > {
65
+ Cow :: Borrowed ( & self . alpn )
66
+ }
67
+ }
68
+
69
+ /// Contains the host name value passed by the client, as an UTF8-encoded string.
70
+ /// In case of TLS being used on the client connection, this is the exact copy of
71
+ /// the "server_name" extension as defined by RFC3546 [10], section 3.1, often
72
+ /// referred to as "SNI". There are probably other situations where an authority
73
+ /// can be mentioned on a connection without TLS being involved at all.
74
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
75
+ pub struct Authority {
76
+ authority : String ,
77
+ }
78
+
79
+ impl Authority {
80
+ /// A UTF-8
81
+ ///
82
+ /// # Panics
83
+ /// Panics if `authority` is an empty string.
84
+ pub fn new ( authority : impl Into < String > ) -> Self {
85
+ let authority = authority. into ( ) ;
86
+
87
+ assert ! ( !authority. is_empty( ) , "Authority TLV value cannot be empty" ) ;
88
+
89
+ Self { authority }
90
+ }
91
+ }
92
+
93
+ impl Tlv for Authority {
94
+ const TYPE : u8 = PP2_TYPE_AUTHORITY ;
95
+
96
+ fn try_from_value ( value : & [ u8 ] ) -> Option < Self > {
97
+ Some ( Self {
98
+ authority : str:: from_utf8 ( value) . ok ( ) ?. to_owned ( ) ,
99
+ } )
100
+ }
101
+
102
+ fn value_bytes ( & self ) -> Cow < ' _ , [ u8 ] > {
103
+ Cow :: Borrowed ( & self . authority . as_bytes ( ) )
104
+ }
105
+ }
106
+
107
+ /// The value of the type PP2_TYPE_CRC32C is a 32-bit number storing the CRC32c
108
+ /// checksum of the PROXY protocol header.
19
109
#[ derive( Debug , Clone , Default , PartialEq , Eq ) ]
20
110
pub struct Crc32c {
21
111
pub ( crate ) checksum : u32 ,
22
112
}
23
113
24
114
impl Tlv for Crc32c {
25
- const TYPE : u8 = 0x03 ;
115
+ const TYPE : u8 = PP2_TYPE_CRC32C ;
26
116
27
117
fn try_from_value ( value : & [ u8 ] ) -> Option < Self > {
28
118
let checksum_bytes = <[ u8 ; 4 ] >:: try_from ( value) . ok ( ) ?;
@@ -37,7 +127,10 @@ impl Tlv for Crc32c {
37
127
}
38
128
}
39
129
40
- #[ derive( Debug , Clone , Default , PartialEq , Eq ) ]
130
+ /// The TLV of this type should be ignored when parsed. The value is zero or more
131
+ /// bytes. Can be used for data padding or alignment. Note that it can be used
132
+ /// to align only by 3 or more bytes because a TLV can not be smaller than that.
133
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
41
134
pub struct Noop {
42
135
value : Vec < u8 > ,
43
136
}
@@ -46,7 +139,7 @@ impl Noop {
46
139
///
47
140
///
48
141
/// # Panics
49
- /// Panics if value is empty (i.e., has length of 0).
142
+ /// Panics if ` value` is empty (i.e., has length of 0).
50
143
pub fn new ( value : impl Into < Vec < u8 > > ) -> Self {
51
144
let value = value. into ( ) ;
52
145
@@ -57,7 +150,7 @@ impl Noop {
57
150
}
58
151
59
152
impl Tlv for Noop {
60
- const TYPE : u8 = 0x04 ;
153
+ const TYPE : u8 = PP2_TYPE_NOOP ;
61
154
62
155
fn try_from_value ( value : & [ u8 ] ) -> Option < Self > {
63
156
Some ( Self {
@@ -70,7 +163,13 @@ impl Tlv for Noop {
70
163
}
71
164
}
72
165
73
- #[ derive( Debug , Clone , Default , PartialEq , Eq ) ]
166
+ /// The value of the type PP2_TYPE_UNIQUE_ID is an opaque byte sequence of up to
167
+ /// 128 bytes generated by the upstream proxy that uniquely identifies the
168
+ /// connection.
169
+ ///
170
+ /// The unique ID can be used to easily correlate connections across multiple
171
+ /// layers of proxies, without needing to look up IP addresses and port numbers.
172
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
74
173
pub struct UniqueId {
75
174
value : Vec < u8 > ,
76
175
}
@@ -79,9 +178,9 @@ impl UniqueId {
79
178
///
80
179
///
81
180
/// # Panics
82
- /// Panics if value is empty (i.e., has length of 0).
83
- pub fn new ( value : impl Into < Vec < u8 > > ) -> Self {
84
- let value = value . into ( ) ;
181
+ /// Panics if ` value` is empty (i.e., has length of 0).
182
+ pub fn new ( id : impl Into < Vec < u8 > > ) -> Self {
183
+ let value = id . into ( ) ;
85
184
86
185
assert ! ( !value. is_empty( ) , "UniqueId TLV `value` cannot be empty" ) ;
87
186
@@ -90,7 +189,7 @@ impl UniqueId {
90
189
}
91
190
92
191
impl Tlv for UniqueId {
93
- const TYPE : u8 = 0x05 ;
192
+ const TYPE : u8 = PP2_TYPE_UNIQUE_ID ;
94
193
95
194
fn try_from_value ( value : & [ u8 ] ) -> Option < Self > {
96
195
Some ( Self {
0 commit comments