2020-09-13 11:12:07 +02:00
|
|
|
//! General purpose TCP server.
|
|
|
|
|
2020-12-13 00:24:00 +01:00
|
|
|
#![deny(rust_2018_idioms, nonstandard_style)]
|
|
|
|
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
|
|
|
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
2018-09-11 17:43:23 +02:00
|
|
|
|
|
|
|
mod accept;
|
2018-12-10 05:30:04 +01:00
|
|
|
mod builder;
|
2019-03-15 04:09:34 +01:00
|
|
|
mod config;
|
2018-12-10 06:51:35 +01:00
|
|
|
mod server;
|
2019-11-14 13:38:24 +01:00
|
|
|
mod service;
|
2019-11-26 12:03:52 +01:00
|
|
|
mod signals;
|
2019-07-18 13:05:40 +02:00
|
|
|
mod socket;
|
2020-12-29 00:44:53 +01:00
|
|
|
mod waker_queue;
|
2018-09-11 17:43:23 +02:00
|
|
|
mod worker;
|
|
|
|
|
2018-12-10 05:30:04 +01:00
|
|
|
pub use self::builder::ServerBuilder;
|
2019-03-15 04:09:34 +01:00
|
|
|
pub use self::config::{ServiceConfig, ServiceRuntime};
|
2018-12-10 06:51:35 +01:00
|
|
|
pub use self::server::Server;
|
2019-11-14 13:38:24 +01:00
|
|
|
pub use self::service::ServiceFactory;
|
2019-03-04 23:31:46 +01:00
|
|
|
|
2019-07-18 13:05:40 +02:00
|
|
|
#[doc(hidden)]
|
|
|
|
pub use self::socket::FromStream;
|
|
|
|
|
2020-12-29 00:44:53 +01:00
|
|
|
use std::future::Future;
|
|
|
|
use std::pin::Pin;
|
|
|
|
use std::task::{Context, Poll};
|
|
|
|
|
2020-09-13 11:12:07 +02:00
|
|
|
/// Socket ID token
|
2018-11-03 17:09:14 +01:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
2018-09-11 17:43:23 +02:00
|
|
|
pub(crate) struct Token(usize);
|
2018-11-03 17:09:14 +01:00
|
|
|
|
2020-12-29 00:44:53 +01:00
|
|
|
impl Default for Token {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-03 17:09:14 +01:00
|
|
|
impl Token {
|
2020-12-29 00:44:53 +01:00
|
|
|
fn new() -> Self {
|
|
|
|
Self(0)
|
|
|
|
}
|
|
|
|
|
2018-11-14 23:20:33 +01:00
|
|
|
pub(crate) fn next(&mut self) -> Token {
|
2019-12-04 10:12:02 +01:00
|
|
|
let token = Token(self.0);
|
2018-11-14 23:20:33 +01:00
|
|
|
self.0 += 1;
|
|
|
|
token
|
2018-11-03 17:09:14 +01:00
|
|
|
}
|
2018-11-18 03:46:26 +01:00
|
|
|
}
|
2018-12-10 07:19:26 +01:00
|
|
|
|
|
|
|
/// Start server building process
|
2019-03-02 23:42:31 +01:00
|
|
|
pub fn new() -> ServerBuilder {
|
2018-12-10 07:19:26 +01:00
|
|
|
ServerBuilder::default()
|
|
|
|
}
|
2020-12-29 00:44:53 +01:00
|
|
|
|
|
|
|
// temporary Ready type for std::future::{ready, Ready}; Can be removed when MSRV surpass 1.48
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub struct Ready<T>(Option<T>);
|
|
|
|
|
|
|
|
pub(crate) fn ready<T>(t: T) -> Ready<T> {
|
|
|
|
Ready(Some(t))
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Unpin for Ready<T> {}
|
|
|
|
|
|
|
|
impl<T> Future for Ready<T> {
|
|
|
|
type Output = T;
|
|
|
|
|
|
|
|
fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
|
|
|
|
Poll::Ready(self.get_mut().0.take().unwrap())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// a poor man's join future. joined future is only used when starting/stopping the server.
|
|
|
|
// pin_project and pinned futures are overkill for this task.
|
|
|
|
pub(crate) struct JoinAll<T> {
|
|
|
|
fut: Vec<JoinFuture<T>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn join_all<T>(fut: Vec<impl Future<Output = T> + 'static>) -> JoinAll<T> {
|
|
|
|
let fut = fut
|
|
|
|
.into_iter()
|
|
|
|
.map(|f| JoinFuture::Future(Box::pin(f)))
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
JoinAll { fut }
|
|
|
|
}
|
|
|
|
|
|
|
|
enum JoinFuture<T> {
|
|
|
|
Future(Pin<Box<dyn Future<Output = T>>>),
|
|
|
|
Result(Option<T>),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Unpin for JoinAll<T> {}
|
|
|
|
|
|
|
|
impl<T> Future for JoinAll<T> {
|
|
|
|
type Output = Vec<T>;
|
|
|
|
|
|
|
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
|
|
let mut ready = true;
|
|
|
|
|
|
|
|
let this = self.get_mut();
|
|
|
|
for fut in this.fut.iter_mut() {
|
|
|
|
if let JoinFuture::Future(f) = fut {
|
|
|
|
match f.as_mut().poll(cx) {
|
|
|
|
Poll::Ready(t) => {
|
|
|
|
*fut = JoinFuture::Result(Some(t));
|
|
|
|
}
|
|
|
|
Poll::Pending => ready = false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ready {
|
|
|
|
let mut res = Vec::new();
|
|
|
|
for fut in this.fut.iter_mut() {
|
|
|
|
if let JoinFuture::Result(f) = fut {
|
|
|
|
res.push(f.take().unwrap());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Poll::Ready(res)
|
|
|
|
} else {
|
|
|
|
Poll::Pending
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[actix_rt::test]
|
|
|
|
async fn test_join_all() {
|
|
|
|
let futs = vec![ready(Ok(1)), ready(Err(3)), ready(Ok(9))];
|
|
|
|
let mut res = join_all(futs).await.into_iter();
|
|
|
|
assert_eq!(Ok(1), res.next().unwrap());
|
|
|
|
assert_eq!(Err(3), res.next().unwrap());
|
|
|
|
assert_eq!(Ok(9), res.next().unwrap());
|
|
|
|
}
|
|
|
|
}
|