1#![forbid(unsafe_code)]
2use std::{
7 any::Any,
8 collections::{HashMap, HashSet},
9 fmt,
10 future::Future,
11 io,
12 net::{Ipv4Addr, SocketAddr},
13 pin::Pin,
14 sync::Arc,
15 time::Duration,
16};
17
18use arc_swap::ArcSwap;
19use pharos_proto::{BuildError, Message, Name, Rcode, Type};
20use tokio::{
21 net::{TcpListener, UdpSocket},
22 sync::watch,
23 task::JoinHandle,
24};
25
26mod admission;
27pub mod http;
28mod lifecycle;
29pub mod logging;
30pub mod metrics;
31mod outcome;
32mod panic;
33mod process_metrics;
34mod quota;
35pub use admission::{Admission, admit};
36pub use lifecycle::{Lifecycle, Phase};
37pub use outcome::{finish_outcome, response_limit};
38pub use panic::{contain_panic, panics_total};
39mod router;
40mod server;
41mod startup;
42pub use router::{Router, ServerBlock, ViewFilter};
43pub use server::{Chain, Server};
44pub use startup::startup_domains;
45mod tcp;
46mod udp;
47#[cfg(target_os = "linux")]
48mod udp_linux;
49
50pub trait Next {
52 fn run(self, cx: &mut Context<'_>) -> impl Future<Output = Outcome> + Send;
53}
54
55pub trait Plugin {
57 fn serve<N: Next + Send>(
58 &self,
59 cx: &mut Context<'_>,
60 next: N,
61 ) -> impl Future<Output = Outcome> + Send;
62
63 fn readiness(&self) -> Option<&dyn Readiness> {
65 None
66 }
67}
68
69pub trait Readiness: Send + Sync {
71 fn ready(&self) -> bool;
72}
73
74#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
76pub enum Transport {
77 Dns,
78 Tls,
79 Quic,
80 Grpc,
81 Https,
82 Https3,
83}
84
85#[derive(Clone, Copy, Debug, Eq, PartialEq)]
87pub enum Protocol {
88 Udp,
89 Tcp,
90}
91
92#[derive(Clone, Copy, Debug, Eq, PartialEq)]
94pub struct Stream;
95
96#[derive(Clone, Copy, Debug, Eq, PartialEq)]
98pub enum Outcome {
99 Response,
100 Stream(Stream),
101 Drop,
102 Unanswered(Rcode),
103 Error(Error),
104}
105
106#[derive(Clone, Copy, Debug, Eq, PartialEq)]
108pub enum Error {
109 Build(BuildError),
110 InvalidQuery,
111 ResponseBufferTooSmall,
112 NotImplemented,
113 NoNextPlugin,
114 PluginPanic,
115 SelfLookupDepth,
116 SelfLookupUnavailable,
117 SelfLookupDropped,
118}
119
120impl fmt::Display for Error {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 match self {
123 Self::Build(error) => write!(f, "{error}"),
124 Self::InvalidQuery => f.write_str("invalid Query"),
125 Self::ResponseBufferTooSmall => f.write_str("Response buffer too small"),
126 Self::NotImplemented => f.write_str("plugin is not implemented"),
127 Self::NoNextPlugin => f.write_str("no next plugin found"),
128 Self::PluginPanic => f.write_str("plugin panicked"),
129 Self::SelfLookupDepth => f.write_str("Self Lookup depth exceeded"),
130 Self::SelfLookupUnavailable => f.write_str("no Server available for Self Lookup"),
131 Self::SelfLookupDropped => f.write_str("Self Lookup produced no Response"),
132 }
133 }
134}
135
136impl std::error::Error for Error {}
137
138pub struct Metadata<'a> {
140 slots: &'a mut [Option<(&'a str, &'a str)>],
141 inline_name: Option<&'static str>,
142 inline_value: [u8; 64],
143 inline_len: usize,
144 copied: [Option<(&'static str, usize, usize)>; 12],
146 copied_data: [u8; 1024],
147 copied_len: usize,
148 source: Option<Arc<dyn MetadataSource>>,
149 enabled: bool,
150 self_lookup: Option<SelfLookupState<'a>>,
151}
152
153impl<'a> Metadata<'a> {
154 pub fn new(slots: &'a mut [Option<(&'a str, &'a str)>]) -> Self {
155 Self {
156 slots,
157 inline_name: None,
158 inline_value: [0; 64],
159 inline_len: 0,
160 copied: [None; 12],
161 copied_data: [0; 1024],
162 copied_len: 0,
163 source: None,
164 enabled: true,
165 self_lookup: None,
166 }
167 }
168
169 pub fn set_source(&mut self, source: Arc<dyn MetadataSource>) {
171 self.source = Some(source);
172 }
173
174 pub fn set_enabled(&mut self, enabled: bool) {
176 self.enabled = enabled;
177 }
178
179 #[must_use]
180 pub fn enabled(&self) -> bool {
181 self.enabled
182 }
183
184 pub fn with_self_lookup(
186 slots: &'a mut [Option<(&'a str, &'a str)>],
187 handle: Option<&'a SelfLookupHandle>,
188 ) -> Self {
189 let mut metadata = Self::new(slots);
190 metadata.self_lookup = handle.map(|handle| SelfLookupState {
191 server: handle,
192 depth: handle.depth,
193 });
194 metadata
195 }
196
197 pub fn insert(&mut self, name: &'a str, value: &'a str) -> bool {
199 let slot = self
200 .slots
201 .iter()
202 .position(|slot| slot.is_some_and(|(existing, _)| existing == name))
203 .or_else(|| self.slots.iter().position(Option::is_none));
204 let Some(slot) = slot else { return false };
205 self.remove_copied(name);
206 if self.inline_name == Some(name) {
207 self.inline_name = None;
208 }
209 self.slots[slot] = Some((name, value));
210 true
211 }
212
213 pub fn insert_inline(&mut self, name: &'static str, value: &str) -> bool {
215 if value.len() > self.inline_value.len()
216 || self.inline_name.is_some_and(|existing| existing != name)
217 {
218 return false;
219 }
220 self.remove_copied(name);
221 for slot in self.slots.iter_mut() {
222 if slot.is_some_and(|(key, _)| key == name) {
223 *slot = None;
224 }
225 }
226 self.inline_name = Some(name);
228 self.inline_len = value.len();
229 self.inline_value[..value.len()].copy_from_slice(value.as_bytes());
230 true
231 }
232
233 pub fn insert_copied(&mut self, name: &'static str, value: &str) -> bool {
235 let previous = self
236 .copied
237 .iter()
238 .flatten()
239 .find(|(key, _, _)| *key == name)
240 .map_or(0, |(_, start, end)| end - start);
241 if value.len() > self.copied_data.len() - (self.copied_len - previous) {
242 return false;
243 }
244 let Some(index) = self
245 .copied
246 .iter()
247 .position(|slot| slot.is_none_or(|(key, _, _)| key == name))
248 else {
249 return false;
250 };
251 self.remove_copied(name);
252 if self.inline_name == Some(name) {
253 self.inline_name = None;
254 }
255 for slot in self.slots.iter_mut() {
256 if slot.is_some_and(|(key, _)| key == name) {
257 *slot = None;
258 }
259 }
260 let end = self.copied_len + value.len();
261 self.copied_data[self.copied_len..end].copy_from_slice(value.as_bytes());
262 self.copied[index] = Some((name, self.copied_len, end));
263 self.copied_len = end;
264 true
265 }
266
267 fn remove_copied(&mut self, name: &str) {
268 let Some(index) = self
269 .copied
270 .iter()
271 .position(|slot| slot.is_some_and(|(key, _, _)| key == name))
272 else {
273 return;
274 };
275 let (_, start, end) = self.copied[index].take().unwrap();
276 self.copied_data.copy_within(end..self.copied_len, start);
277 self.copied_len -= end - start;
278 for (_, other_start, other_end) in self.copied.iter_mut().flatten() {
279 if *other_start >= end {
280 *other_start -= end - start;
281 *other_end -= end - start;
282 }
283 }
284 }
285
286 #[must_use]
287 pub fn get(&self, name: &str) -> Option<&str> {
288 if let Some((_, start, end)) = self
289 .copied
290 .iter()
291 .flatten()
292 .find(|(key, _, _)| *key == name)
293 {
294 return std::str::from_utf8(&self.copied_data[*start..*end]).ok();
295 }
296 if self.inline_name == Some(name) {
297 return std::str::from_utf8(&self.inline_value[..self.inline_len]).ok();
298 }
299 self.slots
300 .iter()
301 .flatten()
302 .find_map(|(key, value)| (*key == name).then_some(*value))
303 .or_else(|| self.source.as_ref().and_then(|source| source.get(name)))
304 }
305}
306
307pub trait MetadataSource: Send + Sync {
309 fn get(&self, label: &str) -> Option<&str>;
310}
311
312pub struct Context<'a> {
314 pub query: Message<'a>,
315 pub client: SocketAddr,
316 pub local: SocketAddr,
318 pub transport: Transport,
319 pub protocol: Protocol,
320 pub domain: &'a Name,
321 pub metadata: Metadata<'a>,
322 pub response: &'a mut Vec<u8>,
323 pub max_response_size: usize,
324}
325
326struct SelfLookupState<'a> {
328 server: &'a dyn SelfLookupServer,
329 depth: u8,
330}
331
332trait SelfLookupServer: Sync {
334 fn lookup<'a>(
335 &'a self,
336 wire: &'a [u8],
337 peer: SocketAddr,
338 protocol: Protocol,
339 depth: u8,
340 response: &'a mut Vec<u8>,
341 ) -> Pin<Box<dyn Future<Output = Action> + Send + 'a>>;
342
343 fn owned(&self) -> Option<Arc<dyn OwnedSelfLookupServer>> {
344 None
345 }
346}
347
348trait OwnedSelfLookupServer: Send + Sync {
349 fn lookup<'a>(
350 self: Arc<Self>,
351 wire: &'a [u8],
352 peer: SocketAddr,
353 protocol: Protocol,
354 depth: u8,
355 response: &'a mut Vec<u8>,
356 ) -> Pin<Box<dyn Future<Output = Action> + Send + 'a>>;
357}
358
359pub struct SelfLookupHandle {
361 server: Arc<dyn OwnedSelfLookupServer>,
362 depth: u8,
363}
364
365impl SelfLookupServer for SelfLookupHandle {
366 fn lookup<'a>(
367 &'a self,
368 wire: &'a [u8],
369 peer: SocketAddr,
370 protocol: Protocol,
371 depth: u8,
372 response: &'a mut Vec<u8>,
373 ) -> Pin<Box<dyn Future<Output = Action> + Send + 'a>> {
374 Arc::clone(&self.server).lookup(wire, peer, protocol, depth, response)
375 }
376
377 fn owned(&self) -> Option<Arc<dyn OwnedSelfLookupServer>> {
378 Some(Arc::clone(&self.server))
379 }
380}
381
382impl Context<'_> {
383 pub fn self_lookup_handle(&self) -> Option<SelfLookupHandle> {
385 let state = self.metadata.self_lookup.as_ref()?;
386 Some(SelfLookupHandle {
387 server: state.server.owned()?,
388 depth: state.depth,
389 })
390 }
391
392 pub async fn self_lookup(&self, name: &Name, qtype: Type) -> Result<Vec<u8>, Error> {
394 let state = self
395 .metadata
396 .self_lookup
397 .as_ref()
398 .ok_or(Error::SelfLookupUnavailable)?;
399 if state.depth >= 10 {
400 return Err(Error::SelfLookupDepth);
401 }
402 let query = self
403 .query
404 .with_question(name, qtype)
405 .map_err(Error::Build)?;
406 let mut response = Vec::with_capacity(usize::from(u16::MAX));
407 match state
408 .server
409 .lookup(
410 &query,
411 self.client,
412 self.protocol,
413 state.depth + 1,
414 &mut response,
415 )
416 .await
417 {
418 Action::Respond => Ok(response),
419 Action::Drop => Err(Error::SelfLookupDropped),
420 }
421 }
422}
423
424#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
425pub struct ListenerKey {
426 pub transport: Transport,
427 pub address: SocketAddr,
428}
429
430fn canonical_peer(mut peer: SocketAddr) -> SocketAddr {
431 let ip = peer.ip().to_canonical();
432 if ip != peer.ip() {
433 peer.set_ip(ip);
434 }
435 peer
436}
437
438#[derive(Clone, Copy, Debug, Eq, PartialEq)]
439pub enum Action {
440 Respond,
441 Drop,
442}
443
444pub trait Handler: Send + Sync + 'static {
449 fn udp_workers(&self) -> usize {
451 quota::worker_count()
452 }
453 fn parallel_query(&self, _query: &[u8], _peer: SocketAddr) -> Option<watch::Receiver<bool>> {
455 None
456 }
457 fn handle(
458 &self,
459 query: &[u8],
460 peer: SocketAddr,
461 protocol: Protocol,
462 response: &mut Vec<u8>,
463 ) -> impl Future<Output = Action> + Send;
464
465 fn handle_shared(
467 self: &Arc<Self>,
468 query: &[u8],
469 peer: SocketAddr,
470 protocol: Protocol,
471 response: &mut Vec<u8>,
472 ) -> impl Future<Output = Action> + Send {
473 self.handle(query, peer, protocol, response)
474 }
475}
476
477pub struct Listener {
479 address: SocketAddr,
480 stop: watch::Sender<bool>,
481 tasks: Vec<JoinHandle<io::Result<()>>>,
482 udp_stop: watch::Sender<bool>,
483 udp_tasks: Vec<JoinHandle<io::Result<()>>>,
484}
485
486impl Listener {
487 pub async fn bind<H: Handler>(address: SocketAddr, handler: H) -> io::Result<Self> {
488 let workers = handler.udp_workers();
489 Self::bind_with_ipv6(address, handler, workers, bind_ipv6_dual, udp::bind).await
490 }
491
492 async fn bind_with_ipv6<H: Handler>(
493 address: SocketAddr,
494 handler: H,
495 workers: usize,
496 bind_ipv6: fn(SocketAddr) -> io::Result<TcpListener>,
497 bind_udp: fn(SocketAddr) -> io::Result<std::net::UdpSocket>,
498 ) -> io::Result<Self> {
499 let wildcard = address.is_ipv6() && address.ip().is_unspecified();
500 let mut ipv4_only = false;
501 let mut attempts = if address.port() == 0 { 16 } else { 1 };
503 let (tcp, address, sockets) = loop {
505 let tcp = if wildcard && !ipv4_only {
506 match optional_ipv6(bind_ipv6(address)) {
507 Ok(Some(tcp)) => tcp,
508 Ok(None) => {
509 ipv4_only = true;
510 continue;
511 }
512 Err(error) if error.kind() == io::ErrorKind::AddrInUse && attempts > 1 => {
513 attempts -= 1;
514 continue;
515 }
516 Err(error) => return Err(error),
517 }
518 } else if ipv4_only {
519 TcpListener::bind((Ipv4Addr::UNSPECIFIED, address.port())).await?
520 } else {
521 TcpListener::bind(address).await?
522 };
523 let bound = tcp.local_addr()?;
524 let sockets = (0..workers)
525 .map(|_| bind_udp(bound))
526 .collect::<io::Result<Vec<_>>>();
527 match sockets {
528 Ok(sockets) => break (tcp, bound, sockets),
529 Err(error) if wildcard && bound.is_ipv6() && ipv6_unavailable(&error) => {
530 ipv4_only = true;
531 }
532 Err(error) if error.kind() == io::ErrorKind::AddrInUse && attempts > 1 => {
533 attempts -= 1;
534 }
535 Err(error) => return Err(error),
536 }
537 };
538 let (stop, receiver) = watch::channel(false);
539 let (udp_stop, udp_receiver) = watch::channel(false);
540 let handler = Arc::new(handler);
541 let udp_tasks = sockets
542 .into_iter()
543 .map(|socket| {
544 let socket = UdpSocket::from_std(socket)?;
545 Ok(udp::spawn(
546 socket,
547 Arc::clone(&handler),
548 udp_receiver.clone(),
549 ))
550 })
551 .collect::<io::Result<Vec<_>>>()?;
552 let tasks = vec![tcp::spawn(tcp, handler, receiver)];
553 Ok(Self {
554 address,
555 stop,
556 tasks,
557 udp_stop,
558 udp_tasks,
559 })
560 }
561
562 pub fn local_addr(&self) -> SocketAddr {
563 self.address
564 }
565
566 pub async fn shutdown(mut self) -> io::Result<()> {
568 self.stop.send_replace(true);
569 self.udp_stop.send_replace(true);
570 self.tasks.append(&mut self.udp_tasks);
571 let mut result = Ok(());
572 let deadline = tokio::time::Instant::now() + Duration::from_secs(5);
573 while let Some(mut task) = self.tasks.pop() {
574 match tokio::time::timeout_at(deadline, &mut task).await {
575 Ok(next) => {
576 let next = next.map_err(io::Error::other).and_then(|v| v);
577 if result.is_ok() {
578 result = next;
579 }
580 }
581 Err(_) => {
582 task.abort();
583 for task in &self.tasks {
584 task.abort();
585 }
586 let _ = task.await;
587 for task in self.tasks.drain(..) {
588 let _ = task.await;
589 }
590 break;
591 }
592 }
593 }
594 result
595 }
596}
597
598fn bind_ipv6_dual(address: SocketAddr) -> io::Result<TcpListener> {
599 let socket = socket2::Socket::new(
600 socket2::Domain::IPV6,
601 socket2::Type::STREAM,
602 Some(socket2::Protocol::TCP),
603 )?;
604 socket.set_only_v6(false)?;
605 socket.set_reuse_address(true)?;
606 socket.set_nonblocking(true)?;
607 socket.bind(&address.into())?;
608 socket.listen(1024)?;
609 TcpListener::from_std(socket.into())
610}
611
612fn optional_ipv6<T>(result: io::Result<T>) -> io::Result<Option<T>> {
613 match result {
614 Ok(value) => Ok(Some(value)),
615 Err(error) if ipv6_unavailable(&error) => Ok(None),
616 Err(error) => Err(error),
617 }
618}
619
620fn ipv6_unavailable(error: &io::Error) -> bool {
621 error.kind() == io::ErrorKind::AddrNotAvailable
622 || error.raw_os_error() == Some(libc::EAFNOSUPPORT)
623}
624
625#[cfg(test)]
626mod wildcard_tests {
627 use super::{
628 Action, Handler, Listener, Protocol, bind_ipv6_dual, canonical_peer, optional_ipv6, udp,
629 };
630 use std::{
631 io,
632 net::{Ipv6Addr, SocketAddr, SocketAddrV6},
633 };
634
635 #[test]
636 fn canonical_peer_preserves_native_ipv6_scope() {
637 let scoped = SocketAddr::V6(SocketAddrV6::new(
638 "fe80::1".parse::<Ipv6Addr>().unwrap(),
639 53,
640 7,
641 3,
642 ));
643 assert_eq!(canonical_peer(scoped), scoped);
644 assert_eq!(
645 canonical_peer("[::ffff:127.0.0.1]:53".parse().unwrap()),
646 "127.0.0.1:53".parse().unwrap()
647 );
648 }
649
650 #[test]
651 fn unavailable_ipv6_falls_back_but_other_errors_remain_errors() {
652 assert_eq!(
653 optional_ipv6::<()>(Err(io::Error::from_raw_os_error(libc::EAFNOSUPPORT))).unwrap(),
654 None
655 );
656 assert_eq!(
657 optional_ipv6::<()>(Err(io::Error::from(io::ErrorKind::AddrNotAvailable))).unwrap(),
658 None
659 );
660 assert_eq!(optional_ipv6(Ok(7)).unwrap(), Some(7));
661 assert!(
662 optional_ipv6::<()>(Err(io::Error::new(io::ErrorKind::AddrInUse, "occupied"))).is_err()
663 );
664 }
665
666 struct Echo;
667 impl Handler for Echo {
668 async fn handle(
669 &self,
670 query: &[u8],
671 _: SocketAddr,
672 _: Protocol,
673 response: &mut Vec<u8>,
674 ) -> Action {
675 response.extend_from_slice(query);
676 Action::Respond
677 }
678 }
679
680 #[tokio::test]
681 async fn listener_binds_the_requested_number_of_udp_sockets() {
682 use std::sync::atomic::{AtomicUsize, Ordering};
683 static BINDS: AtomicUsize = AtomicUsize::new(0);
684 fn counting_bind(address: SocketAddr) -> io::Result<std::net::UdpSocket> {
685 BINDS.fetch_add(1, Ordering::SeqCst);
686 udp::bind(address)
687 }
688 let listener = Listener::bind_with_ipv6(
689 "127.0.0.1:0".parse().unwrap(),
690 Echo,
691 3,
692 bind_ipv6_dual,
693 counting_bind,
694 )
695 .await
696 .unwrap();
697 assert_eq!(BINDS.load(Ordering::SeqCst), 3);
698 listener.shutdown().await.unwrap();
699 }
700
701 #[tokio::test]
702 async fn reload_replaces_only_changed_udp_workers_and_keeps_tcp() {
703 use std::collections::HashMap;
704 use tokio::io::{AsyncReadExt, AsyncWriteExt};
705 struct Counted(usize, u8);
706 impl Handler for Counted {
707 fn udp_workers(&self) -> usize {
708 self.0
709 }
710 async fn handle(
711 &self,
712 _: &[u8],
713 _: SocketAddr,
714 _: Protocol,
715 response: &mut Vec<u8>,
716 ) -> Action {
717 response.push(self.1);
718 Action::Respond
719 }
720 }
721 let key = super::ListenerKey {
722 transport: super::Transport::Dns,
723 address: "127.0.0.1:0".parse().unwrap(),
724 };
725 let mut registry = super::ListenerRegistry::default();
726 registry
727 .apply(HashMap::from([(key, Counted(2, 1))]))
728 .await
729 .unwrap();
730 let listener = registry.get(&key).unwrap();
731 let address = listener.local_addr();
732 let ids: Vec<_> = listener
733 .udp_tasks
734 .iter()
735 .map(tokio::task::JoinHandle::id)
736 .collect();
737 assert_eq!(ids.len(), 2);
738 let mut tcp = tokio::net::TcpStream::connect(address).await.unwrap();
739 registry
740 .apply(HashMap::from([(key, Counted(2, 2))]))
741 .await
742 .unwrap();
743 assert_eq!(
744 registry
745 .get(&key)
746 .unwrap()
747 .udp_tasks
748 .iter()
749 .map(tokio::task::JoinHandle::id)
750 .collect::<Vec<_>>(),
751 ids
752 );
753 registry
754 .apply(HashMap::from([(key, Counted(3, 3))]))
755 .await
756 .unwrap();
757 let listener = registry.get(&key).unwrap();
758 assert_eq!(listener.local_addr(), address);
759 let new_ids: Vec<_> = listener
760 .udp_tasks
761 .iter()
762 .map(tokio::task::JoinHandle::id)
763 .collect();
764 assert_eq!(new_ids.len(), 3);
765 assert!(new_ids.iter().all(|id| !ids.contains(id)));
766 tcp.write_all(&[0, 1, 42]).await.unwrap();
767 let mut response = [0; 3];
768 tcp.read_exact(&mut response).await.unwrap();
769 assert_eq!(response, [0, 1, 3]);
770 let udp = tokio::net::UdpSocket::bind("127.0.0.1:0").await.unwrap();
771 udp.send_to(b"q", address).await.unwrap();
772 let mut byte = [0];
773 tokio::time::timeout(std::time::Duration::from_secs(2), udp.recv(&mut byte))
774 .await
775 .unwrap()
776 .unwrap();
777 assert_eq!(byte, [3]);
778 tokio::time::timeout(std::time::Duration::from_secs(2), async {
779 while registry
780 .get(&key)
781 .unwrap()
782 .tasks
783 .iter()
784 .skip(1)
785 .any(|task| !task.is_finished())
786 {
787 tokio::task::yield_now().await;
788 }
789 })
790 .await
791 .unwrap();
792 registry
793 .apply(HashMap::from([(key, Counted(1, 4))]))
794 .await
795 .unwrap();
796 let listener = registry.get(&key).unwrap();
797 assert_eq!(listener.udp_tasks.len(), 1);
798 assert_eq!(
799 listener.tasks.len(),
800 4,
801 "completed workers should be reaped"
802 );
803 drop(tcp);
804 registry.shutdown().await.unwrap();
805 }
806
807 async fn assert_ipv4_fallback(listener: Listener) {
808 use tokio::io::{AsyncReadExt, AsyncWriteExt};
809 assert!(listener.local_addr().is_ipv4());
810 let socket = tokio::net::UdpSocket::bind("127.0.0.1:0").await.unwrap();
811 socket
812 .send_to(b"query", ("127.0.0.1", listener.local_addr().port()))
813 .await
814 .unwrap();
815 let mut response = [0; 16];
816 let (len, _) = tokio::time::timeout(
817 std::time::Duration::from_secs(2),
818 socket.recv_from(&mut response),
819 )
820 .await
821 .unwrap()
822 .unwrap();
823 assert_eq!(&response[..len], b"query");
824 let mut tcp = tokio::net::TcpStream::connect(("127.0.0.1", listener.local_addr().port()))
825 .await
826 .unwrap();
827 tcp.write_u16(5).await.unwrap();
828 tcp.write_all(b"query").await.unwrap();
829 let len = tokio::time::timeout(std::time::Duration::from_secs(2), tcp.read_u16())
830 .await
831 .unwrap()
832 .unwrap();
833 assert_eq!(len, 5);
834 let mut response = [0; 5];
835 tokio::time::timeout(
836 std::time::Duration::from_secs(2),
837 tcp.read_exact(&mut response),
838 )
839 .await
840 .unwrap()
841 .unwrap();
842 assert_eq!(&response, b"query");
843 drop(tcp);
844 listener.shutdown().await.unwrap();
845 }
846
847 #[tokio::test]
848 async fn wildcard_falls_back_to_ipv4_when_ipv6_tcp_is_unavailable() {
849 fn unavailable(_: SocketAddr) -> io::Result<tokio::net::TcpListener> {
850 Err(io::Error::from_raw_os_error(libc::EAFNOSUPPORT))
851 }
852 let listener =
853 Listener::bind_with_ipv6("[::]:0".parse().unwrap(), Echo, 1, unavailable, udp::bind)
854 .await
855 .unwrap();
856 assert_ipv4_fallback(listener).await;
857 }
858
859 #[tokio::test]
860 async fn wildcard_falls_back_to_ipv4_when_ipv6_udp_is_unavailable() {
861 use std::sync::atomic::{AtomicBool, Ordering};
862
863 static TRIED_IPV6_UDP: AtomicBool = AtomicBool::new(false);
864 if std::net::TcpListener::bind("[::1]:0").is_err() {
865 return;
866 }
867 fn unavailable(address: SocketAddr) -> io::Result<std::net::UdpSocket> {
868 if address.is_ipv6() {
869 TRIED_IPV6_UDP.store(true, Ordering::Relaxed);
870 Err(io::Error::from(io::ErrorKind::AddrNotAvailable))
871 } else {
872 udp::bind(address)
873 }
874 }
875 let listener = Listener::bind_with_ipv6(
876 "[::]:0".parse().unwrap(),
877 Echo,
878 1,
879 bind_ipv6_dual,
880 unavailable,
881 )
882 .await
883 .unwrap();
884 assert!(TRIED_IPV6_UDP.load(Ordering::Relaxed));
885 assert_ipv4_fallback(listener).await;
886 }
887}
888
889impl Drop for Listener {
890 fn drop(&mut self) {
891 self.stop.send_replace(true);
892 self.udp_stop.send_replace(true);
893 }
894}
895
896#[derive(Default)]
897pub struct ListenerRegistry {
898 listeners: HashMap<ListenerKey, Listener>,
899 handlers: HashMap<ListenerKey, Box<dyn Any + Send + Sync>>,
900}
901
902impl ListenerRegistry {
903 pub fn insert(&mut self, key: ListenerKey, listener: Listener) -> Option<Listener> {
904 self.handlers.remove(&key);
905 self.listeners.insert(key, listener)
906 }
907
908 pub fn remove(&mut self, key: &ListenerKey) -> Option<Listener> {
909 self.handlers.remove(key);
910 self.listeners.remove(key)
911 }
912
913 pub fn get(&self, key: &ListenerKey) -> Option<&Listener> {
914 self.listeners.get(key)
915 }
916
917 pub async fn shutdown(mut self) -> io::Result<()> {
919 let mut result = Ok(());
920 for (_, listener) in self.listeners.drain() {
921 if let Err(error) = listener.shutdown().await
922 && result.is_ok()
923 {
924 result = Err(error);
925 }
926 }
927 result
928 }
929
930 pub async fn apply<H: Handler>(
932 &mut self,
933 mut servers: HashMap<ListenerKey, H>,
934 ) -> io::Result<Vec<Arc<H>>> {
935 let desired: HashSet<_> = servers.keys().copied().collect();
936 if desired.iter().any(|key| key.transport != Transport::Dns) {
937 return Err(io::Error::new(
938 io::ErrorKind::InvalidInput,
939 "unsupported Listener transport",
940 ));
941 }
942 for key in servers
943 .keys()
944 .filter(|key| self.listeners.contains_key(key))
945 {
946 if self
947 .handlers
948 .get(key)
949 .and_then(|handler| handler.downcast_ref::<Arc<ArcSwap<H>>>())
950 .is_none()
951 {
952 return Err(io::Error::new(
953 io::ErrorKind::InvalidInput,
954 "Listener handler type mismatch",
955 ));
956 }
957 }
958 let mut added: Vec<(ListenerKey, Listener, Arc<ArcSwap<H>>)> = Vec::new();
959 let new_keys: Vec<_> = servers
960 .keys()
961 .filter(|key| !self.listeners.contains_key(key))
962 .copied()
963 .collect();
964 for key in new_keys {
965 let handler = Arc::new(ArcSwap::from_pointee(
966 servers.remove(&key).expect("new Listener"),
967 ));
968 let listener = match Listener::bind(key.address, Swappable(Arc::clone(&handler))).await
969 {
970 Ok(listener) => listener,
971 Err(error) => {
972 for (_, listener, _) in added {
973 let _: io::Result<()> = listener.shutdown().await;
974 }
975 return Err(io::Error::new(
976 error.kind(),
977 format!("{}: {error}", key.address),
978 ));
979 }
980 };
981 added.push((key, listener, handler));
982 }
983 let mut replacements = Vec::new();
984 for (key, server) in &servers {
985 let listener = &self.listeners[key];
986 let count = server.udp_workers();
987 if count == listener.udp_tasks.len() {
988 continue;
989 }
990 let sockets = (0..count)
991 .map(|_| udp::bind(listener.address).and_then(UdpSocket::from_std))
992 .collect::<io::Result<Vec<_>>>();
993 match sockets {
994 Ok(sockets) => replacements.push((*key, sockets)),
995 Err(error) => {
996 for (_, listener, _) in added {
997 let _: io::Result<()> = listener.shutdown().await;
998 }
999 return Err(io::Error::new(
1000 error.kind(),
1001 format!("{}: {error}", key.address),
1002 ));
1003 }
1004 }
1005 }
1006 let mut retired = Vec::new();
1007 for (key, server) in servers {
1008 retired.push(
1009 self.handlers[&key]
1010 .downcast_ref::<Arc<ArcSwap<H>>>()
1011 .expect("validated handler")
1012 .swap(Arc::new(server)),
1013 );
1014 }
1015 for (key, sockets) in replacements {
1016 let handler = self.handlers[&key]
1017 .downcast_ref::<Arc<ArcSwap<H>>>()
1018 .expect("validated handler");
1019 let handler = Arc::new(Swappable(Arc::clone(handler)));
1020 let listener = self.listeners.get_mut(&key).expect("existing Listener");
1021 for task in listener.tasks.split_off(1) {
1022 if task.is_finished() {
1023 if let Err(error) = task.await.map_err(io::Error::other).and_then(|v| v) {
1024 logging::log("ERROR", "", &format!("UDP worker shutdown: {error}"));
1025 }
1026 } else {
1027 listener.tasks.push(task);
1028 }
1029 }
1030 let (stop, receiver) = watch::channel(false);
1031 let tasks = sockets
1032 .into_iter()
1033 .map(|socket| udp::spawn(socket, Arc::clone(&handler), receiver.clone()))
1034 .collect();
1035 listener.udp_stop.send_replace(true);
1036 listener.tasks.append(&mut listener.udp_tasks);
1037 listener.udp_stop = stop;
1038 listener.udp_tasks = tasks;
1039 }
1040 let removed: Vec<_> = self
1041 .listeners
1042 .keys()
1043 .filter(|key| !desired.contains(key))
1044 .copied()
1045 .collect();
1046 for (key, listener, handler) in added {
1047 self.listeners.insert(key, listener);
1048 self.handlers.insert(key, Box::new(handler));
1049 }
1050 for key in removed {
1051 if let Some(handler) = self
1052 .handlers
1053 .get(&key)
1054 .and_then(|handler| handler.downcast_ref::<Arc<ArcSwap<H>>>())
1055 {
1056 retired.push(handler.load_full());
1057 }
1058 if let Some(listener) = self.remove(&key)
1059 && let Err(error) = listener.shutdown().await
1060 {
1061 logging::log("ERROR", "", &format!("Listener shutdown: {error}"));
1062 }
1063 }
1064 Ok(retired)
1065 }
1066}
1067
1068struct Swappable<H>(Arc<ArcSwap<H>>);
1069
1070impl<H: Handler> Handler for Swappable<H> {
1071 fn udp_workers(&self) -> usize {
1072 self.0.load().udp_workers()
1073 }
1074 fn parallel_query(&self, query: &[u8], peer: SocketAddr) -> Option<watch::Receiver<bool>> {
1075 self.0.load().parallel_query(query, peer)
1076 }
1077 async fn handle(
1078 &self,
1079 query: &[u8],
1080 peer: SocketAddr,
1081 protocol: Protocol,
1082 response: &mut Vec<u8>,
1083 ) -> Action {
1084 let handler = self.0.load();
1085 H::handle_shared(&handler, query, peer, protocol, response).await
1086 }
1087}