UNPKG

qws

Version:

An HTML5 Web Sockets Server Module

86 lines (70 loc) 2.77 kB
{Message} = require './message' {EventEmitter} = require 'events' {parse: urlParse} = require 'url' crypto = require 'crypto' os = require 'options-stream' class Server extends EventEmitter constructor : (@server, options, cb) -> @serverConfigList = [] @addServer options, cb { server } = @ server.on 'upgrade', (req, socket) => if result = @_handShake req, socket socket.end "HTTP/1.1 400 Bad Request\r\n\r\n#{result}\r\n" return msg = new Message socket, {deflate:false} msg.request = req {path} = urlParse req.url for config in @serverConfigList if path is config.url if result = @_domainCheck req, config msg.errorHandle "HTTP/1.1 403 Forbidden\r\n\r\n#{result}\r\n" return msg.reset config return @emit 'connect', msg msg.errorHandle 'HTTP/1.1 400 Bad Request\r\n\r\nurl not matched\r\n' return addServer : (options, cb) -> serverConfig = os { url : '/ws' deflate : false min_deflate_length : 32 origins : [] cb : cb }, options if serverConfig.origins.length serverConfig.origins[i] = origin.replace /\/$/g, '' for origin, i in serverConfig.origins @serverConfigList.push serverConfig _handShake : (req, socket) -> uinfo = urlParse req.url return 'protocol not match' if uinfo.protocol and uinfo.protocol isnt 'ws:' return 'upgrade not match' unless 'websocket' is req.headers.upgrade return 'version not match' unless '13' is req.headers['sec-websocket-version'] return 'key missed' unless req.headers['sec-websocket-key'] protocol = req.headers['sec-websocket-protocol'] # sign key = req.headers['sec-websocket-key'] sha1 = crypto.createHash 'sha1' sha1.update key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' sign = sha1.digest 'base64' # response header head = """ HTTP/1.1 101 Switching Protocols\r Upgrade: websocket\r Connection: Upgrade\r Sec-WebSocket-Accept: #{sign}\r Sec-WebSocket-Origin: #{req.headers.origin}\r\n""" head += "Sec-WebSocket-Protocol: #{protocol}\r\n" if protocol head += "Sec-WebSocket-Location: ws://#{req.headers.host + req.url}\r\n\r\n" socket.write head false _domainCheck : (req, config) -> origins = config.origins {host} = urlParse req.headers.origin reqOrigin = req.headers.origin.replace /\/$/g, '' if host isnt req.headers.host for origin in origins return false if origin is '*' or origin is reqOrigin return "Origin #{req.headers.origin} is not allowed" false exports.Server = Server