|
@@ -1,15 +1,13 @@
|
|
#[global_allocator]
|
|
#[global_allocator]
|
|
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
|
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
|
|
|
|
|
-use std::future::Future;
|
|
|
|
-use std::io;
|
|
|
|
-use std::pin::Pin;
|
|
|
|
-use std::task::{Context, Poll};
|
|
|
|
|
|
+use std::{
|
|
|
|
+ cell::RefCell, future::Future, io, pin::Pin, rc::Rc, task::Context, task::Poll,
|
|
|
|
+};
|
|
|
|
|
|
-use bytes::BytesMut;
|
|
|
|
-use ntex::codec::{AsyncRead, AsyncWrite, Decoder};
|
|
|
|
use ntex::fn_service;
|
|
use ntex::fn_service;
|
|
-use ntex::http::{h1, Request};
|
|
|
|
|
|
+use ntex::framed::{ReadTask, State, WriteTask};
|
|
|
|
+use ntex::http::h1;
|
|
use ntex::rt::net::TcpStream;
|
|
use ntex::rt::net::TcpStream;
|
|
use yarte::Serialize;
|
|
use yarte::Serialize;
|
|
|
|
|
|
@@ -27,100 +25,61 @@ pub struct Message {
|
|
}
|
|
}
|
|
|
|
|
|
struct App {
|
|
struct App {
|
|
- io: TcpStream,
|
|
|
|
- read_buf: BytesMut,
|
|
|
|
- write_buf: BytesMut,
|
|
|
|
- write_pos: usize,
|
|
|
|
|
|
+ state: State,
|
|
codec: h1::Codec,
|
|
codec: h1::Codec,
|
|
}
|
|
}
|
|
|
|
|
|
-impl App {
|
|
|
|
- fn handle_request(&mut self, req: Request) {
|
|
|
|
- match req.path() {
|
|
|
|
- "/json" => {
|
|
|
|
- self.write_buf.extend_from_slice(JSON);
|
|
|
|
- self.codec.set_date_header(&mut self.write_buf);
|
|
|
|
- Message {
|
|
|
|
- message: "Hello, World!",
|
|
|
|
- }
|
|
|
|
- .to_bytes_mut(&mut self.write_buf);
|
|
|
|
- }
|
|
|
|
- "/plaintext" => {
|
|
|
|
- self.write_buf.extend_from_slice(PLAIN);
|
|
|
|
- self.codec.set_date_header(&mut self.write_buf);
|
|
|
|
- self.write_buf.extend_from_slice(BODY);
|
|
|
|
- }
|
|
|
|
- _ => {
|
|
|
|
- self.write_buf.extend_from_slice(HTTPNFOUND);
|
|
|
|
- self.write_buf.extend_from_slice(HDR_SERVER);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
impl Future for App {
|
|
impl Future for App {
|
|
type Output = Result<(), ()>;
|
|
type Output = Result<(), ()>;
|
|
|
|
|
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
let this = self.as_mut().get_mut();
|
|
let this = self.as_mut().get_mut();
|
|
-
|
|
|
|
- if !this.write_buf.is_empty() {
|
|
|
|
- let len = this.write_buf.len();
|
|
|
|
- let mut written = this.write_pos;
|
|
|
|
- while written < len {
|
|
|
|
- match Pin::new(&mut this.io).poll_write(cx, &this.write_buf[written..]) {
|
|
|
|
- Poll::Pending => {
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- Poll::Ready(Ok(n)) => {
|
|
|
|
- if n == 0 {
|
|
|
|
- return Poll::Ready(Ok(()));
|
|
|
|
- } else {
|
|
|
|
- written += n;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- Poll::Ready(Err(_)) => return Poll::Ready(Err(())),
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if written == len {
|
|
|
|
- this.write_pos = 0;
|
|
|
|
- unsafe { this.write_buf.set_len(0) }
|
|
|
|
- } else if written > 0 {
|
|
|
|
- this.write_pos = written;
|
|
|
|
- return Poll::Pending;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if this.read_buf.capacity() - this.read_buf.len() < 4096 {
|
|
|
|
- this.read_buf.reserve(32_768);
|
|
|
|
|
|
+ if !this.state.is_open() {
|
|
|
|
+ this.state.close();
|
|
|
|
+ return Poll::Ready(Ok(()));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ let mut updated = false;
|
|
loop {
|
|
loop {
|
|
- let read = Pin::new(&mut this.io).poll_read_buf(cx, &mut this.read_buf);
|
|
|
|
- match read {
|
|
|
|
- Poll::Pending => break,
|
|
|
|
- Poll::Ready(Ok(n)) => {
|
|
|
|
- if n == 0 {
|
|
|
|
- return Poll::Ready(Ok(()));
|
|
|
|
|
|
+ match this.state.decode_item(&this.codec) {
|
|
|
|
+ Ok(Some((req, _))) => {
|
|
|
|
+ match req.path() {
|
|
|
|
+ "/json" => this.state.with_write_buf(|buf| {
|
|
|
|
+ buf.extend_from_slice(JSON);
|
|
|
|
+ this.codec.set_date_header(buf);
|
|
|
|
+ Message {
|
|
|
|
+ message: "Hello, World!",
|
|
|
|
+ }
|
|
|
|
+ .to_bytes_mut(buf);
|
|
|
|
+ }),
|
|
|
|
+ "/plaintext" => this.state.with_write_buf(|buf| {
|
|
|
|
+ buf.extend_from_slice(PLAIN);
|
|
|
|
+ this.codec.set_date_header(buf);
|
|
|
|
+ buf.extend_from_slice(BODY);
|
|
|
|
+ }),
|
|
|
|
+ _ => this.state.with_write_buf(|buf| {
|
|
|
|
+ buf.extend_from_slice(HTTPNFOUND);
|
|
|
|
+ buf.extend_from_slice(HDR_SERVER);
|
|
|
|
+ }),
|
|
}
|
|
}
|
|
|
|
+ updated = true;
|
|
}
|
|
}
|
|
- Poll::Ready(Err(_)) => return Poll::Ready(Err(())),
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- loop {
|
|
|
|
- match this.codec.decode(&mut this.read_buf) {
|
|
|
|
- Ok(Some(h1::Message::Item(req))) => this.handle_request(req),
|
|
|
|
Ok(None) => break,
|
|
Ok(None) => break,
|
|
- _ => return Poll::Ready(Err(())),
|
|
|
|
|
|
+ _ => {
|
|
|
|
+ this.state.close();
|
|
|
|
+ return Poll::Ready(Err(()));
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- if !this.write_buf.is_empty() {
|
|
|
|
- self.poll(cx)
|
|
|
|
- } else {
|
|
|
|
- Poll::Pending
|
|
|
|
|
|
+ if updated {
|
|
|
|
+ this.state.dsp_flush_write_data(cx.waker());
|
|
|
|
+ }
|
|
|
|
+ if !this.state.is_read_ready() {
|
|
|
|
+ this.state.dsp_read_more_data(cx.waker());
|
|
|
|
+ } else if !updated {
|
|
|
|
+ this.state.dsp_register_task(cx.waker());
|
|
}
|
|
}
|
|
|
|
+ Poll::Pending
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -132,12 +91,16 @@ async fn main() -> io::Result<()> {
|
|
ntex::server::build()
|
|
ntex::server::build()
|
|
.backlog(1024)
|
|
.backlog(1024)
|
|
.bind("techempower", "0.0.0.0:8080", || {
|
|
.bind("techempower", "0.0.0.0:8080", || {
|
|
- fn_service(|io: TcpStream| App {
|
|
|
|
- io,
|
|
|
|
- read_buf: BytesMut::with_capacity(32_768),
|
|
|
|
- write_buf: BytesMut::with_capacity(32_768),
|
|
|
|
- write_pos: 0,
|
|
|
|
- codec: h1::Codec::default(),
|
|
|
|
|
|
+ fn_service(|io: TcpStream| {
|
|
|
|
+ let state = State::new();
|
|
|
|
+ let io = Rc::new(RefCell::new(io));
|
|
|
|
+ ntex::rt::spawn(ReadTask::new(io.clone(), state.clone()));
|
|
|
|
+ ntex::rt::spawn(WriteTask::new(io, state.clone()));
|
|
|
|
+
|
|
|
|
+ App {
|
|
|
|
+ state,
|
|
|
|
+ codec: h1::Codec::default(),
|
|
|
|
+ }
|
|
})
|
|
})
|
|
})?
|
|
})?
|
|
.start()
|
|
.start()
|