//! Convenience wrapper for streams to switch between plain TCP and TLS at runtime. //! //! There is no dependency on actual TLS implementations. Everything like //! `native_tls` or `openssl` will work as long as there is a TLS stream supporting standard //! `Read + Write` traits. use std::io::{Error as IoError, Read, Result as IoResult, Write}; use std::net::SocketAddr; use bytes::{Buf, BufMut}; use futures::Poll; use tokio_io::{AsyncRead, AsyncWrite}; /// Trait to switch TCP_NODELAY. pub trait NoDelay { /// Set the TCP_NODELAY option to the given value. fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()>; } /// Trait to get the remote address from the underlying stream. pub trait PeerAddr { /// Returns the remote address that this stream is connected to. fn peer_addr(&self) -> IoResult; } /// Stream, either plain TCP or TLS. pub enum Stream { /// Unencrypted socket stream. Plain(S), /// Encrypted socket stream. Tls(T), } impl Read for Stream { fn read(&mut self, buf: &mut [u8]) -> IoResult { match *self { Stream::Plain(ref mut s) => s.read(buf), Stream::Tls(ref mut s) => s.read(buf), } } } impl Write for Stream { fn write(&mut self, buf: &[u8]) -> IoResult { match *self { Stream::Plain(ref mut s) => s.write(buf), Stream::Tls(ref mut s) => s.write(buf), } } fn flush(&mut self) -> IoResult<()> { match *self { Stream::Plain(ref mut s) => s.flush(), Stream::Tls(ref mut s) => s.flush(), } } } impl NoDelay for Stream { fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()> { match *self { Stream::Plain(ref mut s) => s.set_nodelay(nodelay), Stream::Tls(ref mut s) => s.set_nodelay(nodelay), } } } impl PeerAddr for Stream { fn peer_addr(&self) -> IoResult { match *self { Stream::Plain(ref s) => s.peer_addr(), Stream::Tls(ref s) => s.peer_addr(), } } } impl AsyncRead for Stream { unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { match *self { Stream::Plain(ref s) => s.prepare_uninitialized_buffer(buf), Stream::Tls(ref s) => s.prepare_uninitialized_buffer(buf), } } fn read_buf(&mut self, buf: &mut B) -> Poll { match *self { Stream::Plain(ref mut s) => s.read_buf(buf), Stream::Tls(ref mut s) => s.read_buf(buf), } } } impl AsyncWrite for Stream { fn shutdown(&mut self) -> Poll<(), IoError> { match *self { Stream::Plain(ref mut s) => s.shutdown(), Stream::Tls(ref mut s) => s.shutdown(), } } fn write_buf(&mut self, buf: &mut B) -> Poll { match *self { Stream::Plain(ref mut s) => s.write_buf(buf), Stream::Tls(ref mut s) => s.write_buf(buf), } } }