async_listen/lib.rs
1//! # Async Listen
2//!
3//! The crate contains various helpers for writing production-ready servers in
4//! rust using [async-std](https://async.rs/).
5//!
6//! [Docs](https://docs.rs/async-listen/) |
7//! [Github](https://github.com/tailhook/async-listen/) |
8//! [Crate](https://crates.io/crates/async-listen)
9//!
10//! # Utilities
11//! * [ListenExt](trait.ListenExt.html) -- extension trait for stream of
12//! accepted sockets, provides useful conbinators for a stream
13//! * [error_hint](fn.error_hint.html) -- shows end-user hints no how to fix
14//! [the most imporant errors](errors/index.html)
15//!
16//! # Low-Level Utilities
17//!
18//! * [is_transient_error](fn.is_transient_error.html) -- determines if the
19//! error returned from `accept()` can be ignored
20//!
21//! # Example
22//!
23//! Here is a quite elaborate example that demonstrates:
24//! * Backpressure (limit on the number of simultaneous connections)
25//! * Error handling
26//! * Unification of Tcp and Unix sockets
27//!
28//! ```no_run
29//! use std::env::args;
30//! use std::error::Error;
31//! use std::fs::remove_file;
32//! use std::io;
33//! use std::time::Duration;
34//!
35//! use async_std::task;
36//! use async_std::net::TcpListener;
37//! use async_std::prelude::*;
38//!
39//! use async_listen::{ListenExt, ByteStream, backpressure, error_hint};
40//!
41//!
42//! fn main() -> Result<(), Box<dyn Error>> {
43//! let (_, bp) = backpressure::new(10);
44//! #[cfg(unix)] {
45//! use async_std::os::unix::net::UnixListener;
46//!
47//! if args().any(|x| x == "--unix") {
48//! remove_file("./example.sock").ok();
49//! return task::block_on(async {
50//! let listener = UnixListener::bind("./example.sock").await?;
51//! eprintln!("Accepting connections on ./example.sock");
52//! let mut incoming = listener.incoming()
53//! .log_warnings(log_accept_error)
54//! .handle_errors(Duration::from_millis(500))
55//! .backpressure_wrapper(bp);
56//! while let Some(stream) = incoming.next().await {
57//! task::spawn(connection_loop(stream));
58//! }
59//! Ok(())
60//! });
61//! }
62//! }
63//! task::block_on(async {
64//! let listener = TcpListener::bind("localhost:8080").await?;
65//! eprintln!("Accepting connections on localhost:8080");
66//! let mut incoming = listener.incoming()
67//! .log_warnings(log_accept_error)
68//! .handle_errors(Duration::from_millis(500))
69//! .backpressure_wrapper(bp);
70//! while let Some(stream) = incoming.next().await {
71//! task::spawn(async {
72//! if let Err(e) = connection_loop(stream).await {
73//! eprintln!("Error: {}", e);
74//! }
75//! });
76//! }
77//! Ok(())
78//! })
79//! }
80//!
81//! async fn connection_loop(mut stream: ByteStream) -> Result<(), io::Error> {
82//! println!("Connected from {}", stream.peer_addr()?);
83//! task::sleep(Duration::from_secs(5)).await;
84//! stream.write_all("hello\n".as_bytes()).await?;
85//! Ok(())
86//! }
87//!
88//! fn log_accept_error(e: &io::Error) {
89//! eprintln!("Accept error: {}. Sleeping 0.5s. {}", e, error_hint(&e));
90//! }
91//! ```
92#![warn(missing_debug_implementations)]
93#![warn(missing_docs)]
94#![forbid(unsafe_code)]
95
96mod error;
97mod listen_ext;
98mod log;
99mod sleep;
100mod byte_stream;
101pub mod backpressure;
102pub mod wrapper_types;
103pub mod errors;
104
105pub use byte_stream::{ByteStream, PeerAddr};
106pub use error::{is_transient_error, error_hint};
107pub use listen_ext::ListenExt;