Skip to content

Instantly share code, notes, and snippets.

@robertjpayne
Created October 13, 2013 11:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save robertjpayne/6961149 to your computer and use it in GitHub Desktop.
Save robertjpayne/6961149 to your computer and use it in GitHub Desktop.
require File.expand_path('../websocket_handler.rb', __FILE__)
class Server < Reel::Server
include Celluloid::Logger
def initialize(host = '0.0.0.0', port = (ENV['PORT'] || 5000).to_i)
super(host, port, &method(:on_connection))
end
def on_connection(connection)
connection.each_request do |request|
if request.websocket?
handle_websocket_request(request, connection)
else
handle_http_request(request, connection)
end
end
end
def handle_http_request(request, connection)
request.respond :ok, "Hello Lame"
end
def handle_websocket_request(request, connection)
debug("[handle_websocket_request] method: #{request.method}, url: #{request.url}, uri: #{request.uri}, query_string: #{request.query_string}, fragment: #{request.fragment}, headers: #{request.headers}")
ws = WebSocketHandler.new(request, connection)
ws.on :open do |event|
debug('[ws] open')
end
ws.on :message do |event|
debug('[ws] message')
end
ws.on :close do |event|
debug('[ws] close')
end
ws.on :error do |event|
debug('[ws] error')
end
ws.run
debug("[handle_websocket_request] finished")
end
end
require 'forwardable'
require 'websocket/driver'
class WebSocketHandler
include Celluloid::Logger
extend Forwardable
def initialize(request, connection)
@request = request
@connection = connection
@socket = nil
end
def_delegators :driver, :on, :text, :binary, :ping, :close
def run
# detach the connection and manage it ourselves
@connection.detach
# grab socket
@socket = @connection.socket
# start the driver
driver.start
# hook into close message from client
driver.on(:close) { @connection.close }
begin
loop do
break unless @connection.alive?
buffer = @socket.readpartial(@connection.buffer_size)
driver.parse(buffer)
end
ensure
@connection.close
end
rescue EOFError
@connection.close
end
def url
@request.url
end
def env
@env ||= begin
e = {
:method => @request.method,
:input => @request.body.to_s,
'REMOTE_ADDR' => @request.remote_addr
}.merge(Hash[@request.headers.map { |key, value| ['HTTP_' + key.upcase.gsub('-','_'),value ] }])
::Rack::MockRequest.env_for(url, e)
end
end
def write(buffer)
# should probably raise an error here if
# writing to socket that has not been started up yet
@socket.write(buffer)
end
def close
@connection.close if @connection.alive? && !@connection.attached?
end
protected
def driver
@driver ||= ::WebSocket::Driver.rack(self)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment