1
0
mirror of https://github.com/fafhrd91/actix-net synced 2024-11-28 06:32:39 +01:00
actix-net/src/server_service.rs

230 lines
5.5 KiB
Rust
Raw Normal View History

2018-09-07 20:35:25 +02:00
use std::cell::Cell;
use std::net;
2018-09-07 20:35:25 +02:00
use std::rc::Rc;
use std::sync::atomic::{AtomicUsize, Ordering};
2018-08-19 19:47:04 +02:00
2018-09-07 22:06:51 +02:00
use futures::future::{err, ok};
2018-09-07 20:35:25 +02:00
use futures::task::AtomicTask;
2018-09-07 22:06:51 +02:00
use futures::{Async, Future, Poll};
2018-08-19 19:47:04 +02:00
use tokio_reactor::Handle;
use tokio_tcp::TcpStream;
2018-08-22 02:08:23 +02:00
2018-08-24 00:42:34 +02:00
use super::{NewService, Service};
2018-08-19 19:47:04 +02:00
2018-09-07 22:06:51 +02:00
pub enum ServerMessage {
Connect(net::TcpStream),
Shutdown,
ForceShutdown,
}
2018-08-19 19:47:04 +02:00
pub(crate) type BoxedServerService = Box<
Service<
2018-09-07 22:06:51 +02:00
Request = ServerMessage,
2018-08-19 19:47:04 +02:00
Response = (),
Error = (),
Future = Box<Future<Item = (), Error = ()>>,
>,
>;
2018-09-07 20:35:25 +02:00
const MAX_CONNS: AtomicUsize = AtomicUsize::new(25600);
/// Sets the maximum per-worker number of concurrent connections.
///
/// All socket listeners will stop accepting connections when this limit is
/// reached for each worker.
///
/// By default max connections is set to a 25k per worker.
pub fn max_concurrent_connections(num: usize) {
MAX_CONNS.store(num, Ordering::Relaxed);
}
pub(crate) fn num_connections() -> usize {
MAX_CONNS_COUNTER.with(|counter| counter.total())
}
thread_local! {
static MAX_CONNS_COUNTER: Counter = Counter::new(MAX_CONNS.load(Ordering::Relaxed));
}
2018-08-19 19:47:04 +02:00
pub(crate) struct ServerService<T> {
2018-09-07 20:35:25 +02:00
service: T,
counter: Counter,
}
impl<T> ServerService<T> {
fn new(service: T) -> Self {
MAX_CONNS_COUNTER.with(|counter| ServerService {
service,
counter: counter.clone(),
})
}
2018-08-19 19:47:04 +02:00
}
impl<T> Service for ServerService<T>
where
T: Service<Request = TcpStream, Response = (), Error = ()>,
2018-08-19 19:47:04 +02:00
T::Future: 'static,
T::Error: 'static,
2018-08-19 19:47:04 +02:00
{
2018-09-07 22:06:51 +02:00
type Request = ServerMessage;
2018-08-19 19:47:04 +02:00
type Response = ();
type Error = ();
type Future = Box<Future<Item = (), Error = ()>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
2018-09-07 20:35:25 +02:00
if self.counter.check() {
self.service.poll_ready().map_err(|_| ())
} else {
Ok(Async::NotReady)
}
2018-08-19 19:47:04 +02:00
}
2018-09-07 22:06:51 +02:00
fn call(&mut self, req: ServerMessage) -> Self::Future {
match req {
ServerMessage::Connect(stream) => {
let stream = TcpStream::from_std(stream, &Handle::default()).map_err(|e| {
error!("Can not convert to an async tcp stream: {}", e);
});
if let Ok(stream) = stream {
let guard = self.counter.get();
Box::new(
self.service
.call(stream)
.map_err(|_| ())
.map(move |_| drop(guard)),
)
} else {
Box::new(err(()))
}
}
_ => Box::new(ok(())),
2018-08-19 19:47:04 +02:00
}
}
}
2018-08-24 00:42:34 +02:00
pub(crate) struct ServerNewService<F, T>
where
F: Fn() -> T + Send + Clone,
{
inner: F,
2018-08-19 19:47:04 +02:00
}
2018-08-24 00:42:34 +02:00
impl<F, T> ServerNewService<F, T>
2018-08-19 19:47:04 +02:00
where
F: Fn() -> T + Send + Clone + 'static,
T: NewService<Request = TcpStream, Response = (), Error = (), InitError = ()> + 'static,
2018-08-19 19:47:04 +02:00
T::Service: 'static,
T::Future: 'static,
{
2018-08-24 00:42:34 +02:00
pub(crate) fn create(inner: F) -> Box<ServerServiceFactory + Send> {
2018-09-07 20:35:25 +02:00
Box::new(Self { inner })
2018-08-19 19:47:04 +02:00
}
}
2018-08-24 00:42:34 +02:00
pub trait ServerServiceFactory {
fn clone_factory(&self) -> Box<ServerServiceFactory + Send>;
2018-08-19 19:47:04 +02:00
fn create(&self) -> Box<Future<Item = BoxedServerService, Error = ()>>;
}
2018-08-24 00:42:34 +02:00
impl<F, T> ServerServiceFactory for ServerNewService<F, T>
2018-08-19 19:47:04 +02:00
where
F: Fn() -> T + Send + Clone + 'static,
T: NewService<Request = TcpStream, Response = (), Error = (), InitError = ()> + 'static,
2018-08-19 19:47:04 +02:00
T::Service: 'static,
T::Future: 'static,
{
2018-08-24 00:42:34 +02:00
fn clone_factory(&self) -> Box<ServerServiceFactory + Send> {
2018-08-19 19:47:04 +02:00
Box::new(Self {
inner: self.inner.clone(),
})
}
fn create(&self) -> Box<Future<Item = BoxedServerService, Error = ()>> {
2018-09-07 22:06:51 +02:00
Box::new((self.inner)().new_service().map(move |inner| {
let service: BoxedServerService = Box::new(ServerService::new(inner));
service
}))
2018-08-19 19:47:04 +02:00
}
}
2018-08-24 00:42:34 +02:00
impl ServerServiceFactory for Box<ServerServiceFactory> {
fn clone_factory(&self) -> Box<ServerServiceFactory + Send> {
2018-08-19 19:47:04 +02:00
self.as_ref().clone_factory()
}
fn create(&self) -> Box<Future<Item = BoxedServerService, Error = ()>> {
self.as_ref().create()
}
}
2018-09-07 20:35:25 +02:00
#[derive(Clone)]
pub(crate) struct Counter(Rc<CounterInner>);
struct CounterInner {
count: Cell<usize>,
maxconn: usize,
task: AtomicTask,
}
impl Counter {
pub fn new(maxconn: usize) -> Self {
Counter(Rc::new(CounterInner {
maxconn,
count: Cell::new(0),
task: AtomicTask::new(),
}))
}
pub fn get(&self) -> CounterGuard {
CounterGuard::new(self.0.clone())
}
pub fn check(&self) -> bool {
self.0.check()
}
pub fn total(&self) -> usize {
self.0.count.get()
}
}
pub(crate) struct CounterGuard(Rc<CounterInner>);
impl CounterGuard {
fn new(inner: Rc<CounterInner>) -> Self {
inner.inc();
CounterGuard(inner)
}
}
impl Drop for CounterGuard {
fn drop(&mut self) {
self.0.dec();
}
}
impl CounterInner {
fn inc(&self) {
let num = self.count.get() + 1;
self.count.set(num);
if num == self.maxconn {
self.task.register();
}
}
fn dec(&self) {
let num = self.count.get();
self.count.set(num - 1);
if num == self.maxconn {
self.task.notify();
}
}
fn check(&self) -> bool {
self.count.get() < self.maxconn
}
}