faye 1.0.3 → 1.4.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 +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
|
-
|