added unit testing, and started implementing unit tests...phew
This commit is contained in:
88
node_modules/websocket/.jshintrc
generated
vendored
Normal file
88
node_modules/websocket/.jshintrc
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
{
|
||||
// JSHint Default Configuration File (as on JSHint website)
|
||||
// See http://jshint.com/docs/ for more details
|
||||
|
||||
"maxerr" : 50, // {int} Maximum error before stopping
|
||||
|
||||
// Enforcing
|
||||
"bitwise" : false, // true: Prohibit bitwise operators (&, |, ^, etc.)
|
||||
"camelcase" : false, // true: Identifiers must be in camelCase
|
||||
"curly" : true, // true: Require {} for every new block or scope
|
||||
"eqeqeq" : true, // true: Require triple equals (===) for comparison
|
||||
"freeze" : true, // true: prohibits overwriting prototypes of native objects such as Array, Date etc.
|
||||
"forin" : false, // true: Require filtering for..in loops with obj.hasOwnProperty()
|
||||
"immed" : true, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
|
||||
"latedef" : "nofunc", // true: Require variables/functions to be defined before being used
|
||||
"newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()`
|
||||
"noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
|
||||
"noempty" : true, // true: Prohibit use of empty blocks
|
||||
"nonbsp" : true, // true: Prohibit "non-breaking whitespace" characters.
|
||||
"nonew" : true, // true: Prohibit use of constructors for side-effects (without assignment)
|
||||
"plusplus" : false, // true: Prohibit use of `++` & `--`
|
||||
"quotmark" : "single", // Quotation mark consistency:
|
||||
// false : do nothing (default)
|
||||
// true : ensure whatever is used is consistent
|
||||
// "single" : require single quotes
|
||||
// "double" : require double quotes
|
||||
"undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
|
||||
"unused" : "vars", // vars: Require all defined variables be used, ignore function params
|
||||
"strict" : false, // true: Requires all functions run in ES5 Strict Mode
|
||||
"maxparams" : false, // {int} Max number of formal params allowed per function
|
||||
"maxdepth" : false, // {int} Max depth of nested blocks (within functions)
|
||||
"maxstatements" : false, // {int} Max number statements per function
|
||||
"maxcomplexity" : false, // {int} Max cyclomatic complexity per function
|
||||
"maxlen" : false, // {int} Max number of characters per line
|
||||
|
||||
// Relaxing
|
||||
"asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
|
||||
"boss" : false, // true: Tolerate assignments where comparisons would be expected
|
||||
"debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
|
||||
"eqnull" : false, // true: Tolerate use of `== null`
|
||||
"es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
|
||||
"esnext" : true, // true: Allow ES.next (ES6) syntax (ex: `const`)
|
||||
"moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
|
||||
// (ex: `for each`, multiple try/catch, function expression…)
|
||||
"evil" : false, // true: Tolerate use of `eval` and `new Function()`
|
||||
"expr" : false, // true: Tolerate `ExpressionStatement` as Programs
|
||||
"funcscope" : false, // true: Tolerate defining variables inside control statements
|
||||
"globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
|
||||
"iterator" : false, // true: Tolerate using the `__iterator__` property
|
||||
"lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
|
||||
"laxbreak" : false, // true: Tolerate possibly unsafe line breakings
|
||||
"laxcomma" : false, // true: Tolerate comma-first style coding
|
||||
"loopfunc" : false, // true: Tolerate functions being defined in loops
|
||||
"multistr" : false, // true: Tolerate multi-line strings
|
||||
"noyield" : false, // true: Tolerate generator functions with no yield statement in them.
|
||||
"notypeof" : false, // true: Tolerate invalid typeof operator values
|
||||
"proto" : false, // true: Tolerate using the `__proto__` property
|
||||
"scripturl" : false, // true: Tolerate script-targeted URLs
|
||||
"shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
|
||||
"sub" : true, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
|
||||
"supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
|
||||
"validthis" : false, // true: Tolerate using this in a non-constructor function
|
||||
|
||||
// Environments
|
||||
"browser" : true, // Web Browser (window, document, etc)
|
||||
"browserify" : true, // Browserify (node.js code in the browser)
|
||||
"couch" : false, // CouchDB
|
||||
"devel" : true, // Development/debugging (alert, confirm, etc)
|
||||
"dojo" : false, // Dojo Toolkit
|
||||
"jasmine" : false, // Jasmine
|
||||
"jquery" : false, // jQuery
|
||||
"mocha" : false, // Mocha
|
||||
"mootools" : false, // MooTools
|
||||
"node" : true, // Node.js
|
||||
"nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
|
||||
"prototypejs" : false, // Prototype and Scriptaculous
|
||||
"qunit" : false, // QUnit
|
||||
"rhino" : false, // Rhino
|
||||
"shelljs" : false, // ShellJS
|
||||
"worker" : false, // Web Workers
|
||||
"wsh" : false, // Windows Scripting Host
|
||||
"yui" : false, // Yahoo User Interface
|
||||
|
||||
// Custom Globals
|
||||
"globals" : { // additional predefined global variables
|
||||
"WebSocket": true
|
||||
}
|
||||
}
|
244
node_modules/websocket/CHANGELOG.md
generated
vendored
Normal file
244
node_modules/websocket/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,244 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
Version 1.0.28
|
||||
--------------
|
||||
*Released 2018-09-19*
|
||||
|
||||
* Updated to latest version of [nan](https://github.com/nodejs/nan)
|
||||
|
||||
Version 1.0.27
|
||||
--------------
|
||||
*Released 2018-09-19*
|
||||
|
||||
* Allowing additional request `headers` to be specified in the `tlsOptions` config parameter for WebSocketClient. See pull request #323
|
||||
* Resolving deprecation warnings relating to usage of `new Buffer`
|
||||
|
||||
Version 1.0.26
|
||||
--------------
|
||||
*Released 2018-04-27*
|
||||
|
||||
* No longer using the deprecated `noAssert` parameter for functions reading and writing binary numeric data. (Thanks, [@BridgeAR](https://github.com/BridgeAR))
|
||||
|
||||
Version 1.0.25
|
||||
--------------
|
||||
*Released 2017-10-18*
|
||||
|
||||
* Bumping minimum supported node version specified in package.json to v0.10.x because some upstream libraries no longer install on v0.8.x
|
||||
* [Allowing use of close codes 1012, 1013, 1014](https://www.iana.org/assignments/websocket/websocket.xml)
|
||||
* [Allowing the `Host` header to be overridden.](https://github.com/theturtle32/WebSocket-Node/pull/291) (Thanks, [@Juneil](https://github.com/Juneil))
|
||||
* [Mitigating infinite loop for broken connections](https://github.com/theturtle32/WebSocket-Node/pull/289) (Thanks, [@tvkit](https://github.com/tvkit))
|
||||
* [Fixed Markdown Typos](https://github.com/theturtle32/WebSocket-Node/pull/281) (Thanks, [@teramotodaiki](https://github.com/teramotodaiki))
|
||||
* [Adding old readyState constants for W3CWebSocket interface](https://github.com/theturtle32/WebSocket-Node/pull/282) (Thanks, [@thechriswalker](https://github.com/thechriswalker))
|
||||
|
||||
|
||||
Version 1.0.24
|
||||
--------------
|
||||
*Released 2016-12-28*
|
||||
|
||||
* Fixed a bug when using native keepalive on Node >= 6.0. (Thanks, [@prossin](https://github.com/prossin))
|
||||
* Upgrading outdated dependencies
|
||||
|
||||
Version 1.0.23
|
||||
--------------
|
||||
*Released 2016-05-18*
|
||||
|
||||
* Official support for Node 6.x
|
||||
* Updating dependencies. Specifically, updating nan to ^2.3.3
|
||||
|
||||
Version 1.0.22
|
||||
--------------
|
||||
*Released 2015-09-28*
|
||||
|
||||
* Updating to work with nan 2.x
|
||||
|
||||
Version 1.0.21
|
||||
--------------
|
||||
*Released 2015-07-22*
|
||||
|
||||
* Incremented and re-published to work around an aborted npm publish of v1.0.20.
|
||||
|
||||
Version 1.0.20
|
||||
--------------
|
||||
*Released 2015-07-22*
|
||||
|
||||
* Added EventTarget to the W3CWebSocket interface (Thanks, [@ibc](https://github.com/ibc)!)
|
||||
* Corrected an inaccurate error message. (Thanks, [@lekoaf](https://github.com/lekoaf)!)
|
||||
|
||||
Version 1.0.19
|
||||
--------------
|
||||
*Released 2015-05-28*
|
||||
|
||||
* Updated to nan v1.8.x (tested with v1.8.4)
|
||||
* Added `"license": "Apache-2.0"` to package.json via [pull request #199](https://github.com/theturtle32/WebSocket-Node/pull/199) by [@pgilad](https://github.com/pgilad). See [npm1k.org](http://npm1k.org/).
|
||||
|
||||
|
||||
Version 1.0.18
|
||||
--------------
|
||||
*Released 2015-03-19*
|
||||
|
||||
* Resolves [issue #195](https://github.com/theturtle32/WebSocket-Node/pull/179) - passing number to connection.send() causes crash
|
||||
* [Added close code/reason arguments to W3CWebSocket#close()](https://github.com/theturtle32/WebSocket-Node/issues/184)
|
||||
|
||||
|
||||
Version 1.0.17
|
||||
--------------
|
||||
*Released 2015-01-17*
|
||||
|
||||
* Resolves [issue #179](https://github.com/theturtle32/WebSocket-Node/pull/179) - Allow toBuffer to work with empty data
|
||||
|
||||
|
||||
Version 1.0.16
|
||||
--------------
|
||||
*Released 2015-01-16*
|
||||
|
||||
* Resolves [issue #178](https://github.com/theturtle32/WebSocket-Node/issues/178) - Ping Frames with no data
|
||||
|
||||
|
||||
Version 1.0.15
|
||||
--------------
|
||||
*Released 2015-01-13*
|
||||
|
||||
* Resolves [issue #177](https://github.com/theturtle32/WebSocket-Node/issues/177) - WebSocketClient ignores options unless it has a tlsOptions property
|
||||
|
||||
|
||||
Version 1.0.14
|
||||
--------------
|
||||
*Released 2014-12-03*
|
||||
|
||||
* Resolves [issue #173](https://github.com/theturtle32/WebSocket-Node/issues/173) - To allow the W3CWebSocket interface to accept an optional non-standard configuration object as its third parameter, which will be ignored when running in a browser context.
|
||||
|
||||
|
||||
Version 1.0.13
|
||||
--------------
|
||||
*Released 2014-11-29*
|
||||
|
||||
* Fixes [issue #171](https://github.com/theturtle32/WebSocket-Node/issues/171) - Code to prevent calling req.accept/req.reject multiple times breaks sanity checks in req.accept
|
||||
|
||||
|
||||
Version 1.0.12
|
||||
--------------
|
||||
*Released 2014-11-28*
|
||||
|
||||
* Fixes [issue #170](https://github.com/theturtle32/WebSocket-Node/issues/170) - Non-native XOR implementation broken after making JSHint happy
|
||||
|
||||
|
||||
Version 1.0.11
|
||||
--------------
|
||||
*Released 2014-11-25*
|
||||
|
||||
* Fixes some undefined behavior surrounding closing WebSocket connections and more reliably handles edge cases.
|
||||
* Adds an implementation of the W3C WebSocket API for browsers to facilitate sharing code between client and server via browserify. (Thanks, [@ibc](https://github.com/ibc)!)
|
||||
* `WebSocketConnection.prototype.close` now accepts optional `reasonCode` and `description` parameters.
|
||||
* Calling `accept` or `reject` more than once on a `WebSocketRequest` will now throw an error. [Issue #149](https://github.com/theturtle32/WebSocket-Node/issues/149)
|
||||
* Handling connections dropped by client before accepted by server [Issue #167](https://github.com/theturtle32/WebSocket-Node/issues/167)
|
||||
* Integrating Gulp and JSHint (Thanks, [@ibc](https://github.com/ibc)!)
|
||||
* Starting to add individual unit tests (using substack's [tape](github.com/substack/tape) and [faucet](github.com/substack/faucet))
|
||||
|
||||
|
||||
Version 1.0.10
|
||||
--------------
|
||||
*Released 2014-10-22*
|
||||
|
||||
* Fixed Issue [#146](https://github.com/theturtle32/WebSocket-Node/issues/146) that was causing WebSocketClient to throw errors when instantiated if passed `tlsOptions`.
|
||||
|
||||
Version 1.0.9
|
||||
-------------
|
||||
*Released 2014-10-20*
|
||||
|
||||
* Fixing an insidious corner-case bug that prevented `WebSocketConnection` from firing the `close` event in certain cases when there was an error on the underlying `Socket`, leading to connections sticking around forever, stuck erroneously in the `connected` state. These "ghost" connections would cause an error event when trying to write to them.
|
||||
* Removed deprecated `websocketVersion` property. Use `webSocketVersion` instead (case difference).
|
||||
* Allowing user to specify all properties for `tlsOptions` in WebSocketClient, not just a few whitelisted properties. This keeps us from having to constantly add new config properties for new versions of Node. (Thanks, [jesusprubio](https://github.com/jesusprubio))
|
||||
* Removing support for Node 0.4.x and 0.6.x.
|
||||
* Adding `fuzzingclient.json` spec file for the Autobahn Test Suite.
|
||||
* Now more fairly emitting `message` events from the `WebSocketConnection`. Previously, all buffered frames for a connection would be processed and all `message` events emitted before moving on to processing the next connection with available data. Now We process one frame per connection (most of the time) in a more fair round-robin fashion.
|
||||
* Now correctly calling the `EventEmitter` superclass constructor during class instance initialization.
|
||||
* `WebSocketClient.prototype.connect` now accepts the empty string (`''`) to mean "no subprotocol requested." Previously either `null` or an empty array (`[]`) was required.
|
||||
* Fixing a `TypeError` bug in `WebSocketRouter` (Thanks, [a0000778](https://github.com/a0000778))
|
||||
* Fixing a potential race condition when attaching event listeners to the underlying `Socket`. (Thanks [RichardBsolut](https://github.com/RichardBsolut))
|
||||
* `WebSocketClient` now accepts an optional options hash to be passed to `(http|https).request`. (Thanks [mildred](https://github.com/mildred) and [aus](https://github.com/aus)) This enables the following new abilities, amongst others:
|
||||
* Use WebSocket-Node from behind HTTP/HTTPS proxy servers using [koichik/node-tunnel](https://github.com/koichik/node-tunnel) or similar.
|
||||
* Specify the local port and local address to bind the outgoing request socket to.
|
||||
* Adding option to ignore `X-Forwarded-For` headers when accepting connections from untrusted clients.
|
||||
* Adding ability to mount a `WebSocketServer` instance to an arbitrary number of Node http/https servers.
|
||||
* Adding browser shim so Browserify won't blow up when trying to package up code that uses WebSocket-Node. The shim is a no-op, it ***does not implement a wrapper*** providing the WebSocket-Node API in the browser.
|
||||
* Incorporating upstream enhancements for the native C++ UTF-8 validation and xor masking functions. (Thanks [einaros](https://github.com/einaros) and [kkoopa](https://github.com/kkoopa))
|
||||
|
||||
|
||||
Version 1.0.8
|
||||
-------------
|
||||
*Released 2012-12-26*
|
||||
|
||||
* Fixed remaining naming inconsistency of "websocketVersion" as opposed to "webSocketVersion" throughout the code, and added deprecation warnings for use of the old casing throughout.
|
||||
* Fixed an issue with our case-insensitive handling of WebSocket subprotocols. Clients that requested a mixed-case subprotocol would end up failing the connection when the server accepted the connection, returning a lower-case version of the subprotocol name. Now we return the subprotocol name in the exact casing that was requested by the client, while still maintaining the case-insensitive verification logic for convenience and practicality.
|
||||
* Making sure that any socket-level activity timeout that may have been set on a TCP socket is removed when initializing a connection.
|
||||
* Added support for native TCP Keep-Alive instead of using the WebSocket ping/pong packets to serve that function.
|
||||
* Fixed cookie parsing to be compliant with RFC 2109
|
||||
|
||||
Version 1.0.7
|
||||
-------------
|
||||
*Released 2012-08-12*
|
||||
|
||||
* ***Native modules are now optional!*** If they fail to compile, WebSocket-Node will still work but will not verify that received UTF-8 data is valid, and xor masking/unmasking of payload data for security purposes will not be as efficient as it is performed in JavaScript instead of native code.
|
||||
* Reduced Node.JS version requirement back to v0.6.10
|
||||
|
||||
Version 1.0.6
|
||||
-------------
|
||||
*Released 2012-05-22*
|
||||
|
||||
* Now requires Node v0.6.13 since that's the first version that I can manage to successfully build the native UTF-8 validator with node-gyp through npm.
|
||||
|
||||
Version 1.0.5
|
||||
-------------
|
||||
*Released 2012-05-21*
|
||||
|
||||
* Fixes the issues that users were having building the native UTF-8 validator on Windows platforms. Special Thanks to:
|
||||
* [zerodivisi0n](https://github.com/zerodivisi0n)
|
||||
* [andreasbotsikas](https://github.com/andreasbotsikas)
|
||||
* Fixed accidental global variable usage (Thanks, [hakobera](https://github.com/hakobera)!)
|
||||
* Added callbacks to the send* methods that provide notification of messages being sent on the wire and any socket errors that may occur when sending a message. (Thanks, [zerodivisi0n](https://github.com/zerodivisi0n)!)
|
||||
* Added option to disable logging in the echo-server in the test folder (Thanks, [oberstet](https://github.com/oberstet)!)
|
||||
|
||||
|
||||
Version 1.0.4
|
||||
-------------
|
||||
*Released 2011-12-18*
|
||||
|
||||
* Now validates that incoming UTF-8 messages do, in fact, contain valid UTF-8 data. The connection is dropped with prejudice if invalid data is received. This strict behavior conforms to the WebSocket RFC and is verified by the Autobahn Test Suite. This is accomplished in a performant way by using a native C++ Node module created by [einaros](https://github.com/einaros).
|
||||
* Updated handling of connection closure to pass more of the Autobahn Test Suite.
|
||||
|
||||
Version 1.0.3
|
||||
-------------
|
||||
*Released 2011-12-18*
|
||||
|
||||
* Substantial speed increase (~150% on my machine, depending on the circumstances) due to an optimization in FastBufferList.js that drastically reduces the number of memory alloctions and buffer copying. ([kazuyukitanimura](https://github.com/kazuyukitanimura))
|
||||
|
||||
|
||||
Version 1.0.2
|
||||
-------------
|
||||
*Released 2011-11-28*
|
||||
|
||||
* Fixing whiteboard example to work under Node 0.6.x ([theturtle32](https://github.com/theturtle32))
|
||||
* Now correctly emitting a `close` event with a 1006 error code if there is a TCP error while writing to the socket during the handshake. ([theturtle32](https://github.com/theturtle32))
|
||||
* Catching errors when writing to the TCP socket during the handshake. ([justoneplanet](https://github.com/justoneplanet))
|
||||
* No longer outputting console.warn messages when there is an error writing to the TCP socket ([justoneplanet](https://github.com/justoneplanet))
|
||||
* Fixing some formatting errors, commas, semicolons, etc. ([kaisellgren](https://github.com/kaisellgren))
|
||||
|
||||
|
||||
Version 1.0.1
|
||||
-------------
|
||||
*Released 2011-11-21*
|
||||
|
||||
* Now works with Node 0.6.2 as well as 0.4.12
|
||||
* Support TLS in WebSocketClient
|
||||
* Added support for setting and reading cookies
|
||||
* Added WebSocketServer.prototype.broadcast(data) convenience method
|
||||
* Added `resourceURL` property to WebSocketRequest objects. It is a Node URL object with the `resource` and any query string params already parsed.
|
||||
* The WebSocket request router no longer includes the entire query string when trying to match the path name of the request.
|
||||
* WebSocketRouterRequest objects now include all the properties and events of WebSocketRequest objects.
|
||||
* Removed more console.log statements. Please rely on the various events emitted to be notified of error conditions. I decided that it is not a library's place to spew information to the console.
|
||||
* Renamed the `websocketVersion` property to `webSocketVersion` throughout the code to fix inconsistent capitalization. `websocketVersion` has been kept for compatibility but is deprecated and may be removed in the future.
|
||||
* Now outputting the sanitized version of custom header names rather than the raw value. This prevents invalid HTTP from being put onto the wire if given an illegal header name.
|
||||
|
||||
|
||||
I decided it's time to start maintaining a changelog now, starting with version 1.0.1.
|
177
node_modules/websocket/LICENSE
generated
vendored
Normal file
177
node_modules/websocket/LICENSE
generated
vendored
Normal file
@ -0,0 +1,177 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
11
node_modules/websocket/Makefile
generated
vendored
Normal file
11
node_modules/websocket/Makefile
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
all:
|
||||
node-gyp configure build
|
||||
|
||||
clean:
|
||||
node-gyp clean
|
||||
|
||||
autobahn:
|
||||
@NODE_PATH=lib node test/autobahn-test-client.js --host=127.0.0.1 --port=9000
|
||||
|
||||
autobahn-server:
|
||||
@NODE_PATH=lib node test/echo-server.js
|
276
node_modules/websocket/README.md
generated
vendored
Normal file
276
node_modules/websocket/README.md
generated
vendored
Normal file
@ -0,0 +1,276 @@
|
||||
WebSocket Client & Server Implementation for Node
|
||||
=================================================
|
||||
|
||||
[](http://badge.fury.io/js/websocket)
|
||||
|
||||
[](https://www.npmjs.com/package/websocket)
|
||||
|
||||
[](https://nodei.co/npm/websocket/)
|
||||
|
||||
[](https://nodei.co/npm/websocket/)
|
||||
|
||||
[ ](https://codeship.com/projects/61106)
|
||||
|
||||
Overview
|
||||
--------
|
||||
This is a (mostly) pure JavaScript implementation of the WebSocket protocol versions 8 and 13 for Node. There are some example client and server applications that implement various interoperability testing protocols in the "test/scripts" folder.
|
||||
|
||||
For a WebSocket client written in ActionScript 3, see my [AS3WebScocket](https://github.com/theturtle32/AS3WebSocket) project.
|
||||
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
[You can read the full API documentation in the docs folder.](docs/index.md)
|
||||
|
||||
|
||||
Changelog
|
||||
---------
|
||||
|
||||
***Current Version: 1.0.28*** — Released 2018-09-19
|
||||
|
||||
* Updated to latest version of [nan](https://github.com/nodejs/nan)
|
||||
* Plus changes published in 1.0.27:
|
||||
* Allowing additional request `headers` to be specified in the `tlsOptions` config parameter for WebSocketClient. See pull request #323
|
||||
* Resolving deprecation warnings relating to usage of `new Buffer`
|
||||
|
||||
[View the full changelog](CHANGELOG.md)
|
||||
|
||||
Browser Support
|
||||
---------------
|
||||
|
||||
All current browsers are fully supported.
|
||||
|
||||
* Firefox 7-9 (Old) (Protocol Version 8)
|
||||
* Firefox 10+ (Protocol Version 13)
|
||||
* Chrome 14,15 (Old) (Protocol Version 8)
|
||||
* Chrome 16+ (Protocol Version 13)
|
||||
* Internet Explorer 10+ (Protocol Version 13)
|
||||
* Safari 6+ (Protocol Version 13)
|
||||
|
||||
***Safari older than 6.0 is not supported since it uses a very old draft of WebSockets***
|
||||
|
||||
***If you need to simultaneously support legacy browser versions that had implemented draft-75/draft-76/draft-00, take a look here: https://gist.github.com/1428579***
|
||||
|
||||
Benchmarks
|
||||
----------
|
||||
There are some basic benchmarking sections in the Autobahn test suite. I've put up a [benchmark page](http://theturtle32.github.com/WebSocket-Node/benchmarks/) that shows the results from the Autobahn tests run against AutobahnServer 0.4.10, WebSocket-Node 1.0.2, WebSocket-Node 1.0.4, and ws 0.3.4.
|
||||
|
||||
Autobahn Tests
|
||||
--------------
|
||||
The very complete [Autobahn Test Suite](http://autobahn.ws/testsuite/) is used by most WebSocket implementations to test spec compliance and interoperability.
|
||||
|
||||
- [View Server Test Results](http://theturtle32.github.com/WebSocket-Node/test-report/servers/)
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
A few users have reported difficulties building the native extensions without first manually installing node-gyp. If you have trouble building the native extensions, make sure you've got a C++ compiler, and have done `npm install -g node-gyp` first.
|
||||
|
||||
Native extensions are optional, however, and WebSocket-Node will work even if the extensions cannot be compiled.
|
||||
|
||||
In your project root:
|
||||
|
||||
$ npm install websocket
|
||||
|
||||
Then in your code:
|
||||
|
||||
```javascript
|
||||
var WebSocketServer = require('websocket').server;
|
||||
var WebSocketClient = require('websocket').client;
|
||||
var WebSocketFrame = require('websocket').frame;
|
||||
var WebSocketRouter = require('websocket').router;
|
||||
var W3CWebSocket = require('websocket').w3cwebsocket;
|
||||
```
|
||||
|
||||
Note for Windows Users
|
||||
----------------------
|
||||
Because there is a small C++ component used for validating UTF-8 data, you will need to install a few other software packages in addition to Node to be able to build this module:
|
||||
|
||||
- [Microsoft Visual C++](http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-cpp-express)
|
||||
- [Python 2.7](http://www.python.org/download/) (NOT Python 3.x)
|
||||
|
||||
|
||||
Current Features:
|
||||
-----------------
|
||||
- Licensed under the Apache License, Version 2.0
|
||||
- Protocol version "8" and "13" (Draft-08 through the final RFC) framing and handshake
|
||||
- Can handle/aggregate received fragmented messages
|
||||
- Can fragment outgoing messages
|
||||
- Router to mount multiple applications to various path and protocol combinations
|
||||
- TLS supported for outbound connections via WebSocketClient
|
||||
- TLS supported for server connections (use https.createServer instead of http.createServer)
|
||||
- Thanks to [pors](https://github.com/pors) for confirming this!
|
||||
- Cookie setting and parsing
|
||||
- Tunable settings
|
||||
- Max Receivable Frame Size
|
||||
- Max Aggregate ReceivedMessage Size
|
||||
- Whether to fragment outgoing messages
|
||||
- Fragmentation chunk size for outgoing messages
|
||||
- Whether to automatically send ping frames for the purposes of keepalive
|
||||
- Keep-alive ping interval
|
||||
- Whether or not to automatically assemble received fragments (allows application to handle individual fragments directly)
|
||||
- How long to wait after sending a close frame for acknowledgment before closing the socket.
|
||||
- [W3C WebSocket API](http://www.w3.org/TR/websockets/) for applications running on both Node and browsers (via the `W3CWebSocket` class).
|
||||
|
||||
|
||||
Known Issues/Missing Features:
|
||||
------------------------------
|
||||
- No API for user-provided protocol extensions.
|
||||
|
||||
|
||||
Usage Examples
|
||||
==============
|
||||
|
||||
Server Example
|
||||
--------------
|
||||
|
||||
Here's a short example showing a server that echos back anything sent to it, whether utf-8 or binary.
|
||||
|
||||
```javascript
|
||||
#!/usr/bin/env node
|
||||
var WebSocketServer = require('websocket').server;
|
||||
var http = require('http');
|
||||
|
||||
var server = http.createServer(function(request, response) {
|
||||
console.log((new Date()) + ' Received request for ' + request.url);
|
||||
response.writeHead(404);
|
||||
response.end();
|
||||
});
|
||||
server.listen(8080, function() {
|
||||
console.log((new Date()) + ' Server is listening on port 8080');
|
||||
});
|
||||
|
||||
wsServer = new WebSocketServer({
|
||||
httpServer: server,
|
||||
// You should not use autoAcceptConnections for production
|
||||
// applications, as it defeats all standard cross-origin protection
|
||||
// facilities built into the protocol and the browser. You should
|
||||
// *always* verify the connection's origin and decide whether or not
|
||||
// to accept it.
|
||||
autoAcceptConnections: false
|
||||
});
|
||||
|
||||
function originIsAllowed(origin) {
|
||||
// put logic here to detect whether the specified origin is allowed.
|
||||
return true;
|
||||
}
|
||||
|
||||
wsServer.on('request', function(request) {
|
||||
if (!originIsAllowed(request.origin)) {
|
||||
// Make sure we only accept requests from an allowed origin
|
||||
request.reject();
|
||||
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
|
||||
return;
|
||||
}
|
||||
|
||||
var connection = request.accept('echo-protocol', request.origin);
|
||||
console.log((new Date()) + ' Connection accepted.');
|
||||
connection.on('message', function(message) {
|
||||
if (message.type === 'utf8') {
|
||||
console.log('Received Message: ' + message.utf8Data);
|
||||
connection.sendUTF(message.utf8Data);
|
||||
}
|
||||
else if (message.type === 'binary') {
|
||||
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
|
||||
connection.sendBytes(message.binaryData);
|
||||
}
|
||||
});
|
||||
connection.on('close', function(reasonCode, description) {
|
||||
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Client Example
|
||||
--------------
|
||||
|
||||
This is a simple example client that will print out any utf-8 messages it receives on the console, and periodically sends a random number.
|
||||
|
||||
*This code demonstrates a client in Node.js, not in the browser*
|
||||
|
||||
```javascript
|
||||
#!/usr/bin/env node
|
||||
var WebSocketClient = require('websocket').client;
|
||||
|
||||
var client = new WebSocketClient();
|
||||
|
||||
client.on('connectFailed', function(error) {
|
||||
console.log('Connect Error: ' + error.toString());
|
||||
});
|
||||
|
||||
client.on('connect', function(connection) {
|
||||
console.log('WebSocket Client Connected');
|
||||
connection.on('error', function(error) {
|
||||
console.log("Connection Error: " + error.toString());
|
||||
});
|
||||
connection.on('close', function() {
|
||||
console.log('echo-protocol Connection Closed');
|
||||
});
|
||||
connection.on('message', function(message) {
|
||||
if (message.type === 'utf8') {
|
||||
console.log("Received: '" + message.utf8Data + "'");
|
||||
}
|
||||
});
|
||||
|
||||
function sendNumber() {
|
||||
if (connection.connected) {
|
||||
var number = Math.round(Math.random() * 0xFFFFFF);
|
||||
connection.sendUTF(number.toString());
|
||||
setTimeout(sendNumber, 1000);
|
||||
}
|
||||
}
|
||||
sendNumber();
|
||||
});
|
||||
|
||||
client.connect('ws://localhost:8080/', 'echo-protocol');
|
||||
```
|
||||
|
||||
Client Example using the *W3C WebSocket API*
|
||||
--------------------------------------------
|
||||
|
||||
Same example as above but using the [W3C WebSocket API](http://www.w3.org/TR/websockets/).
|
||||
|
||||
```javascript
|
||||
var W3CWebSocket = require('websocket').w3cwebsocket;
|
||||
|
||||
var client = new W3CWebSocket('ws://localhost:8080/', 'echo-protocol');
|
||||
|
||||
client.onerror = function() {
|
||||
console.log('Connection Error');
|
||||
};
|
||||
|
||||
client.onopen = function() {
|
||||
console.log('WebSocket Client Connected');
|
||||
|
||||
function sendNumber() {
|
||||
if (client.readyState === client.OPEN) {
|
||||
var number = Math.round(Math.random() * 0xFFFFFF);
|
||||
client.send(number.toString());
|
||||
setTimeout(sendNumber, 1000);
|
||||
}
|
||||
}
|
||||
sendNumber();
|
||||
};
|
||||
|
||||
client.onclose = function() {
|
||||
console.log('echo-protocol Client Closed');
|
||||
};
|
||||
|
||||
client.onmessage = function(e) {
|
||||
if (typeof e.data === 'string') {
|
||||
console.log("Received: '" + e.data + "'");
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Request Router Example
|
||||
----------------------
|
||||
|
||||
For an example of using the request router, see `libwebsockets-test-server.js` in the `test` folder.
|
||||
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
A presentation on the state of the WebSockets protocol that I gave on July 23, 2011 at the LA Hacker News meetup. [WebSockets: The Real-Time Web, Delivered](http://www.scribd.com/doc/60898569/WebSockets-The-Real-Time-Web-Delivered)
|
18
node_modules/websocket/binding.gyp
generated
vendored
Normal file
18
node_modules/websocket/binding.gyp
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'validation',
|
||||
'include_dirs': ["<!(node -e \"require('nan')\")"],
|
||||
'cflags!': [ '-O3' ],
|
||||
'cflags': [ '-O2' ],
|
||||
'sources': [ 'src/validation.cc' ]
|
||||
},
|
||||
{
|
||||
'target_name': 'bufferutil',
|
||||
'include_dirs': ["<!(node -e \"require('nan')\")"],
|
||||
'cflags!': [ '-O3' ],
|
||||
'cflags': [ '-O2' ],
|
||||
'sources': [ 'src/bufferutil.cc' ]
|
||||
}
|
||||
]
|
||||
}
|
347
node_modules/websocket/build/Makefile
generated
vendored
Normal file
347
node_modules/websocket/build/Makefile
generated
vendored
Normal file
@ -0,0 +1,347 @@
|
||||
# We borrow heavily from the kernel build setup, though we are simpler since
|
||||
# we don't have Kconfig tweaking settings on us.
|
||||
|
||||
# The implicit make rules have it looking for RCS files, among other things.
|
||||
# We instead explicitly write all the rules we care about.
|
||||
# It's even quicker (saves ~200ms) to pass -r on the command line.
|
||||
MAKEFLAGS=-r
|
||||
|
||||
# The source directory tree.
|
||||
srcdir := ..
|
||||
abs_srcdir := $(abspath $(srcdir))
|
||||
|
||||
# The name of the builddir.
|
||||
builddir_name ?= .
|
||||
|
||||
# The V=1 flag on command line makes us verbosely print command lines.
|
||||
ifdef V
|
||||
quiet=
|
||||
else
|
||||
quiet=quiet_
|
||||
endif
|
||||
|
||||
# Specify BUILDTYPE=Release on the command line for a release build.
|
||||
BUILDTYPE ?= Release
|
||||
|
||||
# Directory all our build output goes into.
|
||||
# Note that this must be two directories beneath src/ for unit tests to pass,
|
||||
# as they reach into the src/ directory for data with relative paths.
|
||||
builddir ?= $(builddir_name)/$(BUILDTYPE)
|
||||
abs_builddir := $(abspath $(builddir))
|
||||
depsdir := $(builddir)/.deps
|
||||
|
||||
# Object output directory.
|
||||
obj := $(builddir)/obj
|
||||
abs_obj := $(abspath $(obj))
|
||||
|
||||
# We build up a list of every single one of the targets so we can slurp in the
|
||||
# generated dependency rule Makefiles in one pass.
|
||||
all_deps :=
|
||||
|
||||
|
||||
|
||||
CC.target ?= $(CC)
|
||||
CFLAGS.target ?= $(CPPFLAGS) $(CFLAGS)
|
||||
CXX.target ?= $(CXX)
|
||||
CXXFLAGS.target ?= $(CPPFLAGS) $(CXXFLAGS)
|
||||
LINK.target ?= $(LINK)
|
||||
LDFLAGS.target ?= $(LDFLAGS)
|
||||
AR.target ?= $(AR)
|
||||
|
||||
# C++ apps need to be linked with g++.
|
||||
LINK ?= $(CXX.target)
|
||||
|
||||
# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
|
||||
# to replicate this environment fallback in make as well.
|
||||
CC.host ?= gcc
|
||||
CFLAGS.host ?= $(CPPFLAGS_host) $(CFLAGS_host)
|
||||
CXX.host ?= g++
|
||||
CXXFLAGS.host ?= $(CPPFLAGS_host) $(CXXFLAGS_host)
|
||||
LINK.host ?= $(CXX.host)
|
||||
LDFLAGS.host ?=
|
||||
AR.host ?= ar
|
||||
|
||||
# Define a dir function that can handle spaces.
|
||||
# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
|
||||
# "leading spaces cannot appear in the text of the first argument as written.
|
||||
# These characters can be put into the argument value by variable substitution."
|
||||
empty :=
|
||||
space := $(empty) $(empty)
|
||||
|
||||
# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
|
||||
replace_spaces = $(subst $(space),?,$1)
|
||||
unreplace_spaces = $(subst ?,$(space),$1)
|
||||
dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
|
||||
|
||||
# Flags to make gcc output dependency info. Note that you need to be
|
||||
# careful here to use the flags that ccache and distcc can understand.
|
||||
# We write to a dep file on the side first and then rename at the end
|
||||
# so we can't end up with a broken dep file.
|
||||
depfile = $(depsdir)/$(call replace_spaces,$@).d
|
||||
DEPFLAGS = -MMD -MF $(depfile).raw
|
||||
|
||||
# We have to fixup the deps output in a few ways.
|
||||
# (1) the file output should mention the proper .o file.
|
||||
# ccache or distcc lose the path to the target, so we convert a rule of
|
||||
# the form:
|
||||
# foobar.o: DEP1 DEP2
|
||||
# into
|
||||
# path/to/foobar.o: DEP1 DEP2
|
||||
# (2) we want missing files not to cause us to fail to build.
|
||||
# We want to rewrite
|
||||
# foobar.o: DEP1 DEP2 \
|
||||
# DEP3
|
||||
# to
|
||||
# DEP1:
|
||||
# DEP2:
|
||||
# DEP3:
|
||||
# so if the files are missing, they're just considered phony rules.
|
||||
# We have to do some pretty insane escaping to get those backslashes
|
||||
# and dollar signs past make, the shell, and sed at the same time.
|
||||
# Doesn't work with spaces, but that's fine: .d files have spaces in
|
||||
# their names replaced with other characters.
|
||||
define fixup_dep
|
||||
# The depfile may not exist if the input file didn't have any #includes.
|
||||
touch $(depfile).raw
|
||||
# Fixup path as in (1).
|
||||
sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
|
||||
# Add extra rules as in (2).
|
||||
# We remove slashes and replace spaces with new lines;
|
||||
# remove blank lines;
|
||||
# delete the first line and append a colon to the remaining lines.
|
||||
sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
|
||||
grep -v '^$$' |\
|
||||
sed -e 1d -e 's|$$|:|' \
|
||||
>> $(depfile)
|
||||
rm $(depfile).raw
|
||||
endef
|
||||
|
||||
# Command definitions:
|
||||
# - cmd_foo is the actual command to run;
|
||||
# - quiet_cmd_foo is the brief-output summary of the command.
|
||||
|
||||
quiet_cmd_cc = CC($(TOOLSET)) $@
|
||||
cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
|
||||
|
||||
quiet_cmd_cxx = CXX($(TOOLSET)) $@
|
||||
cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
|
||||
|
||||
quiet_cmd_objc = CXX($(TOOLSET)) $@
|
||||
cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
|
||||
|
||||
quiet_cmd_objcxx = CXX($(TOOLSET)) $@
|
||||
cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
|
||||
|
||||
# Commands for precompiled header files.
|
||||
quiet_cmd_pch_c = CXX($(TOOLSET)) $@
|
||||
cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
|
||||
quiet_cmd_pch_cc = CXX($(TOOLSET)) $@
|
||||
cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
|
||||
quiet_cmd_pch_m = CXX($(TOOLSET)) $@
|
||||
cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
|
||||
quiet_cmd_pch_mm = CXX($(TOOLSET)) $@
|
||||
cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
|
||||
|
||||
# gyp-mac-tool is written next to the root Makefile by gyp.
|
||||
# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd
|
||||
# already.
|
||||
quiet_cmd_mac_tool = MACTOOL $(4) $<
|
||||
cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@"
|
||||
|
||||
quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@
|
||||
cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4)
|
||||
|
||||
quiet_cmd_infoplist = INFOPLIST $@
|
||||
cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@"
|
||||
|
||||
quiet_cmd_touch = TOUCH $@
|
||||
cmd_touch = touch $@
|
||||
|
||||
quiet_cmd_copy = COPY $@
|
||||
# send stderr to /dev/null to ignore messages when linking directories.
|
||||
cmd_copy = rm -rf "$@" && cp -af "$<" "$@"
|
||||
|
||||
quiet_cmd_alink = LIBTOOL-STATIC $@
|
||||
cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool $(GYP_LIBTOOLFLAGS) -static -o $@ $(filter %.o,$^)
|
||||
|
||||
quiet_cmd_link = LINK($(TOOLSET)) $@
|
||||
cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
|
||||
|
||||
quiet_cmd_solink = SOLINK($(TOOLSET)) $@
|
||||
cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
|
||||
|
||||
quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
|
||||
cmd_solink_module = $(LINK.$(TOOLSET)) -bundle $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
|
||||
|
||||
|
||||
# Define an escape_quotes function to escape single quotes.
|
||||
# This allows us to handle quotes properly as long as we always use
|
||||
# use single quotes and escape_quotes.
|
||||
escape_quotes = $(subst ','\'',$(1))
|
||||
# This comment is here just to include a ' to unconfuse syntax highlighting.
|
||||
# Define an escape_vars function to escape '$' variable syntax.
|
||||
# This allows us to read/write command lines with shell variables (e.g.
|
||||
# $LD_LIBRARY_PATH), without triggering make substitution.
|
||||
escape_vars = $(subst $$,$$$$,$(1))
|
||||
# Helper that expands to a shell command to echo a string exactly as it is in
|
||||
# make. This uses printf instead of echo because printf's behaviour with respect
|
||||
# to escape sequences is more portable than echo's across different shells
|
||||
# (e.g., dash, bash).
|
||||
exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
|
||||
|
||||
# Helper to compare the command we're about to run against the command
|
||||
# we logged the last time we ran the command. Produces an empty
|
||||
# string (false) when the commands match.
|
||||
# Tricky point: Make has no string-equality test function.
|
||||
# The kernel uses the following, but it seems like it would have false
|
||||
# positives, where one string reordered its arguments.
|
||||
# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
|
||||
# $(filter-out $(cmd_$@), $(cmd_$(1))))
|
||||
# We instead substitute each for the empty string into the other, and
|
||||
# say they're equal if both substitutions produce the empty string.
|
||||
# .d files contain ? instead of spaces, take that into account.
|
||||
command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
|
||||
$(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
|
||||
|
||||
# Helper that is non-empty when a prerequisite changes.
|
||||
# Normally make does this implicitly, but we force rules to always run
|
||||
# so we can check their command lines.
|
||||
# $? -- new prerequisites
|
||||
# $| -- order-only dependencies
|
||||
prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
|
||||
|
||||
# Helper that executes all postbuilds until one fails.
|
||||
define do_postbuilds
|
||||
@E=0;\
|
||||
for p in $(POSTBUILDS); do\
|
||||
eval $$p;\
|
||||
E=$$?;\
|
||||
if [ $$E -ne 0 ]; then\
|
||||
break;\
|
||||
fi;\
|
||||
done;\
|
||||
if [ $$E -ne 0 ]; then\
|
||||
rm -rf "$@";\
|
||||
exit $$E;\
|
||||
fi
|
||||
endef
|
||||
|
||||
# do_cmd: run a command via the above cmd_foo names, if necessary.
|
||||
# Should always run for a given target to handle command-line changes.
|
||||
# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
|
||||
# Third argument, if non-zero, makes it do POSTBUILDS processing.
|
||||
# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
|
||||
# spaces already and dirx strips the ? characters.
|
||||
define do_cmd
|
||||
$(if $(or $(command_changed),$(prereq_changed)),
|
||||
@$(call exact_echo, $($(quiet)cmd_$(1)))
|
||||
@mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
|
||||
$(if $(findstring flock,$(word 2,$(cmd_$1))),
|
||||
@$(cmd_$(1))
|
||||
@echo " $(quiet_cmd_$(1)): Finished",
|
||||
@$(cmd_$(1))
|
||||
)
|
||||
@$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
|
||||
@$(if $(2),$(fixup_dep))
|
||||
$(if $(and $(3), $(POSTBUILDS)),
|
||||
$(call do_postbuilds)
|
||||
)
|
||||
)
|
||||
endef
|
||||
|
||||
# Declare the "all" target first so it is the default,
|
||||
# even though we don't have the deps yet.
|
||||
.PHONY: all
|
||||
all:
|
||||
|
||||
# make looks for ways to re-generate included makefiles, but in our case, we
|
||||
# don't have a direct way. Explicitly telling make that it has nothing to do
|
||||
# for them makes it go faster.
|
||||
%.d: ;
|
||||
|
||||
# Use FORCE_DO_CMD to force a target to run. Should be coupled with
|
||||
# do_cmd.
|
||||
.PHONY: FORCE_DO_CMD
|
||||
FORCE_DO_CMD:
|
||||
|
||||
TOOLSET := target
|
||||
# Suffix rules, putting all outputs into $(obj).
|
||||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.m FORCE_DO_CMD
|
||||
@$(call do_cmd,objc,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.mm FORCE_DO_CMD
|
||||
@$(call do_cmd,objcxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
|
||||
# Try building from generated source, too.
|
||||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.m FORCE_DO_CMD
|
||||
@$(call do_cmd,objc,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.mm FORCE_DO_CMD
|
||||
@$(call do_cmd,objcxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
|
||||
$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj)/%.m FORCE_DO_CMD
|
||||
@$(call do_cmd,objc,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj)/%.mm FORCE_DO_CMD
|
||||
@$(call do_cmd,objcxx,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
|
||||
@$(call do_cmd,cc,1)
|
||||
|
||||
|
||||
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
|
||||
$(findstring $(join ^,$(prefix)),\
|
||||
$(join ^,bufferutil.target.mk)))),)
|
||||
include bufferutil.target.mk
|
||||
endif
|
||||
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
|
||||
$(findstring $(join ^,$(prefix)),\
|
||||
$(join ^,validation.target.mk)))),)
|
||||
include validation.target.mk
|
||||
endif
|
||||
|
||||
quiet_cmd_regen_makefile = ACTION Regenerating $@
|
||||
cmd_regen_makefile = cd $(srcdir); /usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "--toplevel-dir=." -I/Users/josh.burman/Projects/braid/node_modules/websocket/build/config.gypi -I/usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi -I/Users/josh.burman/.node-gyp/11.10.0/include/node/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/Users/josh.burman/.node-gyp/11.10.0" "-Dnode_gyp_dir=/usr/local/lib/node_modules/npm/node_modules/node-gyp" "-Dnode_lib_file=/Users/josh.burman/.node-gyp/11.10.0/<(target_arch)/node.lib" "-Dmodule_root_dir=/Users/josh.burman/Projects/braid/node_modules/websocket" "-Dnode_engine=v8" binding.gyp
|
||||
Makefile: $(srcdir)/../../../../.node-gyp/11.10.0/include/node/common.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../../../usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi
|
||||
$(call do_cmd,regen_makefile)
|
||||
|
||||
# "all" is a concatenation of the "all" targets from all the included
|
||||
# sub-makefiles. This is just here to clarify.
|
||||
all:
|
||||
|
||||
# Add in dependency-tracking rules. $(all_deps) is the list of every single
|
||||
# target in our tree. Only consider the ones with .d (dependency) info:
|
||||
d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
|
||||
ifneq ($(d_files),)
|
||||
include $(d_files)
|
||||
endif
|
1
node_modules/websocket/build/Release/.deps/Release/bufferutil.node.d
generated
vendored
Normal file
1
node_modules/websocket/build/Release/.deps/Release/bufferutil.node.d
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
cmd_Release/bufferutil.node := c++ -bundle -undefined dynamic_lookup -Wl,-no_pie -Wl,-search_paths_first -mmacosx-version-min=10.7 -arch x86_64 -L./Release -stdlib=libc++ -o Release/bufferutil.node Release/obj.target/bufferutil/src/bufferutil.o
|
52
node_modules/websocket/build/Release/.deps/Release/obj.target/bufferutil/src/bufferutil.o.d
generated
vendored
Normal file
52
node_modules/websocket/build/Release/.deps/Release/obj.target/bufferutil/src/bufferutil.o.d
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
cmd_Release/obj.target/bufferutil/src/bufferutil.o := c++ '-DNODE_GYP_MODULE_NAME=bufferutil' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-D_DARWIN_USE_64_BIT_INODE=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/Users/josh.burman/.node-gyp/11.10.0/include/node -I/Users/josh.burman/.node-gyp/11.10.0/src -I/Users/josh.burman/.node-gyp/11.10.0/deps/openssl/config -I/Users/josh.burman/.node-gyp/11.10.0/deps/openssl/openssl/include -I/Users/josh.burman/.node-gyp/11.10.0/deps/uv/include -I/Users/josh.burman/.node-gyp/11.10.0/deps/zlib -I/Users/josh.burman/.node-gyp/11.10.0/deps/v8/include -I../../nan -Os -gdwarf-2 -mmacosx-version-min=10.7 -arch x86_64 -Wall -Wendif-labels -W -Wno-unused-parameter -std=gnu++1y -stdlib=libc++ -fno-rtti -fno-exceptions -fno-strict-aliasing -MMD -MF ./Release/.deps/Release/obj.target/bufferutil/src/bufferutil.o.d.raw -c -o Release/obj.target/bufferutil/src/bufferutil.o ../src/bufferutil.cc
|
||||
Release/obj.target/bufferutil/src/bufferutil.o: ../src/bufferutil.cc \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8-version.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8config.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8-platform.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node_version.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node_buffer.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node_object_wrap.h \
|
||||
../../nan/nan.h /Users/josh.burman/.node-gyp/11.10.0/include/node/uv.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/errno.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/version.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/unix.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/threadpool.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/darwin.h \
|
||||
../../nan/nan_callbacks.h ../../nan/nan_callbacks_12_inl.h \
|
||||
../../nan/nan_maybe_43_inl.h ../../nan/nan_converters.h \
|
||||
../../nan/nan_converters_43_inl.h ../../nan/nan_new.h \
|
||||
../../nan/nan_implementation_12_inl.h \
|
||||
../../nan/nan_persistent_12_inl.h ../../nan/nan_weak.h \
|
||||
../../nan/nan_object_wrap.h ../../nan/nan_private.h \
|
||||
../../nan/nan_typedarray_contents.h ../../nan/nan_json.h
|
||||
../src/bufferutil.cc:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8-version.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8config.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8-platform.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node_version.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node_buffer.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node_object_wrap.h:
|
||||
../../nan/nan.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/errno.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/version.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/unix.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/threadpool.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/darwin.h:
|
||||
../../nan/nan_callbacks.h:
|
||||
../../nan/nan_callbacks_12_inl.h:
|
||||
../../nan/nan_maybe_43_inl.h:
|
||||
../../nan/nan_converters.h:
|
||||
../../nan/nan_converters_43_inl.h:
|
||||
../../nan/nan_new.h:
|
||||
../../nan/nan_implementation_12_inl.h:
|
||||
../../nan/nan_persistent_12_inl.h:
|
||||
../../nan/nan_weak.h:
|
||||
../../nan/nan_object_wrap.h:
|
||||
../../nan/nan_private.h:
|
||||
../../nan/nan_typedarray_contents.h:
|
||||
../../nan/nan_json.h:
|
52
node_modules/websocket/build/Release/.deps/Release/obj.target/validation/src/validation.o.d
generated
vendored
Normal file
52
node_modules/websocket/build/Release/.deps/Release/obj.target/validation/src/validation.o.d
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
cmd_Release/obj.target/validation/src/validation.o := c++ '-DNODE_GYP_MODULE_NAME=validation' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-D_DARWIN_USE_64_BIT_INODE=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/Users/josh.burman/.node-gyp/11.10.0/include/node -I/Users/josh.burman/.node-gyp/11.10.0/src -I/Users/josh.burman/.node-gyp/11.10.0/deps/openssl/config -I/Users/josh.burman/.node-gyp/11.10.0/deps/openssl/openssl/include -I/Users/josh.burman/.node-gyp/11.10.0/deps/uv/include -I/Users/josh.burman/.node-gyp/11.10.0/deps/zlib -I/Users/josh.burman/.node-gyp/11.10.0/deps/v8/include -I../../nan -Os -gdwarf-2 -mmacosx-version-min=10.7 -arch x86_64 -Wall -Wendif-labels -W -Wno-unused-parameter -std=gnu++1y -stdlib=libc++ -fno-rtti -fno-exceptions -fno-strict-aliasing -MMD -MF ./Release/.deps/Release/obj.target/validation/src/validation.o.d.raw -c -o Release/obj.target/validation/src/validation.o ../src/validation.cc
|
||||
Release/obj.target/validation/src/validation.o: ../src/validation.cc \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8-version.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8config.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8-platform.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node_version.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node_buffer.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node_object_wrap.h \
|
||||
../../nan/nan.h /Users/josh.burman/.node-gyp/11.10.0/include/node/uv.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/errno.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/version.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/unix.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/threadpool.h \
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/darwin.h \
|
||||
../../nan/nan_callbacks.h ../../nan/nan_callbacks_12_inl.h \
|
||||
../../nan/nan_maybe_43_inl.h ../../nan/nan_converters.h \
|
||||
../../nan/nan_converters_43_inl.h ../../nan/nan_new.h \
|
||||
../../nan/nan_implementation_12_inl.h \
|
||||
../../nan/nan_persistent_12_inl.h ../../nan/nan_weak.h \
|
||||
../../nan/nan_object_wrap.h ../../nan/nan_private.h \
|
||||
../../nan/nan_typedarray_contents.h ../../nan/nan_json.h
|
||||
../src/validation.cc:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8-version.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8config.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8-platform.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node_version.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node_buffer.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/node_object_wrap.h:
|
||||
../../nan/nan.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/errno.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/version.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/unix.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/threadpool.h:
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/uv/darwin.h:
|
||||
../../nan/nan_callbacks.h:
|
||||
../../nan/nan_callbacks_12_inl.h:
|
||||
../../nan/nan_maybe_43_inl.h:
|
||||
../../nan/nan_converters.h:
|
||||
../../nan/nan_converters_43_inl.h:
|
||||
../../nan/nan_new.h:
|
||||
../../nan/nan_implementation_12_inl.h:
|
||||
../../nan/nan_persistent_12_inl.h:
|
||||
../../nan/nan_weak.h:
|
||||
../../nan/nan_object_wrap.h:
|
||||
../../nan/nan_private.h:
|
||||
../../nan/nan_typedarray_contents.h:
|
||||
../../nan/nan_json.h:
|
1
node_modules/websocket/build/Release/.deps/Release/validation.node.d
generated
vendored
Normal file
1
node_modules/websocket/build/Release/.deps/Release/validation.node.d
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
cmd_Release/validation.node := c++ -bundle -undefined dynamic_lookup -Wl,-no_pie -Wl,-search_paths_first -mmacosx-version-min=10.7 -arch x86_64 -L./Release -stdlib=libc++ -o Release/validation.node Release/obj.target/validation/src/validation.o
|
BIN
node_modules/websocket/build/Release/bufferutil.node
generated
vendored
Executable file
BIN
node_modules/websocket/build/Release/bufferutil.node
generated
vendored
Executable file
Binary file not shown.
BIN
node_modules/websocket/build/Release/obj.target/bufferutil/src/bufferutil.o
generated
vendored
Normal file
BIN
node_modules/websocket/build/Release/obj.target/bufferutil/src/bufferutil.o
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/websocket/build/Release/obj.target/validation/src/validation.o
generated
vendored
Normal file
BIN
node_modules/websocket/build/Release/obj.target/validation/src/validation.o
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/websocket/build/Release/validation.node
generated
vendored
Executable file
BIN
node_modules/websocket/build/Release/validation.node
generated
vendored
Executable file
Binary file not shown.
6
node_modules/websocket/build/binding.Makefile
generated
vendored
Normal file
6
node_modules/websocket/build/binding.Makefile
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# This file is generated by gyp; do not edit.
|
||||
|
||||
export builddir_name ?= ./build/.
|
||||
.PHONY: all
|
||||
all:
|
||||
$(MAKE) bufferutil validation
|
184
node_modules/websocket/build/bufferutil.target.mk
generated
vendored
Normal file
184
node_modules/websocket/build/bufferutil.target.mk
generated
vendored
Normal file
@ -0,0 +1,184 @@
|
||||
# This file is generated by gyp; do not edit.
|
||||
|
||||
TOOLSET := target
|
||||
TARGET := bufferutil
|
||||
DEFS_Debug := \
|
||||
'-DNODE_GYP_MODULE_NAME=bufferutil' \
|
||||
'-DUSING_UV_SHARED=1' \
|
||||
'-DUSING_V8_SHARED=1' \
|
||||
'-DV8_DEPRECATION_WARNINGS=1' \
|
||||
'-D_DARWIN_USE_64_BIT_INODE=1' \
|
||||
'-D_LARGEFILE_SOURCE' \
|
||||
'-D_FILE_OFFSET_BITS=64' \
|
||||
'-DBUILDING_NODE_EXTENSION' \
|
||||
'-DDEBUG' \
|
||||
'-D_DEBUG' \
|
||||
'-DV8_ENABLE_CHECKS'
|
||||
|
||||
# Flags passed to all source files.
|
||||
CFLAGS_Debug := \
|
||||
-O0 \
|
||||
-gdwarf-2 \
|
||||
-mmacosx-version-min=10.7 \
|
||||
-arch x86_64 \
|
||||
-Wall \
|
||||
-Wendif-labels \
|
||||
-W \
|
||||
-Wno-unused-parameter
|
||||
|
||||
# Flags passed to only C files.
|
||||
CFLAGS_C_Debug := \
|
||||
-fno-strict-aliasing
|
||||
|
||||
# Flags passed to only C++ files.
|
||||
CFLAGS_CC_Debug := \
|
||||
-std=gnu++1y \
|
||||
-stdlib=libc++ \
|
||||
-fno-rtti \
|
||||
-fno-exceptions \
|
||||
-fno-strict-aliasing
|
||||
|
||||
# Flags passed to only ObjC files.
|
||||
CFLAGS_OBJC_Debug :=
|
||||
|
||||
# Flags passed to only ObjC++ files.
|
||||
CFLAGS_OBJCC_Debug :=
|
||||
|
||||
INCS_Debug := \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/include/node \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/src \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/openssl/config \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/openssl/openssl/include \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/uv/include \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/zlib \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/v8/include \
|
||||
-I$(srcdir)/../nan
|
||||
|
||||
DEFS_Release := \
|
||||
'-DNODE_GYP_MODULE_NAME=bufferutil' \
|
||||
'-DUSING_UV_SHARED=1' \
|
||||
'-DUSING_V8_SHARED=1' \
|
||||
'-DV8_DEPRECATION_WARNINGS=1' \
|
||||
'-D_DARWIN_USE_64_BIT_INODE=1' \
|
||||
'-D_LARGEFILE_SOURCE' \
|
||||
'-D_FILE_OFFSET_BITS=64' \
|
||||
'-DBUILDING_NODE_EXTENSION'
|
||||
|
||||
# Flags passed to all source files.
|
||||
CFLAGS_Release := \
|
||||
-Os \
|
||||
-gdwarf-2 \
|
||||
-mmacosx-version-min=10.7 \
|
||||
-arch x86_64 \
|
||||
-Wall \
|
||||
-Wendif-labels \
|
||||
-W \
|
||||
-Wno-unused-parameter
|
||||
|
||||
# Flags passed to only C files.
|
||||
CFLAGS_C_Release := \
|
||||
-fno-strict-aliasing
|
||||
|
||||
# Flags passed to only C++ files.
|
||||
CFLAGS_CC_Release := \
|
||||
-std=gnu++1y \
|
||||
-stdlib=libc++ \
|
||||
-fno-rtti \
|
||||
-fno-exceptions \
|
||||
-fno-strict-aliasing
|
||||
|
||||
# Flags passed to only ObjC files.
|
||||
CFLAGS_OBJC_Release :=
|
||||
|
||||
# Flags passed to only ObjC++ files.
|
||||
CFLAGS_OBJCC_Release :=
|
||||
|
||||
INCS_Release := \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/include/node \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/src \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/openssl/config \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/openssl/openssl/include \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/uv/include \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/zlib \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/v8/include \
|
||||
-I$(srcdir)/../nan
|
||||
|
||||
OBJS := \
|
||||
$(obj).target/$(TARGET)/src/bufferutil.o
|
||||
|
||||
# Add to the list of files we specially track dependencies for.
|
||||
all_deps += $(OBJS)
|
||||
|
||||
# CFLAGS et al overrides must be target-local.
|
||||
# See "Target-specific Variable Values" in the GNU Make manual.
|
||||
$(OBJS): TOOLSET := $(TOOLSET)
|
||||
$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
|
||||
$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
|
||||
$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
|
||||
$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
|
||||
|
||||
# Suffix rules, putting all outputs into $(obj).
|
||||
|
||||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
|
||||
# Try building from generated source, too.
|
||||
|
||||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
|
||||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
|
||||
# End of this set of suffix rules
|
||||
### Rules for final target.
|
||||
LDFLAGS_Debug := \
|
||||
-undefined dynamic_lookup \
|
||||
-Wl,-no_pie \
|
||||
-Wl,-search_paths_first \
|
||||
-mmacosx-version-min=10.7 \
|
||||
-arch x86_64 \
|
||||
-L$(builddir) \
|
||||
-stdlib=libc++
|
||||
|
||||
LIBTOOLFLAGS_Debug := \
|
||||
-undefined dynamic_lookup \
|
||||
-Wl,-no_pie \
|
||||
-Wl,-search_paths_first
|
||||
|
||||
LDFLAGS_Release := \
|
||||
-undefined dynamic_lookup \
|
||||
-Wl,-no_pie \
|
||||
-Wl,-search_paths_first \
|
||||
-mmacosx-version-min=10.7 \
|
||||
-arch x86_64 \
|
||||
-L$(builddir) \
|
||||
-stdlib=libc++
|
||||
|
||||
LIBTOOLFLAGS_Release := \
|
||||
-undefined dynamic_lookup \
|
||||
-Wl,-no_pie \
|
||||
-Wl,-search_paths_first
|
||||
|
||||
LIBS :=
|
||||
|
||||
$(builddir)/bufferutil.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
|
||||
$(builddir)/bufferutil.node: LIBS := $(LIBS)
|
||||
$(builddir)/bufferutil.node: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE))
|
||||
$(builddir)/bufferutil.node: TOOLSET := $(TOOLSET)
|
||||
$(builddir)/bufferutil.node: $(OBJS) FORCE_DO_CMD
|
||||
$(call do_cmd,solink_module)
|
||||
|
||||
all_deps += $(builddir)/bufferutil.node
|
||||
# Add target alias
|
||||
.PHONY: bufferutil
|
||||
bufferutil: $(builddir)/bufferutil.node
|
||||
|
||||
# Short alias for building this executable.
|
||||
.PHONY: bufferutil.node
|
||||
bufferutil.node: $(builddir)/bufferutil.node
|
||||
|
||||
# Add executable to "all" target.
|
||||
.PHONY: all
|
||||
all: $(builddir)/bufferutil.node
|
||||
|
191
node_modules/websocket/build/config.gypi
generated
vendored
Normal file
191
node_modules/websocket/build/config.gypi
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
# Do not edit. File was generated by node-gyp's "configure" step
|
||||
{
|
||||
"target_defaults": {
|
||||
"cflags": [],
|
||||
"default_configuration": "Release",
|
||||
"defines": [],
|
||||
"include_dirs": [],
|
||||
"libraries": []
|
||||
},
|
||||
"variables": {
|
||||
"asan": 0,
|
||||
"build_v8_with_gn": "false",
|
||||
"coverage": "false",
|
||||
"debug_nghttp2": "false",
|
||||
"enable_lto": "false",
|
||||
"enable_pgo_generate": "false",
|
||||
"enable_pgo_use": "false",
|
||||
"force_dynamic_crt": 0,
|
||||
"host_arch": "x64",
|
||||
"icu_gyp_path": "tools/icu/icu-system.gyp",
|
||||
"icu_small": "false",
|
||||
"icu_ver_major": "63",
|
||||
"llvm_version": "0",
|
||||
"node_byteorder": "little",
|
||||
"node_debug_lib": "false",
|
||||
"node_enable_d8": "false",
|
||||
"node_enable_v8_vtunejit": "false",
|
||||
"node_experimental_http_parser": "false",
|
||||
"node_install_npm": "false",
|
||||
"node_module_version": 67,
|
||||
"node_no_browser_globals": "false",
|
||||
"node_prefix": "/usr/local/Cellar/node/11.10.0",
|
||||
"node_release_urlbase": "",
|
||||
"node_report": "true",
|
||||
"node_shared": "false",
|
||||
"node_shared_cares": "false",
|
||||
"node_shared_http_parser": "false",
|
||||
"node_shared_libuv": "false",
|
||||
"node_shared_nghttp2": "false",
|
||||
"node_shared_openssl": "false",
|
||||
"node_shared_zlib": "false",
|
||||
"node_tag": "",
|
||||
"node_target_type": "executable",
|
||||
"node_use_bundled_v8": "true",
|
||||
"node_use_dtrace": "true",
|
||||
"node_use_etw": "false",
|
||||
"node_use_large_pages": "false",
|
||||
"node_use_openssl": "true",
|
||||
"node_use_pch": "false",
|
||||
"node_use_v8_platform": "true",
|
||||
"node_with_ltcg": "false",
|
||||
"node_without_node_options": "false",
|
||||
"openssl_fips": "",
|
||||
"openssl_is_fips": "false",
|
||||
"shlib_suffix": "67.dylib",
|
||||
"target_arch": "x64",
|
||||
"v8_enable_gdbjit": 0,
|
||||
"v8_enable_i18n_support": 1,
|
||||
"v8_enable_inspector": 1,
|
||||
"v8_no_strict_aliasing": 1,
|
||||
"v8_optimized_debug": 1,
|
||||
"v8_promise_internal_field_count": 1,
|
||||
"v8_random_seed": 0,
|
||||
"v8_trace_maps": 0,
|
||||
"v8_typed_array_max_size_in_heap": 0,
|
||||
"v8_use_snapshot": "true",
|
||||
"want_separate_host_toolset": 0,
|
||||
"xcode_version": "9.0",
|
||||
"nodedir": "/Users/josh.burman/.node-gyp/11.10.0",
|
||||
"standalone_static_library": 1,
|
||||
"dry_run": "",
|
||||
"legacy_bundling": "",
|
||||
"save_dev": "",
|
||||
"browser": "",
|
||||
"commit_hooks": "true",
|
||||
"only": "",
|
||||
"viewer": "man",
|
||||
"also": "",
|
||||
"rollback": "true",
|
||||
"sign_git_commit": "",
|
||||
"audit": "true",
|
||||
"usage": "",
|
||||
"globalignorefile": "/usr/local/etc/npmignore",
|
||||
"init_author_url": "",
|
||||
"maxsockets": "50",
|
||||
"shell": "/bin/zsh",
|
||||
"metrics_registry": "https://registry.npmjs.org/",
|
||||
"parseable": "",
|
||||
"shrinkwrap": "true",
|
||||
"init_license": "ISC",
|
||||
"timing": "",
|
||||
"if_present": "",
|
||||
"cache_max": "Infinity",
|
||||
"init_author_email": "",
|
||||
"sign_git_tag": "",
|
||||
"cert": "",
|
||||
"git_tag_version": "true",
|
||||
"local_address": "",
|
||||
"long": "",
|
||||
"preid": "",
|
||||
"fetch_retries": "2",
|
||||
"noproxy": "",
|
||||
"registry": "https://registry.npmjs.org/",
|
||||
"key": "",
|
||||
"message": "%s",
|
||||
"versions": "",
|
||||
"globalconfig": "/usr/local/etc/npmrc",
|
||||
"always_auth": "",
|
||||
"logs_max": "10",
|
||||
"prefer_online": "",
|
||||
"cache_lock_retries": "10",
|
||||
"global_style": "",
|
||||
"update_notifier": "true",
|
||||
"audit_level": "low",
|
||||
"heading": "npm",
|
||||
"fetch_retry_mintimeout": "10000",
|
||||
"offline": "",
|
||||
"read_only": "",
|
||||
"searchlimit": "20",
|
||||
"access": "",
|
||||
"json": "",
|
||||
"allow_same_version": "",
|
||||
"description": "true",
|
||||
"engine_strict": "",
|
||||
"https_proxy": "",
|
||||
"init_module": "/Users/josh.burman/.npm-init.js",
|
||||
"userconfig": "/Users/josh.burman/.npmrc",
|
||||
"cidr": "",
|
||||
"node_version": "11.10.0",
|
||||
"user": "",
|
||||
"save": "true",
|
||||
"auth_type": "legacy",
|
||||
"editor": "vi",
|
||||
"ignore_prepublish": "",
|
||||
"script_shell": "",
|
||||
"tag": "latest",
|
||||
"global": "",
|
||||
"progress": "true",
|
||||
"ham_it_up": "",
|
||||
"optional": "true",
|
||||
"searchstaleness": "900",
|
||||
"bin_links": "true",
|
||||
"force": "",
|
||||
"save_prod": "",
|
||||
"searchopts": "",
|
||||
"depth": "Infinity",
|
||||
"node_gyp": "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js",
|
||||
"rebuild_bundle": "true",
|
||||
"sso_poll_frequency": "500",
|
||||
"unicode": "true",
|
||||
"fetch_retry_maxtimeout": "60000",
|
||||
"ca": "",
|
||||
"save_prefix": "^",
|
||||
"scripts_prepend_node_path": "warn-only",
|
||||
"sso_type": "oauth",
|
||||
"strict_ssl": "true",
|
||||
"tag_version_prefix": "v",
|
||||
"dev": "",
|
||||
"fetch_retry_factor": "10",
|
||||
"group": "20",
|
||||
"save_exact": "",
|
||||
"cache_lock_stale": "60000",
|
||||
"prefer_offline": "",
|
||||
"version": "",
|
||||
"cache_min": "10",
|
||||
"otp": "",
|
||||
"cache": "/Users/josh.burman/.npm",
|
||||
"searchexclude": "",
|
||||
"color": "true",
|
||||
"package_lock": "true",
|
||||
"package_lock_only": "",
|
||||
"save_optional": "",
|
||||
"user_agent": "npm/6.7.0 node/v11.10.0 darwin x64",
|
||||
"ignore_scripts": "",
|
||||
"cache_lock_wait": "10000",
|
||||
"production": "",
|
||||
"save_bundle": "",
|
||||
"send_metrics": "",
|
||||
"init_version": "1.0.0",
|
||||
"node_options": "",
|
||||
"umask": "0022",
|
||||
"scope": "",
|
||||
"git": "git",
|
||||
"init_author_name": "",
|
||||
"onload_script": "",
|
||||
"tmp": "/var/folders/69/6xf1g9sx56jf9zh_4wf_g9xm0000gn/T",
|
||||
"unsafe_perm": "true",
|
||||
"prefix": "/usr/local",
|
||||
"link": ""
|
||||
}
|
||||
}
|
611
node_modules/websocket/build/gyp-mac-tool
generated
vendored
Executable file
611
node_modules/websocket/build/gyp-mac-tool
generated
vendored
Executable file
@ -0,0 +1,611 @@
|
||||
#!/usr/bin/env python
|
||||
# Generated by gyp. Do not edit.
|
||||
# Copyright (c) 2012 Google Inc. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
"""Utility functions to perform Xcode-style build steps.
|
||||
|
||||
These functions are executed via gyp-mac-tool when using the Makefile generator.
|
||||
"""
|
||||
|
||||
import fcntl
|
||||
import fnmatch
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
import plistlib
|
||||
import re
|
||||
import shutil
|
||||
import string
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
|
||||
def main(args):
|
||||
executor = MacTool()
|
||||
exit_code = executor.Dispatch(args)
|
||||
if exit_code is not None:
|
||||
sys.exit(exit_code)
|
||||
|
||||
|
||||
class MacTool(object):
|
||||
"""This class performs all the Mac tooling steps. The methods can either be
|
||||
executed directly, or dispatched from an argument list."""
|
||||
|
||||
def Dispatch(self, args):
|
||||
"""Dispatches a string command to a method."""
|
||||
if len(args) < 1:
|
||||
raise Exception("Not enough arguments")
|
||||
|
||||
method = "Exec%s" % self._CommandifyName(args[0])
|
||||
return getattr(self, method)(*args[1:])
|
||||
|
||||
def _CommandifyName(self, name_string):
|
||||
"""Transforms a tool name like copy-info-plist to CopyInfoPlist"""
|
||||
return name_string.title().replace('-', '')
|
||||
|
||||
def ExecCopyBundleResource(self, source, dest, convert_to_binary):
|
||||
"""Copies a resource file to the bundle/Resources directory, performing any
|
||||
necessary compilation on each resource."""
|
||||
extension = os.path.splitext(source)[1].lower()
|
||||
if os.path.isdir(source):
|
||||
# Copy tree.
|
||||
# TODO(thakis): This copies file attributes like mtime, while the
|
||||
# single-file branch below doesn't. This should probably be changed to
|
||||
# be consistent with the single-file branch.
|
||||
if os.path.exists(dest):
|
||||
shutil.rmtree(dest)
|
||||
shutil.copytree(source, dest)
|
||||
elif extension == '.xib':
|
||||
return self._CopyXIBFile(source, dest)
|
||||
elif extension == '.storyboard':
|
||||
return self._CopyXIBFile(source, dest)
|
||||
elif extension == '.strings':
|
||||
self._CopyStringsFile(source, dest, convert_to_binary)
|
||||
else:
|
||||
shutil.copy(source, dest)
|
||||
|
||||
def _CopyXIBFile(self, source, dest):
|
||||
"""Compiles a XIB file with ibtool into a binary plist in the bundle."""
|
||||
|
||||
# ibtool sometimes crashes with relative paths. See crbug.com/314728.
|
||||
base = os.path.dirname(os.path.realpath(__file__))
|
||||
if os.path.relpath(source):
|
||||
source = os.path.join(base, source)
|
||||
if os.path.relpath(dest):
|
||||
dest = os.path.join(base, dest)
|
||||
|
||||
args = ['xcrun', 'ibtool', '--errors', '--warnings', '--notices',
|
||||
'--output-format', 'human-readable-text', '--compile', dest, source]
|
||||
ibtool_section_re = re.compile(r'/\*.*\*/')
|
||||
ibtool_re = re.compile(r'.*note:.*is clipping its content')
|
||||
ibtoolout = subprocess.Popen(args, stdout=subprocess.PIPE)
|
||||
current_section_header = None
|
||||
for line in ibtoolout.stdout:
|
||||
if ibtool_section_re.match(line):
|
||||
current_section_header = line
|
||||
elif not ibtool_re.match(line):
|
||||
if current_section_header:
|
||||
sys.stdout.write(current_section_header)
|
||||
current_section_header = None
|
||||
sys.stdout.write(line)
|
||||
return ibtoolout.returncode
|
||||
|
||||
def _ConvertToBinary(self, dest):
|
||||
subprocess.check_call([
|
||||
'xcrun', 'plutil', '-convert', 'binary1', '-o', dest, dest])
|
||||
|
||||
def _CopyStringsFile(self, source, dest, convert_to_binary):
|
||||
"""Copies a .strings file using iconv to reconvert the input into UTF-16."""
|
||||
input_code = self._DetectInputEncoding(source) or "UTF-8"
|
||||
|
||||
# Xcode's CpyCopyStringsFile / builtin-copyStrings seems to call
|
||||
# CFPropertyListCreateFromXMLData() behind the scenes; at least it prints
|
||||
# CFPropertyListCreateFromXMLData(): Old-style plist parser: missing
|
||||
# semicolon in dictionary.
|
||||
# on invalid files. Do the same kind of validation.
|
||||
import CoreFoundation
|
||||
s = open(source, 'rb').read()
|
||||
d = CoreFoundation.CFDataCreate(None, s, len(s))
|
||||
_, error = CoreFoundation.CFPropertyListCreateFromXMLData(None, d, 0, None)
|
||||
if error:
|
||||
return
|
||||
|
||||
fp = open(dest, 'wb')
|
||||
fp.write(s.decode(input_code).encode('UTF-16'))
|
||||
fp.close()
|
||||
|
||||
if convert_to_binary == 'True':
|
||||
self._ConvertToBinary(dest)
|
||||
|
||||
def _DetectInputEncoding(self, file_name):
|
||||
"""Reads the first few bytes from file_name and tries to guess the text
|
||||
encoding. Returns None as a guess if it can't detect it."""
|
||||
fp = open(file_name, 'rb')
|
||||
try:
|
||||
header = fp.read(3)
|
||||
except e:
|
||||
fp.close()
|
||||
return None
|
||||
fp.close()
|
||||
if header.startswith("\xFE\xFF"):
|
||||
return "UTF-16"
|
||||
elif header.startswith("\xFF\xFE"):
|
||||
return "UTF-16"
|
||||
elif header.startswith("\xEF\xBB\xBF"):
|
||||
return "UTF-8"
|
||||
else:
|
||||
return None
|
||||
|
||||
def ExecCopyInfoPlist(self, source, dest, convert_to_binary, *keys):
|
||||
"""Copies the |source| Info.plist to the destination directory |dest|."""
|
||||
# Read the source Info.plist into memory.
|
||||
fd = open(source, 'r')
|
||||
lines = fd.read()
|
||||
fd.close()
|
||||
|
||||
# Insert synthesized key/value pairs (e.g. BuildMachineOSBuild).
|
||||
plist = plistlib.readPlistFromString(lines)
|
||||
if keys:
|
||||
plist = dict(plist.items() + json.loads(keys[0]).items())
|
||||
lines = plistlib.writePlistToString(plist)
|
||||
|
||||
# Go through all the environment variables and replace them as variables in
|
||||
# the file.
|
||||
IDENT_RE = re.compile(r'[/\s]')
|
||||
for key in os.environ:
|
||||
if key.startswith('_'):
|
||||
continue
|
||||
evar = '${%s}' % key
|
||||
evalue = os.environ[key]
|
||||
lines = string.replace(lines, evar, evalue)
|
||||
|
||||
# Xcode supports various suffices on environment variables, which are
|
||||
# all undocumented. :rfc1034identifier is used in the standard project
|
||||
# template these days, and :identifier was used earlier. They are used to
|
||||
# convert non-url characters into things that look like valid urls --
|
||||
# except that the replacement character for :identifier, '_' isn't valid
|
||||
# in a URL either -- oops, hence :rfc1034identifier was born.
|
||||
evar = '${%s:identifier}' % key
|
||||
evalue = IDENT_RE.sub('_', os.environ[key])
|
||||
lines = string.replace(lines, evar, evalue)
|
||||
|
||||
evar = '${%s:rfc1034identifier}' % key
|
||||
evalue = IDENT_RE.sub('-', os.environ[key])
|
||||
lines = string.replace(lines, evar, evalue)
|
||||
|
||||
# Remove any keys with values that haven't been replaced.
|
||||
lines = lines.split('\n')
|
||||
for i in range(len(lines)):
|
||||
if lines[i].strip().startswith("<string>${"):
|
||||
lines[i] = None
|
||||
lines[i - 1] = None
|
||||
lines = '\n'.join(filter(lambda x: x is not None, lines))
|
||||
|
||||
# Write out the file with variables replaced.
|
||||
fd = open(dest, 'w')
|
||||
fd.write(lines)
|
||||
fd.close()
|
||||
|
||||
# Now write out PkgInfo file now that the Info.plist file has been
|
||||
# "compiled".
|
||||
self._WritePkgInfo(dest)
|
||||
|
||||
if convert_to_binary == 'True':
|
||||
self._ConvertToBinary(dest)
|
||||
|
||||
def _WritePkgInfo(self, info_plist):
|
||||
"""This writes the PkgInfo file from the data stored in Info.plist."""
|
||||
plist = plistlib.readPlist(info_plist)
|
||||
if not plist:
|
||||
return
|
||||
|
||||
# Only create PkgInfo for executable types.
|
||||
package_type = plist['CFBundlePackageType']
|
||||
if package_type != 'APPL':
|
||||
return
|
||||
|
||||
# The format of PkgInfo is eight characters, representing the bundle type
|
||||
# and bundle signature, each four characters. If that is missing, four
|
||||
# '?' characters are used instead.
|
||||
signature_code = plist.get('CFBundleSignature', '????')
|
||||
if len(signature_code) != 4: # Wrong length resets everything, too.
|
||||
signature_code = '?' * 4
|
||||
|
||||
dest = os.path.join(os.path.dirname(info_plist), 'PkgInfo')
|
||||
fp = open(dest, 'w')
|
||||
fp.write('%s%s' % (package_type, signature_code))
|
||||
fp.close()
|
||||
|
||||
def ExecFlock(self, lockfile, *cmd_list):
|
||||
"""Emulates the most basic behavior of Linux's flock(1)."""
|
||||
# Rely on exception handling to report errors.
|
||||
fd = os.open(lockfile, os.O_RDONLY|os.O_NOCTTY|os.O_CREAT, 0o666)
|
||||
fcntl.flock(fd, fcntl.LOCK_EX)
|
||||
return subprocess.call(cmd_list)
|
||||
|
||||
def ExecFilterLibtool(self, *cmd_list):
|
||||
"""Calls libtool and filters out '/path/to/libtool: file: foo.o has no
|
||||
symbols'."""
|
||||
libtool_re = re.compile(r'^.*libtool: file: .* has no symbols$')
|
||||
libtool_re5 = re.compile(
|
||||
r'^.*libtool: warning for library: ' +
|
||||
r'.* the table of contents is empty ' +
|
||||
r'\(no object file members in the library define global symbols\)$')
|
||||
env = os.environ.copy()
|
||||
# Ref:
|
||||
# http://www.opensource.apple.com/source/cctools/cctools-809/misc/libtool.c
|
||||
# The problem with this flag is that it resets the file mtime on the file to
|
||||
# epoch=0, e.g. 1970-1-1 or 1969-12-31 depending on timezone.
|
||||
env['ZERO_AR_DATE'] = '1'
|
||||
libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE, env=env)
|
||||
_, err = libtoolout.communicate()
|
||||
for line in err.splitlines():
|
||||
if not libtool_re.match(line) and not libtool_re5.match(line):
|
||||
print >>sys.stderr, line
|
||||
# Unconditionally touch the output .a file on the command line if present
|
||||
# and the command succeeded. A bit hacky.
|
||||
if not libtoolout.returncode:
|
||||
for i in range(len(cmd_list) - 1):
|
||||
if cmd_list[i] == "-o" and cmd_list[i+1].endswith('.a'):
|
||||
os.utime(cmd_list[i+1], None)
|
||||
break
|
||||
return libtoolout.returncode
|
||||
|
||||
def ExecPackageFramework(self, framework, version):
|
||||
"""Takes a path to Something.framework and the Current version of that and
|
||||
sets up all the symlinks."""
|
||||
# Find the name of the binary based on the part before the ".framework".
|
||||
binary = os.path.basename(framework).split('.')[0]
|
||||
|
||||
CURRENT = 'Current'
|
||||
RESOURCES = 'Resources'
|
||||
VERSIONS = 'Versions'
|
||||
|
||||
if not os.path.exists(os.path.join(framework, VERSIONS, version, binary)):
|
||||
# Binary-less frameworks don't seem to contain symlinks (see e.g.
|
||||
# chromium's out/Debug/org.chromium.Chromium.manifest/ bundle).
|
||||
return
|
||||
|
||||
# Move into the framework directory to set the symlinks correctly.
|
||||
pwd = os.getcwd()
|
||||
os.chdir(framework)
|
||||
|
||||
# Set up the Current version.
|
||||
self._Relink(version, os.path.join(VERSIONS, CURRENT))
|
||||
|
||||
# Set up the root symlinks.
|
||||
self._Relink(os.path.join(VERSIONS, CURRENT, binary), binary)
|
||||
self._Relink(os.path.join(VERSIONS, CURRENT, RESOURCES), RESOURCES)
|
||||
|
||||
# Back to where we were before!
|
||||
os.chdir(pwd)
|
||||
|
||||
def _Relink(self, dest, link):
|
||||
"""Creates a symlink to |dest| named |link|. If |link| already exists,
|
||||
it is overwritten."""
|
||||
if os.path.lexists(link):
|
||||
os.remove(link)
|
||||
os.symlink(dest, link)
|
||||
|
||||
def ExecCompileXcassets(self, keys, *inputs):
|
||||
"""Compiles multiple .xcassets files into a single .car file.
|
||||
|
||||
This invokes 'actool' to compile all the inputs .xcassets files. The
|
||||
|keys| arguments is a json-encoded dictionary of extra arguments to
|
||||
pass to 'actool' when the asset catalogs contains an application icon
|
||||
or a launch image.
|
||||
|
||||
Note that 'actool' does not create the Assets.car file if the asset
|
||||
catalogs does not contains imageset.
|
||||
"""
|
||||
command_line = [
|
||||
'xcrun', 'actool', '--output-format', 'human-readable-text',
|
||||
'--compress-pngs', '--notices', '--warnings', '--errors',
|
||||
]
|
||||
is_iphone_target = 'IPHONEOS_DEPLOYMENT_TARGET' in os.environ
|
||||
if is_iphone_target:
|
||||
platform = os.environ['CONFIGURATION'].split('-')[-1]
|
||||
if platform not in ('iphoneos', 'iphonesimulator'):
|
||||
platform = 'iphonesimulator'
|
||||
command_line.extend([
|
||||
'--platform', platform, '--target-device', 'iphone',
|
||||
'--target-device', 'ipad', '--minimum-deployment-target',
|
||||
os.environ['IPHONEOS_DEPLOYMENT_TARGET'], '--compile',
|
||||
os.path.abspath(os.environ['CONTENTS_FOLDER_PATH']),
|
||||
])
|
||||
else:
|
||||
command_line.extend([
|
||||
'--platform', 'macosx', '--target-device', 'mac',
|
||||
'--minimum-deployment-target', os.environ['MACOSX_DEPLOYMENT_TARGET'],
|
||||
'--compile',
|
||||
os.path.abspath(os.environ['UNLOCALIZED_RESOURCES_FOLDER_PATH']),
|
||||
])
|
||||
if keys:
|
||||
keys = json.loads(keys)
|
||||
for key, value in keys.iteritems():
|
||||
arg_name = '--' + key
|
||||
if isinstance(value, bool):
|
||||
if value:
|
||||
command_line.append(arg_name)
|
||||
elif isinstance(value, list):
|
||||
for v in value:
|
||||
command_line.append(arg_name)
|
||||
command_line.append(str(v))
|
||||
else:
|
||||
command_line.append(arg_name)
|
||||
command_line.append(str(value))
|
||||
# Note: actool crashes if inputs path are relative, so use os.path.abspath
|
||||
# to get absolute path name for inputs.
|
||||
command_line.extend(map(os.path.abspath, inputs))
|
||||
subprocess.check_call(command_line)
|
||||
|
||||
def ExecMergeInfoPlist(self, output, *inputs):
|
||||
"""Merge multiple .plist files into a single .plist file."""
|
||||
merged_plist = {}
|
||||
for path in inputs:
|
||||
plist = self._LoadPlistMaybeBinary(path)
|
||||
self._MergePlist(merged_plist, plist)
|
||||
plistlib.writePlist(merged_plist, output)
|
||||
|
||||
def ExecCodeSignBundle(self, key, resource_rules, entitlements, provisioning):
|
||||
"""Code sign a bundle.
|
||||
|
||||
This function tries to code sign an iOS bundle, following the same
|
||||
algorithm as Xcode:
|
||||
1. copy ResourceRules.plist from the user or the SDK into the bundle,
|
||||
2. pick the provisioning profile that best match the bundle identifier,
|
||||
and copy it into the bundle as embedded.mobileprovision,
|
||||
3. copy Entitlements.plist from user or SDK next to the bundle,
|
||||
4. code sign the bundle.
|
||||
"""
|
||||
resource_rules_path = self._InstallResourceRules(resource_rules)
|
||||
substitutions, overrides = self._InstallProvisioningProfile(
|
||||
provisioning, self._GetCFBundleIdentifier())
|
||||
entitlements_path = self._InstallEntitlements(
|
||||
entitlements, substitutions, overrides)
|
||||
subprocess.check_call([
|
||||
'codesign', '--force', '--sign', key, '--resource-rules',
|
||||
resource_rules_path, '--entitlements', entitlements_path,
|
||||
os.path.join(
|
||||
os.environ['TARGET_BUILD_DIR'],
|
||||
os.environ['FULL_PRODUCT_NAME'])])
|
||||
|
||||
def _InstallResourceRules(self, resource_rules):
|
||||
"""Installs ResourceRules.plist from user or SDK into the bundle.
|
||||
|
||||
Args:
|
||||
resource_rules: string, optional, path to the ResourceRules.plist file
|
||||
to use, default to "${SDKROOT}/ResourceRules.plist"
|
||||
|
||||
Returns:
|
||||
Path to the copy of ResourceRules.plist into the bundle.
|
||||
"""
|
||||
source_path = resource_rules
|
||||
target_path = os.path.join(
|
||||
os.environ['BUILT_PRODUCTS_DIR'],
|
||||
os.environ['CONTENTS_FOLDER_PATH'],
|
||||
'ResourceRules.plist')
|
||||
if not source_path:
|
||||
source_path = os.path.join(
|
||||
os.environ['SDKROOT'], 'ResourceRules.plist')
|
||||
shutil.copy2(source_path, target_path)
|
||||
return target_path
|
||||
|
||||
def _InstallProvisioningProfile(self, profile, bundle_identifier):
|
||||
"""Installs embedded.mobileprovision into the bundle.
|
||||
|
||||
Args:
|
||||
profile: string, optional, short name of the .mobileprovision file
|
||||
to use, if empty or the file is missing, the best file installed
|
||||
will be used
|
||||
bundle_identifier: string, value of CFBundleIdentifier from Info.plist
|
||||
|
||||
Returns:
|
||||
A tuple containing two dictionary: variables substitutions and values
|
||||
to overrides when generating the entitlements file.
|
||||
"""
|
||||
source_path, provisioning_data, team_id = self._FindProvisioningProfile(
|
||||
profile, bundle_identifier)
|
||||
target_path = os.path.join(
|
||||
os.environ['BUILT_PRODUCTS_DIR'],
|
||||
os.environ['CONTENTS_FOLDER_PATH'],
|
||||
'embedded.mobileprovision')
|
||||
shutil.copy2(source_path, target_path)
|
||||
substitutions = self._GetSubstitutions(bundle_identifier, team_id + '.')
|
||||
return substitutions, provisioning_data['Entitlements']
|
||||
|
||||
def _FindProvisioningProfile(self, profile, bundle_identifier):
|
||||
"""Finds the .mobileprovision file to use for signing the bundle.
|
||||
|
||||
Checks all the installed provisioning profiles (or if the user specified
|
||||
the PROVISIONING_PROFILE variable, only consult it) and select the most
|
||||
specific that correspond to the bundle identifier.
|
||||
|
||||
Args:
|
||||
profile: string, optional, short name of the .mobileprovision file
|
||||
to use, if empty or the file is missing, the best file installed
|
||||
will be used
|
||||
bundle_identifier: string, value of CFBundleIdentifier from Info.plist
|
||||
|
||||
Returns:
|
||||
A tuple of the path to the selected provisioning profile, the data of
|
||||
the embedded plist in the provisioning profile and the team identifier
|
||||
to use for code signing.
|
||||
|
||||
Raises:
|
||||
SystemExit: if no .mobileprovision can be used to sign the bundle.
|
||||
"""
|
||||
profiles_dir = os.path.join(
|
||||
os.environ['HOME'], 'Library', 'MobileDevice', 'Provisioning Profiles')
|
||||
if not os.path.isdir(profiles_dir):
|
||||
print >>sys.stderr, (
|
||||
'cannot find mobile provisioning for %s' % bundle_identifier)
|
||||
sys.exit(1)
|
||||
provisioning_profiles = None
|
||||
if profile:
|
||||
profile_path = os.path.join(profiles_dir, profile + '.mobileprovision')
|
||||
if os.path.exists(profile_path):
|
||||
provisioning_profiles = [profile_path]
|
||||
if not provisioning_profiles:
|
||||
provisioning_profiles = glob.glob(
|
||||
os.path.join(profiles_dir, '*.mobileprovision'))
|
||||
valid_provisioning_profiles = {}
|
||||
for profile_path in provisioning_profiles:
|
||||
profile_data = self._LoadProvisioningProfile(profile_path)
|
||||
app_id_pattern = profile_data.get(
|
||||
'Entitlements', {}).get('application-identifier', '')
|
||||
for team_identifier in profile_data.get('TeamIdentifier', []):
|
||||
app_id = '%s.%s' % (team_identifier, bundle_identifier)
|
||||
if fnmatch.fnmatch(app_id, app_id_pattern):
|
||||
valid_provisioning_profiles[app_id_pattern] = (
|
||||
profile_path, profile_data, team_identifier)
|
||||
if not valid_provisioning_profiles:
|
||||
print >>sys.stderr, (
|
||||
'cannot find mobile provisioning for %s' % bundle_identifier)
|
||||
sys.exit(1)
|
||||
# If the user has multiple provisioning profiles installed that can be
|
||||
# used for ${bundle_identifier}, pick the most specific one (ie. the
|
||||
# provisioning profile whose pattern is the longest).
|
||||
selected_key = max(valid_provisioning_profiles, key=lambda v: len(v))
|
||||
return valid_provisioning_profiles[selected_key]
|
||||
|
||||
def _LoadProvisioningProfile(self, profile_path):
|
||||
"""Extracts the plist embedded in a provisioning profile.
|
||||
|
||||
Args:
|
||||
profile_path: string, path to the .mobileprovision file
|
||||
|
||||
Returns:
|
||||
Content of the plist embedded in the provisioning profile as a dictionary.
|
||||
"""
|
||||
with tempfile.NamedTemporaryFile() as temp:
|
||||
subprocess.check_call([
|
||||
'security', 'cms', '-D', '-i', profile_path, '-o', temp.name])
|
||||
return self._LoadPlistMaybeBinary(temp.name)
|
||||
|
||||
def _MergePlist(self, merged_plist, plist):
|
||||
"""Merge |plist| into |merged_plist|."""
|
||||
for key, value in plist.iteritems():
|
||||
if isinstance(value, dict):
|
||||
merged_value = merged_plist.get(key, {})
|
||||
if isinstance(merged_value, dict):
|
||||
self._MergePlist(merged_value, value)
|
||||
merged_plist[key] = merged_value
|
||||
else:
|
||||
merged_plist[key] = value
|
||||
else:
|
||||
merged_plist[key] = value
|
||||
|
||||
def _LoadPlistMaybeBinary(self, plist_path):
|
||||
"""Loads into a memory a plist possibly encoded in binary format.
|
||||
|
||||
This is a wrapper around plistlib.readPlist that tries to convert the
|
||||
plist to the XML format if it can't be parsed (assuming that it is in
|
||||
the binary format).
|
||||
|
||||
Args:
|
||||
plist_path: string, path to a plist file, in XML or binary format
|
||||
|
||||
Returns:
|
||||
Content of the plist as a dictionary.
|
||||
"""
|
||||
try:
|
||||
# First, try to read the file using plistlib that only supports XML,
|
||||
# and if an exception is raised, convert a temporary copy to XML and
|
||||
# load that copy.
|
||||
return plistlib.readPlist(plist_path)
|
||||
except:
|
||||
pass
|
||||
with tempfile.NamedTemporaryFile() as temp:
|
||||
shutil.copy2(plist_path, temp.name)
|
||||
subprocess.check_call(['plutil', '-convert', 'xml1', temp.name])
|
||||
return plistlib.readPlist(temp.name)
|
||||
|
||||
def _GetSubstitutions(self, bundle_identifier, app_identifier_prefix):
|
||||
"""Constructs a dictionary of variable substitutions for Entitlements.plist.
|
||||
|
||||
Args:
|
||||
bundle_identifier: string, value of CFBundleIdentifier from Info.plist
|
||||
app_identifier_prefix: string, value for AppIdentifierPrefix
|
||||
|
||||
Returns:
|
||||
Dictionary of substitutions to apply when generating Entitlements.plist.
|
||||
"""
|
||||
return {
|
||||
'CFBundleIdentifier': bundle_identifier,
|
||||
'AppIdentifierPrefix': app_identifier_prefix,
|
||||
}
|
||||
|
||||
def _GetCFBundleIdentifier(self):
|
||||
"""Extracts CFBundleIdentifier value from Info.plist in the bundle.
|
||||
|
||||
Returns:
|
||||
Value of CFBundleIdentifier in the Info.plist located in the bundle.
|
||||
"""
|
||||
info_plist_path = os.path.join(
|
||||
os.environ['TARGET_BUILD_DIR'],
|
||||
os.environ['INFOPLIST_PATH'])
|
||||
info_plist_data = self._LoadPlistMaybeBinary(info_plist_path)
|
||||
return info_plist_data['CFBundleIdentifier']
|
||||
|
||||
def _InstallEntitlements(self, entitlements, substitutions, overrides):
|
||||
"""Generates and install the ${BundleName}.xcent entitlements file.
|
||||
|
||||
Expands variables "$(variable)" pattern in the source entitlements file,
|
||||
add extra entitlements defined in the .mobileprovision file and the copy
|
||||
the generated plist to "${BundlePath}.xcent".
|
||||
|
||||
Args:
|
||||
entitlements: string, optional, path to the Entitlements.plist template
|
||||
to use, defaults to "${SDKROOT}/Entitlements.plist"
|
||||
substitutions: dictionary, variable substitutions
|
||||
overrides: dictionary, values to add to the entitlements
|
||||
|
||||
Returns:
|
||||
Path to the generated entitlements file.
|
||||
"""
|
||||
source_path = entitlements
|
||||
target_path = os.path.join(
|
||||
os.environ['BUILT_PRODUCTS_DIR'],
|
||||
os.environ['PRODUCT_NAME'] + '.xcent')
|
||||
if not source_path:
|
||||
source_path = os.path.join(
|
||||
os.environ['SDKROOT'],
|
||||
'Entitlements.plist')
|
||||
shutil.copy2(source_path, target_path)
|
||||
data = self._LoadPlistMaybeBinary(target_path)
|
||||
data = self._ExpandVariables(data, substitutions)
|
||||
if overrides:
|
||||
for key in overrides:
|
||||
if key not in data:
|
||||
data[key] = overrides[key]
|
||||
plistlib.writePlist(data, target_path)
|
||||
return target_path
|
||||
|
||||
def _ExpandVariables(self, data, substitutions):
|
||||
"""Expands variables "$(variable)" in data.
|
||||
|
||||
Args:
|
||||
data: object, can be either string, list or dictionary
|
||||
substitutions: dictionary, variable substitutions to perform
|
||||
|
||||
Returns:
|
||||
Copy of data where each references to "$(variable)" has been replaced
|
||||
by the corresponding value found in substitutions, or left intact if
|
||||
the key was not found.
|
||||
"""
|
||||
if isinstance(data, str):
|
||||
for key, value in substitutions.iteritems():
|
||||
data = data.replace('$(%s)' % key, value)
|
||||
return data
|
||||
if isinstance(data, list):
|
||||
return [self._ExpandVariables(v, substitutions) for v in data]
|
||||
if isinstance(data, dict):
|
||||
return {k: self._ExpandVariables(data[k], substitutions) for k in data}
|
||||
return data
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
184
node_modules/websocket/build/validation.target.mk
generated
vendored
Normal file
184
node_modules/websocket/build/validation.target.mk
generated
vendored
Normal file
@ -0,0 +1,184 @@
|
||||
# This file is generated by gyp; do not edit.
|
||||
|
||||
TOOLSET := target
|
||||
TARGET := validation
|
||||
DEFS_Debug := \
|
||||
'-DNODE_GYP_MODULE_NAME=validation' \
|
||||
'-DUSING_UV_SHARED=1' \
|
||||
'-DUSING_V8_SHARED=1' \
|
||||
'-DV8_DEPRECATION_WARNINGS=1' \
|
||||
'-D_DARWIN_USE_64_BIT_INODE=1' \
|
||||
'-D_LARGEFILE_SOURCE' \
|
||||
'-D_FILE_OFFSET_BITS=64' \
|
||||
'-DBUILDING_NODE_EXTENSION' \
|
||||
'-DDEBUG' \
|
||||
'-D_DEBUG' \
|
||||
'-DV8_ENABLE_CHECKS'
|
||||
|
||||
# Flags passed to all source files.
|
||||
CFLAGS_Debug := \
|
||||
-O0 \
|
||||
-gdwarf-2 \
|
||||
-mmacosx-version-min=10.7 \
|
||||
-arch x86_64 \
|
||||
-Wall \
|
||||
-Wendif-labels \
|
||||
-W \
|
||||
-Wno-unused-parameter
|
||||
|
||||
# Flags passed to only C files.
|
||||
CFLAGS_C_Debug := \
|
||||
-fno-strict-aliasing
|
||||
|
||||
# Flags passed to only C++ files.
|
||||
CFLAGS_CC_Debug := \
|
||||
-std=gnu++1y \
|
||||
-stdlib=libc++ \
|
||||
-fno-rtti \
|
||||
-fno-exceptions \
|
||||
-fno-strict-aliasing
|
||||
|
||||
# Flags passed to only ObjC files.
|
||||
CFLAGS_OBJC_Debug :=
|
||||
|
||||
# Flags passed to only ObjC++ files.
|
||||
CFLAGS_OBJCC_Debug :=
|
||||
|
||||
INCS_Debug := \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/include/node \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/src \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/openssl/config \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/openssl/openssl/include \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/uv/include \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/zlib \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/v8/include \
|
||||
-I$(srcdir)/../nan
|
||||
|
||||
DEFS_Release := \
|
||||
'-DNODE_GYP_MODULE_NAME=validation' \
|
||||
'-DUSING_UV_SHARED=1' \
|
||||
'-DUSING_V8_SHARED=1' \
|
||||
'-DV8_DEPRECATION_WARNINGS=1' \
|
||||
'-D_DARWIN_USE_64_BIT_INODE=1' \
|
||||
'-D_LARGEFILE_SOURCE' \
|
||||
'-D_FILE_OFFSET_BITS=64' \
|
||||
'-DBUILDING_NODE_EXTENSION'
|
||||
|
||||
# Flags passed to all source files.
|
||||
CFLAGS_Release := \
|
||||
-Os \
|
||||
-gdwarf-2 \
|
||||
-mmacosx-version-min=10.7 \
|
||||
-arch x86_64 \
|
||||
-Wall \
|
||||
-Wendif-labels \
|
||||
-W \
|
||||
-Wno-unused-parameter
|
||||
|
||||
# Flags passed to only C files.
|
||||
CFLAGS_C_Release := \
|
||||
-fno-strict-aliasing
|
||||
|
||||
# Flags passed to only C++ files.
|
||||
CFLAGS_CC_Release := \
|
||||
-std=gnu++1y \
|
||||
-stdlib=libc++ \
|
||||
-fno-rtti \
|
||||
-fno-exceptions \
|
||||
-fno-strict-aliasing
|
||||
|
||||
# Flags passed to only ObjC files.
|
||||
CFLAGS_OBJC_Release :=
|
||||
|
||||
# Flags passed to only ObjC++ files.
|
||||
CFLAGS_OBJCC_Release :=
|
||||
|
||||
INCS_Release := \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/include/node \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/src \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/openssl/config \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/openssl/openssl/include \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/uv/include \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/zlib \
|
||||
-I/Users/josh.burman/.node-gyp/11.10.0/deps/v8/include \
|
||||
-I$(srcdir)/../nan
|
||||
|
||||
OBJS := \
|
||||
$(obj).target/$(TARGET)/src/validation.o
|
||||
|
||||
# Add to the list of files we specially track dependencies for.
|
||||
all_deps += $(OBJS)
|
||||
|
||||
# CFLAGS et al overrides must be target-local.
|
||||
# See "Target-specific Variable Values" in the GNU Make manual.
|
||||
$(OBJS): TOOLSET := $(TOOLSET)
|
||||
$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
|
||||
$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
|
||||
$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
|
||||
$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
|
||||
|
||||
# Suffix rules, putting all outputs into $(obj).
|
||||
|
||||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
|
||||
# Try building from generated source, too.
|
||||
|
||||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
|
||||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
|
||||
# End of this set of suffix rules
|
||||
### Rules for final target.
|
||||
LDFLAGS_Debug := \
|
||||
-undefined dynamic_lookup \
|
||||
-Wl,-no_pie \
|
||||
-Wl,-search_paths_first \
|
||||
-mmacosx-version-min=10.7 \
|
||||
-arch x86_64 \
|
||||
-L$(builddir) \
|
||||
-stdlib=libc++
|
||||
|
||||
LIBTOOLFLAGS_Debug := \
|
||||
-undefined dynamic_lookup \
|
||||
-Wl,-no_pie \
|
||||
-Wl,-search_paths_first
|
||||
|
||||
LDFLAGS_Release := \
|
||||
-undefined dynamic_lookup \
|
||||
-Wl,-no_pie \
|
||||
-Wl,-search_paths_first \
|
||||
-mmacosx-version-min=10.7 \
|
||||
-arch x86_64 \
|
||||
-L$(builddir) \
|
||||
-stdlib=libc++
|
||||
|
||||
LIBTOOLFLAGS_Release := \
|
||||
-undefined dynamic_lookup \
|
||||
-Wl,-no_pie \
|
||||
-Wl,-search_paths_first
|
||||
|
||||
LIBS :=
|
||||
|
||||
$(builddir)/validation.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
|
||||
$(builddir)/validation.node: LIBS := $(LIBS)
|
||||
$(builddir)/validation.node: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE))
|
||||
$(builddir)/validation.node: TOOLSET := $(TOOLSET)
|
||||
$(builddir)/validation.node: $(OBJS) FORCE_DO_CMD
|
||||
$(call do_cmd,solink_module)
|
||||
|
||||
all_deps += $(builddir)/validation.node
|
||||
# Add target alias
|
||||
.PHONY: validation
|
||||
validation: $(builddir)/validation.node
|
||||
|
||||
# Short alias for building this executable.
|
||||
.PHONY: validation.node
|
||||
validation.node: $(builddir)/validation.node
|
||||
|
||||
# Add executable to "all" target.
|
||||
.PHONY: all
|
||||
all: $(builddir)/validation.node
|
||||
|
92
node_modules/websocket/builderror.log
generated
vendored
Normal file
92
node_modules/websocket/builderror.log
generated
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
../src/bufferutil.cc:50:40: warning: 'ToObject' is deprecated: Use maybe version [-Wdeprecated-declarations]
|
||||
Local<Object> bufferObj = info[0]->ToObject();
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8.h:2549:10: note: 'ToObject' has been explicitly marked deprecated here
|
||||
inline V8_DEPRECATED("Use maybe version", Local<Object> ToObject() const);
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8config.h:326:29: note: expanded from macro 'V8_DEPRECATED'
|
||||
declarator __attribute__((deprecated(message)))
|
||||
^
|
||||
../src/bufferutil.cc:57:42: warning: 'ToObject' is deprecated: Use maybe version [-Wdeprecated-declarations]
|
||||
Local<Object> src = array->Get(i)->ToObject();
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8.h:2549:10: note: 'ToObject' has been explicitly marked deprecated here
|
||||
inline V8_DEPRECATED("Use maybe version", Local<Object> ToObject() const);
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8config.h:326:29: note: expanded from macro 'V8_DEPRECATED'
|
||||
declarator __attribute__((deprecated(message)))
|
||||
^
|
||||
../src/bufferutil.cc:68:41: warning: 'ToObject' is deprecated: Use maybe version [-Wdeprecated-declarations]
|
||||
Local<Object> buffer_obj = info[0]->ToObject();
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8.h:2549:10: note: 'ToObject' has been explicitly marked deprecated here
|
||||
inline V8_DEPRECATED("Use maybe version", Local<Object> ToObject() const);
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8config.h:326:29: note: expanded from macro 'V8_DEPRECATED'
|
||||
declarator __attribute__((deprecated(message)))
|
||||
^
|
||||
../src/bufferutil.cc:70:39: warning: 'ToObject' is deprecated: Use maybe version [-Wdeprecated-declarations]
|
||||
Local<Object> mask_obj = info[1]->ToObject();
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8.h:2549:10: note: 'ToObject' has been explicitly marked deprecated here
|
||||
inline V8_DEPRECATED("Use maybe version", Local<Object> ToObject() const);
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8config.h:326:29: note: expanded from macro 'V8_DEPRECATED'
|
||||
declarator __attribute__((deprecated(message)))
|
||||
^
|
||||
../src/bufferutil.cc:89:41: warning: 'ToObject' is deprecated: Use maybe version [-Wdeprecated-declarations]
|
||||
Local<Object> buffer_obj = info[0]->ToObject();
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8.h:2549:10: note: 'ToObject' has been explicitly marked deprecated here
|
||||
inline V8_DEPRECATED("Use maybe version", Local<Object> ToObject() const);
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8config.h:326:29: note: expanded from macro 'V8_DEPRECATED'
|
||||
declarator __attribute__((deprecated(message)))
|
||||
^
|
||||
../src/bufferutil.cc:90:39: warning: 'ToObject' is deprecated: Use maybe version [-Wdeprecated-declarations]
|
||||
Local<Object> mask_obj = info[1]->ToObject();
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8.h:2549:10: note: 'ToObject' has been explicitly marked deprecated here
|
||||
inline V8_DEPRECATED("Use maybe version", Local<Object> ToObject() const);
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8config.h:326:29: note: expanded from macro 'V8_DEPRECATED'
|
||||
declarator __attribute__((deprecated(message)))
|
||||
^
|
||||
../src/bufferutil.cc:92:41: warning: 'ToObject' is deprecated: Use maybe version [-Wdeprecated-declarations]
|
||||
Local<Object> output_obj = info[2]->ToObject();
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8.h:2549:10: note: 'ToObject' has been explicitly marked deprecated here
|
||||
inline V8_DEPRECATED("Use maybe version", Local<Object> ToObject() const);
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8config.h:326:29: note: expanded from macro 'V8_DEPRECATED'
|
||||
declarator __attribute__((deprecated(message)))
|
||||
^
|
||||
../src/bufferutil.cc:93:40: warning: 'Int32Value' is deprecated: Use maybe version [-Wdeprecated-declarations]
|
||||
unsigned int dataOffset = info[3]->Int32Value();
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8.h:2572:3: note: 'Int32Value' has been explicitly marked deprecated here
|
||||
V8_DEPRECATED("Use maybe version", int32_t Int32Value() const);
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8config.h:326:29: note: expanded from macro 'V8_DEPRECATED'
|
||||
declarator __attribute__((deprecated(message)))
|
||||
^
|
||||
../src/bufferutil.cc:94:36: warning: 'Int32Value' is deprecated: Use maybe version [-Wdeprecated-declarations]
|
||||
unsigned int length = info[4]->Int32Value();
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8.h:2572:3: note: 'Int32Value' has been explicitly marked deprecated here
|
||||
V8_DEPRECATED("Use maybe version", int32_t Int32Value() const);
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8config.h:326:29: note: expanded from macro 'V8_DEPRECATED'
|
||||
declarator __attribute__((deprecated(message)))
|
||||
^
|
||||
9 warnings generated.
|
||||
../src/validation.cc:133:41: warning: 'ToObject' is deprecated: Use maybe version [-Wdeprecated-declarations]
|
||||
Local<Object> buffer_obj = info[0]->ToObject();
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8.h:2549:10: note: 'ToObject' has been explicitly marked deprecated here
|
||||
inline V8_DEPRECATED("Use maybe version", Local<Object> ToObject() const);
|
||||
^
|
||||
/Users/josh.burman/.node-gyp/11.10.0/include/node/v8config.h:326:29: note: expanded from macro 'V8_DEPRECATED'
|
||||
declarator __attribute__((deprecated(message)))
|
||||
^
|
||||
1 warning generated.
|
14
node_modules/websocket/gulpfile.js
generated
vendored
Normal file
14
node_modules/websocket/gulpfile.js
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Dependencies.
|
||||
*/
|
||||
var gulp = require('gulp');
|
||||
var jshint = require('gulp-jshint');
|
||||
|
||||
gulp.task('lint', function() {
|
||||
return gulp.src(['gulpfile.js', 'lib/**/*.js', 'test/**/*.js'])
|
||||
.pipe(jshint('.jshintrc'))
|
||||
.pipe(jshint.reporter('jshint-stylish', {verbose: true}))
|
||||
.pipe(jshint.reporter('fail'));
|
||||
});
|
||||
|
||||
gulp.task('default', gulp.series('lint'));
|
1
node_modules/websocket/index.js
generated
vendored
Normal file
1
node_modules/websocket/index.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('./lib/websocket');
|
52
node_modules/websocket/lib/BufferUtil.fallback.js
generated
vendored
Normal file
52
node_modules/websocket/lib/BufferUtil.fallback.js
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
/*!
|
||||
* Copied from:
|
||||
* ws: a node.js websocket client
|
||||
* Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/* jshint -W086 */
|
||||
|
||||
module.exports.BufferUtil = {
|
||||
merge: function(mergedBuffer, buffers) {
|
||||
var offset = 0;
|
||||
for (var i = 0, l = buffers.length; i < l; ++i) {
|
||||
var buf = buffers[i];
|
||||
buf.copy(mergedBuffer, offset);
|
||||
offset += buf.length;
|
||||
}
|
||||
},
|
||||
mask: function(source, mask, output, offset, length) {
|
||||
var maskNum = mask.readUInt32LE(0);
|
||||
var i = 0;
|
||||
for (; i < length - 3; i += 4) {
|
||||
var num = maskNum ^ source.readUInt32LE(i);
|
||||
if (num < 0) { num = 4294967296 + num; }
|
||||
output.writeUInt32LE(num, offset + i);
|
||||
}
|
||||
switch (length % 4) {
|
||||
case 3: output[offset + i + 2] = source[i + 2] ^ mask[2];
|
||||
case 2: output[offset + i + 1] = source[i + 1] ^ mask[1];
|
||||
case 1: output[offset + i] = source[i] ^ mask[0];
|
||||
case 0:
|
||||
}
|
||||
},
|
||||
unmask: function(data, mask) {
|
||||
var maskNum = mask.readUInt32LE(0);
|
||||
var length = data.length;
|
||||
var i = 0;
|
||||
for (; i < length - 3; i += 4) {
|
||||
var num = maskNum ^ data.readUInt32LE(i);
|
||||
if (num < 0) { num = 4294967296 + num; }
|
||||
data.writeUInt32LE(num, i);
|
||||
}
|
||||
switch (length % 4) {
|
||||
case 3: data[i + 2] = data[i + 2] ^ mask[2];
|
||||
case 2: data[i + 1] = data[i + 1] ^ mask[1];
|
||||
case 1: data[i] = data[i] ^ mask[0];
|
||||
case 0:
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* jshint +W086 */
|
17
node_modules/websocket/lib/BufferUtil.js
generated
vendored
Normal file
17
node_modules/websocket/lib/BufferUtil.js
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/*!
|
||||
* Copied from:
|
||||
* ws: a node.js websocket client
|
||||
* Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
try {
|
||||
module.exports = require('../build/Release/bufferutil');
|
||||
} catch (e) { try {
|
||||
module.exports = require('../build/default/bufferutil');
|
||||
} catch (e) { try {
|
||||
module.exports = require('./BufferUtil.fallback');
|
||||
} catch (e) {
|
||||
console.error('bufferutil.node seems to not have been built. Run npm install.');
|
||||
throw e;
|
||||
}}}
|
32
node_modules/websocket/lib/Deprecation.js
generated
vendored
Normal file
32
node_modules/websocket/lib/Deprecation.js
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
/************************************************************************
|
||||
* Copyright 2010-2015 Brian McKelvey.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
***********************************************************************/
|
||||
|
||||
var Deprecation = {
|
||||
disableWarnings: false,
|
||||
|
||||
deprecationWarningMap: {
|
||||
|
||||
},
|
||||
|
||||
warn: function(deprecationName) {
|
||||
if (!this.disableWarnings && this.deprecationWarningMap[deprecationName]) {
|
||||
console.warn('DEPRECATION WARNING: ' + this.deprecationWarningMap[deprecationName]);
|
||||
this.deprecationWarningMap[deprecationName] = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Deprecation;
|
12
node_modules/websocket/lib/Validation.fallback.js
generated
vendored
Normal file
12
node_modules/websocket/lib/Validation.fallback.js
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
/*!
|
||||
* UTF-8 Validation Fallback Code originally from:
|
||||
* ws: a node.js websocket client
|
||||
* Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
module.exports.Validation = {
|
||||
isValidUTF8: function() {
|
||||
return true;
|
||||
}
|
||||
};
|
17
node_modules/websocket/lib/Validation.js
generated
vendored
Normal file
17
node_modules/websocket/lib/Validation.js
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/*!
|
||||
* UTF-8 Validation Code originally from:
|
||||
* ws: a node.js websocket client
|
||||
* Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
try {
|
||||
module.exports = require('../build/Release/validation');
|
||||
} catch (e) { try {
|
||||
module.exports = require('../build/default/validation');
|
||||
} catch (e) { try {
|
||||
module.exports = require('./Validation.fallback');
|
||||
} catch (e) {
|
||||
console.error('validation.node seems not to have been built. Run npm install.');
|
||||
throw e;
|
||||
}}}
|
257
node_modules/websocket/lib/W3CWebSocket.js
generated
vendored
Normal file
257
node_modules/websocket/lib/W3CWebSocket.js
generated
vendored
Normal file
@ -0,0 +1,257 @@
|
||||
/************************************************************************
|
||||
* Copyright 2010-2015 Brian McKelvey.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
***********************************************************************/
|
||||
|
||||
var WebSocketClient = require('./WebSocketClient');
|
||||
var toBuffer = require('typedarray-to-buffer');
|
||||
var yaeti = require('yaeti');
|
||||
|
||||
|
||||
const CONNECTING = 0;
|
||||
const OPEN = 1;
|
||||
const CLOSING = 2;
|
||||
const CLOSED = 3;
|
||||
|
||||
|
||||
module.exports = W3CWebSocket;
|
||||
|
||||
|
||||
function W3CWebSocket(url, protocols, origin, headers, requestOptions, clientConfig) {
|
||||
// Make this an EventTarget.
|
||||
yaeti.EventTarget.call(this);
|
||||
|
||||
// Sanitize clientConfig.
|
||||
clientConfig = clientConfig || {};
|
||||
clientConfig.assembleFragments = true; // Required in the W3C API.
|
||||
|
||||
var self = this;
|
||||
|
||||
this._url = url;
|
||||
this._readyState = CONNECTING;
|
||||
this._protocol = undefined;
|
||||
this._extensions = '';
|
||||
this._bufferedAmount = 0; // Hack, always 0.
|
||||
this._binaryType = 'arraybuffer'; // TODO: Should be 'blob' by default, but Node has no Blob.
|
||||
|
||||
// The WebSocketConnection instance.
|
||||
this._connection = undefined;
|
||||
|
||||
// WebSocketClient instance.
|
||||
this._client = new WebSocketClient(clientConfig);
|
||||
|
||||
this._client.on('connect', function(connection) {
|
||||
onConnect.call(self, connection);
|
||||
});
|
||||
|
||||
this._client.on('connectFailed', function() {
|
||||
onConnectFailed.call(self);
|
||||
});
|
||||
|
||||
this._client.connect(url, protocols, origin, headers, requestOptions);
|
||||
}
|
||||
|
||||
|
||||
// Expose W3C read only attributes.
|
||||
Object.defineProperties(W3CWebSocket.prototype, {
|
||||
url: { get: function() { return this._url; } },
|
||||
readyState: { get: function() { return this._readyState; } },
|
||||
protocol: { get: function() { return this._protocol; } },
|
||||
extensions: { get: function() { return this._extensions; } },
|
||||
bufferedAmount: { get: function() { return this._bufferedAmount; } }
|
||||
});
|
||||
|
||||
|
||||
// Expose W3C write/read attributes.
|
||||
Object.defineProperties(W3CWebSocket.prototype, {
|
||||
binaryType: {
|
||||
get: function() {
|
||||
return this._binaryType;
|
||||
},
|
||||
set: function(type) {
|
||||
// TODO: Just 'arraybuffer' supported.
|
||||
if (type !== 'arraybuffer') {
|
||||
throw new SyntaxError('just "arraybuffer" type allowed for "binaryType" attribute');
|
||||
}
|
||||
this._binaryType = type;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Expose W3C readyState constants into the WebSocket instance as W3C states.
|
||||
[['CONNECTING',CONNECTING], ['OPEN',OPEN], ['CLOSING',CLOSING], ['CLOSED',CLOSED]].forEach(function(property) {
|
||||
Object.defineProperty(W3CWebSocket.prototype, property[0], {
|
||||
get: function() { return property[1]; }
|
||||
});
|
||||
});
|
||||
|
||||
// Also expose W3C readyState constants into the WebSocket class (not defined by the W3C,
|
||||
// but there are so many libs relying on them).
|
||||
[['CONNECTING',CONNECTING], ['OPEN',OPEN], ['CLOSING',CLOSING], ['CLOSED',CLOSED]].forEach(function(property) {
|
||||
Object.defineProperty(W3CWebSocket, property[0], {
|
||||
get: function() { return property[1]; }
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
W3CWebSocket.prototype.send = function(data) {
|
||||
if (this._readyState !== OPEN) {
|
||||
throw new Error('cannot call send() while not connected');
|
||||
}
|
||||
|
||||
// Text.
|
||||
if (typeof data === 'string' || data instanceof String) {
|
||||
this._connection.sendUTF(data);
|
||||
}
|
||||
// Binary.
|
||||
else {
|
||||
// Node Buffer.
|
||||
if (data instanceof Buffer) {
|
||||
this._connection.sendBytes(data);
|
||||
}
|
||||
// If ArrayBuffer or ArrayBufferView convert it to Node Buffer.
|
||||
else if (data.byteLength || data.byteLength === 0) {
|
||||
data = toBuffer(data);
|
||||
this._connection.sendBytes(data);
|
||||
}
|
||||
else {
|
||||
throw new Error('unknown binary data:', data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
W3CWebSocket.prototype.close = function(code, reason) {
|
||||
switch(this._readyState) {
|
||||
case CONNECTING:
|
||||
// NOTE: We don't have the WebSocketConnection instance yet so no
|
||||
// way to close the TCP connection.
|
||||
// Artificially invoke the onConnectFailed event.
|
||||
onConnectFailed.call(this);
|
||||
// And close if it connects after a while.
|
||||
this._client.on('connect', function(connection) {
|
||||
if (code) {
|
||||
connection.close(code, reason);
|
||||
} else {
|
||||
connection.close();
|
||||
}
|
||||
});
|
||||
break;
|
||||
case OPEN:
|
||||
this._readyState = CLOSING;
|
||||
if (code) {
|
||||
this._connection.close(code, reason);
|
||||
} else {
|
||||
this._connection.close();
|
||||
}
|
||||
break;
|
||||
case CLOSING:
|
||||
case CLOSED:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Private API.
|
||||
*/
|
||||
|
||||
|
||||
function createCloseEvent(code, reason) {
|
||||
var event = new yaeti.Event('close');
|
||||
|
||||
event.code = code;
|
||||
event.reason = reason;
|
||||
event.wasClean = (typeof code === 'undefined' || code === 1000);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
function createMessageEvent(data) {
|
||||
var event = new yaeti.Event('message');
|
||||
|
||||
event.data = data;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
function onConnect(connection) {
|
||||
var self = this;
|
||||
|
||||
this._readyState = OPEN;
|
||||
this._connection = connection;
|
||||
this._protocol = connection.protocol;
|
||||
this._extensions = connection.extensions;
|
||||
|
||||
this._connection.on('close', function(code, reason) {
|
||||
onClose.call(self, code, reason);
|
||||
});
|
||||
|
||||
this._connection.on('message', function(msg) {
|
||||
onMessage.call(self, msg);
|
||||
});
|
||||
|
||||
this.dispatchEvent(new yaeti.Event('open'));
|
||||
}
|
||||
|
||||
|
||||
function onConnectFailed() {
|
||||
destroy.call(this);
|
||||
this._readyState = CLOSED;
|
||||
|
||||
try {
|
||||
this.dispatchEvent(new yaeti.Event('error'));
|
||||
} finally {
|
||||
this.dispatchEvent(createCloseEvent(1006, 'connection failed'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function onClose(code, reason) {
|
||||
destroy.call(this);
|
||||
this._readyState = CLOSED;
|
||||
|
||||
this.dispatchEvent(createCloseEvent(code, reason || ''));
|
||||
}
|
||||
|
||||
|
||||
function onMessage(message) {
|
||||
if (message.utf8Data) {
|
||||
this.dispatchEvent(createMessageEvent(message.utf8Data));
|
||||
}
|
||||
else if (message.binaryData) {
|
||||
// Must convert from Node Buffer to ArrayBuffer.
|
||||
// TODO: or to a Blob (which does not exist in Node!).
|
||||
if (this.binaryType === 'arraybuffer') {
|
||||
var buffer = message.binaryData;
|
||||
var arraybuffer = new ArrayBuffer(buffer.length);
|
||||
var view = new Uint8Array(arraybuffer);
|
||||
for (var i=0, len=buffer.length; i<len; ++i) {
|
||||
view[i] = buffer[i];
|
||||
}
|
||||
this.dispatchEvent(createMessageEvent(arraybuffer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function destroy() {
|
||||
this._client.removeAllListeners();
|
||||
if (this._connection) {
|
||||
this._connection.removeAllListeners();
|
||||
}
|
||||
}
|
361
node_modules/websocket/lib/WebSocketClient.js
generated
vendored
Normal file
361
node_modules/websocket/lib/WebSocketClient.js
generated
vendored
Normal file
@ -0,0 +1,361 @@
|
||||
/************************************************************************
|
||||
* Copyright 2010-2015 Brian McKelvey.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
***********************************************************************/
|
||||
|
||||
var utils = require('./utils');
|
||||
var extend = utils.extend;
|
||||
var util = require('util');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var http = require('http');
|
||||
var https = require('https');
|
||||
var url = require('url');
|
||||
var crypto = require('crypto');
|
||||
var WebSocketConnection = require('./WebSocketConnection');
|
||||
var bufferAllocUnsafe = utils.bufferAllocUnsafe;
|
||||
|
||||
var protocolSeparators = [
|
||||
'(', ')', '<', '>', '@',
|
||||
',', ';', ':', '\\', '\"',
|
||||
'/', '[', ']', '?', '=',
|
||||
'{', '}', ' ', String.fromCharCode(9)
|
||||
];
|
||||
|
||||
var excludedTlsOptions = ['hostname','port','method','path','headers'];
|
||||
|
||||
function WebSocketClient(config) {
|
||||
// Superclass Constructor
|
||||
EventEmitter.call(this);
|
||||
|
||||
// TODO: Implement extensions
|
||||
|
||||
this.config = {
|
||||
// 1MiB max frame size.
|
||||
maxReceivedFrameSize: 0x100000,
|
||||
|
||||
// 8MiB max message size, only applicable if
|
||||
// assembleFragments is true
|
||||
maxReceivedMessageSize: 0x800000,
|
||||
|
||||
// Outgoing messages larger than fragmentationThreshold will be
|
||||
// split into multiple fragments.
|
||||
fragmentOutgoingMessages: true,
|
||||
|
||||
// Outgoing frames are fragmented if they exceed this threshold.
|
||||
// Default is 16KiB
|
||||
fragmentationThreshold: 0x4000,
|
||||
|
||||
// Which version of the protocol to use for this session. This
|
||||
// option will be removed once the protocol is finalized by the IETF
|
||||
// It is only available to ease the transition through the
|
||||
// intermediate draft protocol versions.
|
||||
// At present, it only affects the name of the Origin header.
|
||||
webSocketVersion: 13,
|
||||
|
||||
// If true, fragmented messages will be automatically assembled
|
||||
// and the full message will be emitted via a 'message' event.
|
||||
// If false, each frame will be emitted via a 'frame' event and
|
||||
// the application will be responsible for aggregating multiple
|
||||
// fragmented frames. Single-frame messages will emit a 'message'
|
||||
// event in addition to the 'frame' event.
|
||||
// Most users will want to leave this set to 'true'
|
||||
assembleFragments: true,
|
||||
|
||||
// The Nagle Algorithm makes more efficient use of network resources
|
||||
// by introducing a small delay before sending small packets so that
|
||||
// multiple messages can be batched together before going onto the
|
||||
// wire. This however comes at the cost of latency, so the default
|
||||
// is to disable it. If you don't need low latency and are streaming
|
||||
// lots of small messages, you can change this to 'false'
|
||||
disableNagleAlgorithm: true,
|
||||
|
||||
// The number of milliseconds to wait after sending a close frame
|
||||
// for an acknowledgement to come back before giving up and just
|
||||
// closing the socket.
|
||||
closeTimeout: 5000,
|
||||
|
||||
// Options to pass to https.connect if connecting via TLS
|
||||
tlsOptions: {}
|
||||
};
|
||||
|
||||
if (config) {
|
||||
var tlsOptions;
|
||||
if (config.tlsOptions) {
|
||||
tlsOptions = config.tlsOptions;
|
||||
delete config.tlsOptions;
|
||||
}
|
||||
else {
|
||||
tlsOptions = {};
|
||||
}
|
||||
extend(this.config, config);
|
||||
extend(this.config.tlsOptions, tlsOptions);
|
||||
}
|
||||
|
||||
this._req = null;
|
||||
|
||||
switch (this.config.webSocketVersion) {
|
||||
case 8:
|
||||
case 13:
|
||||
break;
|
||||
default:
|
||||
throw new Error('Requested webSocketVersion is not supported. Allowed values are 8 and 13.');
|
||||
}
|
||||
}
|
||||
|
||||
util.inherits(WebSocketClient, EventEmitter);
|
||||
|
||||
WebSocketClient.prototype.connect = function(requestUrl, protocols, origin, headers, extraRequestOptions) {
|
||||
var self = this;
|
||||
|
||||
if (typeof(protocols) === 'string') {
|
||||
if (protocols.length > 0) {
|
||||
protocols = [protocols];
|
||||
}
|
||||
else {
|
||||
protocols = [];
|
||||
}
|
||||
}
|
||||
if (!(protocols instanceof Array)) {
|
||||
protocols = [];
|
||||
}
|
||||
this.protocols = protocols;
|
||||
this.origin = origin;
|
||||
|
||||
if (typeof(requestUrl) === 'string') {
|
||||
this.url = url.parse(requestUrl);
|
||||
}
|
||||
else {
|
||||
this.url = requestUrl; // in case an already parsed url is passed in.
|
||||
}
|
||||
if (!this.url.protocol) {
|
||||
throw new Error('You must specify a full WebSocket URL, including protocol.');
|
||||
}
|
||||
if (!this.url.host) {
|
||||
throw new Error('You must specify a full WebSocket URL, including hostname. Relative URLs are not supported.');
|
||||
}
|
||||
|
||||
this.secure = (this.url.protocol === 'wss:');
|
||||
|
||||
// validate protocol characters:
|
||||
this.protocols.forEach(function(protocol) {
|
||||
for (var i=0; i < protocol.length; i ++) {
|
||||
var charCode = protocol.charCodeAt(i);
|
||||
var character = protocol.charAt(i);
|
||||
if (charCode < 0x0021 || charCode > 0x007E || protocolSeparators.indexOf(character) !== -1) {
|
||||
throw new Error('Protocol list contains invalid character "' + String.fromCharCode(charCode) + '"');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var defaultPorts = {
|
||||
'ws:': '80',
|
||||
'wss:': '443'
|
||||
};
|
||||
|
||||
if (!this.url.port) {
|
||||
this.url.port = defaultPorts[this.url.protocol];
|
||||
}
|
||||
|
||||
var nonce = bufferAllocUnsafe(16);
|
||||
for (var i=0; i < 16; i++) {
|
||||
nonce[i] = Math.round(Math.random()*0xFF);
|
||||
}
|
||||
this.base64nonce = nonce.toString('base64');
|
||||
|
||||
var hostHeaderValue = this.url.hostname;
|
||||
if ((this.url.protocol === 'ws:' && this.url.port !== '80') ||
|
||||
(this.url.protocol === 'wss:' && this.url.port !== '443')) {
|
||||
hostHeaderValue += (':' + this.url.port);
|
||||
}
|
||||
|
||||
var reqHeaders = {};
|
||||
if (this.secure && this.config.tlsOptions.hasOwnProperty('headers')) {
|
||||
// Allow for additional headers to be provided when connecting via HTTPS
|
||||
extend(reqHeaders, this.config.tlsOptions.headers);
|
||||
}
|
||||
if (headers) {
|
||||
// Explicitly provided headers take priority over any from tlsOptions
|
||||
extend(reqHeaders, headers);
|
||||
}
|
||||
extend(reqHeaders, {
|
||||
'Upgrade': 'websocket',
|
||||
'Connection': 'Upgrade',
|
||||
'Sec-WebSocket-Version': this.config.webSocketVersion.toString(10),
|
||||
'Sec-WebSocket-Key': this.base64nonce,
|
||||
'Host': reqHeaders.Host || hostHeaderValue
|
||||
});
|
||||
|
||||
if (this.protocols.length > 0) {
|
||||
reqHeaders['Sec-WebSocket-Protocol'] = this.protocols.join(', ');
|
||||
}
|
||||
if (this.origin) {
|
||||
if (this.config.webSocketVersion === 13) {
|
||||
reqHeaders['Origin'] = this.origin;
|
||||
}
|
||||
else if (this.config.webSocketVersion === 8) {
|
||||
reqHeaders['Sec-WebSocket-Origin'] = this.origin;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Implement extensions
|
||||
|
||||
var pathAndQuery;
|
||||
// Ensure it begins with '/'.
|
||||
if (this.url.pathname) {
|
||||
pathAndQuery = this.url.path;
|
||||
}
|
||||
else if (this.url.path) {
|
||||
pathAndQuery = '/' + this.url.path;
|
||||
}
|
||||
else {
|
||||
pathAndQuery = '/';
|
||||
}
|
||||
|
||||
function handleRequestError(error) {
|
||||
self._req = null;
|
||||
self.emit('connectFailed', error);
|
||||
}
|
||||
|
||||
var requestOptions = {
|
||||
agent: false
|
||||
};
|
||||
if (extraRequestOptions) {
|
||||
extend(requestOptions, extraRequestOptions);
|
||||
}
|
||||
// These options are always overridden by the library. The user is not
|
||||
// allowed to specify these directly.
|
||||
extend(requestOptions, {
|
||||
hostname: this.url.hostname,
|
||||
port: this.url.port,
|
||||
method: 'GET',
|
||||
path: pathAndQuery,
|
||||
headers: reqHeaders
|
||||
});
|
||||
if (this.secure) {
|
||||
var tlsOptions = this.config.tlsOptions;
|
||||
for (var key in tlsOptions) {
|
||||
if (tlsOptions.hasOwnProperty(key) && excludedTlsOptions.indexOf(key) === -1) {
|
||||
requestOptions[key] = tlsOptions[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var req = this._req = (this.secure ? https : http).request(requestOptions);
|
||||
req.on('upgrade', function handleRequestUpgrade(response, socket, head) {
|
||||
self._req = null;
|
||||
req.removeListener('error', handleRequestError);
|
||||
self.socket = socket;
|
||||
self.response = response;
|
||||
self.firstDataChunk = head;
|
||||
self.validateHandshake();
|
||||
});
|
||||
req.on('error', handleRequestError);
|
||||
|
||||
req.on('response', function(response) {
|
||||
self._req = null;
|
||||
if (utils.eventEmitterListenerCount(self, 'httpResponse') > 0) {
|
||||
self.emit('httpResponse', response, self);
|
||||
if (response.socket) {
|
||||
response.socket.end();
|
||||
}
|
||||
}
|
||||
else {
|
||||
var headerDumpParts = [];
|
||||
for (var headerName in response.headers) {
|
||||
headerDumpParts.push(headerName + ': ' + response.headers[headerName]);
|
||||
}
|
||||
self.failHandshake(
|
||||
'Server responded with a non-101 status: ' +
|
||||
response.statusCode + ' ' + response.statusMessage +
|
||||
'\nResponse Headers Follow:\n' +
|
||||
headerDumpParts.join('\n') + '\n'
|
||||
);
|
||||
}
|
||||
});
|
||||
req.end();
|
||||
};
|
||||
|
||||
WebSocketClient.prototype.validateHandshake = function() {
|
||||
var headers = this.response.headers;
|
||||
|
||||
if (this.protocols.length > 0) {
|
||||
this.protocol = headers['sec-websocket-protocol'];
|
||||
if (this.protocol) {
|
||||
if (this.protocols.indexOf(this.protocol) === -1) {
|
||||
this.failHandshake('Server did not respond with a requested protocol.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.failHandshake('Expected a Sec-WebSocket-Protocol header.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(headers['connection'] && headers['connection'].toLocaleLowerCase() === 'upgrade')) {
|
||||
this.failHandshake('Expected a Connection: Upgrade header from the server');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(headers['upgrade'] && headers['upgrade'].toLocaleLowerCase() === 'websocket')) {
|
||||
this.failHandshake('Expected an Upgrade: websocket header from the server');
|
||||
return;
|
||||
}
|
||||
|
||||
var sha1 = crypto.createHash('sha1');
|
||||
sha1.update(this.base64nonce + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11');
|
||||
var expectedKey = sha1.digest('base64');
|
||||
|
||||
if (!headers['sec-websocket-accept']) {
|
||||
this.failHandshake('Expected Sec-WebSocket-Accept header from server');
|
||||
return;
|
||||
}
|
||||
|
||||
if (headers['sec-websocket-accept'] !== expectedKey) {
|
||||
this.failHandshake('Sec-WebSocket-Accept header from server didn\'t match expected value of ' + expectedKey);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Support extensions
|
||||
|
||||
this.succeedHandshake();
|
||||
};
|
||||
|
||||
WebSocketClient.prototype.failHandshake = function(errorDescription) {
|
||||
if (this.socket && this.socket.writable) {
|
||||
this.socket.end();
|
||||
}
|
||||
this.emit('connectFailed', new Error(errorDescription));
|
||||
};
|
||||
|
||||
WebSocketClient.prototype.succeedHandshake = function() {
|
||||
var connection = new WebSocketConnection(this.socket, [], this.protocol, true, this.config);
|
||||
|
||||
connection.webSocketVersion = this.config.webSocketVersion;
|
||||
connection._addSocketEventListeners();
|
||||
|
||||
this.emit('connect', connection);
|
||||
if (this.firstDataChunk.length > 0) {
|
||||
connection.handleSocketData(this.firstDataChunk);
|
||||
}
|
||||
this.firstDataChunk = null;
|
||||
};
|
||||
|
||||
WebSocketClient.prototype.abort = function() {
|
||||
if (this._req) {
|
||||
this._req.abort();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = WebSocketClient;
|
896
node_modules/websocket/lib/WebSocketConnection.js
generated
vendored
Normal file
896
node_modules/websocket/lib/WebSocketConnection.js
generated
vendored
Normal file
@ -0,0 +1,896 @@
|
||||
/************************************************************************
|
||||
* Copyright 2010-2015 Brian McKelvey.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
***********************************************************************/
|
||||
|
||||
var util = require('util');
|
||||
var utils = require('./utils');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var WebSocketFrame = require('./WebSocketFrame');
|
||||
var BufferList = require('../vendor/FastBufferList');
|
||||
var Validation = require('./Validation').Validation;
|
||||
var bufferAllocUnsafe = utils.bufferAllocUnsafe;
|
||||
var bufferFromString = utils.bufferFromString;
|
||||
|
||||
// Connected, fully-open, ready to send and receive frames
|
||||
const STATE_OPEN = 'open';
|
||||
// Received a close frame from the remote peer
|
||||
const STATE_PEER_REQUESTED_CLOSE = 'peer_requested_close';
|
||||
// Sent close frame to remote peer. No further data can be sent.
|
||||
const STATE_ENDING = 'ending';
|
||||
// Connection is fully closed. No further data can be sent or received.
|
||||
const STATE_CLOSED = 'closed';
|
||||
|
||||
var setImmediateImpl = ('setImmediate' in global) ?
|
||||
global.setImmediate.bind(global) :
|
||||
process.nextTick.bind(process);
|
||||
|
||||
var idCounter = 0;
|
||||
|
||||
function WebSocketConnection(socket, extensions, protocol, maskOutgoingPackets, config) {
|
||||
this._debug = utils.BufferingLogger('websocket:connection', ++idCounter);
|
||||
this._debug('constructor');
|
||||
|
||||
if (this._debug.enabled) {
|
||||
instrumentSocketForDebugging(this, socket);
|
||||
}
|
||||
|
||||
// Superclass Constructor
|
||||
EventEmitter.call(this);
|
||||
|
||||
this._pingListenerCount = 0;
|
||||
this.on('newListener', function(ev) {
|
||||
if (ev === 'ping'){
|
||||
this._pingListenerCount++;
|
||||
}
|
||||
}).on('removeListener', function(ev) {
|
||||
if (ev === 'ping') {
|
||||
this._pingListenerCount--;
|
||||
}
|
||||
});
|
||||
|
||||
this.config = config;
|
||||
this.socket = socket;
|
||||
this.protocol = protocol;
|
||||
this.extensions = extensions;
|
||||
this.remoteAddress = socket.remoteAddress;
|
||||
this.closeReasonCode = -1;
|
||||
this.closeDescription = null;
|
||||
this.closeEventEmitted = false;
|
||||
|
||||
// We have to mask outgoing packets if we're acting as a WebSocket client.
|
||||
this.maskOutgoingPackets = maskOutgoingPackets;
|
||||
|
||||
// We re-use the same buffers for the mask and frame header for all frames
|
||||
// received on each connection to avoid a small memory allocation for each
|
||||
// frame.
|
||||
this.maskBytes = bufferAllocUnsafe(4);
|
||||
this.frameHeader = bufferAllocUnsafe(10);
|
||||
|
||||
// the BufferList will handle the data streaming in
|
||||
this.bufferList = new BufferList();
|
||||
|
||||
// Prepare for receiving first frame
|
||||
this.currentFrame = new WebSocketFrame(this.maskBytes, this.frameHeader, this.config);
|
||||
this.fragmentationSize = 0; // data received so far...
|
||||
this.frameQueue = [];
|
||||
|
||||
// Various bits of connection state
|
||||
this.connected = true;
|
||||
this.state = STATE_OPEN;
|
||||
this.waitingForCloseResponse = false;
|
||||
// Received TCP FIN, socket's readable stream is finished.
|
||||
this.receivedEnd = false;
|
||||
|
||||
this.closeTimeout = this.config.closeTimeout;
|
||||
this.assembleFragments = this.config.assembleFragments;
|
||||
this.maxReceivedMessageSize = this.config.maxReceivedMessageSize;
|
||||
|
||||
this.outputBufferFull = false;
|
||||
this.inputPaused = false;
|
||||
this.receivedDataHandler = this.processReceivedData.bind(this);
|
||||
this._closeTimerHandler = this.handleCloseTimer.bind(this);
|
||||
|
||||
// Disable nagle algorithm?
|
||||
this.socket.setNoDelay(this.config.disableNagleAlgorithm);
|
||||
|
||||
// Make sure there is no socket inactivity timeout
|
||||
this.socket.setTimeout(0);
|
||||
|
||||
if (this.config.keepalive && !this.config.useNativeKeepalive) {
|
||||
if (typeof(this.config.keepaliveInterval) !== 'number') {
|
||||
throw new Error('keepaliveInterval must be specified and numeric ' +
|
||||
'if keepalive is true.');
|
||||
}
|
||||
this._keepaliveTimerHandler = this.handleKeepaliveTimer.bind(this);
|
||||
this.setKeepaliveTimer();
|
||||
|
||||
if (this.config.dropConnectionOnKeepaliveTimeout) {
|
||||
if (typeof(this.config.keepaliveGracePeriod) !== 'number') {
|
||||
throw new Error('keepaliveGracePeriod must be specified and ' +
|
||||
'numeric if dropConnectionOnKeepaliveTimeout ' +
|
||||
'is true.');
|
||||
}
|
||||
this._gracePeriodTimerHandler = this.handleGracePeriodTimer.bind(this);
|
||||
}
|
||||
}
|
||||
else if (this.config.keepalive && this.config.useNativeKeepalive) {
|
||||
if (!('setKeepAlive' in this.socket)) {
|
||||
throw new Error('Unable to use native keepalive: unsupported by ' +
|
||||
'this version of Node.');
|
||||
}
|
||||
this.socket.setKeepAlive(true, this.config.keepaliveInterval);
|
||||
}
|
||||
|
||||
// The HTTP Client seems to subscribe to socket error events
|
||||
// and re-dispatch them in such a way that doesn't make sense
|
||||
// for users of our client, so we want to make sure nobody
|
||||
// else is listening for error events on the socket besides us.
|
||||
this.socket.removeAllListeners('error');
|
||||
}
|
||||
|
||||
WebSocketConnection.CLOSE_REASON_NORMAL = 1000;
|
||||
WebSocketConnection.CLOSE_REASON_GOING_AWAY = 1001;
|
||||
WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR = 1002;
|
||||
WebSocketConnection.CLOSE_REASON_UNPROCESSABLE_INPUT = 1003;
|
||||
WebSocketConnection.CLOSE_REASON_RESERVED = 1004; // Reserved value. Undefined meaning.
|
||||
WebSocketConnection.CLOSE_REASON_NOT_PROVIDED = 1005; // Not to be used on the wire
|
||||
WebSocketConnection.CLOSE_REASON_ABNORMAL = 1006; // Not to be used on the wire
|
||||
WebSocketConnection.CLOSE_REASON_INVALID_DATA = 1007;
|
||||
WebSocketConnection.CLOSE_REASON_POLICY_VIOLATION = 1008;
|
||||
WebSocketConnection.CLOSE_REASON_MESSAGE_TOO_BIG = 1009;
|
||||
WebSocketConnection.CLOSE_REASON_EXTENSION_REQUIRED = 1010;
|
||||
WebSocketConnection.CLOSE_REASON_INTERNAL_SERVER_ERROR = 1011;
|
||||
WebSocketConnection.CLOSE_REASON_TLS_HANDSHAKE_FAILED = 1015; // Not to be used on the wire
|
||||
|
||||
WebSocketConnection.CLOSE_DESCRIPTIONS = {
|
||||
1000: 'Normal connection closure',
|
||||
1001: 'Remote peer is going away',
|
||||
1002: 'Protocol error',
|
||||
1003: 'Unprocessable input',
|
||||
1004: 'Reserved',
|
||||
1005: 'Reason not provided',
|
||||
1006: 'Abnormal closure, no further detail available',
|
||||
1007: 'Invalid data received',
|
||||
1008: 'Policy violation',
|
||||
1009: 'Message too big',
|
||||
1010: 'Extension requested by client is required',
|
||||
1011: 'Internal Server Error',
|
||||
1015: 'TLS Handshake Failed'
|
||||
};
|
||||
|
||||
function validateCloseReason(code) {
|
||||
if (code < 1000) {
|
||||
// Status codes in the range 0-999 are not used
|
||||
return false;
|
||||
}
|
||||
if (code >= 1000 && code <= 2999) {
|
||||
// Codes from 1000 - 2999 are reserved for use by the protocol. Only
|
||||
// a few codes are defined, all others are currently illegal.
|
||||
return [1000, 1001, 1002, 1003, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014].indexOf(code) !== -1;
|
||||
}
|
||||
if (code >= 3000 && code <= 3999) {
|
||||
// Reserved for use by libraries, frameworks, and applications.
|
||||
// Should be registered with IANA. Interpretation of these codes is
|
||||
// undefined by the WebSocket protocol.
|
||||
return true;
|
||||
}
|
||||
if (code >= 4000 && code <= 4999) {
|
||||
// Reserved for private use. Interpretation of these codes is
|
||||
// undefined by the WebSocket protocol.
|
||||
return true;
|
||||
}
|
||||
if (code >= 5000) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
util.inherits(WebSocketConnection, EventEmitter);
|
||||
|
||||
WebSocketConnection.prototype._addSocketEventListeners = function() {
|
||||
this.socket.on('error', this.handleSocketError.bind(this));
|
||||
this.socket.on('end', this.handleSocketEnd.bind(this));
|
||||
this.socket.on('close', this.handleSocketClose.bind(this));
|
||||
this.socket.on('drain', this.handleSocketDrain.bind(this));
|
||||
this.socket.on('pause', this.handleSocketPause.bind(this));
|
||||
this.socket.on('resume', this.handleSocketResume.bind(this));
|
||||
this.socket.on('data', this.handleSocketData.bind(this));
|
||||
};
|
||||
|
||||
// set or reset the keepalive timer when data is received.
|
||||
WebSocketConnection.prototype.setKeepaliveTimer = function() {
|
||||
this._debug('setKeepaliveTimer');
|
||||
if (!this.config.keepalive || this.config.useNativeKeepalive) { return; }
|
||||
this.clearKeepaliveTimer();
|
||||
this.clearGracePeriodTimer();
|
||||
this._keepaliveTimeoutID = setTimeout(this._keepaliveTimerHandler, this.config.keepaliveInterval);
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.clearKeepaliveTimer = function() {
|
||||
if (this._keepaliveTimeoutID) {
|
||||
clearTimeout(this._keepaliveTimeoutID);
|
||||
}
|
||||
};
|
||||
|
||||
// No data has been received within config.keepaliveTimeout ms.
|
||||
WebSocketConnection.prototype.handleKeepaliveTimer = function() {
|
||||
this._debug('handleKeepaliveTimer');
|
||||
this._keepaliveTimeoutID = null;
|
||||
this.ping();
|
||||
|
||||
// If we are configured to drop connections if the client doesn't respond
|
||||
// then set the grace period timer.
|
||||
if (this.config.dropConnectionOnKeepaliveTimeout) {
|
||||
this.setGracePeriodTimer();
|
||||
}
|
||||
else {
|
||||
// Otherwise reset the keepalive timer to send the next ping.
|
||||
this.setKeepaliveTimer();
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.setGracePeriodTimer = function() {
|
||||
this._debug('setGracePeriodTimer');
|
||||
this.clearGracePeriodTimer();
|
||||
this._gracePeriodTimeoutID = setTimeout(this._gracePeriodTimerHandler, this.config.keepaliveGracePeriod);
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.clearGracePeriodTimer = function() {
|
||||
if (this._gracePeriodTimeoutID) {
|
||||
clearTimeout(this._gracePeriodTimeoutID);
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.handleGracePeriodTimer = function() {
|
||||
this._debug('handleGracePeriodTimer');
|
||||
// If this is called, the client has not responded and is assumed dead.
|
||||
this._gracePeriodTimeoutID = null;
|
||||
this.drop(WebSocketConnection.CLOSE_REASON_ABNORMAL, 'Peer not responding.', true);
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.handleSocketData = function(data) {
|
||||
this._debug('handleSocketData');
|
||||
// Reset the keepalive timer when receiving data of any kind.
|
||||
this.setKeepaliveTimer();
|
||||
|
||||
// Add received data to our bufferList, which efficiently holds received
|
||||
// data chunks in a linked list of Buffer objects.
|
||||
this.bufferList.write(data);
|
||||
|
||||
this.processReceivedData();
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.processReceivedData = function() {
|
||||
this._debug('processReceivedData');
|
||||
// If we're not connected, we should ignore any data remaining on the buffer.
|
||||
if (!this.connected) { return; }
|
||||
|
||||
// Receiving/parsing is expected to be halted when paused.
|
||||
if (this.inputPaused) { return; }
|
||||
|
||||
var frame = this.currentFrame;
|
||||
|
||||
// WebSocketFrame.prototype.addData returns true if all data necessary to
|
||||
// parse the frame was available. It returns false if we are waiting for
|
||||
// more data to come in on the wire.
|
||||
if (!frame.addData(this.bufferList)) { this._debug('-- insufficient data for frame'); return; }
|
||||
|
||||
var self = this;
|
||||
|
||||
// Handle possible parsing errors
|
||||
if (frame.protocolError) {
|
||||
// Something bad happened.. get rid of this client.
|
||||
this._debug('-- protocol error');
|
||||
process.nextTick(function() {
|
||||
self.drop(WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR, frame.dropReason);
|
||||
});
|
||||
return;
|
||||
}
|
||||
else if (frame.frameTooLarge) {
|
||||
this._debug('-- frame too large');
|
||||
process.nextTick(function() {
|
||||
self.drop(WebSocketConnection.CLOSE_REASON_MESSAGE_TOO_BIG, frame.dropReason);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// For now since we don't support extensions, all RSV bits are illegal
|
||||
if (frame.rsv1 || frame.rsv2 || frame.rsv3) {
|
||||
this._debug('-- illegal rsv flag');
|
||||
process.nextTick(function() {
|
||||
self.drop(WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR,
|
||||
'Unsupported usage of rsv bits without negotiated extension.');
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.assembleFragments) {
|
||||
this._debug('-- emitting frame');
|
||||
process.nextTick(function() { self.emit('frame', frame); });
|
||||
}
|
||||
|
||||
process.nextTick(function() { self.processFrame(frame); });
|
||||
|
||||
this.currentFrame = new WebSocketFrame(this.maskBytes, this.frameHeader, this.config);
|
||||
|
||||
// If there's data remaining, schedule additional processing, but yield
|
||||
// for now so that other connections have a chance to have their data
|
||||
// processed. We use setImmediate here instead of process.nextTick to
|
||||
// explicitly indicate that we wish for other I/O to be handled first.
|
||||
if (this.bufferList.length > 0) {
|
||||
setImmediateImpl(this.receivedDataHandler);
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.handleSocketError = function(error) {
|
||||
this._debug('handleSocketError: %j', error);
|
||||
if (this.state === STATE_CLOSED) {
|
||||
// See https://github.com/theturtle32/WebSocket-Node/issues/288
|
||||
this._debug(' --- Socket \'error\' after \'close\'');
|
||||
return;
|
||||
}
|
||||
this.closeReasonCode = WebSocketConnection.CLOSE_REASON_ABNORMAL;
|
||||
this.closeDescription = 'Socket Error: ' + error.syscall + ' ' + error.code;
|
||||
this.connected = false;
|
||||
this.state = STATE_CLOSED;
|
||||
this.fragmentationSize = 0;
|
||||
if (utils.eventEmitterListenerCount(this, 'error') > 0) {
|
||||
this.emit('error', error);
|
||||
}
|
||||
this.socket.destroy(error);
|
||||
this._debug.printOutput();
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.handleSocketEnd = function() {
|
||||
this._debug('handleSocketEnd: received socket end. state = %s', this.state);
|
||||
this.receivedEnd = true;
|
||||
if (this.state === STATE_CLOSED) {
|
||||
// When using the TLS module, sometimes the socket will emit 'end'
|
||||
// after it emits 'close'. I don't think that's correct behavior,
|
||||
// but we should deal with it gracefully by ignoring it.
|
||||
this._debug(' --- Socket \'end\' after \'close\'');
|
||||
return;
|
||||
}
|
||||
if (this.state !== STATE_PEER_REQUESTED_CLOSE &&
|
||||
this.state !== STATE_ENDING) {
|
||||
this._debug(' --- UNEXPECTED socket end.');
|
||||
this.socket.end();
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.handleSocketClose = function(hadError) {
|
||||
this._debug('handleSocketClose: received socket close');
|
||||
this.socketHadError = hadError;
|
||||
this.connected = false;
|
||||
this.state = STATE_CLOSED;
|
||||
// If closeReasonCode is still set to -1 at this point then we must
|
||||
// not have received a close frame!!
|
||||
if (this.closeReasonCode === -1) {
|
||||
this.closeReasonCode = WebSocketConnection.CLOSE_REASON_ABNORMAL;
|
||||
this.closeDescription = 'Connection dropped by remote peer.';
|
||||
}
|
||||
this.clearCloseTimer();
|
||||
this.clearKeepaliveTimer();
|
||||
this.clearGracePeriodTimer();
|
||||
if (!this.closeEventEmitted) {
|
||||
this.closeEventEmitted = true;
|
||||
this._debug('-- Emitting WebSocketConnection close event');
|
||||
this.emit('close', this.closeReasonCode, this.closeDescription);
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.handleSocketDrain = function() {
|
||||
this._debug('handleSocketDrain: socket drain event');
|
||||
this.outputBufferFull = false;
|
||||
this.emit('drain');
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.handleSocketPause = function() {
|
||||
this._debug('handleSocketPause: socket pause event');
|
||||
this.inputPaused = true;
|
||||
this.emit('pause');
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.handleSocketResume = function() {
|
||||
this._debug('handleSocketResume: socket resume event');
|
||||
this.inputPaused = false;
|
||||
this.emit('resume');
|
||||
this.processReceivedData();
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.pause = function() {
|
||||
this._debug('pause: pause requested');
|
||||
this.socket.pause();
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.resume = function() {
|
||||
this._debug('resume: resume requested');
|
||||
this.socket.resume();
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.close = function(reasonCode, description) {
|
||||
if (this.connected) {
|
||||
this._debug('close: Initating clean WebSocket close sequence.');
|
||||
if ('number' !== typeof reasonCode) {
|
||||
reasonCode = WebSocketConnection.CLOSE_REASON_NORMAL;
|
||||
}
|
||||
if (!validateCloseReason(reasonCode)) {
|
||||
throw new Error('Close code ' + reasonCode + ' is not valid.');
|
||||
}
|
||||
if ('string' !== typeof description) {
|
||||
description = WebSocketConnection.CLOSE_DESCRIPTIONS[reasonCode];
|
||||
}
|
||||
this.closeReasonCode = reasonCode;
|
||||
this.closeDescription = description;
|
||||
this.setCloseTimer();
|
||||
this.sendCloseFrame(this.closeReasonCode, this.closeDescription);
|
||||
this.state = STATE_ENDING;
|
||||
this.connected = false;
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.drop = function(reasonCode, description, skipCloseFrame) {
|
||||
this._debug('drop');
|
||||
if (typeof(reasonCode) !== 'number') {
|
||||
reasonCode = WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
if (typeof(description) !== 'string') {
|
||||
// If no description is provided, try to look one up based on the
|
||||
// specified reasonCode.
|
||||
description = WebSocketConnection.CLOSE_DESCRIPTIONS[reasonCode];
|
||||
}
|
||||
|
||||
this._debug('Forcefully dropping connection. skipCloseFrame: %s, code: %d, description: %s',
|
||||
skipCloseFrame, reasonCode, description
|
||||
);
|
||||
|
||||
this.closeReasonCode = reasonCode;
|
||||
this.closeDescription = description;
|
||||
this.frameQueue = [];
|
||||
this.fragmentationSize = 0;
|
||||
if (!skipCloseFrame) {
|
||||
this.sendCloseFrame(reasonCode, description);
|
||||
}
|
||||
this.connected = false;
|
||||
this.state = STATE_CLOSED;
|
||||
this.clearCloseTimer();
|
||||
this.clearKeepaliveTimer();
|
||||
this.clearGracePeriodTimer();
|
||||
|
||||
if (!this.closeEventEmitted) {
|
||||
this.closeEventEmitted = true;
|
||||
this._debug('Emitting WebSocketConnection close event');
|
||||
this.emit('close', this.closeReasonCode, this.closeDescription);
|
||||
}
|
||||
|
||||
this._debug('Drop: destroying socket');
|
||||
this.socket.destroy();
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.setCloseTimer = function() {
|
||||
this._debug('setCloseTimer');
|
||||
this.clearCloseTimer();
|
||||
this._debug('Setting close timer');
|
||||
this.waitingForCloseResponse = true;
|
||||
this.closeTimer = setTimeout(this._closeTimerHandler, this.closeTimeout);
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.clearCloseTimer = function() {
|
||||
this._debug('clearCloseTimer');
|
||||
if (this.closeTimer) {
|
||||
this._debug('Clearing close timer');
|
||||
clearTimeout(this.closeTimer);
|
||||
this.waitingForCloseResponse = false;
|
||||
this.closeTimer = null;
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.handleCloseTimer = function() {
|
||||
this._debug('handleCloseTimer');
|
||||
this.closeTimer = null;
|
||||
if (this.waitingForCloseResponse) {
|
||||
this._debug('Close response not received from client. Forcing socket end.');
|
||||
this.waitingForCloseResponse = false;
|
||||
this.state = STATE_CLOSED;
|
||||
this.socket.end();
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.processFrame = function(frame) {
|
||||
this._debug('processFrame');
|
||||
this._debug(' -- frame: %s', frame);
|
||||
|
||||
// Any non-control opcode besides 0x00 (continuation) received in the
|
||||
// middle of a fragmented message is illegal.
|
||||
if (this.frameQueue.length !== 0 && (frame.opcode > 0x00 && frame.opcode < 0x08)) {
|
||||
this.drop(WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR,
|
||||
'Illegal frame opcode 0x' + frame.opcode.toString(16) + ' ' +
|
||||
'received in middle of fragmented message.');
|
||||
return;
|
||||
}
|
||||
|
||||
switch(frame.opcode) {
|
||||
case 0x02: // WebSocketFrame.BINARY_FRAME
|
||||
this._debug('-- Binary Frame');
|
||||
if (this.assembleFragments) {
|
||||
if (frame.fin) {
|
||||
// Complete single-frame message received
|
||||
this._debug('---- Emitting \'message\' event');
|
||||
this.emit('message', {
|
||||
type: 'binary',
|
||||
binaryData: frame.binaryPayload
|
||||
});
|
||||
}
|
||||
else {
|
||||
// beginning of a fragmented message
|
||||
this.frameQueue.push(frame);
|
||||
this.fragmentationSize = frame.length;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x01: // WebSocketFrame.TEXT_FRAME
|
||||
this._debug('-- Text Frame');
|
||||
if (this.assembleFragments) {
|
||||
if (frame.fin) {
|
||||
if (!Validation.isValidUTF8(frame.binaryPayload)) {
|
||||
this.drop(WebSocketConnection.CLOSE_REASON_INVALID_DATA,
|
||||
'Invalid UTF-8 Data Received');
|
||||
return;
|
||||
}
|
||||
// Complete single-frame message received
|
||||
this._debug('---- Emitting \'message\' event');
|
||||
this.emit('message', {
|
||||
type: 'utf8',
|
||||
utf8Data: frame.binaryPayload.toString('utf8')
|
||||
});
|
||||
}
|
||||
else {
|
||||
// beginning of a fragmented message
|
||||
this.frameQueue.push(frame);
|
||||
this.fragmentationSize = frame.length;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x00: // WebSocketFrame.CONTINUATION
|
||||
this._debug('-- Continuation Frame');
|
||||
if (this.assembleFragments) {
|
||||
if (this.frameQueue.length === 0) {
|
||||
this.drop(WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR,
|
||||
'Unexpected Continuation Frame');
|
||||
return;
|
||||
}
|
||||
|
||||
this.fragmentationSize += frame.length;
|
||||
|
||||
if (this.fragmentationSize > this.maxReceivedMessageSize) {
|
||||
this.drop(WebSocketConnection.CLOSE_REASON_MESSAGE_TOO_BIG,
|
||||
'Maximum message size exceeded.');
|
||||
return;
|
||||
}
|
||||
|
||||
this.frameQueue.push(frame);
|
||||
|
||||
if (frame.fin) {
|
||||
// end of fragmented message, so we process the whole
|
||||
// message now. We also have to decode the utf-8 data
|
||||
// for text frames after combining all the fragments.
|
||||
var bytesCopied = 0;
|
||||
var binaryPayload = bufferAllocUnsafe(this.fragmentationSize);
|
||||
var opcode = this.frameQueue[0].opcode;
|
||||
this.frameQueue.forEach(function (currentFrame) {
|
||||
currentFrame.binaryPayload.copy(binaryPayload, bytesCopied);
|
||||
bytesCopied += currentFrame.binaryPayload.length;
|
||||
});
|
||||
this.frameQueue = [];
|
||||
this.fragmentationSize = 0;
|
||||
|
||||
switch (opcode) {
|
||||
case 0x02: // WebSocketOpcode.BINARY_FRAME
|
||||
this.emit('message', {
|
||||
type: 'binary',
|
||||
binaryData: binaryPayload
|
||||
});
|
||||
break;
|
||||
case 0x01: // WebSocketOpcode.TEXT_FRAME
|
||||
if (!Validation.isValidUTF8(binaryPayload)) {
|
||||
this.drop(WebSocketConnection.CLOSE_REASON_INVALID_DATA,
|
||||
'Invalid UTF-8 Data Received');
|
||||
return;
|
||||
}
|
||||
this.emit('message', {
|
||||
type: 'utf8',
|
||||
utf8Data: binaryPayload.toString('utf8')
|
||||
});
|
||||
break;
|
||||
default:
|
||||
this.drop(WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR,
|
||||
'Unexpected first opcode in fragmentation sequence: 0x' + opcode.toString(16));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x09: // WebSocketFrame.PING
|
||||
this._debug('-- Ping Frame');
|
||||
|
||||
if (this._pingListenerCount > 0) {
|
||||
// logic to emit the ping frame: this is only done when a listener is known to exist
|
||||
// Expose a function allowing the user to override the default ping() behavior
|
||||
var cancelled = false;
|
||||
var cancel = function() {
|
||||
cancelled = true;
|
||||
};
|
||||
this.emit('ping', cancel, frame.binaryPayload);
|
||||
|
||||
// Only send a pong if the client did not indicate that he would like to cancel
|
||||
if (!cancelled) {
|
||||
this.pong(frame.binaryPayload);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.pong(frame.binaryPayload);
|
||||
}
|
||||
|
||||
break;
|
||||
case 0x0A: // WebSocketFrame.PONG
|
||||
this._debug('-- Pong Frame');
|
||||
this.emit('pong', frame.binaryPayload);
|
||||
break;
|
||||
case 0x08: // WebSocketFrame.CONNECTION_CLOSE
|
||||
this._debug('-- Close Frame');
|
||||
if (this.waitingForCloseResponse) {
|
||||
// Got response to our request to close the connection.
|
||||
// Close is complete, so we just hang up.
|
||||
this._debug('---- Got close response from peer. Completing closing handshake.');
|
||||
this.clearCloseTimer();
|
||||
this.waitingForCloseResponse = false;
|
||||
this.state = STATE_CLOSED;
|
||||
this.socket.end();
|
||||
return;
|
||||
}
|
||||
|
||||
this._debug('---- Closing handshake initiated by peer.');
|
||||
// Got request from other party to close connection.
|
||||
// Send back acknowledgement and then hang up.
|
||||
this.state = STATE_PEER_REQUESTED_CLOSE;
|
||||
var respondCloseReasonCode;
|
||||
|
||||
// Make sure the close reason provided is legal according to
|
||||
// the protocol spec. Providing no close status is legal.
|
||||
// WebSocketFrame sets closeStatus to -1 by default, so if it
|
||||
// is still -1, then no status was provided.
|
||||
if (frame.invalidCloseFrameLength) {
|
||||
this.closeReasonCode = 1005; // 1005 = No reason provided.
|
||||
respondCloseReasonCode = WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR;
|
||||
}
|
||||
else if (frame.closeStatus === -1 || validateCloseReason(frame.closeStatus)) {
|
||||
this.closeReasonCode = frame.closeStatus;
|
||||
respondCloseReasonCode = WebSocketConnection.CLOSE_REASON_NORMAL;
|
||||
}
|
||||
else {
|
||||
this.closeReasonCode = frame.closeStatus;
|
||||
respondCloseReasonCode = WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
// If there is a textual description in the close frame, extract it.
|
||||
if (frame.binaryPayload.length > 1) {
|
||||
if (!Validation.isValidUTF8(frame.binaryPayload)) {
|
||||
this.drop(WebSocketConnection.CLOSE_REASON_INVALID_DATA,
|
||||
'Invalid UTF-8 Data Received');
|
||||
return;
|
||||
}
|
||||
this.closeDescription = frame.binaryPayload.toString('utf8');
|
||||
}
|
||||
else {
|
||||
this.closeDescription = WebSocketConnection.CLOSE_DESCRIPTIONS[this.closeReasonCode];
|
||||
}
|
||||
this._debug(
|
||||
'------ Remote peer %s - code: %d - %s - close frame payload length: %d',
|
||||
this.remoteAddress, this.closeReasonCode,
|
||||
this.closeDescription, frame.length
|
||||
);
|
||||
this._debug('------ responding to remote peer\'s close request.');
|
||||
this.sendCloseFrame(respondCloseReasonCode, null);
|
||||
this.connected = false;
|
||||
break;
|
||||
default:
|
||||
this._debug('-- Unrecognized Opcode %d', frame.opcode);
|
||||
this.drop(WebSocketConnection.CLOSE_REASON_PROTOCOL_ERROR,
|
||||
'Unrecognized Opcode: 0x' + frame.opcode.toString(16));
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.send = function(data, cb) {
|
||||
this._debug('send');
|
||||
if (Buffer.isBuffer(data)) {
|
||||
this.sendBytes(data, cb);
|
||||
}
|
||||
else if (typeof(data['toString']) === 'function') {
|
||||
this.sendUTF(data, cb);
|
||||
}
|
||||
else {
|
||||
throw new Error('Data provided must either be a Node Buffer or implement toString()');
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.sendUTF = function(data, cb) {
|
||||
data = bufferFromString(data.toString(), 'utf8');
|
||||
this._debug('sendUTF: %d bytes', data.length);
|
||||
var frame = new WebSocketFrame(this.maskBytes, this.frameHeader, this.config);
|
||||
frame.opcode = 0x01; // WebSocketOpcode.TEXT_FRAME
|
||||
frame.binaryPayload = data;
|
||||
this.fragmentAndSend(frame, cb);
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.sendBytes = function(data, cb) {
|
||||
this._debug('sendBytes');
|
||||
if (!Buffer.isBuffer(data)) {
|
||||
throw new Error('You must pass a Node Buffer object to WebSocketConnection.prototype.sendBytes()');
|
||||
}
|
||||
var frame = new WebSocketFrame(this.maskBytes, this.frameHeader, this.config);
|
||||
frame.opcode = 0x02; // WebSocketOpcode.BINARY_FRAME
|
||||
frame.binaryPayload = data;
|
||||
this.fragmentAndSend(frame, cb);
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.ping = function(data) {
|
||||
this._debug('ping');
|
||||
var frame = new WebSocketFrame(this.maskBytes, this.frameHeader, this.config);
|
||||
frame.opcode = 0x09; // WebSocketOpcode.PING
|
||||
frame.fin = true;
|
||||
if (data) {
|
||||
if (!Buffer.isBuffer(data)) {
|
||||
data = bufferFromString(data.toString(), 'utf8');
|
||||
}
|
||||
if (data.length > 125) {
|
||||
this._debug('WebSocket: Data for ping is longer than 125 bytes. Truncating.');
|
||||
data = data.slice(0,124);
|
||||
}
|
||||
frame.binaryPayload = data;
|
||||
}
|
||||
this.sendFrame(frame);
|
||||
};
|
||||
|
||||
// Pong frames have to echo back the contents of the data portion of the
|
||||
// ping frame exactly, byte for byte.
|
||||
WebSocketConnection.prototype.pong = function(binaryPayload) {
|
||||
this._debug('pong');
|
||||
var frame = new WebSocketFrame(this.maskBytes, this.frameHeader, this.config);
|
||||
frame.opcode = 0x0A; // WebSocketOpcode.PONG
|
||||
if (Buffer.isBuffer(binaryPayload) && binaryPayload.length > 125) {
|
||||
this._debug('WebSocket: Data for pong is longer than 125 bytes. Truncating.');
|
||||
binaryPayload = binaryPayload.slice(0,124);
|
||||
}
|
||||
frame.binaryPayload = binaryPayload;
|
||||
frame.fin = true;
|
||||
this.sendFrame(frame);
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.fragmentAndSend = function(frame, cb) {
|
||||
this._debug('fragmentAndSend');
|
||||
if (frame.opcode > 0x07) {
|
||||
throw new Error('You cannot fragment control frames.');
|
||||
}
|
||||
|
||||
var threshold = this.config.fragmentationThreshold;
|
||||
var length = frame.binaryPayload.length;
|
||||
|
||||
// Send immediately if fragmentation is disabled or the message is not
|
||||
// larger than the fragmentation threshold.
|
||||
if (!this.config.fragmentOutgoingMessages || (frame.binaryPayload && length <= threshold)) {
|
||||
frame.fin = true;
|
||||
this.sendFrame(frame, cb);
|
||||
return;
|
||||
}
|
||||
|
||||
var numFragments = Math.ceil(length / threshold);
|
||||
var sentFragments = 0;
|
||||
var sentCallback = function fragmentSentCallback(err) {
|
||||
if (err) {
|
||||
if (typeof cb === 'function') {
|
||||
// pass only the first error
|
||||
cb(err);
|
||||
cb = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
++sentFragments;
|
||||
if ((sentFragments === numFragments) && (typeof cb === 'function')) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
for (var i=1; i <= numFragments; i++) {
|
||||
var currentFrame = new WebSocketFrame(this.maskBytes, this.frameHeader, this.config);
|
||||
|
||||
// continuation opcode except for first frame.
|
||||
currentFrame.opcode = (i === 1) ? frame.opcode : 0x00;
|
||||
|
||||
// fin set on last frame only
|
||||
currentFrame.fin = (i === numFragments);
|
||||
|
||||
// length is likely to be shorter on the last fragment
|
||||
var currentLength = (i === numFragments) ? length - (threshold * (i-1)) : threshold;
|
||||
var sliceStart = threshold * (i-1);
|
||||
|
||||
// Slice the right portion of the original payload
|
||||
currentFrame.binaryPayload = frame.binaryPayload.slice(sliceStart, sliceStart + currentLength);
|
||||
|
||||
this.sendFrame(currentFrame, sentCallback);
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.sendCloseFrame = function(reasonCode, description, cb) {
|
||||
if (typeof(reasonCode) !== 'number') {
|
||||
reasonCode = WebSocketConnection.CLOSE_REASON_NORMAL;
|
||||
}
|
||||
|
||||
this._debug('sendCloseFrame state: %s, reasonCode: %d, description: %s', this.state, reasonCode, description);
|
||||
|
||||
if (this.state !== STATE_OPEN && this.state !== STATE_PEER_REQUESTED_CLOSE) { return; }
|
||||
|
||||
var frame = new WebSocketFrame(this.maskBytes, this.frameHeader, this.config);
|
||||
frame.fin = true;
|
||||
frame.opcode = 0x08; // WebSocketOpcode.CONNECTION_CLOSE
|
||||
frame.closeStatus = reasonCode;
|
||||
if (typeof(description) === 'string') {
|
||||
frame.binaryPayload = bufferFromString(description, 'utf8');
|
||||
}
|
||||
|
||||
this.sendFrame(frame, cb);
|
||||
this.socket.end();
|
||||
};
|
||||
|
||||
WebSocketConnection.prototype.sendFrame = function(frame, cb) {
|
||||
this._debug('sendFrame');
|
||||
frame.mask = this.maskOutgoingPackets;
|
||||
var flushed = this.socket.write(frame.toBuffer(), cb);
|
||||
this.outputBufferFull = !flushed;
|
||||
return flushed;
|
||||
};
|
||||
|
||||
module.exports = WebSocketConnection;
|
||||
|
||||
|
||||
|
||||
function instrumentSocketForDebugging(connection, socket) {
|
||||
/* jshint loopfunc: true */
|
||||
if (!connection._debug.enabled) { return; }
|
||||
|
||||
var originalSocketEmit = socket.emit;
|
||||
socket.emit = function(event) {
|
||||
connection._debug('||| Socket Event \'%s\'', event);
|
||||
originalSocketEmit.apply(this, arguments);
|
||||
};
|
||||
|
||||
for (var key in socket) {
|
||||
if ('function' !== typeof(socket[key])) { continue; }
|
||||
if (['emit'].indexOf(key) !== -1) { continue; }
|
||||
(function(key) {
|
||||
var original = socket[key];
|
||||
if (key === 'on') {
|
||||
socket[key] = function proxyMethod__EventEmitter__On() {
|
||||
connection._debug('||| Socket method called: %s (%s)', key, arguments[0]);
|
||||
return original.apply(this, arguments);
|
||||
};
|
||||
return;
|
||||
}
|
||||
socket[key] = function proxyMethod() {
|
||||
connection._debug('||| Socket method called: %s', key);
|
||||
return original.apply(this, arguments);
|
||||
};
|
||||
})(key);
|
||||
}
|
||||
}
|
280
node_modules/websocket/lib/WebSocketFrame.js
generated
vendored
Normal file
280
node_modules/websocket/lib/WebSocketFrame.js
generated
vendored
Normal file
@ -0,0 +1,280 @@
|
||||
/************************************************************************
|
||||
* Copyright 2010-2015 Brian McKelvey.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
***********************************************************************/
|
||||
|
||||
var bufferUtil = require('./BufferUtil').BufferUtil;
|
||||
var bufferAllocUnsafe = require('./utils').bufferAllocUnsafe;
|
||||
|
||||
const DECODE_HEADER = 1;
|
||||
const WAITING_FOR_16_BIT_LENGTH = 2;
|
||||
const WAITING_FOR_64_BIT_LENGTH = 3;
|
||||
const WAITING_FOR_MASK_KEY = 4;
|
||||
const WAITING_FOR_PAYLOAD = 5;
|
||||
const COMPLETE = 6;
|
||||
|
||||
// WebSocketConnection will pass shared buffer objects for maskBytes and
|
||||
// frameHeader into the constructor to avoid tons of small memory allocations
|
||||
// for each frame we have to parse. This is only used for parsing frames
|
||||
// we receive off the wire.
|
||||
function WebSocketFrame(maskBytes, frameHeader, config) {
|
||||
this.maskBytes = maskBytes;
|
||||
this.frameHeader = frameHeader;
|
||||
this.config = config;
|
||||
this.maxReceivedFrameSize = config.maxReceivedFrameSize;
|
||||
this.protocolError = false;
|
||||
this.frameTooLarge = false;
|
||||
this.invalidCloseFrameLength = false;
|
||||
this.parseState = DECODE_HEADER;
|
||||
this.closeStatus = -1;
|
||||
}
|
||||
|
||||
WebSocketFrame.prototype.addData = function(bufferList) {
|
||||
if (this.parseState === DECODE_HEADER) {
|
||||
if (bufferList.length >= 2) {
|
||||
bufferList.joinInto(this.frameHeader, 0, 0, 2);
|
||||
bufferList.advance(2);
|
||||
var firstByte = this.frameHeader[0];
|
||||
var secondByte = this.frameHeader[1];
|
||||
|
||||
this.fin = Boolean(firstByte & 0x80);
|
||||
this.rsv1 = Boolean(firstByte & 0x40);
|
||||
this.rsv2 = Boolean(firstByte & 0x20);
|
||||
this.rsv3 = Boolean(firstByte & 0x10);
|
||||
this.mask = Boolean(secondByte & 0x80);
|
||||
|
||||
this.opcode = firstByte & 0x0F;
|
||||
this.length = secondByte & 0x7F;
|
||||
|
||||
// Control frame sanity check
|
||||
if (this.opcode >= 0x08) {
|
||||
if (this.length > 125) {
|
||||
this.protocolError = true;
|
||||
this.dropReason = 'Illegal control frame longer than 125 bytes.';
|
||||
return true;
|
||||
}
|
||||
if (!this.fin) {
|
||||
this.protocolError = true;
|
||||
this.dropReason = 'Control frames must not be fragmented.';
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.length === 126) {
|
||||
this.parseState = WAITING_FOR_16_BIT_LENGTH;
|
||||
}
|
||||
else if (this.length === 127) {
|
||||
this.parseState = WAITING_FOR_64_BIT_LENGTH;
|
||||
}
|
||||
else {
|
||||
this.parseState = WAITING_FOR_MASK_KEY;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.parseState === WAITING_FOR_16_BIT_LENGTH) {
|
||||
if (bufferList.length >= 2) {
|
||||
bufferList.joinInto(this.frameHeader, 2, 0, 2);
|
||||
bufferList.advance(2);
|
||||
this.length = this.frameHeader.readUInt16BE(2);
|
||||
this.parseState = WAITING_FOR_MASK_KEY;
|
||||
}
|
||||
}
|
||||
else if (this.parseState === WAITING_FOR_64_BIT_LENGTH) {
|
||||
if (bufferList.length >= 8) {
|
||||
bufferList.joinInto(this.frameHeader, 2, 0, 8);
|
||||
bufferList.advance(8);
|
||||
var lengthPair = [
|
||||
this.frameHeader.readUInt32BE(2),
|
||||
this.frameHeader.readUInt32BE(2+4)
|
||||
];
|
||||
|
||||
if (lengthPair[0] !== 0) {
|
||||
this.protocolError = true;
|
||||
this.dropReason = 'Unsupported 64-bit length frame received';
|
||||
return true;
|
||||
}
|
||||
this.length = lengthPair[1];
|
||||
this.parseState = WAITING_FOR_MASK_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.parseState === WAITING_FOR_MASK_KEY) {
|
||||
if (this.mask) {
|
||||
if (bufferList.length >= 4) {
|
||||
bufferList.joinInto(this.maskBytes, 0, 0, 4);
|
||||
bufferList.advance(4);
|
||||
this.parseState = WAITING_FOR_PAYLOAD;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.parseState = WAITING_FOR_PAYLOAD;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.parseState === WAITING_FOR_PAYLOAD) {
|
||||
if (this.length > this.maxReceivedFrameSize) {
|
||||
this.frameTooLarge = true;
|
||||
this.dropReason = 'Frame size of ' + this.length.toString(10) +
|
||||
' bytes exceeds maximum accepted frame size';
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.length === 0) {
|
||||
this.binaryPayload = bufferAllocUnsafe(0);
|
||||
this.parseState = COMPLETE;
|
||||
return true;
|
||||
}
|
||||
if (bufferList.length >= this.length) {
|
||||
this.binaryPayload = bufferList.take(this.length);
|
||||
bufferList.advance(this.length);
|
||||
if (this.mask) {
|
||||
bufferUtil.unmask(this.binaryPayload, this.maskBytes);
|
||||
// xor(this.binaryPayload, this.maskBytes, 0);
|
||||
}
|
||||
|
||||
if (this.opcode === 0x08) { // WebSocketOpcode.CONNECTION_CLOSE
|
||||
if (this.length === 1) {
|
||||
// Invalid length for a close frame. Must be zero or at least two.
|
||||
this.binaryPayload = bufferAllocUnsafe(0);
|
||||
this.invalidCloseFrameLength = true;
|
||||
}
|
||||
if (this.length >= 2) {
|
||||
this.closeStatus = this.binaryPayload.readUInt16BE(0);
|
||||
this.binaryPayload = this.binaryPayload.slice(2);
|
||||
}
|
||||
}
|
||||
|
||||
this.parseState = COMPLETE;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
WebSocketFrame.prototype.throwAwayPayload = function(bufferList) {
|
||||
if (bufferList.length >= this.length) {
|
||||
bufferList.advance(this.length);
|
||||
this.parseState = COMPLETE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
WebSocketFrame.prototype.toBuffer = function(nullMask) {
|
||||
var maskKey;
|
||||
var headerLength = 2;
|
||||
var data;
|
||||
var outputPos;
|
||||
var firstByte = 0x00;
|
||||
var secondByte = 0x00;
|
||||
|
||||
if (this.fin) {
|
||||
firstByte |= 0x80;
|
||||
}
|
||||
if (this.rsv1) {
|
||||
firstByte |= 0x40;
|
||||
}
|
||||
if (this.rsv2) {
|
||||
firstByte |= 0x20;
|
||||
}
|
||||
if (this.rsv3) {
|
||||
firstByte |= 0x10;
|
||||
}
|
||||
if (this.mask) {
|
||||
secondByte |= 0x80;
|
||||
}
|
||||
|
||||
firstByte |= (this.opcode & 0x0F);
|
||||
|
||||
// the close frame is a special case because the close reason is
|
||||
// prepended to the payload data.
|
||||
if (this.opcode === 0x08) {
|
||||
this.length = 2;
|
||||
if (this.binaryPayload) {
|
||||
this.length += this.binaryPayload.length;
|
||||
}
|
||||
data = bufferAllocUnsafe(this.length);
|
||||
data.writeUInt16BE(this.closeStatus, 0);
|
||||
if (this.length > 2) {
|
||||
this.binaryPayload.copy(data, 2);
|
||||
}
|
||||
}
|
||||
else if (this.binaryPayload) {
|
||||
data = this.binaryPayload;
|
||||
this.length = data.length;
|
||||
}
|
||||
else {
|
||||
this.length = 0;
|
||||
}
|
||||
|
||||
if (this.length <= 125) {
|
||||
// encode the length directly into the two-byte frame header
|
||||
secondByte |= (this.length & 0x7F);
|
||||
}
|
||||
else if (this.length > 125 && this.length <= 0xFFFF) {
|
||||
// Use 16-bit length
|
||||
secondByte |= 126;
|
||||
headerLength += 2;
|
||||
}
|
||||
else if (this.length > 0xFFFF) {
|
||||
// Use 64-bit length
|
||||
secondByte |= 127;
|
||||
headerLength += 8;
|
||||
}
|
||||
|
||||
var output = bufferAllocUnsafe(this.length + headerLength + (this.mask ? 4 : 0));
|
||||
|
||||
// write the frame header
|
||||
output[0] = firstByte;
|
||||
output[1] = secondByte;
|
||||
|
||||
outputPos = 2;
|
||||
|
||||
if (this.length > 125 && this.length <= 0xFFFF) {
|
||||
// write 16-bit length
|
||||
output.writeUInt16BE(this.length, outputPos);
|
||||
outputPos += 2;
|
||||
}
|
||||
else if (this.length > 0xFFFF) {
|
||||
// write 64-bit length
|
||||
output.writeUInt32BE(0x00000000, outputPos);
|
||||
output.writeUInt32BE(this.length, outputPos + 4);
|
||||
outputPos += 8;
|
||||
}
|
||||
|
||||
if (this.mask) {
|
||||
maskKey = nullMask ? 0 : ((Math.random() * 0xFFFFFFFF) >>> 0);
|
||||
this.maskBytes.writeUInt32BE(maskKey, 0);
|
||||
|
||||
// write the mask key
|
||||
this.maskBytes.copy(output, outputPos);
|
||||
outputPos += 4;
|
||||
|
||||
if (data) {
|
||||
bufferUtil.mask(data, this.maskBytes, output, outputPos, this.length);
|
||||
}
|
||||
}
|
||||
else if (data) {
|
||||
data.copy(output, outputPos);
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
WebSocketFrame.prototype.toString = function() {
|
||||
return 'Opcode: ' + this.opcode + ', fin: ' + this.fin + ', length: ' + this.length + ', hasPayload: ' + Boolean(this.binaryPayload) + ', masked: ' + this.mask;
|
||||
};
|
||||
|
||||
|
||||
module.exports = WebSocketFrame;
|
524
node_modules/websocket/lib/WebSocketRequest.js
generated
vendored
Normal file
524
node_modules/websocket/lib/WebSocketRequest.js
generated
vendored
Normal file
@ -0,0 +1,524 @@
|
||||
/************************************************************************
|
||||
* Copyright 2010-2015 Brian McKelvey.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
***********************************************************************/
|
||||
|
||||
var crypto = require('crypto');
|
||||
var util = require('util');
|
||||
var url = require('url');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var WebSocketConnection = require('./WebSocketConnection');
|
||||
|
||||
var headerValueSplitRegExp = /,\s*/;
|
||||
var headerParamSplitRegExp = /;\s*/;
|
||||
var headerSanitizeRegExp = /[\r\n]/g;
|
||||
var xForwardedForSeparatorRegExp = /,\s*/;
|
||||
var separators = [
|
||||
'(', ')', '<', '>', '@',
|
||||
',', ';', ':', '\\', '\"',
|
||||
'/', '[', ']', '?', '=',
|
||||
'{', '}', ' ', String.fromCharCode(9)
|
||||
];
|
||||
var controlChars = [String.fromCharCode(127) /* DEL */];
|
||||
for (var i=0; i < 31; i ++) {
|
||||
/* US-ASCII Control Characters */
|
||||
controlChars.push(String.fromCharCode(i));
|
||||
}
|
||||
|
||||
var cookieNameValidateRegEx = /([\x00-\x20\x22\x28\x29\x2c\x2f\x3a-\x3f\x40\x5b-\x5e\x7b\x7d\x7f])/;
|
||||
var cookieValueValidateRegEx = /[^\x21\x23-\x2b\x2d-\x3a\x3c-\x5b\x5d-\x7e]/;
|
||||
var cookieValueDQuoteValidateRegEx = /^"[^"]*"$/;
|
||||
var controlCharsAndSemicolonRegEx = /[\x00-\x20\x3b]/g;
|
||||
|
||||
var cookieSeparatorRegEx = /[;,] */;
|
||||
|
||||
var httpStatusDescriptions = {
|
||||
100: 'Continue',
|
||||
101: 'Switching Protocols',
|
||||
200: 'OK',
|
||||
201: 'Created',
|
||||
203: 'Non-Authoritative Information',
|
||||
204: 'No Content',
|
||||
205: 'Reset Content',
|
||||
206: 'Partial Content',
|
||||
300: 'Multiple Choices',
|
||||
301: 'Moved Permanently',
|
||||
302: 'Found',
|
||||
303: 'See Other',
|
||||
304: 'Not Modified',
|
||||
305: 'Use Proxy',
|
||||
307: 'Temporary Redirect',
|
||||
400: 'Bad Request',
|
||||
401: 'Unauthorized',
|
||||
402: 'Payment Required',
|
||||
403: 'Forbidden',
|
||||
404: 'Not Found',
|
||||
406: 'Not Acceptable',
|
||||
407: 'Proxy Authorization Required',
|
||||
408: 'Request Timeout',
|
||||
409: 'Conflict',
|
||||
410: 'Gone',
|
||||
411: 'Length Required',
|
||||
412: 'Precondition Failed',
|
||||
413: 'Request Entity Too Long',
|
||||
414: 'Request-URI Too Long',
|
||||
415: 'Unsupported Media Type',
|
||||
416: 'Requested Range Not Satisfiable',
|
||||
417: 'Expectation Failed',
|
||||
426: 'Upgrade Required',
|
||||
500: 'Internal Server Error',
|
||||
501: 'Not Implemented',
|
||||
502: 'Bad Gateway',
|
||||
503: 'Service Unavailable',
|
||||
504: 'Gateway Timeout',
|
||||
505: 'HTTP Version Not Supported'
|
||||
};
|
||||
|
||||
function WebSocketRequest(socket, httpRequest, serverConfig) {
|
||||
// Superclass Constructor
|
||||
EventEmitter.call(this);
|
||||
|
||||
this.socket = socket;
|
||||
this.httpRequest = httpRequest;
|
||||
this.resource = httpRequest.url;
|
||||
this.remoteAddress = socket.remoteAddress;
|
||||
this.remoteAddresses = [this.remoteAddress];
|
||||
this.serverConfig = serverConfig;
|
||||
|
||||
// Watch for the underlying TCP socket closing before we call accept
|
||||
this._socketIsClosing = false;
|
||||
this._socketCloseHandler = this._handleSocketCloseBeforeAccept.bind(this);
|
||||
this.socket.on('end', this._socketCloseHandler);
|
||||
this.socket.on('close', this._socketCloseHandler);
|
||||
|
||||
this._resolved = false;
|
||||
}
|
||||
|
||||
util.inherits(WebSocketRequest, EventEmitter);
|
||||
|
||||
WebSocketRequest.prototype.readHandshake = function() {
|
||||
var self = this;
|
||||
var request = this.httpRequest;
|
||||
|
||||
// Decode URL
|
||||
this.resourceURL = url.parse(this.resource, true);
|
||||
|
||||
this.host = request.headers['host'];
|
||||
if (!this.host) {
|
||||
throw new Error('Client must provide a Host header.');
|
||||
}
|
||||
|
||||
this.key = request.headers['sec-websocket-key'];
|
||||
if (!this.key) {
|
||||
throw new Error('Client must provide a value for Sec-WebSocket-Key.');
|
||||
}
|
||||
|
||||
this.webSocketVersion = parseInt(request.headers['sec-websocket-version'], 10);
|
||||
|
||||
if (!this.webSocketVersion || isNaN(this.webSocketVersion)) {
|
||||
throw new Error('Client must provide a value for Sec-WebSocket-Version.');
|
||||
}
|
||||
|
||||
switch (this.webSocketVersion) {
|
||||
case 8:
|
||||
case 13:
|
||||
break;
|
||||
default:
|
||||
var e = new Error('Unsupported websocket client version: ' + this.webSocketVersion +
|
||||
'Only versions 8 and 13 are supported.');
|
||||
e.httpCode = 426;
|
||||
e.headers = {
|
||||
'Sec-WebSocket-Version': '13'
|
||||
};
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (this.webSocketVersion === 13) {
|
||||
this.origin = request.headers['origin'];
|
||||
}
|
||||
else if (this.webSocketVersion === 8) {
|
||||
this.origin = request.headers['sec-websocket-origin'];
|
||||
}
|
||||
|
||||
// Protocol is optional.
|
||||
var protocolString = request.headers['sec-websocket-protocol'];
|
||||
this.protocolFullCaseMap = {};
|
||||
this.requestedProtocols = [];
|
||||
if (protocolString) {
|
||||
var requestedProtocolsFullCase = protocolString.split(headerValueSplitRegExp);
|
||||
requestedProtocolsFullCase.forEach(function(protocol) {
|
||||
var lcProtocol = protocol.toLocaleLowerCase();
|
||||
self.requestedProtocols.push(lcProtocol);
|
||||
self.protocolFullCaseMap[lcProtocol] = protocol;
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.serverConfig.ignoreXForwardedFor &&
|
||||
request.headers['x-forwarded-for']) {
|
||||
var immediatePeerIP = this.remoteAddress;
|
||||
this.remoteAddresses = request.headers['x-forwarded-for']
|
||||
.split(xForwardedForSeparatorRegExp);
|
||||
this.remoteAddresses.push(immediatePeerIP);
|
||||
this.remoteAddress = this.remoteAddresses[0];
|
||||
}
|
||||
|
||||
// Extensions are optional.
|
||||
var extensionsString = request.headers['sec-websocket-extensions'];
|
||||
this.requestedExtensions = this.parseExtensions(extensionsString);
|
||||
|
||||
// Cookies are optional
|
||||
var cookieString = request.headers['cookie'];
|
||||
this.cookies = this.parseCookies(cookieString);
|
||||
};
|
||||
|
||||
WebSocketRequest.prototype.parseExtensions = function(extensionsString) {
|
||||
if (!extensionsString || extensionsString.length === 0) {
|
||||
return [];
|
||||
}
|
||||
var extensions = extensionsString.toLocaleLowerCase().split(headerValueSplitRegExp);
|
||||
extensions.forEach(function(extension, index, array) {
|
||||
var params = extension.split(headerParamSplitRegExp);
|
||||
var extensionName = params[0];
|
||||
var extensionParams = params.slice(1);
|
||||
extensionParams.forEach(function(rawParam, index, array) {
|
||||
var arr = rawParam.split('=');
|
||||
var obj = {
|
||||
name: arr[0],
|
||||
value: arr[1]
|
||||
};
|
||||
array.splice(index, 1, obj);
|
||||
});
|
||||
var obj = {
|
||||
name: extensionName,
|
||||
params: extensionParams
|
||||
};
|
||||
array.splice(index, 1, obj);
|
||||
});
|
||||
return extensions;
|
||||
};
|
||||
|
||||
// This function adapted from node-cookie
|
||||
// https://github.com/shtylman/node-cookie
|
||||
WebSocketRequest.prototype.parseCookies = function(str) {
|
||||
// Sanity Check
|
||||
if (!str || typeof(str) !== 'string') {
|
||||
return [];
|
||||
}
|
||||
|
||||
var cookies = [];
|
||||
var pairs = str.split(cookieSeparatorRegEx);
|
||||
|
||||
pairs.forEach(function(pair) {
|
||||
var eq_idx = pair.indexOf('=');
|
||||
if (eq_idx === -1) {
|
||||
cookies.push({
|
||||
name: pair,
|
||||
value: null
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var key = pair.substr(0, eq_idx).trim();
|
||||
var val = pair.substr(++eq_idx, pair.length).trim();
|
||||
|
||||
// quoted values
|
||||
if ('"' === val[0]) {
|
||||
val = val.slice(1, -1);
|
||||
}
|
||||
|
||||
cookies.push({
|
||||
name: key,
|
||||
value: decodeURIComponent(val)
|
||||
});
|
||||
});
|
||||
|
||||
return cookies;
|
||||
};
|
||||
|
||||
WebSocketRequest.prototype.accept = function(acceptedProtocol, allowedOrigin, cookies) {
|
||||
this._verifyResolution();
|
||||
|
||||
// TODO: Handle extensions
|
||||
|
||||
var protocolFullCase;
|
||||
|
||||
if (acceptedProtocol) {
|
||||
protocolFullCase = this.protocolFullCaseMap[acceptedProtocol.toLocaleLowerCase()];
|
||||
if (typeof(protocolFullCase) === 'undefined') {
|
||||
protocolFullCase = acceptedProtocol;
|
||||
}
|
||||
}
|
||||
else {
|
||||
protocolFullCase = acceptedProtocol;
|
||||
}
|
||||
this.protocolFullCaseMap = null;
|
||||
|
||||
// Create key validation hash
|
||||
var sha1 = crypto.createHash('sha1');
|
||||
sha1.update(this.key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11');
|
||||
var acceptKey = sha1.digest('base64');
|
||||
|
||||
var response = 'HTTP/1.1 101 Switching Protocols\r\n' +
|
||||
'Upgrade: websocket\r\n' +
|
||||
'Connection: Upgrade\r\n' +
|
||||
'Sec-WebSocket-Accept: ' + acceptKey + '\r\n';
|
||||
|
||||
if (protocolFullCase) {
|
||||
// validate protocol
|
||||
for (var i=0; i < protocolFullCase.length; i++) {
|
||||
var charCode = protocolFullCase.charCodeAt(i);
|
||||
var character = protocolFullCase.charAt(i);
|
||||
if (charCode < 0x21 || charCode > 0x7E || separators.indexOf(character) !== -1) {
|
||||
this.reject(500);
|
||||
throw new Error('Illegal character "' + String.fromCharCode(character) + '" in subprotocol.');
|
||||
}
|
||||
}
|
||||
if (this.requestedProtocols.indexOf(acceptedProtocol) === -1) {
|
||||
this.reject(500);
|
||||
throw new Error('Specified protocol was not requested by the client.');
|
||||
}
|
||||
|
||||
protocolFullCase = protocolFullCase.replace(headerSanitizeRegExp, '');
|
||||
response += 'Sec-WebSocket-Protocol: ' + protocolFullCase + '\r\n';
|
||||
}
|
||||
this.requestedProtocols = null;
|
||||
|
||||
if (allowedOrigin) {
|
||||
allowedOrigin = allowedOrigin.replace(headerSanitizeRegExp, '');
|
||||
if (this.webSocketVersion === 13) {
|
||||
response += 'Origin: ' + allowedOrigin + '\r\n';
|
||||
}
|
||||
else if (this.webSocketVersion === 8) {
|
||||
response += 'Sec-WebSocket-Origin: ' + allowedOrigin + '\r\n';
|
||||
}
|
||||
}
|
||||
|
||||
if (cookies) {
|
||||
if (!Array.isArray(cookies)) {
|
||||
this.reject(500);
|
||||
throw new Error('Value supplied for "cookies" argument must be an array.');
|
||||
}
|
||||
var seenCookies = {};
|
||||
cookies.forEach(function(cookie) {
|
||||
if (!cookie.name || !cookie.value) {
|
||||
this.reject(500);
|
||||
throw new Error('Each cookie to set must at least provide a "name" and "value"');
|
||||
}
|
||||
|
||||
// Make sure there are no \r\n sequences inserted
|
||||
cookie.name = cookie.name.replace(controlCharsAndSemicolonRegEx, '');
|
||||
cookie.value = cookie.value.replace(controlCharsAndSemicolonRegEx, '');
|
||||
|
||||
if (seenCookies[cookie.name]) {
|
||||
this.reject(500);
|
||||
throw new Error('You may not specify the same cookie name twice.');
|
||||
}
|
||||
seenCookies[cookie.name] = true;
|
||||
|
||||
// token (RFC 2616, Section 2.2)
|
||||
var invalidChar = cookie.name.match(cookieNameValidateRegEx);
|
||||
if (invalidChar) {
|
||||
this.reject(500);
|
||||
throw new Error('Illegal character ' + invalidChar[0] + ' in cookie name');
|
||||
}
|
||||
|
||||
// RFC 6265, Section 4.1.1
|
||||
// *cookie-octet / ( DQUOTE *cookie-octet DQUOTE ) | %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
|
||||
if (cookie.value.match(cookieValueDQuoteValidateRegEx)) {
|
||||
invalidChar = cookie.value.slice(1, -1).match(cookieValueValidateRegEx);
|
||||
} else {
|
||||
invalidChar = cookie.value.match(cookieValueValidateRegEx);
|
||||
}
|
||||
if (invalidChar) {
|
||||
this.reject(500);
|
||||
throw new Error('Illegal character ' + invalidChar[0] + ' in cookie value');
|
||||
}
|
||||
|
||||
var cookieParts = [cookie.name + '=' + cookie.value];
|
||||
|
||||
// RFC 6265, Section 4.1.1
|
||||
// 'Path=' path-value | <any CHAR except CTLs or ';'>
|
||||
if(cookie.path){
|
||||
invalidChar = cookie.path.match(controlCharsAndSemicolonRegEx);
|
||||
if (invalidChar) {
|
||||
this.reject(500);
|
||||
throw new Error('Illegal character ' + invalidChar[0] + ' in cookie path');
|
||||
}
|
||||
cookieParts.push('Path=' + cookie.path);
|
||||
}
|
||||
|
||||
// RFC 6265, Section 4.1.2.3
|
||||
// 'Domain=' subdomain
|
||||
if (cookie.domain) {
|
||||
if (typeof(cookie.domain) !== 'string') {
|
||||
this.reject(500);
|
||||
throw new Error('Domain must be specified and must be a string.');
|
||||
}
|
||||
invalidChar = cookie.domain.match(controlCharsAndSemicolonRegEx);
|
||||
if (invalidChar) {
|
||||
this.reject(500);
|
||||
throw new Error('Illegal character ' + invalidChar[0] + ' in cookie domain');
|
||||
}
|
||||
cookieParts.push('Domain=' + cookie.domain.toLowerCase());
|
||||
}
|
||||
|
||||
// RFC 6265, Section 4.1.1
|
||||
//'Expires=' sane-cookie-date | Force Date object requirement by using only epoch
|
||||
if (cookie.expires) {
|
||||
if (!(cookie.expires instanceof Date)){
|
||||
this.reject(500);
|
||||
throw new Error('Value supplied for cookie "expires" must be a vaild date object');
|
||||
}
|
||||
cookieParts.push('Expires=' + cookie.expires.toGMTString());
|
||||
}
|
||||
|
||||
// RFC 6265, Section 4.1.1
|
||||
//'Max-Age=' non-zero-digit *DIGIT
|
||||
if (cookie.maxage) {
|
||||
var maxage = cookie.maxage;
|
||||
if (typeof(maxage) === 'string') {
|
||||
maxage = parseInt(maxage, 10);
|
||||
}
|
||||
if (isNaN(maxage) || maxage <= 0 ) {
|
||||
this.reject(500);
|
||||
throw new Error('Value supplied for cookie "maxage" must be a non-zero number');
|
||||
}
|
||||
maxage = Math.round(maxage);
|
||||
cookieParts.push('Max-Age=' + maxage.toString(10));
|
||||
}
|
||||
|
||||
// RFC 6265, Section 4.1.1
|
||||
//'Secure;'
|
||||
if (cookie.secure) {
|
||||
if (typeof(cookie.secure) !== 'boolean') {
|
||||
this.reject(500);
|
||||
throw new Error('Value supplied for cookie "secure" must be of type boolean');
|
||||
}
|
||||
cookieParts.push('Secure');
|
||||
}
|
||||
|
||||
// RFC 6265, Section 4.1.1
|
||||
//'HttpOnly;'
|
||||
if (cookie.httponly) {
|
||||
if (typeof(cookie.httponly) !== 'boolean') {
|
||||
this.reject(500);
|
||||
throw new Error('Value supplied for cookie "httponly" must be of type boolean');
|
||||
}
|
||||
cookieParts.push('HttpOnly');
|
||||
}
|
||||
|
||||
response += ('Set-Cookie: ' + cookieParts.join(';') + '\r\n');
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
// TODO: handle negotiated extensions
|
||||
// if (negotiatedExtensions) {
|
||||
// response += 'Sec-WebSocket-Extensions: ' + negotiatedExtensions.join(', ') + '\r\n';
|
||||
// }
|
||||
|
||||
// Mark the request resolved now so that the user can't call accept or
|
||||
// reject a second time.
|
||||
this._resolved = true;
|
||||
this.emit('requestResolved', this);
|
||||
|
||||
response += '\r\n';
|
||||
|
||||
var connection = new WebSocketConnection(this.socket, [], acceptedProtocol, false, this.serverConfig);
|
||||
connection.webSocketVersion = this.webSocketVersion;
|
||||
connection.remoteAddress = this.remoteAddress;
|
||||
connection.remoteAddresses = this.remoteAddresses;
|
||||
|
||||
var self = this;
|
||||
|
||||
if (this._socketIsClosing) {
|
||||
// Handle case when the client hangs up before we get a chance to
|
||||
// accept the connection and send our side of the opening handshake.
|
||||
cleanupFailedConnection(connection);
|
||||
}
|
||||
else {
|
||||
this.socket.write(response, 'ascii', function(error) {
|
||||
if (error) {
|
||||
cleanupFailedConnection(connection);
|
||||
return;
|
||||
}
|
||||
|
||||
self._removeSocketCloseListeners();
|
||||
connection._addSocketEventListeners();
|
||||
});
|
||||
}
|
||||
|
||||
this.emit('requestAccepted', connection);
|
||||
return connection;
|
||||
};
|
||||
|
||||
WebSocketRequest.prototype.reject = function(status, reason, extraHeaders) {
|
||||
this._verifyResolution();
|
||||
|
||||
// Mark the request resolved now so that the user can't call accept or
|
||||
// reject a second time.
|
||||
this._resolved = true;
|
||||
this.emit('requestResolved', this);
|
||||
|
||||
if (typeof(status) !== 'number') {
|
||||
status = 403;
|
||||
}
|
||||
var response = 'HTTP/1.1 ' + status + ' ' + httpStatusDescriptions[status] + '\r\n' +
|
||||
'Connection: close\r\n';
|
||||
if (reason) {
|
||||
reason = reason.replace(headerSanitizeRegExp, '');
|
||||
response += 'X-WebSocket-Reject-Reason: ' + reason + '\r\n';
|
||||
}
|
||||
|
||||
if (extraHeaders) {
|
||||
for (var key in extraHeaders) {
|
||||
var sanitizedValue = extraHeaders[key].toString().replace(headerSanitizeRegExp, '');
|
||||
var sanitizedKey = key.replace(headerSanitizeRegExp, '');
|
||||
response += (sanitizedKey + ': ' + sanitizedValue + '\r\n');
|
||||
}
|
||||
}
|
||||
|
||||
response += '\r\n';
|
||||
this.socket.end(response, 'ascii');
|
||||
|
||||
this.emit('requestRejected', this);
|
||||
};
|
||||
|
||||
WebSocketRequest.prototype._handleSocketCloseBeforeAccept = function() {
|
||||
this._socketIsClosing = true;
|
||||
this._removeSocketCloseListeners();
|
||||
};
|
||||
|
||||
WebSocketRequest.prototype._removeSocketCloseListeners = function() {
|
||||
this.socket.removeListener('end', this._socketCloseHandler);
|
||||
this.socket.removeListener('close', this._socketCloseHandler);
|
||||
};
|
||||
|
||||
WebSocketRequest.prototype._verifyResolution = function() {
|
||||
if (this._resolved) {
|
||||
throw new Error('WebSocketRequest may only be accepted or rejected one time.');
|
||||
}
|
||||
};
|
||||
|
||||
function cleanupFailedConnection(connection) {
|
||||
// Since we have to return a connection object even if the socket is
|
||||
// already dead in order not to break the API, we schedule a 'close'
|
||||
// event on the connection object to occur immediately.
|
||||
process.nextTick(function() {
|
||||
// WebSocketConnection.CLOSE_REASON_ABNORMAL = 1006
|
||||
// Third param: Skip sending the close frame to a dead socket
|
||||
connection.drop(1006, 'TCP connection lost before handshake completed.', true);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = WebSocketRequest;
|
157
node_modules/websocket/lib/WebSocketRouter.js
generated
vendored
Normal file
157
node_modules/websocket/lib/WebSocketRouter.js
generated
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
/************************************************************************
|
||||
* Copyright 2010-2015 Brian McKelvey.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
***********************************************************************/
|
||||
|
||||
var extend = require('./utils').extend;
|
||||
var util = require('util');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var WebSocketRouterRequest = require('./WebSocketRouterRequest');
|
||||
|
||||
function WebSocketRouter(config) {
|
||||
// Superclass Constructor
|
||||
EventEmitter.call(this);
|
||||
|
||||
this.config = {
|
||||
// The WebSocketServer instance to attach to.
|
||||
server: null
|
||||
};
|
||||
if (config) {
|
||||
extend(this.config, config);
|
||||
}
|
||||
this.handlers = [];
|
||||
|
||||
this._requestHandler = this.handleRequest.bind(this);
|
||||
if (this.config.server) {
|
||||
this.attachServer(this.config.server);
|
||||
}
|
||||
}
|
||||
|
||||
util.inherits(WebSocketRouter, EventEmitter);
|
||||
|
||||
WebSocketRouter.prototype.attachServer = function(server) {
|
||||
if (server) {
|
||||
this.server = server;
|
||||
this.server.on('request', this._requestHandler);
|
||||
}
|
||||
else {
|
||||
throw new Error('You must specify a WebSocketServer instance to attach to.');
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketRouter.prototype.detachServer = function() {
|
||||
if (this.server) {
|
||||
this.server.removeListener('request', this._requestHandler);
|
||||
this.server = null;
|
||||
}
|
||||
else {
|
||||
throw new Error('Cannot detach from server: not attached.');
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketRouter.prototype.mount = function(path, protocol, callback) {
|
||||
if (!path) {
|
||||
throw new Error('You must specify a path for this handler.');
|
||||
}
|
||||
if (!protocol) {
|
||||
protocol = '____no_protocol____';
|
||||
}
|
||||
if (!callback) {
|
||||
throw new Error('You must specify a callback for this handler.');
|
||||
}
|
||||
|
||||
path = this.pathToRegExp(path);
|
||||
if (!(path instanceof RegExp)) {
|
||||
throw new Error('Path must be specified as either a string or a RegExp.');
|
||||
}
|
||||
var pathString = path.toString();
|
||||
|
||||
// normalize protocol to lower-case
|
||||
protocol = protocol.toLocaleLowerCase();
|
||||
|
||||
if (this.findHandlerIndex(pathString, protocol) !== -1) {
|
||||
throw new Error('You may only mount one handler per path/protocol combination.');
|
||||
}
|
||||
|
||||
this.handlers.push({
|
||||
'path': path,
|
||||
'pathString': pathString,
|
||||
'protocol': protocol,
|
||||
'callback': callback
|
||||
});
|
||||
};
|
||||
WebSocketRouter.prototype.unmount = function(path, protocol) {
|
||||
var index = this.findHandlerIndex(this.pathToRegExp(path).toString(), protocol);
|
||||
if (index !== -1) {
|
||||
this.handlers.splice(index, 1);
|
||||
}
|
||||
else {
|
||||
throw new Error('Unable to find a route matching the specified path and protocol.');
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketRouter.prototype.findHandlerIndex = function(pathString, protocol) {
|
||||
protocol = protocol.toLocaleLowerCase();
|
||||
for (var i=0, len=this.handlers.length; i < len; i++) {
|
||||
var handler = this.handlers[i];
|
||||
if (handler.pathString === pathString && handler.protocol === protocol) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
WebSocketRouter.prototype.pathToRegExp = function(path) {
|
||||
if (typeof(path) === 'string') {
|
||||
if (path === '*') {
|
||||
path = /^.*$/;
|
||||
}
|
||||
else {
|
||||
path = path.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||||
path = new RegExp('^' + path + '$');
|
||||
}
|
||||
}
|
||||
return path;
|
||||
};
|
||||
|
||||
WebSocketRouter.prototype.handleRequest = function(request) {
|
||||
var requestedProtocols = request.requestedProtocols;
|
||||
if (requestedProtocols.length === 0) {
|
||||
requestedProtocols = ['____no_protocol____'];
|
||||
}
|
||||
|
||||
// Find a handler with the first requested protocol first
|
||||
for (var i=0; i < requestedProtocols.length; i++) {
|
||||
var requestedProtocol = requestedProtocols[i].toLocaleLowerCase();
|
||||
|
||||
// find the first handler that can process this request
|
||||
for (var j=0, len=this.handlers.length; j < len; j++) {
|
||||
var handler = this.handlers[j];
|
||||
if (handler.path.test(request.resourceURL.pathname)) {
|
||||
if (requestedProtocol === handler.protocol ||
|
||||
handler.protocol === '*')
|
||||
{
|
||||
var routerRequest = new WebSocketRouterRequest(request, requestedProtocol);
|
||||
handler.callback(routerRequest);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here we were unable to find a suitable handler.
|
||||
request.reject(404, 'No handler is available for the given request.');
|
||||
};
|
||||
|
||||
module.exports = WebSocketRouter;
|
54
node_modules/websocket/lib/WebSocketRouterRequest.js
generated
vendored
Normal file
54
node_modules/websocket/lib/WebSocketRouterRequest.js
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
/************************************************************************
|
||||
* Copyright 2010-2015 Brian McKelvey.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
***********************************************************************/
|
||||
|
||||
var util = require('util');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
|
||||
function WebSocketRouterRequest(webSocketRequest, resolvedProtocol) {
|
||||
// Superclass Constructor
|
||||
EventEmitter.call(this);
|
||||
|
||||
this.webSocketRequest = webSocketRequest;
|
||||
if (resolvedProtocol === '____no_protocol____') {
|
||||
this.protocol = null;
|
||||
}
|
||||
else {
|
||||
this.protocol = resolvedProtocol;
|
||||
}
|
||||
this.origin = webSocketRequest.origin;
|
||||
this.resource = webSocketRequest.resource;
|
||||
this.resourceURL = webSocketRequest.resourceURL;
|
||||
this.httpRequest = webSocketRequest.httpRequest;
|
||||
this.remoteAddress = webSocketRequest.remoteAddress;
|
||||
this.webSocketVersion = webSocketRequest.webSocketVersion;
|
||||
this.requestedExtensions = webSocketRequest.requestedExtensions;
|
||||
this.cookies = webSocketRequest.cookies;
|
||||
}
|
||||
|
||||
util.inherits(WebSocketRouterRequest, EventEmitter);
|
||||
|
||||
WebSocketRouterRequest.prototype.accept = function(origin, cookies) {
|
||||
var connection = this.webSocketRequest.accept(this.protocol, origin, cookies);
|
||||
this.emit('requestAccepted', connection);
|
||||
return connection;
|
||||
};
|
||||
|
||||
WebSocketRouterRequest.prototype.reject = function(status, reason, extraHeaders) {
|
||||
this.webSocketRequest.reject(status, reason, extraHeaders);
|
||||
this.emit('requestRejected', this);
|
||||
};
|
||||
|
||||
module.exports = WebSocketRouterRequest;
|
245
node_modules/websocket/lib/WebSocketServer.js
generated
vendored
Normal file
245
node_modules/websocket/lib/WebSocketServer.js
generated
vendored
Normal file
@ -0,0 +1,245 @@
|
||||
/************************************************************************
|
||||
* Copyright 2010-2015 Brian McKelvey.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
***********************************************************************/
|
||||
|
||||
var extend = require('./utils').extend;
|
||||
var utils = require('./utils');
|
||||
var util = require('util');
|
||||
var debug = require('debug')('websocket:server');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var WebSocketRequest = require('./WebSocketRequest');
|
||||
|
||||
var WebSocketServer = function WebSocketServer(config) {
|
||||
// Superclass Constructor
|
||||
EventEmitter.call(this);
|
||||
|
||||
this._handlers = {
|
||||
upgrade: this.handleUpgrade.bind(this),
|
||||
requestAccepted: this.handleRequestAccepted.bind(this),
|
||||
requestResolved: this.handleRequestResolved.bind(this)
|
||||
};
|
||||
this.connections = [];
|
||||
this.pendingRequests = [];
|
||||
if (config) {
|
||||
this.mount(config);
|
||||
}
|
||||
};
|
||||
|
||||
util.inherits(WebSocketServer, EventEmitter);
|
||||
|
||||
WebSocketServer.prototype.mount = function(config) {
|
||||
this.config = {
|
||||
// The http server instance to attach to. Required.
|
||||
httpServer: null,
|
||||
|
||||
// 64KiB max frame size.
|
||||
maxReceivedFrameSize: 0x10000,
|
||||
|
||||
// 1MiB max message size, only applicable if
|
||||
// assembleFragments is true
|
||||
maxReceivedMessageSize: 0x100000,
|
||||
|
||||
// Outgoing messages larger than fragmentationThreshold will be
|
||||
// split into multiple fragments.
|
||||
fragmentOutgoingMessages: true,
|
||||
|
||||
// Outgoing frames are fragmented if they exceed this threshold.
|
||||
// Default is 16KiB
|
||||
fragmentationThreshold: 0x4000,
|
||||
|
||||
// If true, the server will automatically send a ping to all
|
||||
// clients every 'keepaliveInterval' milliseconds. The timer is
|
||||
// reset on any received data from the client.
|
||||
keepalive: true,
|
||||
|
||||
// The interval to send keepalive pings to connected clients if the
|
||||
// connection is idle. Any received data will reset the counter.
|
||||
keepaliveInterval: 20000,
|
||||
|
||||
// If true, the server will consider any connection that has not
|
||||
// received any data within the amount of time specified by
|
||||
// 'keepaliveGracePeriod' after a keepalive ping has been sent to
|
||||
// be dead, and will drop the connection.
|
||||
// Ignored if keepalive is false.
|
||||
dropConnectionOnKeepaliveTimeout: true,
|
||||
|
||||
// The amount of time to wait after sending a keepalive ping before
|
||||
// closing the connection if the connected peer does not respond.
|
||||
// Ignored if keepalive is false.
|
||||
keepaliveGracePeriod: 10000,
|
||||
|
||||
// Whether to use native TCP keep-alive instead of WebSockets ping
|
||||
// and pong packets. Native TCP keep-alive sends smaller packets
|
||||
// on the wire and so uses bandwidth more efficiently. This may
|
||||
// be more important when talking to mobile devices.
|
||||
// If this value is set to true, then these values will be ignored:
|
||||
// keepaliveGracePeriod
|
||||
// dropConnectionOnKeepaliveTimeout
|
||||
useNativeKeepalive: false,
|
||||
|
||||
// If true, fragmented messages will be automatically assembled
|
||||
// and the full message will be emitted via a 'message' event.
|
||||
// If false, each frame will be emitted via a 'frame' event and
|
||||
// the application will be responsible for aggregating multiple
|
||||
// fragmented frames. Single-frame messages will emit a 'message'
|
||||
// event in addition to the 'frame' event.
|
||||
// Most users will want to leave this set to 'true'
|
||||
assembleFragments: true,
|
||||
|
||||
// If this is true, websocket connections will be accepted
|
||||
// regardless of the path and protocol specified by the client.
|
||||
// The protocol accepted will be the first that was requested
|
||||
// by the client. Clients from any origin will be accepted.
|
||||
// This should only be used in the simplest of cases. You should
|
||||
// probably leave this set to 'false' and inspect the request
|
||||
// object to make sure it's acceptable before accepting it.
|
||||
autoAcceptConnections: false,
|
||||
|
||||
// Whether or not the X-Forwarded-For header should be respected.
|
||||
// It's important to set this to 'true' when accepting connections
|
||||
// from untrusted clients, as a malicious client could spoof its
|
||||
// IP address by simply setting this header. It's meant to be added
|
||||
// by a trusted proxy or other intermediary within your own
|
||||
// infrastructure.
|
||||
// See: http://en.wikipedia.org/wiki/X-Forwarded-For
|
||||
ignoreXForwardedFor: false,
|
||||
|
||||
// The Nagle Algorithm makes more efficient use of network resources
|
||||
// by introducing a small delay before sending small packets so that
|
||||
// multiple messages can be batched together before going onto the
|
||||
// wire. This however comes at the cost of latency, so the default
|
||||
// is to disable it. If you don't need low latency and are streaming
|
||||
// lots of small messages, you can change this to 'false'
|
||||
disableNagleAlgorithm: true,
|
||||
|
||||
// The number of milliseconds to wait after sending a close frame
|
||||
// for an acknowledgement to come back before giving up and just
|
||||
// closing the socket.
|
||||
closeTimeout: 5000
|
||||
};
|
||||
extend(this.config, config);
|
||||
|
||||
if (this.config.httpServer) {
|
||||
if (!Array.isArray(this.config.httpServer)) {
|
||||
this.config.httpServer = [this.config.httpServer];
|
||||
}
|
||||
var upgradeHandler = this._handlers.upgrade;
|
||||
this.config.httpServer.forEach(function(httpServer) {
|
||||
httpServer.on('upgrade', upgradeHandler);
|
||||
});
|
||||
}
|
||||
else {
|
||||
throw new Error('You must specify an httpServer on which to mount the WebSocket server.');
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketServer.prototype.unmount = function() {
|
||||
var upgradeHandler = this._handlers.upgrade;
|
||||
this.config.httpServer.forEach(function(httpServer) {
|
||||
httpServer.removeListener('upgrade', upgradeHandler);
|
||||
});
|
||||
};
|
||||
|
||||
WebSocketServer.prototype.closeAllConnections = function() {
|
||||
this.connections.forEach(function(connection) {
|
||||
connection.close();
|
||||
});
|
||||
this.pendingRequests.forEach(function(request) {
|
||||
process.nextTick(function() {
|
||||
request.reject(503); // HTTP 503 Service Unavailable
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
WebSocketServer.prototype.broadcast = function(data) {
|
||||
if (Buffer.isBuffer(data)) {
|
||||
this.broadcastBytes(data);
|
||||
}
|
||||
else if (typeof(data.toString) === 'function') {
|
||||
this.broadcastUTF(data);
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketServer.prototype.broadcastUTF = function(utfData) {
|
||||
this.connections.forEach(function(connection) {
|
||||
connection.sendUTF(utfData);
|
||||
});
|
||||
};
|
||||
|
||||
WebSocketServer.prototype.broadcastBytes = function(binaryData) {
|
||||
this.connections.forEach(function(connection) {
|
||||
connection.sendBytes(binaryData);
|
||||
});
|
||||
};
|
||||
|
||||
WebSocketServer.prototype.shutDown = function() {
|
||||
this.unmount();
|
||||
this.closeAllConnections();
|
||||
};
|
||||
|
||||
WebSocketServer.prototype.handleUpgrade = function(request, socket) {
|
||||
var wsRequest = new WebSocketRequest(socket, request, this.config);
|
||||
try {
|
||||
wsRequest.readHandshake();
|
||||
}
|
||||
catch(e) {
|
||||
wsRequest.reject(
|
||||
e.httpCode ? e.httpCode : 400,
|
||||
e.message,
|
||||
e.headers
|
||||
);
|
||||
debug('Invalid handshake: %s', e.message);
|
||||
return;
|
||||
}
|
||||
|
||||
this.pendingRequests.push(wsRequest);
|
||||
|
||||
wsRequest.once('requestAccepted', this._handlers.requestAccepted);
|
||||
wsRequest.once('requestResolved', this._handlers.requestResolved);
|
||||
|
||||
if (!this.config.autoAcceptConnections && utils.eventEmitterListenerCount(this, 'request') > 0) {
|
||||
this.emit('request', wsRequest);
|
||||
}
|
||||
else if (this.config.autoAcceptConnections) {
|
||||
wsRequest.accept(wsRequest.requestedProtocols[0], wsRequest.origin);
|
||||
}
|
||||
else {
|
||||
wsRequest.reject(404, 'No handler is configured to accept the connection.');
|
||||
}
|
||||
};
|
||||
|
||||
WebSocketServer.prototype.handleRequestAccepted = function(connection) {
|
||||
var self = this;
|
||||
connection.once('close', function(closeReason, description) {
|
||||
self.handleConnectionClose(connection, closeReason, description);
|
||||
});
|
||||
this.connections.push(connection);
|
||||
this.emit('connect', connection);
|
||||
};
|
||||
|
||||
WebSocketServer.prototype.handleConnectionClose = function(connection, closeReason, description) {
|
||||
var index = this.connections.indexOf(connection);
|
||||
if (index !== -1) {
|
||||
this.connections.splice(index, 1);
|
||||
}
|
||||
this.emit('close', connection, closeReason, description);
|
||||
};
|
||||
|
||||
WebSocketServer.prototype.handleRequestResolved = function(request) {
|
||||
var index = this.pendingRequests.indexOf(request);
|
||||
if (index !== -1) { this.pendingRequests.splice(index, 1); }
|
||||
};
|
||||
|
||||
module.exports = WebSocketServer;
|
42
node_modules/websocket/lib/browser.js
generated
vendored
Normal file
42
node_modules/websocket/lib/browser.js
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
var _global = (function() { return this; })();
|
||||
var NativeWebSocket = _global.WebSocket || _global.MozWebSocket;
|
||||
var websocket_version = require('./version');
|
||||
|
||||
|
||||
/**
|
||||
* Expose a W3C WebSocket class with just one or two arguments.
|
||||
*/
|
||||
function W3CWebSocket(uri, protocols) {
|
||||
var native_instance;
|
||||
|
||||
if (protocols) {
|
||||
native_instance = new NativeWebSocket(uri, protocols);
|
||||
}
|
||||
else {
|
||||
native_instance = new NativeWebSocket(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* 'native_instance' is an instance of nativeWebSocket (the browser's WebSocket
|
||||
* class). Since it is an Object it will be returned as it is when creating an
|
||||
* instance of W3CWebSocket via 'new W3CWebSocket()'.
|
||||
*
|
||||
* ECMAScript 5: http://bclary.com/2004/11/07/#a-13.2.2
|
||||
*/
|
||||
return native_instance;
|
||||
}
|
||||
if (NativeWebSocket) {
|
||||
['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'].forEach(function(prop) {
|
||||
Object.defineProperty(W3CWebSocket, prop, {
|
||||
get: function() { return NativeWebSocket[prop]; }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
*/
|
||||
module.exports = {
|
||||
'w3cwebsocket' : NativeWebSocket ? W3CWebSocket : null,
|
||||
'version' : websocket_version
|
||||
};
|
66
node_modules/websocket/lib/utils.js
generated
vendored
Normal file
66
node_modules/websocket/lib/utils.js
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
var noop = exports.noop = function(){};
|
||||
|
||||
exports.extend = function extend(dest, source) {
|
||||
for (var prop in source) {
|
||||
dest[prop] = source[prop];
|
||||
}
|
||||
};
|
||||
|
||||
exports.eventEmitterListenerCount =
|
||||
require('events').EventEmitter.listenerCount ||
|
||||
function(emitter, type) { return emitter.listeners(type).length; };
|
||||
|
||||
exports.bufferAllocUnsafe = Buffer.allocUnsafe ?
|
||||
Buffer.allocUnsafe :
|
||||
function oldBufferAllocUnsafe(size) { return new Buffer(size); };
|
||||
|
||||
exports.bufferFromString = Buffer.from ?
|
||||
Buffer.from :
|
||||
function oldBufferFromString(string, encoding) {
|
||||
return new Buffer(string, encoding);
|
||||
};
|
||||
|
||||
exports.BufferingLogger = function createBufferingLogger(identifier, uniqueID) {
|
||||
var logFunction = require('debug')(identifier);
|
||||
if (logFunction.enabled) {
|
||||
var logger = new BufferingLogger(identifier, uniqueID, logFunction);
|
||||
var debug = logger.log.bind(logger);
|
||||
debug.printOutput = logger.printOutput.bind(logger);
|
||||
debug.enabled = logFunction.enabled;
|
||||
return debug;
|
||||
}
|
||||
logFunction.printOutput = noop;
|
||||
return logFunction;
|
||||
};
|
||||
|
||||
function BufferingLogger(identifier, uniqueID, logFunction) {
|
||||
this.logFunction = logFunction;
|
||||
this.identifier = identifier;
|
||||
this.uniqueID = uniqueID;
|
||||
this.buffer = [];
|
||||
}
|
||||
|
||||
BufferingLogger.prototype.log = function() {
|
||||
this.buffer.push([ new Date(), Array.prototype.slice.call(arguments) ]);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferingLogger.prototype.clear = function() {
|
||||
this.buffer = [];
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferingLogger.prototype.printOutput = function(logFunction) {
|
||||
if (!logFunction) { logFunction = this.logFunction; }
|
||||
var uniqueID = this.uniqueID;
|
||||
this.buffer.forEach(function(entry) {
|
||||
var date = entry[0].toLocaleString();
|
||||
var args = entry[1].slice();
|
||||
var formatString = args[0];
|
||||
if (formatString !== (void 0) && formatString !== null) {
|
||||
formatString = '%s - %s - ' + formatString.toString();
|
||||
args.splice(0, 1, formatString, date, uniqueID);
|
||||
logFunction.apply(global, args);
|
||||
}
|
||||
});
|
||||
};
|
1
node_modules/websocket/lib/version.js
generated
vendored
Normal file
1
node_modules/websocket/lib/version.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('../package.json').version;
|
11
node_modules/websocket/lib/websocket.js
generated
vendored
Normal file
11
node_modules/websocket/lib/websocket.js
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
'server' : require('./WebSocketServer'),
|
||||
'client' : require('./WebSocketClient'),
|
||||
'router' : require('./WebSocketRouter'),
|
||||
'frame' : require('./WebSocketFrame'),
|
||||
'request' : require('./WebSocketRequest'),
|
||||
'connection' : require('./WebSocketConnection'),
|
||||
'w3cwebsocket' : require('./W3CWebSocket'),
|
||||
'deprecation' : require('./Deprecation'),
|
||||
'version' : require('./version')
|
||||
};
|
95
node_modules/websocket/package.json
generated
vendored
Normal file
95
node_modules/websocket/package.json
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
{
|
||||
"_from": "websocket",
|
||||
"_id": "websocket@1.0.28",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-00y/20/80P7H4bCYkzuuvvfDvh+dgtXi5kzDf3UcZwN6boTYaKvsrtZ5lIYm1Gsg48siMErd9M4zjSYfYFHTrA==",
|
||||
"_location": "/websocket",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "tag",
|
||||
"registry": true,
|
||||
"raw": "websocket",
|
||||
"name": "websocket",
|
||||
"escapedName": "websocket",
|
||||
"rawSpec": "",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "latest"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER",
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.28.tgz",
|
||||
"_shasum": "9e5f6fdc8a3fe01d4422647ef93abdd8d45a78d3",
|
||||
"_spec": "websocket",
|
||||
"_where": "/Users/josh.burman/Projects/braid",
|
||||
"author": {
|
||||
"name": "Brian McKelvey",
|
||||
"email": "theturtle32@gmail.com",
|
||||
"url": "https://github.com/theturtle32"
|
||||
},
|
||||
"browser": "lib/browser.js",
|
||||
"bugs": {
|
||||
"url": "https://github.com/theturtle32/WebSocket-Node/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"config": {
|
||||
"verbose": false
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Iñaki Baz Castillo",
|
||||
"email": "ibc@aliax.net",
|
||||
"url": "http://dev.sipdoc.net"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"debug": "^2.2.0",
|
||||
"nan": "^2.11.0",
|
||||
"typedarray-to-buffer": "^3.1.5",
|
||||
"yaeti": "^0.0.6"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "Websocket Client & Server Library implementing the WebSocket protocol as specified in RFC 6455.",
|
||||
"devDependencies": {
|
||||
"buffer-equal": "^1.0.0",
|
||||
"faucet": "^0.0.1",
|
||||
"gulp": "git+https://github.com/gulpjs/gulp.git#4.0",
|
||||
"gulp-jshint": "^2.0.4",
|
||||
"jshint": "^2.0.0",
|
||||
"jshint-stylish": "^2.2.1",
|
||||
"tape": "^4.9.1"
|
||||
},
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"homepage": "https://github.com/theturtle32/WebSocket-Node",
|
||||
"keywords": [
|
||||
"websocket",
|
||||
"websockets",
|
||||
"socket",
|
||||
"networking",
|
||||
"comet",
|
||||
"push",
|
||||
"RFC-6455",
|
||||
"realtime",
|
||||
"server",
|
||||
"client"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"main": "index",
|
||||
"name": "websocket",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/theturtle32/WebSocket-Node.git"
|
||||
},
|
||||
"scripts": {
|
||||
"gulp": "gulp",
|
||||
"install": "(node-gyp rebuild 2> builderror.log) || (exit 0)",
|
||||
"test": "faucet test/unit"
|
||||
},
|
||||
"version": "1.0.28"
|
||||
}
|
121
node_modules/websocket/src/bufferutil.cc
generated
vendored
Normal file
121
node_modules/websocket/src/bufferutil.cc
generated
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
/*!
|
||||
* BufferUtil originally from:
|
||||
* ws: a node.js websocket client
|
||||
* Copyright(c) 2015 Einar Otto Stangvik <einaros@gmail.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
#include <v8.h>
|
||||
#include <node.h>
|
||||
#include <node_version.h>
|
||||
#include <node_buffer.h>
|
||||
#include <node_object_wrap.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <stdio.h>
|
||||
#include "nan.h"
|
||||
|
||||
using namespace v8;
|
||||
using namespace node;
|
||||
|
||||
class BufferUtil : public ObjectWrap
|
||||
{
|
||||
public:
|
||||
|
||||
static void Initialize(v8::Handle<v8::Object> target)
|
||||
{
|
||||
Nan::HandleScope scope;
|
||||
Local<FunctionTemplate> t = Nan::New<FunctionTemplate>(New);
|
||||
t->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
Nan::SetMethod(t, "unmask", BufferUtil::Unmask);
|
||||
Nan::SetMethod(t, "mask", BufferUtil::Mask);
|
||||
Nan::SetMethod(t, "merge", BufferUtil::Merge);
|
||||
Nan::Set(target, Nan::New<String>("BufferUtil").ToLocalChecked(), t->GetFunction());
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
static NAN_METHOD(New)
|
||||
{
|
||||
Nan::HandleScope scope;
|
||||
BufferUtil* bufferUtil = new BufferUtil();
|
||||
bufferUtil->Wrap(info.This());
|
||||
info.GetReturnValue().Set(info.This());
|
||||
}
|
||||
|
||||
static NAN_METHOD(Merge)
|
||||
{
|
||||
Nan::HandleScope scope;
|
||||
Local<Object> bufferObj = info[0]->ToObject();
|
||||
char* buffer = Buffer::Data(bufferObj);
|
||||
Local<Array> array = Local<Array>::Cast(info[1]);
|
||||
unsigned int arrayLength = array->Length();
|
||||
size_t offset = 0;
|
||||
unsigned int i;
|
||||
for (i = 0; i < arrayLength; ++i) {
|
||||
Local<Object> src = array->Get(i)->ToObject();
|
||||
size_t length = Buffer::Length(src);
|
||||
memcpy(buffer + offset, Buffer::Data(src), length);
|
||||
offset += length;
|
||||
}
|
||||
info.GetReturnValue().Set(Nan::True());
|
||||
}
|
||||
|
||||
static NAN_METHOD(Unmask)
|
||||
{
|
||||
Nan::HandleScope scope;
|
||||
Local<Object> buffer_obj = info[0]->ToObject();
|
||||
size_t length = Buffer::Length(buffer_obj);
|
||||
Local<Object> mask_obj = info[1]->ToObject();
|
||||
unsigned int *mask = (unsigned int*)Buffer::Data(mask_obj);
|
||||
unsigned int* from = (unsigned int*)Buffer::Data(buffer_obj);
|
||||
size_t len32 = length / 4;
|
||||
unsigned int i;
|
||||
for (i = 0; i < len32; ++i) *(from + i) ^= *mask;
|
||||
from += i;
|
||||
switch (length % 4) {
|
||||
case 3: *((unsigned char*)from+2) = *((unsigned char*)from+2) ^ ((unsigned char*)mask)[2];
|
||||
case 2: *((unsigned char*)from+1) = *((unsigned char*)from+1) ^ ((unsigned char*)mask)[1];
|
||||
case 1: *((unsigned char*)from ) = *((unsigned char*)from ) ^ ((unsigned char*)mask)[0];
|
||||
case 0:;
|
||||
}
|
||||
info.GetReturnValue().Set(Nan::True());
|
||||
}
|
||||
|
||||
static NAN_METHOD(Mask)
|
||||
{
|
||||
Nan::HandleScope scope;
|
||||
Local<Object> buffer_obj = info[0]->ToObject();
|
||||
Local<Object> mask_obj = info[1]->ToObject();
|
||||
unsigned int *mask = (unsigned int*)Buffer::Data(mask_obj);
|
||||
Local<Object> output_obj = info[2]->ToObject();
|
||||
unsigned int dataOffset = info[3]->Int32Value();
|
||||
unsigned int length = info[4]->Int32Value();
|
||||
unsigned int* to = (unsigned int*)(Buffer::Data(output_obj) + dataOffset);
|
||||
unsigned int* from = (unsigned int*)Buffer::Data(buffer_obj);
|
||||
unsigned int len32 = length / 4;
|
||||
unsigned int i;
|
||||
for (i = 0; i < len32; ++i) *(to + i) = *(from + i) ^ *mask;
|
||||
to += i;
|
||||
from += i;
|
||||
switch (length % 4) {
|
||||
case 3: *((unsigned char*)to+2) = *((unsigned char*)from+2) ^ *((unsigned char*)mask+2);
|
||||
case 2: *((unsigned char*)to+1) = *((unsigned char*)from+1) ^ *((unsigned char*)mask+1);
|
||||
case 1: *((unsigned char*)to ) = *((unsigned char*)from ) ^ *((unsigned char*)mask);
|
||||
case 0:;
|
||||
}
|
||||
info.GetReturnValue().Set(Nan::True());
|
||||
}
|
||||
};
|
||||
|
||||
#if !NODE_VERSION_AT_LEAST(0,10,0)
|
||||
extern "C"
|
||||
#endif
|
||||
void init (Handle<Object> target)
|
||||
{
|
||||
Nan::HandleScope scope;
|
||||
BufferUtil::Initialize(target);
|
||||
}
|
||||
|
||||
NODE_MODULE(bufferutil, init)
|
148
node_modules/websocket/src/validation.cc
generated
vendored
Normal file
148
node_modules/websocket/src/validation.cc
generated
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
/*!
|
||||
* UTF-8 Validation Code originally from:
|
||||
* ws: a node.js websocket client
|
||||
* Copyright(c) 2015 Einar Otto Stangvik <einaros@gmail.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
#include <v8.h>
|
||||
#include <node.h>
|
||||
#include <node_version.h>
|
||||
#include <node_buffer.h>
|
||||
#include <node_object_wrap.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <stdio.h>
|
||||
#include "nan.h"
|
||||
|
||||
using namespace v8;
|
||||
using namespace node;
|
||||
|
||||
#define UNI_SUR_HIGH_START (uint32_t) 0xD800
|
||||
#define UNI_SUR_LOW_END (uint32_t) 0xDFFF
|
||||
#define UNI_REPLACEMENT_CHAR (uint32_t) 0x0000FFFD
|
||||
#define UNI_MAX_LEGAL_UTF32 (uint32_t) 0x0010FFFF
|
||||
|
||||
static const uint8_t trailingBytesForUTF8[256] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
|
||||
};
|
||||
|
||||
static const uint32_t offsetsFromUTF8[6] = {
|
||||
0x00000000, 0x00003080, 0x000E2080,
|
||||
0x03C82080, 0xFA082080, 0x82082080
|
||||
};
|
||||
|
||||
static int isLegalUTF8(const uint8_t *source, const int length)
|
||||
{
|
||||
uint8_t a;
|
||||
const uint8_t *srcptr = source+length;
|
||||
switch (length) {
|
||||
default: return 0;
|
||||
/* Everything else falls through when "true"... */
|
||||
/* RFC3629 makes 5 & 6 bytes UTF-8 illegal
|
||||
case 6: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
|
||||
case 5: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; */
|
||||
case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
|
||||
case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
|
||||
case 2: if ((a = (*--srcptr)) > 0xBF) return 0;
|
||||
switch (*source) {
|
||||
/* no fall-through in this inner switch */
|
||||
case 0xE0: if (a < 0xA0) return 0; break;
|
||||
case 0xED: if (a > 0x9F) return 0; break;
|
||||
case 0xF0: if (a < 0x90) return 0; break;
|
||||
case 0xF4: if (a > 0x8F) return 0; break;
|
||||
default: if (a < 0x80) return 0;
|
||||
}
|
||||
|
||||
case 1: if (*source >= 0x80 && *source < 0xC2) return 0;
|
||||
}
|
||||
if (*source > 0xF4) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int is_valid_utf8 (size_t len, char *value)
|
||||
{
|
||||
/* is the string valid UTF-8? */
|
||||
for (unsigned int i = 0; i < len; i++) {
|
||||
uint32_t ch = 0;
|
||||
uint8_t extrabytes = trailingBytesForUTF8[(uint8_t) value[i]];
|
||||
|
||||
if (extrabytes + i >= len)
|
||||
return 0;
|
||||
|
||||
if (isLegalUTF8 ((uint8_t *) (value + i), extrabytes + 1) == 0) return 0;
|
||||
|
||||
switch (extrabytes) {
|
||||
case 5 : ch += (uint8_t) value[i++]; ch <<= 6;
|
||||
case 4 : ch += (uint8_t) value[i++]; ch <<= 6;
|
||||
case 3 : ch += (uint8_t) value[i++]; ch <<= 6;
|
||||
case 2 : ch += (uint8_t) value[i++]; ch <<= 6;
|
||||
case 1 : ch += (uint8_t) value[i++]; ch <<= 6;
|
||||
case 0 : ch += (uint8_t) value[i];
|
||||
}
|
||||
|
||||
ch -= offsetsFromUTF8[extrabytes];
|
||||
|
||||
if (ch <= UNI_MAX_LEGAL_UTF32) {
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
class Validation : public ObjectWrap
|
||||
{
|
||||
public:
|
||||
|
||||
static void Initialize(v8::Handle<v8::Object> target)
|
||||
{
|
||||
Nan::HandleScope scope;
|
||||
Local<FunctionTemplate> t = Nan::New<FunctionTemplate>(New);
|
||||
t->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
Nan::SetMethod(t, "isValidUTF8", Validation::IsValidUTF8);
|
||||
Nan::Set(target, Nan::New<String>("Validation").ToLocalChecked(), t->GetFunction());
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
static NAN_METHOD(New)
|
||||
{
|
||||
Nan::HandleScope scope;
|
||||
Validation* validation = new Validation();
|
||||
validation->Wrap(info.This());
|
||||
info.GetReturnValue().Set(info.This());
|
||||
}
|
||||
|
||||
static NAN_METHOD(IsValidUTF8)
|
||||
{
|
||||
Nan::HandleScope scope;
|
||||
if (!Buffer::HasInstance(info[0])) {
|
||||
return Nan::ThrowTypeError("First argument needs to be a buffer");
|
||||
}
|
||||
Local<Object> buffer_obj = info[0]->ToObject();
|
||||
char *buffer_data = Buffer::Data(buffer_obj);
|
||||
size_t buffer_length = Buffer::Length(buffer_obj);
|
||||
info.GetReturnValue().Set(is_valid_utf8(buffer_length, buffer_data) == 1 ? Nan::True() : Nan::False());
|
||||
}
|
||||
};
|
||||
#if !NODE_VERSION_AT_LEAST(0,10,0)
|
||||
extern "C"
|
||||
#endif
|
||||
void init (Handle<Object> target)
|
||||
{
|
||||
Nan::HandleScope scope;
|
||||
Validation::Initialize(target);
|
||||
}
|
||||
|
||||
NODE_MODULE(validation, init)
|
191
node_modules/websocket/vendor/FastBufferList.js
generated
vendored
Normal file
191
node_modules/websocket/vendor/FastBufferList.js
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
// This file was copied from https://github.com/substack/node-bufferlist
|
||||
// and modified to be able to copy bytes from the bufferlist directly into
|
||||
// a pre-existing fixed-size buffer without an additional memory allocation.
|
||||
|
||||
// bufferlist.js
|
||||
// Treat a linked list of buffers as a single variable-size buffer.
|
||||
var Buffer = require('buffer').Buffer;
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var bufferAllocUnsafe = require('../lib/utils').bufferAllocUnsafe;
|
||||
|
||||
module.exports = BufferList;
|
||||
module.exports.BufferList = BufferList; // backwards compatibility
|
||||
|
||||
function BufferList(opts) {
|
||||
if (!(this instanceof BufferList)) return new BufferList(opts);
|
||||
EventEmitter.call(this);
|
||||
var self = this;
|
||||
|
||||
if (typeof(opts) == 'undefined') opts = {};
|
||||
|
||||
// default encoding to use for take(). Leaving as 'undefined'
|
||||
// makes take() return a Buffer instead.
|
||||
self.encoding = opts.encoding;
|
||||
|
||||
var head = { next : null, buffer : null };
|
||||
var last = { next : null, buffer : null };
|
||||
|
||||
// length can get negative when advanced past the end
|
||||
// and this is the desired behavior
|
||||
var length = 0;
|
||||
self.__defineGetter__('length', function () {
|
||||
return length;
|
||||
});
|
||||
|
||||
// keep an offset of the head to decide when to head = head.next
|
||||
var offset = 0;
|
||||
|
||||
// Write to the bufferlist. Emits 'write'. Always returns true.
|
||||
self.write = function (buf) {
|
||||
if (!head.buffer) {
|
||||
head.buffer = buf;
|
||||
last = head;
|
||||
}
|
||||
else {
|
||||
last.next = { next : null, buffer : buf };
|
||||
last = last.next;
|
||||
}
|
||||
length += buf.length;
|
||||
self.emit('write', buf);
|
||||
return true;
|
||||
};
|
||||
|
||||
self.end = function (buf) {
|
||||
if (Buffer.isBuffer(buf)) self.write(buf);
|
||||
};
|
||||
|
||||
// Push buffers to the end of the linked list. (deprecated)
|
||||
// Return this (self).
|
||||
self.push = function () {
|
||||
var args = [].concat.apply([], arguments);
|
||||
args.forEach(self.write);
|
||||
return self;
|
||||
};
|
||||
|
||||
// For each buffer, perform some action.
|
||||
// If fn's result is a true value, cut out early.
|
||||
// Returns this (self).
|
||||
self.forEach = function (fn) {
|
||||
if (!head.buffer) return bufferAllocUnsafe(0);
|
||||
|
||||
if (head.buffer.length - offset <= 0) return self;
|
||||
var firstBuf = head.buffer.slice(offset);
|
||||
|
||||
var b = { buffer : firstBuf, next : head.next };
|
||||
|
||||
while (b && b.buffer) {
|
||||
var r = fn(b.buffer);
|
||||
if (r) break;
|
||||
b = b.next;
|
||||
}
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
// Create a single Buffer out of all the chunks or some subset specified by
|
||||
// start and one-past the end (like slice) in bytes.
|
||||
self.join = function (start, end) {
|
||||
if (!head.buffer) return bufferAllocUnsafe(0);
|
||||
if (start == undefined) start = 0;
|
||||
if (end == undefined) end = self.length;
|
||||
|
||||
var big = bufferAllocUnsafe(end - start);
|
||||
var ix = 0;
|
||||
self.forEach(function (buffer) {
|
||||
if (start < (ix + buffer.length) && ix < end) {
|
||||
// at least partially contained in the range
|
||||
buffer.copy(
|
||||
big,
|
||||
Math.max(0, ix - start),
|
||||
Math.max(0, start - ix),
|
||||
Math.min(buffer.length, end - ix)
|
||||
);
|
||||
}
|
||||
ix += buffer.length;
|
||||
if (ix > end) return true; // stop processing past end
|
||||
});
|
||||
|
||||
return big;
|
||||
};
|
||||
|
||||
self.joinInto = function (targetBuffer, targetStart, sourceStart, sourceEnd) {
|
||||
if (!head.buffer) return new bufferAllocUnsafe(0);
|
||||
if (sourceStart == undefined) sourceStart = 0;
|
||||
if (sourceEnd == undefined) sourceEnd = self.length;
|
||||
|
||||
var big = targetBuffer;
|
||||
if (big.length - targetStart < sourceEnd - sourceStart) {
|
||||
throw new Error("Insufficient space available in target Buffer.");
|
||||
}
|
||||
var ix = 0;
|
||||
self.forEach(function (buffer) {
|
||||
if (sourceStart < (ix + buffer.length) && ix < sourceEnd) {
|
||||
// at least partially contained in the range
|
||||
buffer.copy(
|
||||
big,
|
||||
Math.max(targetStart, targetStart + ix - sourceStart),
|
||||
Math.max(0, sourceStart - ix),
|
||||
Math.min(buffer.length, sourceEnd - ix)
|
||||
);
|
||||
}
|
||||
ix += buffer.length;
|
||||
if (ix > sourceEnd) return true; // stop processing past end
|
||||
});
|
||||
|
||||
return big;
|
||||
};
|
||||
|
||||
// Advance the buffer stream by n bytes.
|
||||
// If n the aggregate advance offset passes the end of the buffer list,
|
||||
// operations such as .take() will return empty strings until enough data is
|
||||
// pushed.
|
||||
// Returns this (self).
|
||||
self.advance = function (n) {
|
||||
offset += n;
|
||||
length -= n;
|
||||
while (head.buffer && offset >= head.buffer.length) {
|
||||
offset -= head.buffer.length;
|
||||
head = head.next
|
||||
? head.next
|
||||
: { buffer : null, next : null }
|
||||
;
|
||||
}
|
||||
if (head.buffer === null) last = { next : null, buffer : null };
|
||||
self.emit('advance', n);
|
||||
return self;
|
||||
};
|
||||
|
||||
// Take n bytes from the start of the buffers.
|
||||
// Returns a string.
|
||||
// If there are less than n bytes in all the buffers or n is undefined,
|
||||
// returns the entire concatenated buffer string.
|
||||
self.take = function (n, encoding) {
|
||||
if (n == undefined) n = self.length;
|
||||
else if (typeof n !== 'number') {
|
||||
encoding = n;
|
||||
n = self.length;
|
||||
}
|
||||
var b = head;
|
||||
if (!encoding) encoding = self.encoding;
|
||||
if (encoding) {
|
||||
var acc = '';
|
||||
self.forEach(function (buffer) {
|
||||
if (n <= 0) return true;
|
||||
acc += buffer.toString(
|
||||
encoding, 0, Math.min(n,buffer.length)
|
||||
);
|
||||
n -= buffer.length;
|
||||
});
|
||||
return acc;
|
||||
} else {
|
||||
// If no 'encoding' is specified, then return a Buffer.
|
||||
return self.join(0, n);
|
||||
}
|
||||
};
|
||||
|
||||
// The entire concatenated buffer as a string.
|
||||
self.toString = function () {
|
||||
return self.take('binary');
|
||||
};
|
||||
}
|
||||
require('util').inherits(BufferList, EventEmitter);
|
Reference in New Issue
Block a user