1use crate::action::{
4 Action, AddPortMappingParams, DeletePortMappingParams, GetGenericPortMappingEntryParams,
5 GetSpecificPortMappingEntryParams,
6};
7
8#[derive(Debug, Clone)]
10pub struct SoapRequest {
11 pub action_name: String,
12 pub service_type: String,
13 pub body: SoapRequestBody,
14}
15
16#[derive(Debug, Clone)]
18pub enum SoapRequestBody {
19 GetExternalIPAddress,
20 GetStatusInfo,
21 AddPortMapping(AddPortMappingRequest),
22 DeletePortMapping(DeletePortMappingRequest),
23 GetGenericPortMappingEntry(GetGenericPortMappingEntryRequest),
24 GetSpecificPortMappingEntry(GetSpecificPortMappingEntryRequest),
25 GetCommonLinkProperties,
26 GetTotalBytesReceived,
27 GetTotalBytesSent,
28 Unknown(String),
29}
30
31#[derive(Debug, Clone)]
33pub struct AddPortMappingRequest {
34 pub remote_host: String,
35 pub external_port: u16,
36 pub protocol: String,
37 pub internal_port: u16,
38 pub internal_client: String,
39 pub enabled: bool,
40 pub description: String,
41 pub lease_duration: u32,
42}
43
44#[derive(Debug, Clone)]
46pub struct DeletePortMappingRequest {
47 pub remote_host: String,
48 pub external_port: u16,
49 pub protocol: String,
50}
51
52#[derive(Debug, Clone)]
54pub struct GetGenericPortMappingEntryRequest {
55 pub index: u32,
56}
57
58#[derive(Debug, Clone)]
60pub struct GetSpecificPortMappingEntryRequest {
61 pub remote_host: String,
62 pub external_port: u16,
63 pub protocol: String,
64}
65
66pub trait Matcher: Send + Sync {
68 fn matches(&self, request: &SoapRequest) -> bool;
70}
71
72impl Matcher for Action {
73 fn matches(&self, request: &SoapRequest) -> bool {
74 match self {
75 Action::Any => true,
76
77 Action::GetExternalIPAddress => {
78 matches!(request.body, SoapRequestBody::GetExternalIPAddress)
79 }
80
81 Action::GetStatusInfo => {
82 matches!(request.body, SoapRequestBody::GetStatusInfo)
83 }
84
85 Action::AddPortMapping(params) => match &request.body {
86 SoapRequestBody::AddPortMapping(req) => matches_add_port_mapping(params, req),
87 _ => false,
88 },
89
90 Action::DeletePortMapping(params) => match &request.body {
91 SoapRequestBody::DeletePortMapping(req) => matches_delete_port_mapping(params, req),
92 _ => false,
93 },
94
95 Action::GetGenericPortMappingEntry(params) => match &request.body {
96 SoapRequestBody::GetGenericPortMappingEntry(req) => {
97 matches_get_generic_port_mapping_entry(params, req)
98 }
99 _ => false,
100 },
101
102 Action::GetSpecificPortMappingEntry(params) => match &request.body {
103 SoapRequestBody::GetSpecificPortMappingEntry(req) => {
104 matches_get_specific_port_mapping_entry(params, req)
105 }
106 _ => false,
107 },
108
109 Action::GetCommonLinkProperties => {
110 matches!(request.body, SoapRequestBody::GetCommonLinkProperties)
111 }
112
113 Action::GetTotalBytesReceived => {
114 matches!(request.body, SoapRequestBody::GetTotalBytesReceived)
115 }
116
117 Action::GetTotalBytesSent => {
118 matches!(request.body, SoapRequestBody::GetTotalBytesSent)
119 }
120 }
121 }
122}
123
124fn matches_add_port_mapping(params: &AddPortMappingParams, req: &AddPortMappingRequest) -> bool {
125 if let Some(port) = params.external_port {
126 if req.external_port != port {
127 return false;
128 }
129 }
130 if let Some(protocol) = ¶ms.protocol {
131 if req.protocol.to_uppercase() != protocol.as_str() {
132 return false;
133 }
134 }
135 if let Some(port) = params.internal_port {
136 if req.internal_port != port {
137 return false;
138 }
139 }
140 if let Some(client) = ¶ms.internal_client {
141 if req.internal_client != client.to_string() {
142 return false;
143 }
144 }
145 if let Some(desc) = ¶ms.description {
146 if !req.description.contains(desc.as_str()) {
147 return false;
148 }
149 }
150 true
151}
152
153fn matches_delete_port_mapping(
154 params: &DeletePortMappingParams,
155 req: &DeletePortMappingRequest,
156) -> bool {
157 if let Some(port) = params.external_port {
158 if req.external_port != port {
159 return false;
160 }
161 }
162 if let Some(protocol) = ¶ms.protocol {
163 if req.protocol.to_uppercase() != protocol.as_str() {
164 return false;
165 }
166 }
167 true
168}
169
170fn matches_get_generic_port_mapping_entry(
171 params: &GetGenericPortMappingEntryParams,
172 req: &GetGenericPortMappingEntryRequest,
173) -> bool {
174 if let Some(index) = params.index {
175 if req.index != index {
176 return false;
177 }
178 }
179 true
180}
181
182fn matches_get_specific_port_mapping_entry(
183 params: &GetSpecificPortMappingEntryParams,
184 req: &GetSpecificPortMappingEntryRequest,
185) -> bool {
186 if let Some(port) = params.external_port {
187 if req.external_port != port {
188 return false;
189 }
190 }
191 if let Some(protocol) = ¶ms.protocol {
192 if req.protocol.to_uppercase() != protocol.as_str() {
193 return false;
194 }
195 }
196 true
197}