From 67fdec20726e48ba3a934cb25bb30d47ec4a4f29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yaroslav=20De=20La=20Pe=C3=B1a=20Smirnov?= Date: Wed, 29 Nov 2017 11:44:34 +0300 Subject: Initial commit, version 0.5.3 --- node_modules/socket.io/lib/index.js | 474 ++++++++++++++++++++++++++++++++++++ 1 file changed, 474 insertions(+) create mode 100644 node_modules/socket.io/lib/index.js (limited to 'node_modules/socket.io/lib/index.js') diff --git a/node_modules/socket.io/lib/index.js b/node_modules/socket.io/lib/index.js new file mode 100644 index 0000000..e16133a --- /dev/null +++ b/node_modules/socket.io/lib/index.js @@ -0,0 +1,474 @@ + +/** + * Module dependencies. + */ + +var http = require('http'); +var read = require('fs').readFileSync; +var path = require('path'); +var exists = require('fs').existsSync; +var engine = require('engine.io'); +var clientVersion = require('socket.io-client/package.json').version; +var Client = require('./client'); +var Emitter = require('events').EventEmitter; +var Namespace = require('./namespace'); +var Adapter = require('socket.io-adapter'); +var parser = require('socket.io-parser'); +var debug = require('debug')('socket.io:server'); +var url = require('url'); + +/** + * Module exports. + */ + +module.exports = Server; + +/** + * Socket.IO client source. + */ + +var clientSource = undefined; +var clientSourceMap = undefined; + +/** + * Server constructor. + * + * @param {http.Server|Number|Object} srv http server, port or options + * @param {Object} [opts] + * @api public + */ + +function Server(srv, opts){ + if (!(this instanceof Server)) return new Server(srv, opts); + if ('object' == typeof srv && srv instanceof Object && !srv.listen) { + opts = srv; + srv = null; + } + opts = opts || {}; + this.nsps = {}; + this.path(opts.path || '/socket.io'); + this.serveClient(false !== opts.serveClient); + this.parser = opts.parser || parser; + this.encoder = new this.parser.Encoder(); + this.adapter(opts.adapter || Adapter); + this.origins(opts.origins || '*:*'); + this.sockets = this.of('/'); + if (srv) this.attach(srv, opts); +} + +/** + * Server request verification function, that checks for allowed origins + * + * @param {http.IncomingMessage} req request + * @param {Function} fn callback to be called with the result: `fn(err, success)` + */ + +Server.prototype.checkRequest = function(req, fn) { + var origin = req.headers.origin || req.headers.referer; + + // file:// URLs produce a null Origin which can't be authorized via echo-back + if ('null' == origin || null == origin) origin = '*'; + + if (!!origin && typeof(this._origins) == 'function') return this._origins(origin, fn); + if (this._origins.indexOf('*:*') !== -1) return fn(null, true); + if (origin) { + try { + var parts = url.parse(origin); + var defaultPort = 'https:' == parts.protocol ? 443 : 80; + parts.port = parts.port != null + ? parts.port + : defaultPort; + var ok = + ~this._origins.indexOf(parts.hostname + ':' + parts.port) || + ~this._origins.indexOf(parts.hostname + ':*') || + ~this._origins.indexOf('*:' + parts.port); + return fn(null, !!ok); + } catch (ex) { + } + } + fn(null, false); +}; + +/** + * Sets/gets whether client code is being served. + * + * @param {Boolean} v whether to serve client code + * @return {Server|Boolean} self when setting or value when getting + * @api public + */ + +Server.prototype.serveClient = function(v){ + if (!arguments.length) return this._serveClient; + this._serveClient = v; + var resolvePath = function(file){ + var filepath = path.resolve(__dirname, './../../', file); + if (exists(filepath)) { + return filepath; + } + return require.resolve(file); + }; + if (v && !clientSource) { + clientSource = read(resolvePath( 'socket.io-client/dist/socket.io.js'), 'utf-8'); + try { + clientSourceMap = read(resolvePath( 'socket.io-client/dist/socket.io.js.map'), 'utf-8'); + } catch(err) { + debug('could not load sourcemap file'); + } + } + return this; +}; + +/** + * Old settings for backwards compatibility + */ + +var oldSettings = { + "transports": "transports", + "heartbeat timeout": "pingTimeout", + "heartbeat interval": "pingInterval", + "destroy buffer size": "maxHttpBufferSize" +}; + +/** + * Backwards compatibility. + * + * @api public + */ + +Server.prototype.set = function(key, val){ + if ('authorization' == key && val) { + this.use(function(socket, next) { + val(socket.request, function(err, authorized) { + if (err) return next(new Error(err)); + if (!authorized) return next(new Error('Not authorized')); + next(); + }); + }); + } else if ('origins' == key && val) { + this.origins(val); + } else if ('resource' == key) { + this.path(val); + } else if (oldSettings[key] && this.eio[oldSettings[key]]) { + this.eio[oldSettings[key]] = val; + } else { + console.error('Option %s is not valid. Please refer to the README.', key); + } + + return this; +}; + +/** + * Sets the client serving path. + * + * @param {String} v pathname + * @return {Server|String} self when setting or value when getting + * @api public + */ + +Server.prototype.path = function(v){ + if (!arguments.length) return this._path; + this._path = v.replace(/\/$/, ''); + return this; +}; + +/** + * Sets the adapter for rooms. + * + * @param {Adapter} v pathname + * @return {Server|Adapter} self when setting or value when getting + * @api public + */ + +Server.prototype.adapter = function(v){ + if (!arguments.length) return this._adapter; + this._adapter = v; + for (var i in this.nsps) { + if (this.nsps.hasOwnProperty(i)) { + this.nsps[i].initAdapter(); + } + } + return this; +}; + +/** + * Sets the allowed origins for requests. + * + * @param {String} v origins + * @return {Server|Adapter} self when setting or value when getting + * @api public + */ + +Server.prototype.origins = function(v){ + if (!arguments.length) return this._origins; + + this._origins = v; + return this; +}; + +/** + * Attaches socket.io to a server or port. + * + * @param {http.Server|Number} server or port + * @param {Object} options passed to engine.io + * @return {Server} self + * @api public + */ + +Server.prototype.listen = +Server.prototype.attach = function(srv, opts){ + if ('function' == typeof srv) { + var msg = 'You are trying to attach socket.io to an express ' + + 'request handler function. Please pass a http.Server instance.'; + throw new Error(msg); + } + + // handle a port as a string + if (Number(srv) == srv) { + srv = Number(srv); + } + + if ('number' == typeof srv) { + debug('creating http server and binding to %d', srv); + var port = srv; + srv = http.Server(function(req, res){ + res.writeHead(404); + res.end(); + }); + srv.listen(port); + + } + + // set engine.io path to `/socket.io` + opts = opts || {}; + opts.path = opts.path || this.path(); + // set origins verification + opts.allowRequest = opts.allowRequest || this.checkRequest.bind(this); + + if (this.sockets.fns.length > 0) { + this.initEngine(srv, opts); + return this; + } + + var self = this; + var connectPacket = { type: parser.CONNECT, nsp: '/' }; + this.encoder.encode(connectPacket, function (encodedPacket){ + // the CONNECT packet will be merged with Engine.IO handshake, + // to reduce the number of round trips + opts.initialPacket = encodedPacket; + + self.initEngine(srv, opts); + }); + return this; +}; + +/** + * Initialize engine + * + * @param {Object} options passed to engine.io + * @api private + */ + +Server.prototype.initEngine = function(srv, opts){ + // initialize engine + debug('creating engine.io instance with opts %j', opts); + this.eio = engine.attach(srv, opts); + + // attach static file serving + if (this._serveClient) this.attachServe(srv); + + // Export http server + this.httpServer = srv; + + // bind to engine events + this.bind(this.eio); +}; + +/** + * Attaches the static file serving. + * + * @param {Function|http.Server} srv http server + * @api private + */ + +Server.prototype.attachServe = function(srv){ + debug('attaching client serving req handler'); + var url = this._path + '/socket.io.js'; + var urlMap = this._path + '/socket.io.js.map'; + var evs = srv.listeners('request').slice(0); + var self = this; + srv.removeAllListeners('request'); + srv.on('request', function(req, res) { + if (0 === req.url.indexOf(urlMap)) { + self.serveMap(req, res); + } else if (0 === req.url.indexOf(url)) { + self.serve(req, res); + } else { + for (var i = 0; i < evs.length; i++) { + evs[i].call(srv, req, res); + } + } + }); +}; + +/** + * Handles a request serving `/socket.io.js` + * + * @param {http.Request} req + * @param {http.Response} res + * @api private + */ + +Server.prototype.serve = function(req, res){ + // Per the standard, ETags must be quoted: + // https://tools.ietf.org/html/rfc7232#section-2.3 + var expectedEtag = '"' + clientVersion + '"'; + + var etag = req.headers['if-none-match']; + if (etag) { + if (expectedEtag == etag) { + debug('serve client 304'); + res.writeHead(304); + res.end(); + return; + } + } + + debug('serve client source'); + res.setHeader('Content-Type', 'application/javascript'); + res.setHeader('ETag', expectedEtag); + res.writeHead(200); + res.end(clientSource); +}; + +/** + * Handles a request serving `/socket.io.js.map` + * + * @param {http.Request} req + * @param {http.Response} res + * @api private + */ + +Server.prototype.serveMap = function(req, res){ + // Per the standard, ETags must be quoted: + // https://tools.ietf.org/html/rfc7232#section-2.3 + var expectedEtag = '"' + clientVersion + '"'; + + var etag = req.headers['if-none-match']; + if (etag) { + if (expectedEtag == etag) { + debug('serve client 304'); + res.writeHead(304); + res.end(); + return; + } + } + + debug('serve client sourcemap'); + res.setHeader('Content-Type', 'application/json'); + res.setHeader('ETag', expectedEtag); + res.writeHead(200); + res.end(clientSourceMap); +}; + +/** + * Binds socket.io to an engine.io instance. + * + * @param {engine.Server} engine engine.io (or compatible) server + * @return {Server} self + * @api public + */ + +Server.prototype.bind = function(engine){ + this.engine = engine; + this.engine.on('connection', this.onconnection.bind(this)); + return this; +}; + +/** + * Called with each incoming transport connection. + * + * @param {engine.Socket} conn + * @return {Server} self + * @api public + */ + +Server.prototype.onconnection = function(conn){ + debug('incoming connection with id %s', conn.id); + var client = new Client(this, conn); + client.connect('/'); + return this; +}; + +/** + * Looks up a namespace. + * + * @param {String} name nsp name + * @param {Function} [fn] optional, nsp `connection` ev handler + * @api public + */ + +Server.prototype.of = function(name, fn){ + if (String(name)[0] !== '/') name = '/' + name; + + var nsp = this.nsps[name]; + if (!nsp) { + debug('initializing namespace %s', name); + nsp = new Namespace(this, name); + this.nsps[name] = nsp; + } + if (fn) nsp.on('connect', fn); + return nsp; +}; + +/** + * Closes server connection + * + * @param {Function} [fn] optional, called as `fn([err])` on error OR all conns closed + * @api public + */ + +Server.prototype.close = function(fn){ + for (var id in this.nsps['/'].sockets) { + if (this.nsps['/'].sockets.hasOwnProperty(id)) { + this.nsps['/'].sockets[id].onclose(); + } + } + + this.engine.close(); + + if (this.httpServer) { + this.httpServer.close(fn); + } else { + fn && fn(); + } +}; + +/** + * Expose main namespace (/). + */ + +var emitterMethods = Object.keys(Emitter.prototype).filter(function(key){ + return typeof Emitter.prototype[key] === 'function'; +}); + +emitterMethods.concat(['to', 'in', 'use', 'send', 'write', 'clients', 'compress']).forEach(function(fn){ + Server.prototype[fn] = function(){ + return this.sockets[fn].apply(this.sockets, arguments); + }; +}); + +Namespace.flags.forEach(function(flag){ + Object.defineProperty(Server.prototype, flag, { + get: function() { + this.sockets.flags = this.sockets.flags || {}; + this.sockets.flags[flag] = true; + return this; + } + }); +}); + +/** + * BC with `io.listen` + */ + +Server.listen = Server; -- cgit v1.2.3