use std::{ptr, mem, time, io}; use std::rc::Rc; use std::net::{SocketAddr, Shutdown}; use bytes::{Bytes, BytesMut, Buf, BufMut}; use futures::{Future, Poll, Async}; use tokio_io::{AsyncRead, AsyncWrite}; use super::{h1, h2, utils, HttpHandler, IoStream}; use super::settings::WorkerSettings; const HTTP2_PREFACE: [u8; 14] = *b"PRI * HTTP/2.0"; enum HttpProtocol { H1(h1::Http1), H2(h2::Http2), Unknown(Rc>, Option, T, BytesMut), } impl HttpProtocol { fn is_unknown(&self) -> bool { match *self { HttpProtocol::Unknown(_, _, _, _) => true, _ => false } } } enum ProtocolKind { Http1, Http2, } #[doc(hidden)] pub struct HttpChannel where T: IoStream, H: HttpHandler + 'static { proto: Option>, node: Option>>, } impl HttpChannel where T: IoStream, H: HttpHandler + 'static { pub(crate) fn new(settings: Rc>, io: T, peer: Option, http2: bool) -> HttpChannel { settings.add_channel(); if http2 { HttpChannel { node: None, proto: Some(HttpProtocol::H2( h2::Http2::new(settings, io, peer, Bytes::new()))) } } else { HttpChannel { node: None, proto: Some(HttpProtocol::Unknown( settings, peer, io, BytesMut::with_capacity(4096))) } } } fn shutdown(&mut self) { match self.proto { Some(HttpProtocol::H1(ref mut h1)) => { let io = h1.io(); let _ = IoStream::set_linger(io, Some(time::Duration::new(0, 0))); let _ = IoStream::shutdown(io, Shutdown::Both); } Some(HttpProtocol::H2(ref mut h2)) => { h2.shutdown() } _ => (), } } } impl Future for HttpChannel where T: IoStream, H: HttpHandler + 'static { type Item = (); type Error = (); fn poll(&mut self) -> Poll { if !self.proto.as_ref().map(|p| p.is_unknown()).unwrap_or(false) && self.node.is_none() { self.node = Some(Node::new(self)); match self.proto { Some(HttpProtocol::H1(ref mut h1)) => h1.settings().head().insert(self.node.as_ref().unwrap()), Some(HttpProtocol::H2(ref mut h2)) => h2.settings().head().insert(self.node.as_ref().unwrap()), _ => (), } } let kind = match self.proto { Some(HttpProtocol::H1(ref mut h1)) => { let result = h1.poll(); match result { Ok(Async::Ready(())) | Err(_) => { h1.settings().remove_channel(); self.node.as_ref().unwrap().remove(); }, _ => (), } return result }, Some(HttpProtocol::H2(ref mut h2)) => { let result = h2.poll(); match result { Ok(Async::Ready(())) | Err(_) => { h2.settings().remove_channel(); self.node.as_ref().unwrap().remove(); }, _ => (), } return result }, Some(HttpProtocol::Unknown(ref mut settings, _, ref mut io, ref mut buf)) => { match utils::read_from_io(io, buf) { Ok(Async::Ready(0)) | Err(_) => { debug!("Ignored premature client disconnection"); settings.remove_channel(); return Err(()) }, _ => (), } if buf.len() >= 14 { if buf[..14] == HTTP2_PREFACE[..] { ProtocolKind::Http2 } else { ProtocolKind::Http1 } } else { return Ok(Async::NotReady); } }, None => unreachable!(), }; // upgrade to specific http protocol if let Some(HttpProtocol::Unknown(settings, addr, io, buf)) = self.proto.take() { match kind { ProtocolKind::Http1 => { self.proto = Some( HttpProtocol::H1(h1::Http1::new(settings, io, addr, buf))); return self.poll() }, ProtocolKind::Http2 => { self.proto = Some( HttpProtocol::H2(h2::Http2::new(settings, io, addr, buf.freeze()))); return self.poll() }, } } unreachable!() } } pub(crate) struct Node { next: Option<*mut Node<()>>, prev: Option<*mut Node<()>>, element: *mut T, } impl Node { fn new(el: &mut T) -> Self { Node { next: None, prev: None, element: el as *mut _, } } fn insert(&self, next: &Node) { #[allow(mutable_transmutes)] unsafe { if let Some(ref next2) = self.next { let n: &mut Node<()> = mem::transmute(next2.as_ref().unwrap()); n.prev = Some(next as *const _ as *mut _); } let slf: &mut Node = mem::transmute(self); slf.next = Some(next as *const _ as *mut _); let next: &mut Node = mem::transmute(next); next.prev = Some(slf as *const _ as *mut _); } } fn remove(&self) { #[allow(mutable_transmutes)] unsafe { if let Some(ref prev) = self.prev { let p: &mut Node<()> = mem::transmute(prev.as_ref().unwrap()); let slf: &mut Node = mem::transmute(self); p.next = slf.next.take(); } } } } impl Node<()> { pub(crate) fn head() -> Self { Node { next: None, prev: None, element: ptr::null_mut(), } } pub(crate) fn traverse(&self) where T: IoStream, H: HttpHandler + 'static { let mut next = self.next.as_ref(); loop { if let Some(n) = next { unsafe { let n: &Node<()> = mem::transmute(n.as_ref().unwrap()); next = n.next.as_ref(); if !n.element.is_null() { let ch: &mut HttpChannel = mem::transmute( &mut *(n.element as *mut _)); ch.shutdown(); } } } else { return } } } } /// Wrapper for `AsyncRead + AsyncWrite` types pub(crate) struct WrapperStream where T: AsyncRead + AsyncWrite + 'static { io: T, } impl WrapperStream where T: AsyncRead + AsyncWrite + 'static { pub fn new(io: T) -> Self { WrapperStream{io: io} } } impl IoStream for WrapperStream where T: AsyncRead + AsyncWrite + 'static { #[inline] fn shutdown(&mut self, _: Shutdown) -> io::Result<()> { Ok(()) } #[inline] fn set_nodelay(&mut self, _: bool) -> io::Result<()> { Ok(()) } #[inline] fn set_linger(&mut self, _: Option) -> io::Result<()> { Ok(()) } } impl io::Read for WrapperStream where T: AsyncRead + AsyncWrite + 'static { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { self.io.read(buf) } } impl io::Write for WrapperStream where T: AsyncRead + AsyncWrite + 'static { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { self.io.write(buf) } #[inline] fn flush(&mut self) -> io::Result<()> { self.io.flush() } } impl AsyncRead for WrapperStream where T: AsyncRead + AsyncWrite + 'static { #[inline] fn read_buf(&mut self, buf: &mut B) -> Poll { self.io.read_buf(buf) } } impl AsyncWrite for WrapperStream where T: AsyncRead + AsyncWrite + 'static { #[inline] fn shutdown(&mut self) -> Poll<(), io::Error> { self.io.shutdown() } #[inline] fn write_buf(&mut self, buf: &mut B) -> Poll { self.io.write_buf(buf) } }