faye-websocket 0.10.5 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: [](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 [](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>
|