diff --git a/lib/websocket/driver.rb b/lib/websocket/driver.rb index 0c3f11d..8306157 100644 --- a/lib/websocket/driver.rb +++ b/lib/websocket/driver.rb @@ -33,13 +33,12 @@ module WebSocket end end - unless String.instance_methods.include?(:force_encoding) - require root + '/utf8_match' - end - MAX_LENGTH = 0x3ffffff STATES = [:connecting, :open, :closing, :closed] + BINARY = 'ASCII-8BIT' + UNICODE = 'UTF-8' + ConnectEvent = Struct.new(nil) OpenEvent = Struct.new(nil) MessageEvent = Struct.new(:data) @@ -94,13 +93,14 @@ module WebSocket return false unless @ready_state == 0 response = handshake_response return false unless response - @socket.write(Driver.encode(response, :binary)) + @socket.write(response) open unless @stage == -1 true end def text(message) - frame(message) + message = message.encode(UNICODE) unless message.encoding.name == UNICODE + frame(message, :text) end def binary(message) @@ -159,14 +159,15 @@ module WebSocket case string when Array then string = string.pack('C*') - encoding ||= :binary + encoding ||= BINARY when String then - encoding ||= :utf8 + encoding ||= UNICODE end - encodings = {:utf8 => 'UTF-8', :binary => 'ASCII-8BIT'} - string.force_encoding(encodings[encoding]) if string.respond_to?(:force_encoding) - return nil if encoding == :utf8 and not valid_utf8?(string) - string + unless string.encoding.name == encoding + string = string.dup if string.frozen? + string.force_encoding(encoding) + end + string.valid_encoding? ? string : nil end def self.validate_options(options, valid_keys) @@ -177,14 +178,6 @@ module WebSocket end end - def self.valid_utf8?(string) - if defined?(UTF8_MATCH) - UTF8_MATCH =~ string ? true : false - else - string.valid_encoding? - end - end - def self.websocket?(env) connection = env['HTTP_CONNECTION'] || '' upgrade = env['HTTP_UPGRADE'] || '' diff --git a/lib/websocket/driver/client.rb b/lib/websocket/driver/client.rb index d2c54b6..0a45534 100644 --- a/lib/websocket/driver/client.rb +++ b/lib/websocket/driver/client.rb @@ -53,7 +53,7 @@ module WebSocket def start return false unless @ready_state == -1 - @socket.write(Driver.encode(handshake_request, :binary)) + @socket.write(handshake_request) @ready_state = 0 true end diff --git a/lib/websocket/driver/draft75.rb b/lib/websocket/driver/draft75.rb index 403fcbe..041b725 100644 --- a/lib/websocket/driver/draft75.rb +++ b/lib/websocket/driver/draft75.rb @@ -56,7 +56,7 @@ module WebSocket when 2 then if octet == 0xFF @stage = 0 - emit(:message, MessageEvent.new(Driver.encode(@buffer, :utf8))) + emit(:message, MessageEvent.new(Driver.encode(@buffer, UNICODE))) else if @length @skipped += 1 diff --git a/lib/websocket/driver/draft76.rb b/lib/websocket/driver/draft76.rb index 3643b75..aa28c2c 100644 --- a/lib/websocket/driver/draft76.rb +++ b/lib/websocket/driver/draft76.rb @@ -8,7 +8,7 @@ module WebSocket super input = @socket.env['rack.input'] @stage = -1 - @body = Driver.encode(input ? input.read : '', :binary) + @body = (input ? input.read : String.new('')).force_encoding(BINARY) @headers.clear @headers['Upgrade'] = 'WebSocket' @@ -70,7 +70,7 @@ module WebSocket def send_handshake_body return unless signature = handshake_signature - @socket.write(Driver.encode(signature, :binary)) + @socket.write(signature) @stage = 0 open parse(@body[BODY_SIZE..-1]) if @body.bytesize > BODY_SIZE diff --git a/lib/websocket/driver/hybi.rb b/lib/websocket/driver/hybi.rb index 6c47219..36d1905 100644 --- a/lib/websocket/driver/hybi.rb +++ b/lib/websocket/driver/hybi.rb @@ -129,10 +129,6 @@ module WebSocket end end - def text(message) - frame(message, :text) - end - def binary(message) frame(message, :binary) end @@ -356,7 +352,7 @@ module WebSocket when OPCODES[:close] then code = (bytesize >= 2) ? payload.unpack(PACK_FORMATS[2]).first : nil - reason = (bytesize > 2) ? Driver.encode(bytes[2..-1] || [], :utf8) : nil + reason = (bytesize > 2) ? Driver.encode(bytes[2..-1] || [], UNICODE) : nil unless (bytesize == 0) or (code && code >= MIN_RESERVED_ERROR && code <= MAX_RESERVED_ERROR) or @@ -374,7 +370,7 @@ module WebSocket frame(payload, :pong) when OPCODES[:pong] then - message = Driver.encode(payload, :utf8) + message = Driver.encode(payload, UNICODE) callback = @ping_callbacks[message] @ping_callbacks.delete(message) callback.call if callback @@ -391,7 +387,7 @@ module WebSocket case message.opcode when OPCODES[:text] then - payload = Driver.encode(payload, :utf8) + payload = Driver.encode(payload, UNICODE) when OPCODES[:binary] payload = payload.bytes.to_a end diff --git a/lib/websocket/driver/hybi/message.rb b/lib/websocket/driver/hybi/message.rb index 06fcf94..7a62f9e 100644 --- a/lib/websocket/driver/hybi/message.rb +++ b/lib/websocket/driver/hybi/message.rb @@ -14,7 +14,7 @@ module WebSocket @rsv2 = false @rsv3 = false @opcode = nil - @data = Driver.encode('', :binary) + @data = String.new('').force_encoding(BINARY) end def <<(frame) diff --git a/lib/websocket/driver/proxy.rb b/lib/websocket/driver/proxy.rb index 6434782..e4891e3 100644 --- a/lib/websocket/driver/proxy.rb +++ b/lib/websocket/driver/proxy.rb @@ -44,7 +44,7 @@ module WebSocket start = "CONNECT #{@origin.host}:#{port} HTTP/1.1" headers = [start, @headers.to_s, ''] - @socket.write(Driver.encode(headers.join("\r\n"), :binary)) + @socket.write(headers.join("\r\n")) true end diff --git a/lib/websocket/driver/server.rb b/lib/websocket/driver/server.rb index 1cbaf23..f13fde9 100644 --- a/lib/websocket/driver/server.rb +++ b/lib/websocket/driver/server.rb @@ -58,7 +58,7 @@ module WebSocket end def write(buffer) - @socket.write(Driver.encode(buffer, :binary)) + @socket.write(buffer) end private diff --git a/lib/websocket/driver/stream_reader.rb b/lib/websocket/driver/stream_reader.rb index 90e7172..0ce8683 100644 --- a/lib/websocket/driver/stream_reader.rb +++ b/lib/websocket/driver/stream_reader.rb @@ -6,13 +6,13 @@ module WebSocket MINIMUM_AUTOMATIC_PRUNE_OFFSET = 128 def initialize - @buffer = Driver.encode('', :binary) + @buffer = String.new('').force_encoding(BINARY) @offset = 0 end def put(chunk) return unless chunk and chunk.bytesize > 0 - @buffer << Driver.encode(chunk, :binary) + @buffer << chunk.force_encoding(BINARY) end # Read bytes from the data: @@ -42,7 +42,7 @@ module WebSocket buffer_size = @buffer.bytesize if @offset > buffer_size - @buffer = Driver.encode('', :binary) + @buffer = String.new('').force_encoding(BINARY) else @buffer = @buffer.byteslice(@offset, buffer_size - @offset) end diff --git a/lib/websocket/driver/utf8_match.rb b/lib/websocket/driver/utf8_match.rb deleted file mode 100644 index b0fc7af..0000000 --- a/lib/websocket/driver/utf8_match.rb +++ /dev/null @@ -1,6 +0,0 @@ -module WebSocket - class Driver - # http://www.w3.org/International/questions/qa-forms-utf-8.en.php - UTF8_MATCH = /^([\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})*$/ - end -end diff --git a/spec/websocket/driver/draft75_spec.rb b/spec/websocket/driver/draft75_spec.rb index 1ab8f00..4cbd88d 100644 --- a/spec/websocket/driver/draft75_spec.rb +++ b/spec/websocket/driver/draft75_spec.rb @@ -90,7 +90,7 @@ describe WebSocket::Driver::Draft75 do "WebSocket-Origin: http://www.example.com\r\n" + "WebSocket-Location: ws://www.example.com/socket\r\n" + "\r\n") - expect(socket).to receive(:write).with(WebSocket::Driver.encode "\x00Hi\xFF", :binary) + expect(socket).to receive(:write).with(WebSocket::Driver.encode "\x00Hi\xFF", WebSocket::Driver::BINARY) driver.frame("Hi") driver.start diff --git a/spec/websocket/driver/draft76_spec.rb b/spec/websocket/driver/draft76_spec.rb index 39aa1e7..7c3a8b1 100644 --- a/spec/websocket/driver/draft76_spec.rb +++ b/spec/websocket/driver/draft76_spec.rb @@ -137,7 +137,7 @@ describe WebSocket::Driver::Draft76 do "Sec-WebSocket-Location: ws://www.example.com/socket\r\n" + "\r\n") expect(socket).to receive(:write).with(response) - expect(socket).to receive(:write).with(WebSocket::Driver.encode "\x00Hi\xFF", :binary) + expect(socket).to receive(:write).with(WebSocket::Driver.encode "\x00Hi\xFF", WebSocket::Driver::BINARY) driver.frame("Hi") driver.start @@ -191,7 +191,7 @@ describe WebSocket::Driver::Draft76 do it "sends any frames queued before the handshake was complete" do expect(socket).to receive(:write).with(response) - expect(socket).to receive(:write).with(WebSocket::Driver.encode "\x00hello\xFF", :binary) + expect(socket).to receive(:write).with(WebSocket::Driver.encode "\x00hello\xFF", WebSocket::Driver::BINARY) driver.frame("hello") driver.parse(body) expect(@bytes).to eq [0, 104, 101, 108, 108, 111, 255]