1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#![doc(
    html_root_url = "https://docs.rs/spirit-tokio/0.5.2/spirit_tokio/",
    test(attr(deny(warnings)))
)]
#![forbid(unsafe_code)]
#![warn(missing_docs)]

//! A collection of [`Fragment`]s and [`Extension`]s integrating tokio primitives into [spirit].
//!
//! The crate provides utilities to auto-configure tokio primitives, like listening sockets. This
//! allows, for example, specifying just the function that handles a single connection and let
//! spirit handle all the rest ‒ creating and shutting down the listening socket based on the
//! configuration changes, specifying details like the listen backlog or TCP keepalive, etc. It
//! couples them together and spawns the resulting future onto a tokio runtime (also created by
//! this crate, around the main body of application).
//!
//! # Available fragments
//!
//! * [`TcpListen`] for [`TcpListener`]
//! * [`UdpListen`] for [`UdpSocket`] (bound to an address)
//! * [`UnixListen`] for [`UnixListener`] (available on unix systems)
//! * [`DatagramListen`] for [`UnixDatagram`] (available on unix systems)
//!
//! The [`WithListenLimits`] is a wrapper that adds limits to number of concurrent connections as
//! well as a backoff timeout in case of soft errors (like „Too many open files“). There are also
//! type aliases [`TcpListenWithLimits`] and [`UnixListenWithLimits`].
//!
//! # Runtime
//!
//! Currently, the crate supports spawning futures on the default runtime only. It also sets up the
//! default runtime as part of the pipelines. However, this works only if at least one pipeline is
//! plugged into the [`Builder`]. If all the pipelines you install into [spirit] are plugged after
//! building, it'll panic.
//!
//! In such case, the runtime needs to be plugged in manually as part of the setup, like this:
//!
//! ```rust
//! # use spirit::prelude::*;
//! # use spirit_tokio::runtime::Runtime;
//! Spirit::<Empty, Empty>::new()
//!     .with_singleton(Runtime::default())
//!     .run(|_spirit| {
//!         // Plugging spirit-tokio pipelines in here into _spirit
//!         Ok(())
//!     });
//! ```
//!
//! # Examples
//!
//! ```rust
//! use std::sync::Arc;
//!
//! use failure::Error;
//! use serde::Deserialize;
//! use spirit::prelude::*;
//! use spirit_tokio::{HandleListener, TcpListenWithLimits};
//! use tokio::prelude::*;
//!
//! const DEFAULT_CONFIG: &str = r#"
//! [listening_socket]
//! port = 1234
//! max-conn = 20
//! error-sleep = "100ms"
//! "#;
//!
//! #[derive(Default, Deserialize)]
//! struct Config {
//!     listening_socket: TcpListenWithLimits,
//! }
//!
//! impl Config {
//!     fn listening_socket(&self) -> TcpListenWithLimits {
//!         self.listening_socket.clone()
//!     }
//! }
//!
//! fn connection<C: AsyncRead + AsyncWrite>(conn: C) -> impl Future<Item = (), Error = Error> {
//!     tokio::io::write_all(conn, "Hello\n")
//!         .map(|_| ())
//!         .map_err(Error::from)
//! }
//!
//! fn main() {
//!     Spirit::<Empty, Config>::new()
//!         .config_defaults(DEFAULT_CONFIG)
//!         .with(
//!             Pipeline::new("listener")
//!                 .extract_cfg(Config::listening_socket)
//!                 .transform(HandleListener(|conn, _cfg: &_| connection(conn)))
//!         )
//!         .run(|spirit| {
//! #           let spirit = Arc::clone(spirit);
//! #           std::thread::spawn(move || spirit.terminate());
//!             Ok(())
//!         });
//! }
//! ```
//!
//! Further examples are in the
//! [git repository](https://github.com/vorner/spirit/tree/master/spirit-tokio/examples).
//!
//! [`Fragment`]: spirit::Fragment
//! [`Extension`]: spirit::extension::Extension
//! [spirit]: https://crates.io/crates/spirit.
//! [`TcpListener`]: ::tokio::net::TcpListener
//! [`UdpSocket`]: ::tokio::net::UdpSocket
//! [`UnixListen`]: net::unix::UnixListen
//! [`UnixListener`]: ::tokio::net::unix::UnixListener
//! [`DatagramListen`]: net::unix::DatagramListen
//! [`UnixDatagram`]: ::tokio::net::unix::UnixDatagram
//! [`WithListenLimits`]: net::limits::WithListenLimits
//! [`UnixListenWithLimits`]: net::unix::UnixListenWithLimits
//! [`Builder`]: spirit::Builder

pub mod either;
pub mod handlers;
pub mod installer;
pub mod net;
pub mod runtime;
// pub mod scaled; XXX

pub use crate::handlers::{HandleListener, HandleListenerInit, HandleSocket};
pub use crate::net::{TcpListen, TcpListenWithLimits, UdpListen};
pub use crate::runtime::Runtime;