Class: Midori::WebSocket
- Inherits:
-
Object
- Object
- Midori::WebSocket
- Defined in:
- lib/midori/websocket.rb
Overview
This class provides methods for WebSocket connection instance.
Instance Attribute Summary collapse
-
#connection ⇒ EM::Connection
raw EventMachine connection.
-
#events ⇒ Hash
response for different event.
-
#msg ⇒ Array<Integer>, String
message send from client.
-
#opcode ⇒ Integer
operation code of WebSocket.
-
#request ⇒ Midori::Request
raw request.
Instance Method Summary collapse
-
#close ⇒ Object
Close a websocket connection.
-
#decode(data) ⇒ Object
Decode raw data send from client.
-
#decode_mask(data) ⇒ Object
Decode masked message send from client.
-
#heartbeat(method, str) ⇒ Object
Ancestor of ping pong.
-
#initialize(connection) ⇒ WebSocket
constructor
Init a WebSocket instance with a connection.
-
#on(event) { ... } ⇒ Object
API definition for events.
-
#ping(str) ⇒ Object
Send a Ping request.
-
#pong(str) ⇒ Object
Send a Pong request.
-
#send(msg) ⇒ Object
Send data.
Constructor Details
#initialize(connection) ⇒ WebSocket
Init a WebSocket instance with a connection
13 14 15 16 |
# File 'lib/midori/websocket.rb', line 13 def initialize(connection) @events = {} @connection = connection end |
Instance Attribute Details
#connection ⇒ EM::Connection
raw EventMachine connection
8 9 10 |
# File 'lib/midori/websocket.rb', line 8 def connection @connection end |
#events ⇒ Hash
response for different event
8 9 10 |
# File 'lib/midori/websocket.rb', line 8 def events @events end |
#msg ⇒ Array<Integer>, String
message send from client
8 9 10 |
# File 'lib/midori/websocket.rb', line 8 def msg @msg end |
#opcode ⇒ Integer
operation code of WebSocket
8 9 10 |
# File 'lib/midori/websocket.rb', line 8 def opcode @opcode end |
#request ⇒ Midori::Request
raw request
8 9 10 |
# File 'lib/midori/websocket.rb', line 8 def request @request end |
Instance Method Details
#close ⇒ Object
Close a websocket connection
102 103 104 |
# File 'lib/midori/websocket.rb', line 102 def close raise Midori::Exception::FrameEnd end |
#decode(data) ⇒ Object
Decode raw data send from client
20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/midori/websocket.rb', line 20 def decode(data) # Fin and Opcode byte_tmp = data.getbyte fin = byte_tmp & 0b10000000 @opcode = byte_tmp & 0b00001111 # NOT Support Multiple Fragments raise Midori::Exception::ContinuousFrame unless fin raise Midori::Exception::OpCodeError unless [0x1, 0x2, 0x8, 0x9, 0xA].include? opcode close if @opcode == 0x8 # Close Frame # return if @opcode == 0x9 || @opcode == 0xA # Ping Pong decode_mask(data) end |
#decode_mask(data) ⇒ Object
Decode masked message send from client
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/midori/websocket.rb', line 35 def decode_mask(data) # Mask byte_tmp = data.getbyte is_masked = byte_tmp & 0b10000000 raise Midori::Exception::NotMasked unless is_masked == 128 # Payload payload = byte_tmp & 0b01111111 mask = Array.new(4) { data.getbyte } # Message masked_msg = Array.new(payload) { data.getbyte } @msg = masked_msg.each_with_index.map { |byte, i| byte ^ mask[i % 4] } @msg = @msg.pack('C*').force_encoding('utf-8') if [0x1, 0x9, 0xA].include?opcode # For debug # data.rewind # data.bytes {|byte| puts byte.to_s(16)} end |
#heartbeat(method, str) ⇒ Object
Ancestor of ping pong
96 97 98 99 |
# File 'lib/midori/websocket.rb', line 96 def heartbeat(method, str) raise Midori::Exception::PingPongSizeTooLarge if str.size > 125 @connection.send_data [method, str.size, str].pack("CCA#{str.size}") end |
#on(event) { ... } ⇒ Object
API definition for events
61 62 63 |
# File 'lib/midori/websocket.rb', line 61 def on(event, &block) # open, message, close, ping, pong @events[event] = block end |
#ping(str) ⇒ Object
Send a Ping request
83 84 85 |
# File 'lib/midori/websocket.rb', line 83 def ping(str) heartbeat(0b10001001, str) end |
#pong(str) ⇒ Object
Send a Pong request
89 90 91 |
# File 'lib/midori/websocket.rb', line 89 def pong(str) heartbeat(0b10001010, str) end |
#send(msg) ⇒ Object
Send data
67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/midori/websocket.rb', line 67 def send(msg) output = [] if msg.is_a?String output << 0b10000001 << msg.size << msg @connection.send_data(output.pack("CCA#{msg.size}")) elsif msg.is_a?Array output << 0b10000010 << msg.size output.concat msg @connection.send_data(output.pack('C*')) else raise Midori::Exception::OpCodeError end end |