xref: /webrtc/util/src/vnet/chunk.rs (revision ffe74184)
1 #[cfg(test)]
2 mod chunk_test;
3 
4 use super::net::*;
5 use crate::error::Result;
6 
7 use std::fmt;
8 use std::net::{IpAddr, SocketAddr};
9 use std::ops::{BitAnd, BitOr};
10 use std::str::FromStr;
11 use std::sync::atomic::{AtomicU64, Ordering};
12 use std::time::SystemTime;
13 
14 lazy_static! {
15     static ref TAG_CTR: AtomicU64 = AtomicU64::new(0);
16 }
17 
18 /// Encodes a u64 value to a lowercase base 36 string.
base36(value: impl Into<u64>) -> String19 pub fn base36(value: impl Into<u64>) -> String {
20     let mut digits: Vec<u8> = vec![];
21 
22     let mut value = value.into();
23     while value > 0 {
24         let digit = (value % 36) as usize;
25         value /= 36;
26 
27         digits.push(b"0123456789abcdefghijklmnopqrstuvwxyz"[digit]);
28     }
29 
30     digits.reverse();
31     format!("{:0>8}", String::from_utf8(digits).unwrap())
32 }
33 
34 // Generate a base36-encoded unique tag
35 // See: https://play.golang.org/p/0ZaAID1q-HN
assign_chunk_tag() -> String36 fn assign_chunk_tag() -> String {
37     let n = TAG_CTR.fetch_add(1, Ordering::SeqCst);
38     base36(n)
39 }
40 
41 #[derive(Copy, Clone, PartialEq, Debug)]
42 pub(crate) struct TcpFlag(pub(crate) u8);
43 
44 pub(crate) const TCP_FLAG_ZERO: TcpFlag = TcpFlag(0x00);
45 pub(crate) const TCP_FLAG_FIN: TcpFlag = TcpFlag(0x01);
46 pub(crate) const TCP_FLAG_SYN: TcpFlag = TcpFlag(0x02);
47 pub(crate) const TCP_FLAG_RST: TcpFlag = TcpFlag(0x04);
48 pub(crate) const TCP_FLAG_PSH: TcpFlag = TcpFlag(0x08);
49 pub(crate) const TCP_FLAG_ACK: TcpFlag = TcpFlag(0x10);
50 
51 impl BitOr for TcpFlag {
52     type Output = Self;
53 
54     // rhs is the "right-hand side" of the expression `a | b`
bitor(self, rhs: Self) -> Self::Output55     fn bitor(self, rhs: Self) -> Self::Output {
56         Self(self.0 | rhs.0)
57     }
58 }
59 
60 impl BitAnd for TcpFlag {
61     type Output = Self;
62 
63     // rhs is the "right-hand side" of the expression `a & b`
bitand(self, rhs: Self) -> Self::Output64     fn bitand(self, rhs: Self) -> Self::Output {
65         Self(self.0 & rhs.0)
66     }
67 }
68 
69 impl fmt::Display for TcpFlag {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result70     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71         let mut sa = vec![];
72         if *self & TCP_FLAG_FIN != TCP_FLAG_ZERO {
73             sa.push("FIN");
74         }
75         if *self & TCP_FLAG_SYN != TCP_FLAG_ZERO {
76             sa.push("SYN");
77         }
78         if *self & TCP_FLAG_RST != TCP_FLAG_ZERO {
79             sa.push("RST");
80         }
81         if *self & TCP_FLAG_PSH != TCP_FLAG_ZERO {
82             sa.push("PSH");
83         }
84         if *self & TCP_FLAG_ACK != TCP_FLAG_ZERO {
85             sa.push("ACK");
86         }
87 
88         write!(f, "{}", sa.join("-"))
89     }
90 }
91 
92 // Chunk represents a packet passed around in the vnet
93 pub trait Chunk: fmt::Display + fmt::Debug {
set_timestamp(&mut self) -> SystemTime94     fn set_timestamp(&mut self) -> SystemTime; // used by router
get_timestamp(&self) -> SystemTime95     fn get_timestamp(&self) -> SystemTime; // used by router
get_source_ip(&self) -> IpAddr96     fn get_source_ip(&self) -> IpAddr; // used by routee
get_destination_ip(&self) -> IpAddr97     fn get_destination_ip(&self) -> IpAddr; // used by router
set_source_addr(&mut self, address: &str) -> Result<()>98     fn set_source_addr(&mut self, address: &str) -> Result<()>; // used by nat
set_destination_addr(&mut self, address: &str) -> Result<()>99     fn set_destination_addr(&mut self, address: &str) -> Result<()>; // used by nat
100 
source_addr(&self) -> SocketAddr101     fn source_addr(&self) -> SocketAddr;
destination_addr(&self) -> SocketAddr102     fn destination_addr(&self) -> SocketAddr;
user_data(&self) -> Vec<u8>103     fn user_data(&self) -> Vec<u8>;
tag(&self) -> String104     fn tag(&self) -> String;
network(&self) -> String105     fn network(&self) -> String; // returns "udp" or "tcp"
clone_to(&self) -> Box<dyn Chunk + Send + Sync>106     fn clone_to(&self) -> Box<dyn Chunk + Send + Sync>;
107 }
108 
109 #[derive(PartialEq, Debug)]
110 pub(crate) struct ChunkIp {
111     pub(crate) timestamp: SystemTime,
112     pub(crate) source_ip: IpAddr,
113     pub(crate) destination_ip: IpAddr,
114     pub(crate) tag: String,
115 }
116 
117 impl ChunkIp {
set_timestamp(&mut self) -> SystemTime118     fn set_timestamp(&mut self) -> SystemTime {
119         self.timestamp = SystemTime::now();
120         self.timestamp
121     }
122 
get_timestamp(&self) -> SystemTime123     fn get_timestamp(&self) -> SystemTime {
124         self.timestamp
125     }
126 
get_destination_ip(&self) -> IpAddr127     fn get_destination_ip(&self) -> IpAddr {
128         self.destination_ip
129     }
130 
get_source_ip(&self) -> IpAddr131     fn get_source_ip(&self) -> IpAddr {
132         self.source_ip
133     }
134 
tag(&self) -> String135     fn tag(&self) -> String {
136         self.tag.clone()
137     }
138 }
139 
140 #[derive(PartialEq, Debug)]
141 pub(crate) struct ChunkUdp {
142     pub(crate) chunk_ip: ChunkIp,
143     pub(crate) source_port: u16,
144     pub(crate) destination_port: u16,
145     pub(crate) user_data: Vec<u8>,
146 }
147 
148 impl fmt::Display for ChunkUdp {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result149     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150         write!(
151             f,
152             "{} chunk {} {} => {}",
153             self.network(),
154             self.tag(),
155             self.source_addr(),
156             self.destination_addr(),
157         )
158     }
159 }
160 
161 impl Chunk for ChunkUdp {
set_timestamp(&mut self) -> SystemTime162     fn set_timestamp(&mut self) -> SystemTime {
163         self.chunk_ip.set_timestamp()
164     }
165 
get_timestamp(&self) -> SystemTime166     fn get_timestamp(&self) -> SystemTime {
167         self.chunk_ip.get_timestamp()
168     }
169 
get_destination_ip(&self) -> IpAddr170     fn get_destination_ip(&self) -> IpAddr {
171         self.chunk_ip.get_destination_ip()
172     }
173 
get_source_ip(&self) -> IpAddr174     fn get_source_ip(&self) -> IpAddr {
175         self.chunk_ip.get_source_ip()
176     }
177 
tag(&self) -> String178     fn tag(&self) -> String {
179         self.chunk_ip.tag()
180     }
181 
source_addr(&self) -> SocketAddr182     fn source_addr(&self) -> SocketAddr {
183         SocketAddr::new(self.chunk_ip.source_ip, self.source_port)
184     }
185 
destination_addr(&self) -> SocketAddr186     fn destination_addr(&self) -> SocketAddr {
187         SocketAddr::new(self.chunk_ip.destination_ip, self.destination_port)
188     }
189 
user_data(&self) -> Vec<u8>190     fn user_data(&self) -> Vec<u8> {
191         self.user_data.clone()
192     }
193 
clone_to(&self) -> Box<dyn Chunk + Send + Sync>194     fn clone_to(&self) -> Box<dyn Chunk + Send + Sync> {
195         Box::new(ChunkUdp {
196             chunk_ip: ChunkIp {
197                 timestamp: self.chunk_ip.timestamp,
198                 source_ip: self.chunk_ip.source_ip,
199                 destination_ip: self.chunk_ip.destination_ip,
200                 tag: self.chunk_ip.tag.clone(),
201             },
202             source_port: self.source_port,
203             destination_port: self.destination_port,
204             user_data: self.user_data.clone(),
205         })
206     }
207 
network(&self) -> String208     fn network(&self) -> String {
209         UDP_STR.to_owned()
210     }
211 
set_source_addr(&mut self, address: &str) -> Result<()>212     fn set_source_addr(&mut self, address: &str) -> Result<()> {
213         let addr = SocketAddr::from_str(address)?;
214         self.chunk_ip.source_ip = addr.ip();
215         self.source_port = addr.port();
216         Ok(())
217     }
218 
set_destination_addr(&mut self, address: &str) -> Result<()>219     fn set_destination_addr(&mut self, address: &str) -> Result<()> {
220         let addr = SocketAddr::from_str(address)?;
221         self.chunk_ip.destination_ip = addr.ip();
222         self.destination_port = addr.port();
223         Ok(())
224     }
225 }
226 
227 impl ChunkUdp {
new(src_addr: SocketAddr, dst_addr: SocketAddr) -> Self228     pub(crate) fn new(src_addr: SocketAddr, dst_addr: SocketAddr) -> Self {
229         ChunkUdp {
230             chunk_ip: ChunkIp {
231                 timestamp: SystemTime::now(),
232                 source_ip: src_addr.ip(),
233                 destination_ip: dst_addr.ip(),
234                 tag: assign_chunk_tag(),
235             },
236             source_port: src_addr.port(),
237             destination_port: dst_addr.port(),
238             user_data: vec![],
239         }
240     }
241 }
242 
243 #[derive(PartialEq, Debug)]
244 pub(crate) struct ChunkTcp {
245     chunk_ip: ChunkIp,
246     source_port: u16,
247     destination_port: u16,
248     flags: TcpFlag, // control bits
249     user_data: Vec<u8>, // only with PSH flag
250                     // seq             :u32,  // always starts with 0
251                     // ack             :u32,  // always starts with 0
252 }
253 
254 impl fmt::Display for ChunkTcp {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result255     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256         write!(
257             f,
258             "{} {} chunk {} {} => {}",
259             self.network(),
260             self.flags,
261             self.chunk_ip.tag,
262             self.source_addr(),
263             self.destination_addr(),
264         )
265     }
266 }
267 
268 impl Chunk for ChunkTcp {
set_timestamp(&mut self) -> SystemTime269     fn set_timestamp(&mut self) -> SystemTime {
270         self.chunk_ip.set_timestamp()
271     }
272 
get_timestamp(&self) -> SystemTime273     fn get_timestamp(&self) -> SystemTime {
274         self.chunk_ip.get_timestamp()
275     }
276 
get_destination_ip(&self) -> IpAddr277     fn get_destination_ip(&self) -> IpAddr {
278         self.chunk_ip.get_destination_ip()
279     }
280 
get_source_ip(&self) -> IpAddr281     fn get_source_ip(&self) -> IpAddr {
282         self.chunk_ip.get_source_ip()
283     }
284 
tag(&self) -> String285     fn tag(&self) -> String {
286         self.chunk_ip.tag()
287     }
288 
source_addr(&self) -> SocketAddr289     fn source_addr(&self) -> SocketAddr {
290         SocketAddr::new(self.chunk_ip.source_ip, self.source_port)
291     }
292 
destination_addr(&self) -> SocketAddr293     fn destination_addr(&self) -> SocketAddr {
294         SocketAddr::new(self.chunk_ip.destination_ip, self.destination_port)
295     }
296 
user_data(&self) -> Vec<u8>297     fn user_data(&self) -> Vec<u8> {
298         self.user_data.clone()
299     }
300 
clone_to(&self) -> Box<dyn Chunk + Send + Sync>301     fn clone_to(&self) -> Box<dyn Chunk + Send + Sync> {
302         Box::new(ChunkTcp {
303             chunk_ip: ChunkIp {
304                 timestamp: self.chunk_ip.timestamp,
305                 source_ip: self.chunk_ip.source_ip,
306                 destination_ip: self.chunk_ip.destination_ip,
307                 tag: self.chunk_ip.tag.clone(),
308             },
309             source_port: self.source_port,
310             destination_port: self.destination_port,
311             flags: self.flags,
312             user_data: self.user_data.clone(),
313         })
314     }
315 
network(&self) -> String316     fn network(&self) -> String {
317         "tcp".to_owned()
318     }
319 
set_source_addr(&mut self, address: &str) -> Result<()>320     fn set_source_addr(&mut self, address: &str) -> Result<()> {
321         let addr = SocketAddr::from_str(address)?;
322         self.chunk_ip.source_ip = addr.ip();
323         self.source_port = addr.port();
324         Ok(())
325     }
326 
set_destination_addr(&mut self, address: &str) -> Result<()>327     fn set_destination_addr(&mut self, address: &str) -> Result<()> {
328         let addr = SocketAddr::from_str(address)?;
329         self.chunk_ip.destination_ip = addr.ip();
330         self.destination_port = addr.port();
331         Ok(())
332     }
333 }
334 
335 impl ChunkTcp {
new(src_addr: SocketAddr, dst_addr: SocketAddr, flags: TcpFlag) -> Self336     pub(crate) fn new(src_addr: SocketAddr, dst_addr: SocketAddr, flags: TcpFlag) -> Self {
337         ChunkTcp {
338             chunk_ip: ChunkIp {
339                 timestamp: SystemTime::now(),
340                 source_ip: src_addr.ip(),
341                 destination_ip: dst_addr.ip(),
342                 tag: assign_chunk_tag(),
343             },
344             source_port: src_addr.port(),
345             destination_port: dst_addr.port(),
346             flags,
347             user_data: vec![],
348         }
349     }
350 }
351