use std::fmt;
use std::io::{self, Read, Write};
use std::mem;
use std::net::{self, Shutdown, SocketAddr};
use std::time::Duration;
use bytes::{Buf, BufMut};
use futures::{Async, Future, Poll};
use iovec::IoVec;
use mio;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_reactor::{Handle, PollEvented};
pub struct TcpStream {
io: PollEvented<mio::net::TcpStream>,
}
#[must_use = "futures do nothing unless polled"]
#[derive(Debug)]
pub struct ConnectFuture {
inner: ConnectFutureState,
}
#[must_use = "futures do nothing unless polled"]
#[derive(Debug)]
enum ConnectFutureState {
Waiting(TcpStream),
Error(io::Error),
Empty,
}
impl TcpStream {
pub fn connect(addr: &SocketAddr) -> ConnectFuture {
use self::ConnectFutureState::*;
let inner = match mio::net::TcpStream::connect(addr) {
Ok(tcp) => Waiting(TcpStream::new(tcp)),
Err(e) => Error(e),
};
ConnectFuture { inner }
}
pub(crate) fn new(connected: mio::net::TcpStream) -> TcpStream {
let io = PollEvented::new(connected);
TcpStream { io }
}
pub fn from_std(stream: net::TcpStream, handle: &Handle) -> io::Result<TcpStream> {
let io = mio::net::TcpStream::from_stream(stream)?;
let io = PollEvented::new_with_handle(io, handle)?;
Ok(TcpStream { io })
}
pub fn connect_std(
stream: net::TcpStream,
addr: &SocketAddr,
handle: &Handle,
) -> ConnectFuture {
use self::ConnectFutureState::*;
let io = mio::net::TcpStream::connect_stream(stream, addr)
.and_then(|io| PollEvented::new_with_handle(io, handle));
let inner = match io {
Ok(io) => Waiting(TcpStream { io }),
Err(e) => Error(e),
};
ConnectFuture { inner: inner }
}
pub fn poll_read_ready(&self, mask: mio::Ready) -> Poll<mio::Ready, io::Error> {
self.io.poll_read_ready(mask)
}
pub fn poll_write_ready(&self) -> Poll<mio::Ready, io::Error> {
self.io.poll_write_ready()
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
self.io.get_ref().local_addr()
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
self.io.get_ref().peer_addr()
}
#[deprecated(since = "0.1.2", note = "use poll_peek instead")]
#[doc(hidden)]
pub fn peek(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self.poll_peek(buf)? {
Async::Ready(n) => Ok(n),
Async::NotReady => Err(io::ErrorKind::WouldBlock.into()),
}
}
pub fn poll_peek(&mut self, buf: &mut [u8]) -> Poll<usize, io::Error> {
try_ready!(self.io.poll_read_ready(mio::Ready::readable()));
match self.io.get_ref().peek(buf) {
Ok(ret) => Ok(ret.into()),
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
self.io.clear_read_ready(mio::Ready::readable())?;
Ok(Async::NotReady)
}
Err(e) => Err(e),
}
}
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
self.io.get_ref().shutdown(how)
}
pub fn nodelay(&self) -> io::Result<bool> {
self.io.get_ref().nodelay()
}
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
self.io.get_ref().set_nodelay(nodelay)
}
pub fn recv_buffer_size(&self) -> io::Result<usize> {
self.io.get_ref().recv_buffer_size()
}
pub fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
self.io.get_ref().set_recv_buffer_size(size)
}
pub fn send_buffer_size(&self) -> io::Result<usize> {
self.io.get_ref().send_buffer_size()
}
pub fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
self.io.get_ref().set_send_buffer_size(size)
}
pub fn keepalive(&self) -> io::Result<Option<Duration>> {
self.io.get_ref().keepalive()
}
pub fn set_keepalive(&self, keepalive: Option<Duration>) -> io::Result<()> {
self.io.get_ref().set_keepalive(keepalive)
}
pub fn ttl(&self) -> io::Result<u32> {
self.io.get_ref().ttl()
}
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
self.io.get_ref().set_ttl(ttl)
}
pub fn linger(&self) -> io::Result<Option<Duration>> {
self.io.get_ref().linger()
}
pub fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
self.io.get_ref().set_linger(dur)
}
#[deprecated(since = "0.1.14", note = "use `split()` instead")]
#[doc(hidden)]
pub fn try_clone(&self) -> io::Result<TcpStream> {
let msg = "`TcpStream::try_clone()` is deprecated because it doesn't work as intended";
Err(io::Error::new(io::ErrorKind::Other, msg))
}
}
impl Read for TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.io.read(buf)
}
}
impl Write for TcpStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.io.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl AsyncRead for TcpStream {
unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool {
false
}
fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Poll<usize, io::Error> {
<&TcpStream>::read_buf(&mut &*self, buf)
}
}
impl AsyncWrite for TcpStream {
fn shutdown(&mut self) -> Poll<(), io::Error> {
<&TcpStream>::shutdown(&mut &*self)
}
fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Poll<usize, io::Error> {
<&TcpStream>::write_buf(&mut &*self, buf)
}
}
impl<'a> Read for &'a TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
(&self.io).read(buf)
}
}
impl<'a> Write for &'a TcpStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
(&self.io).write(buf)
}
fn flush(&mut self) -> io::Result<()> {
(&self.io).flush()
}
}
impl<'a> AsyncRead for &'a TcpStream {
unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool {
false
}
fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Poll<usize, io::Error> {
if let Async::NotReady = self.io.poll_read_ready(mio::Ready::readable())? {
return Ok(Async::NotReady);
}
let r = unsafe {
let b1: &mut [u8] = &mut [0];
let b2: &mut [u8] = &mut [0];
let b3: &mut [u8] = &mut [0];
let b4: &mut [u8] = &mut [0];
let b5: &mut [u8] = &mut [0];
let b6: &mut [u8] = &mut [0];
let b7: &mut [u8] = &mut [0];
let b8: &mut [u8] = &mut [0];
let b9: &mut [u8] = &mut [0];
let b10: &mut [u8] = &mut [0];
let b11: &mut [u8] = &mut [0];
let b12: &mut [u8] = &mut [0];
let b13: &mut [u8] = &mut [0];
let b14: &mut [u8] = &mut [0];
let b15: &mut [u8] = &mut [0];
let b16: &mut [u8] = &mut [0];
let mut bufs: [&mut IoVec; 16] = [
b1.into(),
b2.into(),
b3.into(),
b4.into(),
b5.into(),
b6.into(),
b7.into(),
b8.into(),
b9.into(),
b10.into(),
b11.into(),
b12.into(),
b13.into(),
b14.into(),
b15.into(),
b16.into(),
];
let n = buf.bytes_vec_mut(&mut bufs);
self.io.get_ref().read_bufs(&mut bufs[..n])
};
match r {
Ok(n) => {
unsafe {
buf.advance_mut(n);
}
Ok(Async::Ready(n))
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
self.io.clear_read_ready(mio::Ready::readable())?;
Ok(Async::NotReady)
}
Err(e) => Err(e),
}
}
}
impl<'a> AsyncWrite for &'a TcpStream {
fn shutdown(&mut self) -> Poll<(), io::Error> {
Ok(().into())
}
fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Poll<usize, io::Error> {
if let Async::NotReady = self.io.poll_write_ready()? {
return Ok(Async::NotReady);
}
let r = {
static DUMMY: &[u8] = &[0];
let iovec = <&IoVec>::from(DUMMY);
let mut bufs = [iovec; 64];
let n = buf.bytes_vec(&mut bufs);
self.io.get_ref().write_bufs(&bufs[..n])
};
match r {
Ok(n) => {
buf.advance(n);
Ok(Async::Ready(n))
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
self.io.clear_write_ready()?;
Ok(Async::NotReady)
}
Err(e) => Err(e),
}
}
}
impl fmt::Debug for TcpStream {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.io.get_ref().fmt(f)
}
}
impl Future for ConnectFuture {
type Item = TcpStream;
type Error = io::Error;
fn poll(&mut self) -> Poll<TcpStream, io::Error> {
self.inner.poll()
}
}
impl ConnectFutureState {
fn poll_inner<F>(&mut self, f: F) -> Poll<TcpStream, io::Error>
where
F: FnOnce(&mut PollEvented<mio::net::TcpStream>) -> Poll<mio::Ready, io::Error>,
{
{
let stream = match *self {
ConnectFutureState::Waiting(ref mut s) => s,
ConnectFutureState::Error(_) => {
let e = match mem::replace(self, ConnectFutureState::Empty) {
ConnectFutureState::Error(e) => e,
_ => panic!(),
};
return Err(e);
}
ConnectFutureState::Empty => panic!("can't poll TCP stream twice"),
};
if let Async::NotReady = f(&mut stream.io)? {
return Ok(Async::NotReady);
}
if let Some(e) = stream.io.get_ref().take_error()? {
return Err(e);
}
}
match mem::replace(self, ConnectFutureState::Empty) {
ConnectFutureState::Waiting(stream) => Ok(Async::Ready(stream)),
_ => panic!(),
}
}
}
impl Future for ConnectFutureState {
type Item = TcpStream;
type Error = io::Error;
fn poll(&mut self) -> Poll<TcpStream, io::Error> {
self.poll_inner(|io| io.poll_write_ready())
}
}
#[cfg(unix)]
mod sys {
use super::TcpStream;
use std::os::unix::prelude::*;
impl AsRawFd for TcpStream {
fn as_raw_fd(&self) -> RawFd {
self.io.get_ref().as_raw_fd()
}
}
}
#[cfg(windows)]
mod sys {
}