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
//! 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 //! [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 //! [5]: https://git.io/vy9vi#L56-L59 //! [abstract-ns]: https://docs.rs/abstract-ns //! //! # Example //! //! Simple example looks like this: //! //! ```rust,ignore //! let TIME_TO_WAIT_ON_ERROR = Duration::from_millis(100); //! let MAX_SIMULTANEOUS_CONNECTIONS = 1000; //! //! let mut lp = Core::new().unwrap(); //! let listener = TcpListener::bind(&addr, &lp.handle()).unwrap(); //! lp.run( //! listener.incoming() //! .sleep_on_error(TIME_TO_WAIT_ON_ERROR, &h2) //! .map(move |(mut socket, _addr)| { //! // Your future is here: //! Proto::new(socket) //! // Errors should not pass silently //! // common idea is to log them //! .map_err(|e| error!("Protocol error: {}", e)) //! }) //! .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, &h2) //! .map(move |(mut socket, _addr)| { //! // Your future is here: //! Proto::new(socket) //! // Errors should not pass silently //! // common Idea is to log them //! .map_err(|e| error!("Protocol error: {}", e)) //! }) //! .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_core; #[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;