faye 0.8.8 → 0.8.9

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of faye might be problematic. Click here for more details.

Files changed (67) hide show
  1. data/History.txt +16 -10
  2. data/README.rdoc +1 -1
  3. data/lib/faye-browser-min.js +1 -1
  4. data/lib/faye-browser-min.js.map +2 -2
  5. data/lib/faye-browser.js +302 -287
  6. data/lib/faye.rb +21 -21
  7. data/lib/faye/adapters/rack_adapter.rb +50 -48
  8. data/lib/faye/adapters/static_server.rb +22 -22
  9. data/lib/faye/engines/connection.rb +13 -13
  10. data/lib/faye/engines/memory.rb +21 -21
  11. data/lib/faye/engines/proxy.rb +23 -23
  12. data/lib/faye/error.rb +6 -6
  13. data/lib/faye/mixins/logging.rb +12 -12
  14. data/lib/faye/mixins/publisher.rb +6 -6
  15. data/lib/faye/mixins/timeouts.rb +1 -1
  16. data/lib/faye/protocol/channel.rb +24 -24
  17. data/lib/faye/protocol/client.rb +71 -73
  18. data/lib/faye/protocol/extensible.rb +7 -7
  19. data/lib/faye/protocol/grammar.rb +13 -13
  20. data/lib/faye/protocol/server.rb +57 -57
  21. data/lib/faye/protocol/socket.rb +4 -4
  22. data/lib/faye/protocol/subscription.rb +4 -4
  23. data/lib/faye/transport/http.rb +13 -13
  24. data/lib/faye/transport/local.rb +5 -5
  25. data/lib/faye/transport/transport.rb +25 -25
  26. data/lib/faye/transport/web_socket.rb +34 -30
  27. data/lib/faye/util/namespace.rb +4 -4
  28. data/spec/browser.html +5 -5
  29. data/spec/javascript/channel_spec.js +3 -3
  30. data/spec/javascript/client_spec.js +104 -98
  31. data/spec/javascript/engine/memory_spec.js +1 -1
  32. data/spec/javascript/engine_spec.js +70 -70
  33. data/spec/javascript/faye_spec.js +6 -6
  34. data/spec/javascript/grammar_spec.js +12 -12
  35. data/spec/javascript/node_adapter_spec.js +46 -46
  36. data/spec/javascript/publisher_spec.js +4 -4
  37. data/spec/javascript/server/connect_spec.js +21 -21
  38. data/spec/javascript/server/disconnect_spec.js +15 -15
  39. data/spec/javascript/server/extensions_spec.js +6 -6
  40. data/spec/javascript/server/handshake_spec.js +18 -18
  41. data/spec/javascript/server/integration_spec.js +23 -23
  42. data/spec/javascript/server/publish_spec.js +9 -9
  43. data/spec/javascript/server/subscribe_spec.js +30 -30
  44. data/spec/javascript/server/unsubscribe_spec.js +30 -30
  45. data/spec/javascript/server_spec.js +15 -15
  46. data/spec/javascript/transport_spec.js +32 -27
  47. data/spec/node.js +2 -2
  48. data/spec/ruby/channel_spec.rb +2 -2
  49. data/spec/ruby/client_spec.rb +100 -92
  50. data/spec/ruby/engine_examples.rb +51 -51
  51. data/spec/ruby/faye_spec.rb +5 -5
  52. data/spec/ruby/grammar_spec.rb +12 -12
  53. data/spec/ruby/publisher_spec.rb +4 -4
  54. data/spec/ruby/rack_adapter_spec.rb +34 -34
  55. data/spec/ruby/server/connect_spec.rb +22 -22
  56. data/spec/ruby/server/disconnect_spec.rb +16 -16
  57. data/spec/ruby/server/extensions_spec.rb +8 -8
  58. data/spec/ruby/server/handshake_spec.rb +20 -20
  59. data/spec/ruby/server/integration_spec.rb +22 -24
  60. data/spec/ruby/server/publish_spec.rb +9 -9
  61. data/spec/ruby/server/subscribe_spec.rb +31 -31
  62. data/spec/ruby/server/unsubscribe_spec.rb +31 -31
  63. data/spec/ruby/server_spec.rb +17 -17
  64. data/spec/ruby/transport_spec.rb +23 -23
  65. data/spec/testswarm +23 -10
  66. data/spec/thin_proxy.rb +5 -5
  67. metadata +90 -59
@@ -1,28 +1,28 @@
1
1
  module Faye
2
2
  class Client
3
-
3
+
4
4
  include EventMachine::Deferrable
5
5
  include Publisher
6
6
  include Logging
7
7
  include Extensible
8
-
8
+
9
9
  UNCONNECTED = 1
10
10
  CONNECTING = 2
11
11
  CONNECTED = 3
12
12
  DISCONNECTED = 4
13
-
13
+
14
14
  HANDSHAKE = 'handshake'
15
15
  RETRY = 'retry'
16
16
  NONE = 'none'
17
-
17
+
18
18
  CONNECTION_TIMEOUT = 60.0
19
19
  DEFAULT_RETRY = 5.0
20
-
20
+
21
21
  attr_reader :client_id, :endpoint, :endpoints, :retry, :transports
22
-
22
+
23
23
  def initialize(endpoint = nil, options = {})
24
24
  info('New client created for ?', endpoint)
25
-
25
+
26
26
  @options = options
27
27
  @endpoint = endpoint || RackAdapter::DEFAULT_ENDPOINT
28
28
  @endpoints = @options[:endpoints] || {}
@@ -32,29 +32,27 @@ module Faye
32
32
  @disabled = []
33
33
  @retry = @options[:retry] || DEFAULT_RETRY
34
34
 
35
- select_transport(MANDATORY_CONNECTION_TYPES)
36
-
37
35
  @state = UNCONNECTED
38
36
  @channels = Channel::Set.new
39
37
  @message_id = 0
40
-
38
+
41
39
  @response_callbacks = {}
42
-
40
+
43
41
  @advice = {
44
42
  'reconnect' => RETRY,
45
43
  'interval' => 1000.0 * (@options[:interval] || Engine::INTERVAL),
46
44
  'timeout' => 1000.0 * (@options[:timeout] || CONNECTION_TIMEOUT)
47
45
  }
48
46
  end
49
-
47
+
50
48
  def disable(feature)
51
49
  @disabled << feature
52
50
  end
53
-
51
+
54
52
  def set_header(name, value)
55
53
  @headers[name.to_s] = value.to_s
56
54
  end
57
-
55
+
58
56
  def state
59
57
  case @state
60
58
  when UNCONNECTED then :UNCONNECTED
@@ -71,7 +69,7 @@ module Faye
71
69
  # MAY include: * minimumVersion
72
70
  # * ext
73
71
  # * id
74
- #
72
+ #
75
73
  # Success Response Failed Response
76
74
  # MUST include: * channel MUST include: * channel
77
75
  # * version * successful
@@ -86,30 +84,30 @@ module Faye
86
84
  def handshake(&block)
87
85
  return if @advice['reconnect'] == NONE
88
86
  return if @state != UNCONNECTED
89
-
87
+
90
88
  @state = CONNECTING
91
-
89
+
92
90
  info('Initiating handshake with ?', @endpoint)
93
-
91
+ select_transport(MANDATORY_CONNECTION_TYPES)
92
+
94
93
  send({
95
94
  'channel' => Channel::HANDSHAKE,
96
95
  'version' => BAYEUX_VERSION,
97
96
  'supportedConnectionTypes' => [@transport.connection_type]
98
-
97
+
99
98
  }) do |response|
100
-
99
+
101
100
  if response['successful']
102
101
  @state = CONNECTED
103
102
  @client_id = response['clientId']
104
-
105
- connection_types = response['supportedConnectionTypes'] - @disabled
106
- select_transport(connection_types)
107
-
103
+
104
+ select_transport(response['supportedConnectionTypes'])
105
+
108
106
  info('Handshake successful: ?', @client_id)
109
-
107
+
110
108
  subscribe(@channels.keys, true)
111
109
  block.call if block_given?
112
-
110
+
113
111
  else
114
112
  info('Handshake unsuccessful')
115
113
  EventMachine.add_timer(@advice['interval'] / 1000.0) { handshake(&block) }
@@ -117,7 +115,7 @@ module Faye
117
115
  end
118
116
  end
119
117
  end
120
-
118
+
121
119
  # Request Response
122
120
  # MUST include: * channel MUST include: * channel
123
121
  # * clientId * successful
@@ -130,31 +128,31 @@ module Faye
130
128
  def connect(&block)
131
129
  return if @advice['reconnect'] == NONE or
132
130
  @state == DISCONNECTED
133
-
131
+
134
132
  return handshake { connect(&block) } if @state == UNCONNECTED
135
-
133
+
136
134
  callback(&block)
137
135
  return unless @state == CONNECTED
138
-
136
+
139
137
  info('Calling deferred actions for ?', @client_id)
140
138
  set_deferred_status(:succeeded)
141
139
  set_deferred_status(:deferred)
142
-
140
+
143
141
  return unless @connect_request.nil?
144
142
  @connect_request = true
145
-
143
+
146
144
  info('Initiating connection for ?', @client_id)
147
-
145
+
148
146
  send({
149
147
  'channel' => Channel::CONNECT,
150
148
  'clientId' => @client_id,
151
149
  'connectionType' => @transport.connection_type
152
-
150
+
153
151
  }) do
154
152
  cycle_connection
155
153
  end
156
154
  end
157
-
155
+
158
156
  # Request Response
159
157
  # MUST include: * channel MUST include: * channel
160
158
  # * clientId * successful
@@ -165,21 +163,21 @@ module Faye
165
163
  def disconnect
166
164
  return unless @state == CONNECTED
167
165
  @state = DISCONNECTED
168
-
166
+
169
167
  info('Disconnecting ?', @client_id)
170
-
168
+
171
169
  send({
172
170
  'channel' => Channel::DISCONNECT,
173
171
  'clientId' => @client_id
174
-
172
+
175
173
  }) do |response|
176
174
  @transport.close if response['successful']
177
175
  end
178
-
176
+
179
177
  info('Clearing channel listeners for ?', @client_id)
180
178
  @channels = Channel::Set.new
181
179
  end
182
-
180
+
183
181
  # Request Response
184
182
  # MUST include: * channel MUST include: * channel
185
183
  # * clientId * successful
@@ -194,31 +192,31 @@ module Faye
194
192
  if Array === channel
195
193
  return channel.map { |c| subscribe(c, force, &block) }
196
194
  end
197
-
195
+
198
196
  subscription = Subscription.new(self, channel, block)
199
197
  has_subscribe = @channels.has_subscription?(channel)
200
-
198
+
201
199
  if has_subscribe and not force
202
200
  @channels.subscribe([channel], block)
203
201
  subscription.set_deferred_status(:succeeded)
204
202
  return subscription
205
203
  end
206
-
204
+
207
205
  connect {
208
206
  info('Client ? attempting to subscribe to ?', @client_id, channel)
209
207
  @channels.subscribe([channel], block) unless force
210
-
208
+
211
209
  send({
212
210
  'channel' => Channel::SUBSCRIBE,
213
211
  'clientId' => @client_id,
214
212
  'subscription' => channel
215
-
213
+
216
214
  }) do |response|
217
215
  unless response['successful']
218
216
  subscription.set_deferred_status(:failed, Error.parse(response['error']))
219
217
  next @channels.unsubscribe(channel, block)
220
218
  end
221
-
219
+
222
220
  channels = [response['subscription']].flatten
223
221
  info('Subscription acknowledged for ? to ?', @client_id, channels)
224
222
  subscription.set_deferred_status(:succeeded)
@@ -226,7 +224,7 @@ module Faye
226
224
  }
227
225
  subscription
228
226
  end
229
-
227
+
230
228
  # Request Response
231
229
  # MUST include: * channel MUST include: * channel
232
230
  # * clientId * successful
@@ -241,27 +239,27 @@ module Faye
241
239
  if Array === channel
242
240
  return channel.map { |c| unsubscribe(c, &block) }
243
241
  end
244
-
242
+
245
243
  dead = @channels.unsubscribe(channel, block)
246
244
  return unless dead
247
-
245
+
248
246
  connect {
249
247
  info('Client ? attempting to unsubscribe from ?', @client_id, channel)
250
-
248
+
251
249
  send({
252
250
  'channel' => Channel::UNSUBSCRIBE,
253
251
  'clientId' => @client_id,
254
252
  'subscription' => channel
255
-
253
+
256
254
  }) do |response|
257
255
  next unless response['successful']
258
-
256
+
259
257
  channels = [response['subscription']].flatten
260
258
  info('Unsubscription acknowledged for ? from ?', @client_id, channels)
261
259
  end
262
260
  }
263
261
  end
264
-
262
+
265
263
  # Request Response
266
264
  # MUST include: * channel MUST include: * channel
267
265
  # * data * successful
@@ -272,7 +270,7 @@ module Faye
272
270
  publication = Publication.new
273
271
  connect {
274
272
  info('Client ? queueing published message to ?: ?', @client_id, channel, data)
275
-
273
+
276
274
  send({
277
275
  'channel' => channel,
278
276
  'data' => data,
@@ -287,41 +285,41 @@ module Faye
287
285
  }
288
286
  publication
289
287
  end
290
-
288
+
291
289
  def receive_message(message)
292
290
  pipe_through_extensions(:incoming, message) do |message|
293
291
  next unless message
294
-
292
+
295
293
  handle_advice(message['advice']) if message['advice']
296
294
  deliver_message(message)
297
-
295
+
298
296
  next unless message.has_key?('successful')
299
-
297
+
300
298
  callback = @response_callbacks[message['id']]
301
299
  next unless callback
302
-
300
+
303
301
  @response_callbacks.delete(message['id'])
304
302
  callback.call(message)
305
303
  end
306
304
  end
307
-
305
+
308
306
  private
309
-
307
+
310
308
  def select_transport(transport_types)
311
- Transport.get(self, transport_types) do |transport|
309
+ Transport.get(self, transport_types, @disabled) do |transport|
312
310
  debug('Selected ? transport for ?', transport.connection_type, transport.endpoint)
313
-
311
+
314
312
  @transport = transport
315
313
  @transport.cookies = @cookies
316
314
  @transport.headers = @headers
317
-
315
+
318
316
  transport.bind :down do
319
317
  if @transport_up.nil? or @transport_up
320
318
  @transport_up = false
321
319
  trigger('transport:down')
322
320
  end
323
321
  end
324
-
322
+
325
323
  transport.bind :up do
326
324
  if @transport_up.nil? or not @transport_up
327
325
  @transport_up = true
@@ -330,7 +328,7 @@ module Faye
330
328
  end
331
329
  end
332
330
  end
333
-
331
+
334
332
  def send(message, &callback)
335
333
  message['id'] = generate_message_id
336
334
  @response_callbacks[message['id']] = callback if callback
@@ -339,40 +337,40 @@ module Faye
339
337
  @transport.send(message, @advice['timeout'] / 1000.0) if message
340
338
  end
341
339
  end
342
-
340
+
343
341
  def generate_message_id
344
342
  @message_id += 1
345
343
  @message_id = 0 if @message_id >= 2**32
346
344
  @message_id.to_s(36)
347
345
  end
348
-
346
+
349
347
  def handle_advice(advice)
350
348
  @advice.update(advice)
351
-
349
+
352
350
  if @advice['reconnect'] == HANDSHAKE and @state != DISCONNECTED
353
351
  @state = UNCONNECTED
354
352
  @client_id = nil
355
353
  cycle_connection
356
354
  end
357
355
  end
358
-
356
+
359
357
  def deliver_message(message)
360
358
  return unless message.has_key?('channel') and message.has_key?('data')
361
359
  info('Client ? calling listeners for ? with ?', @client_id, message['channel'], message['data'])
362
360
  @channels.distribute_message(message)
363
361
  end
364
-
362
+
365
363
  def teardown_connection
366
364
  return unless @connect_request
367
365
  @connect_request = nil
368
366
  info('Closed connection for ?', @client_id)
369
367
  end
370
-
368
+
371
369
  def cycle_connection
372
370
  teardown_connection
373
371
  EventMachine.add_timer(@advice['interval'] / 1000.0) { connect }
374
372
  end
375
-
373
+
376
374
  end
377
375
  end
378
376
 
@@ -1,13 +1,13 @@
1
1
  module Faye
2
2
  module Extensible
3
3
  include Logging
4
-
4
+
5
5
  def add_extension(extension)
6
6
  @extensions ||= []
7
7
  @extensions << extension
8
8
  extension.added(self) if extension.respond_to?(:added)
9
9
  end
10
-
10
+
11
11
  def remove_extension(extension)
12
12
  return unless @extensions
13
13
  @extensions.delete_if do |ext|
@@ -16,19 +16,19 @@ module Faye
16
16
  true
17
17
  end
18
18
  end
19
-
19
+
20
20
  def pipe_through_extensions(stage, message, &callback)
21
21
  debug 'Passing through ? extensions: ?', stage, message
22
22
 
23
23
  return callback.call(message) unless @extensions
24
24
  extensions = @extensions.dup
25
-
25
+
26
26
  pipe = lambda do |message|
27
27
  next callback.call(message) unless message
28
-
28
+
29
29
  extension = extensions.shift
30
30
  next callback.call(message) unless extension
31
-
31
+
32
32
  if extension.respond_to?(stage)
33
33
  extension.__send__(stage, message, pipe)
34
34
  else
@@ -37,7 +37,7 @@ module Faye
37
37
  end
38
38
  pipe.call(message)
39
39
  end
40
-
40
+
41
41
  end
42
42
  end
43
43
 
@@ -1,28 +1,28 @@
1
1
  module Faye
2
2
  module Grammar
3
-
3
+
4
4
  def self.rule(&block)
5
5
  source = instance_eval(&block)
6
6
  %r{^#{string(source)}$}
7
7
  end
8
-
8
+
9
9
  def self.choice(*list)
10
10
  '(' + list.map(&method(:string)) * '|' + ')'
11
11
  end
12
-
12
+
13
13
  def self.repeat(*pattern)
14
14
  '(' + string(pattern) + ')*'
15
15
  end
16
-
16
+
17
17
  def self.oneormore(*pattern)
18
18
  '(' + string(pattern) + ')+'
19
19
  end
20
-
20
+
21
21
  def self.string(item)
22
22
  return item.map(&method(:string)) * '' if Array === item
23
23
  String === item ? item : item.source.gsub(/^\^/, '').gsub(/\$$/, '')
24
24
  end
25
-
25
+
26
26
  LOWALPHA = rule {[ '[a-z]' ]}
27
27
  UPALPHA = rule {[ '[A-Z]' ]}
28
28
  ALPHA = rule {[ choice(LOWALPHA, UPALPHA) ]}
@@ -32,27 +32,27 @@ module Faye
32
32
  STRING = rule {[ repeat(choice(ALPHANUM, MARK, ' ', '\\/', '\\*', '\\.')) ]}
33
33
  TOKEN = rule {[ oneormore(choice(ALPHANUM, MARK)) ]}
34
34
  INTEGER = rule {[ oneormore(DIGIT) ]}
35
-
35
+
36
36
  CHANNEL_SEGMENT = rule {[ TOKEN ]}
37
37
  CHANNEL_SEGMENTS = rule {[ CHANNEL_SEGMENT, repeat('\\/', CHANNEL_SEGMENT) ]}
38
38
  CHANNEL_NAME = rule {[ '\\/', CHANNEL_SEGMENTS ]}
39
-
39
+
40
40
  WILD_CARD = rule {[ '\\*{1,2}' ]}
41
41
  CHANNEL_PATTERN = rule {[ repeat('\\/', CHANNEL_SEGMENT), '\\/', WILD_CARD ]}
42
-
42
+
43
43
  VERSION_ELEMENT = rule {[ ALPHANUM, repeat(choice(ALPHANUM, '\\-', '\\_')) ]}
44
44
  VERSION = rule {[ INTEGER, repeat('\\.', VERSION_ELEMENT) ]}
45
-
45
+
46
46
  CLIENT_ID = rule {[ oneormore(ALPHANUM) ]}
47
-
47
+
48
48
  ID = rule {[ oneormore(ALPHANUM) ]}
49
-
49
+
50
50
  ERROR_MESSAGE = rule {[ STRING ]}
51
51
  ERROR_ARGS = rule {[ STRING, repeat(',', STRING) ]}
52
52
  ERROR_CODE = rule {[ DIGIT, DIGIT, DIGIT ]}
53
53
  ERROR = rule {[ choice(string([ERROR_CODE, ':', ERROR_ARGS, ':', ERROR_MESSAGE]),
54
54
  string([ERROR_CODE, ':', ':', ERROR_MESSAGE])) ]}
55
-
55
+
56
56
  end
57
57
  end
58
58