Skip to content

Instantly share code, notes, and snippets.

@testingbot
Created July 24, 2012 20:23
Show Gist options
  • Save testingbot/3172407 to your computer and use it in GitHub Desktop.
Save testingbot/3172407 to your computer and use it in GitHub Desktop.
websockify.rb with SSL
--- a/other/websocket.rb
+++ b/other/websocket.rb
@@ -13,11 +13,12 @@ require 'stringio'
require 'digest/md5'
require 'digest/sha1'
require 'base64'
+require 'openssl'
class EClose < Exception
end
-class WebSocketServer < GServer
+class WebSocketServer
@@Buffer_size = 65536
#
@@ -43,12 +44,28 @@ Sec-WebSocket-Accept: %s\r
port = opts['listen_port']
host = opts['listen_host'] || GServer::DEFAULT_HOST
- super(port, host)
-
+ server = TCPServer.new(port)
+ sslContext = OpenSSL::SSL::SSLContext.new
+ sslContext.cert = OpenSSL::X509::Certificate.new(File.open("/Users/jochen/websockify/other/server.crt"))
+ sslContext.key = OpenSSL::PKey::RSA.new(File.open("/Users/jochen/websockify/other/server.key"))
+ sslServer = OpenSSL::SSL::SSLServer.new(server, sslContext)
+
@@client_id = 0 # Track client number total on class
@verbose = opts['verbose']
@opts = opts
+
+
+ loop do
+ connection = sslServer.accept
+ Thread.new {
+ begin
+ serve(connection)
+ rescue
+ $stderr.puts $!
+ end
+ }
+ end
end
def serve(io)
@@ -237,7 +254,7 @@ Sec-WebSocket-Accept: %s\r
while t[:send_parts].length > 0
buf = t[:send_parts].shift
- sent = t[:client].send(buf, 0)
+ sent = t[:client].syswrite(buf)
if sent == buf.length
traffic "<"
@@ -257,7 +274,7 @@ Sec-WebSocket-Accept: %s\r
closed = false
bufs = []
- buf = t[:client].recv(@@Buffer_size)
+ buf = t[:client].sysread(@@Buffer_size)
if buf.length == 0
return bufs, "Client closed abrubtly"
@@ -286,10 +303,10 @@ Sec-WebSocket-Accept: %s\r
end
end
else
- if buf[0...2] == "\xff\x00":
+ if buf[0...2] == "\xff\x00"
closed = "Client sent orderly close frame"
break
- elsif buf[0...2] == "\x00\xff":
+ elsif buf[0...2] == "\x00\xff"
buf = buf[2...buf.length]
continue # No-op frame
elsif buf.count("\xff") == 0
@@ -308,7 +325,7 @@ Sec-WebSocket-Accept: %s\r
bufs << frame['payload']
- if frame['left'] > 0:
+ if frame['left'] > 0
buf = buf[-frame['left']...buf.length]
else
buf = ''
@@ -328,10 +345,10 @@ Sec-WebSocket-Accept: %s\r
end
buf, lenh, lent = encode_hybi(msg, opcode=0x08, base64=false)
- t[:client].send(buf, 0)
+ t[:client].syswrite(buf)
elsif t[:version] == "hixie-76"
buf = "\xff\x00"
- t[:client].send(buf, 0)
+ t[:client].syswrite(buf)
end
end
@@ -343,8 +360,16 @@ Sec-WebSocket-Accept: %s\r
if !IO.select([sock], nil, nil, 3)
raise EClose, "ignoring socket not ready"
end
+
+ handshake = ""
+ while ((lineIn = sock.gets) && !lineIn[0..1].empty?)
+ #$stdout.puts "=> " + lineIn
+ handshake += lineIn.chomp + "|"
+ if lineIn[0..1].chomp.empty?
+ break
+ end
+ end
- handshake = sock.recv(1024, Socket::MSG_PEEK)
#msg "Handshake [#{handshake.inspect}]"
if handshake == ""
@@ -353,19 +378,21 @@ Sec-WebSocket-Accept: %s\r
stype = "Plain non-SSL (ws://)"
scheme = "ws"
retsock = sock
- sock.recv(1024)
+ # sock.sysread(1024)
end
h = t[:headers] = {}
- hlines = handshake.split("\r\n")
+ hlines = handshake.split("|")
req_split = hlines.shift.match(/^(\w+) (\/[^\s]*) HTTP\/1\.1$/)
t[:path] = req_split[2].strip
hlines.each do |hline|
break if hline == ""
hsplit = hline.match(/^([^:]+):\s*(.+)$/)
- h[hsplit[1].strip.downcase] = hsplit[2]
+ if !hsplit.nil?
+ h[hsplit[1].strip.downcase] = hsplit[2]
+ end
end
- #puts "Headers: #{h.inspect}"
+ puts "Headers: #{h.inspect}"
unless h.has_key?('upgrade') &&
h['upgrade'].downcase == 'websocket'
@@ -445,7 +472,7 @@ Sec-WebSocket-Accept: %s\r
if t[:path] then msg "Path: '%s'" % [t[:path]] end
#puts "sending reponse #{response.inspect}"
- retsock.send(response, 0)
+ retsock.syswrite(response)
# Return the WebSocket socket which may be SSL wrapped
return retsock
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment