auto_discovery/protocols/
mod.rs1use crate::{
4 config::DiscoveryConfig,
5 error::{DiscoveryError, Result},
6 registry::ServiceRegistry,
7 service::ServiceInfo,
8 types::{ProtocolType, ServiceType},
9};
10use async_trait::async_trait;
11use std::{collections::HashMap, sync::Arc, time::Duration};
12use tracing::warn;
13
14pub mod mdns;
15pub mod upnp;
16pub mod dns_sd;
17
18#[async_trait]
23pub trait DiscoveryProtocol: Send + Sync {
24 fn protocol_type(&self) -> ProtocolType;
26
27 async fn discover_services(
29 &self,
30 service_types: Vec<ServiceType>,
31 timeout: Option<Duration>,
32 ) -> Result<Vec<ServiceInfo>>;
33
34 async fn register_service(&self, service: ServiceInfo) -> Result<()>;
36
37 async fn unregister_service(&self, service: &ServiceInfo) -> Result<()>;
39
40 async fn verify_service(&self, service: &ServiceInfo) -> Result<bool>;
42
43 async fn is_available(&self) -> bool;
45
46 fn set_registry(&mut self, registry: Arc<ServiceRegistry>);
48}
49
50#[derive(Clone)]
52pub struct ProtocolManager {
53 #[allow(dead_code)]
54 config: DiscoveryConfig,
55 protocols: HashMap<ProtocolType, Arc<dyn DiscoveryProtocol + Send + Sync>>,
56}
57
58impl ProtocolManager {
59 pub async fn new(config: DiscoveryConfig) -> Result<Self> {
61 let mut protocols: HashMap<ProtocolType, Arc<dyn DiscoveryProtocol + Send + Sync>> = HashMap::new();
62
63 if config.has_protocol(ProtocolType::Mdns) {
65 #[cfg(all(feature = "simple-mdns", not(feature = "mdns")))]
66 {
67 if let Ok(mdns) = simple_mdns::SimpleMdnsProtocol::new(&config).await {
68 protocols.insert(ProtocolType::Mdns, Arc::new(mdns) as Arc<dyn DiscoveryProtocol + Send + Sync>);
69 }
70 }
71 #[cfg(not(feature = "simple-mdns"))]
72 {
73 if let Ok(mdns) = mdns::MdnsProtocol::new(&config).await {
74 protocols.insert(ProtocolType::Mdns, Arc::new(mdns) as Arc<dyn DiscoveryProtocol + Send + Sync>);
75 }
76 }
77 }
78
79 if config.has_protocol(ProtocolType::Upnp) {
80 if let Ok(ssdp) = upnp::SsdpProtocol::new(config.clone()) {
81 protocols.insert(ProtocolType::Upnp, Arc::new(ssdp) as Arc<dyn DiscoveryProtocol + Send + Sync>);
82 }
83 }
84
85 if config.has_protocol(ProtocolType::DnsSd) {
86 if let Ok(dns_sd) = dns_sd::DnsSdProtocol::new(&config).await {
87 protocols.insert(ProtocolType::DnsSd, Arc::new(dns_sd) as Arc<dyn DiscoveryProtocol + Send + Sync>);
88 }
89 }
90
91 Ok(Self { config, protocols })
105 }
106
107 pub fn protocol_types(&self) -> Vec<ProtocolType> {
109 self.protocols.keys().copied().collect()
110 }
111
112 pub async fn discover_services(
114 &self,
115 service_types: Vec<ServiceType>,
116 timeout: Option<Duration>,
117 ) -> Result<Vec<ServiceInfo>> {
118 let mut all_services = Vec::new();
119
120 for protocol in self.protocols.values() {
121 match protocol.discover_services(service_types.clone(), timeout).await {
122 Ok(services) => all_services.extend(services),
123 Err(e) => warn!(
124 "Error discovering services with protocol {:?}: {}",
125 protocol.protocol_type(),
126 e
127 ),
128 }
129 }
130
131 Ok(all_services)
132 }
133
134 pub async fn discover_services_with_protocol(
136 &self,
137 protocol_type: ProtocolType,
138 service_types: Vec<ServiceType>,
139 timeout: Option<Duration>,
140 ) -> Result<Vec<ServiceInfo>> {
141 if let Some(protocol) = self.protocols.get(&protocol_type) {
142 return protocol.discover_services(service_types, timeout).await;
143 }
144 Err(DiscoveryError::protocol(format!("Protocol {protocol_type:?} not available")))
145 }
146
147 pub async fn register_service(&self, service: ServiceInfo) -> Result<()> {
149 let protocol_type = service.protocol_type();
150 if let Some(protocol) = self.protocols.get(&protocol_type) {
151 return protocol.register_service(service).await;
152 }
153
154 Err(DiscoveryError::protocol(format!(
155 "Protocol {protocol_type:?} not available"
156 )))
157 }
158
159 pub async fn unregister_service(&self, service: &ServiceInfo) -> Result<()> {
161 let protocol_type = service.protocol_type();
162 if let Some(protocol) = self.protocols.get(&protocol_type) {
163 return protocol.unregister_service(service).await;
164 }
165 Err(DiscoveryError::protocol(format!(
166 "Protocol {protocol_type:?} not available"
167 )))
168 }
169
170 pub async fn verify_service(&self, service: &ServiceInfo) -> Result<bool> {
172 let protocol_type = service.protocol_type();
173 if let Some(protocol) = self.protocols.get(&protocol_type) {
174 return protocol.verify_service(service).await;
175 }
176 Err(DiscoveryError::protocol(format!(
177 "Protocol {protocol_type:?} not available"
178 )))
179 }
180
181 pub fn protocols(&self) -> &HashMap<ProtocolType, Arc<dyn DiscoveryProtocol + Send + Sync>> {
183 &self.protocols
184 }
185
186 pub async fn health_check(&self) -> HashMap<ProtocolType, bool> {
188 let mut statuses = HashMap::new();
189 for (protocol_type, protocol) in &self.protocols {
190 statuses.insert(*protocol_type, protocol.is_available().await);
191 }
192 statuses
193 }
194}
195
196#[cfg(test)]
197mod tests {
198 use super::*;
199 use crate::config::DiscoveryConfig;
200
201 #[tokio::test]
202 async fn test_protocol_manager_creation() {
203 let config = DiscoveryConfig::new();
204 let manager = ProtocolManager::new(config).await;
205
206 match manager {
208 Ok(manager) => {
209 assert!(!manager.protocols.is_empty());
210 }
211 Err(_) => {
212 }
214 }
215 }
216
217 #[tokio::test]
218 async fn test_protocol_availability() {
219 let config = DiscoveryConfig::new().with_protocol(ProtocolType::Mdns);
220 if let Ok(manager) = ProtocolManager::new(config).await {
221 let protocols = manager.protocol_types();
222 assert!(!protocols.is_empty());
223 }
224 }
225
226 #[tokio::test]
227 async fn test_service_registration() {
228 let config = DiscoveryConfig::new().with_protocol(ProtocolType::Mdns);
229 let manager = ProtocolManager::new(config).await.unwrap();
230
231 let service = ServiceInfo::new(
232 "test_service",
233 "_http._tcp.local.",
234 8080,
235 Some(vec![("version", "1.0")])
236 )
237 .unwrap()
238 .with_protocol_type(ProtocolType::Mdns);
239
240 assert!(manager.register_service(service).await.is_ok());
241 }
242}