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(self);
80        boxes.and(rhs);
81        boxes
82    }
83}
84
85impl PunchModel {
86    pub fn all() -> Self {
87        Self {
88            set: vec![PunchPolicySet::all()],
89        }
90    }
91    pub fn empty() -> Self {
92        Self { set: Vec::new() }
93    }
94    pub fn and(&mut self, punch_model_box: PunchPolicySet) {
95        self.set.push(punch_model_box)
96    }
97    pub fn is_match(&self, punch_model: PunchPolicy) -> bool {
98        if self.set.is_empty() {
99            return false;
100        }
101        for x in &self.set {
102            if !x.is_match(punch_model) {
103                return false;
104            }
105        }
106        true
107    }
108}
109
110#[derive(Clone, Debug, Serialize, Deserialize)]
111pub struct PunchConsultInfo {
112    pub peer_punch_model: PunchPolicySet,
113    pub peer_nat_info: NatInfo,
114}
115
116impl PunchConsultInfo {
117    pub fn new(peer_punch_model: PunchPolicySet, peer_nat_info: NatInfo) -> Self {
118        Self {
119            peer_punch_model,
120            peer_nat_info,
121        }
122    }
123}
124
125#[derive(Clone, Debug)]
126pub struct PunchInfo {
127    pub(crate) punch_model: PunchModel,
128    pub(crate) peer_nat_info: NatInfo,
129}
130
131impl PunchInfo {
132    pub fn new(punch_model: PunchModel, peer_nat_info: NatInfo) -> Self {
133        Self {
134            punch_model,
135            peer_nat_info,
136        }
137    }
138}
139
140impl FromStr for PunchPolicy {
141    type Err = String;
142
143    fn from_str(s: &str) -> Result<Self, Self::Err> {
144        match s.to_lowercase().trim() {
145            "ipv4-tcp" => Ok(PunchPolicy::IPv4Tcp),
146            "ipv4-udp" => Ok(PunchPolicy::IPv4Udp),
147            "ipv6-tcp" => Ok(PunchPolicy::IPv6Tcp),
148            "ipv6-udp" => Ok(PunchPolicy::IPv6Udp),
149            _ => Err(format!(
150                "not match '{s}', enum: ipv4-tcp/ipv4-udp/ipv6-tcp/ipv6-udp"
151            )),
152        }
153    }
154}