mock_igd/responder/
mod.rs1mod builder;
4mod templates;
5
6pub use builder::SuccessResponseBuilder;
7pub(crate) use templates::generate_soap_fault;
8use templates::generate_success_response;
9
10use crate::matcher::SoapRequest;
11use std::net::IpAddr;
12use std::sync::Arc;
13
14#[derive(Clone)]
16pub struct Responder {
17 inner: Arc<ResponderInner>,
18}
19
20enum ResponderInner {
21 Success(SuccessResponse),
22 Error { code: u16, description: String },
23 Custom(Arc<dyn Fn(&SoapRequest) -> ResponseBody + Send + Sync>),
24}
25
26#[derive(Debug, Clone)]
28pub enum ResponseBody {
29 Soap(String),
31 SoapFault { code: u16, description: String },
33 Raw { content_type: String, body: String },
35}
36
37#[derive(Debug, Clone, Default)]
39pub(crate) struct SuccessResponse {
40 pub(crate) external_ip: Option<IpAddr>,
42
43 pub(crate) connection_status: Option<String>,
45 pub(crate) last_connection_error: Option<String>,
46 pub(crate) uptime: Option<u32>,
47
48 pub(crate) remote_host: Option<String>,
50 pub(crate) external_port: Option<u16>,
51 pub(crate) protocol: Option<String>,
52 pub(crate) internal_port: Option<u16>,
53 pub(crate) internal_client: Option<String>,
54 pub(crate) enabled: Option<bool>,
55 pub(crate) description: Option<String>,
56 pub(crate) lease_duration: Option<u32>,
57
58 pub(crate) wan_access_type: Option<String>,
60 pub(crate) layer1_upstream_max_bit_rate: Option<u32>,
61 pub(crate) layer1_downstream_max_bit_rate: Option<u32>,
62 pub(crate) physical_link_status: Option<String>,
63
64 pub(crate) total_bytes: Option<u64>,
66}
67
68impl Responder {
69 pub fn success() -> SuccessResponseBuilder {
71 SuccessResponseBuilder::default()
72 }
73
74 pub fn error(code: u16, description: impl Into<String>) -> Self {
76 Responder {
77 inner: Arc::new(ResponderInner::Error {
78 code,
79 description: description.into(),
80 }),
81 }
82 }
83
84 pub fn custom<F>(f: F) -> Self
86 where
87 F: Fn(&SoapRequest) -> ResponseBody + Send + Sync + 'static,
88 {
89 Responder {
90 inner: Arc::new(ResponderInner::Custom(Arc::new(f))),
91 }
92 }
93
94 pub fn respond(&self, request: &SoapRequest) -> ResponseBody {
96 match self.inner.as_ref() {
97 ResponderInner::Success(data) => {
98 let xml = generate_success_response(&request.action_name, data);
99 ResponseBody::Soap(xml)
100 }
101 ResponderInner::Error { code, description } => ResponseBody::SoapFault {
102 code: *code,
103 description: description.clone(),
104 },
105 ResponderInner::Custom(f) => f(request),
106 }
107 }
108}
109
110impl std::fmt::Debug for Responder {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 match self.inner.as_ref() {
113 ResponderInner::Success(data) => f.debug_tuple("Responder::Success").field(data).finish(),
114 ResponderInner::Error { code, description } => f
115 .debug_struct("Responder::Error")
116 .field("code", code)
117 .field("description", description)
118 .finish(),
119 ResponderInner::Custom(_) => f.debug_tuple("Responder::Custom").finish(),
120 }
121 }
122}