faye 1.0.4 → 1.1.0
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +12 -4
- data/README.md +10 -9
- data/lib/faye-browser-min.js +2 -1
- data/lib/faye-browser-min.js.map +1 -1
- data/lib/faye-browser.js +566 -343
- data/lib/faye.rb +10 -10
- data/lib/faye/adapters/rack_adapter.rb +29 -10
- 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 +2 -4
- data/lib/faye/protocol/client.rb +101 -154
- 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 +11 -22
- data/lib/faye/protocol/socket.rb +0 -1
- data/lib/faye/protocol/subscription.rb +0 -1
- data/lib/faye/transport/http.rb +41 -28
- data/lib/faye/transport/local.rb +4 -5
- data/lib/faye/transport/transport.rb +57 -36
- data/lib/faye/transport/web_socket.rb +38 -26
- data/lib/faye/util/namespace.rb +0 -1
- metadata +26 -10
- data/lib/faye/protocol/envelope.rb +0 -24
data/lib/faye.rb
CHANGED
@@ -14,30 +14,31 @@ require 'time'
|
|
14
14
|
require 'uri'
|
15
15
|
|
16
16
|
module Faye
|
17
|
-
VERSION = '1.0
|
17
|
+
VERSION = '1.1.0'
|
18
18
|
|
19
19
|
ROOT = File.expand_path(File.dirname(__FILE__))
|
20
20
|
|
21
|
-
autoload :Publisher, File.join(ROOT, 'faye', 'mixins', 'publisher')
|
22
21
|
autoload :Deferrable, File.join(ROOT, 'faye', 'mixins', 'deferrable')
|
23
|
-
autoload :Timeouts, File.join(ROOT, 'faye', 'mixins', 'timeouts')
|
24
22
|
autoload :Logging, File.join(ROOT, 'faye', 'mixins', 'logging')
|
23
|
+
autoload :Publisher, File.join(ROOT, 'faye', 'mixins', 'publisher')
|
24
|
+
autoload :Timeouts, File.join(ROOT, 'faye', 'mixins', 'timeouts')
|
25
25
|
|
26
26
|
autoload :Namespace, File.join(ROOT, 'faye', 'util', 'namespace')
|
27
27
|
|
28
28
|
autoload :Engine, File.join(ROOT, 'faye', 'engines', 'proxy')
|
29
29
|
|
30
|
-
autoload :Grammar, File.join(ROOT, 'faye', 'protocol', 'grammar')
|
31
|
-
autoload :Extensible, File.join(ROOT, 'faye', 'protocol', 'extensible')
|
32
30
|
autoload :Channel, File.join(ROOT, 'faye', 'protocol', 'channel')
|
33
|
-
autoload :Envelope, File.join(ROOT, 'faye', 'protocol', 'envelope')
|
34
|
-
autoload :Subscription, File.join(ROOT, 'faye', 'protocol', 'subscription')
|
35
|
-
autoload :Publication, File.join(ROOT, 'faye', 'protocol', 'publication')
|
36
31
|
autoload :Client, File.join(ROOT, 'faye', 'protocol', 'client')
|
32
|
+
autoload :Dispatcher, File.join(ROOT, 'faye', 'protocol', 'dispatcher')
|
33
|
+
autoload :Scheduler, File.join(ROOT, 'faye', 'protocol', 'scheduler')
|
34
|
+
autoload :Extensible, File.join(ROOT, 'faye', 'protocol', 'extensible')
|
35
|
+
autoload :Grammar, File.join(ROOT, 'faye', 'protocol', 'grammar')
|
36
|
+
autoload :Publication, File.join(ROOT, 'faye', 'protocol', 'publication')
|
37
37
|
autoload :Server, File.join(ROOT, 'faye', 'protocol', 'server')
|
38
|
+
autoload :Subscription, File.join(ROOT, 'faye', 'protocol', 'subscription')
|
38
39
|
|
39
|
-
autoload :Transport, File.join(ROOT, 'faye', 'transport', 'transport')
|
40
40
|
autoload :Error, File.join(ROOT, 'faye', 'error')
|
41
|
+
autoload :Transport, File.join(ROOT, 'faye', 'transport', 'transport')
|
41
42
|
|
42
43
|
autoload :RackAdapter, File.join(ROOT, 'faye', 'adapters', 'rack_adapter')
|
43
44
|
autoload :StaticServer, File.join(ROOT, 'faye', 'adapters', 'static_server')
|
@@ -125,4 +126,3 @@ module Faye
|
|
125
126
|
resume.call
|
126
127
|
end
|
127
128
|
end
|
128
|
-
|
@@ -22,11 +22,14 @@ module Faye
|
|
22
22
|
# down. Better suggestions welcome.
|
23
23
|
HTTP_X_NO_CONTENT_LENGTH = 'HTTP_X_NO_CONTENT_LENGTH'
|
24
24
|
|
25
|
-
def initialize(app = nil, options = nil)
|
25
|
+
def initialize(app = nil, options = nil, &block)
|
26
26
|
@app = app if app.respond_to?(:call)
|
27
27
|
@options = [app, options].grep(Hash).first || {}
|
28
28
|
|
29
|
+
::WebSocket::Driver.validate_options(@options, [:engine, :mount, :ping, :timeout, :extensions, :websocket_extensions])
|
30
|
+
|
29
31
|
@endpoint = @options[:mount] || DEFAULT_ENDPOINT
|
32
|
+
@extensions = []
|
30
33
|
@endpoint_re = Regexp.new('^' + @endpoint.gsub(/\/$/, '') + '(/[^/]*)*(\\.[^\\.]+)?$')
|
31
34
|
@server = Server.new(@options)
|
32
35
|
|
@@ -34,8 +37,15 @@ module Faye
|
|
34
37
|
@static.map(File.basename(@endpoint) + '.js', SCRIPT_PATH)
|
35
38
|
@static.map('client.js', SCRIPT_PATH)
|
36
39
|
|
37
|
-
|
38
|
-
|
40
|
+
if extensions = @options[:extensions]
|
41
|
+
[*extensions].each { |extension| add_extension(extension) }
|
42
|
+
end
|
43
|
+
|
44
|
+
if websocket_extensions = @options[:websocket_extensions]
|
45
|
+
[*websocket_extensions].each { |ext| add_websocket_extension(ext) }
|
46
|
+
end
|
47
|
+
|
48
|
+
block.call(self) if block
|
39
49
|
end
|
40
50
|
|
41
51
|
def listen(*args)
|
@@ -50,6 +60,10 @@ module Faye
|
|
50
60
|
@server.remove_extension(extension)
|
51
61
|
end
|
52
62
|
|
63
|
+
def add_websocket_extension(extension)
|
64
|
+
@extensions << extension
|
65
|
+
end
|
66
|
+
|
53
67
|
def close
|
54
68
|
@server.close
|
55
69
|
end
|
@@ -89,7 +103,12 @@ module Faye
|
|
89
103
|
return [400, TYPE_TEXT, ['Bad request']]
|
90
104
|
end
|
91
105
|
|
92
|
-
|
106
|
+
unless json_msg.force_encoding('UTF-8').valid_encoding?
|
107
|
+
error 'Received request with invalid encoding: ?', format_request(request)
|
108
|
+
return [400, TYPE_TEXT, ['Bad request']]
|
109
|
+
end
|
110
|
+
|
111
|
+
debug("Received message via HTTP #{request.request_method}: ?", json_msg)
|
93
112
|
|
94
113
|
message = MultiJson.load(json_msg)
|
95
114
|
jsonp = request.params['jsonp'] || JSONP_CALLBACK
|
@@ -120,7 +139,7 @@ module Faye
|
|
120
139
|
|
121
140
|
headers['Content-Length'] = response.bytesize.to_s unless request.env[HTTP_X_NO_CONTENT_LENGTH]
|
122
141
|
headers['Connection'] = 'close'
|
123
|
-
debug
|
142
|
+
debug('HTTP response: ?', response)
|
124
143
|
send_response([200, headers, [response]], hijack, callback)
|
125
144
|
end
|
126
145
|
end
|
@@ -169,17 +188,18 @@ module Faye
|
|
169
188
|
end
|
170
189
|
|
171
190
|
def handle_websocket(request)
|
172
|
-
|
191
|
+
options = {:extensions => @extensions, :ping => @options[:ping]}
|
192
|
+
ws = Faye::WebSocket.new(request.env, [], options)
|
173
193
|
client_id = nil
|
174
194
|
|
175
195
|
ws.onmessage = lambda do |event|
|
176
196
|
begin
|
177
|
-
debug
|
197
|
+
debug("Received message via WebSocket[#{ws.version}]: ?", event.data)
|
178
198
|
|
179
199
|
message = MultiJson.load(event.data)
|
180
200
|
cid = Faye.client_id_from_messages(message)
|
181
201
|
|
182
|
-
@server.close_socket(client_id) if client_id and cid and cid != client_id
|
202
|
+
@server.close_socket(client_id, false) if client_id and cid and cid != client_id
|
183
203
|
@server.open_socket(cid, ws, request)
|
184
204
|
client_id = cid
|
185
205
|
|
@@ -203,7 +223,7 @@ module Faye
|
|
203
223
|
es = Faye::EventSource.new(request.env, :ping => @options[:ping])
|
204
224
|
client_id = es.url.split('/').pop
|
205
225
|
|
206
|
-
debug
|
226
|
+
debug('Opened EventSource connection for ?', client_id)
|
207
227
|
@server.open_socket(client_id, es, request)
|
208
228
|
|
209
229
|
es.onclose = lambda do |event|
|
@@ -238,4 +258,3 @@ module Faye
|
|
238
258
|
|
239
259
|
end
|
240
260
|
end
|
241
|
-
|
@@ -15,7 +15,8 @@ module Faye
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def deliver(message)
|
18
|
-
|
18
|
+
message.delete('clientId')
|
19
|
+
return @socket.send(message) if @socket
|
19
20
|
return unless @inbox.add?(message)
|
20
21
|
begin_delivery_timeout
|
21
22
|
end
|
@@ -31,28 +32,27 @@ module Faye
|
|
31
32
|
begin_connection_timeout(timeout)
|
32
33
|
end
|
33
34
|
|
34
|
-
def flush
|
35
|
-
@engine.close_connection(@id) if force or socket.nil?
|
36
|
-
|
35
|
+
def flush
|
37
36
|
remove_timeout(:connection)
|
38
37
|
remove_timeout(:delivery)
|
39
38
|
|
40
39
|
set_deferred_status(:succeeded, @inbox.entries)
|
41
40
|
@inbox = []
|
41
|
+
|
42
|
+
@engine.close_connection(@id) unless @socket
|
42
43
|
end
|
43
44
|
|
44
45
|
private
|
45
46
|
|
46
47
|
def begin_delivery_timeout
|
47
48
|
return if @inbox.empty?
|
48
|
-
add_timeout(:delivery, MAX_DELAY) { flush
|
49
|
+
add_timeout(:delivery, MAX_DELAY) { flush }
|
49
50
|
end
|
50
51
|
|
51
52
|
def begin_connection_timeout(timeout)
|
52
|
-
add_timeout(:connection, timeout) { flush
|
53
|
+
add_timeout(:connection, timeout) { flush }
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
56
57
|
end
|
57
58
|
end
|
58
|
-
|
data/lib/faye/engines/memory.rb
CHANGED
@@ -28,7 +28,7 @@ module Faye
|
|
28
28
|
|
29
29
|
def create_client(&callback)
|
30
30
|
client_id = @namespace.generate
|
31
|
-
@server.debug
|
31
|
+
@server.debug('Created new client ?', client_id)
|
32
32
|
ping(client_id)
|
33
33
|
@server.trigger(:handshake, client_id)
|
34
34
|
callback.call(client_id)
|
@@ -44,7 +44,7 @@ module Faye
|
|
44
44
|
remove_timeout(client_id)
|
45
45
|
@namespace.release(client_id)
|
46
46
|
@messages.delete(client_id)
|
47
|
-
@server.debug
|
47
|
+
@server.debug('Destroyed client ?', client_id)
|
48
48
|
@server.trigger(:disconnect, client_id)
|
49
49
|
@server.trigger(:close, client_id)
|
50
50
|
callback.call if callback
|
@@ -57,7 +57,7 @@ module Faye
|
|
57
57
|
def ping(client_id)
|
58
58
|
timeout = @server.timeout
|
59
59
|
return unless Numeric === timeout
|
60
|
-
@server.debug
|
60
|
+
@server.debug('Ping ?, ?', client_id, timeout)
|
61
61
|
remove_timeout(client_id)
|
62
62
|
add_timeout(client_id, 2 * timeout) { destroy_client(client_id) }
|
63
63
|
end
|
@@ -69,7 +69,7 @@ module Faye
|
|
69
69
|
@channels[channel] ||= Set.new
|
70
70
|
@channels[channel].add(client_id)
|
71
71
|
|
72
|
-
@server.debug
|
72
|
+
@server.debug('Subscribed client ? to channel ?', client_id, channel)
|
73
73
|
@server.trigger(:subscribe, client_id, channel) if should_trigger
|
74
74
|
callback.call(true) if callback
|
75
75
|
end
|
@@ -85,13 +85,13 @@ module Faye
|
|
85
85
|
@channels.delete(channel) if @channels[channel].empty?
|
86
86
|
end
|
87
87
|
|
88
|
-
@server.debug
|
88
|
+
@server.debug('Unsubscribed client ? from channel ?', client_id, channel)
|
89
89
|
@server.trigger(:unsubscribe, client_id, channel) if should_trigger
|
90
90
|
callback.call(true) if callback
|
91
91
|
end
|
92
92
|
|
93
93
|
def publish(message, channels)
|
94
|
-
@server.debug
|
94
|
+
@server.debug('Publishing message ?', message)
|
95
95
|
|
96
96
|
clients = Set.new
|
97
97
|
|
@@ -101,7 +101,7 @@ module Faye
|
|
101
101
|
end
|
102
102
|
|
103
103
|
clients.each do |client_id|
|
104
|
-
@server.debug
|
104
|
+
@server.debug('Queueing for client ?: ?', client_id, message)
|
105
105
|
@messages[client_id] ||= []
|
106
106
|
@messages[client_id] << Faye.copy_object(message)
|
107
107
|
empty_queue(client_id)
|
@@ -119,4 +119,3 @@ module Faye
|
|
119
119
|
|
120
120
|
end
|
121
121
|
end
|
122
|
-
|
data/lib/faye/engines/proxy.rb
CHANGED
@@ -21,7 +21,7 @@ module Faye
|
|
21
21
|
|
22
22
|
def self.random(bitlength = ID_LENGTH)
|
23
23
|
limit = 2 ** bitlength
|
24
|
-
max_size = (
|
24
|
+
max_size = (bitlength * Math.log(2) / Math.log(36)).ceil
|
25
25
|
string = SecureRandom.random_number(limit).to_s(36)
|
26
26
|
string = '0' + string while string.size < max_size
|
27
27
|
string
|
@@ -48,14 +48,14 @@ module Faye
|
|
48
48
|
@engine = engine_class.create(self, @options)
|
49
49
|
|
50
50
|
bind :close do |client_id|
|
51
|
-
EventMachine.next_tick {
|
51
|
+
EventMachine.next_tick { flush_connection(client_id) }
|
52
52
|
end
|
53
53
|
|
54
|
-
debug
|
54
|
+
debug('Created new engine: ?', @options)
|
55
55
|
end
|
56
56
|
|
57
57
|
def connect(client_id, options = {}, &callback)
|
58
|
-
debug
|
58
|
+
debug('Accepting connection from ?', client_id)
|
59
59
|
@engine.ping(client_id)
|
60
60
|
conn = connection(client_id, true)
|
61
61
|
conn.connect(options, &callback)
|
@@ -75,9 +75,8 @@ module Faye
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def close_connection(client_id)
|
78
|
-
debug
|
79
|
-
conn = @connections[client_id]
|
80
|
-
return unless conn
|
78
|
+
debug('Closing connection for ?', client_id)
|
79
|
+
return unless conn = @connections[client_id]
|
81
80
|
conn.socket.close if conn.socket
|
82
81
|
trigger('connection:close', client_id)
|
83
82
|
@connections.delete(client_id)
|
@@ -90,8 +89,7 @@ module Faye
|
|
90
89
|
|
91
90
|
def deliver(client_id, messages)
|
92
91
|
return if !messages || messages.empty?
|
93
|
-
conn = connection(client_id, false)
|
94
|
-
return false unless conn
|
92
|
+
return false unless conn = connection(client_id, false)
|
95
93
|
messages.each(&conn.method(:deliver))
|
96
94
|
true
|
97
95
|
end
|
@@ -100,15 +98,17 @@ module Faye
|
|
100
98
|
Engine.random
|
101
99
|
end
|
102
100
|
|
103
|
-
def
|
101
|
+
def flush_connection(client_id, close = true)
|
104
102
|
return unless client_id
|
105
|
-
debug
|
106
|
-
conn = connection(client_id, false)
|
107
|
-
conn.
|
103
|
+
debug('Flushing connection for ?', client_id)
|
104
|
+
return unless conn = connection(client_id, false)
|
105
|
+
conn.socket = nil unless close
|
106
|
+
conn.flush
|
107
|
+
close_connection(client_id)
|
108
108
|
end
|
109
109
|
|
110
110
|
def close
|
111
|
-
@connections.keys.each { |client_id|
|
111
|
+
@connections.keys.each { |client_id| flush_connection(client_id) }
|
112
112
|
@engine.disconnect
|
113
113
|
end
|
114
114
|
|
@@ -124,4 +124,3 @@ module Faye
|
|
124
124
|
|
125
125
|
end
|
126
126
|
end
|
127
|
-
|
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
|
|
@@ -92,10 +92,9 @@ module Faye
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def subscribe(names, callback)
|
95
|
-
return unless callback
|
96
95
|
names.each do |name|
|
97
96
|
channel = @channels[name] ||= Channel.new(name)
|
98
|
-
channel.bind(:message, &callback)
|
97
|
+
channel.bind(:message, &callback) if callback
|
99
98
|
end
|
100
99
|
end
|
101
100
|
|
@@ -122,4 +121,3 @@ module Faye
|
|
122
121
|
|
123
122
|
end
|
124
123
|
end
|
125
|
-
|
data/lib/faye/protocol/client.rb
CHANGED
@@ -6,59 +6,42 @@ 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])
|
25
25
|
super()
|
26
26
|
info('New client created for ?', endpoint)
|
27
27
|
|
28
|
-
@
|
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
|
28
|
+
@endpoint = endpoint || RackAdapter::DEFAULT_ENDPOINT
|
44
29
|
@channels = Channel::Set.new
|
30
|
+
@dispatcher = Dispatcher.new(self, @endpoint, options)
|
31
|
+
|
45
32
|
@message_id = 0
|
33
|
+
@state = UNCONNECTED
|
46
34
|
|
47
35
|
@response_callbacks = {}
|
48
36
|
|
49
37
|
@advice = {
|
50
38
|
'reconnect' => RETRY,
|
51
|
-
'interval' => 1000.0 * (
|
52
|
-
'timeout' => 1000.0 * (
|
39
|
+
'interval' => 1000.0 * (options[:interval] || Engine::INTERVAL),
|
40
|
+
'timeout' => 1000.0 * (options[:timeout] || CONNECTION_TIMEOUT)
|
53
41
|
}
|
54
|
-
|
55
|
-
|
56
|
-
def disable(feature)
|
57
|
-
@disabled << feature
|
58
|
-
end
|
42
|
+
@dispatcher.timeout = @advice['timeout'] / 1000.0
|
59
43
|
|
60
|
-
|
61
|
-
@headers[name.to_s] = value.to_s
|
44
|
+
@dispatcher.bind(:message, &method(:receive_message))
|
62
45
|
end
|
63
46
|
|
64
47
|
# Request
|
@@ -87,29 +70,29 @@ module Faye
|
|
87
70
|
@state = CONNECTING
|
88
71
|
|
89
72
|
info('Initiating handshake with ?', @endpoint)
|
90
|
-
select_transport(MANDATORY_CONNECTION_TYPES)
|
73
|
+
@dispatcher.select_transport(MANDATORY_CONNECTION_TYPES)
|
91
74
|
|
92
|
-
|
93
|
-
'channel'
|
94
|
-
'version'
|
95
|
-
'supportedConnectionTypes'
|
75
|
+
send_message({
|
76
|
+
'channel' => Channel::HANDSHAKE,
|
77
|
+
'version' => BAYEUX_VERSION,
|
78
|
+
'supportedConnectionTypes' => @dispatcher.connection_types
|
96
79
|
|
97
|
-
}) do |response|
|
80
|
+
}, {}) do |response|
|
98
81
|
|
99
82
|
if response['successful']
|
100
|
-
@state
|
101
|
-
@client_id = response['clientId']
|
83
|
+
@state = CONNECTED
|
84
|
+
@dispatcher.client_id = response['clientId']
|
102
85
|
|
103
|
-
select_transport(response['supportedConnectionTypes'])
|
86
|
+
@dispatcher.select_transport(response['supportedConnectionTypes'])
|
104
87
|
|
105
|
-
info('Handshake successful: ?', @client_id)
|
88
|
+
info('Handshake successful: ?', @dispatcher.client_id)
|
106
89
|
|
107
90
|
subscribe(@channels.keys, true)
|
108
91
|
block.call if block_given?
|
109
92
|
|
110
93
|
else
|
111
94
|
info('Handshake unsuccessful')
|
112
|
-
EventMachine.add_timer(@
|
95
|
+
EventMachine.add_timer(@dispatcher.retry) { handshake(&block) }
|
113
96
|
@state = UNCONNECTED
|
114
97
|
end
|
115
98
|
end
|
@@ -133,21 +116,21 @@ module Faye
|
|
133
116
|
callback(&block)
|
134
117
|
return unless @state == CONNECTED
|
135
118
|
|
136
|
-
info('Calling deferred actions for ?', @client_id)
|
119
|
+
info('Calling deferred actions for ?', @dispatcher.client_id)
|
137
120
|
set_deferred_status(:succeeded)
|
138
121
|
set_deferred_status(:unknown)
|
139
122
|
|
140
123
|
return unless @connect_request.nil?
|
141
124
|
@connect_request = true
|
142
125
|
|
143
|
-
info('Initiating connection for ?', @client_id)
|
126
|
+
info('Initiating connection for ?', @dispatcher.client_id)
|
144
127
|
|
145
|
-
|
146
|
-
'channel'
|
147
|
-
'clientId'
|
148
|
-
'connectionType'
|
128
|
+
send_message({
|
129
|
+
'channel' => Channel::CONNECT,
|
130
|
+
'clientId' => @dispatcher.client_id,
|
131
|
+
'connectionType' => @dispatcher.connection_type
|
149
132
|
|
150
|
-
}) do
|
133
|
+
}, {}) do
|
151
134
|
cycle_connection
|
152
135
|
end
|
153
136
|
end
|
@@ -163,18 +146,26 @@ module Faye
|
|
163
146
|
return unless @state == CONNECTED
|
164
147
|
@state = DISCONNECTED
|
165
148
|
|
166
|
-
info('Disconnecting ?', @client_id)
|
149
|
+
info('Disconnecting ?', @dispatcher.client_id)
|
150
|
+
promise = Publication.new
|
167
151
|
|
168
|
-
|
169
|
-
'channel'
|
170
|
-
'clientId'
|
152
|
+
send_message({
|
153
|
+
'channel' => Channel::DISCONNECT,
|
154
|
+
'clientId' => @dispatcher.client_id
|
171
155
|
|
172
|
-
}) do |response|
|
173
|
-
|
156
|
+
}, {}) do |response|
|
157
|
+
if response['successful']
|
158
|
+
@dispatcher.close
|
159
|
+
promise.set_deferred_status(:succeeded)
|
160
|
+
else
|
161
|
+
promise.set_deferred_status(:failed, Error.parse(response['error']))
|
162
|
+
end
|
174
163
|
end
|
175
164
|
|
176
|
-
info('Clearing channel listeners for ?', @client_id)
|
165
|
+
info('Clearing channel listeners for ?', @dispatcher.client_id)
|
177
166
|
@channels = Channel::Set.new
|
167
|
+
|
168
|
+
promise
|
178
169
|
end
|
179
170
|
|
180
171
|
# Request Response
|
@@ -202,22 +193,22 @@ module Faye
|
|
202
193
|
end
|
203
194
|
|
204
195
|
connect {
|
205
|
-
info('Client ? attempting to subscribe to ?', @client_id, channel)
|
196
|
+
info('Client ? attempting to subscribe to ?', @dispatcher.client_id, channel)
|
206
197
|
@channels.subscribe([channel], block) unless force
|
207
198
|
|
208
|
-
|
209
|
-
'channel'
|
210
|
-
'clientId'
|
211
|
-
'subscription'
|
199
|
+
send_message({
|
200
|
+
'channel' => Channel::SUBSCRIBE,
|
201
|
+
'clientId' => @dispatcher.client_id,
|
202
|
+
'subscription' => channel
|
212
203
|
|
213
|
-
}) do |response|
|
204
|
+
}, {}) do |response|
|
214
205
|
unless response['successful']
|
215
206
|
subscription.set_deferred_status(:failed, Error.parse(response['error']))
|
216
207
|
next @channels.unsubscribe(channel, block)
|
217
208
|
end
|
218
209
|
|
219
210
|
channels = [response['subscription']].flatten
|
220
|
-
info('Subscription acknowledged for ? to ?', @client_id, channels)
|
211
|
+
info('Subscription acknowledged for ? to ?', @dispatcher.client_id, channels)
|
221
212
|
subscription.set_deferred_status(:succeeded)
|
222
213
|
end
|
223
214
|
}
|
@@ -243,18 +234,18 @@ module Faye
|
|
243
234
|
return unless dead
|
244
235
|
|
245
236
|
connect {
|
246
|
-
info('Client ? attempting to unsubscribe from ?', @client_id, channel)
|
237
|
+
info('Client ? attempting to unsubscribe from ?', @dispatcher.client_id, channel)
|
247
238
|
|
248
|
-
|
249
|
-
'channel'
|
250
|
-
'clientId'
|
251
|
-
'subscription'
|
239
|
+
send_message({
|
240
|
+
'channel' => Channel::UNSUBSCRIBE,
|
241
|
+
'clientId' => @dispatcher.client_id,
|
242
|
+
'subscription' => channel
|
252
243
|
|
253
|
-
}) do |response|
|
244
|
+
}, {}) do |response|
|
254
245
|
next unless response['successful']
|
255
246
|
|
256
247
|
channels = [response['subscription']].flatten
|
257
|
-
info('Unsubscription acknowledged for ? from ?', @client_id, channels)
|
248
|
+
info('Unsubscription acknowledged for ? from ?', @dispatcher.client_id, channels)
|
258
249
|
end
|
259
250
|
}
|
260
251
|
end
|
@@ -265,17 +256,19 @@ module Faye
|
|
265
256
|
# MAY include: * clientId MAY include: * id
|
266
257
|
# * id * error
|
267
258
|
# * ext * ext
|
268
|
-
def publish(channel, data)
|
259
|
+
def publish(channel, data, options = {})
|
260
|
+
::WebSocket::Driver.validate_options(options, [:attempts, :deadline])
|
261
|
+
|
269
262
|
publication = Publication.new
|
270
263
|
connect {
|
271
|
-
info('Client ? queueing published message to ?: ?', @client_id, channel, data)
|
264
|
+
info('Client ? queueing published message to ?: ?', @dispatcher.client_id, channel, data)
|
272
265
|
|
273
|
-
|
274
|
-
'channel'
|
275
|
-
'data'
|
276
|
-
'clientId'
|
266
|
+
send_message({
|
267
|
+
'channel' => channel,
|
268
|
+
'data' => data,
|
269
|
+
'clientId' => @dispatcher.client_id
|
277
270
|
|
278
|
-
}) do |response|
|
271
|
+
}, options) do |response|
|
279
272
|
if response['successful']
|
280
273
|
publication.set_deferred_status(:succeeded)
|
281
274
|
else
|
@@ -286,81 +279,20 @@ module Faye
|
|
286
279
|
publication
|
287
280
|
end
|
288
281
|
|
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
282
|
private
|
327
283
|
|
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
|
284
|
+
def send_message(message, options, &callback)
|
341
285
|
message['id'] = generate_message_id
|
342
286
|
|
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
287
|
timeout = [nil, 0].include?(@advice['timeout']) ?
|
354
|
-
1.2 * @retry :
|
288
|
+
1.2 * @dispatcher.retry :
|
355
289
|
1.2 * @advice['timeout'] / 1000.0
|
356
290
|
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
291
|
+
pipe_through_extensions(:outgoing, message, nil) do |message|
|
292
|
+
next unless message
|
293
|
+
@response_callbacks[message['id']] = callback if callback
|
294
|
+
@dispatcher.send_message(message, timeout, options)
|
361
295
|
end
|
362
|
-
|
363
|
-
@transport.send(envelope)
|
364
296
|
end
|
365
297
|
|
366
298
|
def generate_message_id
|
@@ -369,30 +301,45 @@ module Faye
|
|
369
301
|
@message_id.to_s(36)
|
370
302
|
end
|
371
303
|
|
304
|
+
def receive_message(message)
|
305
|
+
id = message['id']
|
306
|
+
|
307
|
+
if message.has_key?('successful')
|
308
|
+
callback = @response_callbacks.delete(id)
|
309
|
+
end
|
310
|
+
|
311
|
+
pipe_through_extensions(:incoming, message, nil) do |message|
|
312
|
+
next unless message
|
313
|
+
handle_advice(message['advice']) if message['advice']
|
314
|
+
deliver_message(message)
|
315
|
+
callback.call(message) if callback
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
372
319
|
def handle_advice(advice)
|
373
320
|
@advice.update(advice)
|
321
|
+
@dispatcher.timeout = @advice['timeout'] / 1000.0
|
374
322
|
|
375
323
|
if @advice['reconnect'] == HANDSHAKE and @state != DISCONNECTED
|
376
|
-
@state
|
377
|
-
@client_id = nil
|
324
|
+
@state = UNCONNECTED
|
325
|
+
@dispatcher.client_id = nil
|
378
326
|
cycle_connection
|
379
327
|
end
|
380
328
|
end
|
381
329
|
|
382
330
|
def deliver_message(message)
|
383
331
|
return unless message.has_key?('channel') and message.has_key?('data')
|
384
|
-
info('Client ? calling listeners for ? with ?', @client_id, message['channel'], message['data'])
|
332
|
+
info('Client ? calling listeners for ? with ?', @dispatcher.client_id, message['channel'], message['data'])
|
385
333
|
@channels.distribute_message(message)
|
386
334
|
end
|
387
335
|
|
388
336
|
def cycle_connection
|
389
337
|
if @connect_request
|
390
338
|
@connect_request = nil
|
391
|
-
info('Closed connection for ?', @client_id)
|
339
|
+
info('Closed connection for ?', @dispatcher.client_id)
|
392
340
|
end
|
393
341
|
EventMachine.add_timer(@advice['interval'] / 1000.0) { connect }
|
394
342
|
end
|
395
343
|
|
396
344
|
end
|
397
345
|
end
|
398
|
-
|