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,13 +1,13 @@
1
1
  module Faye
2
2
  module Engine
3
-
3
+
4
4
  class Memory
5
5
  include Timeouts
6
-
6
+
7
7
  def self.create(server, options)
8
8
  new(server, options)
9
9
  end
10
-
10
+
11
11
  def initialize(server, options)
12
12
  @server = server
13
13
  @options = options
@@ -16,7 +16,7 @@ module Faye
16
16
  @channels = {}
17
17
  @messages = {}
18
18
  end
19
-
19
+
20
20
  def create_client(&callback)
21
21
  client_id = @namespace.generate
22
22
  @server.debug 'Created new client ?', client_id
@@ -24,14 +24,14 @@ module Faye
24
24
  @server.trigger(:handshake, client_id)
25
25
  callback.call(client_id)
26
26
  end
27
-
27
+
28
28
  def destroy_client(client_id, &callback)
29
29
  return unless @namespace.exists?(client_id)
30
-
30
+
31
31
  if @clients.has_key?(client_id)
32
32
  @clients[client_id].each { |channel| unsubscribe(client_id, channel) }
33
33
  end
34
-
34
+
35
35
  remove_timeout(client_id)
36
36
  @namespace.release(client_id)
37
37
  @messages.delete(client_id)
@@ -39,11 +39,11 @@ module Faye
39
39
  @server.trigger(:disconnect, client_id)
40
40
  callback.call if callback
41
41
  end
42
-
42
+
43
43
  def client_exists(client_id, &callback)
44
44
  callback.call(@namespace.exists?(client_id))
45
45
  end
46
-
46
+
47
47
  def ping(client_id)
48
48
  timeout = @server.timeout
49
49
  return unless Numeric === timeout
@@ -51,45 +51,45 @@ module Faye
51
51
  remove_timeout(client_id)
52
52
  add_timeout(client_id, 2 * timeout) { destroy_client(client_id) }
53
53
  end
54
-
54
+
55
55
  def subscribe(client_id, channel, &callback)
56
56
  @clients[client_id] ||= Set.new
57
57
  should_trigger = @clients[client_id].add?(channel)
58
-
58
+
59
59
  @channels[channel] ||= Set.new
60
60
  @channels[channel].add(client_id)
61
-
61
+
62
62
  @server.debug 'Subscribed client ? to channel ?', client_id, channel
63
63
  @server.trigger(:subscribe, client_id, channel) if should_trigger
64
64
  callback.call(true) if callback
65
65
  end
66
-
66
+
67
67
  def unsubscribe(client_id, channel, &callback)
68
68
  if @clients.has_key?(client_id)
69
69
  should_trigger = @clients[client_id].delete?(channel)
70
70
  @clients.delete(client_id) if @clients[client_id].empty?
71
71
  end
72
-
72
+
73
73
  if @channels.has_key?(channel)
74
74
  @channels[channel].delete(client_id)
75
75
  @channels.delete(channel) if @channels[channel].empty?
76
76
  end
77
-
77
+
78
78
  @server.debug 'Unsubscribed client ? from channel ?', client_id, channel
79
79
  @server.trigger(:unsubscribe, client_id, channel) if should_trigger
80
80
  callback.call(true) if callback
81
81
  end
82
-
82
+
83
83
  def publish(message, channels)
84
84
  @server.debug 'Publishing message ?', message
85
-
85
+
86
86
  clients = Set.new
87
-
87
+
88
88
  channels.each do |channel|
89
89
  next unless subs = @channels[channel]
90
90
  subs.each(&clients.method(:add))
91
91
  end
92
-
92
+
93
93
  clients.each do |client_id|
94
94
  @server.debug 'Queueing for client ?: ?', client_id, message
95
95
  @messages[client_id] ||= []
@@ -99,14 +99,14 @@ module Faye
99
99
 
100
100
  @server.trigger(:publish, message['clientId'], message['channel'], message['data'])
101
101
  end
102
-
102
+
103
103
  def empty_queue(client_id)
104
104
  return unless @server.has_connection?(client_id)
105
105
  @server.deliver(client_id, @messages[client_id])
106
106
  @messages.delete(client_id)
107
107
  end
108
108
  end
109
-
109
+
110
110
  end
111
111
  end
112
112
 
@@ -1,24 +1,24 @@
1
1
  module Faye
2
2
  module Engine
3
-
3
+
4
4
  METHODS = %w[create_client client_exists destroy_client ping subscribe unsubscribe]
5
5
  MAX_DELAY = 0.0
6
6
  INTERVAL = 0.0
7
7
  TIMEOUT = 60.0
8
8
  ID_LENGTH = 160
9
-
9
+
10
10
  autoload :Connection, File.expand_path('../connection', __FILE__)
11
11
  autoload :Memory, File.expand_path('../memory', __FILE__)
12
-
12
+
13
13
  def self.ensure_reactor_running!
14
14
  Thread.new { EventMachine.run } unless EventMachine.reactor_running?
15
15
  Thread.pass until EventMachine.reactor_running?
16
16
  end
17
-
17
+
18
18
  def self.get(options)
19
19
  Proxy.new(options)
20
20
  end
21
-
21
+
22
22
  def self.random(bitlength = ID_LENGTH)
23
23
  limit = 2 ** bitlength - 1
24
24
  max_size = limit.to_s(36).size
@@ -26,32 +26,32 @@ module Faye
26
26
  string = '0' + string while string.size < max_size
27
27
  string
28
28
  end
29
-
29
+
30
30
  class Proxy
31
31
  include Publisher
32
32
  include Logging
33
-
33
+
34
34
  attr_reader :interval, :timeout
35
-
35
+
36
36
  extend Forwardable
37
37
  def_delegators :@engine, *METHODS
38
-
38
+
39
39
  def initialize(options)
40
40
  @options = options
41
41
  @connections = {}
42
42
  @interval = @options[:interval] || INTERVAL
43
43
  @timeout = @options[:timeout] || TIMEOUT
44
-
44
+
45
45
  engine_class = @options[:type] || Memory
46
46
  @engine = engine_class.create(self, @options)
47
-
47
+
48
48
  bind :disconnect do |client_id|
49
49
  EventMachine.next_tick { close_connection(client_id) }
50
50
  end
51
-
51
+
52
52
  debug 'Created new engine: ?', @options
53
53
  end
54
-
54
+
55
55
  def connect(client_id, options = {}, &callback)
56
56
  debug 'Accepting connection from ?', client_id
57
57
  @engine.ping(client_id)
@@ -59,11 +59,11 @@ module Faye
59
59
  conn.connect(options, &callback)
60
60
  @engine.empty_queue(client_id)
61
61
  end
62
-
62
+
63
63
  def has_connection?(client_id)
64
64
  @connections.has_key?(client_id)
65
65
  end
66
-
66
+
67
67
  def connection(client_id, create)
68
68
  conn = @connections[client_id]
69
69
  return conn if conn or not create
@@ -71,7 +71,7 @@ module Faye
71
71
  trigger('connection:open', client_id)
72
72
  @connections[client_id]
73
73
  end
74
-
74
+
75
75
  def close_connection(client_id)
76
76
  debug 'Closing connection for ?', client_id
77
77
  conn = @connections[client_id]
@@ -80,13 +80,13 @@ module Faye
80
80
  trigger('connection:close', client_id)
81
81
  @connections.delete(client_id)
82
82
  end
83
-
83
+
84
84
  def open_socket(client_id, socket)
85
85
  return unless client_id
86
86
  conn = connection(client_id, true)
87
87
  conn.socket = socket
88
88
  end
89
-
89
+
90
90
  def deliver(client_id, messages)
91
91
  return if !messages || messages.empty?
92
92
  conn = connection(client_id, false)
@@ -94,28 +94,28 @@ module Faye
94
94
  messages.each(&conn.method(:deliver))
95
95
  true
96
96
  end
97
-
97
+
98
98
  def generate_id
99
99
  Engine.random
100
100
  end
101
-
101
+
102
102
  def flush(client_id)
103
103
  return unless client_id
104
104
  debug 'Flushing connection for ?', client_id
105
105
  conn = connection(client_id, false)
106
106
  conn.flush!(true) if conn
107
107
  end
108
-
108
+
109
109
  def disconnect
110
110
  @engine.disconnect if @engine.respond_to?(:disconnect)
111
111
  end
112
-
112
+
113
113
  def publish(message)
114
114
  channels = Channel.expand(message['channel'])
115
115
  @engine.publish(message, channels)
116
116
  end
117
117
  end
118
-
118
+
119
119
  end
120
120
  end
121
121
 
@@ -1,11 +1,11 @@
1
1
  module Faye
2
2
  class Error
3
-
3
+
4
4
  def self.method_missing(type, *args)
5
5
  code = const_get(type.to_s.upcase)
6
6
  new(code[0], args, code[1]).to_s
7
7
  end
8
-
8
+
9
9
  def self.parse(message)
10
10
  message ||= ''
11
11
  return new(nil, [], message) unless Grammar::ERROR =~ message
@@ -19,17 +19,17 @@ module Faye
19
19
  end
20
20
 
21
21
  attr_reader :code, :params, :message
22
-
22
+
23
23
  def initialize(code, params, message)
24
24
  @code = code
25
25
  @params = params
26
26
  @message = message
27
27
  end
28
-
28
+
29
29
  def to_s
30
30
  "#{ @code }:#{ @params * ',' }:#{ @message }"
31
31
  end
32
-
32
+
33
33
  # http://code.google.com/p/cometd/wiki/BayeuxCodes
34
34
  VERSION_MISMATCH = [300, 'Version mismatch']
35
35
  CONNTYPE_MISMATCH = [301, 'Connection types not supported']
@@ -43,7 +43,7 @@ module Faye
43
43
  EXT_UNKNOWN = [406, 'Unknown extension']
44
44
  PUBLISH_FAILED = [407, 'Failed to publish']
45
45
  SERVER_ERROR = [500, 'Internal server error']
46
-
46
+
47
47
  end
48
48
  end
49
49
 
@@ -1,47 +1,47 @@
1
1
  module Faye
2
2
  module Logging
3
-
3
+
4
4
  DEFAULT_LOG_LEVEL = :error
5
-
5
+
6
6
  LOG_LEVELS = {
7
7
  :error => 3,
8
8
  :warn => 2,
9
9
  :info => 1,
10
10
  :debug => 0
11
11
  }
12
-
12
+
13
13
  class << self
14
14
  attr_writer :log_level
15
-
15
+
16
16
  def log_level
17
17
  @log_level || DEFAULT_LOG_LEVEL
18
18
  end
19
19
  end
20
-
20
+
21
21
  attr_writer :log_level
22
-
22
+
23
23
  def log_level
24
24
  @log_level || Logging.log_level
25
25
  end
26
-
26
+
27
27
  def log(message_args, level)
28
28
  return unless Faye.logger
29
29
  return if LOG_LEVELS[log_level] > LOG_LEVELS[level]
30
-
30
+
31
31
  message = message_args.shift.gsub(/\?/) do
32
32
  Faye.to_json(message_args.shift)
33
33
  end
34
-
34
+
35
35
  timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S')
36
36
  banner = " [#{ level.to_s.upcase }] [#{ self.class.name }] "
37
-
37
+
38
38
  Faye.logger.call(timestamp + banner + message)
39
39
  end
40
-
40
+
41
41
  LOG_LEVELS.each do |level, value|
42
42
  define_method(level) { |*args| log(args, level) }
43
43
  end
44
-
44
+
45
45
  end
46
46
  end
47
47
 
@@ -1,30 +1,30 @@
1
1
  module Faye
2
2
  module Publisher
3
-
3
+
4
4
  def count_listeners(event_type)
5
5
  return 0 unless @subscribers and @subscribers[event_type]
6
6
  @subscribers[event_type].size
7
7
  end
8
-
8
+
9
9
  def bind(event_type, &listener)
10
10
  @subscribers ||= {}
11
11
  list = @subscribers[event_type] ||= []
12
12
  list << listener
13
13
  end
14
-
14
+
15
15
  def unbind(event_type, &listener)
16
16
  return unless @subscribers and @subscribers[event_type]
17
17
  return @subscribers.delete(event_type) unless listener
18
-
18
+
19
19
  @subscribers[event_type].delete_if(&listener.method(:==))
20
20
  end
21
-
21
+
22
22
  def trigger(event_type, *args)
23
23
  return unless @subscribers and @subscribers[event_type]
24
24
  listeners = @subscribers[event_type].dup
25
25
  listeners.each { |listener| listener.call(*args) }
26
26
  end
27
-
27
+
28
28
  end
29
29
  end
30
30
 
@@ -9,7 +9,7 @@ module Faye
9
9
  block.call
10
10
  end
11
11
  end
12
-
12
+
13
13
  def remove_timeout(name)
14
14
  @timeouts ||= {}
15
15
  timeout = @timeouts[name]
@@ -1,95 +1,95 @@
1
1
  module Faye
2
2
  class Channel
3
-
3
+
4
4
  include Publisher
5
5
  attr_reader :name
6
-
6
+
7
7
  def initialize(name)
8
8
  @name = name
9
9
  end
10
-
10
+
11
11
  def <<(message)
12
12
  trigger(:message, message)
13
13
  end
14
-
14
+
15
15
  def unused?
16
16
  count_listeners(:message).zero?
17
17
  end
18
-
18
+
19
19
  HANDSHAKE = '/meta/handshake'
20
20
  CONNECT = '/meta/connect'
21
21
  SUBSCRIBE = '/meta/subscribe'
22
22
  UNSUBSCRIBE = '/meta/unsubscribe'
23
23
  DISCONNECT = '/meta/disconnect'
24
-
24
+
25
25
  META = 'meta'
26
26
  SERVICE = 'service'
27
-
27
+
28
28
  class << self
29
29
  def expand(name)
30
30
  segments = parse(name)
31
31
  channels = ['/**', name]
32
-
32
+
33
33
  copy = segments.dup
34
34
  copy[copy.size - 1] = '*'
35
35
  channels << unparse(copy)
36
-
36
+
37
37
  1.upto(segments.size - 1) do |i|
38
38
  copy = segments[0...i]
39
39
  copy << '**'
40
40
  channels << unparse(copy)
41
41
  end
42
-
42
+
43
43
  channels
44
44
  end
45
-
45
+
46
46
  def valid?(name)
47
47
  Grammar::CHANNEL_NAME =~ name or
48
48
  Grammar::CHANNEL_PATTERN =~ name
49
49
  end
50
-
50
+
51
51
  def parse(name)
52
52
  return nil unless valid?(name)
53
53
  name.split('/')[1..-1]
54
54
  end
55
-
55
+
56
56
  def unparse(segments)
57
57
  '/' + segments.join('/')
58
58
  end
59
-
59
+
60
60
  def meta?(name)
61
61
  segments = parse(name)
62
62
  segments ? (segments.first == META) : nil
63
63
  end
64
-
64
+
65
65
  def service?(name)
66
66
  segments = parse(name)
67
67
  segments ? (segments.first == SERVICE) : nil
68
68
  end
69
-
69
+
70
70
  def subscribable?(name)
71
71
  return nil unless valid?(name)
72
72
  not meta?(name) and not service?(name)
73
73
  end
74
74
  end
75
-
75
+
76
76
  class Set
77
77
  def initialize(parent = nil, value = nil)
78
78
  @channels = {}
79
79
  end
80
-
80
+
81
81
  def keys
82
82
  @channels.keys
83
83
  end
84
-
84
+
85
85
  def remove(name)
86
86
  @channels.delete(name)
87
87
  end
88
-
88
+
89
89
  def has_subscription?(name)
90
90
  @channels.has_key?(name)
91
91
  end
92
-
92
+
93
93
  def subscribe(names, callback)
94
94
  return unless callback
95
95
  names.each do |name|
@@ -97,7 +97,7 @@ module Faye
97
97
  channel.bind(:message, &callback)
98
98
  end
99
99
  end
100
-
100
+
101
101
  def unsubscribe(name, callback)
102
102
  channel = @channels[name]
103
103
  return false unless channel
@@ -109,7 +109,7 @@ module Faye
109
109
  false
110
110
  end
111
111
  end
112
-
112
+
113
113
  def distribute_message(message)
114
114
  channels = Channel.expand(message['channel'])
115
115
  channels.each do |name|
@@ -118,7 +118,7 @@ module Faye
118
118
  end
119
119
  end
120
120
  end
121
-
121
+
122
122
  end
123
123
  end
124
124