Skip to content

Commit 1472417

Browse files
committed
feat: Support permessage-deflate extension
1 parent 494b188 commit 1472417

19 files changed

+1126
-490
lines changed

Cargo.toml

+15-15
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,26 @@ license = "MIT"
77
name = "ws"
88
readme = "README.md"
99
repository = "https://github.com/housleyjk/ws-rs"
10-
version = "0.4.8"
10+
version = "0.5.0"
1111

1212
[dependencies]
13-
httparse = "1.1.2"
14-
log = "0.3.6"
15-
mio = "0.5.1"
16-
rand = "0.3.14"
17-
sha1 = "0.1.1"
18-
url = "1.1.1"
19-
20-
[dependencies.openssl]
21-
optional = true
22-
version = "0.7.13"
13+
httparse = "*"
14+
log = "*"
15+
mio = "*"
16+
rand = "*"
17+
sha1 = "*"
18+
url = "*"
19+
openssl = { version = "*", optional = true }
20+
libz-sys = { version = "*", optional = true }
21+
libc = { version = "*", optional = true }
2322

2423
[dev-dependencies]
25-
clap = "2.5.1"
26-
env_logger = "0.3.3"
27-
term = "0.4.4"
28-
time = "0.1.35"
24+
clap = "*"
25+
env_logger = "*"
26+
term = "*"
27+
time = "*"
2928

3029
[features]
3130
default = []
31+
permessage-deflate = ["libz-sys", "libc"]
3232
ssl = ["openssl"]

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright (c) 2015 Jason Housley
1+
Copyright (c) 2016 Jason Housley
22

33
Permission is hereby granted, free of charge, to any person obtaining a copy
44
of this software and associated documentation files (the "Software"), to deal

README.md

+24-101
Original file line numberDiff line numberDiff line change
@@ -17,116 +17,39 @@ Introduction
1717
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
1818
[![Crate](http://meritbadge.herokuapp.com/ws)](https://crates.io/crates/ws)
1919

20-
This library provides an implementation of WebSockets, [RFC6455](https://tools.ietf.org/html/rfc6455) using [MIO](https://github.com/carllerche/mio).
21-
It allows for handling multiple connections on a single thread, and even spawning new client connections on the same thread. This makes for very fast
22-
and resource efficient WebSockets. The API design abstracts away the menial parts of the WebSocket protocol, masking and unmasking frames,
23-
which allows you to focus on application code and rely on WS-RS to handle protocol conformance. However, it is also possible to get low-level
24-
access to individual WebSocket frames if you need to write extensions or want to optimize around the WebSocket protocol.
20+
**[Homepage](https://ws-rs.org)**
2521

26-
**[API documentation](http://housleyjk.github.io/ws-rs/ws)**
22+
**[API Documentation](https://ws-rs.org/docs)**
2723

24+
This library provides an implementation of WebSockets,
25+
[RFC6455](https://tools.ietf.org/html/rfc6455) using [MIO](https://github.com/carllerche/mio). It
26+
allows for handling multiple connections on a single thread, and even spawning new client
27+
connections on the same thread. This makes for very fast and resource efficient WebSockets. The API
28+
design abstracts away the menial parts of the WebSocket protocol and allows you to focus on
29+
application code without worrying about protocol conformance. However, it is also possible to get
30+
low-level access to individual WebSocket frames if you need to write extensions or want to optimize
31+
around the WebSocket protocol.
2832

29-
Examples
30-
--------
31-
* [Server](https://github.com/housleyjk/ws-rs/tree/stable/examples/server.rs).
32-
A simple WebSocket echo server using closures.
33-
* [Client](https://github.com/housleyjk/ws-rs/tree/stable/examples/client.rs)
34-
A simple WebSocket client for connecting to an echo server using closures.
35-
* [Single Threaded](https://github.com/housleyjk/ws-rs/tree/stable/examples/shared.rs)
36-
An example of an echo client and an echo server on one thread using closures.
37-
* [Threads](https://github.com/housleyjk/ws-rs/tree/stable/examples/threaded.rs)
38-
An example of an echo client and an echo server on separate threads. This demonstrates using a struct as a WebSocket handler.
39-
* [Channels](https://github.com/housleyjk/ws-rs/tree/stable/examples/channel.rs)
40-
A more complex example using channels to communicate with a WebSocket handler to accomplish a separate task.
41-
* [Pong](https://github.com/housleyjk/ws-rs/tree/stable/examples/pong.rs)
42-
An example demonstrating how to send and recieve a custom ping/pong frame.
43-
44-
Stability and Testing
45-
---------------------
46-
47-
WS-RS passes both the client and server sides of the [Autobahn Testsuite](http://autobahn.ws/testsuite/).
48-
To run the tests yourself, install the [Autobahn Testsuite](http://autobahn.ws/testsuite/).
49-
For example:
50-
51-
```
52-
mkvirtualenv wstest --python=/usr/bin/python2
53-
pip install autobahntestsuite
54-
```
33+
Getting Started
34+
---------------
5535

56-
To run the client tests, start the test server in one window:
57-
```
58-
cd tests
59-
wstest -m fuzzingserver
60-
```
61-
And run the WS-RS client in the other:
62-
```
63-
cargo run --example autobahn-client
64-
```
65-
66-
To run the server tests, start the WS-RS server in one window:
67-
```
68-
cargo run --example autobahn-server
69-
```
70-
And run the test client in the other:
71-
```
72-
cd tests
73-
wstest -m fuzzingclient
74-
```
36+
For detailed installation and usage instructions, check out the [guide](https://ws-rs.org/guide).
7537

76-
SSL
77-
---
78-
WS-RS supports WebSocket connections using SSL (e.g. `wss://mysecure/websocket`). To enable the ssl feature, require WS-RS in your `Cargo.toml`
79-
file as so:
38+
Features
39+
--------
8040

81-
``` TOML
82-
[dependencies.ws]
83-
version = "*"
84-
features = ["ssl"]
85-
```
41+
WS-RS provides a complete implementation of the WebSocket specification. There is also support for
42+
[ssl](https://ws-rs.org/guide/ssl) and
43+
[permessage-deflate](https://ws-rs.org/guide/permessage-deflate).
8644

87-
Then simply specify the `wss` scheme to use an encypted connection.
45+
Testing
46+
-------
8847

89-
```rust
90-
/// An encypted Websocket echo client
91-
connect("wss://localhost:3012", |ws| {
92-
move |msg| {
93-
ws.send(msg)
94-
}
95-
})
96-
```
48+
WS-RS is thoroughly tested and passes the [Autobahn Test Suite](http://autobahn.ws/testsuite/) for
49+
WebSockets, including the tests for `permessage-deflate`. Visit
50+
[ws-rs.org](https://ws-rs.org/testing/results) to view the results of the latest test run.
9751

9852
Contributing
9953
------------
10054

101-
Please report bugs and make feature requests [here](https://github.com/housleyjk/ws-rs/issues). I welcome pull requests.
102-
Unit tests for bugs are greatly appreciated.
103-
104-
Comparison with other WebSocket libraries
105-
-----------------------------------------
106-
107-
You don't need to use this library to the exclusion of other WebSocket libraries, in Rust or other languages,
108-
but if you find yourself considering which library to use, here is my opinion: choose the one that has the API
109-
you like the most. The API is generally more important than performance. The library API is what you will have to deal with as
110-
you build your WebSocket application. I've written WS-RS to have an API that fits my needs. If you don't like it,
111-
please make a [feature request](https://github.com/housleyjk/ws-rs/issues) to improve it or use another library
112-
that causes you less problems.
113-
114-
However, if performance is what you value most and you want a WebSocket library in Rust, I would choose this one.
115-
Here is how it stacks up against some other common frameworks using the example [benchmark tool](https://github.com/housleyjk/ws-rs/tree/stable/examples/bench.rs)
116-
to open 10,000 simultaneous connections and send 10 messages. These results are **not** reliable as a serious benchmark:
117-
118-
Library | Time (ms)
119-
--------| ---------
120-
<a href="https://github.com/housleyjk/ws-rs">WS-RS</a> | 1,709
121-
<a href="https://libwebsockets.org/trac/libwebsockets">libwebsockets</a> | 2,067
122-
<a href="https://github.com/cyderize/rust-websocket">rust-websocket</a> | 8,950
123-
<a href="http://aaugustin.github.io/websockets/">\* websockets CPython 3.4.3</a> | 12,638
124-
<a href="http://autobahn.ws/python/">Autobahn CPython 2.7.10</a> | 48,902
125-
<a href="https://github.com/websockets/ws">\*\* NodeJS via ws</a> | 127,635
126-
127-
\* websockets encountered a few (3) broken pipe errors<br>
128-
\*\* NodeJS encountered several (229) connection timeout errors
129-
130-
Your results will vary. The system specs for this test were as follows:
131-
132-
Intel(R) Core(TM) i3 CPU 560 @ 3.33GHz, 8GB RAM
55+
Please report bugs and make feature requests [here](https://github.com/housleyjk/ws-rs/issues).

examples/autobahn-client.rs

+27
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@ use std::rc::Rc;
66
use std::cell::Cell;
77
use ws::{connect, CloseCode, Message, Result};
88

9+
#[cfg(feature="permessage-deflate")]
10+
use ws::deflate::DeflateHandler;
11+
912
const AGENT: &'static str = "WS-RS";
1013

14+
#[cfg(not(feature="permessage-deflate"))]
1115
fn main () {
1216

1317
let total = get_case_count().unwrap();
@@ -30,6 +34,29 @@ fn main () {
3034
update_reports().unwrap();
3135
}
3236

37+
#[cfg(feature="permessage-deflate")]
38+
fn main () {
39+
40+
let total = get_case_count().unwrap();
41+
let mut case_id = 1;
42+
43+
44+
while case_id <= total {
45+
46+
let case_url = format!("ws://127.0.0.1:9001/runCase?case={}&agent={}", case_id, AGENT);
47+
48+
connect(case_url, |out| {
49+
DeflateHandler::new(move |msg| {
50+
out.send(msg)
51+
})
52+
}).unwrap();
53+
54+
case_id += 1
55+
}
56+
57+
update_reports().unwrap();
58+
}
59+
3360
fn get_case_count() -> Result<u32> {
3461

3562
// sadly we need to use a Cell because we need to set the total, and RC is immutable

examples/autobahn-server.rs

+18
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,29 @@
22
/// example without printing output or comments.
33
44
extern crate ws;
5+
extern crate env_logger;
56

7+
#[cfg(feature="permessage-deflate")]
8+
use ws::deflate::DeflateHandler;
9+
10+
#[cfg(not(feature="permessage-deflate"))]
611
fn main () {
12+
env_logger::init().unwrap();
13+
714
ws::listen("127.0.0.1:3012", |out| {
815
move |msg| {
916
out.send(msg)
1017
}
1118
}).unwrap()
1219
}
20+
21+
#[cfg(feature="permessage-deflate")]
22+
fn main () {
23+
env_logger::init().unwrap();
24+
25+
ws::listen("127.0.0.1:3012", |out| {
26+
DeflateHandler::new(move |msg| {
27+
out.send(msg)
28+
})
29+
}).unwrap();
30+
}

src/communication.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,11 @@ impl Sender {
7979

8080
/// Send a message to the endpoints of all connections.
8181
///
82-
/// Be careful with this method because it
83-
/// does not discriminate between client and server connections, only connections that are not
84-
/// part of *this* side of the WebSocket. If your WebSocket is only functioning as a server,
85-
/// then usage is simple, however if you have a WebSocket that is listening for
86-
/// connections and is also connected to another WebSocket, this method will broadcast a
87-
/// message to all the clients connected and to the server at the other end of the single
88-
/// client connection.
82+
/// Be careful with this method. It does not discriminate between client and server connections.
83+
/// If your WebSocket is only functioning as a server, then usage is simple, this method will
84+
/// send a copy of the message to each connected client. However, if you have a WebSocket that
85+
/// is listening for connections and is also connected to another WebSocket, this method will
86+
/// broadcast a copy of the message to all the clients connected and to that WebSocket server.
8987
#[inline]
9088
pub fn broadcast<M>(&self, msg: M) -> Result<()>
9189
where M: Into<message::Message>

0 commit comments

Comments
 (0)