12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494 |
- /*!
- * faye-websocket@0.11.1 - Standards-compliant WebSocket server and client
- * Copyright (c) 2019, James Coglan (MIT)
- * https://github.com/faye/faye-websocket-node
- *
- * License for websocket-driver@0.7.0:
- *
- * # The MIT License
- *
- * Copyright (c) 2010-2017 James Coglan
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the 'Software'), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * License for http-parser-js@0.5.0:
- *
- * Copyright (c) 2015 Tim Caswell (https://github.com/creationix) and other
- * contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Some files from the tests folder are from joyent/node and mscedex/io.js, a
- * fork of nodejs/io.js:
- *
- * - tests/iojs/test-http-parser-durability.js
- *
- * This file is from
- * https://github.com/mscdex/io.js/blob/js-http-parser/test/pummel/test-http-parser-durability.js
- * with modifications by Jan Schär (jscissr).
- *
- * """ Copyright io.js contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE. """
- *
- * - tests/fixtures/* tests/parallel/* tests/testpy/* tests/common.js
- * tests/test.py tests/utils.py
- *
- * These files are from https://github.com/nodejs/node with changes by Jan Schär
- * (jscissr).
- *
- * Node.js is licensed for use as follows:
- *
- * """ Copyright Node.js contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE. """
- *
- * This license applies to parts of Node.js originating from the
- * https://github.com/joyent/node repository:
- *
- * """ Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE. """
- *
- * License for websocket-extensions@0.1.3:
- *
- * # The MIT License
- *
- * Copyright (c) 2014-2017 James Coglan
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the 'Software'), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
- var __node_modules__ = [
- [/* 0 */ 'faye-websocket', '/lib/faye/websocket.js', function(exports, module, __filename, __dirname, __meta) {
- // API references:
- //
- // * https://html.spec.whatwg.org/multipage/comms.html#network
- // * https://dom.spec.whatwg.org/#interface-eventtarget
- // * https://dom.spec.whatwg.org/#interface-event
-
- var util = require('util'),
- driver = __node_require__(1 /* 'websocket-driver' */),
- API = __node_require__(23 /* './websocket/api' */);
-
- var WebSocket = function(request, socket, body, protocols, options) {
- options = options || {};
-
- this._stream = socket;
- this._driver = driver.http(request, {maxLength: options.maxLength, protocols: protocols});
-
- var self = this;
- if (!this._stream || !this._stream.writable) return;
- if (!this._stream.readable) return this._stream.end();
-
- var catchup = function() { self._stream.removeListener('data', catchup) };
- this._stream.on('data', catchup);
-
- API.call(this, options);
-
- process.nextTick(function() {
- self._driver.start();
- self._driver.io.write(body);
- });
- };
- util.inherits(WebSocket, API);
-
- WebSocket.isWebSocket = function(request) {
- return driver.isWebSocket(request);
- };
-
- WebSocket.validateOptions = function(options, validKeys) {
- driver.validateOptions(options, validKeys);
- };
-
- WebSocket.WebSocket = WebSocket;
- WebSocket.Client = __node_require__(26 /* './websocket/client' */);
- WebSocket.EventSource = __node_require__(27 /* './eventsource' */);
-
- module.exports = WebSocket;
- }],
- [/* 1 */ 'websocket-driver', '/lib/websocket/driver.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- // Protocol references:
- //
- // * http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75
- // * http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
- // * http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
-
- var Base = __node_require__(2 /* './driver/base' */),
- Client = __node_require__(6 /* './driver/client' */),
- Server = __node_require__(20 /* './driver/server' */);
-
- var Driver = {
- client: function(url, options) {
- options = options || {};
- if (options.masking === undefined) options.masking = true;
- return new Client(url, options);
- },
-
- server: function(options) {
- options = options || {};
- if (options.requireMasking === undefined) options.requireMasking = true;
- return new Server(options);
- },
-
- http: function() {
- return Server.http.apply(Server, arguments);
- },
-
- isSecureRequest: function(request) {
- return Server.isSecureRequest(request);
- },
-
- isWebSocket: function(request) {
- if (request.method !== 'GET') return false;
-
- var connection = request.headers.connection || '',
- upgrade = request.headers.upgrade || '';
-
- return request.method === 'GET' &&
- connection.toLowerCase().split(/ *, */).indexOf('upgrade') >= 0 &&
- upgrade.toLowerCase() === 'websocket';
- },
-
- validateOptions: function(options, validKeys) {
- Base.validateOptions(options, validKeys);
- }
- };
-
- module.exports = Driver;
- }],
- [/* 2 */ 'websocket-driver', '/lib/websocket/driver/base.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var Emitter = require('events').EventEmitter,
- util = require('util'),
- streams = __node_require__(3 /* '../streams' */),
- Headers = __node_require__(4 /* './headers' */),
- Reader = __node_require__(5 /* './stream_reader' */);
-
- var Base = function(request, url, options) {
- Emitter.call(this);
- Base.validateOptions(options || {}, ['maxLength', 'masking', 'requireMasking', 'protocols']);
-
- this._request = request;
- this._reader = new Reader();
- this._options = options || {};
- this._maxLength = this._options.maxLength || this.MAX_LENGTH;
- this._headers = new Headers();
- this.__queue = [];
- this.readyState = 0;
- this.url = url;
-
- this.io = new streams.IO(this);
- this.messages = new streams.Messages(this);
- this._bindEventListeners();
- };
- util.inherits(Base, Emitter);
-
- Base.validateOptions = function(options, validKeys) {
- for (var key in options) {
- if (validKeys.indexOf(key) < 0)
- throw new Error('Unrecognized option: ' + key);
- }
- };
-
- var instance = {
- // This is 64MB, small enough for an average VPS to handle without
- // crashing from process out of memory
- MAX_LENGTH: 0x3ffffff,
-
- STATES: ['connecting', 'open', 'closing', 'closed'],
-
- _bindEventListeners: function() {
- var self = this;
-
- // Protocol errors are informational and do not have to be handled
- this.messages.on('error', function() {});
-
- this.on('message', function(event) {
- var messages = self.messages;
- if (messages.readable) messages.emit('data', event.data);
- });
-
- this.on('error', function(error) {
- var messages = self.messages;
- if (messages.readable) messages.emit('error', error);
- });
-
- this.on('close', function() {
- var messages = self.messages;
- if (!messages.readable) return;
- messages.readable = messages.writable = false;
- messages.emit('end');
- });
- },
-
- getState: function() {
- return this.STATES[this.readyState] || null;
- },
-
- addExtension: function(extension) {
- return false;
- },
-
- setHeader: function(name, value) {
- if (this.readyState > 0) return false;
- this._headers.set(name, value);
- return true;
- },
-
- start: function() {
- if (this.readyState !== 0) return false;
- var response = this._handshakeResponse();
- if (!response) return false;
- this._write(response);
- if (this._stage !== -1) this._open();
- return true;
- },
-
- text: function(message) {
- return this.frame(message);
- },
-
- binary: function(message) {
- return false;
- },
-
- ping: function() {
- return false;
- },
-
- pong: function() {
- return false;
- },
-
- close: function(reason, code) {
- if (this.readyState !== 1) return false;
- this.readyState = 3;
- this.emit('close', new Base.CloseEvent(null, null));
- return true;
- },
-
- _open: function() {
- this.readyState = 1;
- this.__queue.forEach(function(args) { this.frame.apply(this, args) }, this);
- this.__queue = [];
- this.emit('open', new Base.OpenEvent());
- },
-
- _queue: function(message) {
- this.__queue.push(message);
- return true;
- },
-
- _write: function(chunk) {
- var io = this.io;
- if (io.readable) io.emit('data', chunk);
- }
- };
-
- for (var key in instance)
- Base.prototype[key] = instance[key];
-
-
- Base.ConnectEvent = function() {};
-
- Base.OpenEvent = function() {};
-
- Base.CloseEvent = function(code, reason) {
- this.code = code;
- this.reason = reason;
- };
-
- Base.MessageEvent = function(data) {
- this.data = data;
- };
-
- Base.PingEvent = function(data) {
- this.data = data;
- };
-
- Base.PongEvent = function(data) {
- this.data = data;
- };
-
- module.exports = Base;
- }],
- [/* 3 */ 'websocket-driver', '/lib/websocket/streams.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- /**
-
- Streams in a WebSocket connection
- ---------------------------------
-
- We model a WebSocket as two duplex streams: one stream is for the wire protocol
- over an I/O socket, and the other is for incoming/outgoing messages.
-
-
- +----------+ +---------+ +----------+
- [1] write(chunk) -->| ~~~~~~~~ +----->| parse() +----->| ~~~~~~~~ +--> emit('data') [2]
- | | +----+----+ | |
- | | | | |
- | IO | | [5] | Messages |
- | | V | |
- | | +---------+ | |
- [4] emit('data') <--+ ~~~~~~~~ |<-----+ frame() |<-----+ ~~~~~~~~ |<-- write(chunk) [3]
- +----------+ +---------+ +----------+
-
-
- Message transfer in each direction is simple: IO receives a byte stream [1] and
- sends this stream for parsing. The parser will periodically emit a complete
- message text on the Messages stream [2]. Similarly, when messages are written
- to the Messages stream [3], they are framed using the WebSocket wire format and
- emitted via IO [4].
-
- There is a feedback loop via [5] since some input from [1] will be things like
- ping, pong and close frames. In these cases the protocol responds by emitting
- responses directly back to [4] rather than emitting messages via [2].
-
- For the purposes of flow control, we consider the sources of each Readable
- stream to be as follows:
-
- * [2] receives input from [1]
- * [4] receives input from [1] and [3]
-
- The classes below express the relationships described above without prescribing
- anything about how parse() and frame() work, other than assuming they emit
- 'data' events to the IO and Messages streams. They will work with any protocol
- driver having these two methods.
- **/
-
-
- var Stream = require('stream').Stream,
- util = require('util');
-
-
- var IO = function(driver) {
- this.readable = this.writable = true;
- this._paused = false;
- this._driver = driver;
- };
- util.inherits(IO, Stream);
-
- // The IO pause() and resume() methods will be called when the socket we are
- // piping to gets backed up and drains. Since IO output [4] comes from IO input
- // [1] and Messages input [3], we need to tell both of those to return false
- // from write() when this stream is paused.
-
- IO.prototype.pause = function() {
- this._paused = true;
- this._driver.messages._paused = true;
- };
-
- IO.prototype.resume = function() {
- this._paused = false;
- this.emit('drain');
-
- var messages = this._driver.messages;
- messages._paused = false;
- messages.emit('drain');
- };
-
- // When we receive input from a socket, send it to the parser and tell the
- // source whether to back off.
- IO.prototype.write = function(chunk) {
- if (!this.writable) return false;
- this._driver.parse(chunk);
- return !this._paused;
- };
-
- // The IO end() method will be called when the socket piping into it emits
- // 'close' or 'end', i.e. the socket is closed. In this situation the Messages
- // stream will not emit any more data so we emit 'end'.
- IO.prototype.end = function(chunk) {
- if (!this.writable) return;
- if (chunk !== undefined) this.write(chunk);
- this.writable = false;
-
- var messages = this._driver.messages;
- if (messages.readable) {
- messages.readable = messages.writable = false;
- messages.emit('end');
- }
- };
-
- IO.prototype.destroy = function() {
- this.end();
- };
-
-
- var Messages = function(driver) {
- this.readable = this.writable = true;
- this._paused = false;
- this._driver = driver;
- };
- util.inherits(Messages, Stream);
-
- // The Messages pause() and resume() methods will be called when the app that's
- // processing the messages gets backed up and drains. If we're emitting
- // messages too fast we should tell the source to slow down. Message output [2]
- // comes from IO input [1].
-
- Messages.prototype.pause = function() {
- this._driver.io._paused = true;
- };
-
- Messages.prototype.resume = function() {
- this._driver.io._paused = false;
- this._driver.io.emit('drain');
- };
-
- // When we receive messages from the user, send them to the formatter and tell
- // the source whether to back off.
- Messages.prototype.write = function(message) {
- if (!this.writable) return false;
- if (typeof message === 'string') this._driver.text(message);
- else this._driver.binary(message);
- return !this._paused;
- };
-
- // The Messages end() method will be called when a stream piping into it emits
- // 'end'. Many streams may be piped into the WebSocket and one of them ending
- // does not mean the whole socket is done, so just process the input and move
- // on leaving the socket open.
- Messages.prototype.end = function(message) {
- if (message !== undefined) this.write(message);
- };
-
- Messages.prototype.destroy = function() {};
-
-
- exports.IO = IO;
- exports.Messages = Messages;
- }],
- [/* 4 */ 'websocket-driver', '/lib/websocket/driver/headers.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var Headers = function() {
- this.clear();
- };
-
- Headers.prototype.ALLOWED_DUPLICATES = ['set-cookie', 'set-cookie2', 'warning', 'www-authenticate'];
-
- Headers.prototype.clear = function() {
- this._sent = {};
- this._lines = [];
- };
-
- Headers.prototype.set = function(name, value) {
- if (value === undefined) return;
-
- name = this._strip(name);
- value = this._strip(value);
-
- var key = name.toLowerCase();
- if (!this._sent.hasOwnProperty(key) || this.ALLOWED_DUPLICATES.indexOf(key) >= 0) {
- this._sent[key] = true;
- this._lines.push(name + ': ' + value + '\r\n');
- }
- };
-
- Headers.prototype.toString = function() {
- return this._lines.join('');
- };
-
- Headers.prototype._strip = function(string) {
- return string.toString().replace(/^ */, '').replace(/ *$/, '');
- };
-
- module.exports = Headers;
- }],
- [/* 5 */ 'websocket-driver', '/lib/websocket/driver/stream_reader.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var StreamReader = function() {
- this._queue = [];
- this._queueSize = 0;
- this._offset = 0;
- };
-
- StreamReader.prototype.put = function(buffer) {
- if (!buffer || buffer.length === 0) return;
- if (!buffer.copy) buffer = new Buffer(buffer);
- this._queue.push(buffer);
- this._queueSize += buffer.length;
- };
-
- StreamReader.prototype.read = function(length) {
- if (length > this._queueSize) return null;
- if (length === 0) return new Buffer(0);
-
- this._queueSize -= length;
-
- var queue = this._queue,
- remain = length,
- first = queue[0],
- buffers, buffer;
-
- if (first.length >= length) {
- if (first.length === length) {
- return queue.shift();
- } else {
- buffer = first.slice(0, length);
- queue[0] = first.slice(length);
- return buffer;
- }
- }
-
- for (var i = 0, n = queue.length; i < n; i++) {
- if (remain < queue[i].length) break;
- remain -= queue[i].length;
- }
- buffers = queue.splice(0, i);
-
- if (remain > 0 && queue.length > 0) {
- buffers.push(queue[0].slice(0, remain));
- queue[0] = queue[0].slice(remain);
- }
- return this._concat(buffers, length);
- };
-
- StreamReader.prototype.eachByte = function(callback, context) {
- var buffer, n, index;
-
- while (this._queue.length > 0) {
- buffer = this._queue[0];
- n = buffer.length;
-
- while (this._offset < n) {
- index = this._offset;
- this._offset += 1;
- callback.call(context, buffer[index]);
- }
- this._offset = 0;
- this._queue.shift();
- }
- };
-
- StreamReader.prototype._concat = function(buffers, length) {
- if (Buffer.concat) return Buffer.concat(buffers, length);
-
- var buffer = new Buffer(length),
- offset = 0;
-
- for (var i = 0, n = buffers.length; i < n; i++) {
- buffers[i].copy(buffer, offset);
- offset += buffers[i].length;
- }
- return buffer;
- };
-
- module.exports = StreamReader;
- }],
- [/* 6 */ 'websocket-driver', '/lib/websocket/driver/client.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var crypto = require('crypto'),
- url = require('url'),
- util = require('util'),
- HttpParser = __node_require__(7 /* '../http_parser' */),
- Base = __node_require__(2 /* './base' */),
- Hybi = __node_require__(9 /* './hybi' */),
- Proxy = __node_require__(19 /* './proxy' */);
-
- var Client = function(_url, options) {
- this.version = 'hybi-13';
- Hybi.call(this, null, _url, options);
-
- this.readyState = -1;
- this._key = Client.generateKey();
- this._accept = Hybi.generateAccept(this._key);
- this._http = new HttpParser('response');
-
- var uri = url.parse(this.url),
- auth = uri.auth && new Buffer(uri.auth, 'utf8').toString('base64');
-
- if (this.VALID_PROTOCOLS.indexOf(uri.protocol) < 0)
- throw new Error(this.url + ' is not a valid WebSocket URL');
-
- this._pathname = (uri.pathname || '/') + (uri.search || '');
-
- this._headers.set('Host', uri.host);
- this._headers.set('Upgrade', 'websocket');
- this._headers.set('Connection', 'Upgrade');
- this._headers.set('Sec-WebSocket-Key', this._key);
- this._headers.set('Sec-WebSocket-Version', '13');
-
- if (this._protocols.length > 0)
- this._headers.set('Sec-WebSocket-Protocol', this._protocols.join(', '));
-
- if (auth)
- this._headers.set('Authorization', 'Basic ' + auth);
- };
- util.inherits(Client, Hybi);
-
- Client.generateKey = function() {
- return crypto.randomBytes(16).toString('base64');
- };
-
- var instance = {
- VALID_PROTOCOLS: ['ws:', 'wss:'],
-
- proxy: function(origin, options) {
- return new Proxy(this, origin, options);
- },
-
- start: function() {
- if (this.readyState !== -1) return false;
- this._write(this._handshakeRequest());
- this.readyState = 0;
- return true;
- },
-
- parse: function(chunk) {
- if (this.readyState === 3) return;
- if (this.readyState > 0) return Hybi.prototype.parse.call(this, chunk);
-
- this._http.parse(chunk);
- if (!this._http.isComplete()) return;
-
- this._validateHandshake();
- if (this.readyState === 3) return;
-
- this._open();
- this.parse(this._http.body);
- },
-
- _handshakeRequest: function() {
- var extensions = this._extensions.generateOffer();
- if (extensions)
- this._headers.set('Sec-WebSocket-Extensions', extensions);
-
- var start = 'GET ' + this._pathname + ' HTTP/1.1',
- headers = [start, this._headers.toString(), ''];
-
- return new Buffer(headers.join('\r\n'), 'utf8');
- },
-
- _failHandshake: function(message) {
- message = 'Error during WebSocket handshake: ' + message;
- this.readyState = 3;
- this.emit('error', new Error(message));
- this.emit('close', new Base.CloseEvent(this.ERRORS.protocol_error, message));
- },
-
- _validateHandshake: function() {
- this.statusCode = this._http.statusCode;
- this.headers = this._http.headers;
-
- if (this._http.error)
- return this._failHandshake(this._http.error.message);
-
- if (this._http.statusCode !== 101)
- return this._failHandshake('Unexpected response code: ' + this._http.statusCode);
-
- var headers = this._http.headers,
- upgrade = headers['upgrade'] || '',
- connection = headers['connection'] || '',
- accept = headers['sec-websocket-accept'] || '',
- protocol = headers['sec-websocket-protocol'] || '';
-
- if (upgrade === '')
- return this._failHandshake("'Upgrade' header is missing");
- if (upgrade.toLowerCase() !== 'websocket')
- return this._failHandshake("'Upgrade' header value is not 'WebSocket'");
-
- if (connection === '')
- return this._failHandshake("'Connection' header is missing");
- if (connection.toLowerCase() !== 'upgrade')
- return this._failHandshake("'Connection' header value is not 'Upgrade'");
-
- if (accept !== this._accept)
- return this._failHandshake('Sec-WebSocket-Accept mismatch');
-
- this.protocol = null;
-
- if (protocol !== '') {
- if (this._protocols.indexOf(protocol) < 0)
- return this._failHandshake('Sec-WebSocket-Protocol mismatch');
- else
- this.protocol = protocol;
- }
-
- try {
- this._extensions.activate(this.headers['sec-websocket-extensions']);
- } catch (e) {
- return this._failHandshake(e.message);
- }
- }
- };
-
- for (var key in instance)
- Client.prototype[key] = instance[key];
-
- module.exports = Client;
- }],
- [/* 7 */ 'websocket-driver', '/lib/websocket/http_parser.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var NodeHTTPParser = __node_require__(8 /* 'http-parser-js' */).HTTPParser;
-
- var VERSION = process.version.match(/[0-9]+/g).map(function(n) { return parseInt(n, 10) });
-
- var TYPES = {
- request: NodeHTTPParser.REQUEST || 'request',
- response: NodeHTTPParser.RESPONSE || 'response'
- };
-
- var HttpParser = function(type) {
- this._type = type;
- this._parser = new NodeHTTPParser(TYPES[type]);
- this._complete = false;
- this.headers = {};
-
- var current = null,
- self = this;
-
- this._parser.onHeaderField = function(b, start, length) {
- current = b.toString('utf8', start, start + length).toLowerCase();
- };
-
- this._parser.onHeaderValue = function(b, start, length) {
- var value = b.toString('utf8', start, start + length);
-
- if (self.headers.hasOwnProperty(current))
- self.headers[current] += ', ' + value;
- else
- self.headers[current] = value;
- };
-
- this._parser.onHeadersComplete = this._parser[NodeHTTPParser.kOnHeadersComplete] =
- function(majorVersion, minorVersion, headers, method, pathname, statusCode) {
- var info = arguments[0];
-
- if (typeof info === 'object') {
- method = info.method;
- pathname = info.url;
- statusCode = info.statusCode;
- headers = info.headers;
- }
-
- self.method = (typeof method === 'number') ? HttpParser.METHODS[method] : method;
- self.statusCode = statusCode;
- self.url = pathname;
-
- if (!headers) return;
-
- for (var i = 0, n = headers.length, key, value; i < n; i += 2) {
- key = headers[i].toLowerCase();
- value = headers[i+1];
- if (self.headers.hasOwnProperty(key))
- self.headers[key] += ', ' + value;
- else
- self.headers[key] = value;
- }
-
- self._complete = true;
- };
- };
-
- HttpParser.METHODS = {
- 0: 'DELETE',
- 1: 'GET',
- 2: 'HEAD',
- 3: 'POST',
- 4: 'PUT',
- 5: 'CONNECT',
- 6: 'OPTIONS',
- 7: 'TRACE',
- 8: 'COPY',
- 9: 'LOCK',
- 10: 'MKCOL',
- 11: 'MOVE',
- 12: 'PROPFIND',
- 13: 'PROPPATCH',
- 14: 'SEARCH',
- 15: 'UNLOCK',
- 16: 'BIND',
- 17: 'REBIND',
- 18: 'UNBIND',
- 19: 'ACL',
- 20: 'REPORT',
- 21: 'MKACTIVITY',
- 22: 'CHECKOUT',
- 23: 'MERGE',
- 24: 'M-SEARCH',
- 25: 'NOTIFY',
- 26: 'SUBSCRIBE',
- 27: 'UNSUBSCRIBE',
- 28: 'PATCH',
- 29: 'PURGE',
- 30: 'MKCALENDAR',
- 31: 'LINK',
- 32: 'UNLINK'
- };
-
- if (VERSION[0] === 0 && VERSION[1] === 12) {
- HttpParser.METHODS[16] = 'REPORT';
- HttpParser.METHODS[17] = 'MKACTIVITY';
- HttpParser.METHODS[18] = 'CHECKOUT';
- HttpParser.METHODS[19] = 'MERGE';
- HttpParser.METHODS[20] = 'M-SEARCH';
- HttpParser.METHODS[21] = 'NOTIFY';
- HttpParser.METHODS[22] = 'SUBSCRIBE';
- HttpParser.METHODS[23] = 'UNSUBSCRIBE';
- HttpParser.METHODS[24] = 'PATCH';
- HttpParser.METHODS[25] = 'PURGE';
- }
-
- HttpParser.prototype.isComplete = function() {
- return this._complete;
- };
-
- HttpParser.prototype.parse = function(chunk) {
- var consumed = this._parser.execute(chunk, 0, chunk.length);
-
- if (typeof consumed !== 'number') {
- this.error = consumed;
- this._complete = true;
- return;
- }
-
- if (VERSION[0] === 0 && VERSION[1] < 6) consumed += 1;
-
- if (this._complete)
- this.body = (consumed < chunk.length)
- ? chunk.slice(consumed)
- : new Buffer(0);
- };
-
- module.exports = HttpParser;
- }],
- [/* 8 */ 'http-parser-js', '/http-parser.js', function(exports, module, __filename, __dirname, __meta) {
- /*jshint node:true */
-
- var assert = require('assert');
-
- exports.HTTPParser = HTTPParser;
- function HTTPParser(type) {
- assert.ok(type === HTTPParser.REQUEST || type === HTTPParser.RESPONSE);
- this.type = type;
- this.state = type + '_LINE';
- this.info = {
- headers: [],
- upgrade: false
- };
- this.trailers = [];
- this.line = '';
- this.isChunked = false;
- this.connection = '';
- this.headerSize = 0; // for preventing too big headers
- this.body_bytes = null;
- this.isUserCall = false;
- this.hadError = false;
- }
- HTTPParser.encoding = 'ascii';
- HTTPParser.maxHeaderSize = 80 * 1024; // maxHeaderSize (in bytes) is configurable, but 80kb by default;
- HTTPParser.REQUEST = 'REQUEST';
- HTTPParser.RESPONSE = 'RESPONSE';
- var kOnHeaders = HTTPParser.kOnHeaders = 0;
- var kOnHeadersComplete = HTTPParser.kOnHeadersComplete = 1;
- var kOnBody = HTTPParser.kOnBody = 2;
- var kOnMessageComplete = HTTPParser.kOnMessageComplete = 3;
-
- // Some handler stubs, needed for compatibility
- HTTPParser.prototype[kOnHeaders] =
- HTTPParser.prototype[kOnHeadersComplete] =
- HTTPParser.prototype[kOnBody] =
- HTTPParser.prototype[kOnMessageComplete] = function () {};
-
- var compatMode0_12 = true;
- Object.defineProperty(HTTPParser, 'kOnExecute', {
- get: function () {
- // hack for backward compatibility
- compatMode0_12 = false;
- return 4;
- }
- });
-
- var methods = exports.methods = HTTPParser.methods = [
- 'DELETE',
- 'GET',
- 'HEAD',
- 'POST',
- 'PUT',
- 'CONNECT',
- 'OPTIONS',
- 'TRACE',
- 'COPY',
- 'LOCK',
- 'MKCOL',
- 'MOVE',
- 'PROPFIND',
- 'PROPPATCH',
- 'SEARCH',
- 'UNLOCK',
- 'BIND',
- 'REBIND',
- 'UNBIND',
- 'ACL',
- 'REPORT',
- 'MKACTIVITY',
- 'CHECKOUT',
- 'MERGE',
- 'M-SEARCH',
- 'NOTIFY',
- 'SUBSCRIBE',
- 'UNSUBSCRIBE',
- 'PATCH',
- 'PURGE',
- 'MKCALENDAR',
- 'LINK',
- 'UNLINK'
- ];
- var method_connect = methods.indexOf('CONNECT');
- HTTPParser.prototype.reinitialize = HTTPParser;
- HTTPParser.prototype.close =
- HTTPParser.prototype.pause =
- HTTPParser.prototype.resume =
- HTTPParser.prototype.free = function () {};
- HTTPParser.prototype._compatMode0_11 = false;
- HTTPParser.prototype.getAsyncId = function() { return 0; };
-
- var headerState = {
- REQUEST_LINE: true,
- RESPONSE_LINE: true,
- HEADER: true
- };
- HTTPParser.prototype.execute = function (chunk, start, length) {
- if (!(this instanceof HTTPParser)) {
- throw new TypeError('not a HTTPParser');
- }
-
- // backward compat to node < 0.11.4
- // Note: the start and length params were removed in newer version
- start = start || 0;
- length = typeof length === 'number' ? length : chunk.length;
-
- this.chunk = chunk;
- this.offset = start;
- var end = this.end = start + length;
- try {
- while (this.offset < end) {
- if (this[this.state]()) {
- break;
- }
- }
- } catch (err) {
- if (this.isUserCall) {
- throw err;
- }
- this.hadError = true;
- return err;
- }
- this.chunk = null;
- length = this.offset - start;
- if (headerState[this.state]) {
- this.headerSize += length;
- if (this.headerSize > HTTPParser.maxHeaderSize) {
- return new Error('max header size exceeded');
- }
- }
- return length;
- };
-
- var stateFinishAllowed = {
- REQUEST_LINE: true,
- RESPONSE_LINE: true,
- BODY_RAW: true
- };
- HTTPParser.prototype.finish = function () {
- if (this.hadError) {
- return;
- }
- if (!stateFinishAllowed[this.state]) {
- return new Error('invalid state for EOF');
- }
- if (this.state === 'BODY_RAW') {
- this.userCall()(this[kOnMessageComplete]());
- }
- };
-
- // These three methods are used for an internal speed optimization, and it also
- // works if theses are noops. Basically consume() asks us to read the bytes
- // ourselves, but if we don't do it we get them through execute().
- HTTPParser.prototype.consume =
- HTTPParser.prototype.unconsume =
- HTTPParser.prototype.getCurrentBuffer = function () {};
-
- //For correct error handling - see HTTPParser#execute
- //Usage: this.userCall()(userFunction('arg'));
- HTTPParser.prototype.userCall = function () {
- this.isUserCall = true;
- var self = this;
- return function (ret) {
- self.isUserCall = false;
- return ret;
- };
- };
-
- HTTPParser.prototype.nextRequest = function () {
- this.userCall()(this[kOnMessageComplete]());
- this.reinitialize(this.type);
- };
-
- HTTPParser.prototype.consumeLine = function () {
- var end = this.end,
- chunk = this.chunk;
- for (var i = this.offset; i < end; i++) {
- if (chunk[i] === 0x0a) { // \n
- var line = this.line + chunk.toString(HTTPParser.encoding, this.offset, i);
- if (line.charAt(line.length - 1) === '\r') {
- line = line.substr(0, line.length - 1);
- }
- this.line = '';
- this.offset = i + 1;
- return line;
- }
- }
- //line split over multiple chunks
- this.line += chunk.toString(HTTPParser.encoding, this.offset, this.end);
- this.offset = this.end;
- };
-
- var headerExp = /^([^: \t]+):[ \t]*((?:.*[^ \t])|)/;
- var headerContinueExp = /^[ \t]+(.*[^ \t])/;
- HTTPParser.prototype.parseHeader = function (line, headers) {
- if (line.indexOf('\r') !== -1) {
- throw parseErrorCode('HPE_LF_EXPECTED');
- }
-
- var match = headerExp.exec(line);
- var k = match && match[1];
- if (k) { // skip empty string (malformed header)
- headers.push(k);
- headers.push(match[2]);
- } else {
- var matchContinue = headerContinueExp.exec(line);
- if (matchContinue && headers.length) {
- if (headers[headers.length - 1]) {
- headers[headers.length - 1] += ' ';
- }
- headers[headers.length - 1] += matchContinue[1];
- }
- }
- };
-
- var requestExp = /^([A-Z-]+) ([^ ]+) HTTP\/(\d)\.(\d)$/;
- HTTPParser.prototype.REQUEST_LINE = function () {
- var line = this.consumeLine();
- if (!line) {
- return;
- }
- var match = requestExp.exec(line);
- if (match === null) {
- throw parseErrorCode('HPE_INVALID_CONSTANT');
- }
- this.info.method = this._compatMode0_11 ? match[1] : methods.indexOf(match[1]);
- if (this.info.method === -1) {
- throw new Error('invalid request method');
- }
- this.info.url = match[2];
- this.info.versionMajor = +match[3];
- this.info.versionMinor = +match[4];
- this.body_bytes = 0;
- this.state = 'HEADER';
- };
-
- var responseExp = /^HTTP\/(\d)\.(\d) (\d{3}) ?(.*)$/;
- HTTPParser.prototype.RESPONSE_LINE = function () {
- var line = this.consumeLine();
- if (!line) {
- return;
- }
- var match = responseExp.exec(line);
- if (match === null) {
- throw parseErrorCode('HPE_INVALID_CONSTANT');
- }
- this.info.versionMajor = +match[1];
- this.info.versionMinor = +match[2];
- var statusCode = this.info.statusCode = +match[3];
- this.info.statusMessage = match[4];
- // Implied zero length.
- if ((statusCode / 100 | 0) === 1 || statusCode === 204 || statusCode === 304) {
- this.body_bytes = 0;
- }
- this.state = 'HEADER';
- };
-
- HTTPParser.prototype.shouldKeepAlive = function () {
- if (this.info.versionMajor > 0 && this.info.versionMinor > 0) {
- if (this.connection.indexOf('close') !== -1) {
- return false;
- }
- } else if (this.connection.indexOf('keep-alive') === -1) {
- return false;
- }
- if (this.body_bytes !== null || this.isChunked) { // || skipBody
- return true;
- }
- return false;
- };
-
- HTTPParser.prototype.HEADER = function () {
- var line = this.consumeLine();
- if (line === undefined) {
- return;
- }
- var info = this.info;
- if (line) {
- this.parseHeader(line, info.headers);
- } else {
- var headers = info.headers;
- var hasContentLength = false;
- var currentContentLengthValue;
- var hasUpgradeHeader = false;
- for (var i = 0; i < headers.length; i += 2) {
- switch (headers[i].toLowerCase()) {
- case 'transfer-encoding':
- this.isChunked = headers[i + 1].toLowerCase() === 'chunked';
- break;
- case 'content-length':
- currentContentLengthValue = +headers[i + 1];
- if (hasContentLength) {
- // Fix duplicate Content-Length header with same values.
- // Throw error only if values are different.
- // Known issues:
- // https://github.com/request/request/issues/2091#issuecomment-328715113
- // https://github.com/nodejs/node/issues/6517#issuecomment-216263771
- if (currentContentLengthValue !== this.body_bytes) {
- throw parseErrorCode('HPE_UNEXPECTED_CONTENT_LENGTH');
- }
- } else {
- hasContentLength = true;
- this.body_bytes = currentContentLengthValue;
- }
- break;
- case 'connection':
- this.connection += headers[i + 1].toLowerCase();
- break;
- case 'upgrade':
- hasUpgradeHeader = true;
- break;
- }
- }
-
- // if both isChunked and hasContentLength, isChunked wins
- // This is required so the body is parsed using the chunked method, and matches
- // Chrome's behavior. We could, maybe, ignore them both (would get chunked
- // encoding into the body), and/or disable shouldKeepAlive to be more
- // resilient.
- if (this.isChunked && hasContentLength) {
- hasContentLength = false;
- this.body_bytes = null;
- }
-
- // Logic from https://github.com/nodejs/http-parser/blob/921d5585515a153fa00e411cf144280c59b41f90/http_parser.c#L1727-L1737
- // "For responses, "Upgrade: foo" and "Connection: upgrade" are
- // mandatory only when it is a 101 Switching Protocols response,
- // otherwise it is purely informational, to announce support.
- if (hasUpgradeHeader && this.connection.indexOf('upgrade') != -1) {
- info.upgrade = this.type === HTTPParser.REQUEST || info.statusCode === 101;
- } else {
- info.upgrade = info.method === method_connect;
- }
-
- info.shouldKeepAlive = this.shouldKeepAlive();
- //problem which also exists in original node: we should know skipBody before calling onHeadersComplete
- var skipBody;
- if (compatMode0_12) {
- skipBody = this.userCall()(this[kOnHeadersComplete](info));
- } else {
- skipBody = this.userCall()(this[kOnHeadersComplete](info.versionMajor,
- info.versionMinor, info.headers, info.method, info.url, info.statusCode,
- info.statusMessage, info.upgrade, info.shouldKeepAlive));
- }
- if (skipBody === 2) {
- this.nextRequest();
- return true;
- } else if (this.isChunked && !skipBody) {
- this.state = 'BODY_CHUNKHEAD';
- } else if (skipBody || this.body_bytes === 0) {
- this.nextRequest();
- // For older versions of node (v6.x and older?), that return skipBody=1 or skipBody=true,
- // need this "return true;" if it's an upgrade request.
- return info.upgrade;
- } else if (this.body_bytes === null) {
- this.state = 'BODY_RAW';
- } else {
- this.state = 'BODY_SIZED';
- }
- }
- };
-
- HTTPParser.prototype.BODY_CHUNKHEAD = function () {
- var line = this.consumeLine();
- if (line === undefined) {
- return;
- }
- this.body_bytes = parseInt(line, 16);
- if (!this.body_bytes) {
- this.state = 'BODY_CHUNKTRAILERS';
- } else {
- this.state = 'BODY_CHUNK';
- }
- };
-
- HTTPParser.prototype.BODY_CHUNK = function () {
- var length = Math.min(this.end - this.offset, this.body_bytes);
- this.userCall()(this[kOnBody](this.chunk, this.offset, length));
- this.offset += length;
- this.body_bytes -= length;
- if (!this.body_bytes) {
- this.state = 'BODY_CHUNKEMPTYLINE';
- }
- };
-
- HTTPParser.prototype.BODY_CHUNKEMPTYLINE = function () {
- var line = this.consumeLine();
- if (line === undefined) {
- return;
- }
- assert.equal(line, '');
- this.state = 'BODY_CHUNKHEAD';
- };
-
- HTTPParser.prototype.BODY_CHUNKTRAILERS = function () {
- var line = this.consumeLine();
- if (line === undefined) {
- return;
- }
- if (line) {
- this.parseHeader(line, this.trailers);
- } else {
- if (this.trailers.length) {
- this.userCall()(this[kOnHeaders](this.trailers, ''));
- }
- this.nextRequest();
- }
- };
-
- HTTPParser.prototype.BODY_RAW = function () {
- var length = this.end - this.offset;
- this.userCall()(this[kOnBody](this.chunk, this.offset, length));
- this.offset = this.end;
- };
-
- HTTPParser.prototype.BODY_SIZED = function () {
- var length = Math.min(this.end - this.offset, this.body_bytes);
- this.userCall()(this[kOnBody](this.chunk, this.offset, length));
- this.offset += length;
- this.body_bytes -= length;
- if (!this.body_bytes) {
- this.nextRequest();
- }
- };
-
- // backward compat to node < 0.11.6
- ['Headers', 'HeadersComplete', 'Body', 'MessageComplete'].forEach(function (name) {
- var k = HTTPParser['kOn' + name];
- Object.defineProperty(HTTPParser.prototype, 'on' + name, {
- get: function () {
- return this[k];
- },
- set: function (to) {
- // hack for backward compatibility
- this._compatMode0_11 = true;
- method_connect = 'CONNECT';
- return (this[k] = to);
- }
- });
- });
-
- function parseErrorCode(code) {
- var err = new Error('Parse Error');
- err.code = code;
- return err;
- }
- }],
- [/* 9 */ 'websocket-driver', '/lib/websocket/driver/hybi.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var crypto = require('crypto'),
- util = require('util'),
- Extensions = __node_require__(10 /* 'websocket-extensions' */),
- Base = __node_require__(2 /* './base' */),
- Frame = __node_require__(17 /* './hybi/frame' */),
- Message = __node_require__(18 /* './hybi/message' */);
-
- var Hybi = function(request, url, options) {
- Base.apply(this, arguments);
-
- this._extensions = new Extensions();
- this._stage = 0;
- this._masking = this._options.masking;
- this._protocols = this._options.protocols || [];
- this._requireMasking = this._options.requireMasking;
- this._pingCallbacks = {};
-
- if (typeof this._protocols === 'string')
- this._protocols = this._protocols.split(/ *, */);
-
- if (!this._request) return;
-
- var secKey = this._request.headers['sec-websocket-key'],
- protos = this._request.headers['sec-websocket-protocol'],
- version = this._request.headers['sec-websocket-version'],
- supported = this._protocols;
-
- this._headers.set('Upgrade', 'websocket');
- this._headers.set('Connection', 'Upgrade');
- this._headers.set('Sec-WebSocket-Accept', Hybi.generateAccept(secKey));
-
- if (protos !== undefined) {
- if (typeof protos === 'string') protos = protos.split(/ *, */);
- this.protocol = protos.filter(function(p) { return supported.indexOf(p) >= 0 })[0];
- if (this.protocol) this._headers.set('Sec-WebSocket-Protocol', this.protocol);
- }
-
- this.version = 'hybi-' + version;
- };
- util.inherits(Hybi, Base);
-
- Hybi.mask = function(payload, mask, offset) {
- if (!mask || mask.length === 0) return payload;
- offset = offset || 0;
-
- for (var i = 0, n = payload.length - offset; i < n; i++) {
- payload[offset + i] = payload[offset + i] ^ mask[i % 4];
- }
- return payload;
- };
-
- Hybi.generateAccept = function(key) {
- var sha1 = crypto.createHash('sha1');
- sha1.update(key + Hybi.GUID);
- return sha1.digest('base64');
- };
-
- Hybi.GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
-
- var instance = {
- FIN: 0x80,
- MASK: 0x80,
- RSV1: 0x40,
- RSV2: 0x20,
- RSV3: 0x10,
- OPCODE: 0x0F,
- LENGTH: 0x7F,
-
- OPCODES: {
- continuation: 0,
- text: 1,
- binary: 2,
- close: 8,
- ping: 9,
- pong: 10
- },
-
- OPCODE_CODES: [0, 1, 2, 8, 9, 10],
- MESSAGE_OPCODES: [0, 1, 2],
- OPENING_OPCODES: [1, 2],
-
- ERRORS: {
- normal_closure: 1000,
- going_away: 1001,
- protocol_error: 1002,
- unacceptable: 1003,
- encoding_error: 1007,
- policy_violation: 1008,
- too_large: 1009,
- extension_error: 1010,
- unexpected_condition: 1011
- },
-
- ERROR_CODES: [1000, 1001, 1002, 1003, 1007, 1008, 1009, 1010, 1011],
- DEFAULT_ERROR_CODE: 1000,
- MIN_RESERVED_ERROR: 3000,
- MAX_RESERVED_ERROR: 4999,
-
- // http://www.w3.org/International/questions/qa-forms-utf-8.en.php
- UTF8_MATCH: /^([\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})*$/,
-
- addExtension: function(extension) {
- this._extensions.add(extension);
- return true;
- },
-
- parse: function(chunk) {
- this._reader.put(chunk);
- var buffer = true;
- while (buffer) {
- switch (this._stage) {
- case 0:
- buffer = this._reader.read(1);
- if (buffer) this._parseOpcode(buffer[0]);
- break;
-
- case 1:
- buffer = this._reader.read(1);
- if (buffer) this._parseLength(buffer[0]);
- break;
-
- case 2:
- buffer = this._reader.read(this._frame.lengthBytes);
- if (buffer) this._parseExtendedLength(buffer);
- break;
-
- case 3:
- buffer = this._reader.read(4);
- if (buffer) {
- this._stage = 4;
- this._frame.maskingKey = buffer;
- }
- break;
-
- case 4:
- buffer = this._reader.read(this._frame.length);
- if (buffer) {
- this._stage = 0;
- this._emitFrame(buffer);
- }
- break;
-
- default:
- buffer = null;
- }
- }
- },
-
- text: function(message) {
- if (this.readyState > 1) return false;
- return this.frame(message, 'text');
- },
-
- binary: function(message) {
- if (this.readyState > 1) return false;
- return this.frame(message, 'binary');
- },
-
- ping: function(message, callback) {
- if (this.readyState > 1) return false;
- message = message || '';
- if (callback) this._pingCallbacks[message] = callback;
- return this.frame(message, 'ping');
- },
-
- pong: function(message) {
- if (this.readyState > 1) return false;
- message = message ||'';
- return this.frame(message, 'pong');
- },
-
- close: function(reason, code) {
- reason = reason || '';
- code = code || this.ERRORS.normal_closure;
-
- if (this.readyState <= 0) {
- this.readyState = 3;
- this.emit('close', new Base.CloseEvent(code, reason));
- return true;
- } else if (this.readyState === 1) {
- this.readyState = 2;
- this._extensions.close(function() { this.frame(reason, 'close', code) }, this);
- return true;
- } else {
- return false;
- }
- },
-
- frame: function(buffer, type, code) {
- if (this.readyState <= 0) return this._queue([buffer, type, code]);
- if (this.readyState > 2) return false;
-
- if (buffer instanceof Array) buffer = new Buffer(buffer);
- if (typeof buffer === 'number') buffer = buffer.toString();
-
- var message = new Message(),
- isText = (typeof buffer === 'string'),
- payload, copy;
-
- message.rsv1 = message.rsv2 = message.rsv3 = false;
- message.opcode = this.OPCODES[type || (isText ? 'text' : 'binary')];
-
- payload = isText ? new Buffer(buffer, 'utf8') : buffer;
-
- if (code) {
- copy = payload;
- payload = new Buffer(2 + copy.length);
- payload.writeUInt16BE(code, 0);
- copy.copy(payload, 2);
- }
- message.data = payload;
-
- var onMessageReady = function(message) {
- var frame = new Frame();
-
- frame.final = true;
- frame.rsv1 = message.rsv1;
- frame.rsv2 = message.rsv2;
- frame.rsv3 = message.rsv3;
- frame.opcode = message.opcode;
- frame.masked = !!this._masking;
- frame.length = message.data.length;
- frame.payload = message.data;
-
- if (frame.masked) frame.maskingKey = crypto.randomBytes(4);
-
- this._sendFrame(frame);
- };
-
- if (this.MESSAGE_OPCODES.indexOf(message.opcode) >= 0)
- this._extensions.processOutgoingMessage(message, function(error, message) {
- if (error) return this._fail('extension_error', error.message);
- onMessageReady.call(this, message);
- }, this);
- else
- onMessageReady.call(this, message);
-
- return true;
- },
-
- _sendFrame: function(frame) {
- var length = frame.length,
- header = (length <= 125) ? 2 : (length <= 65535 ? 4 : 10),
- offset = header + (frame.masked ? 4 : 0),
- buffer = new Buffer(offset + length),
- masked = frame.masked ? this.MASK : 0;
-
- buffer[0] = (frame.final ? this.FIN : 0) |
- (frame.rsv1 ? this.RSV1 : 0) |
- (frame.rsv2 ? this.RSV2 : 0) |
- (frame.rsv3 ? this.RSV3 : 0) |
- frame.opcode;
-
- if (length <= 125) {
- buffer[1] = masked | length;
- } else if (length <= 65535) {
- buffer[1] = masked | 126;
- buffer.writeUInt16BE(length, 2);
- } else {
- buffer[1] = masked | 127;
- buffer.writeUInt32BE(Math.floor(length / 0x100000000), 2);
- buffer.writeUInt32BE(length % 0x100000000, 6);
- }
-
- frame.payload.copy(buffer, offset);
-
- if (frame.masked) {
- frame.maskingKey.copy(buffer, header);
- Hybi.mask(buffer, frame.maskingKey, offset);
- }
-
- this._write(buffer);
- },
-
- _handshakeResponse: function() {
- try {
- var extensions = this._extensions.generateResponse(this._request.headers['sec-websocket-extensions']);
- } catch (e) {
- return this._fail('protocol_error', e.message);
- }
-
- if (extensions) this._headers.set('Sec-WebSocket-Extensions', extensions);
-
- var start = 'HTTP/1.1 101 Switching Protocols',
- headers = [start, this._headers.toString(), ''];
-
- return new Buffer(headers.join('\r\n'), 'utf8');
- },
-
- _shutdown: function(code, reason, error) {
- delete this._frame;
- delete this._message;
- this._stage = 5;
-
- var sendCloseFrame = (this.readyState === 1);
- this.readyState = 2;
-
- this._extensions.close(function() {
- if (sendCloseFrame) this.frame(reason, 'close', code);
- this.readyState = 3;
- if (error) this.emit('error', new Error(reason));
- this.emit('close', new Base.CloseEvent(code, reason));
- }, this);
- },
-
- _fail: function(type, message) {
- if (this.readyState > 1) return;
- this._shutdown(this.ERRORS[type], message, true);
- },
-
- _parseOpcode: function(octet) {
- var rsvs = [this.RSV1, this.RSV2, this.RSV3].map(function(rsv) {
- return (octet & rsv) === rsv;
- });
-
- var frame = this._frame = new Frame();
-
- frame.final = (octet & this.FIN) === this.FIN;
- frame.rsv1 = rsvs[0];
- frame.rsv2 = rsvs[1];
- frame.rsv3 = rsvs[2];
- frame.opcode = (octet & this.OPCODE);
-
- this._stage = 1;
-
- if (!this._extensions.validFrameRsv(frame))
- return this._fail('protocol_error',
- 'One or more reserved bits are on: reserved1 = ' + (frame.rsv1 ? 1 : 0) +
- ', reserved2 = ' + (frame.rsv2 ? 1 : 0) +
- ', reserved3 = ' + (frame.rsv3 ? 1 : 0));
-
- if (this.OPCODE_CODES.indexOf(frame.opcode) < 0)
- return this._fail('protocol_error', 'Unrecognized frame opcode: ' + frame.opcode);
-
- if (this.MESSAGE_OPCODES.indexOf(frame.opcode) < 0 && !frame.final)
- return this._fail('protocol_error', 'Received fragmented control frame: opcode = ' + frame.opcode);
-
- if (this._message && this.OPENING_OPCODES.indexOf(frame.opcode) >= 0)
- return this._fail('protocol_error', 'Received new data frame but previous continuous frame is unfinished');
- },
-
- _parseLength: function(octet) {
- var frame = this._frame;
- frame.masked = (octet & this.MASK) === this.MASK;
- frame.length = (octet & this.LENGTH);
-
- if (frame.length >= 0 && frame.length <= 125) {
- this._stage = frame.masked ? 3 : 4;
- if (!this._checkFrameLength()) return;
- } else {
- this._stage = 2;
- frame.lengthBytes = (frame.length === 126 ? 2 : 8);
- }
-
- if (this._requireMasking && !frame.masked)
- return this._fail('unacceptable', 'Received unmasked frame but masking is required');
- },
-
- _parseExtendedLength: function(buffer) {
- var frame = this._frame;
- frame.length = this._readUInt(buffer);
-
- this._stage = frame.masked ? 3 : 4;
-
- if (this.MESSAGE_OPCODES.indexOf(frame.opcode) < 0 && frame.length > 125)
- return this._fail('protocol_error', 'Received control frame having too long payload: ' + frame.length);
-
- if (!this._checkFrameLength()) return;
- },
-
- _checkFrameLength: function() {
- var length = this._message ? this._message.length : 0;
-
- if (length + this._frame.length > this._maxLength) {
- this._fail('too_large', 'WebSocket frame length too large');
- return false;
- } else {
- return true;
- }
- },
-
- _emitFrame: function(buffer) {
- var frame = this._frame,
- payload = frame.payload = Hybi.mask(buffer, frame.maskingKey),
- opcode = frame.opcode,
- message,
- code, reason,
- callbacks, callback;
-
- delete this._frame;
-
- if (opcode === this.OPCODES.continuation) {
- if (!this._message) return this._fail('protocol_error', 'Received unexpected continuation frame');
- this._message.pushFrame(frame);
- }
-
- if (opcode === this.OPCODES.text || opcode === this.OPCODES.binary) {
- this._message = new Message();
- this._message.pushFrame(frame);
- }
-
- if (frame.final && this.MESSAGE_OPCODES.indexOf(opcode) >= 0)
- return this._emitMessage(this._message);
-
- if (opcode === this.OPCODES.close) {
- code = (payload.length >= 2) ? payload.readUInt16BE(0) : null;
- reason = (payload.length > 2) ? this._encode(payload.slice(2)) : null;
-
- if (!(payload.length === 0) &&
- !(code !== null && code >= this.MIN_RESERVED_ERROR && code <= this.MAX_RESERVED_ERROR) &&
- this.ERROR_CODES.indexOf(code) < 0)
- code = this.ERRORS.protocol_error;
-
- if (payload.length > 125 || (payload.length > 2 && !reason))
- code = this.ERRORS.protocol_error;
-
- this._shutdown(code || this.DEFAULT_ERROR_CODE, reason || '');
- }
-
- if (opcode === this.OPCODES.ping) {
- this.frame(payload, 'pong');
- this.emit('ping', new Base.PingEvent(payload.toString()))
- }
-
- if (opcode === this.OPCODES.pong) {
- callbacks = this._pingCallbacks;
- message = this._encode(payload);
- callback = callbacks[message];
-
- delete callbacks[message];
- if (callback) callback()
-
- this.emit('pong', new Base.PongEvent(payload.toString()))
- }
- },
-
- _emitMessage: function(message) {
- var message = this._message;
- message.read();
-
- delete this._message;
-
- this._extensions.processIncomingMessage(message, function(error, message) {
- if (error) return this._fail('extension_error', error.message);
-
- var payload = message.data;
- if (message.opcode === this.OPCODES.text) payload = this._encode(payload);
-
- if (payload === null)
- return this._fail('encoding_error', 'Could not decode a text frame as UTF-8');
- else
- this.emit('message', new Base.MessageEvent(payload));
- }, this);
- },
-
- _encode: function(buffer) {
- try {
- var string = buffer.toString('binary', 0, buffer.length);
- if (!this.UTF8_MATCH.test(string)) return null;
- } catch (e) {}
- return buffer.toString('utf8', 0, buffer.length);
- },
-
- _readUInt: function(buffer) {
- if (buffer.length === 2) return buffer.readUInt16BE(0);
-
- return buffer.readUInt32BE(0) * 0x100000000 +
- buffer.readUInt32BE(4);
- }
- };
-
- for (var key in instance)
- Hybi.prototype[key] = instance[key];
-
- module.exports = Hybi;
- }],
- [/* 10 */ 'websocket-extensions', '/lib/websocket_extensions.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var Parser = __node_require__(11 /* './parser' */),
- Pipeline = __node_require__(12 /* './pipeline' */);
-
- var Extensions = function() {
- this._rsv1 = this._rsv2 = this._rsv3 = null;
-
- this._byName = {};
- this._inOrder = [];
- this._sessions = [];
- this._index = {};
- };
-
- Extensions.MESSAGE_OPCODES = [1, 2];
-
- var instance = {
- add: function(ext) {
- if (typeof ext.name !== 'string') throw new TypeError('extension.name must be a string');
- if (ext.type !== 'permessage') throw new TypeError('extension.type must be "permessage"');
-
- if (typeof ext.rsv1 !== 'boolean') throw new TypeError('extension.rsv1 must be true or false');
- if (typeof ext.rsv2 !== 'boolean') throw new TypeError('extension.rsv2 must be true or false');
- if (typeof ext.rsv3 !== 'boolean') throw new TypeError('extension.rsv3 must be true or false');
-
- if (this._byName.hasOwnProperty(ext.name))
- throw new TypeError('An extension with name "' + ext.name + '" is already registered');
-
- this._byName[ext.name] = ext;
- this._inOrder.push(ext);
- },
-
- generateOffer: function() {
- var sessions = [],
- offer = [],
- index = {};
-
- this._inOrder.forEach(function(ext) {
- var session = ext.createClientSession();
- if (!session) return;
-
- var record = [ext, session];
- sessions.push(record);
- index[ext.name] = record;
-
- var offers = session.generateOffer();
- offers = offers ? [].concat(offers) : [];
-
- offers.forEach(function(off) {
- offer.push(Parser.serializeParams(ext.name, off));
- }, this);
- }, this);
-
- this._sessions = sessions;
- this._index = index;
-
- return offer.length > 0 ? offer.join(', ') : null;
- },
-
- activate: function(header) {
- var responses = Parser.parseHeader(header),
- sessions = [];
-
- responses.eachOffer(function(name, params) {
- var record = this._index[name];
-
- if (!record)
- throw new Error('Server sent an extension response for unknown extension "' + name + '"');
-
- var ext = record[0],
- session = record[1],
- reserved = this._reserved(ext);
-
- if (reserved)
- throw new Error('Server sent two extension responses that use the RSV' +
- reserved[0] + ' bit: "' +
- reserved[1] + '" and "' + ext.name + '"');
-
- if (session.activate(params) !== true)
- throw new Error('Server sent unacceptable extension parameters: ' +
- Parser.serializeParams(name, params));
-
- this._reserve(ext);
- sessions.push(record);
- }, this);
-
- this._sessions = sessions;
- this._pipeline = new Pipeline(sessions);
- },
-
- generateResponse: function(header) {
- var sessions = [],
- response = [],
- offers = Parser.parseHeader(header);
-
- this._inOrder.forEach(function(ext) {
- var offer = offers.byName(ext.name);
- if (offer.length === 0 || this._reserved(ext)) return;
-
- var session = ext.createServerSession(offer);
- if (!session) return;
-
- this._reserve(ext);
- sessions.push([ext, session]);
- response.push(Parser.serializeParams(ext.name, session.generateResponse()));
- }, this);
-
- this._sessions = sessions;
- this._pipeline = new Pipeline(sessions);
-
- return response.length > 0 ? response.join(', ') : null;
- },
-
- validFrameRsv: function(frame) {
- var allowed = {rsv1: false, rsv2: false, rsv3: false},
- ext;
-
- if (Extensions.MESSAGE_OPCODES.indexOf(frame.opcode) >= 0) {
- for (var i = 0, n = this._sessions.length; i < n; i++) {
- ext = this._sessions[i][0];
- allowed.rsv1 = allowed.rsv1 || ext.rsv1;
- allowed.rsv2 = allowed.rsv2 || ext.rsv2;
- allowed.rsv3 = allowed.rsv3 || ext.rsv3;
- }
- }
-
- return (allowed.rsv1 || !frame.rsv1) &&
- (allowed.rsv2 || !frame.rsv2) &&
- (allowed.rsv3 || !frame.rsv3);
- },
-
- processIncomingMessage: function(message, callback, context) {
- this._pipeline.processIncomingMessage(message, callback, context);
- },
-
- processOutgoingMessage: function(message, callback, context) {
- this._pipeline.processOutgoingMessage(message, callback, context);
- },
-
- close: function(callback, context) {
- if (!this._pipeline) return callback.call(context);
- this._pipeline.close(callback, context);
- },
-
- _reserve: function(ext) {
- this._rsv1 = this._rsv1 || (ext.rsv1 && ext.name);
- this._rsv2 = this._rsv2 || (ext.rsv2 && ext.name);
- this._rsv3 = this._rsv3 || (ext.rsv3 && ext.name);
- },
-
- _reserved: function(ext) {
- if (this._rsv1 && ext.rsv1) return [1, this._rsv1];
- if (this._rsv2 && ext.rsv2) return [2, this._rsv2];
- if (this._rsv3 && ext.rsv3) return [3, this._rsv3];
- return false;
- }
- };
-
- for (var key in instance)
- Extensions.prototype[key] = instance[key];
-
- module.exports = Extensions;
- }],
- [/* 11 */ 'websocket-extensions', '/lib/parser.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var TOKEN = /([!#\$%&'\*\+\-\.\^_`\|~0-9A-Za-z]+)/,
- NOTOKEN = /([^!#\$%&'\*\+\-\.\^_`\|~0-9A-Za-z])/g,
- QUOTED = /"((?:\\[\x00-\x7f]|[^\x00-\x08\x0a-\x1f\x7f"])*)"/,
- PARAM = new RegExp(TOKEN.source + '(?:=(?:' + TOKEN.source + '|' + QUOTED.source + '))?'),
- EXT = new RegExp(TOKEN.source + '(?: *; *' + PARAM.source + ')*', 'g'),
- EXT_LIST = new RegExp('^' + EXT.source + '(?: *, *' + EXT.source + ')*$'),
- NUMBER = /^-?(0|[1-9][0-9]*)(\.[0-9]+)?$/;
-
- var hasOwnProperty = Object.prototype.hasOwnProperty;
-
- var Parser = {
- parseHeader: function(header) {
- var offers = new Offers();
- if (header === '' || header === undefined) return offers;
-
- if (!EXT_LIST.test(header))
- throw new SyntaxError('Invalid Sec-WebSocket-Extensions header: ' + header);
-
- var values = header.match(EXT);
-
- values.forEach(function(value) {
- var params = value.match(new RegExp(PARAM.source, 'g')),
- name = params.shift(),
- offer = {};
-
- params.forEach(function(param) {
- var args = param.match(PARAM), key = args[1], data;
-
- if (args[2] !== undefined) {
- data = args[2];
- } else if (args[3] !== undefined) {
- data = args[3].replace(/\\/g, '');
- } else {
- data = true;
- }
- if (NUMBER.test(data)) data = parseFloat(data);
-
- if (hasOwnProperty.call(offer, key)) {
- offer[key] = [].concat(offer[key]);
- offer[key].push(data);
- } else {
- offer[key] = data;
- }
- }, this);
- offers.push(name, offer);
- }, this);
-
- return offers;
- },
-
- serializeParams: function(name, params) {
- var values = [];
-
- var print = function(key, value) {
- if (value instanceof Array) {
- value.forEach(function(v) { print(key, v) });
- } else if (value === true) {
- values.push(key);
- } else if (typeof value === 'number') {
- values.push(key + '=' + value);
- } else if (NOTOKEN.test(value)) {
- values.push(key + '="' + value.replace(/"/g, '\\"') + '"');
- } else {
- values.push(key + '=' + value);
- }
- };
-
- for (var key in params) print(key, params[key]);
-
- return [name].concat(values).join('; ');
- }
- };
-
- var Offers = function() {
- this._byName = {};
- this._inOrder = [];
- };
-
- Offers.prototype.push = function(name, params) {
- if (!hasOwnProperty.call(this._byName, name))
- this._byName[name] = [];
-
- this._byName[name].push(params);
- this._inOrder.push({name: name, params: params});
- };
-
- Offers.prototype.eachOffer = function(callback, context) {
- var list = this._inOrder;
- for (var i = 0, n = list.length; i < n; i++)
- callback.call(context, list[i].name, list[i].params);
- };
-
- Offers.prototype.byName = function(name) {
- return this._byName[name] || [];
- };
-
- Offers.prototype.toArray = function() {
- return this._inOrder.slice();
- };
-
- module.exports = Parser;
- }],
- [/* 12 */ 'websocket-extensions', '/lib/pipeline/index.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var Cell = __node_require__(13 /* './cell' */),
- Pledge = __node_require__(16 /* './pledge' */);
-
- var Pipeline = function(sessions) {
- this._cells = sessions.map(function(session) { return new Cell(session) });
- this._stopped = {incoming: false, outgoing: false};
- };
-
- Pipeline.prototype.processIncomingMessage = function(message, callback, context) {
- if (this._stopped.incoming) return;
- this._loop('incoming', this._cells.length - 1, -1, -1, message, callback, context);
- };
-
- Pipeline.prototype.processOutgoingMessage = function(message, callback, context) {
- if (this._stopped.outgoing) return;
- this._loop('outgoing', 0, this._cells.length, 1, message, callback, context);
- };
-
- Pipeline.prototype.close = function(callback, context) {
- this._stopped = {incoming: true, outgoing: true};
-
- var closed = this._cells.map(function(a) { return a.close() });
- if (callback)
- Pledge.all(closed).then(function() { callback.call(context) });
- };
-
- Pipeline.prototype._loop = function(direction, start, end, step, message, callback, context) {
- var cells = this._cells,
- n = cells.length,
- self = this;
-
- while (n--) cells[n].pending(direction);
-
- var pipe = function(index, error, msg) {
- if (index === end) return callback.call(context, error, msg);
-
- cells[index][direction](error, msg, function(err, m) {
- if (err) self._stopped[direction] = true;
- pipe(index + step, err, m);
- });
- };
- pipe(start, null, message);
- };
-
- module.exports = Pipeline;
- }],
- [/* 13 */ 'websocket-extensions', '/lib/pipeline/cell.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var Functor = __node_require__(14 /* './functor' */),
- Pledge = __node_require__(16 /* './pledge' */);
-
- var Cell = function(tuple) {
- this._ext = tuple[0];
- this._session = tuple[1];
-
- this._functors = {
- incoming: new Functor(this._session, 'processIncomingMessage'),
- outgoing: new Functor(this._session, 'processOutgoingMessage')
- };
- };
-
- Cell.prototype.pending = function(direction) {
- var functor = this._functors[direction];
- if (!functor._stopped) functor.pending += 1;
- };
-
- Cell.prototype.incoming = function(error, message, callback, context) {
- this._exec('incoming', error, message, callback, context);
- };
-
- Cell.prototype.outgoing = function(error, message, callback, context) {
- this._exec('outgoing', error, message, callback, context);
- };
-
- Cell.prototype.close = function() {
- this._closed = this._closed || new Pledge();
- this._doClose();
- return this._closed;
- };
-
- Cell.prototype._exec = function(direction, error, message, callback, context) {
- this._functors[direction].call(error, message, function(err, msg) {
- if (err) err.message = this._ext.name + ': ' + err.message;
- callback.call(context, err, msg);
- this._doClose();
- }, this);
- };
-
- Cell.prototype._doClose = function() {
- var fin = this._functors.incoming,
- fout = this._functors.outgoing;
-
- if (!this._closed || fin.pending + fout.pending !== 0) return;
- if (this._session) this._session.close();
- this._session = null;
- this._closed.done();
- };
-
- module.exports = Cell;
- }],
- [/* 14 */ 'websocket-extensions', '/lib/pipeline/functor.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var RingBuffer = __node_require__(15 /* './ring_buffer' */);
-
- var Functor = function(session, method) {
- this._session = session;
- this._method = method;
- this._queue = new RingBuffer(Functor.QUEUE_SIZE);
- this._stopped = false;
- this.pending = 0;
- };
-
- Functor.QUEUE_SIZE = 8;
-
- Functor.prototype.call = function(error, message, callback, context) {
- if (this._stopped) return;
-
- var record = {error: error, message: message, callback: callback, context: context, done: false},
- called = false,
- self = this;
-
- this._queue.push(record);
-
- if (record.error) {
- record.done = true;
- this._stop();
- return this._flushQueue();
- }
-
- var handler = function(err, msg) {
- if (!(called ^ (called = true))) return;
-
- if (err) {
- self._stop();
- record.error = err;
- record.message = null;
- } else {
- record.message = msg;
- }
-
- record.done = true;
- self._flushQueue();
- };
-
- try {
- this._session[this._method](message, handler);
- } catch (err) {
- handler(err);
- }
- };
-
- Functor.prototype._stop = function() {
- this.pending = this._queue.length;
- this._stopped = true;
- };
-
- Functor.prototype._flushQueue = function() {
- var queue = this._queue, record;
-
- while (queue.length > 0 && queue.peek().done) {
- record = queue.shift();
- if (record.error) {
- this.pending = 0;
- queue.clear();
- } else {
- this.pending -= 1;
- }
- record.callback.call(record.context, record.error, record.message);
- }
- };
-
- module.exports = Functor;
- }],
- [/* 15 */ 'websocket-extensions', '/lib/pipeline/ring_buffer.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var RingBuffer = function(bufferSize) {
- this._bufferSize = bufferSize;
- this.clear();
- };
-
- RingBuffer.prototype.clear = function() {
- this._buffer = new Array(this._bufferSize);
- this._ringOffset = 0;
- this._ringSize = this._bufferSize;
- this._head = 0;
- this._tail = 0;
- this.length = 0;
- };
-
- RingBuffer.prototype.push = function(value) {
- var expandBuffer = false,
- expandRing = false;
-
- if (this._ringSize < this._bufferSize) {
- expandBuffer = (this._tail === 0);
- } else if (this._ringOffset === this._ringSize) {
- expandBuffer = true;
- expandRing = (this._tail === 0);
- }
-
- if (expandBuffer) {
- this._tail = this._bufferSize;
- this._buffer = this._buffer.concat(new Array(this._bufferSize));
- this._bufferSize = this._buffer.length;
-
- if (expandRing)
- this._ringSize = this._bufferSize;
- }
-
- this._buffer[this._tail] = value;
- this.length += 1;
- if (this._tail < this._ringSize) this._ringOffset += 1;
- this._tail = (this._tail + 1) % this._bufferSize;
- };
-
- RingBuffer.prototype.peek = function() {
- if (this.length === 0) return void 0;
- return this._buffer[this._head];
- };
-
- RingBuffer.prototype.shift = function() {
- if (this.length === 0) return void 0;
-
- var value = this._buffer[this._head];
- this._buffer[this._head] = void 0;
- this.length -= 1;
- this._ringOffset -= 1;
-
- if (this._ringOffset === 0 && this.length > 0) {
- this._head = this._ringSize;
- this._ringOffset = this.length;
- this._ringSize = this._bufferSize;
- } else {
- this._head = (this._head + 1) % this._ringSize;
- }
- return value;
- };
-
- module.exports = RingBuffer;
- }],
- [/* 16 */ 'websocket-extensions', '/lib/pipeline/pledge.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var RingBuffer = __node_require__(15 /* './ring_buffer' */);
-
- var Pledge = function() {
- this._complete = false;
- this._callbacks = new RingBuffer(Pledge.QUEUE_SIZE);
- };
-
- Pledge.QUEUE_SIZE = 4;
-
- Pledge.all = function(list) {
- var pledge = new Pledge(),
- pending = list.length,
- n = pending;
-
- if (pending === 0) pledge.done();
-
- while (n--) list[n].then(function() {
- pending -= 1;
- if (pending === 0) pledge.done();
- });
- return pledge;
- };
-
- Pledge.prototype.then = function(callback) {
- if (this._complete) callback();
- else this._callbacks.push(callback);
- };
-
- Pledge.prototype.done = function() {
- this._complete = true;
- var callbacks = this._callbacks, callback;
- while (callback = callbacks.shift()) callback();
- };
-
- module.exports = Pledge;
- }],
- [/* 17 */ 'websocket-driver', '/lib/websocket/driver/hybi/frame.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var Frame = function() {};
-
- var instance = {
- final: false,
- rsv1: false,
- rsv2: false,
- rsv3: false,
- opcode: null,
- masked: false,
- maskingKey: null,
- lengthBytes: 1,
- length: 0,
- payload: null
- };
-
- for (var key in instance)
- Frame.prototype[key] = instance[key];
-
- module.exports = Frame;
- }],
- [/* 18 */ 'websocket-driver', '/lib/websocket/driver/hybi/message.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var Message = function() {
- this.rsv1 = false;
- this.rsv2 = false;
- this.rsv3 = false;
- this.opcode = null
- this.length = 0;
- this._chunks = [];
- };
-
- var instance = {
- read: function() {
- if (this.data) return this.data;
-
- this.data = new Buffer(this.length);
- var offset = 0;
-
- for (var i = 0, n = this._chunks.length; i < n; i++) {
- this._chunks[i].copy(this.data, offset);
- offset += this._chunks[i].length;
- }
- return this.data;
- },
-
- pushFrame: function(frame) {
- this.rsv1 = this.rsv1 || frame.rsv1;
- this.rsv2 = this.rsv2 || frame.rsv2;
- this.rsv3 = this.rsv3 || frame.rsv3;
-
- if (this.opcode === null) this.opcode = frame.opcode;
-
- this._chunks.push(frame.payload);
- this.length += frame.length;
- }
- };
-
- for (var key in instance)
- Message.prototype[key] = instance[key];
-
- module.exports = Message;
- }],
- [/* 19 */ 'websocket-driver', '/lib/websocket/driver/proxy.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var Stream = require('stream').Stream,
- url = require('url'),
- util = require('util'),
- Base = __node_require__(2 /* './base' */),
- Headers = __node_require__(4 /* './headers' */),
- HttpParser = __node_require__(7 /* '../http_parser' */);
-
- var PORTS = {'ws:': 80, 'wss:': 443};
-
- var Proxy = function(client, origin, options) {
- this._client = client;
- this._http = new HttpParser('response');
- this._origin = (typeof client.url === 'object') ? client.url : url.parse(client.url);
- this._url = (typeof origin === 'object') ? origin : url.parse(origin);
- this._options = options || {};
- this._state = 0;
-
- this.readable = this.writable = true;
- this._paused = false;
-
- this._headers = new Headers();
- this._headers.set('Host', this._origin.host);
- this._headers.set('Connection', 'keep-alive');
- this._headers.set('Proxy-Connection', 'keep-alive');
-
- var auth = this._url.auth && new Buffer(this._url.auth, 'utf8').toString('base64');
- if (auth) this._headers.set('Proxy-Authorization', 'Basic ' + auth);
- };
- util.inherits(Proxy, Stream);
-
- var instance = {
- setHeader: function(name, value) {
- if (this._state !== 0) return false;
- this._headers.set(name, value);
- return true;
- },
-
- start: function() {
- if (this._state !== 0) return false;
- this._state = 1;
-
- var origin = this._origin,
- port = origin.port || PORTS[origin.protocol],
- start = 'CONNECT ' + origin.hostname + ':' + port + ' HTTP/1.1';
-
- var headers = [start, this._headers.toString(), ''];
-
- this.emit('data', new Buffer(headers.join('\r\n'), 'utf8'));
- return true;
- },
-
- pause: function() {
- this._paused = true;
- },
-
- resume: function() {
- this._paused = false;
- this.emit('drain');
- },
-
- write: function(chunk) {
- if (!this.writable) return false;
-
- this._http.parse(chunk);
- if (!this._http.isComplete()) return !this._paused;
-
- this.statusCode = this._http.statusCode;
- this.headers = this._http.headers;
-
- if (this.statusCode === 200) {
- this.emit('connect', new Base.ConnectEvent());
- } else {
- var message = "Can't establish a connection to the server at " + this._origin.href;
- this.emit('error', new Error(message));
- }
- this.end();
- return !this._paused;
- },
-
- end: function(chunk) {
- if (!this.writable) return;
- if (chunk !== undefined) this.write(chunk);
- this.readable = this.writable = false;
- this.emit('close');
- this.emit('end');
- },
-
- destroy: function() {
- this.end();
- }
- };
-
- for (var key in instance)
- Proxy.prototype[key] = instance[key];
-
- module.exports = Proxy;
- }],
- [/* 20 */ 'websocket-driver', '/lib/websocket/driver/server.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var util = require('util'),
- HttpParser = __node_require__(7 /* '../http_parser' */),
- Base = __node_require__(2 /* './base' */),
- Draft75 = __node_require__(21 /* './draft75' */),
- Draft76 = __node_require__(22 /* './draft76' */),
- Hybi = __node_require__(9 /* './hybi' */);
-
- var Server = function(options) {
- Base.call(this, null, null, options);
- this._http = new HttpParser('request');
- };
- util.inherits(Server, Base);
-
- var instance = {
- EVENTS: ['open', 'message', 'error', 'close'],
-
- _bindEventListeners: function() {
- this.messages.on('error', function() {});
- this.on('error', function() {});
- },
-
- parse: function(chunk) {
- if (this._delegate) return this._delegate.parse(chunk);
-
- this._http.parse(chunk);
- if (!this._http.isComplete()) return;
-
- this.method = this._http.method;
- this.url = this._http.url;
- this.headers = this._http.headers;
- this.body = this._http.body;
-
- var self = this;
- this._delegate = Server.http(this, this._options);
- this._delegate.messages = this.messages;
- this._delegate.io = this.io;
- this._open();
-
- this.EVENTS.forEach(function(event) {
- this._delegate.on(event, function(e) { self.emit(event, e) });
- }, this);
-
- this.protocol = this._delegate.protocol;
- this.version = this._delegate.version;
-
- this.parse(this._http.body);
- this.emit('connect', new Base.ConnectEvent());
- },
-
- _open: function() {
- this.__queue.forEach(function(msg) {
- this._delegate[msg[0]].apply(this._delegate, msg[1]);
- }, this);
- this.__queue = [];
- }
- };
-
- ['addExtension', 'setHeader', 'start', 'frame', 'text', 'binary', 'ping', 'close'].forEach(function(method) {
- instance[method] = function() {
- if (this._delegate) {
- return this._delegate[method].apply(this._delegate, arguments);
- } else {
- this.__queue.push([method, arguments]);
- return true;
- }
- };
- });
-
- for (var key in instance)
- Server.prototype[key] = instance[key];
-
- Server.isSecureRequest = function(request) {
- if (request.connection && request.connection.authorized !== undefined) return true;
- if (request.socket && request.socket.secure) return true;
-
- var headers = request.headers;
- if (!headers) return false;
- if (headers['https'] === 'on') return true;
- if (headers['x-forwarded-ssl'] === 'on') return true;
- if (headers['x-forwarded-scheme'] === 'https') return true;
- if (headers['x-forwarded-proto'] === 'https') return true;
-
- return false;
- };
-
- Server.determineUrl = function(request) {
- var scheme = this.isSecureRequest(request) ? 'wss:' : 'ws:';
- return scheme + '//' + request.headers.host + request.url;
- };
-
- Server.http = function(request, options) {
- options = options || {};
- if (options.requireMasking === undefined) options.requireMasking = true;
-
- var headers = request.headers,
- url = this.determineUrl(request);
-
- if (headers['sec-websocket-version'])
- return new Hybi(request, url, options);
- else if (headers['sec-websocket-key1'])
- return new Draft76(request, url, options);
- else
- return new Draft75(request, url, options);
- };
-
- module.exports = Server;
- }],
- [/* 21 */ 'websocket-driver', '/lib/websocket/driver/draft75.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var Base = __node_require__(2 /* './base' */),
- util = require('util');
-
- var Draft75 = function(request, url, options) {
- Base.apply(this, arguments);
- this._stage = 0;
- this.version = 'hixie-75';
-
- this._headers.set('Upgrade', 'WebSocket');
- this._headers.set('Connection', 'Upgrade');
- this._headers.set('WebSocket-Origin', this._request.headers.origin);
- this._headers.set('WebSocket-Location', this.url);
- };
- util.inherits(Draft75, Base);
-
- var instance = {
- close: function() {
- if (this.readyState === 3) return false;
- this.readyState = 3;
- this.emit('close', new Base.CloseEvent(null, null));
- return true;
- },
-
- parse: function(chunk) {
- if (this.readyState > 1) return;
-
- this._reader.put(chunk);
-
- this._reader.eachByte(function(octet) {
- var message;
-
- switch (this._stage) {
- case -1:
- this._body.push(octet);
- this._sendHandshakeBody();
- break;
-
- case 0:
- this._parseLeadingByte(octet);
- break;
-
- case 1:
- this._length = (octet & 0x7F) + 128 * this._length;
-
- if (this._closing && this._length === 0) {
- return this.close();
- }
- else if ((octet & 0x80) !== 0x80) {
- if (this._length === 0) {
- this._stage = 0;
- }
- else {
- this._skipped = 0;
- this._stage = 2;
- }
- }
- break;
-
- case 2:
- if (octet === 0xFF) {
- this._stage = 0;
- message = new Buffer(this._buffer).toString('utf8', 0, this._buffer.length);
- this.emit('message', new Base.MessageEvent(message));
- }
- else {
- if (this._length) {
- this._skipped += 1;
- if (this._skipped === this._length)
- this._stage = 0;
- } else {
- this._buffer.push(octet);
- if (this._buffer.length > this._maxLength) return this.close();
- }
- }
- break;
- }
- }, this);
- },
-
- frame: function(buffer) {
- if (this.readyState === 0) return this._queue([buffer]);
- if (this.readyState > 1) return false;
-
- if (typeof buffer !== 'string') buffer = buffer.toString();
-
- var payload = new Buffer(buffer, 'utf8'),
- frame = new Buffer(payload.length + 2);
-
- frame[0] = 0x00;
- frame[payload.length + 1] = 0xFF;
- payload.copy(frame, 1);
-
- this._write(frame);
- return true;
- },
-
- _handshakeResponse: function() {
- var start = 'HTTP/1.1 101 Web Socket Protocol Handshake',
- headers = [start, this._headers.toString(), ''];
-
- return new Buffer(headers.join('\r\n'), 'utf8');
- },
-
- _parseLeadingByte: function(octet) {
- if ((octet & 0x80) === 0x80) {
- this._length = 0;
- this._stage = 1;
- } else {
- delete this._length;
- delete this._skipped;
- this._buffer = [];
- this._stage = 2;
- }
- }
- };
-
- for (var key in instance)
- Draft75.prototype[key] = instance[key];
-
- module.exports = Draft75;
- }],
- [/* 22 */ 'websocket-driver', '/lib/websocket/driver/draft76.js', function(exports, module, __filename, __dirname, __meta) {
- 'use strict';
-
- var Base = __node_require__(2 /* './base' */),
- Draft75 = __node_require__(21 /* './draft75' */),
- crypto = require('crypto'),
- util = require('util');
-
-
- var numberFromKey = function(key) {
- return parseInt(key.match(/[0-9]/g).join(''), 10);
- };
-
- var spacesInKey = function(key) {
- return key.match(/ /g).length;
- };
-
-
- var Draft76 = function(request, url, options) {
- Draft75.apply(this, arguments);
- this._stage = -1;
- this._body = [];
- this.version = 'hixie-76';
-
- this._headers.clear();
-
- this._headers.set('Upgrade', 'WebSocket');
- this._headers.set('Connection', 'Upgrade');
- this._headers.set('Sec-WebSocket-Origin', this._request.headers.origin);
- this._headers.set('Sec-WebSocket-Location', this.url);
- };
- util.inherits(Draft76, Draft75);
-
- var instance = {
- BODY_SIZE: 8,
-
- start: function() {
- if (!Draft75.prototype.start.call(this)) return false;
- this._started = true;
- this._sendHandshakeBody();
- return true;
- },
-
- close: function() {
- if (this.readyState === 3) return false;
- this._write(new Buffer([0xFF, 0x00]));
- this.readyState = 3;
- this.emit('close', new Base.CloseEvent(null, null));
- return true;
- },
-
- _handshakeResponse: function() {
- var headers = this._request.headers,
-
- key1 = headers['sec-websocket-key1'],
- number1 = numberFromKey(key1),
- spaces1 = spacesInKey(key1),
-
- key2 = headers['sec-websocket-key2'],
- number2 = numberFromKey(key2),
- spaces2 = spacesInKey(key2);
-
- if (number1 % spaces1 !== 0 || number2 % spaces2 !== 0) {
- this.emit('error', new Error('Client sent invalid Sec-WebSocket-Key headers'));
- this.close();
- return null;
- }
-
- this._keyValues = [number1 / spaces1, number2 / spaces2];
-
- var start = 'HTTP/1.1 101 WebSocket Protocol Handshake',
- headers = [start, this._headers.toString(), ''];
-
- return new Buffer(headers.join('\r\n'), 'binary');
- },
-
- _handshakeSignature: function() {
- if (this._body.length < this.BODY_SIZE) return null;
-
- var md5 = crypto.createHash('md5'),
- buffer = new Buffer(8 + this.BODY_SIZE);
-
- buffer.writeUInt32BE(this._keyValues[0], 0);
- buffer.writeUInt32BE(this._keyValues[1], 4);
- new Buffer(this._body).copy(buffer, 8, 0, this.BODY_SIZE);
-
- md5.update(buffer);
- return new Buffer(md5.digest('binary'), 'binary');
- },
-
- _sendHandshakeBody: function() {
- if (!this._started) return;
- var signature = this._handshakeSignature();
- if (!signature) return;
-
- this._write(signature);
- this._stage = 0;
- this._open();
-
- if (this._body.length > this.BODY_SIZE)
- this.parse(this._body.slice(this.BODY_SIZE));
- },
-
- _parseLeadingByte: function(octet) {
- if (octet !== 0xFF)
- return Draft75.prototype._parseLeadingByte.call(this, octet);
-
- this._closing = true;
- this._length = 0;
- this._stage = 1;
- }
- };
-
- for (var key in instance)
- Draft76.prototype[key] = instance[key];
-
- module.exports = Draft76;
- }],
- [/* 23 */ 'faye-websocket', '/lib/faye/websocket/api.js', function(exports, module, __filename, __dirname, __meta) {
- var Stream = require('stream').Stream,
- util = require('util'),
- driver = __node_require__(1 /* 'websocket-driver' */),
- EventTarget = __node_require__(24 /* './api/event_target' */),
- Event = __node_require__(25 /* './api/event' */);
-
- var API = function(options) {
- options = options || {};
- driver.validateOptions(options, ['headers', 'extensions', 'maxLength', 'ping', 'proxy', 'tls', 'ca']);
-
- this.readable = this.writable = true;
-
- var headers = options.headers;
- if (headers) {
- for (var name in headers) this._driver.setHeader(name, headers[name]);
- }
-
- var extensions = options.extensions;
- if (extensions) {
- [].concat(extensions).forEach(this._driver.addExtension, this._driver);
- }
-
- this._ping = options.ping;
- this._pingId = 0;
- this.readyState = API.CONNECTING;
- this.bufferedAmount = 0;
- this.protocol = '';
- this.url = this._driver.url;
- this.version = this._driver.version;
-
- var self = this;
-
- this._driver.on('open', function(e) { self._open() });
- this._driver.on('message', function(e) { self._receiveMessage(e.data) });
- this._driver.on('close', function(e) { self._beginClose(e.reason, e.code) });
-
- this._driver.on('error', function(error) {
- self._emitError(error.message);
- });
- this.on('error', function() {});
-
- this._driver.messages.on('drain', function() {
- self.emit('drain');
- });
-
- if (this._ping)
- this._pingTimer = setInterval(function() {
- self._pingId += 1;
- self.ping(self._pingId.toString());
- }, this._ping * 1000);
-
- this._configureStream();
-
- if (!this._proxy) {
- this._stream.pipe(this._driver.io);
- this._driver.io.pipe(this._stream);
- }
- };
- util.inherits(API, Stream);
-
- API.CONNECTING = 0;
- API.OPEN = 1;
- API.CLOSING = 2;
- API.CLOSED = 3;
-
- API.CLOSE_TIMEOUT = 30000;
-
- var instance = {
- write: function(data) {
- return this.send(data);
- },
-
- end: function(data) {
- if (data !== undefined) this.send(data);
- this.close();
- },
-
- pause: function() {
- return this._driver.messages.pause();
- },
-
- resume: function() {
- return this._driver.messages.resume();
- },
-
- send: function(data) {
- if (this.readyState > API.OPEN) return false;
- if (!(data instanceof Buffer)) data = String(data);
- return this._driver.messages.write(data);
- },
-
- ping: function(message, callback) {
- if (this.readyState > API.OPEN) return false;
- return this._driver.ping(message, callback);
- },
-
- close: function(code, reason) {
- if (code === undefined) code = 1000;
- if (reason === undefined) reason = '';
-
- if (code !== 1000 && (code < 3000 || code > 4999))
- throw new Error("Failed to execute 'close' on WebSocket: " +
- "The code must be either 1000, or between 3000 and 4999. " +
- code + " is neither.");
-
- if (this.readyState !== API.CLOSED) this.readyState = API.CLOSING;
-
- var self = this;
-
- this._closeTimer = setTimeout(function() {
- self._beginClose('', 1006);
- }, API.CLOSE_TIMEOUT);
-
- this._driver.close(reason, code);
- },
-
- _configureStream: function() {
- var self = this;
-
- this._stream.setTimeout(0);
- this._stream.setNoDelay(true);
-
- ['close', 'end'].forEach(function(event) {
- this._stream.on(event, function() { self._finalizeClose() });
- }, this);
-
- this._stream.on('error', function(error) {
- self._emitError('Network error: ' + self.url + ': ' + error.message);
- self._finalizeClose();
- });
- },
-
- _open: function() {
- if (this.readyState !== API.CONNECTING) return;
-
- this.readyState = API.OPEN;
- this.protocol = this._driver.protocol || '';
-
- var event = new Event('open');
- event.initEvent('open', false, false);
- this.dispatchEvent(event);
- },
-
- _receiveMessage: function(data) {
- if (this.readyState > API.OPEN) return false;
-
- if (this.readable) this.emit('data', data);
-
- var event = new Event('message', {data: data});
- event.initEvent('message', false, false);
- this.dispatchEvent(event);
- },
-
- _emitError: function(message) {
- if (this.readyState >= API.CLOSING) return;
-
- var event = new Event('error', {message: message});
- event.initEvent('error', false, false);
- this.dispatchEvent(event);
- },
-
- _beginClose: function(reason, code) {
- if (this.readyState === API.CLOSED) return;
- this.readyState = API.CLOSING;
- this._closeParams = [reason, code];
-
- if (this._stream) {
- this._stream.destroy();
- if (!this._stream.readable) this._finalizeClose();
- }
- },
-
- _finalizeClose: function() {
- if (this._closeTimer) clearTimeout(this._closeTimer);
-
- if (this.readyState === API.CLOSED) return;
- this.readyState = API.CLOSED;
-
- if (this._pingTimer) clearInterval(this._pingTimer);
- if (this._stream) this._stream.end();
-
- if (this.readable) this.emit('end');
- this.readable = this.writable = false;
-
- var reason = this._closeParams ? this._closeParams[0] : '',
- code = this._closeParams ? this._closeParams[1] : 1006;
-
- var event = new Event('close', {code: code, reason: reason});
- event.initEvent('close', false, false);
- this.dispatchEvent(event);
- }
- };
-
- for (var method in instance) API.prototype[method] = instance[method];
- for (var key in EventTarget) API.prototype[key] = EventTarget[key];
-
- module.exports = API;
- }],
- [/* 24 */ 'faye-websocket', '/lib/faye/websocket/api/event_target.js', function(exports, module, __filename, __dirname, __meta) {
- var Event = __node_require__(25 /* './event' */);
-
- var EventTarget = {
- onopen: null,
- onmessage: null,
- onerror: null,
- onclose: null,
-
- addEventListener: function(eventType, listener, useCapture) {
- this.on(eventType, listener);
- },
-
- removeEventListener: function(eventType, listener, useCapture) {
- this.removeListener(eventType, listener);
- },
-
- dispatchEvent: function(event) {
- event.target = event.currentTarget = this;
- event.eventPhase = Event.AT_TARGET;
-
- if (this['on' + event.type])
- this['on' + event.type](event);
-
- this.emit(event.type, event);
- }
- };
-
- module.exports = EventTarget;
- }],
- [/* 25 */ 'faye-websocket', '/lib/faye/websocket/api/event.js', function(exports, module, __filename, __dirname, __meta) {
- var Event = function(eventType, options) {
- this.type = eventType;
- for (var key in options)
- this[key] = options[key];
- };
-
- Event.prototype.initEvent = function(eventType, canBubble, cancelable) {
- this.type = eventType;
- this.bubbles = canBubble;
- this.cancelable = cancelable;
- };
-
- Event.prototype.stopPropagation = function() {};
- Event.prototype.preventDefault = function() {};
-
- Event.CAPTURING_PHASE = 1;
- Event.AT_TARGET = 2;
- Event.BUBBLING_PHASE = 3;
-
- module.exports = Event;
- }],
- [/* 26 */ 'faye-websocket', '/lib/faye/websocket/client.js', function(exports, module, __filename, __dirname, __meta) {
- var util = require('util'),
- net = require('net'),
- tls = require('tls'),
- url = require('url'),
- driver = __node_require__(1 /* 'websocket-driver' */),
- API = __node_require__(23 /* './api' */),
- Event = __node_require__(25 /* './api/event' */);
-
- var DEFAULT_PORTS = {'http:': 80, 'https:': 443, 'ws:':80, 'wss:': 443},
- SECURE_PROTOCOLS = ['https:', 'wss:'];
-
- var Client = function(_url, protocols, options) {
- options = options || {};
-
- this.url = _url;
- this._driver = driver.client(this.url, {maxLength: options.maxLength, protocols: protocols});
-
- ['open', 'error'].forEach(function(event) {
- this._driver.on(event, function() {
- self.headers = self._driver.headers;
- self.statusCode = self._driver.statusCode;
- });
- }, this);
-
- var proxy = options.proxy || {},
- endpoint = url.parse(proxy.origin || this.url),
- port = endpoint.port || DEFAULT_PORTS[endpoint.protocol],
- secure = SECURE_PROTOCOLS.indexOf(endpoint.protocol) >= 0,
- onConnect = function() { self._onConnect() },
- netOptions = options.net || {},
- originTLS = options.tls || {},
- socketTLS = proxy.origin ? (proxy.tls || {}) : originTLS,
- self = this;
-
- netOptions.host = socketTLS.host = endpoint.hostname;
- netOptions.port = socketTLS.port = port;
-
- originTLS.ca = originTLS.ca || options.ca;
- socketTLS.servername = socketTLS.servername || endpoint.hostname;
-
- this._stream = secure
- ? tls.connect(socketTLS, onConnect)
- : net.connect(netOptions, onConnect);
-
- if (proxy.origin) this._configureProxy(proxy, originTLS);
-
- API.call(this, options);
- };
- util.inherits(Client, API);
-
- Client.prototype._onConnect = function() {
- var worker = this._proxy || this._driver;
- worker.start();
- };
-
- Client.prototype._configureProxy = function(proxy, originTLS) {
- var uri = url.parse(this.url),
- secure = SECURE_PROTOCOLS.indexOf(uri.protocol) >= 0,
- self = this,
- name;
-
- this._proxy = this._driver.proxy(proxy.origin);
-
- if (proxy.headers) {
- for (name in proxy.headers) this._proxy.setHeader(name, proxy.headers[name]);
- }
-
- this._proxy.pipe(this._stream, {end: false});
- this._stream.pipe(this._proxy);
-
- this._proxy.on('connect', function() {
- if (secure) {
- var options = {socket: self._stream, servername: uri.hostname};
- for (name in originTLS) options[name] = originTLS[name];
- self._stream = tls.connect(options);
- self._configureStream();
- }
- self._driver.io.pipe(self._stream);
- self._stream.pipe(self._driver.io);
- self._driver.start();
- });
-
- this._proxy.on('error', function(error) {
- self._driver.emit('error', error);
- });
- };
-
- module.exports = Client;
- }],
- [/* 27 */ 'faye-websocket', '/lib/faye/eventsource.js', function(exports, module, __filename, __dirname, __meta) {
- var Stream = require('stream').Stream,
- util = require('util'),
- driver = __node_require__(1 /* 'websocket-driver' */),
- Headers = __node_require__(4 /* 'websocket-driver/lib/websocket/driver/headers' */),
- API = __node_require__(23 /* './websocket/api' */),
- EventTarget = __node_require__(24 /* './websocket/api/event_target' */),
- Event = __node_require__(25 /* './websocket/api/event' */);
-
- var EventSource = function(request, response, options) {
- this.writable = true;
- options = options || {};
-
- this._stream = response.socket;
- this._ping = options.ping || this.DEFAULT_PING;
- this._retry = options.retry || this.DEFAULT_RETRY;
-
- var scheme = driver.isSecureRequest(request) ? 'https:' : 'http:';
- this.url = scheme + '//' + request.headers.host + request.url;
- this.lastEventId = request.headers['last-event-id'] || '';
- this.readyState = API.CONNECTING;
-
- var headers = new Headers(),
- self = this;
-
- if (options.headers) {
- for (var key in options.headers) headers.set(key, options.headers[key]);
- }
-
- if (!this._stream || !this._stream.writable) return;
- process.nextTick(function() { self._open() });
-
- this._stream.setTimeout(0);
- this._stream.setNoDelay(true);
-
- var handshake = 'HTTP/1.1 200 OK\r\n' +
- 'Content-Type: text/event-stream\r\n' +
- 'Cache-Control: no-cache, no-store\r\n' +
- 'Connection: close\r\n' +
- headers.toString() +
- '\r\n' +
- 'retry: ' + Math.floor(this._retry * 1000) + '\r\n\r\n';
-
- this._write(handshake);
-
- this._stream.on('drain', function() { self.emit('drain') });
-
- if (this._ping)
- this._pingTimer = setInterval(function() { self.ping() }, this._ping * 1000);
-
- ['error', 'end'].forEach(function(event) {
- self._stream.on(event, function() { self.close() });
- });
- };
- util.inherits(EventSource, Stream);
-
- EventSource.isEventSource = function(request) {
- if (request.method !== 'GET') return false;
- var accept = (request.headers.accept || '').split(/\s*,\s*/);
- return accept.indexOf('text/event-stream') >= 0;
- };
-
- var instance = {
- DEFAULT_PING: 10,
- DEFAULT_RETRY: 5,
-
- _write: function(chunk) {
- if (!this.writable) return false;
- try {
- return this._stream.write(chunk, 'utf8');
- } catch (e) {
- return false;
- }
- },
-
- _open: function() {
- if (this.readyState !== API.CONNECTING) return;
-
- this.readyState = API.OPEN;
-
- var event = new Event('open');
- event.initEvent('open', false, false);
- this.dispatchEvent(event);
- },
-
- write: function(message) {
- return this.send(message);
- },
-
- end: function(message) {
- if (message !== undefined) this.write(message);
- this.close();
- },
-
- send: function(message, options) {
- if (this.readyState > API.OPEN) return false;
-
- message = String(message).replace(/(\r\n|\r|\n)/g, '$1data: ');
- options = options || {};
-
- var frame = '';
- if (options.event) frame += 'event: ' + options.event + '\r\n';
- if (options.id) frame += 'id: ' + options.id + '\r\n';
- frame += 'data: ' + message + '\r\n\r\n';
-
- return this._write(frame);
- },
-
- ping: function() {
- return this._write(':\r\n\r\n');
- },
-
- close: function() {
- if (this.readyState > API.OPEN) return false;
-
- this.readyState = API.CLOSED;
- this.writable = false;
- if (this._pingTimer) clearInterval(this._pingTimer);
- if (this._stream) this._stream.end();
-
- var event = new Event('close');
- event.initEvent('close', false, false);
- this.dispatchEvent(event);
-
- return true;
- }
- };
-
- for (var method in instance) EventSource.prototype[method] = instance[method];
- for (var key in EventTarget) EventSource.prototype[key] = EventTarget[key];
-
- module.exports = EventSource;
- }]
- ];
-
- var __node_cache__ = [];
-
- function __node_error__(location) {
- var err = new Error('Cannot find module \'' + location + '\'');
- err.code = 'MODULE_NOT_FOUND';
- throw err;
- }
-
- function __node_require__(id) {
- if ((id >>> 0) !== id || id > __node_modules__.length)
- return __node_error__(id);
-
- while (__node_cache__.length <= id)
- __node_cache__.push(null);
-
- var cache = __node_cache__[id];
-
- if (cache)
- return cache.exports;
-
- var mod = __node_modules__[id];
- var name = mod[0];
- var path = mod[1];
- var func = mod[2];
- var meta;
-
- var _exports = exports;
- var _module = module;
-
- if (id !== 0) {
- _exports = {};
- _module = {
- id: '/' + name + path,
- exports: _exports,
- parent: module.parent,
- filename: module.filename,
- loaded: false,
- children: module.children,
- paths: module.paths
- };
- }
-
- __node_cache__[id] = _module;
-
- try {
- func.call(_exports, _exports, _module,
- __filename, __dirname, meta);
- } catch (e) {
- __node_cache__[id] = null;
- throw e;
- }
-
- __node_modules__[id] = null;
-
- if (id !== 0)
- _module.loaded = true;
-
- return _module.exports;
- }
-
- __node_require__(0);
|