UNPKG

qws

Version:

An HTML5 Web Sockets Server Module

116 lines (102 loc) 3.9 kB
// Generated by CoffeeScript 1.6.3 var EventEmitter, Message, Server, crypto, os, urlParse, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; Message = require('./message').Message; EventEmitter = require('events').EventEmitter; urlParse = require('url').parse; crypto = require('crypto'); os = require('options-stream'); Server = (function(_super) { __extends(Server, _super); function Server(server, options, cb) { var _this = this; this.server = server; this.serverConfigList = []; this.addServer(options, cb); server.on('upgrade', function(req, socket) { var config, msg, path, result, _i, _len, _ref; if (result = _this._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).path; _ref = _this.serverConfigList; for (_i = 0, _len = _ref.length; _i < _len; _i++) { config = _ref[_i]; if (path === config.url) { if (result = _this._domainCheck(req, config)) { msg.errorHandle("HTTP/1.1 403 Forbidden\r\n\r\n" + result + "\r\n"); return; } msg.reset(config); return _this.emit('connect', msg); } } msg.errorHandle('HTTP/1.1 400 Bad Request\r\n\r\nurl not matched\r\n'); }); } Server.prototype.addServer = function(options, cb) { var i, origin, serverConfig, _i, _len, _ref; serverConfig = os({ url: '/ws', deflate: false, min_deflate_length: 32, origins: [], cb: cb }, options); if (serverConfig.origins.length) { _ref = serverConfig.origins; for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { origin = _ref[i]; serverConfig.origins[i] = origin.replace(/\/$/g, ''); } } return this.serverConfigList.push(serverConfig); }; Server.prototype._handShake = function(req, socket) { var head, key, sha1, sign, uinfo; uinfo = urlParse(req.url); if (uinfo.protocol && uinfo.protocol !== 'ws:') { return 'protocol not match'; } if ('websocket' !== req.headers.upgrade) { return 'upgrade not match'; } if ('13' !== req.headers['sec-websocket-version']) { return 'version not match'; } if (!req.headers['sec-websocket-key']) { return 'key missed'; } key = req.headers['sec-websocket-key']; sha1 = crypto.createHash('sha1'); sha1.update(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'); sign = sha1.digest('base64'); head = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: " + sign + "\r\nSec-WebSocket-Extensions: x-webkit-deflate-frame\r\nSec-WebSocket-Origin: " + req.headers.origin + "\r\nSec-WebSocket-Location: ws://" + (req.headers.host + req.url) + "\r\n\r\n"; socket.write(head); return false; }; Server.prototype._domainCheck = function(req, config) { var host, origin, origins, reqOrigin, _i, _len; origins = config.origins; host = urlParse(req.headers.origin).host; reqOrigin = req.headers.origin.replace(/\/$/g, ''); if (host !== req.headers.host) { for (_i = 0, _len = origins.length; _i < _len; _i++) { origin = origins[_i]; if (origin === '*' || origin === reqOrigin) { return false; } } return "Origin " + req.headers.origin + " is not allowed"; } return false; }; return Server; })(EventEmitter); exports.Server = Server;