feat(net): add socket timeouts to Server and Client

While these methods are marked unstable in libstd, this is behind a
feature flag, `timeouts`. The Client and Server both have
`set_read_timeout` and `set_write_timeout` methods, that will affect all
connections with that entity.

BREAKING CHANGE: Any custom implementation of NetworkStream must now
  implement `set_read_timeout` and `set_write_timeout`, so those will
  break. Most users who only use the provided streams should work with
  no changes needed.

Closes #315
This commit is contained in:
Sean McArthur
2015-06-16 11:02:36 -07:00
parent 421422b620
commit 7d1f154cb7
11 changed files with 311 additions and 50 deletions

View File

@@ -8,6 +8,9 @@ use std::mem;
#[cfg(feature = "openssl")]
pub use self::openssl::Openssl;
#[cfg(feature = "timeouts")]
use std::time::Duration;
use typeable::Typeable;
use traitobject;
@@ -21,8 +24,6 @@ pub enum Streaming {}
pub trait NetworkListener: Clone {
/// The stream produced for each connection.
type Stream: NetworkStream + Send + Clone;
/// Listens on a socket.
//fn listen<To: ToSocketAddrs>(&mut self, addr: To) -> io::Result<Self::Acceptor>;
/// Returns an iterator of streams.
fn accept(&mut self) -> ::Result<Self::Stream>;
@@ -30,9 +31,6 @@ pub trait NetworkListener: Clone {
/// Get the address this Listener ended up listening on.
fn local_addr(&mut self) -> io::Result<SocketAddr>;
/// Closes the Acceptor, so no more incoming connections will be handled.
// fn close(&mut self) -> io::Result<()>;
/// Returns an iterator over incoming connections.
fn incoming(&mut self) -> NetworkConnections<Self> {
NetworkConnections(self)
@@ -53,6 +51,12 @@ impl<'a, N: NetworkListener + 'a> Iterator for NetworkConnections<'a, N> {
pub trait NetworkStream: Read + Write + Any + Send + Typeable {
/// Get the remote address of the underlying connection.
fn peer_addr(&mut self) -> io::Result<SocketAddr>;
/// Set the maximum time to wait for a read to complete.
#[cfg(feature = "timeouts")]
fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()>;
/// Set the maximum time to wait for a write to complete.
#[cfg(feature = "timeouts")]
fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()>;
/// This will be called when Stream should no longer be kept alive.
#[inline]
fn close(&mut self, _how: Shutdown) -> io::Result<()> {
@@ -222,6 +226,18 @@ impl NetworkStream for HttpStream {
self.0.peer_addr()
}
#[cfg(feature = "timeouts")]
#[inline]
fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.0.set_read_timeout(dur)
}
#[cfg(feature = "timeouts")]
#[inline]
fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.0.set_write_timeout(dur)
}
#[inline]
fn close(&mut self, how: Shutdown) -> io::Result<()> {
match self.0.shutdown(how) {
@@ -312,6 +328,24 @@ impl<S: NetworkStream> NetworkStream for HttpsStream<S> {
}
}
#[cfg(feature = "timeouts")]
#[inline]
fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
match *self {
HttpsStream::Http(ref inner) => inner.0.set_read_timeout(dur),
HttpsStream::Https(ref inner) => inner.set_read_timeout(dur)
}
}
#[cfg(feature = "timeouts")]
#[inline]
fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
match *self {
HttpsStream::Http(ref inner) => inner.0.set_read_timeout(dur),
HttpsStream::Https(ref inner) => inner.set_read_timeout(dur)
}
}
#[inline]
fn close(&mut self, how: Shutdown) -> io::Result<()> {
match *self {
@@ -397,6 +431,9 @@ mod openssl {
use std::net::{SocketAddr, Shutdown};
use std::path::Path;
use std::sync::Arc;
#[cfg(feature = "timeouts")]
use std::time::Duration;
use openssl::ssl::{Ssl, SslContext, SslStream, SslMethod, SSL_VERIFY_NONE};
use openssl::ssl::error::StreamError as SslIoError;
use openssl::ssl::error::SslError;
@@ -475,6 +512,18 @@ mod openssl {
self.get_mut().peer_addr()
}
#[cfg(feature = "timeouts")]
#[inline]
fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.get_ref().set_read_timeout(dur)
}
#[cfg(feature = "timeouts")]
#[inline]
fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.get_ref().set_write_timeout(dur)
}
fn close(&mut self, how: Shutdown) -> io::Result<()> {
self.get_mut().close(how)
}