1mod engine;
4mod source;
5
6use std::fmt;
7use std::net::{SocketAddr, ToSocketAddrs};
8use std::sync::Arc;
9use std::thread::JoinHandle;
10use std::time::{Duration, Instant};
11
12use crate::control::ControlLine;
13use crate::driver::DriverKind;
14use crate::error::{CloseReason, ConfigReason, KillReason, NetError, RefusalCause};
15use crate::events::{EventSink, NoopSink};
16use crate::gate::Gate;
17use crate::id::{ConnectionId, WorkerId};
18use crate::limits::Limits;
19use crate::opts::ListenOptions;
20use crate::session::SessionFactory;
21use crate::tcp::{ListenerInfo, TcpConnection};
22use crate::time::Clock;
23use crate::tls::{NoTls, TlsAcceptor};
24
25pub(crate) use engine::Shared;
26
27#[derive(Clone, Copy, Debug, PartialEq, Eq)]
33pub enum DoorState {
34 Open,
36 Closed,
38}
39
40#[derive(Clone, Copy, Debug, PartialEq, Eq)]
47pub struct DrainReport {
48 pub graceful: u32,
50 pub killed: u32,
52 pub took: Duration,
54}
55
56#[non_exhaustive]
65#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
66pub struct Stats {
67 pub open: u64,
69 pub accepted: u64,
71 pub refused: u64,
73 pub closed: u64,
75 pub bytes_in: u64,
77 pub bytes_out: u64,
79 pub egress_denied: u64,
81 pub killed: u64,
83 pub slow_peers: u64,
85 pub timeouts: u64,
87 pub descriptor_pressure: u64,
89 pub stale_completions: u64,
91 pub session_panics: u64,
93 refused_by: [u64; RefusalCause::COUNT],
94 closed_by: [u64; CloseReason::COUNT],
95}
96
97impl Stats {
98 #[must_use]
100 pub fn refused_for(&self, cause: RefusalCause) -> u64 {
101 self.refused_by[cause.index()]
102 }
103
104 #[must_use]
106 pub fn closed_for(&self, reason: CloseReason) -> u64 {
107 self.closed_by[reason.index()]
108 }
109}
110
111#[must_use]
122#[derive(Debug)]
123pub struct ListenerSpec {
124 pub(crate) addrs: Result<Vec<SocketAddr>, String>,
125 pub(crate) options: Option<ListenOptions>,
126 pub(crate) name: Option<String>,
127 pub(crate) limits: Limits,
128}
129
130impl ListenerSpec {
131 pub fn tcp<A: ToSocketAddrs>(addr: A) -> ListenerSpec {
133 ListenerSpec {
134 addrs: addr
135 .to_socket_addrs()
136 .map(|i| i.collect())
137 .map_err(|e| e.to_string()),
138 options: None,
139 name: None,
140 limits: Limits::default(),
141 }
142 }
143
144 pub fn tcp_with<A: ToSocketAddrs>(addr: A, options: ListenOptions) -> ListenerSpec {
146 ListenerSpec {
147 options: Some(options),
148 ..ListenerSpec::tcp(addr)
149 }
150 }
151
152 pub fn name(mut self, name: &str) -> ListenerSpec {
154 self.name = Some(name.to_owned());
155 self
156 }
157
158 pub fn limits(mut self, limits: Limits) -> ListenerSpec {
160 self.limits = limits;
161 self
162 }
163}
164
165#[derive(Clone, Copy, Debug, Default)]
167pub struct NoWork;
168
169#[derive(Clone, Copy, Debug, Default)]
171pub struct NoGate;
172
173#[derive(Debug)]
175pub struct Sessions<F> {
176 pub(crate) factory: F,
177}
178
179pub struct BlockingHandler<H> {
181 pub(crate) handler: H,
182}
183
184impl<H> fmt::Debug for BlockingHandler<H> {
185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186 f.write_str("BlockingHandler")
187 }
188}
189
190pub(crate) mod sealed {
191 pub trait Sealed {}
192}
193
194pub trait Workload: sealed::Sealed + engine::Serve + Send + Sync + 'static {}
196
197impl<F: SessionFactory> sealed::Sealed for Sessions<F> {}
198impl<F: SessionFactory> Workload for Sessions<F> {}
199
200impl<H> sealed::Sealed for BlockingHandler<H> where
201 H: Fn(&mut TcpConnection) -> Result<(), NetError> + Send + Sync + 'static
202{
203}
204impl<H> Workload for BlockingHandler<H> where
205 H: Fn(&mut TcpConnection) -> Result<(), NetError> + Send + Sync + 'static
206{
207}
208
209#[must_use]
234pub struct ServerBuilder<W = NoWork, G = NoGate, S = NoopSink, T = NoTls> {
235 listeners: Vec<ListenerSpec>,
236 driver: DriverKind,
237 workers: Option<u16>,
238 limits: Limits,
239 work: W,
240 gate: G,
241 sink: S,
242 tls: T,
243 control: Option<Arc<dyn ControlLine>>,
244 wipe: bool,
245 clock: Option<Arc<dyn Clock>>,
246}
247
248impl ServerBuilder {
249 pub fn new() -> ServerBuilder {
251 ServerBuilder {
252 listeners: Vec::new(),
253 driver: DriverKind::Auto,
254 workers: None,
255 limits: Limits::default(),
256 work: NoWork,
257 gate: NoGate,
258 sink: NoopSink,
259 tls: NoTls,
260 control: None,
261 wipe: true,
262 clock: None,
263 }
264 }
265}
266
267impl Default for ServerBuilder {
268 fn default() -> ServerBuilder {
269 ServerBuilder::new()
270 }
271}
272
273impl<W, G, S, T> ServerBuilder<W, G, S, T> {
274 fn map<W2, G2, S2, T2>(
275 self,
276 f: impl FnOnce(W, G, S, T) -> (W2, G2, S2, T2),
277 ) -> ServerBuilder<W2, G2, S2, T2> {
278 let ServerBuilder {
279 listeners,
280 driver,
281 workers,
282 limits,
283 work,
284 gate,
285 sink,
286 tls,
287 control,
288 wipe,
289 clock,
290 } = self;
291 let (work, gate, sink, tls) = f(work, gate, sink, tls);
292 ServerBuilder {
293 listeners,
294 driver,
295 workers,
296 limits,
297 work,
298 gate,
299 sink,
300 tls,
301 control,
302 wipe,
303 clock,
304 }
305 }
306
307 pub fn listener(mut self, spec: ListenerSpec) -> Self {
309 self.listeners.push(spec);
310 self
311 }
312
313 pub fn driver(mut self, kind: DriverKind) -> Self {
315 self.driver = kind;
316 self
317 }
318
319 pub fn workers(mut self, n: u16) -> Self {
321 self.workers = Some(n);
322 self
323 }
324
325 pub fn limits(mut self, limits: Limits) -> Self {
327 self.limits = limits;
328 self
329 }
330
331 pub fn sessions<F: SessionFactory>(self, factory: F) -> ServerBuilder<Sessions<F>, G, S, T> {
333 self.map(|_, g, s, t| (Sessions { factory }, g, s, t))
334 }
335
336 pub fn handler<H>(self, handler: H) -> ServerBuilder<BlockingHandler<H>, G, S, T>
338 where
339 H: Fn(&mut TcpConnection) -> Result<(), NetError> + Send + Sync + 'static,
340 {
341 self.map(|_, g, s, t| (BlockingHandler { handler }, g, s, t))
342 }
343
344 pub fn gate<G2: Gate>(self, gate: G2) -> ServerBuilder<W, G2, S, T> {
346 self.map(|w, _, s, t| (w, gate, s, t))
347 }
348
349 pub fn events<S2: EventSink>(self, sink: S2) -> ServerBuilder<W, G, S2, T> {
351 self.map(|w, g, _, t| (w, g, sink, t))
352 }
353
354 pub fn control<C: ControlLine>(mut self, line: Arc<C>) -> Self {
356 self.control = Some(line);
357 self
358 }
359
360 pub fn wipe_buffers(mut self, on: bool) -> Self {
362 self.wipe = on;
363 self
364 }
365
366 pub fn clock<K: Clock>(mut self, clock: Arc<K>) -> Self {
368 self.clock = Some(clock);
369 self
370 }
371}
372
373impl<W, G, S, T> ServerBuilder<W, G, S, T>
374where
375 W: Workload,
376 G: Gate,
377 S: EventSink,
378 T: TlsAcceptor,
379{
380 pub fn build(self) -> Result<Server, NetError> {
388 let driver = match self.driver.resolve() {
389 DriverKind::Blocking => DriverKind::Blocking,
390 other => {
391 return Err(NetError::Unsupported {
392 feature: match other {
393 DriverKind::Uring => "the io_uring driver (after 1.0.0)",
394 _ => "the reactor driver (0.5.0)",
395 },
396 platform: std::env::consts::OS,
397 });
398 }
399 };
400 if self.listeners.is_empty() {
401 return Err(invalid("listener", ConfigReason::Missing));
402 }
403 if self.listeners.len() > 64 {
404 return Err(invalid("listener", ConfigReason::TooLarge { max: 64 }));
405 }
406 let workers = self.workers.unwrap_or(128);
407 if workers == 0 {
408 return Err(invalid("workers", ConfigReason::Zero));
409 }
410 if workers > 4096 {
411 return Err(invalid("workers", ConfigReason::TooLarge { max: 4096 }));
412 }
413 let mut names = Vec::new();
414 for spec in &self.listeners {
415 if let Some(n) = &spec.name {
416 if n.len() > 64 {
417 return Err(invalid("name", ConfigReason::TooLarge { max: 64 }));
418 }
419 if names.contains(n) {
420 return Err(invalid("name", ConfigReason::Inconsistent));
421 }
422 names.push(n.clone());
423 }
424 }
425 let limits = if self.limits.max_connections().is_none() {
427 self.limits
428 .to_builder()
429 .max_connections(u32::from(workers))
430 .build()?
431 } else {
432 self.limits.clone()
433 };
434 limits.validate(workers, crate::sys::descriptor_limit())?;
435 for spec in &self.listeners {
436 limits.overlay(&spec.limits).validate(workers, None)?;
437 }
438 let _ = &self.tls;
439 engine::start(engine::Config {
440 listeners: self.listeners,
441 driver,
442 workers,
443 limits,
444 work: self.work,
445 gate: self.gate,
446 sink: self.sink,
447 control: self.control,
448 wipe: self.wipe,
449 clock: self.clock,
450 })
451 }
452}
453
454fn invalid(field: &'static str, reason: ConfigReason) -> NetError {
455 NetError::InvalidConfig { field, reason }
456}
457
458#[must_use = "dropping a Server stops it; call wait_for_stop() to run until a stop is requested"]
461pub struct Server {
462 pub(crate) shared: Arc<Shared>,
463 pub(crate) threads: Vec<JoinHandle<()>>,
464 pub(crate) listeners: Vec<ListenerInfo>,
465 pub(crate) stopped: bool,
466}
467
468impl Server {
469 pub fn open_door(&self) -> Result<(), NetError> {
475 self.shared.open_door()
476 }
477
478 pub fn close_door(&self) {
480 self.shared.close_door();
481 }
482
483 #[must_use]
485 pub fn door(&self) -> DoorState {
486 self.shared.door()
487 }
488
489 pub fn drain(&self, deadline: Instant) -> DrainReport {
492 self.shared.drain(deadline)
493 }
494
495 pub fn shutdown(mut self, deadline: Instant) -> DrainReport {
497 self.stop(deadline)
498 }
499
500 pub fn wait_for_stop(mut self) -> DrainReport {
503 let deadline = self.shared.wait_for_stop_request();
504 self.stop(deadline)
505 }
506
507 fn stop(&mut self, deadline: Instant) -> DrainReport {
508 if self.stopped {
509 return DrainReport {
510 graceful: 0,
511 killed: 0,
512 took: Duration::ZERO,
513 };
514 }
515 self.stopped = true;
516 let report = self.shared.drain(deadline);
517 self.shared.stop_threads();
518 for t in self.threads.drain(..) {
519 let _ = t.join();
520 }
521 report
522 }
523
524 #[must_use]
526 pub fn handle(&self) -> ServerHandle {
527 ServerHandle {
528 shared: self.shared.clone(),
529 }
530 }
531
532 #[must_use]
534 pub fn stats(&self) -> Stats {
535 self.shared.stats()
536 }
537
538 #[must_use]
540 pub fn listeners(&self) -> &[ListenerInfo] {
541 &self.listeners
542 }
543}
544
545impl Drop for Server {
546 fn drop(&mut self) {
547 let deadline = Instant::now() + self.shared.drain_timeout;
548 self.stop(deadline);
549 }
550}
551
552impl fmt::Debug for Server {
553 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
554 f.debug_struct("Server")
555 .field("listeners", &self.listeners)
556 .field("door", &self.door())
557 .finish()
558 }
559}
560
561#[derive(Clone)]
575pub struct ServerHandle {
576 pub(crate) shared: Arc<Shared>,
577}
578
579impl ServerHandle {
580 pub fn kill(&self, id: ConnectionId, reason: KillReason) -> bool {
582 self.shared.kill(id, reason)
583 }
584
585 pub fn close_door(&self) {
587 self.shared.close_door();
588 }
589
590 pub fn request_stop(&self) {
592 self.shared.request_stop(None);
593 }
594
595 pub fn wake_all(&self) {
597 self.shared.wake_all();
598 }
599
600 #[must_use]
602 pub fn completer(&self, worker: WorkerId) -> Option<crate::completer::Completer> {
603 self.shared.completer(worker)
604 }
605
606 #[must_use]
608 pub fn stats(&self) -> Stats {
609 self.shared.stats()
610 }
611
612 #[must_use]
614 pub fn door(&self) -> DoorState {
615 self.shared.door()
616 }
617}
618
619impl fmt::Debug for ServerHandle {
620 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
621 f.debug_struct("ServerHandle")
622 .field("door", &self.door())
623 .finish()
624 }
625}
626
627impl Stats {
628 pub(crate) fn from_parts(
629 mut base: Stats,
630 refused_by: [u64; RefusalCause::COUNT],
631 closed_by: [u64; CloseReason::COUNT],
632 ) -> Stats {
633 base.refused_by = refused_by;
634 base.closed_by = closed_by;
635 base
636 }
637}