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