1mod engine;
4#[cfg(feature = "reactor")]
5mod reactor;
6mod source;
7
8use std::any::TypeId;
9use std::fmt;
10use std::net::{SocketAddr, ToSocketAddrs};
11use std::path::PathBuf;
12use std::sync::Arc;
13use std::thread::JoinHandle;
14use std::time::{Duration, Instant};
15
16use crate::control::ControlLine;
17use crate::driver::DriverKind;
18use crate::error::{CloseReason, ConfigReason, KillReason, NetError, RefusalCause};
19use crate::events::{EventSink, NoopSink};
20use crate::gate::Gate;
21use crate::handoff::ListenerHandle;
22use crate::id::{ConnectionId, ListenerId, WorkerId};
23use crate::limits::Limits;
24use crate::opts::{ListenOptions, LocalOptions};
25use crate::proxy::ProxyMode;
26use crate::session::SessionFactory;
27use crate::tcp::{ListenerInfo, TcpConnection};
28use crate::time::Clock;
29use crate::tls::ErasedAcceptor;
30use crate::tls::{NoTls, TlsAcceptor};
31use crate::trusted::TrustedProxies;
32
33pub(crate) use engine::Shared;
34
35#[derive(Clone, Copy, Debug, PartialEq, Eq)]
41pub enum DoorState {
42 Open,
44 Closed,
46}
47
48#[derive(Clone, Copy, Debug, PartialEq, Eq)]
55pub struct DrainReport {
56 pub graceful: u32,
58 pub killed: u32,
60 pub took: Duration,
62}
63
64#[non_exhaustive]
73#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
74pub struct Stats {
75 pub open: u64,
77 pub accepted: u64,
79 pub refused: u64,
81 pub closed: u64,
83 pub bytes_in: u64,
85 pub bytes_out: u64,
87 pub egress_denied: u64,
89 pub killed: u64,
91 pub slow_peers: u64,
93 pub timeouts: u64,
95 pub descriptor_pressure: u64,
97 pub stale_completions: u64,
99 pub session_panics: u64,
101 refused_by: [u64; RefusalCause::COUNT],
102 closed_by: [u64; CloseReason::COUNT],
103}
104
105impl Stats {
106 #[must_use]
108 pub fn refused_for(&self, cause: RefusalCause) -> u64 {
109 self.refused_by[cause.index()]
110 }
111
112 #[must_use]
114 pub fn closed_for(&self, reason: CloseReason) -> u64 {
115 self.closed_by[reason.index()]
116 }
117
118 pub fn closes(&self) -> impl Iterator<Item = (CloseReason, u64)> + '_ {
129 CloseReason::BY_INDEX
130 .iter()
131 .zip(self.closed_by.iter())
132 .filter(|(_, n)| **n > 0)
133 .map(|(r, n)| (*r, *n))
134 }
135
136 pub fn refusals(&self) -> impl Iterator<Item = (RefusalCause, u64)> + '_ {
138 RefusalCause::BY_INDEX
139 .iter()
140 .zip(self.refused_by.iter())
141 .filter(|(_, n)| **n > 0)
142 .map(|(r, n)| (*r, *n))
143 }
144}
145
146#[must_use]
157#[derive(Debug)]
158pub struct ListenerSpec {
159 pub(crate) addrs: Result<Vec<SocketAddr>, String>,
160 pub(crate) options: Option<ListenOptions>,
161 pub(crate) name: Option<String>,
162 pub(crate) limits: Limits,
163 pub(crate) proxy: ProxyMode,
164 pub(crate) trusted: Option<Arc<TrustedProxies>>,
165 pub(crate) tls: bool,
166 pub(crate) unix: Option<(PathBuf, LocalOptions)>,
167 #[cfg(all(windows, feature = "local"))]
168 pub(crate) pipe: Option<(String, crate::pipe::PipeOptions)>,
169 #[cfg(feature = "udp")]
170 pub(crate) udp: Option<crate::udp::UdpOptions>,
171 pub(crate) adopt: Option<ListenerHandle>,
172 pub(crate) lockdown_allowed: bool,
173}
174
175impl ListenerSpec {
176 pub fn tcp<A: ToSocketAddrs>(addr: A) -> ListenerSpec {
178 ListenerSpec {
179 addrs: addr
180 .to_socket_addrs()
181 .map(|i| i.collect())
182 .map_err(|e| e.to_string()),
183 options: None,
184 name: None,
185 limits: Limits::default(),
186 proxy: ProxyMode::Off,
187 trusted: None,
188 tls: false,
189 unix: None,
190 #[cfg(all(windows, feature = "local"))]
191 pipe: None,
192 #[cfg(feature = "udp")]
193 udp: None,
194 adopt: None,
195 lockdown_allowed: false,
196 }
197 }
198
199 pub fn lockdown_allowed(mut self, on: bool) -> ListenerSpec {
202 self.lockdown_allowed = on;
203 self
204 }
205
206 pub fn tcp_with<A: ToSocketAddrs>(addr: A, options: ListenOptions) -> ListenerSpec {
208 ListenerSpec {
209 options: Some(options),
210 ..ListenerSpec::tcp(addr)
211 }
212 }
213
214 #[cfg(feature = "udp")]
225 pub fn udp<A: ToSocketAddrs>(addr: A, options: crate::udp::UdpOptions) -> ListenerSpec {
226 ListenerSpec {
227 udp: Some(options),
228 ..ListenerSpec::tcp(addr)
229 }
230 }
231
232 #[cfg(all(windows, feature = "local"))]
243 pub fn pipe(name: &str, options: crate::pipe::PipeOptions) -> ListenerSpec {
244 ListenerSpec {
245 pipe: Some((name.to_owned(), options)),
246 ..ListenerSpec::tcp(std::net::SocketAddr::from(([127, 0, 0, 1], 0)))
247 }
248 }
249
250 pub fn unix(path: impl Into<PathBuf>, options: LocalOptions) -> ListenerSpec {
265 ListenerSpec {
266 addrs: Ok(Vec::new()),
267 options: None,
268 name: None,
269 limits: Limits::default(),
270 proxy: ProxyMode::Off,
271 trusted: None,
272 tls: false,
273 unix: Some((path.into(), options)),
274 lockdown_allowed: false,
275 #[cfg(all(windows, feature = "local"))]
276 pipe: None,
277 #[cfg(feature = "udp")]
278 udp: None,
279 adopt: None,
280 }
281 }
282
283 pub fn adopt(handle: ListenerHandle) -> ListenerSpec {
299 ListenerSpec {
300 addrs: Ok(Vec::new()),
301 options: None,
302 name: None,
303 limits: Limits::default(),
304 proxy: ProxyMode::Off,
305 trusted: None,
306 tls: false,
307 unix: None,
308 #[cfg(all(windows, feature = "local"))]
309 pipe: None,
310 #[cfg(feature = "udp")]
311 udp: None,
312 adopt: Some(handle),
313 lockdown_allowed: false,
314 }
315 }
316
317 pub fn name(mut self, name: &str) -> ListenerSpec {
319 self.name = Some(name.to_owned());
320 self
321 }
322
323 pub fn limits(mut self, limits: Limits) -> ListenerSpec {
325 self.limits = limits;
326 self
327 }
328
329 pub fn proxy(mut self, mode: ProxyMode) -> ListenerSpec {
338 self.proxy = mode;
339 self
340 }
341
342 pub fn tls(mut self, on: bool) -> ListenerSpec {
345 self.tls = on;
346 self
347 }
348
349 pub fn trusted_proxies(mut self, proxies: TrustedProxies) -> ListenerSpec {
351 self.trusted = Some(Arc::new(proxies));
352 self
353 }
354}
355
356#[derive(Clone, Copy, Debug, Default)]
358pub struct NoWork;
359
360#[cfg(feature = "udp")]
363#[derive(Debug)]
364pub struct UdpOnly;
365
366#[derive(Clone, Copy, Debug, Default)]
368pub struct NoGate;
369
370#[non_exhaustive]
377#[derive(Clone, Debug, Default, PartialEq, Eq)]
378pub enum Placement {
379 #[default]
381 Off,
382 PinPerCore,
384 Explicit(Vec<usize>),
386}
387
388#[derive(Debug)]
390pub struct Sessions<F> {
391 pub(crate) factory: F,
392}
393
394#[cfg(feature = "reactor")]
395impl<F> Sessions<F> {
396 pub(crate) fn factory(&self) -> &F {
397 &self.factory
398 }
399}
400
401pub struct BlockingHandler<H> {
403 pub(crate) handler: H,
404}
405
406impl<H> fmt::Debug for BlockingHandler<H> {
407 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
408 f.write_str("BlockingHandler")
409 }
410}
411
412pub(crate) mod sealed {
413 pub trait Sealed {}
414}
415
416pub trait Workload: sealed::Sealed + engine::Serve + Send + Sync + 'static {}
418
419#[cfg(feature = "udp")]
420impl sealed::Sealed for UdpOnly {}
421#[cfg(feature = "udp")]
422impl Workload for UdpOnly {}
423
424impl<F: SessionFactory> sealed::Sealed for Sessions<F> {}
425impl<F: SessionFactory> Workload for Sessions<F> {}
426
427impl<H> sealed::Sealed for BlockingHandler<H> where
428 H: Fn(&mut TcpConnection) -> Result<(), NetError> + Send + Sync + 'static
429{
430}
431impl<H> Workload for BlockingHandler<H> where
432 H: Fn(&mut TcpConnection) -> Result<(), NetError> + Send + Sync + 'static
433{
434}
435
436#[must_use]
461pub struct ServerBuilder<W = NoWork, G = NoGate, S = NoopSink, T = NoTls> {
462 listeners: Vec<ListenerSpec>,
463 driver: DriverKind,
464 workers: Option<u16>,
465 limits: Limits,
466 work: W,
467 gate: G,
468 sink: S,
469 tls: T,
470 control: Option<Arc<dyn ControlLine>>,
471 wipe: bool,
472 clock: Option<Arc<dyn Clock>>,
473 trusted: Option<Arc<TrustedProxies>>,
474 placement: Placement,
475 #[cfg(feature = "udp")]
476 udp: Option<Arc<dyn crate::udp::UdpSessionFactory>>,
477}
478
479impl ServerBuilder {
480 pub fn new() -> ServerBuilder {
482 ServerBuilder {
483 listeners: Vec::new(),
484 driver: DriverKind::Auto,
485 workers: None,
486 limits: Limits::default(),
487 work: NoWork,
488 gate: NoGate,
489 sink: NoopSink,
490 tls: NoTls,
491 control: None,
492 wipe: true,
493 clock: None,
494 trusted: None,
495 placement: Placement::Off,
496 #[cfg(feature = "udp")]
497 udp: None,
498 }
499 }
500}
501
502impl Default for ServerBuilder {
503 fn default() -> ServerBuilder {
504 ServerBuilder::new()
505 }
506}
507
508impl<W, G, S, T> ServerBuilder<W, G, S, T> {
509 fn map<W2, G2, S2, T2>(
510 self,
511 f: impl FnOnce(W, G, S, T) -> (W2, G2, S2, T2),
512 ) -> ServerBuilder<W2, G2, S2, T2> {
513 let ServerBuilder {
514 listeners,
515 driver,
516 workers,
517 limits,
518 work,
519 gate,
520 sink,
521 tls,
522 control,
523 wipe,
524 clock,
525 trusted,
526 placement,
527 #[cfg(feature = "udp")]
528 udp,
529 } = self;
530 let (work, gate, sink, tls) = f(work, gate, sink, tls);
531 ServerBuilder {
532 listeners,
533 driver,
534 workers,
535 limits,
536 work,
537 gate,
538 sink,
539 tls,
540 control,
541 wipe,
542 clock,
543 trusted,
544 placement,
545 #[cfg(feature = "udp")]
546 udp,
547 }
548 }
549
550 pub fn trusted_proxies(mut self, proxies: TrustedProxies) -> Self {
553 self.trusted = Some(Arc::new(proxies));
554 self
555 }
556
557 pub fn listener(mut self, spec: ListenerSpec) -> Self {
559 self.listeners.push(spec);
560 self
561 }
562
563 pub fn driver(mut self, kind: DriverKind) -> Self {
565 self.driver = kind;
566 self
567 }
568
569 pub fn placement(mut self, placement: Placement) -> Self {
572 self.placement = placement;
573 self
574 }
575
576 pub fn workers(mut self, n: u16) -> Self {
578 self.workers = Some(n);
579 self
580 }
581
582 pub fn limits(mut self, limits: Limits) -> Self {
584 self.limits = limits;
585 self
586 }
587
588 pub fn sessions<F: SessionFactory>(self, factory: F) -> ServerBuilder<Sessions<F>, G, S, T> {
590 self.map(|_, g, s, t| (Sessions { factory }, g, s, t))
591 }
592
593 pub fn handler<H>(self, handler: H) -> ServerBuilder<BlockingHandler<H>, G, S, T>
595 where
596 H: Fn(&mut TcpConnection) -> Result<(), NetError> + Send + Sync + 'static,
597 {
598 self.map(|_, g, s, t| (BlockingHandler { handler }, g, s, t))
599 }
600
601 pub fn tls<T2: TlsAcceptor>(self, acceptor: T2) -> ServerBuilder<W, G, S, T2> {
603 self.map(|w, g, s, _| (w, g, s, acceptor))
604 }
605
606 pub fn gate<G2: Gate>(self, gate: G2) -> ServerBuilder<W, G2, S, T> {
608 self.map(|w, _, s, t| (w, gate, s, t))
609 }
610
611 pub fn events<S2: EventSink>(self, sink: S2) -> ServerBuilder<W, G, S2, T> {
613 self.map(|w, g, _, t| (w, g, sink, t))
614 }
615
616 pub fn control<C: ControlLine>(mut self, line: Arc<C>) -> Self {
618 self.control = Some(line);
619 self
620 }
621
622 pub fn wipe_buffers(mut self, on: bool) -> Self {
624 self.wipe = on;
625 self
626 }
627
628 pub fn clock<K: Clock>(mut self, clock: Arc<K>) -> Self {
630 self.clock = Some(clock);
631 self
632 }
633}
634
635#[cfg(feature = "udp")]
636impl<G, S, T> ServerBuilder<NoWork, G, S, T> {
637 pub fn udp_sessions<F>(self, factory: F) -> ServerBuilder<UdpOnly, G, S, T>
658 where
659 F: crate::udp::UdpSessionFactory,
660 {
661 let mut b = self.map(|_, g, s, t| (UdpOnly, g, s, t));
662 b.udp = Some(Arc::new(factory));
663 b.workers.get_or_insert(1);
664 b
665 }
666}
667
668#[cfg(feature = "udp")]
669impl<W: Workload, G, S, T> ServerBuilder<W, G, S, T> {
670 pub fn udp_sessions<F>(mut self, factory: F) -> Self
672 where
673 F: crate::udp::UdpSessionFactory,
674 {
675 self.udp = Some(Arc::new(factory));
676 self
677 }
678}
679
680impl<W, G, S, T> ServerBuilder<W, G, S, T>
681where
682 W: Workload,
683 G: Gate,
684 S: EventSink,
685 T: TlsAcceptor,
686{
687 pub fn build(self) -> Result<Server, NetError> {
695 let requested = match self.driver {
697 DriverKind::Auto if <W as engine::Serve>::BLOCKING_ONLY => DriverKind::Blocking,
698 other => other,
699 };
700 let driver = match requested.resolve() {
701 DriverKind::Reactor if <W as engine::Serve>::BLOCKING_ONLY => {
702 return Err(invalid("driver", ConfigReason::Inconsistent));
703 }
704 DriverKind::Reactor if !DriverKind::reactor_built() => {
705 return Err(NetError::Unsupported {
706 feature: "the reactor driver",
707 platform: std::env::consts::OS,
708 });
709 }
710 DriverKind::Uring => {
711 return Err(NetError::Unsupported {
712 feature: "the io_uring driver (after 1.0.0)",
713 platform: std::env::consts::OS,
714 });
715 }
716 kind => kind,
717 };
718 if self.listeners.is_empty() {
719 return Err(invalid("listener", ConfigReason::Missing));
720 }
721 if self.listeners.len() > 64 {
722 return Err(invalid("listener", ConfigReason::TooLarge { max: 64 }));
723 }
724 let workers = self.workers.unwrap_or_else(|| {
725 if driver == DriverKind::Reactor {
726 std::thread::available_parallelism()
727 .map_or(4, |n| u16::try_from(n.get()).unwrap_or(4096).min(4096))
728 } else {
729 128
730 }
731 });
732 if workers == 0 {
733 return Err(invalid("workers", ConfigReason::Zero));
734 }
735 if workers > 4096 {
736 return Err(invalid("workers", ConfigReason::TooLarge { max: 4096 }));
737 }
738 let mut listeners = self.listeners;
739 let has_tls = TypeId::of::<T>() != TypeId::of::<NoTls>();
740 let mut names = Vec::new();
741 #[cfg(feature = "udp")]
742 for spec in &listeners {
743 if (spec.udp.is_some() && self.udp.is_none())
744 || (spec.udp.is_none() && <W as engine::Serve>::UDP_ONLY)
745 {
746 return Err(invalid("udp_sessions", ConfigReason::Inconsistent));
747 }
748 if spec.udp.is_some() && (spec.tls || spec.proxy != ProxyMode::Off) {
749 return Err(invalid("udp", ConfigReason::Inconsistent));
750 }
751 }
752 for spec in &mut listeners {
753 check_spec(spec, self.trusted.as_ref(), has_tls, &names)?;
754 if let Some(n) = &spec.name {
755 names.push(n.clone());
756 }
757 }
758 let limits = if self.limits.max_connections().is_none() {
761 let cap = if driver == DriverKind::Reactor {
762 reactor_default_cap(workers)
763 } else {
764 u32::from(workers)
765 };
766 self.limits.to_builder().max_connections(cap).build()?
767 } else {
768 self.limits.clone()
769 };
770 limits.validate(workers, crate::sys::descriptor_limit())?;
771 for spec in &listeners {
772 limits.overlay(&spec.limits).validate(workers, None)?;
773 }
774 if self.placement != Placement::Off && !crate::sys::CAN_PIN {
775 return Err(NetError::Unsupported {
776 feature: "worker placement",
777 platform: std::env::consts::OS,
778 });
779 }
780 if self.placement == Placement::Explicit(Vec::new()) {
781 return Err(invalid("placement", ConfigReason::Zero));
782 }
783 let tls: Option<Arc<dyn ErasedAcceptor>> = if has_tls {
784 Some(Arc::new(self.tls))
785 } else {
786 None
787 };
788 engine::start(engine::Config {
789 tls,
790 trusted: self.trusted,
791 listeners,
792 driver,
793 workers,
794 limits,
795 work: self.work,
796 gate: self.gate,
797 sink: self.sink,
798 control: self.control,
799 wipe: self.wipe,
800 clock: self.clock,
801 placement: self.placement,
802 #[cfg(feature = "udp")]
803 udp: self.udp,
804 })
805 }
806}
807
808fn reactor_default_cap(workers: u16) -> u32 {
811 let wanted = 10_000u32;
812 match crate::sys::descriptor_limit() {
813 Some(have) => {
814 let spare = u64::from(workers).saturating_mul(2) + 64;
815 let room = have.saturating_sub(spare).clamp(16, u64::from(wanted));
816 u32::try_from(room).unwrap_or(wanted)
817 }
818 None => wanted,
819 }
820}
821
822fn invalid(field: &'static str, reason: ConfigReason) -> NetError {
823 NetError::InvalidConfig { field, reason }
824}
825
826#[must_use]
834#[derive(Clone, Debug, PartialEq, Eq)]
835pub struct AdoptSpec {
836 listener: String,
837 lane: Option<crate::info::Lane>,
838}
839
840impl AdoptSpec {
841 pub fn new(listener: &str) -> AdoptSpec {
843 AdoptSpec {
844 listener: listener.to_owned(),
845 lane: None,
846 }
847 }
848
849 pub fn lane(mut self, lane: crate::info::Lane) -> AdoptSpec {
851 self.lane = Some(lane);
852 self
853 }
854}
855
856fn check_spec(
859 spec: &mut ListenerSpec,
860 server_trusted: Option<&Arc<TrustedProxies>>,
861 has_tls: bool,
862 taken: &[String],
863) -> Result<(), NetError> {
864 if spec.name.is_none() {
865 spec.name = spec
866 .adopt
867 .as_ref()
868 .and_then(|h| h.name())
869 .map(str::to_owned);
870 }
871 let unix = spec.unix.is_some()
872 || spec
873 .adopt
874 .as_ref()
875 .is_some_and(|h| h.kind() == crate::info::Transport::Unix);
876 if unix && !cfg!(feature = "local") {
877 return Err(NetError::Unsupported {
878 feature: "Unix domain sockets (the `local` feature)",
879 platform: std::env::consts::OS,
880 });
881 }
882 if spec.tls {
883 if !cfg!(feature = "tls") {
884 return Err(NetError::Unsupported {
885 feature: "TLS (the `tls` feature)",
886 platform: std::env::consts::OS,
887 });
888 }
889 if !has_tls {
890 return Err(invalid("tls", ConfigReason::Missing));
891 }
892 }
893 if spec.proxy != ProxyMode::Off {
894 if !cfg!(feature = "proxy") {
895 return Err(NetError::Unsupported {
896 feature: "PROXY protocol (the `proxy` feature)",
897 platform: std::env::consts::OS,
898 });
899 }
900 if !unix {
902 let trusted = spec.trusted.clone().or_else(|| server_trusted.cloned());
903 match trusted {
904 Some(t) if !t.is_empty() => spec.trusted = Some(t),
905 _ => return Err(invalid("trusted_proxies", ConfigReason::Missing)),
907 }
908 }
909 }
910 if let Some(n) = &spec.name {
911 if n.len() > 64 {
912 return Err(invalid("name", ConfigReason::TooLarge { max: 64 }));
913 }
914 if taken.contains(n) {
915 return Err(invalid("name", ConfigReason::Inconsistent));
916 }
917 }
918 Ok(())
919}
920
921#[must_use = "dropping a Server stops it; call wait_for_stop() to run until a stop is requested"]
924pub struct Server {
925 pub(crate) shared: Arc<Shared>,
926 pub(crate) threads: Vec<JoinHandle<()>>,
927 pub(crate) listeners: Vec<ListenerInfo>,
928 pub(crate) stopped: bool,
929}
930
931impl Server {
932 pub fn open_door(&self) -> Result<(), NetError> {
938 self.shared.open_door()
939 }
940
941 pub fn close_door(&self) {
943 self.shared.close_door();
944 }
945
946 #[must_use]
948 pub fn door(&self) -> DoorState {
949 self.shared.door()
950 }
951
952 pub fn drain(&self, deadline: Instant) -> DrainReport {
955 self.shared.drain(deadline)
956 }
957
958 pub fn shutdown(mut self, deadline: Instant) -> DrainReport {
960 self.stop(deadline)
961 }
962
963 pub fn wait_for_stop(mut self) -> DrainReport {
966 let deadline = self.shared.wait_for_stop_request();
967 self.stop(deadline)
968 }
969
970 fn stop(&mut self, deadline: Instant) -> DrainReport {
971 if self.stopped {
972 return DrainReport {
973 graceful: 0,
974 killed: 0,
975 took: Duration::ZERO,
976 };
977 }
978 self.stopped = true;
979 let report = self.shared.drain(deadline);
980 self.shared.stop_threads();
981 for t in self.threads.drain(..) {
982 let _ = t.join();
983 }
984 self.shared.join_listeners();
985 report
986 }
987
988 pub fn adopt(&self, conn: TcpConnection, spec: AdoptSpec) -> Result<ConnectionId, NetError> {
1015 let mut conn = conn;
1016 let link = conn.take_link().ok_or(NetError::Closed)?;
1017 let (Some(peer), Some(local)) =
1018 (link.info.peer.socket_addr(), link.info.local.socket_addr())
1019 else {
1020 return Err(invalid("connection", ConfigReason::Inconsistent));
1021 };
1022 let stream = link
1023 .into_stream(CloseReason::SessionClosed)
1024 .and_then(crate::sys::Stream::into_tcp)
1025 .ok_or(invalid("connection", ConfigReason::Inconsistent))?;
1026 self.shared
1027 .adopt(stream, peer, local, &spec.listener, spec.lane)
1028 }
1029
1030 pub fn release_listeners(&self) -> Result<Vec<ListenerHandle>, NetError> {
1040 self.shared.release_listeners()
1041 }
1042
1043 pub fn add_listener(&mut self, spec: ListenerSpec) -> Result<ListenerId, NetError> {
1067 let mut spec = spec;
1068 if self.listeners.len() >= 64 {
1069 return Err(invalid("listener", ConfigReason::TooLarge { max: 64 }));
1070 }
1071 let names: Vec<String> = self
1072 .listeners
1073 .iter()
1074 .filter_map(|l| l.name.clone())
1075 .collect();
1076 check_spec(
1077 &mut spec,
1078 self.shared.trusted.as_ref(),
1079 self.shared.tls.is_some(),
1080 &names,
1081 )?;
1082 let workers = u16::try_from(self.shared.worker_count()).unwrap_or(u16::MAX);
1083 self.shared
1084 .base_limits
1085 .overlay(&spec.limits)
1086 .validate(workers, None)?;
1087 let info = self.shared.add_listener(spec)?;
1088 let id = info.id;
1089 self.listeners.push(info);
1090 Ok(id)
1091 }
1092
1093 pub fn remove_listener(
1103 &mut self,
1104 id: ListenerId,
1105 deadline: Instant,
1106 ) -> Result<DrainReport, NetError> {
1107 let report = self.shared.remove_listener(id, deadline)?;
1108 self.listeners.retain(|l| l.id != id);
1109 Ok(report)
1110 }
1111
1112 #[must_use]
1114 pub fn handle(&self) -> ServerHandle {
1115 ServerHandle {
1116 shared: self.shared.clone(),
1117 }
1118 }
1119
1120 #[must_use]
1122 pub fn stats(&self) -> Stats {
1123 self.shared.stats()
1124 }
1125
1126 #[must_use]
1128 pub fn listeners(&self) -> &[ListenerInfo] {
1129 &self.listeners
1130 }
1131}
1132
1133impl Drop for Server {
1134 fn drop(&mut self) {
1135 let deadline = Instant::now() + self.shared.drain_timeout;
1136 self.stop(deadline);
1137 }
1138}
1139
1140impl fmt::Debug for Server {
1141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1142 f.debug_struct("Server")
1143 .field("listeners", &self.listeners)
1144 .field("door", &self.door())
1145 .finish()
1146 }
1147}
1148
1149#[derive(Clone)]
1163pub struct ServerHandle {
1164 pub(crate) shared: Arc<Shared>,
1165}
1166
1167impl ServerHandle {
1168 pub fn kill(&self, id: ConnectionId, reason: KillReason) -> bool {
1170 self.shared.kill(id, reason)
1171 }
1172
1173 pub fn close_door(&self) {
1175 self.shared.close_door();
1176 }
1177
1178 pub fn request_stop(&self) {
1180 self.shared.request_stop(None);
1181 }
1182
1183 pub fn wake_all(&self) {
1185 self.shared.wake_all();
1186 }
1187
1188 #[must_use]
1190 pub fn completer(&self, worker: WorkerId) -> Option<crate::completer::Completer> {
1191 self.shared.completer(worker)
1192 }
1193
1194 #[must_use]
1196 pub fn stats(&self) -> Stats {
1197 self.shared.stats()
1198 }
1199
1200 #[must_use]
1202 pub fn door(&self) -> DoorState {
1203 self.shared.door()
1204 }
1205}
1206
1207impl fmt::Debug for ServerHandle {
1208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1209 f.debug_struct("ServerHandle")
1210 .field("door", &self.door())
1211 .finish()
1212 }
1213}
1214
1215impl Stats {
1216 pub(crate) fn from_parts(
1217 mut base: Stats,
1218 refused_by: [u64; RefusalCause::COUNT],
1219 closed_by: [u64; CloseReason::COUNT],
1220 ) -> Stats {
1221 base.refused_by = refused_by;
1222 base.closed_by = closed_by;
1223 base
1224 }
1225}