sfo_cmd_server/
tunnel_id.rs1use std::hash::{Hash, Hasher};
2use std::sync::atomic::{AtomicU32, Ordering};
3use std::time::{Duration, SystemTime, UNIX_EPOCH};
4use bucky_raw_codec::{RawDecode, RawEncode};
5
6#[derive(Clone, Copy, Ord, PartialEq, Eq, Debug, RawEncode, RawDecode)]
7pub struct TunnelId(u32);
8
9impl TunnelId {
10 pub fn value(&self) -> u32 {
11 self.0
12 }
13
14 fn now(_now: u64) -> u32 {
15 let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs() as u32;
16 let since_2021 = Duration::from_secs((50 * 365 + 9) * 24 * 3600).as_secs() as u32;
17 (now - since_2021) * 10
19 }
20
21 }
25
26impl PartialOrd for TunnelId {
27 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
28 if self.0 == 0 || other.0 == 0 {
29 self.0.partial_cmp(&other.0)
30 } else if (std::cmp::max(self.0, other.0) - std::cmp::min(self.0, other.0)) > (u32::MAX / 2)
31 {
32 Some(if self.0 > other.0 {
33 std::cmp::Ordering::Less
34 } else {
35 std::cmp::Ordering::Greater
36 })
37 } else {
38 self.0.partial_cmp(&other.0)
39 }
40 }
41}
42
43impl Default for TunnelId {
44 fn default() -> Self {
45 Self(0)
46 }
47}
48
49impl From<u32> for TunnelId {
50 fn from(v: u32) -> Self {
51 Self(v)
52 }
53}
54
55impl Hash for TunnelId {
56 fn hash<H: Hasher>(&self, state: &mut H) {
57 state.write_u32(self.0)
58 }
59}
60
61pub struct TunnelIdGenerator {
62 cur: AtomicU32,
63}
64
65
66impl From<TunnelId> for TunnelIdGenerator {
67 fn from(init: TunnelId) -> Self {
68 Self {
69 cur: AtomicU32::new(init.value())
70 }
71 }
72}
73
74
75impl TunnelIdGenerator {
76 pub fn new() -> Self {
77 let now = TunnelId::now(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() as u64);
78 Self {
79 cur: AtomicU32::new(now),
80 }
81 }
82
83 pub fn generate(&self) -> TunnelId {
84 let v = self.cur.fetch_add(1, Ordering::SeqCst);
85 if v == 0 {
86 TunnelId(self.cur.fetch_add(1, Ordering::SeqCst))
87 } else {
88 TunnelId(v)
89 }
90 }
91}