Permalink
Browse files

Use faye-websocket for handling WebSocket transport.

  • Loading branch information...
1 parent 5d3be6e commit 0bfea2cdf739c6e0040f892754e1b8ba22fe9ebf @jcoglan jcoglan committed Jan 16, 2012
View
@@ -4,6 +4,7 @@ PATH
cramp (0.15.1)
activesupport (~> 3.0.9)
eventmachine (~> 1.0.0.beta.3)
+ faye-websocket (~> 0.3.0)
rack (~> 1.3.2)
thor (~> 0.14.6)
@@ -39,6 +40,8 @@ GEM
erubis (2.7.0)
escape_utils (0.2.3)
eventmachine (1.0.0.beta.3)
+ faye-websocket (0.3.0)
+ eventmachine (>= 0.12.0)
http_router (0.10.0)
rack (>= 1.0.0)
url_mount (~> 0.2.1)
View
@@ -12,10 +12,11 @@ Gem::Specification.new do |s|
# Not in a very distant future
# s.required_ruby_version = '>=1.9.2'
- s.add_dependency('activesupport', '~> 3.0.9')
- s.add_dependency('rack', '~> 1.3.2')
- s.add_dependency('eventmachine', '~> 1.0.0.beta.3')
- s.add_dependency('thor', '~> 0.14.6')
+ s.add_dependency('activesupport', '~> 3.0.9')
+ s.add_dependency('rack', '~> 1.3.2')
+ s.add_dependency('eventmachine', '~> 1.0.0.beta.3')
+ s.add_dependency('faye-websocket', '~> 0.3.0')
+ s.add_dependency('thor', '~> 0.14.6')
s.files = Dir['README', 'MIT-LICENSE', 'lib/**/*', 'bin/**/*']
s.has_rdoc = false
View
@@ -14,6 +14,7 @@
require 'active_support/buffered_logger'
require 'rack'
+require 'faye/websocket'
begin
require 'fiber'
View
@@ -5,7 +5,14 @@ class Action < Abstract
def initialize(env)
super
- @env['websocket.receive_callback'] = method(:_on_data_receive)
+
+ if Faye::WebSocket.websocket?(env)
+ @web_socket = Faye::WebSocket.new(env)
+ @web_socket.onmessage = lambda do |event|
+ message = event.data
+ _invoke_data_callbacks(message) if message.is_a?(String)
+ end
+ end
end
protected
@@ -74,13 +81,7 @@ def render_sse(data, options = {})
end
def render_websocket(body, *)
- if websockets_protocol_10?
- data = encode(protocol10_parser.send_text_frame(body), 'BINARY')
- else
- data = ["\x00", body, "\xFF"].map(&method(:encode)) * ''
- end
-
- @body.call(data)
+ @web_socket.send(body)
end
CHUNKED_TERM = "\r\n"
@@ -112,13 +113,5 @@ def finish
super
end
- def websockets_protocol_10?
- [7, 8, 9, 10].include?(@env['HTTP_SEC_WEBSOCKET_VERSION'].to_i)
- end
-
- def protocol10_parser
- @protocol10_parser ||= Protocol10FrameParser.new
- end
-
end
end
View
@@ -62,26 +62,8 @@ def callback_wrapper
end
end
- def _on_data_receive(data)
- websockets_protocol_10? ? _receive_protocol10_data(data) : _receive_protocol76_data(data)
- end
-
protected
- def _receive_protocol10_data(data)
- protocol10_parser.data << data
-
- messages = @protocol10_parser.process_data
- messages.each do |type, content|
- _invoke_data_callbacks(content) if type == :text
- end
- end
-
- def _receive_protocol76_data(data)
- data = data.split(/\000([^\377]*)\377/).select{|d| !d.empty? }.collect{|d| d.gsub(/^\x00|\xff$/, '') }
- data.each {|message| _invoke_data_callbacks(message) }
- end
-
def _invoke_data_callbacks(message)
self.class.on_data_callbacks.each do |callback|
callback_wrapper { send(callback, message) }
@@ -106,4 +88,4 @@ def handle_exception(exception)
end
end
-end
+end
View
@@ -5,7 +5,7 @@ class Websocket < Action
class << self
def backend=(backend)
raise "Websocket backend #{backend} is unknown" unless [:thin, :rainbows].include?(backend.to_sym)
- require "cramp/websocket/#{backend}_backend.rb"
+ Faye::WebSocket.load_adapter(backend.to_s)
end
end
@@ -1,92 +0,0 @@
-require 'base64'
-require 'digest/sha1'
-
-module Cramp
- module WebsocketExtension
- WEBSOCKET_RECEIVE_CALLBACK = 'websocket.receive_callback'.freeze
-
- def protocol_class
- @env['HTTP_SEC_WEBSOCKET_VERSION'] ? Protocol10 : Protocol76
- end
-
- def websocket?
- ['WebSocket', 'websocket'].include?(@env['HTTP_UPGRADE'])
- end
-
- def secure_websocket?
- if @env.has_key?('HTTP_X_FORWARDED_PROTO')
- @env['HTTP_X_FORWARDED_PROTO'] == 'https'
- else
- @env['HTTP_ORIGIN'] =~ /^https:/i
- end
- end
-
- def websocket_url
- scheme = secure_websocket? ? 'wss:' : 'ws:'
- @env['websocket.url'] = "#{ scheme }//#{ @env['HTTP_HOST'] }#{ @env['REQUEST_URI'] }"
- end
-
- class WebSocketHandler
- def initialize(env, websocket_url, body = nil)
- @env = env
- @websocket_url = websocket_url
- @body = body
- end
- end
-
- class Protocol10 < WebSocketHandler
- MAGIC_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".freeze
-
- def handshake
- digest = Base64.encode64(Digest::SHA1.digest("#{@env['HTTP_SEC_WEBSOCKET_KEY']}#{MAGIC_GUID}")).chomp
-
- upgrade = "HTTP/1.1 101 Switching Protocols\r\n"
- upgrade << "Upgrade: websocket\r\n"
- upgrade << "Connection: Upgrade\r\n"
- upgrade << "Sec-WebSocket-Accept: #{digest}\r\n\r\n"
- upgrade
- end
- end
-
- class Protocol76 < WebSocketHandler
- def handshake
- key1 = @env['HTTP_SEC_WEBSOCKET_KEY1']
- value1 = number_from_key(key1) / spaces_in_key(key1)
-
- key2 = @env['HTTP_SEC_WEBSOCKET_KEY2']
- value2 = number_from_key(key2) / spaces_in_key(key2)
-
- hash = Digest::MD5.digest(big_endian(value1) +
- big_endian(value2) +
- @body)
-
- upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
- upgrade << "Upgrade: WebSocket\r\n"
- upgrade << "Connection: Upgrade\r\n"
- upgrade << "Sec-WebSocket-Origin: #{@env['HTTP_ORIGIN']}\r\n"
- upgrade << "Sec-WebSocket-Location: #{@websocket_url}\r\n\r\n"
- upgrade << hash
- upgrade
- end
-
- private
-
- def number_from_key(key)
- key.scan(/[0-9]/).join('').to_i(10)
- end
-
- def spaces_in_key(key)
- key.scan(/ /).size
- end
-
- def big_endian(number)
- string = ''
- [24,16,8,0].each do |offset|
- string << (number >> offset & 0xFF).chr
- end
- string
- end
- end
-
- end
-end
Oops, something went wrong.

0 comments on commit 0bfea2c

Please sign in to comment.