Skip to content
This repository has been archived by the owner on Dec 7, 2018. It is now read-only.

Commit

Permalink
Merge 8a42629 into 96c6d00
Browse files Browse the repository at this point in the history
  • Loading branch information
mwean committed Jul 13, 2014
2 parents 96c6d00 + 8a42629 commit d3e2fdf
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 202 deletions.
4 changes: 2 additions & 2 deletions lib/reel/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,10 @@ def websocket?; @request_info.websocket_request?; end

# Return a Reel::WebSocket for this request, hijacking the socket from
# the underlying connection
def websocket
def websocket(&block)
@websocket ||= begin
raise StateError, "can't upgrade this request to a websocket" unless websocket?
WebSocket.new(@request_info, @connection.hijack_socket)
WebSocket.new(@connection, &block)
end
end

Expand Down
114 changes: 36 additions & 78 deletions lib/reel/websocket.rb
Original file line number Diff line number Diff line change
@@ -1,105 +1,63 @@
require 'forwardable'
require 'websocket_parser'
require 'websocket/driver'

module Reel
class WebSocket
extend Forwardable
include ConnectionMixin
include RequestMixin

attr_reader :socket
def_delegators :@socket, :addr, :peeraddr
NO_PREFIX_HEADERS = %w(CONTENT_TYPE CONTENT_LENGTH).freeze

def initialize(info, socket)
@request_info = info
@socket = socket
attr_reader :env, :url, :socket
def_delegators :driver, :text, :binary, :ping, :close
def_delegators :socket, :write

handshake = ::WebSocket::ClientHandshake.new(:get, url, headers)
def initialize(connection)
@connection = connection
@socket = @connection.socket

if handshake.valid?
response = handshake.accept_response
response.render(socket)
else
error = handshake.errors.first
@connection.detach
@connection.hijack_socket

response = Response.new(400)
response.reason = handshake.errors.first
response.render(@socket)
driver.on(:close) { close }
driver.on(:connect) { driver.start }

raise HandshakeError, "error during handshake: #{error}"
end

@parser = ::WebSocket::Parser.new

@parser.on_close do |status, reason|
# According to the spec the server must respond with another
# close message before closing the connection
@socket << ::WebSocket::Message.close.to_data
close
end
yield driver if block_given?

@parser.on_ping do |payload|
@socket << ::WebSocket::Message.pong(payload).to_data
end
start_listening
end

[:next_message, :next_messages, :on_message, :on_error, :on_close, :on_ping, :on_pong].each do |meth|
define_method meth do |&proc|
@parser.send __method__, &proc
end
def close
socket.close unless socket.closed?
end

def read_every(n, unit = :s)
cancel_timer! # only one timer allowed per stream
seconds = case unit.to_s
when /\Am/
n * 60
when /\Ah/
n * 3600
else
n
def start_listening
loop do
break if socket.closed?
buffer = socket.readpartial(@connection.buffer_size)
driver.parse(buffer)
end
@timer = Celluloid.every(seconds) { read }
rescue EOFError
close
end
alias read_interval read_every
alias read_frequency read_every

def read
@parser.append @socket.readpartial(Connection::BUFFER_SIZE) until msg = @parser.next_message
msg
rescue
cancel_timer!
raise
end
private

def body
nil
def driver
@driver ||= ::WebSocket::Driver.server(self)
end

def write(msg)
@socket << ::WebSocket::Message.new(msg).to_data
msg
rescue IOError, Errno::ECONNRESET, Errno::EPIPE
cancel_timer!
raise SocketError, "error writing to socket"
rescue
cancel_timer!
raise
end
alias_method :<<, :write

def closed?
@socket.closed?
end
def convert_headers(headers)
prefixed_headers = headers.map do |key, value|
header = key.upcase.gsub('-', '_')

def close
cancel_timer!
@socket.close unless closed?
end
if NO_PREFIX_HEADERS.member?(header)
[header, value]
else
['HTTP_' + header, value]
end
end

def cancel_timer!
@timer && @timer.cancel
Hash[prefixed_headers]
end

end
end
2 changes: 1 addition & 1 deletion reel.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Gem::Specification.new do |gem|
gem.add_runtime_dependency 'celluloid-io', '>= 0.15.0'
gem.add_runtime_dependency 'http', '>= 0.6.0.pre'
gem.add_runtime_dependency 'http_parser.rb', '>= 0.6.0'
gem.add_runtime_dependency 'websocket_parser', '>= 0.1.6'
gem.add_runtime_dependency 'websocket-driver', '>= 0.3.0'

gem.add_development_dependency 'rake'
gem.add_development_dependency 'rspec', '>= 2.11.0'
Expand Down
Loading

0 comments on commit d3e2fdf

Please sign in to comment.