faye 1.0.3 → 1.4.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 +386 -196
- data/LICENSE.md +12 -0
- data/README.md +4 -30
- data/build/client/faye-browser-min.js +2 -0
- data/build/client/faye-browser-min.js.map +1 -0
- data/build/client/faye-browser.js +3371 -0
- data/build/client/faye-browser.js.map +1 -0
- data/lib/faye.rb +10 -14
- data/lib/faye/adapters/rack_adapter.rb +64 -34
- data/lib/faye/engines/connection.rb +7 -7
- data/lib/faye/engines/memory.rb +7 -8
- data/lib/faye/engines/proxy.rb +14 -15
- data/lib/faye/error.rb +0 -1
- data/lib/faye/mixins/deferrable.rb +0 -1
- data/lib/faye/mixins/logging.rb +0 -1
- data/lib/faye/mixins/publisher.rb +0 -1
- data/lib/faye/mixins/timeouts.rb +0 -1
- data/lib/faye/protocol/channel.rb +6 -8
- data/lib/faye/protocol/client.rb +109 -161
- data/lib/faye/protocol/dispatcher.rb +170 -0
- data/lib/faye/protocol/extensible.rb +1 -2
- data/lib/faye/protocol/grammar.rb +0 -1
- data/lib/faye/protocol/scheduler.rb +43 -0
- data/lib/faye/protocol/server.rb +23 -14
- data/lib/faye/protocol/socket.rb +0 -1
- data/lib/faye/protocol/subscription.rb +17 -2
- data/lib/faye/transport/http.rb +43 -33
- data/lib/faye/transport/local.rb +6 -5
- data/lib/faye/transport/transport.rb +69 -38
- data/lib/faye/transport/web_socket.rb +47 -41
- data/lib/faye/util/namespace.rb +0 -1
- metadata +59 -29
- data/lib/faye-browser-min.js +0 -3
- data/lib/faye-browser-min.js.map +0 -1
- data/lib/faye-browser.js +0 -2541
- data/lib/faye/protocol/envelope.rb +0 -24
data/lib/faye/error.rb
CHANGED
data/lib/faye/mixins/logging.rb
CHANGED
data/lib/faye/mixins/timeouts.rb
CHANGED
@@ -75,7 +75,7 @@ module Faye
|
|
75
75
|
end
|
76
76
|
|
77
77
|
class Set
|
78
|
-
def initialize
|
78
|
+
def initialize
|
79
79
|
@channels = {}
|
80
80
|
end
|
81
81
|
|
@@ -91,18 +91,17 @@ module Faye
|
|
91
91
|
@channels.has_key?(name)
|
92
92
|
end
|
93
93
|
|
94
|
-
def subscribe(names,
|
95
|
-
return unless callback
|
94
|
+
def subscribe(names, subscription)
|
96
95
|
names.each do |name|
|
97
96
|
channel = @channels[name] ||= Channel.new(name)
|
98
|
-
channel.bind(:message, &
|
97
|
+
channel.bind(:message, &subscription)
|
99
98
|
end
|
100
99
|
end
|
101
100
|
|
102
|
-
def unsubscribe(name,
|
101
|
+
def unsubscribe(name, subscription)
|
103
102
|
channel = @channels[name]
|
104
103
|
return false unless channel
|
105
|
-
channel.unbind(:message, &
|
104
|
+
channel.unbind(:message, &subscription)
|
106
105
|
if channel.unused?
|
107
106
|
remove(name)
|
108
107
|
true
|
@@ -115,11 +114,10 @@ module Faye
|
|
115
114
|
channels = Channel.expand(message['channel'])
|
116
115
|
channels.each do |name|
|
117
116
|
channel = @channels[name]
|
118
|
-
channel.trigger(:message, message
|
117
|
+
channel.trigger(:message, message) if channel
|
119
118
|
end
|
120
119
|
end
|
121
120
|
end
|
122
121
|
|
123
122
|
end
|
124
123
|
end
|
125
|
-
|
data/lib/faye/protocol/client.rb
CHANGED
@@ -6,59 +6,41 @@ module Faye
|
|
6
6
|
include Logging
|
7
7
|
include Extensible
|
8
8
|
|
9
|
-
UNCONNECTED
|
10
|
-
CONNECTING
|
11
|
-
CONNECTED
|
12
|
-
DISCONNECTED
|
9
|
+
UNCONNECTED = 1
|
10
|
+
CONNECTING = 2
|
11
|
+
CONNECTED = 3
|
12
|
+
DISCONNECTED = 4
|
13
13
|
|
14
|
-
HANDSHAKE
|
15
|
-
RETRY
|
16
|
-
NONE
|
14
|
+
HANDSHAKE = 'handshake'
|
15
|
+
RETRY = 'retry'
|
16
|
+
NONE = 'none'
|
17
17
|
|
18
|
-
CONNECTION_TIMEOUT
|
19
|
-
DEFAULT_RETRY = 5.0
|
20
|
-
MAX_REQUEST_SIZE = 2048
|
18
|
+
CONNECTION_TIMEOUT = 60.0
|
21
19
|
|
22
|
-
|
20
|
+
extend Forwardable
|
21
|
+
def_delegators :@dispatcher, :add_websocket_extension, :disable, :set_header
|
23
22
|
|
24
23
|
def initialize(endpoint = nil, options = {})
|
24
|
+
::WebSocket::Driver.validate_options(options, [:interval, :timeout, :endpoints, :proxy, :retry, :scheduler, :websocket_extensions, :tls])
|
25
25
|
super()
|
26
26
|
info('New client created for ?', endpoint)
|
27
27
|
|
28
|
-
@options = options
|
29
|
-
@endpoint = Faye.parse_url(endpoint || RackAdapter::DEFAULT_ENDPOINT)
|
30
|
-
@endpoints = @options[:endpoints] || {}
|
31
|
-
@transports = {}
|
32
|
-
@cookies = CookieJar::Jar.new
|
33
|
-
@headers = {}
|
34
|
-
@disabled = []
|
35
|
-
@retry = @options[:retry] || DEFAULT_RETRY
|
36
|
-
|
37
|
-
@endpoints.each do |key, value|
|
38
|
-
@endpoints[key] = Faye.parse_url(value)
|
39
|
-
end
|
40
|
-
|
41
|
-
@max_request_size = MAX_REQUEST_SIZE
|
42
|
-
|
43
|
-
@state = UNCONNECTED
|
44
28
|
@channels = Channel::Set.new
|
29
|
+
@dispatcher = Dispatcher.new(self, endpoint || RackAdapter::DEFAULT_ENDPOINT, options)
|
30
|
+
|
45
31
|
@message_id = 0
|
32
|
+
@state = UNCONNECTED
|
46
33
|
|
47
34
|
@response_callbacks = {}
|
48
35
|
|
49
36
|
@advice = {
|
50
37
|
'reconnect' => RETRY,
|
51
|
-
'interval' => 1000.0 * (
|
52
|
-
'timeout' => 1000.0 * (
|
38
|
+
'interval' => 1000.0 * (options[:interval] || Engine::INTERVAL),
|
39
|
+
'timeout' => 1000.0 * (options[:timeout] || CONNECTION_TIMEOUT)
|
53
40
|
}
|
54
|
-
|
41
|
+
@dispatcher.timeout = @advice['timeout'] / 1000.0
|
55
42
|
|
56
|
-
|
57
|
-
@disabled << feature
|
58
|
-
end
|
59
|
-
|
60
|
-
def set_header(name, value)
|
61
|
-
@headers[name.to_s] = value.to_s
|
43
|
+
@dispatcher.bind(:message, &method(:receive_message))
|
62
44
|
end
|
63
45
|
|
64
46
|
# Request
|
@@ -86,30 +68,30 @@ module Faye
|
|
86
68
|
|
87
69
|
@state = CONNECTING
|
88
70
|
|
89
|
-
info('Initiating handshake with ?', @endpoint)
|
90
|
-
select_transport(MANDATORY_CONNECTION_TYPES)
|
71
|
+
info('Initiating handshake with ?', @dispatcher.endpoint.to_s)
|
72
|
+
@dispatcher.select_transport(MANDATORY_CONNECTION_TYPES)
|
91
73
|
|
92
|
-
|
93
|
-
'channel'
|
94
|
-
'version'
|
95
|
-
'supportedConnectionTypes'
|
74
|
+
send_message({
|
75
|
+
'channel' => Channel::HANDSHAKE,
|
76
|
+
'version' => BAYEUX_VERSION,
|
77
|
+
'supportedConnectionTypes' => @dispatcher.connection_types
|
96
78
|
|
97
|
-
}) do |response|
|
79
|
+
}, {}) do |response|
|
98
80
|
|
99
81
|
if response['successful']
|
100
|
-
@state
|
101
|
-
@client_id = response['clientId']
|
82
|
+
@state = CONNECTED
|
83
|
+
@dispatcher.client_id = response['clientId']
|
102
84
|
|
103
|
-
select_transport(response['supportedConnectionTypes'])
|
85
|
+
@dispatcher.select_transport(response['supportedConnectionTypes'])
|
104
86
|
|
105
|
-
info('Handshake successful: ?', @client_id)
|
87
|
+
info('Handshake successful: ?', @dispatcher.client_id)
|
106
88
|
|
107
89
|
subscribe(@channels.keys, true)
|
108
90
|
block.call if block_given?
|
109
91
|
|
110
92
|
else
|
111
93
|
info('Handshake unsuccessful')
|
112
|
-
EventMachine.add_timer(@
|
94
|
+
EventMachine.add_timer(@dispatcher.retry) { handshake(&block) }
|
113
95
|
@state = UNCONNECTED
|
114
96
|
end
|
115
97
|
end
|
@@ -133,21 +115,21 @@ module Faye
|
|
133
115
|
callback(&block)
|
134
116
|
return unless @state == CONNECTED
|
135
117
|
|
136
|
-
info('Calling deferred actions for ?', @client_id)
|
118
|
+
info('Calling deferred actions for ?', @dispatcher.client_id)
|
137
119
|
set_deferred_status(:succeeded)
|
138
120
|
set_deferred_status(:unknown)
|
139
121
|
|
140
122
|
return unless @connect_request.nil?
|
141
123
|
@connect_request = true
|
142
124
|
|
143
|
-
info('Initiating connection for ?', @client_id)
|
125
|
+
info('Initiating connection for ?', @dispatcher.client_id)
|
144
126
|
|
145
|
-
|
146
|
-
'channel'
|
147
|
-
'clientId'
|
148
|
-
'connectionType'
|
127
|
+
send_message({
|
128
|
+
'channel' => Channel::CONNECT,
|
129
|
+
'clientId' => @dispatcher.client_id,
|
130
|
+
'connectionType' => @dispatcher.connection_type
|
149
131
|
|
150
|
-
}) do
|
132
|
+
}, {}) do
|
151
133
|
cycle_connection
|
152
134
|
end
|
153
135
|
end
|
@@ -163,18 +145,26 @@ module Faye
|
|
163
145
|
return unless @state == CONNECTED
|
164
146
|
@state = DISCONNECTED
|
165
147
|
|
166
|
-
info('Disconnecting ?', @client_id)
|
148
|
+
info('Disconnecting ?', @dispatcher.client_id)
|
149
|
+
promise = Publication.new
|
167
150
|
|
168
|
-
|
169
|
-
'channel'
|
170
|
-
'clientId'
|
151
|
+
send_message({
|
152
|
+
'channel' => Channel::DISCONNECT,
|
153
|
+
'clientId' => @dispatcher.client_id
|
171
154
|
|
172
|
-
}) do |response|
|
173
|
-
|
155
|
+
}, {}) do |response|
|
156
|
+
if response['successful']
|
157
|
+
@dispatcher.close
|
158
|
+
promise.set_deferred_status(:succeeded)
|
159
|
+
else
|
160
|
+
promise.set_deferred_status(:failed, Error.parse(response['error']))
|
161
|
+
end
|
174
162
|
end
|
175
163
|
|
176
|
-
info('Clearing channel listeners for ?', @client_id)
|
164
|
+
info('Clearing channel listeners for ?', @dispatcher.client_id)
|
177
165
|
@channels = Channel::Set.new
|
166
|
+
|
167
|
+
promise
|
178
168
|
end
|
179
169
|
|
180
170
|
# Request Response
|
@@ -196,28 +186,28 @@ module Faye
|
|
196
186
|
has_subscribe = @channels.has_subscription?(channel)
|
197
187
|
|
198
188
|
if has_subscribe and not force
|
199
|
-
@channels.subscribe([channel],
|
189
|
+
@channels.subscribe([channel], subscription)
|
200
190
|
subscription.set_deferred_status(:succeeded)
|
201
191
|
return subscription
|
202
192
|
end
|
203
193
|
|
204
194
|
connect {
|
205
|
-
info('Client ? attempting to subscribe to ?', @client_id, channel)
|
206
|
-
@channels.subscribe([channel],
|
195
|
+
info('Client ? attempting to subscribe to ?', @dispatcher.client_id, channel)
|
196
|
+
@channels.subscribe([channel], subscription) unless force
|
207
197
|
|
208
|
-
|
209
|
-
'channel'
|
210
|
-
'clientId'
|
211
|
-
'subscription'
|
198
|
+
send_message({
|
199
|
+
'channel' => Channel::SUBSCRIBE,
|
200
|
+
'clientId' => @dispatcher.client_id,
|
201
|
+
'subscription' => channel
|
212
202
|
|
213
|
-
}) do |response|
|
203
|
+
}, {}) do |response|
|
214
204
|
unless response['successful']
|
215
205
|
subscription.set_deferred_status(:failed, Error.parse(response['error']))
|
216
|
-
next @channels.unsubscribe(channel,
|
206
|
+
next @channels.unsubscribe(channel, subscription)
|
217
207
|
end
|
218
208
|
|
219
209
|
channels = [response['subscription']].flatten
|
220
|
-
info('Subscription acknowledged for ? to ?', @client_id, channels)
|
210
|
+
info('Subscription acknowledged for ? to ?', @dispatcher.client_id, channels)
|
221
211
|
subscription.set_deferred_status(:succeeded)
|
222
212
|
end
|
223
213
|
}
|
@@ -234,27 +224,29 @@ module Faye
|
|
234
224
|
# * ext
|
235
225
|
# * id
|
236
226
|
# * timestamp
|
237
|
-
def unsubscribe(channel, &block)
|
227
|
+
def unsubscribe(channel, subscription = nil, &block)
|
228
|
+
subscription ||= block
|
229
|
+
|
238
230
|
if Array === channel
|
239
|
-
return channel.map { |c| unsubscribe(c,
|
231
|
+
return channel.map { |c| unsubscribe(c, subscription) }
|
240
232
|
end
|
241
233
|
|
242
|
-
dead = @channels.unsubscribe(channel,
|
234
|
+
dead = @channels.unsubscribe(channel, subscription)
|
243
235
|
return unless dead
|
244
236
|
|
245
237
|
connect {
|
246
|
-
info('Client ? attempting to unsubscribe from ?', @client_id, channel)
|
238
|
+
info('Client ? attempting to unsubscribe from ?', @dispatcher.client_id, channel)
|
247
239
|
|
248
|
-
|
249
|
-
'channel'
|
250
|
-
'clientId'
|
251
|
-
'subscription'
|
240
|
+
send_message({
|
241
|
+
'channel' => Channel::UNSUBSCRIBE,
|
242
|
+
'clientId' => @dispatcher.client_id,
|
243
|
+
'subscription' => channel
|
252
244
|
|
253
|
-
}) do |response|
|
245
|
+
}, {}) do |response|
|
254
246
|
next unless response['successful']
|
255
247
|
|
256
248
|
channels = [response['subscription']].flatten
|
257
|
-
info('Unsubscription acknowledged for ? from ?', @client_id, channels)
|
249
|
+
info('Unsubscription acknowledged for ? from ?', @dispatcher.client_id, channels)
|
258
250
|
end
|
259
251
|
}
|
260
252
|
end
|
@@ -265,17 +257,19 @@ module Faye
|
|
265
257
|
# MAY include: * clientId MAY include: * id
|
266
258
|
# * id * error
|
267
259
|
# * ext * ext
|
268
|
-
def publish(channel, data)
|
260
|
+
def publish(channel, data, options = {})
|
261
|
+
::WebSocket::Driver.validate_options(options, [:attempts, :deadline])
|
262
|
+
|
269
263
|
publication = Publication.new
|
270
264
|
connect {
|
271
|
-
info('Client ? queueing published message to ?: ?', @client_id, channel, data)
|
265
|
+
info('Client ? queueing published message to ?: ?', @dispatcher.client_id, channel, data)
|
272
266
|
|
273
|
-
|
274
|
-
'channel'
|
275
|
-
'data'
|
276
|
-
'clientId'
|
267
|
+
send_message({
|
268
|
+
'channel' => channel,
|
269
|
+
'data' => data,
|
270
|
+
'clientId' => @dispatcher.client_id
|
277
271
|
|
278
|
-
}) do |response|
|
272
|
+
}, options) do |response|
|
279
273
|
if response['successful']
|
280
274
|
publication.set_deferred_status(:succeeded)
|
281
275
|
else
|
@@ -286,81 +280,20 @@ module Faye
|
|
286
280
|
publication
|
287
281
|
end
|
288
282
|
|
289
|
-
def receive_message(message)
|
290
|
-
id = message['id']
|
291
|
-
|
292
|
-
if message.has_key?('successful')
|
293
|
-
callback = @response_callbacks.delete(id)
|
294
|
-
end
|
295
|
-
|
296
|
-
pipe_through_extensions(:incoming, message, nil) do |message|
|
297
|
-
next unless message
|
298
|
-
|
299
|
-
handle_advice(message['advice']) if message['advice']
|
300
|
-
deliver_message(message)
|
301
|
-
|
302
|
-
callback.call(message) if callback
|
303
|
-
end
|
304
|
-
|
305
|
-
return if @transport_up == true
|
306
|
-
@transport_up = true
|
307
|
-
trigger('transport:up')
|
308
|
-
end
|
309
|
-
|
310
|
-
def message_error(messages, immediate = false)
|
311
|
-
messages.each do |message|
|
312
|
-
id = message['id']
|
313
|
-
|
314
|
-
if immediate
|
315
|
-
transport_send(message)
|
316
|
-
else
|
317
|
-
EventMachine.add_timer(@retry) { transport_send(message) }
|
318
|
-
end
|
319
|
-
end
|
320
|
-
|
321
|
-
return if immediate or @transport_up == false
|
322
|
-
@transport_up = false
|
323
|
-
trigger('transport:down')
|
324
|
-
end
|
325
|
-
|
326
283
|
private
|
327
284
|
|
328
|
-
def
|
329
|
-
Transport.get(self, transport_types, @disabled) do |transport|
|
330
|
-
debug('Selected ? transport for ?', transport.connection_type, transport.endpoint)
|
331
|
-
|
332
|
-
next if transport == @transport
|
333
|
-
@transport.close if @transport
|
334
|
-
|
335
|
-
@transport = transport
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
def send(message, &callback)
|
340
|
-
return unless @transport
|
285
|
+
def send_message(message, options, &callback)
|
341
286
|
message['id'] = generate_message_id
|
342
287
|
|
343
|
-
pipe_through_extensions(:outgoing, message, nil) do |message|
|
344
|
-
next unless message
|
345
|
-
@response_callbacks[message['id']] = callback if callback
|
346
|
-
transport_send(message)
|
347
|
-
end
|
348
|
-
end
|
349
|
-
|
350
|
-
def transport_send(message)
|
351
|
-
return unless @transport
|
352
|
-
|
353
288
|
timeout = [nil, 0].include?(@advice['timeout']) ?
|
354
|
-
1.2 * @retry :
|
289
|
+
1.2 * @dispatcher.retry :
|
355
290
|
1.2 * @advice['timeout'] / 1000.0
|
356
291
|
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
292
|
+
pipe_through_extensions(:outgoing, message, nil) do |message|
|
293
|
+
next unless message
|
294
|
+
@response_callbacks[message['id']] = callback if callback
|
295
|
+
@dispatcher.send_message(message, timeout, options)
|
361
296
|
end
|
362
|
-
|
363
|
-
@transport.send(envelope)
|
364
297
|
end
|
365
298
|
|
366
299
|
def generate_message_id
|
@@ -369,30 +302,45 @@ module Faye
|
|
369
302
|
@message_id.to_s(36)
|
370
303
|
end
|
371
304
|
|
305
|
+
def receive_message(message)
|
306
|
+
id = message['id']
|
307
|
+
|
308
|
+
if message.has_key?('successful')
|
309
|
+
callback = @response_callbacks.delete(id)
|
310
|
+
end
|
311
|
+
|
312
|
+
pipe_through_extensions(:incoming, message, nil) do |message|
|
313
|
+
next unless message
|
314
|
+
handle_advice(message['advice']) if message['advice']
|
315
|
+
deliver_message(message)
|
316
|
+
callback.call(message) if callback
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
372
320
|
def handle_advice(advice)
|
373
321
|
@advice.update(advice)
|
322
|
+
@dispatcher.timeout = @advice['timeout'] / 1000.0
|
374
323
|
|
375
324
|
if @advice['reconnect'] == HANDSHAKE and @state != DISCONNECTED
|
376
|
-
@state
|
377
|
-
@client_id = nil
|
325
|
+
@state = UNCONNECTED
|
326
|
+
@dispatcher.client_id = nil
|
378
327
|
cycle_connection
|
379
328
|
end
|
380
329
|
end
|
381
330
|
|
382
331
|
def deliver_message(message)
|
383
332
|
return unless message.has_key?('channel') and message.has_key?('data')
|
384
|
-
info('Client ? calling listeners for ? with ?', @client_id, message['channel'], message['data'])
|
333
|
+
info('Client ? calling listeners for ? with ?', @dispatcher.client_id, message['channel'], message['data'])
|
385
334
|
@channels.distribute_message(message)
|
386
335
|
end
|
387
336
|
|
388
337
|
def cycle_connection
|
389
338
|
if @connect_request
|
390
339
|
@connect_request = nil
|
391
|
-
info('Closed connection for ?', @client_id)
|
340
|
+
info('Closed connection for ?', @dispatcher.client_id)
|
392
341
|
end
|
393
342
|
EventMachine.add_timer(@advice['interval'] / 1000.0) { connect }
|
394
343
|
end
|
395
344
|
|
396
345
|
end
|
397
346
|
end
|
398
|
-
|