faye-websocket 0.10.5 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +83 -50
- data/LICENSE.md +12 -0
- data/README.md +77 -73
- data/lib/faye/eventsource.rb +4 -4
- data/lib/faye/rack_stream.rb +1 -0
- data/lib/faye/websocket.rb +5 -4
- data/lib/faye/websocket/api.rb +14 -5
- data/lib/faye/websocket/api/event.rb +1 -1
- data/lib/faye/websocket/api/event_target.rb +2 -2
- data/lib/faye/websocket/client.rb +57 -34
- data/lib/faye/websocket/ssl_verifier.rb +89 -0
- metadata +12 -35
- data/examples/app.rb +0 -54
- data/examples/autobahn_client.rb +0 -48
- data/examples/client.rb +0 -34
- data/examples/config.ru +0 -13
- data/examples/haproxy.conf +0 -20
- data/examples/proxy_server.rb +0 -14
- data/examples/rainbows.conf +0 -3
- data/examples/server.rb +0 -50
- data/examples/sse.html +0 -38
- data/examples/ws.html +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 42cb4ec90fb1f2d1fd16739908d415035255136b33c1b8100f4370417d7afeee
|
4
|
+
data.tar.gz: b75409884d2ac82e84a59752027085106d1995e92d9603628400b13d7214bc4d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23293a16e2b1068bb1bd9a7c4e7516f9031185393e50d766833fe468bff7fb3b807d69015c022f35545cf41abb3e5ff9cf96282bb797ecba0eee60cea63de428
|
7
|
+
data.tar.gz: 46ac66a36431ee0adc04dbe5286499c38904b79e4da3259bb42c57c49ff97736568957da641fd640fedc237f67e258d06d5cbd0abb5d3d10eaf662f991368b67
|
data/CHANGELOG.md
CHANGED
@@ -1,152 +1,185 @@
|
|
1
|
+
### 0.11.0 / 2020-07-31
|
2
|
+
|
3
|
+
- Implement TLS certificate verification and enable it by default on client
|
4
|
+
connections
|
5
|
+
- Add a `:tls` option to the client with sub-fields `:root_cert_file` and
|
6
|
+
`:verify_peer` for configuring TLS verification
|
7
|
+
|
8
|
+
### 0.10.9 / 2019-06-13
|
9
|
+
|
10
|
+
- Use the EventMachine API rather than `IO#write` to write data; this uses the
|
11
|
+
event loop and avoids getting blocked by slow clients
|
12
|
+
|
13
|
+
### 0.10.8 / 2019-06-10
|
14
|
+
|
15
|
+
- In the case of a close timeout, don't block on waiting for writing to the
|
16
|
+
socket to complete
|
17
|
+
- Fix a race condition that caused a timeout not to be cancelled immediately
|
18
|
+
when the WebSocket is closed
|
19
|
+
- Change license from MIT to Apache 2.0
|
20
|
+
|
21
|
+
### 0.10.7 / 2017-02-22
|
22
|
+
|
23
|
+
- Emit an error if `EventMachine::Connection#unbind` is called with an error
|
24
|
+
|
25
|
+
### 0.10.6 / 2017-01-22
|
26
|
+
|
27
|
+
- Forcibly close the I/O stream after a timeout if the peer does not respond
|
28
|
+
after calling `close()`
|
29
|
+
|
1
30
|
### 0.10.5 / 2016-11-12
|
2
31
|
|
3
|
-
|
32
|
+
- Set the SNI hostname when making secure requests
|
4
33
|
|
5
34
|
### 0.10.4 / 2016-05-20
|
6
35
|
|
7
|
-
|
36
|
+
- Amend warnings issued when running with -W2
|
8
37
|
|
9
38
|
### 0.10.3 / 2016-02-24
|
10
39
|
|
11
|
-
|
40
|
+
- Use `PATH_INFO` and `QUERY_STRING` rather than the non-standard `REQUEST_URI`
|
41
|
+
from the Rack env
|
12
42
|
|
13
43
|
### 0.10.2 / 2015-11-26
|
14
44
|
|
15
|
-
|
45
|
+
- Fix the `headers` and `status` methods on `Client`, which were broken in the
|
16
46
|
last release
|
17
47
|
|
18
48
|
### 0.10.1 / 2015-11-06
|
19
49
|
|
20
|
-
|
21
|
-
|
50
|
+
- Make sure errors can be safely emitted if creating the driver fails
|
51
|
+
- Prevent a race condition when binding `EM.attach` to the socket
|
22
52
|
|
23
53
|
### 0.10.0 / 2015-07-08
|
24
54
|
|
25
|
-
|
55
|
+
- Add the standard `code` and `reason` parameters to the `close` method
|
26
56
|
|
27
57
|
### 0.9.2 / 2014-12-21
|
28
58
|
|
29
|
-
|
59
|
+
- Only emit `error` once, and don't emit it after `close`
|
30
60
|
|
31
61
|
### 0.9.1 / 2014-12-18
|
32
62
|
|
33
|
-
|
63
|
+
- Check that all options to the WebSocket constructor are recognized
|
34
64
|
|
35
65
|
### 0.9.0 / 2014-12-13
|
36
66
|
|
37
|
-
|
67
|
+
- Allow protocol extensions to be passed into websocket-extensions
|
38
68
|
|
39
69
|
### 0.8.0 / 2014-11-08
|
40
70
|
|
41
|
-
|
71
|
+
- Support connections via HTTP proxies
|
42
72
|
|
43
73
|
### 0.7.5 / 2014-10-04
|
44
74
|
|
45
|
-
|
75
|
+
- Allow sockets to be closed when they are in any state other than `CLOSED`
|
46
76
|
|
47
77
|
### 0.7.4 / 2014-07-06
|
48
78
|
|
49
|
-
|
50
|
-
|
51
|
-
|
79
|
+
- Stop using `define_method` to implement `Event` properties, since it blows the
|
80
|
+
method cache
|
81
|
+
- Stop setup errors masking URI errors in `Client#initialize`
|
82
|
+
- Make the Goliath adapter compatible with goliath-1.0.4.
|
52
83
|
|
53
84
|
### 0.7.3 / 2014-04-24
|
54
85
|
|
55
|
-
|
86
|
+
- Remove an unneeded method override in the `WebSocket` class
|
56
87
|
|
57
88
|
### 0.7.2 / 2013-12-29
|
58
89
|
|
59
|
-
|
90
|
+
- Fix WebSocket detection in cases where the web server does not produce an
|
91
|
+
`env`
|
60
92
|
|
61
93
|
### 0.7.1 / 2013-12-03
|
62
94
|
|
63
|
-
|
64
|
-
|
95
|
+
- Support the `max_length` websocket-driver option
|
96
|
+
- Expose a `message` property on `error` events
|
65
97
|
|
66
98
|
### 0.7.0 / 2013-09-09
|
67
99
|
|
68
|
-
|
100
|
+
- Allow the server to send custom headers with EventSource responses
|
69
101
|
|
70
102
|
### 0.6.3 / 2013-08-04
|
71
103
|
|
72
|
-
|
104
|
+
- Stop implicitly depending on Rack 1.4
|
73
105
|
|
74
106
|
### 0.6.2 / 2013-07-05
|
75
107
|
|
76
|
-
|
108
|
+
- Catch errors thrown by EventMachine and emit `error` and `close` events
|
77
109
|
|
78
110
|
### 0.6.1 / 2013-05-12
|
79
111
|
|
80
|
-
|
112
|
+
- Release a gem without log and pid files in it
|
81
113
|
|
82
114
|
### 0.6.0 / 2013-05-12
|
83
115
|
|
84
|
-
|
116
|
+
- Add support for custom headers
|
85
117
|
|
86
118
|
### 0.5.0 / 2013-05-05
|
87
119
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
120
|
+
- Extract the protocol handlers into the `websocket-driver` library
|
121
|
+
- Support the `rack.hijack` API
|
122
|
+
- Add support for Rainbows 4.5 and Puma
|
123
|
+
- Officially support JRuby and Rubinius
|
92
124
|
|
93
125
|
### 0.4.7 / 2013-02-14
|
94
126
|
|
95
|
-
|
96
|
-
|
97
|
-
|
127
|
+
- Emit the `close` event if TCP is closed before CLOSE frame is acked
|
128
|
+
- Treat the `Upgrade: websocket` header case-insensitively because of IE10
|
129
|
+
- Do not suppress headers in the Thin and Rainbows adapters unless the status is
|
130
|
+
`101`
|
98
131
|
|
99
132
|
### 0.4.6 / 2012-07-09
|
100
133
|
|
101
|
-
|
134
|
+
- Add `Connection: close` to EventSource response
|
102
135
|
|
103
136
|
### 0.4.5 / 2012-04-06
|
104
137
|
|
105
|
-
|
106
|
-
|
138
|
+
- Add WebSocket error code `1011`.
|
139
|
+
- Handle URLs with no path correctly by sending `GET /`
|
107
140
|
|
108
141
|
### 0.4.4 / 2012-03-16
|
109
142
|
|
110
|
-
|
143
|
+
- Fix installation on JRuby with a platform-specific gem
|
111
144
|
|
112
145
|
### 0.4.3 / 2012-03-12
|
113
146
|
|
114
|
-
|
147
|
+
- Make `extconf.rb` a no-op on JRuby
|
115
148
|
|
116
149
|
### 0.4.2 / 2012-03-09
|
117
150
|
|
118
|
-
|
151
|
+
- Port masking-function C extension to Java for JRuby
|
119
152
|
|
120
153
|
### 0.4.1 / 2012-02-26
|
121
154
|
|
122
|
-
|
123
|
-
|
155
|
+
- Treat anything other than an `Array` as a string when calling `send()`
|
156
|
+
- Fix error loading UTF-8 validation code on Ruby 1.9 with `-Ku` flag
|
124
157
|
|
125
158
|
### 0.4.0 / 2012-02-13
|
126
159
|
|
127
|
-
|
128
|
-
|
160
|
+
- Add `ping()` method to server-side `WebSocket` and `EventSource`
|
161
|
+
- Buffer `send()` calls until the draft-76 handshake is complete
|
129
162
|
|
130
163
|
### 0.3.0 / 2012-01-13
|
131
164
|
|
132
|
-
|
133
|
-
|
165
|
+
- Add support for `EventSource` connections
|
166
|
+
- Support the Thin, Rainbows and Goliath web servers
|
134
167
|
|
135
168
|
### 0.2.0 / 2011-12-21
|
136
169
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
170
|
+
- Add support for `Sec-WebSocket-Protocol` negotiation
|
171
|
+
- Support `hixie-76` close frames and 75/76 ignored segments
|
172
|
+
- Improve performance of HyBi parsing/framing functions
|
173
|
+
- Write masking function in C
|
141
174
|
|
142
175
|
### 0.1.2 / 2011-12-05
|
143
176
|
|
144
|
-
|
177
|
+
- Make `hixie-76` sockets work through HAProxy
|
145
178
|
|
146
179
|
### 0.1.1 / 2011-11-30
|
147
180
|
|
148
|
-
|
181
|
+
- Fix `add_event_listener()` interface methods
|
149
182
|
|
150
183
|
### 0.1.0 / 2011-11-27
|
151
184
|
|
152
|
-
|
185
|
+
- Initial release, based on WebSocket components from Faye
|
data/LICENSE.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Copyright 2010-2020 James Coglan
|
2
|
+
|
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
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
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,9 +1,4 @@
|
|
1
|
-
# faye-websocket
|
2
|
-
|
3
|
-
* Travis CI build: [![Build
|
4
|
-
status](https://secure.travis-ci.org/faye/faye-websocket-ruby.svg)](http://travis-ci.org/faye/faye-websocket-ruby)
|
5
|
-
* Autobahn tests: [server](http://faye.jcoglan.com/autobahn/servers/),
|
6
|
-
[client](http://faye.jcoglan.com/autobahn/clients/)
|
1
|
+
# faye-websocket [![Build status](https://secure.travis-ci.org/faye/faye-websocket-ruby.svg)](http://travis-ci.org/faye/faye-websocket-ruby)
|
7
2
|
|
8
3
|
This is a general-purpose WebSocket implementation extracted from the
|
9
4
|
[Faye](http://faye.jcoglan.com) project. It provides classes for easily building
|
@@ -22,11 +17,11 @@ access via proxies than WebSockets.
|
|
22
17
|
The following web servers are supported. Other servers that implement the
|
23
18
|
`rack.hijack` API should also work.
|
24
19
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
20
|
+
- [Goliath](http://postrank-labs.github.com/goliath/)
|
21
|
+
- [Phusion Passenger](https://www.phusionpassenger.com/) >= 4.0 with nginx >= 1.4
|
22
|
+
- [Puma](http://puma.io/) >= 2.0
|
23
|
+
- [Rainbows](http://rainbows.bogomips.org/)
|
24
|
+
- [Thin](http://code.macournoyer.com/thin/)
|
30
25
|
|
31
26
|
|
32
27
|
## Installation
|
@@ -65,7 +60,7 @@ App = lambda do |env|
|
|
65
60
|
|
66
61
|
else
|
67
62
|
# Normal HTTP request
|
68
|
-
[200, {'Content-Type' => 'text/plain'}, ['Hello']]
|
63
|
+
[200, { 'Content-Type' => 'text/plain' }, ['Hello']]
|
69
64
|
end
|
70
65
|
end
|
71
66
|
```
|
@@ -133,7 +128,7 @@ including any authorization information and custom headers you require:
|
|
133
128
|
ws = Faye::WebSocket::Client.new('ws://www.example.com/', [], {
|
134
129
|
:proxy => {
|
135
130
|
:origin => 'http://username:password@proxy.example.com',
|
136
|
-
:headers => {'User-Agent' => 'ruby'}
|
131
|
+
:headers => { 'User-Agent' => 'ruby' }
|
137
132
|
}
|
138
133
|
})
|
139
134
|
```
|
@@ -190,45 +185,78 @@ ws = Faye::WebSocket::Client.new(url, protocols, options)
|
|
190
185
|
`protocols` as an array of subprotocols as described above, or `nil`. `options`
|
191
186
|
is an optional hash containing any of these keys:
|
192
187
|
|
193
|
-
|
188
|
+
- `:extensions` - an array of
|
194
189
|
[websocket-extensions](https://github.com/faye/websocket-extensions-ruby)
|
195
190
|
compatible extensions, as described above
|
196
|
-
|
191
|
+
- `:headers` - a hash containing key-value pairs representing HTTP headers to be
|
197
192
|
sent during the handshake process
|
198
|
-
|
193
|
+
- `:max_length` - the maximum allowed size of incoming message frames, in bytes.
|
199
194
|
The default value is `2^26 - 1`, or 1 byte short of 64 MiB.
|
200
|
-
|
195
|
+
- `:ping` - an integer that sets how often the WebSocket should send ping
|
201
196
|
frames, measured in seconds
|
202
|
-
|
197
|
+
- `:tls` - a hash containing key-value pairs for specifying TLS parameters.
|
203
198
|
These are passed along to EventMachine and you can find
|
204
199
|
[more details here](http://rubydoc.info/gems/eventmachine/EventMachine%2FConnection%3Astart_tls)
|
205
200
|
|
201
|
+
### Secure sockets
|
202
|
+
|
203
|
+
Starting with version 0.11.0, `Faye::WebSocket::Client` will verify the server
|
204
|
+
certificate for `wss` connections. This is not the default behaviour for
|
205
|
+
EventMachine's TLS interface, and so our defaults for the `:tls` option are a
|
206
|
+
little different.
|
207
|
+
|
208
|
+
First, `:verify_peer` is enabled by default. Our implementation checks that the
|
209
|
+
chain of certificates sent by the server is trusted by your root certificates,
|
210
|
+
and that the final certificate's hostname matches the hostname in the request
|
211
|
+
URL.
|
212
|
+
|
213
|
+
By default, we use your system's root certificate store by invoking
|
214
|
+
`OpenSSL::X509::Store#set_default_paths`. If you want to use a different set of
|
215
|
+
root certificates, you can pass them via the `:root_cert_file` option, which
|
216
|
+
takes a path or an array of paths to the certificates you want to use.
|
217
|
+
|
218
|
+
```ruby
|
219
|
+
ws = Faye::WebSocket::Client.new('wss://example.com/', [], :tls => {
|
220
|
+
:root_cert_file => ['path/to/certificate.pem']
|
221
|
+
})
|
222
|
+
```
|
223
|
+
|
224
|
+
If you want to switch off certificate verification altogether, then set
|
225
|
+
`:verify_peer` to `false`.
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
ws = Faye::WebSocket::Client.new('wss://example.com/', [], :tls => {
|
229
|
+
:verify_peer => false
|
230
|
+
})
|
231
|
+
```
|
232
|
+
|
206
233
|
## WebSocket API
|
207
234
|
|
208
235
|
Both the server- and client-side `WebSocket` objects support the following API:
|
209
236
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
237
|
+
- **`on(:open) { |event| }`** fires when the socket connection is established.
|
238
|
+
Event has no attributes.
|
239
|
+
- **`on(:message) { |event| }`** fires when the socket receives a message. Event
|
240
|
+
has one attribute, **`data`**, which is either a `String` (for text frames) or
|
241
|
+
an `Array` of unsigned integers, i.e. integers in the range `0..255` (for
|
242
|
+
binary frames).
|
243
|
+
- **`on(:error) { |event| }`** fires when there is a protocol error due to bad
|
244
|
+
data sent by the other peer. This event is purely informational, you do not
|
245
|
+
need to implement error recovery.
|
246
|
+
- **`on(:close) { |event| }`** fires when either the client or the server closes
|
247
|
+
the connection. Event has two optional attributes, **`code`** and
|
248
|
+
**`reason`**, that expose the status code and message sent by the peer that
|
221
249
|
closed the connection.
|
222
|
-
|
250
|
+
- **`send(message)`** accepts either a `String` or an `Array` of byte-sized
|
223
251
|
integers and sends a text or binary message over the connection to the other
|
224
252
|
peer; binary data must be encoded as an `Array`.
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
253
|
+
- **`ping(message, &callback)`** sends a ping frame with an optional message and
|
254
|
+
fires the callback when a matching pong is received.
|
255
|
+
- **`close(code, reason)`** closes the connection, sending the given status code
|
256
|
+
and reason text, both of which are optional.
|
257
|
+
- **`version`** is a string containing the version of the `WebSocket` protocol
|
258
|
+
the connection is using.
|
259
|
+
- **`protocol`** is a string (which may be empty) identifying the subprotocol
|
232
260
|
the socket is using.
|
233
261
|
|
234
262
|
|
@@ -261,7 +289,7 @@ App = lambda do |env|
|
|
261
289
|
|
262
290
|
else
|
263
291
|
# Normal HTTP request
|
264
|
-
[200, {'Content-Type' => 'text/plain'}, ['Hello']]
|
292
|
+
[200, { 'Content-Type' => 'text/plain' }, ['Hello']]
|
265
293
|
end
|
266
294
|
end
|
267
295
|
```
|
@@ -276,29 +304,29 @@ es.send('Breaking News!', :event => 'notification', :id => '99')
|
|
276
304
|
|
277
305
|
The `EventSource` object exposes the following properties:
|
278
306
|
|
279
|
-
|
307
|
+
- **`url`** is a string containing the URL the client used to create the
|
280
308
|
EventSource.
|
281
|
-
|
282
|
-
|
283
|
-
|
309
|
+
- **`last_event_id`** is a string containing the last event ID received by the
|
310
|
+
client. You can use this when the client reconnects after a dropped connection
|
311
|
+
to determine which messages need resending.
|
284
312
|
|
285
313
|
When you initialize an EventSource with `Faye::EventSource.new`, you can pass
|
286
314
|
configuration options after the `env` parameter. Available options are:
|
287
315
|
|
288
|
-
|
316
|
+
- **`:headers`** is a hash containing custom headers to be set on the
|
289
317
|
EventSource response.
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
318
|
+
- **`:retry`** is a number that tells the client how long (in seconds) it should
|
319
|
+
wait after a dropped connection before attempting to reconnect.
|
320
|
+
- **`:ping`** is a number that tells the server how often (in seconds) to send
|
321
|
+
'ping' packets to the client to keep the connection open, to defeat timeouts
|
322
|
+
set by proxies. The client will ignore these messages.
|
295
323
|
|
296
324
|
For example, this creates a connection that allows access from any origin, pings
|
297
325
|
every 15 seconds and is retryable every 10 seconds if the connection is broken:
|
298
326
|
|
299
327
|
```ruby
|
300
328
|
es = Faye::EventSource.new(es,
|
301
|
-
:headers => {'Access-Control-Allow-Origin' => '*'},
|
329
|
+
:headers => { 'Access-Control-Allow-Origin' => '*' },
|
302
330
|
:ping => 15,
|
303
331
|
:retry => 10
|
304
332
|
)
|
@@ -487,27 +515,3 @@ class EchoServer < Goliath::API
|
|
487
515
|
end
|
488
516
|
end
|
489
517
|
```
|
490
|
-
|
491
|
-
|
492
|
-
## License
|
493
|
-
|
494
|
-
(The MIT License)
|
495
|
-
|
496
|
-
Copyright (c) 2010-2016 James Coglan
|
497
|
-
|
498
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
499
|
-
this software and associated documentation files (the 'Software'), to deal in
|
500
|
-
the Software without restriction, including without limitation the rights to
|
501
|
-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
502
|
-
the Software, and to permit persons to whom the Software is furnished to do so,
|
503
|
-
subject to the following conditions:
|
504
|
-
|
505
|
-
The above copyright notice and this permission notice shall be included in all
|
506
|
-
copies or substantial portions of the Software.
|
507
|
-
|
508
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
509
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
510
|
-
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
511
|
-
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
512
|
-
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
513
|
-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/lib/faye/eventsource.rb
CHANGED
@@ -63,7 +63,7 @@ module Faye
|
|
63
63
|
end
|
64
64
|
|
65
65
|
private
|
66
|
-
|
66
|
+
|
67
67
|
def open
|
68
68
|
return unless @ready_state == WebSocket::API::CONNECTING
|
69
69
|
|
@@ -83,9 +83,9 @@ module Faye
|
|
83
83
|
gsub(/(\r\n|\r|\n)/, '\1data: ')
|
84
84
|
|
85
85
|
frame = ""
|
86
|
-
frame << "event: #{options[:event]}\r\n" if options[:event]
|
87
|
-
frame << "id: #{options[:id]}\r\n" if options[:id]
|
88
|
-
frame << "data: #{message}\r\n\r\n"
|
86
|
+
frame << "event: #{ options[:event] }\r\n" if options[:event]
|
87
|
+
frame << "id: #{ options[:id] }\r\n" if options[:id]
|
88
|
+
frame << "data: #{ message }\r\n\r\n"
|
89
89
|
|
90
90
|
@stream.write(frame)
|
91
91
|
true
|
data/lib/faye/rack_stream.rb
CHANGED
data/lib/faye/websocket.rb
CHANGED
@@ -17,9 +17,10 @@ module Faye
|
|
17
17
|
class WebSocket
|
18
18
|
root = File.expand_path('../websocket', __FILE__)
|
19
19
|
|
20
|
-
autoload :Adapter,
|
21
|
-
autoload :API,
|
22
|
-
autoload :Client,
|
20
|
+
autoload :Adapter, root + '/adapter'
|
21
|
+
autoload :API, root + '/api'
|
22
|
+
autoload :Client, root + '/client'
|
23
|
+
autoload :SslVerifier, root + '/ssl_verifier'
|
23
24
|
|
24
25
|
ADAPTERS = {
|
25
26
|
'goliath' => :Goliath,
|
@@ -44,7 +45,7 @@ module Faye
|
|
44
45
|
def self.load_adapter(backend)
|
45
46
|
const = Kernel.const_get(ADAPTERS[backend]) rescue nil
|
46
47
|
require(backend) unless const
|
47
|
-
path = File.expand_path("../adapters/#{backend}.rb", __FILE__)
|
48
|
+
path = File.expand_path("../adapters/#{ backend }.rb", __FILE__)
|
48
49
|
require(path) if File.file?(path)
|
49
50
|
end
|
50
51
|
|
data/lib/faye/websocket/api.rb
CHANGED
@@ -10,6 +10,8 @@ module Faye
|
|
10
10
|
CLOSING = 2
|
11
11
|
CLOSED = 3
|
12
12
|
|
13
|
+
CLOSE_TIMEOUT = 30
|
14
|
+
|
13
15
|
include EventTarget
|
14
16
|
|
15
17
|
extend Forwardable
|
@@ -36,12 +38,12 @@ module Faye
|
|
36
38
|
@ping_id = 0
|
37
39
|
@buffered_amount = 0
|
38
40
|
|
39
|
-
@close_params = @ping_timer = @proxy = @stream = nil
|
41
|
+
@close_params = @close_timer = @ping_timer = @proxy = @stream = nil
|
40
42
|
@onopen = @onmessage = @onclose = @onerror = nil
|
41
43
|
|
42
44
|
@driver.on(:open) { |e| open }
|
43
45
|
@driver.on(:message) { |e| receive_message(e.data) }
|
44
|
-
@driver.on(:close) { |e| begin_close(e.reason, e.code) }
|
46
|
+
@driver.on(:close) { |e| begin_close(e.reason, e.code, :wait_for_write => true) }
|
45
47
|
|
46
48
|
@driver.on(:error) do |error|
|
47
49
|
emit_error(error.message)
|
@@ -81,10 +83,12 @@ module Faye
|
|
81
83
|
unless code == 1000 or (code >= 3000 and code <= 4999)
|
82
84
|
raise ArgumentError, "Failed to execute 'close' on WebSocket: " +
|
83
85
|
"The code must be either 1000, or between 3000 and 4999. " +
|
84
|
-
"#{code} is neither."
|
86
|
+
"#{ code } is neither."
|
85
87
|
end
|
86
88
|
|
87
89
|
@ready_state = CLOSING unless @ready_state == CLOSED
|
90
|
+
@close_timer = EventMachine.add_timer(CLOSE_TIMEOUT) { begin_close('', 1006) }
|
91
|
+
|
88
92
|
@driver.close(reason, code)
|
89
93
|
end
|
90
94
|
|
@@ -117,13 +121,17 @@ module Faye
|
|
117
121
|
dispatch_event(event)
|
118
122
|
end
|
119
123
|
|
120
|
-
def begin_close(reason, code)
|
124
|
+
def begin_close(reason, code, options = {})
|
121
125
|
return if @ready_state == CLOSED
|
122
126
|
@ready_state = CLOSING
|
123
127
|
@close_params = [reason, code]
|
124
128
|
|
125
129
|
if @stream
|
126
|
-
|
130
|
+
if options[:wait_for_write]
|
131
|
+
@stream.close_connection_after_writing
|
132
|
+
else
|
133
|
+
@stream.close_connection
|
134
|
+
end
|
127
135
|
else
|
128
136
|
finalize_close
|
129
137
|
end
|
@@ -133,6 +141,7 @@ module Faye
|
|
133
141
|
return if @ready_state == CLOSED
|
134
142
|
@ready_state = CLOSED
|
135
143
|
|
144
|
+
EventMachine.cancel_timer(@close_timer) if @close_timer
|
136
145
|
EventMachine.cancel_timer(@ping_timer) if @ping_timer
|
137
146
|
|
138
147
|
reason = @close_params ? @close_params[0] : ''
|
@@ -10,7 +10,7 @@ module Faye::WebSocket::API
|
|
10
10
|
|
11
11
|
def initialize(event_type, options)
|
12
12
|
@type = event_type
|
13
|
-
options.each { |key, value| instance_variable_set("@#{key}", value) }
|
13
|
+
options.each { |key, value| instance_variable_set("@#{ key }", value) }
|
14
14
|
end
|
15
15
|
|
16
16
|
def init_event(event_type, can_bubble, cancelable)
|
@@ -5,10 +5,10 @@ module Faye::WebSocket::API
|
|
5
5
|
events = %w[open message error close]
|
6
6
|
|
7
7
|
events.each do |event_type|
|
8
|
-
define_method "on#{event_type}=" do |handler|
|
8
|
+
define_method "on#{ event_type }=" do |handler|
|
9
9
|
EventMachine.next_tick do
|
10
10
|
flush(event_type, handler)
|
11
|
-
instance_variable_set("@on#{event_type}", handler)
|
11
|
+
instance_variable_set("@on#{ event_type }", handler)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -7,7 +7,7 @@ module Faye
|
|
7
7
|
extend Forwardable
|
8
8
|
include API
|
9
9
|
|
10
|
-
DEFAULT_PORTS = {'http' => 80, 'https' => 443, 'ws' => 80, 'wss' => 443}
|
10
|
+
DEFAULT_PORTS = { 'http' => 80, 'https' => 443, 'ws' => 80, 'wss' => 443 }
|
11
11
|
SECURE_PROTOCOLS = ['https', 'wss']
|
12
12
|
|
13
13
|
def_delegators :@driver, :headers, :status
|
@@ -17,58 +17,72 @@ module Faye
|
|
17
17
|
super(options) { ::WebSocket::Driver.client(self, :max_length => options[:max_length], :protocols => protocols) }
|
18
18
|
|
19
19
|
proxy = options.fetch(:proxy, {})
|
20
|
-
endpoint
|
21
|
-
port = endpoint.port || DEFAULT_PORTS[endpoint.scheme]
|
22
|
-
@secure = SECURE_PROTOCOLS.include?(endpoint.scheme)
|
20
|
+
@endpoint = URI.parse(proxy[:origin] || @url)
|
21
|
+
port = @endpoint.port || DEFAULT_PORTS[@endpoint.scheme]
|
23
22
|
@origin_tls = options.fetch(:tls, {})
|
24
23
|
@socket_tls = proxy[:origin] ? proxy.fetch(:tls, {}) : @origin_tls
|
25
24
|
|
26
|
-
|
27
|
-
@proxy = @driver.proxy(proxy[:origin])
|
28
|
-
if headers = proxy[:headers]
|
29
|
-
headers.each { |name, value| @proxy.set_header(name, value) }
|
30
|
-
end
|
25
|
+
configure_proxy(proxy)
|
31
26
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
27
|
+
EventMachine.connect(@endpoint.host, port, Connection) do |conn|
|
28
|
+
conn.parent = self
|
29
|
+
end
|
30
|
+
rescue => error
|
31
|
+
on_network_error(error)
|
32
|
+
end
|
36
33
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
private
|
35
|
+
|
36
|
+
def configure_proxy(proxy)
|
37
|
+
return unless proxy[:origin]
|
41
38
|
|
42
|
-
|
43
|
-
|
39
|
+
@proxy = @driver.proxy(proxy[:origin])
|
40
|
+
@proxy.on(:error) { |error| @driver.emit(:error, error) }
|
44
41
|
|
45
|
-
|
46
|
-
|
47
|
-
end
|
42
|
+
if headers = proxy[:headers]
|
43
|
+
headers.each { |name, value| @proxy.set_header(name, value) }
|
48
44
|
end
|
49
45
|
|
50
|
-
|
51
|
-
|
46
|
+
@proxy.on(:connect) do
|
47
|
+
@proxy = nil
|
48
|
+
start_tls(URI.parse(@url), @origin_tls)
|
49
|
+
@driver.start
|
52
50
|
end
|
53
|
-
rescue => error
|
54
|
-
emit_error("Network error: #{url}: #{error.message}")
|
55
|
-
finalize_close
|
56
51
|
end
|
57
52
|
|
58
|
-
|
53
|
+
def start_tls(uri, options)
|
54
|
+
return unless SECURE_PROTOCOLS.include?(uri.scheme)
|
55
|
+
|
56
|
+
tls_options = { :sni_hostname => uri.host, :verify_peer => true }.merge(options)
|
57
|
+
@ssl_verifier = SslVerifier.new(uri.host, tls_options)
|
58
|
+
@stream.start_tls(tls_options)
|
59
|
+
end
|
59
60
|
|
60
61
|
def on_connect(stream)
|
61
62
|
@stream = stream
|
62
|
-
|
63
|
-
if @secure
|
64
|
-
socket_tls = {:sni_hostname => URI.parse(@url).host}.merge(@socket_tls)
|
65
|
-
@stream.start_tls(socket_tls)
|
66
|
-
end
|
63
|
+
start_tls(@endpoint, @socket_tls)
|
67
64
|
|
68
65
|
worker = @proxy || @driver
|
69
66
|
worker.start
|
70
67
|
end
|
71
68
|
|
69
|
+
def on_network_error(error)
|
70
|
+
emit_error("Network error: #{ @url }: #{ error.message }")
|
71
|
+
finalize_close
|
72
|
+
end
|
73
|
+
|
74
|
+
def ssl_verify_peer(cert)
|
75
|
+
@ssl_verifier.ssl_verify_peer(cert)
|
76
|
+
rescue => error
|
77
|
+
on_network_error(error)
|
78
|
+
end
|
79
|
+
|
80
|
+
def ssl_handshake_completed
|
81
|
+
@ssl_verifier.ssl_handshake_completed
|
82
|
+
rescue => error
|
83
|
+
on_network_error(error)
|
84
|
+
end
|
85
|
+
|
72
86
|
module Connection
|
73
87
|
attr_accessor :parent
|
74
88
|
|
@@ -76,11 +90,20 @@ module Faye
|
|
76
90
|
parent.__send__(:on_connect, self)
|
77
91
|
end
|
78
92
|
|
93
|
+
def ssl_verify_peer(cert)
|
94
|
+
parent.__send__(:ssl_verify_peer, cert)
|
95
|
+
end
|
96
|
+
|
97
|
+
def ssl_handshake_completed
|
98
|
+
parent.__send__(:ssl_handshake_completed)
|
99
|
+
end
|
100
|
+
|
79
101
|
def receive_data(data)
|
80
102
|
parent.__send__(:parse, data)
|
81
103
|
end
|
82
104
|
|
83
|
-
def unbind
|
105
|
+
def unbind(error = nil)
|
106
|
+
parent.__send__(:emit_error, error) if error
|
84
107
|
parent.__send__(:finalize_close)
|
85
108
|
end
|
86
109
|
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# This code is based on the implementation in Faraday:
|
2
|
+
#
|
3
|
+
# https://github.com/lostisland/faraday/blob/v1.0.1/lib/faraday/adapter/em_http_ssl_patch.rb
|
4
|
+
#
|
5
|
+
# Faraday is published under the MIT license as detailed here:
|
6
|
+
#
|
7
|
+
# https://github.com/lostisland/faraday/blob/v1.0.1/LICENSE.md
|
8
|
+
#
|
9
|
+
# Copyright (c) 2009-2019 Rick Olson, Zack Hobson
|
10
|
+
#
|
11
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
12
|
+
# of this software and associated documentation files (the "Software"), to deal
|
13
|
+
# in the Software without restriction, including without limitation the rights
|
14
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
15
|
+
# copies of the Software, and to permit persons to whom the Software is
|
16
|
+
# furnished to do so, subject to the following conditions:
|
17
|
+
#
|
18
|
+
# The above copyright notice and this permission notice shall be included in
|
19
|
+
# all copies or substantial portions of the Software.
|
20
|
+
|
21
|
+
require 'openssl'
|
22
|
+
|
23
|
+
module Faye
|
24
|
+
class WebSocket
|
25
|
+
|
26
|
+
SSLError = Class.new(OpenSSL::SSL::SSLError)
|
27
|
+
|
28
|
+
class SslVerifier
|
29
|
+
def initialize(hostname, ssl_opts)
|
30
|
+
@hostname = hostname
|
31
|
+
@ssl_opts = ssl_opts
|
32
|
+
@cert_store = OpenSSL::X509::Store.new
|
33
|
+
|
34
|
+
if root = @ssl_opts[:root_cert_file]
|
35
|
+
[root].flatten.each { |ca_path| @cert_store.add_file(ca_path) }
|
36
|
+
else
|
37
|
+
@cert_store.set_default_paths
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def ssl_verify_peer(cert_text)
|
42
|
+
return true unless should_verify?
|
43
|
+
|
44
|
+
certificate = parse_cert(cert_text)
|
45
|
+
return false unless certificate
|
46
|
+
|
47
|
+
unless @cert_store.verify(certificate)
|
48
|
+
raise SSLError, "Unable to verify the server certificate for '#{ @hostname }'"
|
49
|
+
end
|
50
|
+
|
51
|
+
store_cert(certificate)
|
52
|
+
@last_cert = certificate
|
53
|
+
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
def ssl_handshake_completed
|
58
|
+
return unless should_verify?
|
59
|
+
|
60
|
+
unless identity_verified?
|
61
|
+
raise SSLError, "Host '#{ @hostname }' does not match the server certificate"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def should_verify?
|
68
|
+
@ssl_opts[:verify_peer] != false
|
69
|
+
end
|
70
|
+
|
71
|
+
def parse_cert(cert_text)
|
72
|
+
OpenSSL::X509::Certificate.new(cert_text)
|
73
|
+
rescue OpenSSL::X509::CertificateError
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
|
77
|
+
def store_cert(certificate)
|
78
|
+
@cert_store.add_cert(certificate)
|
79
|
+
rescue OpenSSL::X509::StoreError => error
|
80
|
+
raise error unless error.message == 'cert already in hash table'
|
81
|
+
end
|
82
|
+
|
83
|
+
def identity_verified?
|
84
|
+
@last_cert and OpenSSL::SSL.verify_certificate_identity(@last_cert, @hostname)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: faye-websocket
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Coglan
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: eventmachine
|
@@ -66,20 +66,6 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: public_suffix
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "<"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: 1.5.0
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "<"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: 1.5.0
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
70
|
name: puma
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -168,14 +154,14 @@ dependencies:
|
|
168
154
|
name: goliath
|
169
155
|
requirement: !ruby/object:Gem::Requirement
|
170
156
|
requirements:
|
171
|
-
- - "
|
157
|
+
- - ">"
|
172
158
|
- !ruby/object:Gem::Version
|
173
159
|
version: '0'
|
174
160
|
type: :development
|
175
161
|
prerelease: false
|
176
162
|
version_requirements: !ruby/object:Gem::Requirement
|
177
163
|
requirements:
|
178
|
-
- - "
|
164
|
+
- - ">"
|
179
165
|
- !ruby/object:Gem::Version
|
180
166
|
version: '0'
|
181
167
|
- !ruby/object:Gem::Dependency
|
@@ -192,7 +178,7 @@ dependencies:
|
|
192
178
|
- - ">="
|
193
179
|
- !ruby/object:Gem::Version
|
194
180
|
version: 4.0.0
|
195
|
-
description:
|
181
|
+
description:
|
196
182
|
email: jcoglan@gmail.com
|
197
183
|
executables: []
|
198
184
|
extensions: []
|
@@ -200,17 +186,8 @@ extra_rdoc_files:
|
|
200
186
|
- README.md
|
201
187
|
files:
|
202
188
|
- CHANGELOG.md
|
189
|
+
- LICENSE.md
|
203
190
|
- README.md
|
204
|
-
- examples/app.rb
|
205
|
-
- examples/autobahn_client.rb
|
206
|
-
- examples/client.rb
|
207
|
-
- examples/config.ru
|
208
|
-
- examples/haproxy.conf
|
209
|
-
- examples/proxy_server.rb
|
210
|
-
- examples/rainbows.conf
|
211
|
-
- examples/server.rb
|
212
|
-
- examples/sse.html
|
213
|
-
- examples/ws.html
|
214
191
|
- lib/faye/adapters/goliath.rb
|
215
192
|
- lib/faye/adapters/rainbows.rb
|
216
193
|
- lib/faye/adapters/rainbows_client.rb
|
@@ -223,11 +200,12 @@ files:
|
|
223
200
|
- lib/faye/websocket/api/event.rb
|
224
201
|
- lib/faye/websocket/api/event_target.rb
|
225
202
|
- lib/faye/websocket/client.rb
|
203
|
+
- lib/faye/websocket/ssl_verifier.rb
|
226
204
|
homepage: https://github.com/faye/faye-websocket-ruby
|
227
205
|
licenses:
|
228
|
-
-
|
206
|
+
- Apache-2.0
|
229
207
|
metadata: {}
|
230
|
-
post_install_message:
|
208
|
+
post_install_message:
|
231
209
|
rdoc_options:
|
232
210
|
- "--main"
|
233
211
|
- README.md
|
@@ -246,9 +224,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
246
224
|
- !ruby/object:Gem::Version
|
247
225
|
version: '0'
|
248
226
|
requirements: []
|
249
|
-
|
250
|
-
|
251
|
-
signing_key:
|
227
|
+
rubygems_version: 3.1.2
|
228
|
+
signing_key:
|
252
229
|
specification_version: 4
|
253
230
|
summary: Standards-compliant WebSocket server and client
|
254
231
|
test_files: []
|
data/examples/app.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
require 'faye/websocket'
|
2
|
-
require 'permessage_deflate'
|
3
|
-
require 'rack'
|
4
|
-
|
5
|
-
static = Rack::File.new(File.dirname(__FILE__))
|
6
|
-
options = {:extensions => [PermessageDeflate], :ping => 5}
|
7
|
-
|
8
|
-
App = lambda do |env|
|
9
|
-
if Faye::WebSocket.websocket?(env)
|
10
|
-
ws = Faye::WebSocket.new(env, ['irc', 'xmpp'], options)
|
11
|
-
p [:open, ws.url, ws.version, ws.protocol]
|
12
|
-
|
13
|
-
ws.onmessage = lambda do |event|
|
14
|
-
ws.send(event.data)
|
15
|
-
end
|
16
|
-
|
17
|
-
ws.onclose = lambda do |event|
|
18
|
-
p [:close, event.code, event.reason]
|
19
|
-
ws = nil
|
20
|
-
end
|
21
|
-
|
22
|
-
ws.rack_response
|
23
|
-
|
24
|
-
elsif Faye::EventSource.eventsource?(env)
|
25
|
-
es = Faye::EventSource.new(env)
|
26
|
-
time = es.last_event_id.to_i
|
27
|
-
|
28
|
-
p [:open, es.url, es.last_event_id]
|
29
|
-
|
30
|
-
loop = EM.add_periodic_timer(2) do
|
31
|
-
time += 1
|
32
|
-
es.send("Time: #{time}")
|
33
|
-
EM.add_timer(1) do
|
34
|
-
es.send('Update!!', :event => 'update', :id => time) if es
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
es.send("Welcome!\n\nThis is an EventSource server.")
|
39
|
-
|
40
|
-
es.onclose = lambda do |event|
|
41
|
-
EM.cancel_timer(loop)
|
42
|
-
p [:close, es.url]
|
43
|
-
es = nil
|
44
|
-
end
|
45
|
-
|
46
|
-
es.rack_response
|
47
|
-
|
48
|
-
else
|
49
|
-
static.call(env)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def App.log(message)
|
54
|
-
end
|
data/examples/autobahn_client.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler/setup'
|
3
|
-
require 'cgi'
|
4
|
-
require 'faye/websocket'
|
5
|
-
require 'permessage_deflate'
|
6
|
-
require 'progressbar'
|
7
|
-
|
8
|
-
EM.run {
|
9
|
-
host = 'ws://localhost:9001'
|
10
|
-
ruby = RUBY_PLATFORM =~ /java/ ? 'jruby' : 'cruby'
|
11
|
-
agent = CGI.escape("#{ruby}-#{RUBY_VERSION}")
|
12
|
-
cases = 0
|
13
|
-
options = {:extensions => [PermessageDeflate]}
|
14
|
-
|
15
|
-
socket = Faye::WebSocket::Client.new("#{host}/getCaseCount")
|
16
|
-
progress = nil
|
17
|
-
|
18
|
-
socket.onmessage = lambda do |event|
|
19
|
-
puts "Total cases to run: #{event.data}"
|
20
|
-
cases = event.data.to_i
|
21
|
-
progress = ProgressBar.new('Autobahn', cases)
|
22
|
-
end
|
23
|
-
|
24
|
-
run_case = lambda do |n|
|
25
|
-
if n > cases
|
26
|
-
socket = Faye::WebSocket::Client.new("#{host}/updateReports?agent=#{agent}")
|
27
|
-
progress.finish
|
28
|
-
socket.onclose = lambda { |e| EM.stop }
|
29
|
-
next
|
30
|
-
end
|
31
|
-
|
32
|
-
url = "#{host}/runCase?case=#{n}&agent=#{agent}"
|
33
|
-
socket = Faye::WebSocket::Client.new(url, [], options)
|
34
|
-
|
35
|
-
socket.onmessage = lambda do |event|
|
36
|
-
socket.send(event.data)
|
37
|
-
end
|
38
|
-
|
39
|
-
socket.on :close do |event|
|
40
|
-
progress.inc
|
41
|
-
run_case[n + 1]
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
socket.onclose = lambda do |event|
|
46
|
-
run_case[1]
|
47
|
-
end
|
48
|
-
}
|
data/examples/client.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler/setup'
|
3
|
-
require 'faye/websocket'
|
4
|
-
require 'eventmachine'
|
5
|
-
require 'permessage_deflate'
|
6
|
-
|
7
|
-
EM.run {
|
8
|
-
url = ARGV[0]
|
9
|
-
proxy = ARGV[1]
|
10
|
-
|
11
|
-
ws = Faye::WebSocket::Client.new(url, [],
|
12
|
-
:proxy => {:origin => proxy, :headers => {'User-Agent' => 'Echo'}},
|
13
|
-
:headers => {'Origin' => 'http://faye.jcoglan.com'},
|
14
|
-
:extensions => [PermessageDeflate]
|
15
|
-
)
|
16
|
-
|
17
|
-
ws.onopen = lambda do |event|
|
18
|
-
p [:open, ws.headers]
|
19
|
-
ws.send('mic check')
|
20
|
-
end
|
21
|
-
|
22
|
-
ws.onclose = lambda do |close|
|
23
|
-
p [:close, close.code, close.reason]
|
24
|
-
EM.stop
|
25
|
-
end
|
26
|
-
|
27
|
-
ws.onerror = lambda do |error|
|
28
|
-
p [:error, error.message]
|
29
|
-
end
|
30
|
-
|
31
|
-
ws.onmessage = lambda do |message|
|
32
|
-
p [:message, message.data]
|
33
|
-
end
|
34
|
-
}
|
data/examples/config.ru
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
# Run using your favourite server:
|
2
|
-
#
|
3
|
-
# thin start -R examples/config.ru -p 7000
|
4
|
-
# rainbows -c examples/rainbows.conf -E production examples/config.ru -p 7000
|
5
|
-
|
6
|
-
require 'rubygems'
|
7
|
-
require 'bundler/setup'
|
8
|
-
require File.expand_path('../app', __FILE__)
|
9
|
-
|
10
|
-
Faye::WebSocket.load_adapter('thin')
|
11
|
-
Faye::WebSocket.load_adapter('rainbows')
|
12
|
-
|
13
|
-
run App
|
data/examples/haproxy.conf
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
defaults
|
2
|
-
mode http
|
3
|
-
timeout client 5s
|
4
|
-
timeout connect 5s
|
5
|
-
timeout server 5s
|
6
|
-
|
7
|
-
frontend all 0.0.0.0:3000
|
8
|
-
mode http
|
9
|
-
timeout client 120s
|
10
|
-
|
11
|
-
option forwardfor
|
12
|
-
option http-server-close
|
13
|
-
option http-pretend-keepalive
|
14
|
-
|
15
|
-
default_backend sockets
|
16
|
-
|
17
|
-
backend sockets
|
18
|
-
balance uri depth 2
|
19
|
-
timeout server 120s
|
20
|
-
server socket1 127.0.0.1:7000
|
data/examples/proxy_server.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler/setup'
|
3
|
-
require 'eventmachine'
|
4
|
-
require 'websocket/driver'
|
5
|
-
|
6
|
-
require File.expand_path('../../spec/proxy_server', __FILE__)
|
7
|
-
|
8
|
-
port = ARGV[0]
|
9
|
-
secure = ARGV[1] == 'tls'
|
10
|
-
|
11
|
-
EM.run {
|
12
|
-
proxy = ProxyServer.new(:debug => true)
|
13
|
-
proxy.listen(port, secure)
|
14
|
-
}
|
data/examples/rainbows.conf
DELETED
data/examples/server.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler/setup'
|
3
|
-
require 'rack/content_length'
|
4
|
-
require 'rack/chunked'
|
5
|
-
|
6
|
-
port = ARGV[0] || 7000
|
7
|
-
secure = ARGV[1] == 'tls'
|
8
|
-
engine = ARGV[2] || 'thin'
|
9
|
-
spec = File.expand_path('../../spec', __FILE__)
|
10
|
-
|
11
|
-
require File.expand_path('../app', __FILE__)
|
12
|
-
Faye::WebSocket.load_adapter(engine)
|
13
|
-
|
14
|
-
case engine
|
15
|
-
|
16
|
-
when 'goliath'
|
17
|
-
class WebSocketServer < Goliath::API
|
18
|
-
def response(env)
|
19
|
-
App.call(env)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
when 'puma'
|
24
|
-
events = Puma::Events.new($stdout, $stderr)
|
25
|
-
binder = Puma::Binder.new(events)
|
26
|
-
binder.parse(["tcp://0.0.0.0:#{port}"], App)
|
27
|
-
server = Puma::Server.new(App, events)
|
28
|
-
server.binder = binder
|
29
|
-
server.run.join
|
30
|
-
|
31
|
-
when 'rainbows'
|
32
|
-
rackup = Unicorn::Configurator::RACKUP
|
33
|
-
rackup[:port] = port
|
34
|
-
rackup[:set_listener] = true
|
35
|
-
options = rackup[:options]
|
36
|
-
options[:config_file] = File.expand_path('../rainbows.conf', __FILE__)
|
37
|
-
Rainbows::HttpServer.new(App, options).start.join
|
38
|
-
|
39
|
-
when 'thin'
|
40
|
-
thin = Rack::Handler.get('thin')
|
41
|
-
thin.run(App, :Port => port) do |server|
|
42
|
-
if secure
|
43
|
-
server.ssl_options = {
|
44
|
-
:private_key_file => spec + '/server.key',
|
45
|
-
:cert_chain_file => spec + '/server.crt'
|
46
|
-
}
|
47
|
-
server.ssl = true
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
data/examples/sse.html
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
<!doctype html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
5
|
-
<title>EventSource test</title>
|
6
|
-
</head>
|
7
|
-
<body>
|
8
|
-
|
9
|
-
<h1>EventSource test</h1>
|
10
|
-
<ul></ul>
|
11
|
-
|
12
|
-
<script type="text/javascript">
|
13
|
-
var logger = document.getElementsByTagName('ul')[0],
|
14
|
-
socket = new EventSource('/');
|
15
|
-
|
16
|
-
var log = function(text) {
|
17
|
-
logger.innerHTML += '<li>' + text + '</li>';
|
18
|
-
};
|
19
|
-
|
20
|
-
socket.onopen = function() {
|
21
|
-
log('OPEN');
|
22
|
-
};
|
23
|
-
|
24
|
-
socket.onmessage = function(event) {
|
25
|
-
log('MESSAGE: ' + event.data);
|
26
|
-
};
|
27
|
-
|
28
|
-
socket.addEventListener('update', function(event) {
|
29
|
-
log('UPDATE(' + event.lastEventId + '): ' + event.data);
|
30
|
-
});
|
31
|
-
|
32
|
-
socket.onerror = function(event) {
|
33
|
-
log('ERROR: ' + event.message);
|
34
|
-
};
|
35
|
-
</script>
|
36
|
-
|
37
|
-
</body>
|
38
|
-
</html>
|
data/examples/ws.html
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
<!doctype html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
5
|
-
<title>WebSocket test</title>
|
6
|
-
</head>
|
7
|
-
<body>
|
8
|
-
|
9
|
-
<h1>WebSocket test</h1>
|
10
|
-
<ul></ul>
|
11
|
-
|
12
|
-
<script type="text/javascript">
|
13
|
-
var logger = document.getElementsByTagName('ul')[0],
|
14
|
-
Socket = window.MozWebSocket || window.WebSocket,
|
15
|
-
protos = ['foo', 'bar', 'xmpp'],
|
16
|
-
socket = new Socket('ws://' + location.hostname + ':' + location.port + '/', protos),
|
17
|
-
index = 0;
|
18
|
-
|
19
|
-
var log = function(text) {
|
20
|
-
logger.innerHTML += '<li>' + text + '</li>';
|
21
|
-
};
|
22
|
-
|
23
|
-
socket.addEventListener('open', function() {
|
24
|
-
log('OPEN: ' + socket.protocol);
|
25
|
-
socket.send('Hello, world');
|
26
|
-
});
|
27
|
-
|
28
|
-
socket.onerror = function(event) {
|
29
|
-
log('ERROR: ' + event.message);
|
30
|
-
};
|
31
|
-
|
32
|
-
socket.onmessage = function(event) {
|
33
|
-
log('MESSAGE: ' + event.data);
|
34
|
-
setTimeout(function() { socket.send(++index + ' ' + event.data) }, 2000);
|
35
|
-
};
|
36
|
-
|
37
|
-
socket.onclose = function(event) {
|
38
|
-
log('CLOSE: ' + event.code + ', ' + event.reason);
|
39
|
-
};
|
40
|
-
</script>
|
41
|
-
|
42
|
-
</body>
|
43
|
-
</html>
|