{"version":3,"sources":["jsdelivr-header.js","/npm/portluck@0.4.4/server.js"],"names":[],"mappings":"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","file":"/npm/portluck@0.4.4/server.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.37.0.\n * Original file: /npm/portluck@0.4.4/server.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","var net = require('net'),\n    http = require('http'),\n    https = require('https'),\n    util = require('util'),\n    DelimiterStream = require('delimiterstream'),\n    bufferConcatLimit = require('buffer-concat-limit'),\n    WebSocket = require('ws'),\n    debug, parentEmit;\n\n//v0.10.x doesn't have debuglog\nif (typeof util.debuglog === 'function') {\n    debug = util.debuglog('portluck');\n} else {\n    //from net.js in v0.10.x tag\n    if (process.env.NODE_DEBUG && /portluck/.test(process.env.NODE_DEBUG)) {\n        debug = util.log;\n    } else {\n        debug = function() {};\n    }\n}\n\nvar _CR_ = \"\\r\".charCodeAt(0),\n    _LF_ = \"\\n\".charCodeAt(0),\n    _SPACE_ = \" \".charCodeAt(0),\n    //all the first letters of possible HTTP methods (from http_parser.c line 923)\n    _METHODSCHARS_ = [\n        \"C\".charCodeAt(0),\n        \"D\".charCodeAt(0),\n        \"G\".charCodeAt(0),\n        \"H\".charCodeAt(0),\n        \"L\".charCodeAt(0),\n        \"O\".charCodeAt(0),\n        \"P\".charCodeAt(0),\n        \"S\".charCodeAt(0),\n        \"T\".charCodeAt(0),\n        \"U\".charCodeAt(0)\n    ],\n    _P_METHODSCHARS_ = [\n        \"A\".charCodeAt(0),\n        \"O\".charCodeAt(0),\n        \"U\".charCodeAt(0)\n    ],\n    _PURGE_ = new Buffer(\"PURGE\"),\n    _PUT_ = new Buffer(\"PUT\"),\n    _METHODS_ = [\n        new Buffer(\"CONNECT\"),\n        new Buffer(\"DELETE\"),\n        new Buffer(\"GET\"),\n        new Buffer(\"HEAD\"),\n        new Buffer(\"LOCK\"),\n        new Buffer(\"OPTIONS\"),\n        new Buffer(\"PATCH\"),\n        new Buffer(\"POST\"),\n        _PURGE_,\n        _PUT_,\n        new Buffer(\"SEARCH\"),\n        new Buffer(\"TRACE\"),\n        new Buffer(\"UNLOCK\")\n    ],\n    _HTTP_ = [\n        \"H\".charCodeAt(0),\n        \"T\".charCodeAt(0),\n        \"T\".charCodeAt(0),\n        \"P\".charCodeAt(0),\n        \"/\".charCodeAt(0)\n    ],\n    _TLSRECORD_ = 0x16,\n    _TLS_SSL3_ = 0x03,\n    _TLS_CLIENT_HELLO_ = 0x01,\n    _SSL2HEADERBYTE_ = 0x80,\n    TYPE_ERROR = -1, TYPE_HTTP = 1, TYPE_RAW = 2, TYPE_TLS = 3, TYPE_PENDING = 4,\n    EMPTY_STRING = '',\n    i;\n\nfunction ResponseWriter(client) {\n    this._client = client;\n    if (!this._client) {\n        throw new TypeError('Invalid client sent to ResponseWriter');\n    }\n    this._encoding = undefined;\n    this.ended = false;\n    this._pendingWrite = false;\n    this._endAfterWrite = false;\n}\nResponseWriter.prototype.setDefaultEncoding = function(encoding) {\n    if (encoding === 'binary' || encoding === 'buffer') {\n        this._encoding = 'buffer';\n        return;\n    }\n    if (encoding === null){\n        encoding = undefined;\n    }\n    this._encoding = encoding;\n};\nResponseWriter.prototype.write = function(message) {\n    this._pendingWrite = false;\n    if (this.ended) {\n        throw new Error('write called after ResponseWriter ended');\n    }\n    if (this._client instanceof WebSocket) {\n        var options = {binary: false};\n        if (this._encoding === undefined) {\n            options.binary = (message instanceof Buffer);\n        } else if (this._encoding === 'buffer') {\n            options.binary = true;\n        }\n        this._client.send(message, options);\n    } else {\n        this._client.write(message, this._encoding);\n    }\n    if (this._endAfterWrite) {\n        this.end();\n    }\n};\nResponseWriter.prototype.writeHead = function(code, message, headers) {\n    if (this._client instanceof http.ServerResponse && !this._client.headersSent) {\n        this._client.writeHead(code, message, headers);\n    }\n};\nResponseWriter.prototype.setHeader = function(name, value) {\n    if (this._client instanceof http.ServerResponse && !this._client.headersSent) {\n        this._client.setHeader(name, value);\n    }\n};\nResponseWriter.prototype.removeHeader = function(name) {\n    if (this._client instanceof http.ServerResponse && !this._client.headersSent) {\n        this._client.removeHeader(name);\n    }\n};\nResponseWriter.prototype.getHeader = function(name) {\n    if (this._client instanceof http.ServerResponse && !this._client.headersSent) {\n        return this._client.getHeader(name);\n    }\n};\nResponseWriter.prototype.close = function() {\n    if (this._client instanceof WebSocket) {\n        this._client.close();\n        return;\n    }\n    this.ended = true;\n    if (this._client.ended) {\n        return;\n    }\n    this._client.end();\n};\nResponseWriter.prototype._defaultEnd = function() {\n    if (this._pendingWrite) {\n        return;\n    }\n    return this.end();\n};\nResponseWriter.prototype.end = function(message) {\n    if (this._client.ended || (this._client instanceof WebSocket && this._client.readyState !== WebSocket.OPEN)) {\n        this.ended = true;\n        return;\n    }\n    if (message !== undefined) {\n        this.write(message);\n    }\n    //automatically close http responses\n    if (this._client instanceof http.ServerResponse) {\n        this.ended = true;\n        this._client.end();\n    }\n};\nResponseWriter.prototype.done = ResponseWriter.prototype.end;\n\nResponseWriter.prototype.endAfterWrite = function() {\n    this._pendingWrite = true;\n    this._endAfterWrite = true;\n};\nResponseWriter.prototype.doneAfterWrite = ResponseWriter.prototype.endAfterWrite;\nResponseWriter.prototype.destroy = function() {\n    if (this._client instanceof WebSocket) {\n        this._client.terminate();\n        return;\n    }\n    this.ended = true;\n    this._client.destroy();\n};\n\nfunction validateHTTPMethod(data, index, len) {\n    var i = index || 0,\n        l = len || data.length,\n        methodMatch = null,\n        methodMatchIndex = 0,\n        methodMatchLen = 0;\n    for (; i < l; i++) {\n        //ignore these characters and continue looping\n        if (data[i] !== _CR_ && data[i] !== _LF_ && data[i] !== _SPACE_) {\n            break;\n        }\n    }\n    //if we already hit the end then we don't have enough data\n    if (i >= l) {\n        return -2;\n    }\n\n    //if you trust benchmarks then switch is faster than indexOf: http://jsperf.com/switch-vs-array/8\n    switch (data[i]) {\n        case _METHODSCHARS_[0]: //C\n            methodMatch = _METHODS_[0];\n            methodMatchIndex = 1;\n            break;\n        case _METHODSCHARS_[1]: //D\n            methodMatch = _METHODS_[1];\n            methodMatchIndex = 1;\n            break;\n        case _METHODSCHARS_[2]: //G\n            methodMatch = _METHODS_[2];\n            methodMatchIndex = 1;\n            break;\n        case _METHODSCHARS_[3]: //H\n            methodMatch = _METHODS_[3];\n            methodMatchIndex = 1;\n            break;\n        case _METHODSCHARS_[4]: //L\n            methodMatch = _METHODS_[4];\n            methodMatchIndex = 1;\n            break;\n        case _METHODSCHARS_[5]: //O\n            methodMatch = _METHODS_[5];\n            methodMatchIndex = 1;\n            break;\n        case _METHODSCHARS_[6]: //P\n            switch (data[i + 1]) {\n                case _P_METHODSCHARS_[0]: //A\n                    methodMatch = _METHODS_[6];\n                    //we just verified the next char so skip it\n                    i++;\n                    methodMatchIndex = 2;\n                    break;\n                case _P_METHODSCHARS_[1]: //O\n                    methodMatch = _METHODS_[7];\n                    //we just verified the next char so skip it\n                    i++;\n                    methodMatchIndex = 2;\n                    break;\n                case _P_METHODSCHARS_[2]: //U\n                    switch (data[i + 2]) {\n                        case _PURGE_[2]:\n                            methodMatch = _METHODS_[8];\n                            break;\n                        case _PUT_[2]:\n                            methodMatch = _METHODS_[9];\n                            break;\n                        case undefined: //not enough data\n                            return -2;\n                        default:\n                            break;\n                    }\n                    //we just verified the next and next next char so skip them\n                    i += 2;\n                    methodMatchIndex = 3;\n                    break;\n                case undefined: //not enough data\n                    return -2;\n                default:\n                    //no match so we don't set methodMatch which will cause us to return 0 after the outer switch\n                    break;\n            }\n            break;\n        case _METHODSCHARS_[7]: //S\n            methodMatch = _METHODS_[10];\n            methodMatchIndex = 1;\n            break;\n        case _METHODSCHARS_[8]: //T\n            methodMatch = _METHODS_[11];\n            methodMatchIndex = 1;\n            break;\n        case _METHODSCHARS_[9]: //U\n            methodMatch = _METHODS_[12];\n            methodMatchIndex = 1;\n            break;\n    }\n    if (methodMatch === null) {\n        return 0;\n    }\n    //skipping next char since we just matched it above\n    i++;\n    //finishing the loop down here so we don't have to check methodMatch !=== undefined at the top every char\n    methodMatchLen = methodMatch.length;\n    for (; i < l && methodMatchIndex < methodMatchLen; i++, methodMatchIndex++) {\n        //if the method name does not match, invalid method name, return\n        if (methodMatch[methodMatchIndex] !== data[i]) {\n            return 0;\n        }\n    }\n    //if we don't have at least 8 bytes left (for (space)/(space)HTTP/) then we don't have enough data\n    if (i + 8 >= l) {\n        return -2;\n    }\n    //the next character after METHOD is space then a URL\n    if (data[i] !== _SPACE_) {\n        return 0;\n    }\n    i++;\n    //we've found a valid command, now look for HTTP/\n    for (; (i + 4) < l; i++) {\n        //todo: is there a better way to do this?\n        if (data[i] === _HTTP_[0] && data[i + 1] === _HTTP_[1] && data[i + 2] === _HTTP_[2] && data[i + 3] === _HTTP_[3] && data[i + 4] === _HTTP_[4]) {\n            return 1;\n        }\n        //we didn't find HTTP since we already got to a control character\n        if (data[i] <= 19) {\n            return 0;\n        }\n        //todo: we should verify the url characters are valid (like http_parser.c's normal_url_char)\n    }\n    //apache has a max header length of 8kb so if they already sent more than 8kb stop trying to think its HTTP and give up\n    if (l > 8192) {\n        return 0;\n    }\n    //we must've not found a newline character so we don't have enough data\n    return -2;\n}\n\n//via http://security.stackexchange.com/questions/34780/checking-client-hello-for-https-classification\n//also see node_crypto_clienthello.cc ParseRecordHeader\nfunction validateTLSHello(data, index, len) {\n    var i = index || 0,\n        l = len || data.length;\n    if (data[i] !== _TLSRECORD_) {\n        return 0;\n    }\n    if (i + 5 >= l) {\n        return -2;\n    }\n    if (data[i + 1] === _TLS_SSL3_) {\n        if (data[i + 5] !== _TLS_CLIENT_HELLO_) {\n            //invalid message type but still tls\n            return -1;\n        }\n        return 1;\n    }\n    return 0;\n}\n\n//via http://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format\n//also see node_crypto_clienthello.cc ParseRecordHeader\nfunction validateSSLv2(data, index, len) {\n    var i = index || 0,\n        l = len || data.length;\n    if ((data[i] & _SSL2HEADERBYTE_) === 0) {\n        return 0;\n    }\n    if (i + 2 >= l) {\n        return -2;\n    }\n    if (data[i + 2] === _TLS_CLIENT_HELLO_) {\n        return 1;\n    }\n    //some clients are sending 80 03 00 04 00 00 00 14 00 00 00 02 00 00 00 04 00 00 03 e8 00 00 00 07 00 a0 00 00 80 03 00 09 00 00 00 08 00 00 00 00 00 9f 00 00\n    //which I'm not sure what protocol except that it looks like SSLv2 and we should reject it\n    if (data[i + 1] === 0x03 && data[i + 3] === 0x04) {\n        return -1;\n    }\n    return 0;\n}\n\nfunction ParseError(code) {\n    this.message = 'Parse Error';\n    this.code = code;\n}\nutil.inherits(ParseError, Error);\n\nfunction ReadError(code) {\n    this.message = 'Read Error';\n    this.code = code;\n}\nutil.inherits(ReadError, Error);\n\nfunction typeDetermined(server, socket, type) {\n    debug('typeDetermined', type);\n    if (type === TYPE_ERROR) {\n        server.emit('clientError', new ParseError('HPE_UNKNOWN'), socket);\n        return;\n    }\n    //set the timeout now to the value the user wants\n    socket.setTimeout(server.timeout);\n    switch (type) {\n        case TYPE_HTTP:\n            httpConnectionListener(server, socket);\n            break;\n        case TYPE_TLS:\n            httpsConnectionListener(server, socket);\n            break;\n        case TYPE_RAW:\n            rawConnectionListener(server, socket);\n            break;\n        case TYPE_PENDING:\n            pendingConnectionListener(server, socket);\n            break;\n        default:\n            throw new Error('Unknown type determined for socket: ' + type);\n    }\n    //need to call ondata for v0.10.x\n    if (typeof socket.ondata === 'function') {\n        var pendingData = socket.read();\n        socket.ondata(pendingData, 0, pendingData.length);\n    }\n}\n\nfunction setTimeoutForSocket(server, socket) {\n    return setTimeout(function() {\n        if (!socket.readable || !socket.writable || socket.ended) {\n            if (!socket.ended) {\n                socket.end();\n            }\n            return;\n        }\n        socket.emit('_resolveTimeout');\n    }, 1000);\n}\n\nfunction onConnection(server, socket) {\n    var resolvedType = 0,\n        receivedData, timeout;\n\n    //todo: move these all to named functions somehow\n    function triggerClientError(err) {\n        debug('socket error', err);\n        clearTimeout(timeout);\n        timeout = null;\n        server.emit('clientError', err, socket);\n    }\n    function onEnd() {\n        debug('socket end');\n        clearTimeout(timeout);\n        timeout = null;\n        if (!socket.ended) {\n            socket.end();\n        }\n    }\n    function onClose() {\n        debug('socket close');\n        triggerClientError(new ReadError('ECONNRESET'));\n    }\n    function onTimeout() {\n        debug('socket timeout');\n        server.emit('timeout', socket);\n    }\n    function onResolveTimeout() {\n        if (server.rawFallback) {\n            //stop listening for close now since were passing it off to pendingConnectionListener\n            //keep listening to end since that means the client sent a FIN\n            socket.removeListener('close', onClose);\n            debug('timeout waiting for first byte');\n            typeDetermined(server, socket, TYPE_PENDING);\n        } else {\n            debug('timeout waiting for first byte but rawFallback is false. Setting socket timeout');\n            //set the timeout now to the value the user wants so it'll close if no more data is sent\n            socket.setTimeout(server.timeout);\n            socket.once('timeout', onTimeout);\n        }\n        timeout = null;\n    }\n\n    //we're handling our own timeouts for now\n    socket.setTimeout(0);\n\n    //wait at most 1 seconds to determine type, otherwise emit connect and wait till we are told how to handle data\n    timeout = setTimeoutForSocket(server, socket);\n\n    function onReadable() {\n        if (resolvedType !== 0) {\n            throw new Error('onReadable called after we already determined type. Please file a bug.');\n        }\n        debug('socket onReadable');\n        var data = socket.read(),\n            i = 0,\n            len = 0,\n            res = 0;\n        if (data === null) {\n            debug('Received null data from socket.read(). Ignoring...');\n            return;\n        }\n        //ignore the limit for the first packet since node already allocated that memory and delimiter stream will handle limiting the chunks\n        if (receivedData === undefined) {\n            receivedData = data;\n        } else {\n            receivedData = bufferConcatLimit(receivedData, data, server.messageLimit);\n        }\n        //data is a buffer\n        len = receivedData.length;\n        //this is assuming that ALL of these methods start with a different first character\n        if ((res = validateHTTPMethod(receivedData, i, len)) !== 0) {\n            resolvedType = TYPE_HTTP;\n            debug('Determined HTTP');\n        } else if ((res = validateTLSHello(receivedData, i, len)) !== 0) {\n            resolvedType = TYPE_TLS;\n            debug('Determined TLS');\n        } else if ((res = validateSSLv2(receivedData, i, len)) !== 0) {\n            resolvedType = TYPE_ERROR;\n            debug('Determined SSLv2');\n        } else if (server.rawFallback) {\n            resolvedType = TYPE_RAW;\n            debug('Determined RAW');\n        } else {\n            resolvedType = TYPE_ERROR;\n            debug('Determined ERROR');\n        }\n        //result of -2 means we don't know the type yet but we sorta matched so keep waiting and restart the waiting timeout\n        if (res === -2) {\n            if (timeout !== null) {\n                clearTimeout(timeout);\n                //restart the timeout to wait another second before marking as pending\n                timeout = setTimeoutForSocket(server, socket);\n            }\n            debug('Not enough data for a resolution, waiting for more data');\n            resolvedType = 0;\n        } else if (res === -1) {\n            resolvedType = TYPE_ERROR;\n            debug('Error with determined type. Changing resolved type to error');\n        }\n        if (resolvedType !== 0) {\n            //clean up everything since we resolved the type\n            clearTimeout(timeout);\n            timeout = null;\n            socket.removeListener('readable', onReadable);\n            socket.removeListener('end', onEnd);\n            socket.removeListener('error', triggerClientError);\n            socket.removeListener('close', onClose);\n            socket.removeListener('_resolveTimeout', onResolveTimeout);\n            socket.removeListener('timeout', onTimeout);\n\n            socket.emit('_resolvedType', resolvedType);\n\n            //we're no longer listening to readable anymore\n            socket._readableState.readableListening = false;\n            socket._readableState.reading = false;\n\n            //put all the data we received back on the top of the stream\n            //the tls socket will only work if we already have data in the stream\n            socket.unshift(receivedData);\n\n            //Because of Node Bug #9355, we won't get an error when there's a tls error\n            typeDetermined(server, socket, resolvedType);\n        }\n    }\n    socket.on('readable', onReadable);\n    //since the http server is setup with allowHalfOpen, we need to end when we get a FIN\n    socket.once('end', onEnd);\n    socket.once('error', triggerClientError);\n    socket.once('close', onClose);\n    socket.once('_resolveTimeout', onResolveTimeout);\n}\n\n//todo: figure out a way to not store state on the socket\nfunction emitConnect(server, socket, writer) {\n    if (socket._connectEmitted || socket._disconnectEmitted || socket.ended) {\n        return;\n    }\n    parentEmit.call(server, 'clientConnect', writer, socket);\n    socket._connectEmitted = true;\n}\nfunction emitDisconnect(server, socket) {\n    if (!socket._connectEmitted || socket._disconnectEmitted) {\n        return;\n    }\n    parentEmit.call(server, 'clientDisconnect', socket);\n    socket._disconnectEmitted = true;\n}\n\nfunction onNewRawClient(server, socket, writer) {\n    emitConnect(server, socket, writer);\n    socket.once('close', function() {\n        //clean up any listeners on data since we already sent that we're disconnected\n        socket.removeAllListeners('data');\n        socket.removeAllListeners('end');\n        socket.removeAllListeners('timeout');\n        emitDisconnect(server, socket);\n    });\n    socket.once('error', function(err) {\n        parentEmit.call(server, 'clientError', err, socket);\n        writer.destroy();\n    });\n    socket.once('timeout', function() {\n        server.emit('timeout', socket);\n    });\n    //'end' listener needs to be added in listenForDelimiterData\n}\n//for http we need to listen for close on the socket and NOT the listener >_<\nfunction onNewHTTPClient(server, listener, socket, writer) {\n    emitConnect(server, socket, writer);\n    //built-in http automatically handles closing on 'end'\n    //built-in http automatically fires timeout so we can ignore that here\n    socket.once('close', function() {\n        //clean up any listeners on data since we already sent that we're disconnected\n        listener.removeAllListeners('data');\n        listener.removeAllListeners('end');\n        emitDisconnect(server, socket);\n    });\n    listener.once('error', function(err) {\n        parentEmit.call(server, 'clientError', err, socket);\n        writer.destroy();\n    });\n    if (!server.explicitEnd) {\n        listener.once('end', function() {\n            process.nextTick(function() {\n                writer._defaultEnd();\n            });\n        });\n    }\n}\nfunction onNewWSClient(server, listener, socket, writer, incomingMessage) {\n    //ws resets the timeout to 0 for some reason but we want to keep it what the user wants\n    //built-in http server automatically fires timeout so we can ignore that here\n    socket.setTimeout(server.timeout);\n\n    emitConnect(server, socket, writer);\n    listener.once('close', function() {\n        //clean up any listeners on data since we already sent that we're disconnected\n        listener.removeAllListeners('message');\n        emitDisconnect(server, socket);\n    });\n    listener.once('error', function(err) {\n        parentEmit.call(server, 'clientError', err, socket);\n        writer.destroy();\n    });\n    listener.on('message', function(data) {\n        if (data.length === 0) {\n            return;\n        }\n        parentEmit.call(server, 'message', data, writer, socket, incomingMessage);\n    });\n}\n\nfunction httpConnectionListener(server, socket) {\n    server._httpConnectionListener(socket);\n}\n\nfunction httpsConnectionListener(server, socket) {\n    server._httpsConnectionListener(socket);\n}\n\nfunction rawConnectionListener(server, socket) {\n    var writer = new ResponseWriter(socket);\n    onNewRawClient(server, socket, writer);\n    listenForDelimiterData(server, socket, socket, writer);\n    //if we get a FIN, end the writer on the next tick\n    socket.once('end', function() {\n        process.nextTick(function() {\n            writer.close();\n        });\n    });\n}\n\nfunction pendingConnectionListener(server, socket) {\n    var writer = new ResponseWriter(socket);\n    emitConnect(server, socket, writer);\n    function onClose() {\n        emitDisconnect(server, socket);\n    }\n    function onEnd() {\n        if (!socket.ended) {\n            socket.end();\n        }\n    }\n    function onTimeout() {\n        server.emit('timeout', socket);\n    }\n    socket.once('timeout', onTimeout);\n    socket.once('close', onClose);\n    socket.once('end', onEnd);\n    socket.once('_resolvedType', function() {\n        socket.removeListener('end', onEnd);\n        socket.removeListener('close', onClose);\n        socket.removeListener('timeout', onTimeout);\n    });\n}\n\nfunction listenForDelimiterData(server, listener, socket, writer) {\n    //todo: allow passing in custom delimiter\n    var delimiterWrap = DelimiterStream.wrap({dataLimit: server.messageLimit}, function(data) {\n        parentEmit.call(server, 'message', data, writer, socket, listener);\n    });\n    listener.on('data', delimiterWrap);\n    listener.once('end', function() {\n        //send null to flush the rest of the data left buffered\n        delimiterWrap(null);\n    });\n}\n\nfunction onUpgrade(req, socket, upgradeHead) {\n    var server = this;\n    this._wss.handleUpgrade(req, socket, upgradeHead, function(client) {\n        var writer = new ResponseWriter(client);\n        onNewWSClient(server, client, socket, writer, req);\n    });\n}\n\nfunction destroySocket(socket) {\n    socket.destroy();\n}\n\nfunction stripProtocolFromOrigin(origin) {\n    var index = 0;\n    if (origin[4] === ':') { //http://\n        index = 7;\n    } else if (origin[5] === ':') { // https://\n        index = 8\n    } else {\n        index = origin.indexOf('://') + 3;\n        //-1 + 3 = 2 (means not found)\n        if (index === 2) {\n            index = 0;\n        }\n    }\n    return origin.substr(index);\n}\n\nfunction addRequiredListeners(server) {\n    server.addListener('clientError', function(err, socket) {\n        debug('clientError', err);\n        socket.destroy();\n    });\n\n    //we need to *have* a listener for 'upgrade' so it emits the event in http.Server\n    //we won't be letting this event actually fire though in our emit\n    server.addListener('upgrade', onUpgrade);\n}\n\nfunction Portluck(messageListener, opts) {\n    var options = opts || {},\n        httpsEnabled = true;\n    if (arguments.length === 1 && typeof messageListener === 'object') {\n        options = messageListener;\n        messageListener = null;\n    }\n    //if they don't want https don't force them\n    if (!options.pfx && !options.key && !options.cert) {\n        httpsEnabled = false;\n    }\n    if (httpsEnabled) {\n        https.Server.call(this, options);\n\n        if (this._events === undefined || typeof this._events.connection !== 'function') {\n            throw new Error('Assert: missing https connection listener. Please file a bug!');\n        }\n        //ghetto hack to get the https connection listener since its not exposed\n        this._httpsConnectionListener = this._events.connection;\n    } else {\n        debug('disabling https server since no key/cert sent');\n        //calling http.Server since we don't inherit from it actually just makes a new server and returns it...\n        //http.Server.call(this);\n        net.Server.call(this);\n        this._httpsConnectionListener = destroySocket;\n    }\n    this.httpAllowHalfOpen = false;\n    //set this manually since https.Server doesn't set it\n    this.allowHalfOpen = true;\n\n    //this one is exposed, or we'd have to use this._events.secureConnection\n    this._httpConnectionListener = http._connectionListener;\n\n    //remove node's connection listner\n    this.removeAllListeners('connection');\n    this.removeAllListeners('secureConnection');\n\n    //we're using our own listener to clientError\n    this.removeAllListeners('clientError');\n\n    addRequiredListeners(this);\n\n    //\"start\" the websocket server\n    this._wss = new WebSocket.Server({noServer: true});\n\n    if (messageListener) {\n        this.addListener('message', messageListener);\n    }\n\n    if (options.rawFallback !== undefined) {\n        this.rawFallback = options.rawFallback;\n    }\n    if (options.timeout !== undefined) {\n        if (typeof options.timeout !== 'number') {\n            throw new TypeError('options.timeout must be a number');\n        }\n        debug('Setting timeout to ' + options.timeout);\n        this.timeout = options.timeout;\n    } else {\n        //2 minutes is the default timeout\n        this.timeout = 120 * 1000;\n    }\n    if (options.allowOrigin !== undefined) {\n        this.setValidOrigin(options.allowOrigin);\n    }\n    if (options.allowUndefinedOrigin !== undefined) {\n        this.allowUndefinedOrigin = options.allowUndefinedOrigin;\n    }\n    this.explicitEnd = options.explicitEnd || options.explicitDone || false;\n    if (options.messageLimit >= 0) {\n        if (typeof options.messageLimit !== 'number') {\n            throw new TypeError('options.messageLimit must be a number');\n        }\n        debug('Setting message limit to ' + options.messageLimit);\n        this.messageLimit = options.messageLimit;\n    } else {\n        this.messageLimit = 0; //default is unlimited\n    }\n}\nutil.inherits(Portluck, https.Server);\nparentEmit = https.Server.prototype.emit;\nparentRemoveAllListeners = https.Server.prototype.removeAllListeners;\n\n//should we fallback to a raw socket?\nPortluck.prototype.rawFallback = true;\n\nPortluck.prototype.validateOrigin = function() {\n    return true;\n};\n\nPortluck.prototype.setValidOrigin = function(origin) {\n    var originMatch = origin,\n        convertToRegExp = false;\n    if (typeof originMatch === 'string') {\n        //optimize for *.example.com\n        if (originMatch.indexOf('*.') === 0) {\n            convertToRegExp = true;\n            originMatch = '(?:[a-z0-9_\\\\-]+.)?' + originMatch.substr(2);\n        }\n        //check for :* to allow any ports\n        if (originMatch.indexOf(':*') === originMatch.length - 2) {\n            convertToRegExp = true;\n            //if its 443/80 the port usually isn't included so we're making this match optional\n            originMatch = originMatch.replace(/:\\*$/g, '(?:\\\\:[0-9]+)?');\n        }\n        //now just replace all *'s\n        if (originMatch.indexOf('*') !== -1) {\n            convertToRegExp = true;\n            originMatch = originMatch.replace(/\\*/g, '(?:[a-z0-9_\\\\-]+)');\n        }\n        if (convertToRegExp) {\n            originMatch = new RegExp(originMatch + '$', 'i');\n        } else {\n            originMatch = originMatch.toLowerCase();\n        }\n    }\n    if (originMatch instanceof RegExp) {\n        this.validateOrigin = function(o) {\n            var origin = o ? stripProtocolFromOrigin(o) : EMPTY_STRING;\n            return originMatch.test(origin);\n        };\n    } else {\n        this.validateOrigin = function(o) {\n            var origin = o ? stripProtocolFromOrigin(o) : EMPTY_STRING;\n            //only lowercase if we have to\n            return (origin === originMatch) || (origin.toLowerCase() === originMatch);\n        };\n    }\n};\n\nPortluck.prototype.allowUndefinedOrigin = true;\n\n// origin headers ARE NOT checked before calling invalidMethodHandler\n// they can be manually checked here by calling this.validateOrigin(msg.headers.origin)\nPortluck.prototype.invalidMethodHandler = function(msg, resp) {\n    //405 means \"Method Not Allowed\"\n    resp.setHeader('Allow', 'POST,PUT');\n    resp.writeHead(405);\n    resp.end('Allowed methods are POST or PUT.');\n};\n\n//override a bunch of the events in emit so they don't bubble up\nPortluck.prototype.emit = function(type) {\n    var msg, resp, writer, socket;\n    switch (type) {\n        case 'connection': //socket connection from net.Server\n            onConnection(this, arguments[1]);\n            break;\n        case 'secureConnection': //tls connection from tls.Server\n            this._httpConnectionListener(arguments[1]);\n            break;\n        case 'request': //msg, resp\n            //take over the default HTTP \"request\" event so we can publish message\n            msg = arguments[1];\n            resp = arguments[2];\n            debug('received request event', msg.method, msg.httpVersion);\n\n            resp.setHeader('Connection', 'close');\n            resp.setHeader('Content-Type', 'text/plain');\n            resp.removeHeader('Transfer-Encoding');\n\n            //if the method is GET then do not check origin headers\n            if (msg.method !== 'POST' && msg.method !== 'PUT' && msg.method !== 'OPTIONS') {\n                this.invalidMethodHandler(msg, resp);\n                break;\n            }\n\n            //call validateOrigin even if they didn't send one since we might require an origin\n            if ((!this.allowUndefinedOrigin || msg.headers.origin != null) && !this.validateOrigin(msg.headers.origin)) {\n                debug('invalid origin header sent', msg.headers.origin);\n                resp.writeHead(400);\n                resp.end();\n                break;\n            } else if (msg.headers.origin != null) { //only send back approved origin headers if they sent an origin\n                resp.setHeader('Access-Control-Allow-Origin', msg.headers.origin);\n                resp.setHeader('Access-Control-Allow-Methods', 'POST, PUT');\n                resp.setHeader('Access-Control-Allow-Credentials', 'true');\n                //allow some common headers (http://www.w3.org/TR/cors/#simple-header are automatically allowed)\n                resp.setHeader('Access-Control-Allow-Headers', 'DNT,User-Agent,X-Requested-With,Content-Type');\n            }\n\n            //respond to OPTIONS requests for pre-flight access controls\n            if (msg.method === 'OPTIONS') {\n                resp.writeHead(200);\n                resp.end();\n                break;\n            }\n\n            resp.statusCode = 200; //default the statusCode to 200\n            writer = new ResponseWriter(resp);\n            onNewHTTPClient(this, msg, msg.socket, writer);\n            //for a post/put the request can just be treated like a socket\n            listenForDelimiterData(this, msg, msg.socket, writer);\n            break;\n        case 'upgrade': //req, socket, upgradeHead\n            msg = arguments[1];\n            socket = arguments[2];\n            if (!this.validateOrigin(msg.headers.origin)) {\n                debug('invalid origin header sent', msg.headers.origin);\n                socket.end();\n                return;\n            }\n            onUpgrade.call(this, msg, socket, arguments[3]);\n            break;\n        case 'clientError':\n            return parentEmit.call(this, arguments[0], arguments[1], arguments[2]);\n        case 'timeout': //socket\n            socket = arguments[1];\n            //if we get a timeout then immediately end socket\n            if (!socket.ended) {\n                debug('socket timed out and were ending');\n                socket.destroy();\n            }\n            break;\n        default:\n            return parentEmit.apply(this, Array.prototype.slice.call(arguments, 0));\n    }\n    //we handled it so return true\n    return true;\n};\nPortluck.prototype.removeAllListeners = function(type) {\n    var result = parentRemoveAllListeners.apply(this, Array.prototype.slice.call(arguments, 0));\n    if (arguments.length === 0) {\n        addRequiredListeners(this);\n    }\n    return result;\n};\n\nexports.Server = Portluck;\n"]}