faye-websocket 0.4.6-java → 0.4.7-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of faye-websocket might be problematic. Click here for more details.
- data/CHANGELOG.txt +7 -0
- data/README.rdoc +24 -24
- data/examples/app.rb +10 -10
- data/examples/autobahn_client.rb +16 -11
- data/examples/client.rb +4 -4
- data/examples/config.ru +3 -3
- data/examples/sse.html +8 -8
- data/examples/ws.html +8 -8
- data/ext/faye_websocket_mask/FayeWebsocketMaskService.java +7 -7
- data/ext/faye_websocket_mask/faye_websocket_mask.c +2 -2
- data/lib/faye/adapters/goliath.rb +5 -5
- data/lib/faye/adapters/rainbows.rb +3 -3
- data/lib/faye/adapters/rainbows_client.rb +12 -12
- data/lib/faye/adapters/thin.rb +10 -9
- data/lib/faye/eventsource.rb +26 -26
- data/lib/faye/websocket.rb +40 -40
- data/lib/faye/websocket/adapter.rb +5 -5
- data/lib/faye/websocket/api.rb +28 -25
- data/lib/faye/websocket/api/event.rb +7 -7
- data/lib/faye/websocket/api/event_target.rb +8 -8
- data/lib/faye/websocket/client.rb +18 -18
- data/lib/faye/websocket/draft75_parser.rb +13 -13
- data/lib/faye/websocket/draft76_parser.rb +17 -17
- data/lib/faye/websocket/hybi_parser.rb +4 -4
- data/lib/faye/websocket/utf8_match.rb +2 -2
- data/lib/faye_websocket_mask.jar +0 -0
- data/spec/faye/websocket/client_spec.rb +32 -49
- data/spec/faye/websocket/draft75_parser_examples.rb +7 -7
- data/spec/faye/websocket/draft75_parser_spec.rb +4 -4
- data/spec/faye/websocket/draft76_parser_spec.rb +5 -5
- data/spec/spec_helper.rb +4 -4
- metadata +162 -122
@@ -1,21 +1,21 @@
|
|
1
1
|
module Faye
|
2
2
|
class WebSocket
|
3
|
-
|
3
|
+
|
4
4
|
module Adapter
|
5
5
|
def websocket?
|
6
6
|
e = defined?(@env) ? @env : env
|
7
7
|
WebSocket.websocket?(e)
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def eventsource?
|
11
11
|
e = defined?(@env) ? @env : env
|
12
12
|
EventSource.eventsource?(e)
|
13
13
|
end
|
14
|
-
|
15
|
-
def
|
14
|
+
|
15
|
+
def socket_connection?
|
16
16
|
websocket? or eventsource?
|
17
17
|
end
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
end
|
21
21
|
end
|
data/lib/faye/websocket/api.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Faye
|
2
2
|
class WebSocket
|
3
|
-
|
3
|
+
|
4
4
|
module API
|
5
5
|
module ReadyStates
|
6
6
|
CONNECTING = 0
|
@@ -8,35 +8,35 @@ module Faye
|
|
8
8
|
CLOSING = 2
|
9
9
|
CLOSED = 3
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
class IllegalStateError < StandardError
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
require File.expand_path('../api/event_target', __FILE__)
|
16
16
|
require File.expand_path('../api/event', __FILE__)
|
17
17
|
include EventTarget
|
18
18
|
include ReadyStates
|
19
|
-
|
19
|
+
|
20
20
|
attr_reader :url, :ready_state, :buffered_amount
|
21
|
-
|
21
|
+
|
22
22
|
private
|
23
|
-
|
23
|
+
|
24
24
|
def open
|
25
25
|
return if @parser and not @parser.open?
|
26
26
|
@ready_state = OPEN
|
27
|
-
|
27
|
+
|
28
28
|
buffer = @send_buffer || []
|
29
29
|
while message = buffer.shift
|
30
30
|
send(*message)
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
event = Event.new('open')
|
34
34
|
event.init_event('open', false, false)
|
35
35
|
dispatch_event(event)
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
public
|
39
|
-
|
39
|
+
|
40
40
|
def receive(data)
|
41
41
|
return false unless @ready_state == OPEN
|
42
42
|
event = Event.new('message')
|
@@ -44,7 +44,7 @@ module Faye
|
|
44
44
|
event.data = data
|
45
45
|
dispatch_event(event)
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
def send(data, type = nil, error_type = nil)
|
49
49
|
if @ready_state == CONNECTING
|
50
50
|
if @send_buffer
|
@@ -54,22 +54,21 @@ module Faye
|
|
54
54
|
raise IllegalStateError, 'Cannot call send(), socket is not open yet'
|
55
55
|
end
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
return false if @ready_state == CLOSED
|
59
|
-
|
59
|
+
|
60
60
|
data = data.to_s unless Array === data
|
61
|
-
|
61
|
+
|
62
62
|
data = WebSocket.encode(data) if String === data
|
63
63
|
frame = @parser.frame(data, type, error_type)
|
64
64
|
@stream.write(frame) if frame
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
def close(code = nil, reason = nil, ack = true)
|
68
|
-
return if
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
close = lambda do
|
68
|
+
return if @ready_state == CLOSED
|
69
|
+
return if @ready_state == CLOSING && ack
|
70
|
+
|
71
|
+
finalize = lambda do
|
73
72
|
@ready_state = CLOSED
|
74
73
|
EventMachine.cancel_timer(@ping_timer) if @ping_timer
|
75
74
|
@stream.close_connection_after_writing
|
@@ -77,20 +76,24 @@ module Faye
|
|
77
76
|
event.init_event('close', false, false)
|
78
77
|
dispatch_event(event)
|
79
78
|
end
|
80
|
-
|
79
|
+
|
80
|
+
return finalize.call if @ready_state == CONNECTING
|
81
|
+
|
82
|
+
@ready_state = CLOSING
|
83
|
+
|
81
84
|
if ack
|
82
85
|
if @parser.respond_to?(:close)
|
83
|
-
@parser.close(code, reason, &
|
86
|
+
@parser.close(code, reason, &finalize)
|
84
87
|
else
|
85
|
-
|
88
|
+
finalize.call
|
86
89
|
end
|
87
90
|
else
|
88
91
|
@parser.close(code, reason) if @parser.respond_to?(:close)
|
89
|
-
|
92
|
+
finalize.call
|
90
93
|
end
|
91
94
|
end
|
92
95
|
end
|
93
|
-
|
96
|
+
|
94
97
|
end
|
95
98
|
end
|
96
99
|
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module Faye::WebSocket::API
|
2
2
|
class Event
|
3
|
-
|
3
|
+
|
4
4
|
attr_reader :type, :bubbles, :cancelable
|
5
5
|
attr_accessor :target, :current_target, :event_phase, :data
|
6
|
-
|
6
|
+
|
7
7
|
CAPTURING_PHASE = 1
|
8
8
|
AT_TARGET = 2
|
9
9
|
BUBBLING_PHASE = 3
|
10
|
-
|
10
|
+
|
11
11
|
def initialize(event_type, options = {})
|
12
12
|
@type = event_type
|
13
13
|
metaclass = (class << self ; self ; end)
|
@@ -15,19 +15,19 @@ module Faye::WebSocket::API
|
|
15
15
|
metaclass.__send__(:define_method, key) { value }
|
16
16
|
end
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def init_event(event_type, can_bubble, cancelable)
|
20
20
|
@type = event_type
|
21
21
|
@bubbles = can_bubble
|
22
22
|
@cancelable = cancelable
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def stop_propagation
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def prevent_default
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -1,34 +1,34 @@
|
|
1
1
|
module Faye::WebSocket::API
|
2
2
|
module EventTarget
|
3
|
-
|
3
|
+
|
4
4
|
attr_accessor :onopen, :onmessage, :onerror, :onclose
|
5
|
-
|
5
|
+
|
6
6
|
def add_event_listener(event_type, listener, use_capture = false)
|
7
7
|
@listeners ||= {}
|
8
8
|
list = @listeners[event_type] ||= []
|
9
9
|
list << listener
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def remove_event_listener(event_type, listener, use_capture = false)
|
13
13
|
return unless @listeners and @listeners[event_type]
|
14
14
|
return @listeners.delete(event_type) unless listener
|
15
|
-
|
15
|
+
|
16
16
|
@listeners[event_type].delete_if(&listener.method(:==))
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def dispatch_event(event)
|
20
20
|
event.target = event.current_target = self
|
21
21
|
event.event_phase = Event::AT_TARGET
|
22
|
-
|
22
|
+
|
23
23
|
callback = __send__("on#{ event.type }")
|
24
24
|
callback.call(event) if callback
|
25
|
-
|
25
|
+
|
26
26
|
return unless @listeners and @listeners[event.type]
|
27
27
|
@listeners[event.type].each do |listener|
|
28
28
|
listener.call(event)
|
29
29
|
end
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -1,51 +1,51 @@
|
|
1
1
|
module Faye
|
2
2
|
class WebSocket
|
3
|
-
|
3
|
+
|
4
4
|
class Client
|
5
5
|
include API
|
6
6
|
attr_reader :protocol, :uri
|
7
|
-
|
7
|
+
|
8
8
|
def initialize(url, protocols = nil)
|
9
9
|
@parser = HybiParser.new(self, :masking => true, :protocols => protocols)
|
10
10
|
@url = url
|
11
11
|
@uri = URI.parse(url)
|
12
|
-
|
12
|
+
|
13
13
|
@protocol = ''
|
14
14
|
@ready_state = CONNECTING
|
15
15
|
@buffered_amount = 0
|
16
|
-
|
16
|
+
|
17
17
|
port = @uri.port || (@uri.scheme == 'wss' ? 443 : 80)
|
18
|
-
|
18
|
+
|
19
19
|
EventMachine.connect(@uri.host, port, Connection) do |conn|
|
20
20
|
@stream = conn
|
21
21
|
conn.parent = self
|
22
22
|
end
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
private
|
26
|
-
|
26
|
+
|
27
27
|
def on_connect
|
28
28
|
@stream.start_tls if @uri.scheme == 'wss'
|
29
29
|
@handshake = @parser.create_handshake
|
30
30
|
@message = []
|
31
31
|
@stream.write(@handshake.request_data)
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
def receive_data(data)
|
35
35
|
data = WebSocket.encode(data)
|
36
|
-
|
36
|
+
|
37
37
|
case @ready_state
|
38
38
|
when CONNECTING then
|
39
39
|
@message += @handshake.parse(data)
|
40
40
|
return unless @handshake.complete?
|
41
|
-
|
41
|
+
|
42
42
|
if @handshake.valid?
|
43
43
|
@protocol = @handshake.protocol || ''
|
44
44
|
@ready_state = OPEN
|
45
45
|
event = Event.new('open')
|
46
46
|
event.init_event('open', false, false)
|
47
47
|
dispatch_event(event)
|
48
|
-
|
48
|
+
|
49
49
|
receive_data(@message)
|
50
50
|
else
|
51
51
|
@ready_state = CLOSED
|
@@ -53,32 +53,32 @@ module Faye
|
|
53
53
|
event.init_event('close', false, false)
|
54
54
|
dispatch_event(event)
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
when OPEN, CLOSING then
|
58
58
|
@parser.parse(data)
|
59
59
|
end
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
module Connection
|
63
63
|
attr_accessor :parent
|
64
|
-
|
64
|
+
|
65
65
|
def connection_completed
|
66
66
|
parent.__send__(:on_connect)
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
def receive_data(data)
|
70
70
|
parent.__send__(:receive_data, data)
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
def unbind
|
74
74
|
parent.close(1006, '', false)
|
75
75
|
end
|
76
|
-
|
76
|
+
|
77
77
|
def write(data)
|
78
78
|
send_data(data) rescue nil
|
79
79
|
end
|
80
80
|
end
|
81
81
|
end
|
82
|
-
|
82
|
+
|
83
83
|
end
|
84
84
|
end
|
@@ -1,18 +1,18 @@
|
|
1
1
|
module Faye
|
2
2
|
class WebSocket
|
3
|
-
|
3
|
+
|
4
4
|
class Draft75Parser
|
5
5
|
attr_reader :protocol
|
6
|
-
|
6
|
+
|
7
7
|
def initialize(web_socket, options = {})
|
8
8
|
@socket = web_socket
|
9
9
|
@stage = 0
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def version
|
13
13
|
'hixie-75'
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def handshake_response
|
17
17
|
upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
|
18
18
|
upgrade << "Upgrade: WebSocket\r\n"
|
@@ -22,21 +22,21 @@ module Faye
|
|
22
22
|
upgrade << "\r\n"
|
23
23
|
upgrade
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def open?
|
27
27
|
true
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
def parse(buffer)
|
31
31
|
buffer.each_byte do |data|
|
32
32
|
case @stage
|
33
33
|
when 0 then
|
34
34
|
parse_leading_byte(data)
|
35
|
-
|
35
|
+
|
36
36
|
when 1 then
|
37
37
|
value = (data & 0x7F)
|
38
38
|
@length = value + 128 * @length
|
39
|
-
|
39
|
+
|
40
40
|
if @closing and @length.zero?
|
41
41
|
@socket.close(nil, nil, false)
|
42
42
|
elsif (0x80 & data) != 0x80
|
@@ -48,7 +48,7 @@ module Faye
|
|
48
48
|
@stage = 2
|
49
49
|
end
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
when 2 then
|
53
53
|
if data == 0xFF
|
54
54
|
@socket.receive(WebSocket.encode(@buffer))
|
@@ -61,10 +61,10 @@ module Faye
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
nil
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
def parse_leading_byte(data)
|
69
69
|
if (0x80 & data) == 0x80
|
70
70
|
@length = 0
|
@@ -75,13 +75,13 @@ module Faye
|
|
75
75
|
@stage = 2
|
76
76
|
end
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
def frame(data, type = nil, error_type = nil)
|
80
80
|
return WebSocket.encode(data) if Array === data
|
81
81
|
["\x00", data, "\xFF"].map(&WebSocket.method(:encode)) * ''
|
82
82
|
end
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
@@ -1,15 +1,15 @@
|
|
1
1
|
module Faye
|
2
2
|
class WebSocket
|
3
|
-
|
3
|
+
|
4
4
|
class Draft76Parser < Draft75Parser
|
5
5
|
def version
|
6
6
|
'hixie-76'
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
def handshake_response
|
10
10
|
env = @socket.env
|
11
11
|
signature = handshake_signature(env['rack.input'].read)
|
12
|
-
|
12
|
+
|
13
13
|
upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
|
14
14
|
upgrade << "Upgrade: WebSocket\r\n"
|
15
15
|
upgrade << "Connection: Upgrade\r\n"
|
@@ -19,57 +19,57 @@ module Faye
|
|
19
19
|
upgrade << signature if signature
|
20
20
|
upgrade
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def handshake_signature(head)
|
24
24
|
return nil if head.empty?
|
25
25
|
env = @socket.env
|
26
|
-
|
26
|
+
|
27
27
|
key1 = env['HTTP_SEC_WEBSOCKET_KEY1']
|
28
28
|
value1 = number_from_key(key1) / spaces_in_key(key1)
|
29
|
-
|
29
|
+
|
30
30
|
key2 = env['HTTP_SEC_WEBSOCKET_KEY2']
|
31
31
|
value2 = number_from_key(key2) / spaces_in_key(key2)
|
32
|
-
|
32
|
+
|
33
33
|
@handshake_complete = true
|
34
|
-
|
34
|
+
|
35
35
|
Digest::MD5.digest(big_endian(value1) +
|
36
36
|
big_endian(value2) +
|
37
37
|
head)
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
def open?
|
41
41
|
!!@handshake_complete
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
def parse(data)
|
45
45
|
return super if @handshake_complete
|
46
46
|
handshake_signature(data)
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
def close(code = nil, reason = nil, &callback)
|
50
50
|
return if @closed
|
51
51
|
@socket.send([0xFF, 0x00]) if @closing
|
52
52
|
@closed = true
|
53
53
|
callback.call if callback
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
private
|
57
|
-
|
57
|
+
|
58
58
|
def parse_leading_byte(data)
|
59
59
|
return super unless data == 0xFF
|
60
60
|
@closing = true
|
61
61
|
@length = 0
|
62
62
|
@stage = 1
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
def number_from_key(key)
|
66
66
|
key.scan(/[0-9]/).join('').to_i(10)
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
def spaces_in_key(key)
|
70
70
|
key.scan(/ /).size
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
def big_endian(number)
|
74
74
|
string = ''
|
75
75
|
[24,16,8,0].each do |offset|
|
@@ -78,7 +78,7 @@ module Faye
|
|
78
78
|
string
|
79
79
|
end
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|