tokio_proto/
lib.rs

1//! This library provides a toolkit for rapid protocol development and usage,
2//! working with the rest of the Tokio stack.
3//!
4//! You can find extensive documentation and tutorials in addition to this
5//! documentation at [https://tokio.rs](https://tokio.rs)
6//!
7//! # Protocols
8//!
9//! Here, a **protocol** is a way of providing or consuming a service. Protocols
10//! are implemented via traits, which are arranged into a taxonomy:
11//!
12//! - `pipeline::{ClientProto, ServerProto}`
13//! - `multiplex::{ClientProto, ServerProto}`
14//! - `streaming::pipeline::{ClientProto, ServerProto}`
15//! - `streaming::multiplex::{ClientProto, ServerProto}`
16//!
17//! ### Pipeline vs multiplex
18//!
19//! By default, protocols allow a client to transmit multiple requests without
20//! waiting for the corresponding responses, which is commonly used to improve
21//! the throughput of single connections.
22//!
23//! In a **pipelined protocol**, the server responds to client requests in the
24//! order they were sent. Example pipelined protocols include HTTP/1.1 and Redis.
25//! Pipelining with the max number of in-flight requests set to 1 implies that
26//! for each request, the response must be received before sending another
27//! request on the same connection.
28//!
29//! In a **multiplexed protocol**, the server responds to client requests in the
30//! order of completion. Request IDs are used to match responses back to requests.
31//!
32//! In both cases, if multiple requests are sent, the service running on the
33//! server *may* process them concurrently, although many services will impose
34//! some restrictions depending on the request type.
35//!
36//! ### Streaming
37//!
38//! In a non-streaming protocols, the client sends a complete request in a
39//! single message, and the server provides a complete response in a single
40//! message. Protocol tools in this style are available in the top-level `pipeline`
41//! and `multiplex` modules.
42//!
43//! In a **streaming protocol**, requests and responses can carry **body
44//! streams**, which allows partial processing before the complete body has been
45//! transferred. Streaming protocol tools are found within the `streaming`
46//! submodule.
47//!
48//! # Transports
49//!
50//! A key part of any protocol is its **transport**, which is the way that it
51//! sends and receives *frames* on its connection. For simple protocols, these
52//! frames correspond directly to complete requests and responses. For more
53//! complicated protocols, they carry additional metadata, and may only be one
54//! part of a request or response body.
55//!
56//! Transports are defined by implementing the `transport::Transport` trait. The
57//! `transport::CodecTransport` type can be used to wrap a `Codec` (from
58//! `tokio-core`), which is a simple way to build a transport.
59//!
60//! # An example server
61//!
62//! The following code shows how to implement a simple server that receives
63//! newline-separated integer values, doubles them, and returns them. It
64//! illustrates several aspects of the Tokio stack:
65//!
66//! - Implementing a codec `IntCodec` for reading and writing integers from a
67//!   byte buffer.
68//! - Implementing a server protocol `IntProto` using this codec as a transport.
69//! - Implementing a service `Doubler` for doubling integers.
70//! - Spinning up this service on a local port (in `main`).
71//!
72//! ```no_run
73//! extern crate futures;
74//! extern crate tokio_core;
75//! extern crate tokio_proto;
76//! extern crate tokio_service;
77//!
78//! use std::str;
79//! use std::io::{self, ErrorKind, Write};
80//!
81//! use futures::{future, Future, BoxFuture};
82//! use tokio_core::io::{Io, Codec, Framed, EasyBuf};
83//! use tokio_proto::TcpServer;
84//! use tokio_proto::pipeline::ServerProto;
85//! use tokio_service::Service;
86//!
87//! // First, we implement a *codec*, which provides a way of encoding and
88//! // decoding messages for the protocol. See the documentation for `Codec` in
89//! // `tokio-core` for more details on how that works.
90//!
91//! #[derive(Default)]
92//! pub struct IntCodec;
93//!
94//! fn parse_u64(from: &[u8]) -> Result<u64, io::Error> {
95//!     Ok(str::from_utf8(from)
96//!        .map_err(|e| io::Error::new(ErrorKind::InvalidData, e))?
97//!        .parse()
98//!        .map_err(|e| io::Error::new(ErrorKind::InvalidData, e))?)
99//! }
100//!
101//! impl Codec for IntCodec {
102//!     type In = u64;
103//!     type Out = u64;
104//!
105//!     // Attempt to decode a message from the given buffer if a complete
106//!     // message is available; returns `Ok(None)` if the buffer does not yet
107//!     // hold a complete message.
108//!     fn decode(&mut self, buf: &mut EasyBuf) -> Result<Option<u64>, io::Error> {
109//!         if let Some(i) = buf.as_slice().iter().position(|&b| b == b'\n') {
110//!             // remove the line, including the '\n', from the buffer
111//!             let full_line = buf.drain_to(i + 1);
112//!
113//!             // strip the'`\n'
114//!             let slice = &full_line.as_slice()[..i];
115//!
116//!             Ok(Some(parse_u64(slice)?))
117//!         } else {
118//!             Ok(None)
119//!         }
120//!     }
121//!
122//!     // Attempt to decode a message assuming that the given buffer contains
123//!     // *all* remaining input data.
124//!     fn decode_eof(&mut self, buf: &mut EasyBuf) -> io::Result<u64> {
125//!         let amt = buf.len();
126//!         Ok(parse_u64(buf.drain_to(amt).as_slice())?)
127//!     }
128//!
129//!     fn encode(&mut self, item: u64, into: &mut Vec<u8>) -> io::Result<()> {
130//!         writeln!(into, "{}", item);
131//!         Ok(())
132//!     }
133//! }
134//!
135//! // Next, we implement the server protocol, which just hooks up the codec above.
136//!
137//! pub struct IntProto;
138//!
139//! impl<T: Io + 'static> ServerProto<T> for IntProto {
140//!     type Request = u64;
141//!     type Response = u64;
142//!     type Transport = Framed<T, IntCodec>;
143//!     type BindTransport = Result<Self::Transport, io::Error>;
144//!
145//!     fn bind_transport(&self, io: T) -> Self::BindTransport {
146//!         Ok(io.framed(IntCodec))
147//!     }
148//! }
149//!
150//! // Now we implement a service we'd like to run on top of this protocol
151//!
152//! pub struct Doubler;
153//!
154//! impl Service for Doubler {
155//!     type Request = u64;
156//!     type Response = u64;
157//!     type Error = io::Error;
158//!     type Future = BoxFuture<u64, io::Error>;
159//!
160//!     fn call(&self, req: u64) -> Self::Future {
161//!         // Just return the request, doubled
162//!         future::finished(req * 2).boxed()
163//!     }
164//! }
165//!
166//! // Finally, we can actually host this service locally!
167//! fn main() {
168//!     let addr = "0.0.0.0:12345".parse().unwrap();
169//!     TcpServer::new(IntProto, addr)
170//!         .serve(|| Ok(Doubler));
171//! }
172//! ```
173
174#![doc(html_root_url = "https://docs.rs/tokio-proto/0.1")]
175#![deny(warnings, missing_docs, missing_debug_implementations)]
176#![allow(deprecated)] // TODO remove this
177
178extern crate net2;
179extern crate rand;
180extern crate slab;
181extern crate smallvec;
182extern crate take;
183extern crate tokio_core;
184extern crate tokio_io;
185extern crate tokio_service;
186
187#[macro_use]
188extern crate futures;
189
190#[macro_use]
191extern crate log;
192
193mod simple;
194pub use simple::{pipeline, multiplex};
195
196pub mod streaming;
197pub mod util;
198
199mod tcp_client;
200pub use tcp_client::{TcpClient, Connect};
201
202mod tcp_server;
203pub use tcp_server::TcpServer;
204
205use tokio_core::reactor::Handle;
206use tokio_service::Service;
207
208// TODO: move this into futures-rs
209mod buffer_one;
210
211/// Binds a service to an I/O object.
212///
213/// This trait is not intended to be implemented directly; instead, implement
214/// one of the server protocol traits:
215///
216/// - `pipeline::ServerProto`
217/// - `multiplex::ServerProto`
218/// - `streaming::pipeline::ServerProto`
219/// - `streaming::multiplex::ServerProto`
220///
221/// See the crate documentation for more details on those traits.
222///
223/// The `Kind` parameter, in particular, is a zero-sized type used to allow
224/// blanket implementation from the various protocol traits. Any additional
225/// implementations of this trait should use their own zero-sized kind type to
226/// distinguish them.
227pub trait BindServer<Kind, T: 'static>: 'static {
228    /// The request type for the service.
229    type ServiceRequest;
230
231    /// The response type for the service.
232    type ServiceResponse;
233
234    /// The error type for the service.
235    type ServiceError;
236
237    /// Bind the service.
238    ///
239    /// This method should spawn a new task on the given event loop handle which
240    /// provides the given service on the given I/O object.
241    fn bind_server<S>(&self, handle: &Handle, io: T, service: S)
242        where S: Service<Request = Self::ServiceRequest,
243                         Response = Self::ServiceResponse,
244                         Error = Self::ServiceError> + 'static;
245}
246
247/// Binds an I/O object as a client of a service.
248///
249/// This trait is not intended to be implemented directly; instead, implement
250/// one of the server protocol traits:
251///
252/// - `pipeline::ClientProto`
253/// - `multiplex::ClientProto`
254/// - `streaming::pipeline::ClientProto`
255/// - `streaming::multiplex::ClientProto`
256///
257/// See the crate documentation for more details on those traits.
258///
259/// The `Kind` parameter, in particular, is a zero-sized type used to allow
260/// blanket implementation from the various protocol traits. Any additional
261/// implementations of this trait should use their own zero-sized kind type to
262/// distinguish them.
263pub trait BindClient<Kind, T: 'static>: 'static {
264    /// The request type for the service.
265    type ServiceRequest;
266
267    /// The response type for the service.
268    type ServiceResponse;
269
270    /// The error type for the service.
271    type ServiceError;
272
273    /// The bound service.
274    type BindClient: Service<Request = Self::ServiceRequest,
275                             Response = Self::ServiceResponse,
276                             Error = Self::ServiceError>;
277
278    /// Bind an I/O object as a service.
279    fn bind_client(&self, handle: &Handle, io: T) -> Self::BindClient;
280}