websocket 1.0.0
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.
- data/.gitignore +3 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +5 -0
- data/README.md +117 -0
- data/Rakefile +23 -0
- data/autobahn-client.json +11 -0
- data/autobahn-server.json +10 -0
- data/examples/base.rb +162 -0
- data/examples/client.rb +70 -0
- data/examples/server.rb +56 -0
- data/examples/tests/autobahn_client.rb +52 -0
- data/examples/tests/echo_client.rb +42 -0
- data/examples/tests/echo_server.rb +45 -0
- data/lib/websocket.rb +16 -0
- data/lib/websocket/frame.rb +11 -0
- data/lib/websocket/frame/base.rb +45 -0
- data/lib/websocket/frame/data.rb +52 -0
- data/lib/websocket/frame/handler.rb +15 -0
- data/lib/websocket/frame/handler/base.rb +41 -0
- data/lib/websocket/frame/handler/handler03.rb +162 -0
- data/lib/websocket/frame/handler/handler04.rb +19 -0
- data/lib/websocket/frame/handler/handler05.rb +17 -0
- data/lib/websocket/frame/handler/handler07.rb +34 -0
- data/lib/websocket/frame/handler/handler75.rb +79 -0
- data/lib/websocket/frame/incoming.rb +43 -0
- data/lib/websocket/frame/incoming/client.rb +9 -0
- data/lib/websocket/frame/incoming/server.rb +9 -0
- data/lib/websocket/frame/outgoing.rb +28 -0
- data/lib/websocket/frame/outgoing/client.rb +9 -0
- data/lib/websocket/frame/outgoing/server.rb +9 -0
- data/lib/websocket/handshake.rb +10 -0
- data/lib/websocket/handshake/base.rb +67 -0
- data/lib/websocket/handshake/client.rb +80 -0
- data/lib/websocket/handshake/handler.rb +20 -0
- data/lib/websocket/handshake/handler/base.rb +25 -0
- data/lib/websocket/handshake/handler/client.rb +19 -0
- data/lib/websocket/handshake/handler/client01.rb +19 -0
- data/lib/websocket/handshake/handler/client04.rb +47 -0
- data/lib/websocket/handshake/handler/client75.rb +25 -0
- data/lib/websocket/handshake/handler/client76.rb +85 -0
- data/lib/websocket/handshake/handler/server.rb +30 -0
- data/lib/websocket/handshake/handler/server04.rb +38 -0
- data/lib/websocket/handshake/handler/server75.rb +26 -0
- data/lib/websocket/handshake/handler/server76.rb +71 -0
- data/lib/websocket/handshake/server.rb +56 -0
- data/lib/websocket/version.rb +3 -0
- data/spec/frame/incoming_03_spec.rb +117 -0
- data/spec/frame/incoming_04_spec.rb +117 -0
- data/spec/frame/incoming_05_spec.rb +133 -0
- data/spec/frame/incoming_07_spec.rb +133 -0
- data/spec/frame/incoming_75_spec.rb +59 -0
- data/spec/frame/incoming_common_spec.rb +22 -0
- data/spec/frame/outgoing_03_spec.rb +77 -0
- data/spec/frame/outgoing_04_spec.rb +77 -0
- data/spec/frame/outgoing_05_spec.rb +77 -0
- data/spec/frame/outgoing_07_spec.rb +77 -0
- data/spec/frame/outgoing_75_spec.rb +41 -0
- data/spec/frame/outgoing_common_spec.rb +15 -0
- data/spec/handshake/client_04_spec.rb +20 -0
- data/spec/handshake/client_75_spec.rb +11 -0
- data/spec/handshake/client_76_spec.rb +20 -0
- data/spec/handshake/server_04_spec.rb +18 -0
- data/spec/handshake/server_75_spec.rb +11 -0
- data/spec/handshake/server_76_spec.rb +46 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/all_client_drafts.rb +77 -0
- data/spec/support/all_server_drafts.rb +86 -0
- data/spec/support/handshake_requests.rb +72 -0
- data/spec/support/incoming_frames.rb +30 -0
- data/spec/support/outgoing_frames.rb +14 -0
- data/websocket.gemspec +21 -0
- metadata +163 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
require "#{File.expand_path(File.dirname(__FILE__))}/../client"
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
EM.epoll
|
5
|
+
EM.run do
|
6
|
+
|
7
|
+
host = 'ws://localhost:9001'
|
8
|
+
agent = "WebSocket-Ruby (Ruby #{RUBY_VERSION})"
|
9
|
+
cases = 0
|
10
|
+
skip = []
|
11
|
+
|
12
|
+
ws = WebSocket::EventMachine::Client.connect(:uri => "#{host}/getCaseCount")
|
13
|
+
|
14
|
+
ws.onmessage do |msg, type|
|
15
|
+
puts "$ Total cases to run: #{msg}"
|
16
|
+
cases = msg.to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
ws.onclose do
|
20
|
+
|
21
|
+
run_case = lambda do |n|
|
22
|
+
|
23
|
+
if n > cases
|
24
|
+
puts "$ Requesting report"
|
25
|
+
ws = WebSocket::EventMachine::Client.connect(:uri => "#{host}/updateReports?agent=#{CGI.escape agent}")
|
26
|
+
ws.onclose do
|
27
|
+
EM.stop
|
28
|
+
end
|
29
|
+
|
30
|
+
elsif skip.include?(n)
|
31
|
+
EM.next_tick { run_case.call(n+1) }
|
32
|
+
|
33
|
+
else
|
34
|
+
puts "$ Test number #{n}"
|
35
|
+
ws = WebSocket::EventMachine::Client.connect(:uri => "#{host}/runCase?case=#{n}&agent=#{CGI.escape agent}")
|
36
|
+
|
37
|
+
ws.onmessage do |msg, type|
|
38
|
+
puts "Received #{msg}(#{type})"
|
39
|
+
ws.send(msg, :type => type)
|
40
|
+
end
|
41
|
+
|
42
|
+
ws.onclose do |msg|
|
43
|
+
puts("Closing: #{msg}") if msg
|
44
|
+
run_case.call(n + 1)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
run_case.call(1)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "#{File.expand_path(File.dirname(__FILE__))}/../client"
|
2
|
+
|
3
|
+
EM.epoll
|
4
|
+
EM.run do
|
5
|
+
|
6
|
+
trap("TERM") { stop }
|
7
|
+
trap("INT") { stop }
|
8
|
+
|
9
|
+
ws = WebSocket::EventMachine::Client.connect(:host => "localhost", :port => 9001);
|
10
|
+
|
11
|
+
ws.onopen do
|
12
|
+
puts "Connected"
|
13
|
+
ws.send "Hello"
|
14
|
+
end
|
15
|
+
|
16
|
+
ws.onmessage do |msg, type|
|
17
|
+
puts "Received message: #{msg}"
|
18
|
+
ws.send msg, :type => type
|
19
|
+
end
|
20
|
+
|
21
|
+
ws.onclose do
|
22
|
+
puts "Disconnected"
|
23
|
+
end
|
24
|
+
|
25
|
+
ws.onerror do |e|
|
26
|
+
puts "Error: #{e}"
|
27
|
+
end
|
28
|
+
|
29
|
+
ws.onping do |msg|
|
30
|
+
puts "Receied ping: #{msg}"
|
31
|
+
end
|
32
|
+
|
33
|
+
ws.onpong do |msg|
|
34
|
+
puts "Received pong: #{msg}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def stop
|
38
|
+
puts "Terminating connection"
|
39
|
+
EventMachine.stop
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "#{File.expand_path(File.dirname(__FILE__))}/../server"
|
2
|
+
|
3
|
+
EM.epoll
|
4
|
+
EM.run do
|
5
|
+
|
6
|
+
trap("TERM") { stop }
|
7
|
+
trap("INT") { stop }
|
8
|
+
|
9
|
+
WebSocket::EventMachine::Server.start(:host => "0.0.0.0", :port => 9001) do |ws|
|
10
|
+
|
11
|
+
ws.onopen do
|
12
|
+
puts "Client connected"
|
13
|
+
end
|
14
|
+
|
15
|
+
ws.onmessage do |msg, type|
|
16
|
+
puts "Received message: #{msg}"
|
17
|
+
ws.send msg, :type => type
|
18
|
+
end
|
19
|
+
|
20
|
+
ws.onclose do
|
21
|
+
puts "Client disconnected"
|
22
|
+
end
|
23
|
+
|
24
|
+
ws.onerror do |e|
|
25
|
+
puts "Error: #{e}"
|
26
|
+
end
|
27
|
+
|
28
|
+
ws.onping do |msg|
|
29
|
+
puts "Receied ping: #{msg}"
|
30
|
+
end
|
31
|
+
|
32
|
+
ws.onpong do |msg|
|
33
|
+
puts "Received pong: #{msg}"
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
puts "Server started at port 9001"
|
39
|
+
|
40
|
+
def stop
|
41
|
+
puts "Terminating WebSocket Server"
|
42
|
+
EventMachine.stop
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
data/lib/websocket.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# WebSocket protocol implementation in Ruby
|
2
|
+
# This module does not provide a WebSocket server or client, but is made for using
|
3
|
+
# in http servers or clients to provide WebSocket support.
|
4
|
+
# @author Bernard "Imanel" Potocki
|
5
|
+
# @see http://github.com/imanel/websocket-ruby main repository
|
6
|
+
module WebSocket
|
7
|
+
class Error < RuntimeError; end
|
8
|
+
|
9
|
+
DEFAULT_VERSION = 13
|
10
|
+
ROOT = File.expand_path(File.dirname(__FILE__))
|
11
|
+
|
12
|
+
autoload :Frame, "#{ROOT}/websocket/frame"
|
13
|
+
autoload :Handler, "#{ROOT}/websocket/handler"
|
14
|
+
autoload :Handshake, "#{ROOT}/websocket/handshake"
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module WebSocket
|
2
|
+
module Frame
|
3
|
+
|
4
|
+
autoload :Base, "#{::WebSocket::ROOT}/websocket/frame/base"
|
5
|
+
autoload :Data, "#{::WebSocket::ROOT}/websocket/frame/data"
|
6
|
+
autoload :Handler, "#{::WebSocket::ROOT}/websocket/frame/handler"
|
7
|
+
autoload :Incoming, "#{::WebSocket::ROOT}/websocket/frame/incoming"
|
8
|
+
autoload :Outgoing, "#{::WebSocket::ROOT}/websocket/frame/outgoing"
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module WebSocket
|
2
|
+
module Frame
|
3
|
+
class Base
|
4
|
+
|
5
|
+
attr_reader :data, :type, :version, :error
|
6
|
+
|
7
|
+
# Initialize frame
|
8
|
+
# @param args [Hash] Arguments for frame
|
9
|
+
# @option args [Integer] :version Version of draft. Currently supported version are 75, 76 and 00-13.
|
10
|
+
# @option args [String] :type Type of frame - available types are "text", "binary", "ping", "pong" and "close"(support depends on draft version)
|
11
|
+
# @option args [String] :data default data for frame
|
12
|
+
def initialize(args = {})
|
13
|
+
@type = args[:type]
|
14
|
+
@data = Data.new(args[:data].to_s)
|
15
|
+
@version = args[:version] || DEFAULT_VERSION
|
16
|
+
set_handler
|
17
|
+
end
|
18
|
+
|
19
|
+
# Check if some errors occured
|
20
|
+
# @return [Boolean] True if error is set
|
21
|
+
def error?
|
22
|
+
!!@error
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def set_handler
|
28
|
+
case @version
|
29
|
+
when 75..76 then extend Handler::Handler75
|
30
|
+
when 0..2 then extend Handler::Handler75
|
31
|
+
when 3 then extend Handler::Handler03
|
32
|
+
when 4 then extend Handler::Handler04
|
33
|
+
when 5..6 then extend Handler::Handler05
|
34
|
+
when 7..13 then extend Handler::Handler07
|
35
|
+
else set_error(:unknown_protocol_version) and return
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def set_error(message)
|
40
|
+
@error = message
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module WebSocket
|
2
|
+
module Frame
|
3
|
+
class Data < String
|
4
|
+
|
5
|
+
def initialize(*args)
|
6
|
+
super *args.each { |arg| arg.force_encoding('ASCII-8BIT') if respond_to?(:force_encoding) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def <<(*args)
|
10
|
+
super *args.each { |arg| arg.force_encoding('ASCII-8BIT') if respond_to?(:force_encoding) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def set_mask
|
14
|
+
raise "Too short" if bytesize < 4 # TODO - change
|
15
|
+
@masking_key = Data.new(self[0..3])
|
16
|
+
end
|
17
|
+
|
18
|
+
def unset_mask
|
19
|
+
@masking_key = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def getbytes(start_index, count)
|
23
|
+
data = ''
|
24
|
+
data.force_encoding('ASCII-8BIT') if data.respond_to?(:force_encoding)
|
25
|
+
count.times do |i|
|
26
|
+
data << getbyte(start_index + i)
|
27
|
+
end
|
28
|
+
data
|
29
|
+
end
|
30
|
+
|
31
|
+
# Required for support of Ruby 1.8
|
32
|
+
unless new.respond_to?(:getbyte)
|
33
|
+
def getbyte(index)
|
34
|
+
self[index]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def getbyte_with_masking(index)
|
39
|
+
if @masking_key
|
40
|
+
masked_char = getbyte_without_masking(index)
|
41
|
+
masked_char ? masked_char ^ @masking_key.getbyte(index % 4) : nil
|
42
|
+
else
|
43
|
+
getbyte_without_masking(index)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
alias_method :getbyte_without_masking, :getbyte
|
48
|
+
alias_method :getbyte, :getbyte_with_masking
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module WebSocket
|
2
|
+
module Frame
|
3
|
+
module Handler
|
4
|
+
|
5
|
+
autoload :Base, "#{::WebSocket::ROOT}/websocket/frame/handler/base"
|
6
|
+
|
7
|
+
autoload :Handler03, "#{::WebSocket::ROOT}/websocket/frame/handler/handler03"
|
8
|
+
autoload :Handler04, "#{::WebSocket::ROOT}/websocket/frame/handler/handler04"
|
9
|
+
autoload :Handler05, "#{::WebSocket::ROOT}/websocket/frame/handler/handler05"
|
10
|
+
autoload :Handler07, "#{::WebSocket::ROOT}/websocket/frame/handler/handler07"
|
11
|
+
autoload :Handler75, "#{::WebSocket::ROOT}/websocket/frame/handler/handler75"
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module WebSocket
|
2
|
+
module Frame
|
3
|
+
module Handler
|
4
|
+
module Base
|
5
|
+
|
6
|
+
MAX_FRAME_SIZE = 20 * 1024 * 1024 # 20MB
|
7
|
+
|
8
|
+
# Is selected type supported for selected handler?
|
9
|
+
def support_type?
|
10
|
+
supported_frames.include?(@type)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Implement in submodules
|
14
|
+
def supported_frames
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# Convert data to raw frame ready to send to client
|
21
|
+
def encode_frame
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
|
25
|
+
# Convert raw data to decoded frame
|
26
|
+
def decode_frame
|
27
|
+
raise NotImplementedError
|
28
|
+
end
|
29
|
+
|
30
|
+
def control_frame?(frame_type)
|
31
|
+
![:text, :binary, :continuation].include?(frame_type)
|
32
|
+
end
|
33
|
+
|
34
|
+
def data_frame?(frame_type)
|
35
|
+
[:text, :binary].include?(frame_type)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
|
3
|
+
module WebSocket
|
4
|
+
module Frame
|
5
|
+
module Handler
|
6
|
+
module Handler03
|
7
|
+
|
8
|
+
include Base
|
9
|
+
|
10
|
+
def supported_frames
|
11
|
+
[:text, :binary, :close, :ping, :pong]
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def encode_frame
|
17
|
+
frame = ''
|
18
|
+
|
19
|
+
opcode = type_to_opcode(@type)
|
20
|
+
byte1 = opcode | (fin ? 0b10000000 : 0b00000000) # since more, rsv1-3 are 0 and 0x80 for Draft 4
|
21
|
+
frame << byte1
|
22
|
+
|
23
|
+
length = @data.size
|
24
|
+
if length <= 125
|
25
|
+
byte2 = length # since rsv4 is 0
|
26
|
+
frame << byte2
|
27
|
+
elsif length < 65536 # write 2 byte length
|
28
|
+
frame << 126
|
29
|
+
frame << [length].pack('n')
|
30
|
+
else # write 8 byte length
|
31
|
+
frame << 127
|
32
|
+
frame << [length >> 32, length & 0xFFFFFFFF].pack("NN")
|
33
|
+
end
|
34
|
+
|
35
|
+
frame << @data
|
36
|
+
frame
|
37
|
+
rescue WebSocket::Error => e
|
38
|
+
set_error(e.message.to_sym) and return
|
39
|
+
end
|
40
|
+
|
41
|
+
def decode_frame
|
42
|
+
while @data.size > 1
|
43
|
+
pointer = 0
|
44
|
+
|
45
|
+
more = ((@data.getbyte(pointer) & 0b10000000) == 0b10000000) ^ fin
|
46
|
+
|
47
|
+
raise(WebSocket::Error, :reserved_bit_used) if @data.getbyte(pointer) & 0b01110000 != 0b00000000
|
48
|
+
|
49
|
+
opcode = @data.getbyte(pointer) & 0b00001111
|
50
|
+
frame_type = opcode_to_type(opcode)
|
51
|
+
pointer += 1
|
52
|
+
|
53
|
+
raise(WebSocket::Error, :fragmented_control_frame) if more && control_frame?(frame_type)
|
54
|
+
raise(WebSocket::Error, :data_frame_instead_continuation) if data_frame?(frame_type) && !@application_data_buffer.nil?
|
55
|
+
|
56
|
+
mask = masking? && (@data.getbyte(pointer) & 0b10000000) == 0b10000000
|
57
|
+
length = @data.getbyte(pointer) & 0b01111111
|
58
|
+
|
59
|
+
raise(WebSocket::Error, :control_frame_payload_too_long) if length > 125 && control_frame?(frame_type)
|
60
|
+
|
61
|
+
pointer += 1
|
62
|
+
|
63
|
+
payload_length = case length
|
64
|
+
when 127 # Length defined by 8 bytes
|
65
|
+
# Check buffer size
|
66
|
+
return if @data.getbyte(pointer+8-1) == nil # Buffer incomplete
|
67
|
+
|
68
|
+
# Only using the last 4 bytes for now, till I work out how to
|
69
|
+
# unpack 8 bytes. I'm sure 4GB frames will do for now :)
|
70
|
+
l = @data.getbytes(pointer+4, 4).unpack('N').first
|
71
|
+
pointer += 8
|
72
|
+
l
|
73
|
+
when 126 # Length defined by 2 bytes
|
74
|
+
# Check buffer size
|
75
|
+
return if @data.getbyte(pointer+2-1) == nil # Buffer incomplete
|
76
|
+
|
77
|
+
l = @data.getbytes(pointer, 2).unpack('n').first
|
78
|
+
pointer += 2
|
79
|
+
l
|
80
|
+
else
|
81
|
+
length
|
82
|
+
end
|
83
|
+
|
84
|
+
# Compute the expected frame length
|
85
|
+
frame_length = pointer + payload_length
|
86
|
+
frame_length += 4 if mask
|
87
|
+
|
88
|
+
raise(WebSocket::Error, :frame_too_long) if frame_length > MAX_FRAME_SIZE
|
89
|
+
|
90
|
+
# Check buffer size
|
91
|
+
return if @data.getbyte(frame_length-1) == nil # Buffer incomplete
|
92
|
+
|
93
|
+
# Remove frame header
|
94
|
+
@data.slice!(0...pointer)
|
95
|
+
pointer = 0
|
96
|
+
|
97
|
+
# Read application data (unmasked if required)
|
98
|
+
@data.set_mask if mask
|
99
|
+
pointer += 4 if mask
|
100
|
+
application_data = @data.getbytes(pointer, payload_length)
|
101
|
+
application_data.force_encoding('UTF-8') if application_data.respond_to?(:force_encoding)
|
102
|
+
pointer += payload_length
|
103
|
+
@data.unset_mask if mask
|
104
|
+
|
105
|
+
# Throw away data up to pointer
|
106
|
+
@data.slice!(0...pointer)
|
107
|
+
|
108
|
+
raise(WebSocket::Error, :unexpected_continuation_frame) if frame_type == :continuation && !@frame_type
|
109
|
+
|
110
|
+
if more
|
111
|
+
@application_data_buffer ||= ''
|
112
|
+
@application_data_buffer << application_data
|
113
|
+
@frame_type ||= frame_type
|
114
|
+
else
|
115
|
+
# Message is complete
|
116
|
+
if frame_type == :continuation
|
117
|
+
@application_data_buffer << application_data
|
118
|
+
# Test valid UTF-8 encoding
|
119
|
+
raise(WebSocket::Error, :invalid_payload_encoding) if @frame_type == :text && @application_data_buffer.respond_to?(:valid_encoding?) && !@application_data_buffer.valid_encoding?
|
120
|
+
message = self.class.new(:version => version, :type => @frame_type, :data => @application_data_buffer, :decoded => true)
|
121
|
+
@application_data_buffer = nil
|
122
|
+
@frame_type = nil
|
123
|
+
return message
|
124
|
+
else
|
125
|
+
raise(WebSocket::Error, :invalid_payload_encoding) if frame_type == :text && application_data.respond_to?(:valid_encoding?) && !application_data.valid_encoding?
|
126
|
+
return self.class.new(:version => version, :type => frame_type, :data => application_data, :decoded => true)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
return nil
|
131
|
+
rescue WebSocket::Error => e
|
132
|
+
set_error(e.message.to_sym) and return
|
133
|
+
end
|
134
|
+
|
135
|
+
# This allows flipping the more bit to fin for draft 04
|
136
|
+
def fin; false; end
|
137
|
+
|
138
|
+
def masking?; false; end
|
139
|
+
|
140
|
+
FRAME_TYPES = {
|
141
|
+
:continuation => 0,
|
142
|
+
:close => 1,
|
143
|
+
:ping => 2,
|
144
|
+
:pong => 3,
|
145
|
+
:text => 4,
|
146
|
+
:binary => 5
|
147
|
+
}
|
148
|
+
|
149
|
+
FRAME_TYPES_INVERSE = FRAME_TYPES.invert
|
150
|
+
|
151
|
+
def type_to_opcode(frame_type)
|
152
|
+
FRAME_TYPES[frame_type] || raise(WebSocket::Error, :unknown_frame_type)
|
153
|
+
end
|
154
|
+
|
155
|
+
def opcode_to_type(opcode)
|
156
|
+
FRAME_TYPES_INVERSE[opcode] || raise(WebSocket::Error, :unknown_opcode)
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|