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;