tokio_proto/
tcp_client.rs

1use std::{fmt, io};
2use std::sync::Arc;
3use std::net::SocketAddr;
4use std::marker::PhantomData;
5
6use BindClient;
7use tokio_core::reactor::Handle;
8use tokio_core::net::{TcpStream, TcpStreamNew};
9use futures::{Future, Poll, Async};
10
11// TODO: add configuration, e.g.:
12// - connection timeout
13// - multiple addresses
14// - request timeout
15
16// TODO: consider global event loop handle, so that providing one in the builder
17// is optional
18
19/// Builds client connections to external services.
20///
21/// To connect to a service, you need a *client protocol* implementation; see
22/// the crate documentation for guidance.
23///
24/// At the moment, this builder offers minimal configuration, but more will be
25/// added over time.
26#[derive(Debug)]
27pub struct TcpClient<Kind, P> {
28    _kind: PhantomData<Kind>,
29    proto: Arc<P>,
30}
31
32/// A future for establishing a client connection.
33///
34/// Yields a service for interacting with the server.
35pub struct Connect<Kind, P> {
36    _kind: PhantomData<Kind>,
37    proto: Arc<P>,
38    socket: TcpStreamNew,
39    handle: Handle,
40}
41
42impl<Kind, P> Future for Connect<Kind, P> where P: BindClient<Kind, TcpStream> {
43    type Item = P::BindClient;
44    type Error = io::Error;
45
46    fn poll(&mut self) -> Poll<P::BindClient, io::Error> {
47        let socket = try_ready!(self.socket.poll());
48        Ok(Async::Ready(self.proto.bind_client(&self.handle, socket)))
49    }
50}
51
52impl<Kind, P> TcpClient<Kind, P> where P: BindClient<Kind, TcpStream> {
53    /// Create a builder for the given client protocol.
54    ///
55    /// To connect to a service, you need a *client protocol* implementation;
56    /// see the crate documentation for guidance.
57    pub fn new(protocol: P) -> TcpClient<Kind, P> {
58        TcpClient {
59            _kind: PhantomData,
60            proto: Arc::new(protocol)
61        }
62    }
63
64    /// Establish a connection to the given address.
65    ///
66    /// # Return value
67    ///
68    /// Returns a future for the establishment of the connection. When the
69    /// future completes, it yields an instance of `Service` for interacting
70    /// with the server.
71    pub fn connect(&self, addr: &SocketAddr, handle: &Handle) -> Connect<Kind, P> {
72        Connect {
73            _kind: PhantomData,
74            proto: self.proto.clone(),
75            socket: TcpStream::connect(addr, handle),
76            handle: handle.clone(),
77        }
78    }
79}
80
81impl<Kind, P> fmt::Debug for Connect<Kind, P> {
82    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83        write!(f, "Connect {{ ... }}")
84    }
85}