parity_ws/
lib.rs

1//! Lightweight, event-driven WebSockets for Rust.
2#![allow(deprecated)]
3#![deny(missing_copy_implementations, trivial_casts, trivial_numeric_casts, unstable_features,
4        unused_import_braces)]
5
6extern crate byteorder;
7extern crate bytes;
8extern crate httparse;
9extern crate mio;
10extern crate mio_extras;
11#[cfg(feature = "ssl")]
12extern crate openssl;
13#[cfg(feature = "nativetls")]
14extern crate native_tls;
15extern crate rand;
16extern crate sha1;
17extern crate slab;
18extern crate url;
19#[macro_use]
20extern crate log;
21
22mod circular_buffer;
23mod communication;
24mod connection;
25mod factory;
26mod frame;
27mod handler;
28mod handshake;
29mod io;
30mod message;
31mod protocol;
32mod result;
33mod stream;
34
35#[cfg(feature = "permessage-deflate")]
36pub mod deflate;
37
38pub mod util;
39
40pub use factory::Factory;
41pub use handler::Handler;
42
43pub use communication::Sender;
44pub use frame::Frame;
45pub use handshake::{Handshake, Request, Response};
46pub use message::Message;
47pub use protocol::{CloseCode, OpCode};
48pub use result::Kind as ErrorKind;
49pub use result::{Error, Result};
50
51use std::borrow::Borrow;
52use std::default::Default;
53use std::fmt;
54use std::net::{SocketAddr, ToSocketAddrs};
55
56use mio::Poll;
57
58/// A utility function for setting up a WebSocket server.
59///
60/// # Safety
61///
62/// This function blocks until the event loop finishes running. Avoid calling this method within
63/// another WebSocket handler.
64///
65/// # Examples
66///
67/// ```no_run
68/// use parity_ws::listen;
69///
70/// listen("127.0.0.1:3012", |out| {
71///     move |msg| {
72///        out.send(msg)
73///    }
74/// }).unwrap()
75/// ```
76///
77pub fn listen<A, F, H>(addr: A, factory: F) -> Result<()>
78where
79    A: ToSocketAddrs + fmt::Debug,
80    F: FnMut(Sender) -> H,
81    H: Handler,
82{
83    let ws = WebSocket::new(factory)?;
84    ws.listen(addr)?;
85    Ok(())
86}
87
88/// A utility function for setting up a WebSocket client.
89///
90/// # Safety
91///
92/// This function blocks until the event loop finishes running. Avoid calling this method within
93/// another WebSocket handler. If you need to establish a connection from inside of a handler,
94/// use the `connect` method on the Sender.
95///
96/// # Examples
97///
98/// ```no_run
99/// use parity_ws::{connect, CloseCode};
100///
101/// connect("ws://127.0.0.1:3012", |out| {
102///     out.send("Hello WebSocket").unwrap();
103///
104///     move |msg| {
105///         println!("Got message: {}", msg);
106///         out.close(CloseCode::Normal)
107///     }
108/// }).unwrap()
109/// ```
110///
111pub fn connect<U, F, H>(url: U, factory: F) -> Result<()>
112where
113    U: Borrow<str>,
114    F: FnMut(Sender) -> H,
115    H: Handler,
116{
117    let mut ws = WebSocket::new(factory)?;
118    let parsed = url::Url::parse(url.borrow()).map_err(|err| {
119        Error::new(
120            ErrorKind::Internal,
121            format!("Unable to parse {} as url due to {:?}", url.borrow(), err),
122        )
123    })?;
124    ws.connect(parsed)?;
125    ws.run()?;
126    Ok(())
127}
128
129/// WebSocket settings
130#[non_exhaustive]
131#[derive(Debug, Clone, Copy)]
132pub struct Settings {
133    /// The maximum number of connections that this WebSocket will support.
134    /// The default setting is low and should be increased when expecting more
135    /// connections because this is a hard limit and no new connections beyond
136    /// this limit can be made until an old connection is dropped.
137    /// Default: 100
138    pub max_connections: usize,
139    /// The number of events anticipated per connection. The event loop queue size will
140    /// be `queue_size` * `max_connections`. In order to avoid an overflow error,
141    /// `queue_size` * `max_connections` must be less than or equal to `usize::max_value()`.
142    /// The queue is shared between connections, which means that a connection may schedule
143    /// more events than `queue_size` provided that another connection is using less than
144    /// `queue_size`. However, if the queue is maxed out a Queue error will occur.
145    /// Default: 5
146    pub queue_size: usize,
147    /// Whether to panic when unable to establish a new TCP connection.
148    /// Default: false
149    pub panic_on_new_connection: bool,
150    /// Whether to panic when a shutdown of the WebSocket is requested.
151    /// Default: false
152    pub panic_on_shutdown: bool,
153    /// The maximum number of fragments the connection can handle without reallocating.
154    /// Default: 10
155    pub fragments_capacity: usize,
156    /// Whether to reallocate when `fragments_capacity` is reached. If this is false,
157    /// a Capacity error will be triggered instead.
158    /// Default: true
159    pub fragments_grow: bool,
160    /// The maximum length of outgoing frames. Messages longer than this will be fragmented.
161    /// Default: 65,535
162    pub fragment_size: usize,
163    /// The maximum length of a single frame. Frames longer than this will be rejected.
164    /// Default: unlimited
165    pub max_fragment_size: usize,
166    /// The maximum total length of all incoming frames. Messages longer than this will be rejected.
167    /// Default: unlimited
168    pub max_total_fragments_size: usize,
169    /// The initial size of the incoming buffer. A larger buffer uses more memory but will allow for
170    /// fewer reallocations.
171    /// Default: 2048
172    pub in_buffer_capacity: usize,
173    /// The maximum size to which the incoming buffer can grow. This is a hard limit, and anything
174    /// written to the buffer over this limit will result in an error.
175    /// Default: 10,485,760
176    pub in_buffer_capacity_hard_limit: usize,
177    /// The maximum size to which the incoming buffer should grow. This is a soft limit, so it is
178    /// possible for the buffer to grow over this limit, however once its capacity grows beyond
179    /// this value it will be freed as soon as the buffer is emptied out, and reallocated with
180    /// its initial capacity once it's needed again.
181    /// Default: 1,048,576
182    pub in_buffer_capacity_soft_limit: usize,
183    /// The initial size of the outgoing buffer. A larger buffer uses more memory but will allow for
184    /// fewer reallocations.
185    /// Default: 2048
186    pub out_buffer_capacity: usize,
187    /// The maximum size to which the outgoing buffer can grow. This is a hard limit, and anything
188    /// written to the buffer over this limit will result in an error.
189    /// Default: 10,485,760
190    pub out_buffer_capacity_hard_limit: usize,
191    /// The maximum size to which the outgoing buffer should grow. This is a soft limit, so it is
192    /// possible for the buffer to grow over this limit, however once its capacity grows beyond
193    /// this value it will be freed as soon as the buffer is emptied out, and reallocated with
194    /// its initial capacity once it's needed again.
195    /// Default: 1,048,576
196    pub out_buffer_capacity_soft_limit: usize,
197    /// Whether to panic when an Internal error is encountered. Internal errors should generally
198    /// not occur, so this setting defaults to true as a debug measure, whereas production
199    /// applications should consider setting it to false.
200    /// Default: true
201    pub panic_on_internal: bool,
202    /// Whether to panic when a Capacity error is encountered.
203    /// Default: false
204    pub panic_on_capacity: bool,
205    /// Whether to panic when a Protocol error is encountered.
206    /// Default: false
207    pub panic_on_protocol: bool,
208    /// Whether to panic when an Encoding error is encountered.
209    /// Default: false
210    pub panic_on_encoding: bool,
211    /// Whether to panic when a Queue error is encountered.
212    /// Default: false
213    pub panic_on_queue: bool,
214    /// Whether to panic when an Io error is encountered.
215    /// Default: false
216    pub panic_on_io: bool,
217    /// Whether to panic when a Timer error is encountered.
218    /// Default: false
219    pub panic_on_timeout: bool,
220    /// Whether to shutdown the eventloop when an interrupt is received.
221    /// Default: true
222    pub shutdown_on_interrupt: bool,
223    /// The WebSocket protocol requires frames sent from client endpoints to be masked as a
224    /// security and sanity precaution. Enforcing this requirement, which may be removed at some
225    /// point may cause incompatibilities. If you need the extra security, set this to true.
226    /// Default: false
227    pub masking_strict: bool,
228    /// The WebSocket protocol requires clients to verify the key returned by a server to ensure
229    /// that the server and all intermediaries can perform the protocol. Verifying the key will
230    /// consume processing time and other resources with the benefit that we can fail the
231    /// connection early. The default in WS-RS is to accept any key from the server and instead
232    /// fail late if a protocol error occurs. Change this setting to enable key verification.
233    /// Default: false
234    pub key_strict: bool,
235    /// The WebSocket protocol requires clients to perform an opening handshake using the HTTP
236    /// GET method for the request. However, since only WebSockets are supported on the connection,
237    /// verifying the method of handshake requests is not always necessary. To enforce the
238    /// requirement that handshakes begin with a GET method, set this to true.
239    /// Default: false
240    pub method_strict: bool,
241    /// Indicate whether server connections should use ssl encryption when accepting connections.
242    /// Setting this to true means that clients should use the `wss` scheme to connect to this
243    /// server. Note that using this flag will in general necessitate overriding the
244    /// `Handler::upgrade_ssl_server` method in order to provide the details of the ssl context. It may be
245    /// simpler for most users to use a reverse proxy such as nginx to provide server side
246    /// encryption.
247    ///
248    /// Default: false
249    pub encrypt_server: bool,
250    /// Disables Nagle's algorithm.
251    /// Usually tcp socket tries to accumulate packets to send them all together (every 200ms).
252    /// When enabled socket will try to send packet as fast as possible.
253    ///
254    /// Default: false
255    pub tcp_nodelay: bool,
256}
257
258impl Default for Settings {
259    fn default() -> Settings {
260        Settings {
261            max_connections: 100,
262            queue_size: 5,
263            panic_on_new_connection: false,
264            panic_on_shutdown: false,
265            fragments_capacity: 10,
266            fragments_grow: true,
267            fragment_size: u16::max_value() as usize,
268            max_fragment_size: usize::max_value(),
269            max_total_fragments_size: usize::max_value(),
270            in_buffer_capacity: 2048,
271            in_buffer_capacity_hard_limit: 10 * 1024 * 1024,
272            in_buffer_capacity_soft_limit: 1024 * 1024,
273            out_buffer_capacity: 2048,
274            out_buffer_capacity_hard_limit: 10 * 1024 * 1024,
275            out_buffer_capacity_soft_limit: 1024 * 1024,
276            panic_on_internal: true,
277            panic_on_capacity: false,
278            panic_on_protocol: false,
279            panic_on_encoding: false,
280            panic_on_queue: false,
281            panic_on_io: false,
282            panic_on_timeout: false,
283            shutdown_on_interrupt: true,
284            masking_strict: false,
285            key_strict: false,
286            method_strict: false,
287            encrypt_server: false,
288            tcp_nodelay: false,
289        }
290    }
291}
292
293/// The WebSocket struct. A WebSocket can support multiple incoming and outgoing connections.
294pub struct WebSocket<F>
295where
296    F: Factory,
297{
298    poll: Poll,
299    handler: io::Handler<F>,
300}
301
302impl<F> WebSocket<F>
303where
304    F: Factory,
305{
306    /// Create a new WebSocket using the given Factory to create handlers.
307    pub fn new(factory: F) -> Result<WebSocket<F>> {
308        Builder::new().build(factory)
309    }
310
311    /// Consume the WebSocket and bind to the specified address.
312    /// If the `addr_spec` yields multiple addresses this will return after the
313    /// first successful bind. `local_addr` can be called to determine which
314    /// address it ended up binding to.
315    /// After the server is successfully bound you should start it using `run`.
316    pub fn bind<A>(mut self, addr_spec: A) -> Result<WebSocket<F>>
317    where
318        A: ToSocketAddrs,
319    {
320        let mut last_error = Error::new(ErrorKind::Internal, "No address given");
321
322        for addr in addr_spec.to_socket_addrs()? {
323            if let Err(e) = self.handler.listen(&mut self.poll, &addr) {
324                error!("Unable to listen on {}", addr);
325                last_error = e;
326            } else {
327                let actual_addr = self.handler.local_addr().unwrap_or(addr);
328                info!("Listening for new connections on {}.", actual_addr);
329                return Ok(self);
330            }
331        }
332
333        Err(last_error)
334    }
335
336    /// Consume the WebSocket and listen for new connections on the specified address.
337    ///
338    /// # Safety
339    ///
340    /// This method will block until the event loop finishes running.
341    pub fn listen<A>(self, addr_spec: A) -> Result<WebSocket<F>>
342    where
343        A: ToSocketAddrs,
344    {
345        self.bind(addr_spec).and_then(|server| server.run())
346    }
347
348    /// Queue an outgoing connection on this WebSocket. This method may be called multiple times,
349    /// but the actual connections will not be established until `run` is called.
350    pub fn connect(&mut self, url: url::Url) -> Result<&mut WebSocket<F>> {
351        let sender = self.handler.sender();
352        info!("Queuing connection to {}", url);
353        sender.connect(url)?;
354        Ok(self)
355    }
356
357    /// Run the WebSocket. This will run the encapsulated event loop blocking the calling thread until
358    /// the WebSocket is shutdown.
359    pub fn run(mut self) -> Result<WebSocket<F>> {
360        self.handler.run(&mut self.poll)?;
361        Ok(self)
362    }
363
364    /// Get a Sender that can be used to send messages on all connections.
365    /// Calling `send` on this Sender is equivalent to calling `broadcast`.
366    /// Calling `shutdown` on this Sender will shutdown the WebSocket even if no connections have
367    /// been established.
368    #[inline]
369    pub fn broadcaster(&self) -> Sender {
370        self.handler.sender()
371    }
372
373    /// Get the local socket address this socket is bound to. Will return an error
374    /// if the backend returns an error. Will return a `NotFound` error if
375    /// this WebSocket is not a listening socket.
376    pub fn local_addr(&self) -> ::std::io::Result<SocketAddr> {
377        self.handler.local_addr()
378    }
379}
380
381/// Utility for constructing a WebSocket from various settings.
382#[derive(Debug, Default, Clone, Copy)]
383pub struct Builder {
384    settings: Settings,
385}
386
387// TODO: add convenience methods for each setting
388impl Builder {
389    /// Create a new Builder with default settings.
390    pub fn new() -> Builder {
391        Builder::default()
392    }
393
394    /// Build a WebSocket using this builder and a factory.
395    /// It is possible to use the same builder to create multiple WebSockets.
396    pub fn build<F>(&self, factory: F) -> Result<WebSocket<F>>
397    where
398        F: Factory,
399    {
400        Ok(WebSocket {
401            poll: Poll::new()?,
402            handler: io::Handler::new(factory, self.settings),
403        })
404    }
405
406    /// Set the WebSocket settings to use.
407    pub fn with_settings(&mut self, settings: Settings) -> &mut Builder {
408        self.settings = settings;
409        self
410    }
411}