Skip to content

Commit d336fb3

Browse files
committed
add some typed TLVs
1 parent 69d9afd commit d336fb3

File tree

3 files changed

+87
-14
lines changed

3 files changed

+87
-14
lines changed

actix-proxy-protocol/examples/proxy-server.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ async fn wrap_with_proxy_protocol_v2(mut stream: TcpStream) -> io::Result<()> {
7474

7575
let mut proxy_header = v2::Header::new_tcp_ipv4_proxy(([127, 0, 0, 1], 8082), *UPSTREAM);
7676

77-
proxy_header.add_tlv(0x05, [0x34, 0x32, 0x36, 0x39]); // UNIQUE_ID
78-
proxy_header.add_tlv(0x04, "NOOP m9"); // NOOP
77+
proxy_header.add_typed_tlv(tlv::UniqueId::new("4269")); // UNIQUE_ID
78+
proxy_header.add_typed_tlv(tlv::Noop::new("NOOP m8")); // NOOP
7979
proxy_header.add_crc23c_checksum_tlv();
8080

8181
proxy_header.write_to_tokio(&mut upstream).await?;

actix-proxy-protocol/src/tlv.rs

Lines changed: 80 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1-
use std::convert::TryFrom;
1+
use std::{borrow::Cow, convert::TryFrom};
22

33
pub trait Tlv: Sized {
44
const TYPE: u8;
55

6-
fn try_from_parts(typ: u8, value: &[u8]) -> Option<Self>;
6+
fn try_from_value(value: &[u8]) -> Option<Self>;
77

8-
fn value_bytes(&self) -> Vec<u8>;
8+
fn value_bytes(&self) -> Cow<'_, [u8]>;
9+
10+
fn try_from_parts(typ: u8, value: &[u8]) -> Option<Self> {
11+
if typ != Self::TYPE {
12+
return None;
13+
}
14+
15+
Self::try_from_value(value)
16+
}
917
}
1018

1119
#[derive(Debug, Clone, Default, PartialEq, Eq)]
@@ -16,20 +24,82 @@ pub struct Crc32c {
1624
impl Tlv for Crc32c {
1725
const TYPE: u8 = 0x03;
1826

19-
fn try_from_parts(typ: u8, value: &[u8]) -> Option<Self> {
20-
if typ != Self::TYPE {
21-
return None;
22-
}
23-
27+
fn try_from_value(value: &[u8]) -> Option<Self> {
2428
let checksum_bytes = <[u8; 4]>::try_from(value).ok()?;
2529

2630
Some(Self {
2731
checksum: u32::from_be_bytes(checksum_bytes),
2832
})
2933
}
3034

31-
fn value_bytes(&self) -> Vec<u8> {
32-
self.checksum.to_be_bytes().to_vec()
35+
fn value_bytes(&self) -> Cow<'_, [u8]> {
36+
Cow::Owned(self.checksum.to_be_bytes().to_vec())
37+
}
38+
}
39+
40+
#[derive(Debug, Clone, Default, PartialEq, Eq)]
41+
pub struct Noop {
42+
value: Vec<u8>,
43+
}
44+
45+
impl Noop {
46+
///
47+
///
48+
/// # Panics
49+
/// Panics if value is empty (i.e., has length of 0).
50+
pub fn new(value: impl Into<Vec<u8>>) -> Self {
51+
let value = value.into();
52+
53+
assert!(!value.is_empty(), "Noop TLV `value` cannot be empty");
54+
55+
Self { value }
56+
}
57+
}
58+
59+
impl Tlv for Noop {
60+
const TYPE: u8 = 0x04;
61+
62+
fn try_from_value(value: &[u8]) -> Option<Self> {
63+
Some(Self {
64+
value: value.to_owned(),
65+
})
66+
}
67+
68+
fn value_bytes(&self) -> Cow<'_, [u8]> {
69+
Cow::Borrowed(&self.value)
70+
}
71+
}
72+
73+
#[derive(Debug, Clone, Default, PartialEq, Eq)]
74+
pub struct UniqueId {
75+
value: Vec<u8>,
76+
}
77+
78+
impl UniqueId {
79+
///
80+
///
81+
/// # 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();
85+
86+
assert!(!value.is_empty(), "UniqueId TLV `value` cannot be empty");
87+
88+
Self { value }
89+
}
90+
}
91+
92+
impl Tlv for UniqueId {
93+
const TYPE: u8 = 0x05;
94+
95+
fn try_from_value(value: &[u8]) -> Option<Self> {
96+
Some(Self {
97+
value: value.to_owned(),
98+
})
99+
}
100+
101+
fn value_bytes(&self) -> Cow<'_, [u8]> {
102+
Cow::Borrowed(&self.value)
33103
}
34104
}
35105

actix-proxy-protocol/src/v2.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ impl Header {
5757
self.tlvs.push((typ, SmallVec::from_slice(value.as_ref())));
5858
}
5959

60+
pub fn add_typed_tlv<T: Tlv>(&mut self, tlv: T) {
61+
self.add_tlv(T::TYPE, tlv.value_bytes());
62+
}
63+
6064
fn v2_len(&self) -> u16 {
6165
let addr_len = if self.src.is_ipv4() {
6266
4 + 2 // 4b IPv4 + 2b port number
@@ -144,8 +148,7 @@ impl Header {
144148
// the bits unchanged.
145149

146150
// add zeroed checksum field to TLVs
147-
let crc = (Crc32c::TYPE, Crc32c::default().value_bytes().to_smallvec());
148-
self.tlvs.push(crc);
151+
self.add_typed_tlv(Crc32c::default());
149152

150153
// write PROXY header to buffer
151154
let mut buf = Vec::new();

0 commit comments

Comments
 (0)