rust_p2p_core/punch/
config.rs

1use crate::nat::NatInfo;
2use serde::{Deserialize, Serialize};
3use std::collections::HashSet;
4use std::ops;
5use std::str::FromStr;
6
7#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
8pub enum PunchPolicy {
9    IPv4Tcp,
10    IPv4Udp,
11    IPv6Tcp,
12    IPv6Udp,
13}
14
15impl ops::BitOr<PunchPolicy> for PunchPolicy {
16    type Output = PunchPolicySet;
17
18    fn bitor(self, rhs: PunchPolicy) -> Self::Output {
19        let mut model = PunchPolicySet::empty();
20        model.or(self);
21        model.or(rhs);
22        model
23    }
24}
25/// This is middle representation for inner
26#[derive(Clone, Debug, Serialize, Deserialize)]
27pub struct PunchPolicySet {
28    models: HashSet<PunchPolicy>,
29}
30
31impl Default for PunchPolicySet {
32    fn default() -> Self {
33        PunchPolicySet::all()
34    }
35}
36
37impl ops::BitOr<PunchPolicy> for PunchPolicySet {
38    type Output = PunchPolicySet;
39
40    fn bitor(mut self, rhs: PunchPolicy) -> Self::Output {
41        self.or(rhs);
42        self
43    }
44}
45
46impl PunchPolicySet {
47    pub fn all() -> Self {
48        PunchPolicy::IPv4Tcp | PunchPolicy::IPv4Udp | PunchPolicy::IPv6Tcp | PunchPolicy::IPv6Udp
49    }
50    pub fn ipv4() -> Self {
51        PunchPolicy::IPv4Tcp | PunchPolicy::IPv4Udp
52    }
53    pub fn ipv6() -> Self {
54        PunchPolicy::IPv6Tcp | PunchPolicy::IPv6Udp
55    }
56    pub fn empty() -> Self {
57        Self {
58            models: Default::default(),
59        }
60    }
61    pub fn or(&mut self, punch_model: PunchPolicy) {
62        self.models.insert(punch_model);
63    }
64    pub fn is_match(&self, punch_model: PunchPolicy) -> bool {
65        self.models.contains(&punch_model)
66    }
67}
68
69#[derive(Clone, Debug)]
70pub struct PunchModel {
71    set: Vec<PunchPolicySet>,
72}
73
74impl ops::BitAnd<PunchPolicySet> for PunchPolicySet {
75    type Output = PunchModel;
76
77    fn bitand(self, rhs: PunchPolicySet) -> Self::Output {
78        let mut boxes = PunchModel::empty();
79        boxes.and(rhs);
80        boxes
81    }
82}
83
84impl PunchModel {
85    pub fn all() -> Self {
86        Self {
87            set: vec![PunchPolicySet::all()],
88        }
89    }
90    pub fn empty() -> Self {
91        Self { set: Vec::new() }
92    }
93    pub fn and(&mut self, punch_model_box: PunchPolicySet) {
94        self.set.push(punch_model_box)
95    }
96    pub fn is_match(&self, punch_model: PunchPolicy) -> bool {
97        if self.set.is_empty() {
98            return false;
99        }
100        for x in &self.set {
101            if !x.is_match(punch_model) {
102                return false;
103            }
104        }
105        true
106    }
107}
108
109#[derive(Clone, Debug, Serialize, Deserialize)]
110pub struct PunchConsultInfo {
111    pub peer_punch_model: PunchPolicySet,
112    pub peer_nat_info: NatInfo,
113}
114
115impl PunchConsultInfo {
116    pub fn new(peer_punch_model: PunchPolicySet, peer_nat_info: NatInfo) -> Self {
117        Self {
118            peer_punch_model,
119            peer_nat_info,
120        }
121    }
122}
123
124#[derive(Clone, Debug)]
125pub struct PunchInfo {
126    pub(crate) punch_model: PunchModel,
127    pub(crate) peer_nat_info: NatInfo,
128}
129
130impl PunchInfo {
131    pub fn new(punch_model: PunchModel, peer_nat_info: NatInfo) -> Self {
132        Self {
133            punch_model,
134            peer_nat_info,
135        }
136    }
137}
138
139impl FromStr for PunchPolicy {
140    type Err = String;
141
142    fn from_str(s: &str) -> Result<Self, Self::Err> {
143        match s.to_lowercase().trim() {
144            "ipv4-tcp" => Ok(PunchPolicy::IPv4Tcp),
145            "ipv4-udp" => Ok(PunchPolicy::IPv4Udp),
146            "ipv6-tcp" => Ok(PunchPolicy::IPv6Tcp),
147            "ipv6-udp" => Ok(PunchPolicy::IPv6Udp),
148            _ => Err(format!(
149                "not match '{}', enum: ipv4-tcp/ipv4-udp/ipv6-tcp/ipv6-udp",
150                s
151            )),
152        }
153    }
154}