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
//! A library that allows to listen network sockets with proper resource
//! limits and error handling.
//!
//! Library constists of three things:
//!
//! * [`sleep_on_error`][1] -- filters `Stream` of accepted sockets for
//! errors. Simple errors like `ConnectionReset` are just ignored. Severe
//! errors like `Too many files open` will delay next `accept()` call for
//! the delay specified, effectively allowing other connections to be
//! processed and release resources for new ones.
//! [Replaces code like this][2].
//! * [`listen`][3] -- iterates over a stream using [`buffer_unordered`][4]
//! combinator. It also suppresses errors in futures (because otherwise
//! every connection error would shut down the whole stream). And returns
//! `ForEach`-like future, you can `run()` or combine with other futures.
//! [Stands for code like this][5].
//! * [`BindMany`] allows to bind to list of addresses and update that list
//! (i.e. allow configuration reload), resulting into a single stream with
//! accepted sockets. This a good idea to use it with [abstract-ns] to
//! resolve list of names to addresses and keep them updated.
//!
//! [1]: trait.ListenExt.html#method.sleep_on_error
//! TODO: Update
//! [2]: https://git.io/vy9vi#L41-L52
//! [3]: trait.ListenExt.html#method.listen
//! [4]: https://docs.rs/futures/0.1.11/futures/stream/trait.Stream.html#method.buffer_unordered
//! TODO: Update
//! [5]: https://git.io/vy9vi#L56-L59
//! [abstract-ns]: https://docs.rs/abstract-ns
//! [`BindMany`]: struct.BindMany.html
//!
//! # Example
//!
//! Simple example looks like this:
//!
//! ```rust,ignore
//! let TIME_TO_WAIT_ON_ERROR = Duration::from_millis(100);
//! let MAX_SIMULTANEOUS_CONNECTIONS = 1000;
//!
//! let listener = TcpListener::bind(&addr).unwrap();
//! lp.run(
//! listener.incoming()
//! .sleep_on_error(TIME_TO_WAIT_ON_ERROR)
//! .map(move |mut socket| {
//! // Your future is here:
//! Proto::new(socket)
//! // Errors should not pass silently
//! // common idea is to log them
//! .map(|result| {
//! match result {
//! Ok(_) => (),
//! Err(e) => error!("Conn error: {}", e),
//! }
//! })
//! .map_err(|_| ())
//! })
//! .listen(MAX_SIMULTANEOUS_CONNECTIONS)
//! ).unwrap(); // stream doesn't end in this case
//! ```
//!
//! # Example With Listener Shutdown
//!
//! Because tk-listen works as a combinator trait, you can easily add
//! things, like shutdown:
//!
//! ```rust,ignore
//! let (tx, rx) = oneshot::channel();
//! lp.run(
//! listener.incoming()
//! .sleep_on_error(TIME_TO_WAIT_ON_ERROR)
//! .map(move |mut socket| {
//! // Your future is here:
//! Proto::new(socket)
//! // Errors should not pass silently
//! // common Idea is to log them
//! .map(|result| {
//! match result {
//! Ok(_) => (),
//! Err(e) => error!("Conn error: {}", e),
//! }
//! })
//! .map_err(|_| ())
//! })
//! .listen(MAX_SIMULTANEOUS_CONNECTIONS)
//! .select(|_| rx)
//! )
//! ```
//!
//! Now listener will be shut down either when `tx` is dropped or when
//! you send a message via `tx`.
//!
//! This is a "force shutdown", meaning it will close all active connections
//! immediately. It's also possible to stop accepting by closing original
//! stream (e.g. using `take_while`) and wait until all connections
//! shutdown gracefully.
#![warn(missing_docs)]
extern crate futures;
extern crate tokio;
#[macro_use] extern crate log;
mod bind;
mod traits;
mod sleep_on_error;
mod listen;
pub use traits::ListenExt;
pub use sleep_on_error::SleepOnError;
pub use listen::Listen;
pub use bind::BindMany;