Permalink
Browse files

Implement a draft76 WebSocket handler for Ruby.

  • Loading branch information...
1 parent 937aab3 commit a83009636297887fc183bd06692f429bce2dd347 @jcoglan jcoglan committed Jul 31, 2010
Showing with 66 additions and 7 deletions.
  1. +66 −7 lib/thin_extensions.rb
View
@@ -1,5 +1,5 @@
# WebSocket extensions for Thin
-# Taken from the Cramp project
+# Based on code from the Cramp project
# http://github.com/lifo/cramp
# Copyright (c) 2009-2010 Pratik Naik
@@ -23,6 +23,8 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+require 'digest/md5'
+
class Thin::Connection
def receive_data(data)
trace { data }
@@ -61,12 +63,69 @@ def websocket_url
end
def websocket_upgrade_data
- upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
- upgrade << "Upgrade: WebSocket\r\n"
- upgrade << "Connection: Upgrade\r\n"
- upgrade << "WebSocket-Origin: #{@env['HTTP_ORIGIN']}\r\n"
- upgrade << "WebSocket-Location: #{websocket_url}\r\n\r\n"
- upgrade
+ handler = if @env['HTTP_SEC_WEBSOCKET_KEY1'] and @env['HTTP_SEC_WEBSOCKET_KEY2']
+ Protocol76
+ else
+ Protocol75
+ end
+ handler.new(self).handshake
+ end
+
+ class WebSocketHandler
+ def initialize(request)
+ @request = request
+ end
+ end
+
+ class Protocol75 < WebSocketHandler
+ def handshake
+ upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
+ upgrade << "Upgrade: WebSocket\r\n"
+ upgrade << "Connection: Upgrade\r\n"
+ upgrade << "WebSocket-Origin: #{@request.env['HTTP_ORIGIN']}\r\n"
+ upgrade << "WebSocket-Location: #{@request.websocket_url}\r\n\r\n"
+ upgrade
+ end
+ end
+
+ class Protocol76 < WebSocketHandler
+ def handshake
+ key1 = @request.env['HTTP_SEC_WEBSOCKET_KEY1']
+ value1 = number_from_key(key1) / spaces_in_key(key1)
+
+ key2 = @request.env['HTTP_SEC_WEBSOCKET_KEY2']
+ value2 = number_from_key(key2) / spaces_in_key(key2)
+
+ hash = Digest::MD5.digest(big_endian(value1) +
+ big_endian(value2) +
+ @request.body.read)
+
+ 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: #{@request.env['HTTP_ORIGIN']}\r\n"
+ upgrade << "Sec-WebSocket-Location: #{@request.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

0 comments on commit a830096

Please sign in to comment.