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;