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}