faye 1.0.3 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/faye/error.rb CHANGED
@@ -46,4 +46,3 @@ module Faye
46
46
 
47
47
  end
48
48
  end
49
-
@@ -12,4 +12,3 @@ module Faye
12
12
 
13
13
  end
14
14
  end
15
-
@@ -33,4 +33,3 @@ module Faye
33
33
 
34
34
  end
35
35
  end
36
-
@@ -16,4 +16,3 @@ module Faye
16
16
 
17
17
  end
18
18
  end
19
-
@@ -24,4 +24,3 @@ module Faye
24
24
  end
25
25
  end
26
26
  end
27
-
@@ -75,7 +75,7 @@ module Faye
75
75
  end
76
76
 
77
77
  class Set
78
- def initialize(parent = nil, value = nil)
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, callback)
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, &callback)
97
+ channel.bind(:message, &subscription)
99
98
  end
100
99
  end
101
100
 
102
- def unsubscribe(name, callback)
101
+ def unsubscribe(name, subscription)
103
102
  channel = @channels[name]
104
103
  return false unless channel
105
- channel.unbind(:message, &callback)
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['data']) if channel
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
-
@@ -6,59 +6,41 @@ module Faye
6
6
  include Logging
7
7
  include Extensible
8
8
 
9
- UNCONNECTED = 1
10
- CONNECTING = 2
11
- CONNECTED = 3
12
- DISCONNECTED = 4
9
+ UNCONNECTED = 1
10
+ CONNECTING = 2
11
+ CONNECTED = 3
12
+ DISCONNECTED = 4
13
13
 
14
- HANDSHAKE = 'handshake'
15
- RETRY = 'retry'
16
- NONE = 'none'
14
+ HANDSHAKE = 'handshake'
15
+ RETRY = 'retry'
16
+ NONE = 'none'
17
17
 
18
- CONNECTION_TIMEOUT = 60.0
19
- DEFAULT_RETRY = 5.0
20
- MAX_REQUEST_SIZE = 2048
18
+ CONNECTION_TIMEOUT = 60.0
21
19
 
22
- attr_reader :cookies, :endpoint, :endpoints, :headers, :max_request_size, :retry, :transports
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 * (@options[:interval] || Engine::INTERVAL),
52
- 'timeout' => 1000.0 * (@options[:timeout] || CONNECTION_TIMEOUT)
38
+ 'interval' => 1000.0 * (options[:interval] || Engine::INTERVAL),
39
+ 'timeout' => 1000.0 * (options[:timeout] || CONNECTION_TIMEOUT)
53
40
  }
54
- end
41
+ @dispatcher.timeout = @advice['timeout'] / 1000.0
55
42
 
56
- def disable(feature)
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
- send({
93
- 'channel' => Channel::HANDSHAKE,
94
- 'version' => BAYEUX_VERSION,
95
- 'supportedConnectionTypes' => [@transport.connection_type]
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 = CONNECTED
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(@advice['interval'] / 1000.0) { handshake(&block) }
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
- send({
146
- 'channel' => Channel::CONNECT,
147
- 'clientId' => @client_id,
148
- 'connectionType' => @transport.connection_type
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
- send({
169
- 'channel' => Channel::DISCONNECT,
170
- 'clientId' => @client_id
151
+ send_message({
152
+ 'channel' => Channel::DISCONNECT,
153
+ 'clientId' => @dispatcher.client_id
171
154
 
172
- }) do |response|
173
- @transport.close if response['successful']
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], block)
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], block) unless force
195
+ info('Client ? attempting to subscribe to ?', @dispatcher.client_id, channel)
196
+ @channels.subscribe([channel], subscription) unless force
207
197
 
208
- send({
209
- 'channel' => Channel::SUBSCRIBE,
210
- 'clientId' => @client_id,
211
- 'subscription' => channel
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, block)
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, &block) }
231
+ return channel.map { |c| unsubscribe(c, subscription) }
240
232
  end
241
233
 
242
- dead = @channels.unsubscribe(channel, block)
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
- send({
249
- 'channel' => Channel::UNSUBSCRIBE,
250
- 'clientId' => @client_id,
251
- 'subscription' => channel
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
- send({
274
- 'channel' => channel,
275
- 'data' => data,
276
- 'clientId' => @client_id
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 select_transport(transport_types)
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
- envelope = Envelope.new(message, timeout)
358
-
359
- envelope.errback do |immediate|
360
- message_error([message], immediate)
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 = UNCONNECTED
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
-