Skip to content

Commit d2764bb

Browse files
committed
add Tlv trait
1 parent fae793d commit d2764bb

File tree

6 files changed

+122
-121
lines changed

6 files changed

+122
-121
lines changed

actix-proxy-protocol/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ crc32fast = "1"
2121
futures-core = { version = "0.3.17", default-features = false, features = ["std"] }
2222
futures-util = { version = "0.3.17", default-features = false, features = ["std"] }
2323
itoa = "1"
24+
smallvec = "1"
2425
tokio = { version = "1.13.1", features = ["sync", "io-util"] }
2526
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
2627

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

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::{
1111
},
1212
};
1313

14-
use actix_proxy_protocol::{v1, v2, AddressFamily, Command, Tlv, TransportProtocol};
14+
use actix_proxy_protocol::{tlv, v1, v2, AddressFamily, Command, TransportProtocol};
1515
use actix_rt::net::TcpStream;
1616
use actix_server::Server;
1717
use actix_service::{fn_service, ServiceFactoryExt as _};
@@ -31,6 +31,7 @@ TLV = type-length-value
3131
TO DO:
3232
handle UNKNOWN transport
3333
v2 UNSPEC mode
34+
AF_UNIX socket
3435
*/
3536

3637
fn extend_with_ip_bytes(buf: &mut Vec<u8>, ip: IpAddr) {
@@ -71,18 +72,10 @@ async fn wrap_with_proxy_protocol_v2(mut stream: TcpStream) -> io::Result<()> {
7172
UPSTREAM.to_string()
7273
);
7374

74-
let mut proxy_header = v2::Header::new(
75-
Command::Proxy,
76-
TransportProtocol::Stream,
77-
AddressFamily::Inet,
78-
SocketAddr::from(([127, 0, 0, 1], 8082)),
79-
*UPSTREAM,
80-
vec![
81-
Tlv::new(0x05, [0x34, 0x32, 0x36, 0x39]), // UNIQUE_ID
82-
Tlv::new(0x04, "NOOP m9"), // NOOP
83-
],
84-
);
75+
let mut proxy_header = v2::Header::new_tcp_ipv4_proxy(([127, 0, 0, 1], 8082), *UPSTREAM);
8576

77+
proxy_header.add_tlv(0x05, [0x34, 0x32, 0x36, 0x39]); // UNIQUE_ID
78+
proxy_header.add_tlv(0x04, "NOOP m9"); // NOOP
8679
proxy_header.add_crc23c_checksum_tlv();
8780

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

actix-proxy-protocol/src/lib.rs

Lines changed: 1 addition & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use std::{
1616
use arrayvec::{ArrayString, ArrayVec};
1717
use tokio::io::{AsyncWrite, AsyncWriteExt as _};
1818

19+
pub mod tlv;
1920
pub mod v1;
2021
pub mod v2;
2122

@@ -165,80 +166,3 @@ enum ProxyProtocolHeader {
165166
V1(v1::Header),
166167
V2(v2::Header),
167168
}
168-
169-
#[derive(Debug, Clone, Default, PartialEq, Eq)]
170-
pub struct Pp2Crc32c {
171-
checksum: u32,
172-
}
173-
174-
impl Pp2Crc32c {
175-
fn to_tlv(&self) -> Tlv {
176-
Tlv {
177-
r#type: 0x03,
178-
value: self.checksum.to_be_bytes().to_vec(),
179-
}
180-
}
181-
}
182-
183-
#[derive(Debug, Clone)]
184-
pub struct Tlv {
185-
r#type: u8,
186-
value: Vec<u8>,
187-
}
188-
189-
impl Tlv {
190-
pub fn new(r#type: u8, value: impl Into<Vec<u8>>) -> Self {
191-
let value = value.into();
192-
193-
assert!(
194-
!value.is_empty(),
195-
"TLV values must have length greater than 1",
196-
);
197-
198-
Self { r#type, value }
199-
}
200-
201-
fn len(&self) -> u16 {
202-
// 1b type + 2b len
203-
// + [len]b value
204-
1 + 2 + (self.value.len() as u16)
205-
}
206-
207-
pub fn write_to(&self, wrt: &mut impl io::Write) -> io::Result<()> {
208-
wrt.write_all(&[self.r#type])?;
209-
wrt.write_all(&(self.value.len() as u16).to_be_bytes())?;
210-
wrt.write_all(&self.value)?;
211-
Ok(())
212-
}
213-
214-
pub fn as_crc32c(&self) -> Option<Pp2Crc32c> {
215-
if self.r#type != 0x03 {
216-
return None;
217-
}
218-
219-
let checksum_bytes = <[u8; 4]>::try_from(self.value.as_slice()).ok()?;
220-
221-
Some(Pp2Crc32c {
222-
checksum: u32::from_be_bytes(checksum_bytes),
223-
})
224-
}
225-
}
226-
227-
#[cfg(test)]
228-
mod tests {
229-
use super::*;
230-
231-
#[test]
232-
fn tlv_as_crc32c() {
233-
let noop = Tlv::new(0x04, vec![0x00]);
234-
assert_eq!(noop.as_crc32c(), None);
235-
236-
let noop = Tlv::new(0x03, vec![0x08, 0x70, 0x17, 0x7b]);
237-
assert_eq!(
238-
noop.as_crc32c(),
239-
Some(Pp2Crc32c {
240-
checksum: 141563771
241-
})
242-
);
243-
}
244-
}

actix-proxy-protocol/src/tlv.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use std::convert::TryFrom;
2+
3+
pub trait Tlv: Sized {
4+
const TYPE: u8;
5+
6+
fn try_from_parts(typ: u8, value: &[u8]) -> Option<Self>;
7+
8+
fn value_bytes(&self) -> Vec<u8>;
9+
}
10+
11+
#[derive(Debug, Clone, Default, PartialEq, Eq)]
12+
pub struct Crc32c {
13+
pub(crate) checksum: u32,
14+
}
15+
16+
impl Tlv for Crc32c {
17+
const TYPE: u8 = 0x03;
18+
19+
fn try_from_parts(typ: u8, value: &[u8]) -> Option<Self> {
20+
if typ != Self::TYPE {
21+
return None;
22+
}
23+
24+
let checksum_bytes = <[u8; 4]>::try_from(value).ok()?;
25+
26+
Some(Self {
27+
checksum: u32::from_be_bytes(checksum_bytes),
28+
})
29+
}
30+
31+
fn value_bytes(&self) -> Vec<u8> {
32+
self.checksum.to_be_bytes().to_vec()
33+
}
34+
}
35+
36+
#[cfg(test)]
37+
mod tests {
38+
use super::*;
39+
40+
// #[test]
41+
// #[should_panic]
42+
// fn tlv_zero_len() {
43+
// Tlv::new(0x00, vec![]);
44+
// }
45+
46+
#[test]
47+
fn tlv_as_crc32c() {
48+
// noop
49+
assert_eq!(Crc32c::try_from_parts(0x04, &[0x00]), None);
50+
51+
assert_eq!(
52+
Crc32c::try_from_parts(0x03, &[0x08, 0x70, 0x17, 0x7b]),
53+
Some(Crc32c {
54+
checksum: 141563771
55+
})
56+
);
57+
}
58+
}
File renamed without changes.

0 commit comments

Comments
 (0)