websocket-driver 0.6.5-java → 0.7.4-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +73 -44
- data/LICENSE.md +9 -19
- data/README.md +46 -26
- data/ext/websocket-driver/WebsocketMaskService.java +31 -29
- data/ext/websocket-driver/websocket_mask.c +23 -32
- data/lib/websocket/driver.rb +45 -14
- data/lib/websocket/driver/client.rb +8 -8
- data/lib/websocket/driver/draft75.rb +1 -1
- data/lib/websocket/driver/draft76.rb +12 -9
- data/lib/websocket/driver/headers.rb +1 -1
- data/lib/websocket/driver/hybi.rb +56 -44
- data/lib/websocket/driver/hybi/message.rb +1 -1
- data/lib/websocket/driver/proxy.rb +4 -4
- data/lib/websocket/driver/server.rb +3 -3
- data/lib/websocket/driver/stream_reader.rb +3 -3
- data/lib/websocket/http/request.rb +2 -2
- data/lib/websocket/http/response.rb +1 -1
- data/lib/websocket_mask.jar +0 -0
- metadata +29 -31
- data/examples/tcp_server.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: cd9397ef6b3c46b55d4f5809f8b359f261b983f5a29442d6cbb9791fb40761d8
|
4
|
+
data.tar.gz: 871848fa7118981c4543d4533f4a0a845ff848b5da639e42f16f7f5f6762231a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d9b3b03d2ada8d5757d7a2ea189097a2b31b4ffbd980317d88176826aa77db2be291a89d8280533d3e3f79c46997d157c540a2d2ef77f3a80c2d00b5bd7965c
|
7
|
+
data.tar.gz: f87b7664488e57fc8e976809b6554dd05cac016961fef21efa7331917bb247be14f24dbe4642ae909e295d1c61dedb5a5e42d44d298b10921acbd3bf4aa69293
|
data/CHANGELOG.md
CHANGED
@@ -1,123 +1,152 @@
|
|
1
|
+
### 0.7.4 / 2021-05-24
|
2
|
+
|
3
|
+
- Optimise conversions between strings and byte arrays and related encoding
|
4
|
+
operations, to reduce amount of allocation and copying
|
5
|
+
|
6
|
+
### 0.7.3 / 2020-07-09
|
7
|
+
|
8
|
+
- Let the client accept HTTP responses that have an empty reason phrase
|
9
|
+
following the `101` status code
|
10
|
+
|
11
|
+
### 0.7.2 / 2020-05-22
|
12
|
+
|
13
|
+
- Emit `ping` and `pong` events from the `Server` driver
|
14
|
+
- Handle draft-76 handshakes correctly if the request's body is a frozen string
|
15
|
+
|
16
|
+
### 0.7.1 / 2019-06-10
|
17
|
+
|
18
|
+
- Catch any exceptions produced while generating a handshake response and send a
|
19
|
+
`400 Bad Request` response to the client
|
20
|
+
- Pick the RFC-6455 protocol version if the request contains any of the headers
|
21
|
+
used by that version
|
22
|
+
- Handle errors encountered while handling malformed draft-76 requests
|
23
|
+
- Change license from MIT to Apache 2.0
|
24
|
+
|
25
|
+
### 0.7.0 / 2017-09-11
|
26
|
+
|
27
|
+
- Add `ping` and `pong` to the set of events users can listen to
|
28
|
+
|
1
29
|
### 0.6.5 / 2017-01-22
|
2
30
|
|
3
|
-
|
31
|
+
- Provide a pure-Ruby fallback for the native unmasking code
|
4
32
|
|
5
33
|
### 0.6.4 / 2016-05-20
|
6
34
|
|
7
|
-
|
8
|
-
|
9
|
-
|
35
|
+
- Amend warnings issued when running with -W2
|
36
|
+
- Make sure message strings passed in by the app are transcoded to UTF-8
|
37
|
+
- Copy strings if necessary for frozen-string compatibility
|
10
38
|
|
11
39
|
### 0.6.3 / 2015-11-06
|
12
40
|
|
13
|
-
|
14
|
-
|
41
|
+
- Reject draft-76 handshakes if their Sec-WebSocket-Key headers are invalid
|
42
|
+
- Throw a more helpful error if a client is created with an invalid URL
|
15
43
|
|
16
44
|
### 0.6.2 / 2015-07-18
|
17
45
|
|
18
|
-
|
46
|
+
- When the peer sends a close frame with no error code, emit 1000
|
19
47
|
|
20
48
|
### 0.6.1 / 2015-07-13
|
21
49
|
|
22
|
-
|
50
|
+
- Fix how events are stored in `EventEmitter` to fix a backward-compatibility
|
23
51
|
violation introduced in the last release
|
24
|
-
|
52
|
+
- Use the `Array#pack` and `String#unpack` methods for reading/writing numbers
|
25
53
|
to buffers rather than including duplicate logic for this
|
26
54
|
|
27
55
|
### 0.6.0 / 2015-07-08
|
28
56
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
57
|
+
- Use `SecureRandom` to generate the `Sec-WebSocket-Key` header
|
58
|
+
- Allow the parser to recover cleanly if event listeners raise an error
|
59
|
+
- Let the `on()` method take a lambda as a positional argument rather than a
|
60
|
+
block
|
61
|
+
- Add a `pong` method for sending unsolicited pong frames
|
33
62
|
|
34
63
|
### 0.5.4 / 2015-03-29
|
35
64
|
|
36
|
-
|
65
|
+
- Don't emit extra close frames if we receive a close frame after we already
|
37
66
|
sent one
|
38
|
-
|
67
|
+
- Fail the connection when the driver receives an invalid
|
39
68
|
`Sec-WebSocket-Extensions` header
|
40
69
|
|
41
70
|
### 0.5.3 / 2015-02-22
|
42
71
|
|
43
|
-
|
72
|
+
- Don't treat incoming data as WebSocket frames if a client driver is closed
|
44
73
|
before receiving the server handshake
|
45
74
|
|
46
75
|
### 0.5.2 / 2015-02-19
|
47
76
|
|
48
|
-
|
77
|
+
- Don't emit multiple `error` events
|
49
78
|
|
50
79
|
### 0.5.1 / 2014-12-18
|
51
80
|
|
52
|
-
|
81
|
+
- Don't allow drivers to be created with unrecognized options
|
53
82
|
|
54
83
|
### 0.5.0 / 2014-12-13
|
55
84
|
|
56
|
-
|
85
|
+
- Support protocol extensions via the websocket-extensions module
|
57
86
|
|
58
87
|
### 0.4.0 / 2014-11-08
|
59
88
|
|
60
|
-
|
89
|
+
- Support connection via HTTP proxies using `CONNECT`
|
61
90
|
|
62
91
|
### 0.3.5 / 2014-10-04
|
63
92
|
|
64
|
-
|
93
|
+
- Fix bug where the `Server` driver doesn't pass `ping` callbacks to its
|
65
94
|
delegate
|
66
|
-
|
67
|
-
|
95
|
+
- Fix an arity error when calling `fail_request`
|
96
|
+
- Allow `close` to be called before `start` to close the driver
|
68
97
|
|
69
98
|
### 0.3.4 / 2014-07-06
|
70
99
|
|
71
|
-
|
72
|
-
|
73
|
-
|
100
|
+
- Don't hold references to frame buffers after a message has been emitted
|
101
|
+
- Make sure that `protocol` and `version` are exposed properly by the TCP driver
|
102
|
+
- Correct HTTP header parsing based on RFC 7230; header names cannot contain
|
74
103
|
backslashes
|
75
104
|
|
76
105
|
### 0.3.3 / 2014-04-24
|
77
106
|
|
78
|
-
|
79
|
-
|
80
|
-
|
107
|
+
- Fix problems with loading C and Java native extension code
|
108
|
+
- Correct the acceptable characters used in the HTTP parser
|
109
|
+
- Correct the draft-76 status line reason phrase
|
81
110
|
|
82
111
|
### 0.3.2 / 2013-12-29
|
83
112
|
|
84
|
-
|
113
|
+
- Expand `max_length` to cover sequences of continuation frames and
|
85
114
|
`draft-{75,76}`
|
86
|
-
|
87
|
-
|
115
|
+
- Decrease default maximum frame buffer size to 64MB
|
116
|
+
- Stop parsing when the protocol enters a failure mode, to save CPU cycles
|
88
117
|
|
89
118
|
### 0.3.1 / 2013-12-03
|
90
119
|
|
91
|
-
|
120
|
+
- Add a `max_length` option to limit allowed frame size
|
92
121
|
|
93
122
|
### 0.3.0 / 2013-09-09
|
94
123
|
|
95
|
-
|
124
|
+
- Support client URLs with Basic Auth credentials
|
96
125
|
|
97
126
|
### 0.2.3 / 2013-08-04
|
98
127
|
|
99
|
-
|
128
|
+
- Fix bug in EventEmitter#emit when listeners are removed
|
100
129
|
|
101
130
|
### 0.2.2 / 2013-08-04
|
102
131
|
|
103
|
-
|
132
|
+
- Fix bug in EventEmitter#listener_count for unregistered events
|
104
133
|
|
105
134
|
### 0.2.1 / 2013-07-05
|
106
135
|
|
107
|
-
|
108
|
-
|
136
|
+
- Queue sent messages if the client has not begun trying to connect
|
137
|
+
- Encode all strings sent to I/O as `ASCII-8BIT`
|
109
138
|
|
110
139
|
### 0.2.0 / 2013-05-12
|
111
140
|
|
112
|
-
|
113
|
-
|
141
|
+
- Add API for setting and reading headers
|
142
|
+
- Add Driver.server() method for getting a driver for TCP servers
|
114
143
|
|
115
144
|
### 0.1.0 / 2013-05-04
|
116
145
|
|
117
|
-
|
146
|
+
- First stable release
|
118
147
|
|
119
148
|
### 0.0.0 / 2013-04-22
|
120
149
|
|
121
|
-
|
122
|
-
|
123
|
-
|
150
|
+
- First release
|
151
|
+
- Proof of concept for people to try out
|
152
|
+
- Might be unstable
|
data/LICENSE.md
CHANGED
@@ -1,22 +1,12 @@
|
|
1
|
-
|
1
|
+
Copyright 2010-2021 James Coglan
|
2
2
|
|
3
|
-
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
4
|
+
this file except in compliance with the License. You may obtain a copy of the
|
5
|
+
License at
|
4
6
|
|
5
|
-
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
the Software, and to permit persons to whom the Software is furnished to do so,
|
12
|
-
subject to the following conditions:
|
13
|
-
|
14
|
-
The above copyright notice and this permission notice shall be included in all
|
15
|
-
copies or substantial portions of the Software.
|
16
|
-
|
17
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
19
|
-
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
20
|
-
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
21
|
-
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
22
|
-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
Unless required by applicable law or agreed to in writing, software distributed
|
10
|
+
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
11
|
+
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
12
|
+
specific language governing permissions and limitations under the License.
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# websocket-driver
|
1
|
+
# websocket-driver
|
2
2
|
|
3
3
|
This module provides a complete implementation of the WebSocket protocols that
|
4
4
|
can be hooked up to any TCP library. It aims to simplify things by decoupling
|
@@ -10,21 +10,21 @@ pluggable I/O.
|
|
10
10
|
Due to this design, you get a lot of things for free. In particular, if you hook
|
11
11
|
this module up to some I/O object, it will do all of this for you:
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
- Select the correct server-side driver to talk to the client
|
14
|
+
- Generate and send both server- and client-side handshakes
|
15
|
+
- Recognize when the handshake phase completes and the WS protocol begins
|
16
|
+
- Negotiate subprotocol selection based on `Sec-WebSocket-Protocol`
|
17
|
+
- Negotiate and use extensions via the
|
18
18
|
[websocket-extensions](https://github.com/faye/websocket-extensions-ruby)
|
19
19
|
module
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
20
|
+
- Buffer sent messages until the handshake process is finished
|
21
|
+
- Deal with proxies that defer delivery of the draft-76 handshake body
|
22
|
+
- Notify you when the socket is open and closed and when messages arrive
|
23
|
+
- Recombine fragmented messages
|
24
|
+
- Dispatch text, binary, ping, pong and close frames
|
25
|
+
- Manage the socket-closing handshake process
|
26
|
+
- Automatically reply to ping frames with a matching pong
|
27
|
+
- Apply masking to messages sent by the client
|
28
28
|
|
29
29
|
This library was originally extracted from the [Faye](http://faye.jcoglan.com)
|
30
30
|
project but now aims to provide simple WebSocket support for any Ruby server or
|
@@ -43,12 +43,12 @@ $ gem install websocket-driver
|
|
43
43
|
To build either a server-side or client-side socket, the only requirement is
|
44
44
|
that you supply a `socket` object with these methods:
|
45
45
|
|
46
|
-
|
47
|
-
|
46
|
+
- `socket.url` - returns the full URL of the socket as a string.
|
47
|
+
- `socket.write(string)` - writes the given string to a TCP stream.
|
48
48
|
|
49
49
|
Server-side sockets require one additional method:
|
50
50
|
|
51
|
-
|
51
|
+
- `socket.env` - returns a Rack-style env hash that will contain some of the
|
52
52
|
following fields. Their values are strings containing the value of the named
|
53
53
|
header, unless stated otherwise.
|
54
54
|
* `HTTP_CONNECTION`
|
@@ -150,7 +150,16 @@ module Connection
|
|
150
150
|
if WebSocket::Driver.websocket?(@driver.env)
|
151
151
|
@driver.start
|
152
152
|
else
|
153
|
-
# handle other HTTP requests
|
153
|
+
# handle other HTTP requests, for example
|
154
|
+
body = '<h1>hello</h1>'
|
155
|
+
response = [
|
156
|
+
'HTTP/1.1 200 OK',
|
157
|
+
'Content-Type: text/plain',
|
158
|
+
"Content-Length: #{body.bytesize}",
|
159
|
+
'',
|
160
|
+
body
|
161
|
+
]
|
162
|
+
send_data response.join("\r\n")
|
154
163
|
end
|
155
164
|
end
|
156
165
|
|
@@ -193,8 +202,8 @@ and send outgoing data.
|
|
193
202
|
Client drivers have two additional methods for reading the HTTP data that was
|
194
203
|
sent back by the server:
|
195
204
|
|
196
|
-
|
197
|
-
|
205
|
+
- `driver.status` - the integer value of the HTTP status code
|
206
|
+
- `driver.headers` - a hash-like object containing the response headers
|
198
207
|
|
199
208
|
|
200
209
|
### HTTP Proxies
|
@@ -261,9 +270,9 @@ frames.
|
|
261
270
|
The `options` argument is optional, and is a hash. It may contain the following
|
262
271
|
keys:
|
263
272
|
|
264
|
-
|
273
|
+
- `:max_length` - the maximum allowed size of incoming message frames, in bytes.
|
265
274
|
The default value is `2^26 - 1`, or 1 byte short of 64 MiB.
|
266
|
-
|
275
|
+
- `:protocols` - an array of strings representing acceptable subprotocols for
|
267
276
|
use over the socket. The driver will negotiate one of these to use via the
|
268
277
|
`Sec-WebSocket-Protocol` header if supported by the other peer.
|
269
278
|
|
@@ -274,27 +283,38 @@ Note that most of these methods are commands: if they produce data that should
|
|
274
283
|
be sent over the socket, they will give this to you by calling
|
275
284
|
`socket.write(string)`.
|
276
285
|
|
277
|
-
#### `driver.on :open, -> (event) {
|
286
|
+
#### `driver.on :open, -> (event) {}`
|
278
287
|
|
279
288
|
Adds a callback block to execute when the socket becomes open.
|
280
289
|
|
281
|
-
#### `driver.on :message, -> (event) {
|
290
|
+
#### `driver.on :message, -> (event) {}`
|
282
291
|
|
283
292
|
Adds a callback block to execute when a message is received. `event` will have a
|
284
293
|
`data` attribute containing either a string in the case of a text message or an
|
285
294
|
array of integers in the case of a binary message.
|
286
295
|
|
287
|
-
#### `driver.on :error, -> (event) {
|
296
|
+
#### `driver.on :error, -> (event) {}`
|
288
297
|
|
289
298
|
Adds a callback to execute when a protocol error occurs due to the other peer
|
290
299
|
sending an invalid byte sequence. `event` will have a `message` attribute
|
291
300
|
describing the error.
|
292
301
|
|
293
|
-
#### `driver.on :close, -> (event) {
|
302
|
+
#### `driver.on :close, -> (event) {}`
|
294
303
|
|
295
304
|
Adds a callback block to execute when the socket becomes closed. The `event`
|
296
305
|
object has `code` and `reason` attributes.
|
297
306
|
|
307
|
+
#### `driver.on :ping, -> (event) {}`
|
308
|
+
|
309
|
+
Adds a callback block to execute when a ping is received. You do not need to
|
310
|
+
handle this by sending a pong frame yourself; the driver handles this for you.
|
311
|
+
|
312
|
+
#### `driver.on :pong, -> (event) {}`
|
313
|
+
|
314
|
+
Adds a callback block to execute when a pong is received. If this was in
|
315
|
+
response to a ping you sent, you can also handle this event via the
|
316
|
+
`driver.ping(message) { ... }` callback.
|
317
|
+
|
298
318
|
#### `driver.add_extension(extension)`
|
299
319
|
|
300
320
|
Registers a protocol extension whose operation will be negotiated via the
|
@@ -1,8 +1,6 @@
|
|
1
1
|
package com.jcoglan.websocket;
|
2
2
|
|
3
|
-
import java.lang.Long;
|
4
3
|
import java.io.IOException;
|
5
|
-
|
6
4
|
import org.jruby.Ruby;
|
7
5
|
import org.jruby.RubyClass;
|
8
6
|
import org.jruby.RubyModule;
|
@@ -15,41 +13,45 @@ import org.jruby.runtime.builtin.IRubyObject;
|
|
15
13
|
import org.jruby.runtime.load.BasicLibraryService;
|
16
14
|
|
17
15
|
public class WebsocketMaskService implements BasicLibraryService {
|
18
|
-
|
16
|
+
private Ruby runtime;
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
RubyModule websocket = runtime.defineModule("WebSocket");
|
18
|
+
public boolean basicLoad(Ruby runtime) throws IOException {
|
19
|
+
this.runtime = runtime;
|
23
20
|
|
24
|
-
|
25
|
-
|
26
|
-
return new WebsocketMask(runtime, rubyClass);
|
27
|
-
}
|
28
|
-
});
|
21
|
+
RubyModule websocket = runtime.defineModule("WebSocket");
|
22
|
+
RubyClass webSocketMask = websocket.defineClassUnder("Mask", runtime.getObject(), getAllocator());
|
29
23
|
|
30
|
-
|
31
|
-
|
32
|
-
|
24
|
+
webSocketMask.defineAnnotatedMethods(WebsocketMask.class);
|
25
|
+
return true;
|
26
|
+
}
|
33
27
|
|
34
|
-
|
35
|
-
|
36
|
-
|
28
|
+
ObjectAllocator getAllocator() {
|
29
|
+
return new ObjectAllocator() {
|
30
|
+
public IRubyObject allocate(Ruby runtime, RubyClass rubyClass) {
|
31
|
+
return new WebsocketMask(runtime, rubyClass);
|
32
|
+
}
|
33
|
+
};
|
37
34
|
}
|
38
35
|
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
public class WebsocketMask extends RubyObject {
|
37
|
+
public WebsocketMask(final Ruby runtime, RubyClass rubyClass) {
|
38
|
+
super(runtime, rubyClass);
|
39
|
+
}
|
40
|
+
|
41
|
+
@JRubyMethod
|
42
|
+
public IRubyObject mask(ThreadContext context, IRubyObject payload, IRubyObject mask) {
|
43
|
+
if (mask.isNil()) return payload;
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
-
|
45
|
+
byte[] payload_a = ((RubyString)payload).getBytes();
|
46
|
+
byte[] mask_a = ((RubyString)mask).getBytes();
|
47
|
+
int i, n = payload_a.length;
|
46
48
|
|
47
|
-
|
49
|
+
if (n == 0) return payload;
|
48
50
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
51
|
+
for (i = 0; i < n; i++) {
|
52
|
+
payload_a[i] ^= mask_a[i % 4];
|
53
|
+
}
|
54
|
+
return RubyString.newStringNoCopy(runtime, payload_a);
|
55
|
+
}
|
53
56
|
}
|
54
|
-
}
|
55
57
|
}
|