From 434aa8343fdcbb4d5002f934979913c099489bee Mon Sep 17 00:00:00 2001 From: altaf-creator Date: Sun, 16 Nov 2025 19:08:29 +0800 Subject: sdk, del --- .../node_modules/websocket-extensions/CHANGELOG.md | 28 - .../node_modules/websocket-extensions/LICENSE.md | 12 - .../node_modules/websocket-extensions/README.md | 331 ----------- .../websocket-extensions/lib/parser.js | 103 ---- .../websocket-extensions/lib/pipeline/README.md | 607 --------------------- .../websocket-extensions/lib/pipeline/cell.js | 53 -- .../websocket-extensions/lib/pipeline/functor.js | 72 --- .../websocket-extensions/lib/pipeline/index.js | 47 -- .../websocket-extensions/lib/pipeline/pledge.js | 37 -- .../lib/pipeline/ring_buffer.js | 66 --- .../lib/websocket_extensions.js | 162 ------ .../node_modules/websocket-extensions/package.json | 29 - 12 files changed, 1547 deletions(-) delete mode 100644 frontend-old/node_modules/websocket-extensions/CHANGELOG.md delete mode 100644 frontend-old/node_modules/websocket-extensions/LICENSE.md delete mode 100644 frontend-old/node_modules/websocket-extensions/README.md delete mode 100644 frontend-old/node_modules/websocket-extensions/lib/parser.js delete mode 100644 frontend-old/node_modules/websocket-extensions/lib/pipeline/README.md delete mode 100644 frontend-old/node_modules/websocket-extensions/lib/pipeline/cell.js delete mode 100644 frontend-old/node_modules/websocket-extensions/lib/pipeline/functor.js delete mode 100644 frontend-old/node_modules/websocket-extensions/lib/pipeline/index.js delete mode 100644 frontend-old/node_modules/websocket-extensions/lib/pipeline/pledge.js delete mode 100644 frontend-old/node_modules/websocket-extensions/lib/pipeline/ring_buffer.js delete mode 100644 frontend-old/node_modules/websocket-extensions/lib/websocket_extensions.js delete mode 100644 frontend-old/node_modules/websocket-extensions/package.json (limited to 'frontend-old/node_modules/websocket-extensions') diff --git a/frontend-old/node_modules/websocket-extensions/CHANGELOG.md b/frontend-old/node_modules/websocket-extensions/CHANGELOG.md deleted file mode 100644 index bb84f5a..0000000 --- a/frontend-old/node_modules/websocket-extensions/CHANGELOG.md +++ /dev/null @@ -1,28 +0,0 @@ -### 0.1.4 / 2020-06-02 - -- Remove a ReDoS vulnerability in the header parser (CVE-2020-7662, reported by - Robert McLaughlin) -- Change license from MIT to Apache 2.0 - -### 0.1.3 / 2017-11-11 - -- Accept extension names and parameters including uppercase letters -- Handle extension names that clash with `Object.prototype` properties - -### 0.1.2 / 2017-09-10 - -- Catch synchronous exceptions thrown when calling an extension -- Fix race condition caused when a message is pushed after a cell has stopped - due to an error -- Fix failure of `close()` to return if a message that's queued after one that - produces an error never finishes being processed - -### 0.1.1 / 2015-02-19 - -- Prevent sessions being closed before they have finished processing messages -- Add a callback to `Extensions.close()` so the caller can tell when it's safe - to close the socket - -### 0.1.0 / 2014-12-12 - -- Initial release diff --git a/frontend-old/node_modules/websocket-extensions/LICENSE.md b/frontend-old/node_modules/websocket-extensions/LICENSE.md deleted file mode 100644 index 3a88e51..0000000 --- a/frontend-old/node_modules/websocket-extensions/LICENSE.md +++ /dev/null @@ -1,12 +0,0 @@ -Copyright 2014-2020 James Coglan - -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. diff --git a/frontend-old/node_modules/websocket-extensions/README.md b/frontend-old/node_modules/websocket-extensions/README.md deleted file mode 100644 index 68694ea..0000000 --- a/frontend-old/node_modules/websocket-extensions/README.md +++ /dev/null @@ -1,331 +0,0 @@ -# websocket-extensions [![Build status](https://secure.travis-ci.org/faye/websocket-extensions-node.svg)](http://travis-ci.org/faye/websocket-extensions-node) - -A minimal framework that supports the implementation of WebSocket extensions in -a way that's decoupled from the main protocol. This library aims to allow a -WebSocket extension to be written and used with any protocol library, by -defining abstract representations of frames and messages that allow modules to -co-operate. - -`websocket-extensions` provides a container for registering extension plugins, -and provides all the functions required to negotiate which extensions to use -during a session via the `Sec-WebSocket-Extensions` header. By implementing the -APIs defined in this document, an extension may be used by any WebSocket library -based on this framework. - -## Installation - -``` -$ npm install websocket-extensions -``` - -## Usage - -There are two main audiences for this library: authors implementing the -WebSocket protocol, and authors implementing extensions. End users of a -WebSocket library or an extension should be able to use any extension by passing -it as an argument to their chosen protocol library, without needing to know how -either of them work, or how the `websocket-extensions` framework operates. - -The library is designed with the aim that any protocol implementation and any -extension can be used together, so long as they support the same abstract -representation of frames and messages. - -### Data types - -The APIs provided by the framework rely on two data types; extensions will -expect to be given data and to be able to return data in these formats: - -#### *Frame* - -*Frame* is a structure representing a single WebSocket frame of any type. Frames -are simple objects that must have at least the following properties, which -represent the data encoded in the frame: - -| property | description | -| ------------ | ------------------------------------------------------------------ | -| `final` | `true` if the `FIN` bit is set, `false` otherwise | -| `rsv1` | `true` if the `RSV1` bit is set, `false` otherwise | -| `rsv2` | `true` if the `RSV2` bit is set, `false` otherwise | -| `rsv3` | `true` if the `RSV3` bit is set, `false` otherwise | -| `opcode` | the numeric opcode (`0`, `1`, `2`, `8`, `9`, or `10`) of the frame | -| `masked` | `true` if the `MASK` bit is set, `false` otherwise | -| `maskingKey` | a 4-byte `Buffer` if `masked` is `true`, otherwise `null` | -| `payload` | a `Buffer` containing the (unmasked) application data | - -#### *Message* - -A *Message* represents a complete application message, which can be formed from -text, binary and continuation frames. It has the following properties: - -| property | description | -| -------- | ----------------------------------------------------------------- | -| `rsv1` | `true` if the first frame of the message has the `RSV1` bit set | -| `rsv2` | `true` if the first frame of the message has the `RSV2` bit set | -| `rsv3` | `true` if the first frame of the message has the `RSV3` bit set | -| `opcode` | the numeric opcode (`1` or `2`) of the first frame of the message | -| `data` | the concatenation of all the frame payloads in the message | - -### For driver authors - -A driver author is someone implementing the WebSocket protocol proper, and who -wishes end users to be able to use WebSocket extensions with their library. - -At the start of a WebSocket session, on both the client and the server side, -they should begin by creating an extension container and adding whichever -extensions they want to use. - -```js -var Extensions = require('websocket-extensions'), - deflate = require('permessage-deflate'); - -var exts = new Extensions(); -exts.add(deflate); -``` - -In the following examples, `exts` refers to this `Extensions` instance. - -#### Client sessions - -Clients will use the methods `generateOffer()` and `activate(header)`. - -As part of the handshake process, the client must send a -`Sec-WebSocket-Extensions` header to advertise that it supports the registered -extensions. This header should be generated using: - -```js -request.headers['sec-websocket-extensions'] = exts.generateOffer(); -``` - -This returns a string, for example `"permessage-deflate; -client_max_window_bits"`, that represents all the extensions the client is -offering to use, and their parameters. This string may contain multiple offers -for the same extension. - -When the client receives the handshake response from the server, it should pass -the incoming `Sec-WebSocket-Extensions` header in to `exts` to activate the -extensions the server has accepted: - -```js -exts.activate(response.headers['sec-websocket-extensions']); -``` - -If the server has sent any extension responses that the client does not -recognize, or are in conflict with one another for use of RSV bits, or that use -invalid parameters for the named extensions, then `exts.activate()` will -`throw`. In this event, the client driver should fail the connection with -closing code `1010`. - -#### Server sessions - -Servers will use the method `generateResponse(header)`. - -A server session needs to generate a `Sec-WebSocket-Extensions` header to send -in its handshake response: - -```js -var clientOffer = request.headers['sec-websocket-extensions'], - extResponse = exts.generateResponse(clientOffer); - -response.headers['sec-websocket-extensions'] = extResponse; -``` - -Calling `exts.generateResponse(header)` activates those extensions the client -has asked to use, if they are registered, asks each extension for a set of -response parameters, and returns a string containing the response parameters for -all accepted extensions. - -#### In both directions - -Both clients and servers will use the methods `validFrameRsv(frame)`, -`processIncomingMessage(message)` and `processOutgoingMessage(message)`. - -The WebSocket protocol requires that frames do not have any of the `RSV` bits -set unless there is an extension in use that allows otherwise. When processing -an incoming frame, sessions should pass a *Frame* object to: - -```js -exts.validFrameRsv(frame) -``` - -If this method returns `false`, the session should fail the WebSocket connection -with closing code `1002`. - -To pass incoming messages through the extension stack, a session should -construct a *Message* object according to the above datatype definitions, and -call: - -```js -exts.processIncomingMessage(message, function(error, msg) { - // hand the message off to the application -}); -``` - -If any extensions fail to process the message, then the callback will yield an -error and the session should fail the WebSocket connection with closing code -`1010`. If `error` is `null`, then `msg` should be passed on to the application. - -To pass outgoing messages through the extension stack, a session should -construct a *Message* as before, and call: - -```js -exts.processOutgoingMessage(message, function(error, msg) { - // write message to the transport -}); -``` - -If any extensions fail to process the message, then the callback will yield an -error and the session should fail the WebSocket connection with closing code -`1010`. If `error` is `null`, then `message` should be converted into frames -(with the message's `rsv1`, `rsv2`, `rsv3` and `opcode` set on the first frame) -and written to the transport. - -At the end of the WebSocket session (either when the protocol is explicitly -ended or the transport connection disconnects), the driver should call: - -```js -exts.close(function() {}) -``` - -The callback is invoked when all extensions have finished processing any -messages in the pipeline and it's safe to close the socket. - -### For extension authors - -An extension author is someone implementing an extension that transforms -WebSocket messages passing between the client and server. They would like to -implement their extension once and have it work with any protocol library. - -Extension authors will not install `websocket-extensions` or call it directly. -Instead, they should implement the following API to allow their extension to -plug into the `websocket-extensions` framework. - -An `Extension` is any object that has the following properties: - -| property | description | -| -------- | ---------------------------------------------------------------------------- | -| `name` | a string containing the name of the extension as used in negotiation headers | -| `type` | a string, must be `"permessage"` | -| `rsv1` | either `true` if the extension uses the RSV1 bit, `false` otherwise | -| `rsv2` | either `true` if the extension uses the RSV2 bit, `false` otherwise | -| `rsv3` | either `true` if the extension uses the RSV3 bit, `false` otherwise | - -It must also implement the following methods: - -```js -ext.createClientSession() -``` - -This returns a *ClientSession*, whose interface is defined below. - -```js -ext.createServerSession(offers) -``` - -This takes an array of offer params and returns a *ServerSession*, whose -interface is defined below. For example, if the client handshake contains the -offer header: - -``` -Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover; server_max_window_bits=8, \ - permessage-deflate; server_max_window_bits=15 -``` - -then the `permessage-deflate` extension will receive the call: - -```js -ext.createServerSession([ - { server_no_context_takeover: true, server_max_window_bits: 8 }, - { server_max_window_bits: 15 } -]); -``` - -The extension must decide which set of parameters it wants to accept, if any, -and return a *ServerSession* if it wants to accept the parameters and `null` -otherwise. - -#### *ClientSession* - -A *ClientSession* is the type returned by `ext.createClientSession()`. It must -implement the following methods, as well as the *Session* API listed below. - -```js -clientSession.generateOffer() -// e.g. -> [ -// { server_no_context_takeover: true, server_max_window_bits: 8 }, -// { server_max_window_bits: 15 } -// ] -``` - -This must return a set of parameters to include in the client's -`Sec-WebSocket-Extensions` offer header. If the session wants to offer multiple -configurations, it can return an array of sets of parameters as shown above. - -```js -clientSession.activate(params) // -> true -``` - -This must take a single set of parameters from the server's handshake response -and use them to configure the client session. If the client accepts the given -parameters, then this method must return `true`. If it returns any other value, -the framework will interpret this as the client rejecting the response, and will -`throw`. - -#### *ServerSession* - -A *ServerSession* is the type returned by `ext.createServerSession(offers)`. It -must implement the following methods, as well as the *Session* API listed below. - -```js -serverSession.generateResponse() -// e.g. -> { server_max_window_bits: 8 } -``` - -This returns the set of parameters the server session wants to send in its -`Sec-WebSocket-Extensions` response header. Only one set of parameters is -returned to the client per extension. Server sessions that would confict on -their use of RSV bits are not activated. - -#### *Session* - -The *Session* API must be implemented by both client and server sessions. It -contains two methods, `processIncomingMessage(message)` and -`processOutgoingMessage(message)`. - -```js -session.processIncomingMessage(message, function(error, msg) { ... }) -``` - -The session must implement this method to take an incoming *Message* as defined -above, transform it in any way it needs, then return it via the callback. If -there is an error processing the message, this method should yield an error as -the first argument. - -```js -session.processOutgoingMessage(message, function(error, msg) { ... }) -``` - -The session must implement this method to take an outgoing *Message* as defined -above, transform it in any way it needs, then return it via the callback. If -there is an error processing the message, this method should yield an error as -the first argument. - -Note that both `processIncomingMessage()` and `processOutgoingMessage()` can -perform their logic asynchronously, are allowed to process multiple messages -concurrently, and are not required to complete working on messages in the same -order the messages arrive. `websocket-extensions` will reorder messages as your -extension emits them and will make sure every extension is given messages in the -order they arrive from the driver. This allows extensions to maintain state that -depends on the messages' wire order, for example keeping a DEFLATE compression -context between messages. - -```js -session.close() -``` - -The framework will call this method when the WebSocket session ends, allowing -the session to release any resources it's using. - -## Examples - -- Consumer: [websocket-driver](https://github.com/faye/websocket-driver-node) -- Provider: [permessage-deflate](https://github.com/faye/permessage-deflate-node) diff --git a/frontend-old/node_modules/websocket-extensions/lib/parser.js b/frontend-old/node_modules/websocket-extensions/lib/parser.js deleted file mode 100644 index 533767e..0000000 --- a/frontend-old/node_modules/websocket-extensions/lib/parser.js +++ /dev/null @@ -1,103 +0,0 @@ -'use strict'; - -var TOKEN = /([!#\$%&'\*\+\-\.\^_`\|~0-9A-Za-z]+)/, - NOTOKEN = /([^!#\$%&'\*\+\-\.\^_`\|~0-9A-Za-z])/g, - QUOTED = /"((?:\\[\x00-\x7f]|[^\x00-\x08\x0a-\x1f\x7f"\\])*)"/, - PARAM = new RegExp(TOKEN.source + '(?:=(?:' + TOKEN.source + '|' + QUOTED.source + '))?'), - EXT = new RegExp(TOKEN.source + '(?: *; *' + PARAM.source + ')*', 'g'), - EXT_LIST = new RegExp('^' + EXT.source + '(?: *, *' + EXT.source + ')*$'), - NUMBER = /^-?(0|[1-9][0-9]*)(\.[0-9]+)?$/; - -var hasOwnProperty = Object.prototype.hasOwnProperty; - -var Parser = { - parseHeader: function(header) { - var offers = new Offers(); - if (header === '' || header === undefined) return offers; - - if (!EXT_LIST.test(header)) - throw new SyntaxError('Invalid Sec-WebSocket-Extensions header: ' + header); - - var values = header.match(EXT); - - values.forEach(function(value) { - var params = value.match(new RegExp(PARAM.source, 'g')), - name = params.shift(), - offer = {}; - - params.forEach(function(param) { - var args = param.match(PARAM), key = args[1], data; - - if (args[2] !== undefined) { - data = args[2]; - } else if (args[3] !== undefined) { - data = args[3].replace(/\\/g, ''); - } else { - data = true; - } - if (NUMBER.test(data)) data = parseFloat(data); - - if (hasOwnProperty.call(offer, key)) { - offer[key] = [].concat(offer[key]); - offer[key].push(data); - } else { - offer[key] = data; - } - }, this); - offers.push(name, offer); - }, this); - - return offers; - }, - - serializeParams: function(name, params) { - var values = []; - - var print = function(key, value) { - if (value instanceof Array) { - value.forEach(function(v) { print(key, v) }); - } else if (value === true) { - values.push(key); - } else if (typeof value === 'number') { - values.push(key + '=' + value); - } else if (NOTOKEN.test(value)) { - values.push(key + '="' + value.replace(/"/g, '\\"') + '"'); - } else { - values.push(key + '=' + value); - } - }; - - for (var key in params) print(key, params[key]); - - return [name].concat(values).join('; '); - } -}; - -var Offers = function() { - this._byName = {}; - this._inOrder = []; -}; - -Offers.prototype.push = function(name, params) { - if (!hasOwnProperty.call(this._byName, name)) - this._byName[name] = []; - - this._byName[name].push(params); - this._inOrder.push({ name: name, params: params }); -}; - -Offers.prototype.eachOffer = function(callback, context) { - var list = this._inOrder; - for (var i = 0, n = list.length; i < n; i++) - callback.call(context, list[i].name, list[i].params); -}; - -Offers.prototype.byName = function(name) { - return this._byName[name] || []; -}; - -Offers.prototype.toArray = function() { - return this._inOrder.slice(); -}; - -module.exports = Parser; diff --git a/frontend-old/node_modules/websocket-extensions/lib/pipeline/README.md b/frontend-old/node_modules/websocket-extensions/lib/pipeline/README.md deleted file mode 100644 index 322a9c5..0000000 --- a/frontend-old/node_modules/websocket-extensions/lib/pipeline/README.md +++ /dev/null @@ -1,607 +0,0 @@ -# Extension pipelining - -`websocket-extensions` models the extension negotiation and processing pipeline -of the WebSocket protocol. Between the driver parsing messages from the TCP -stream and handing those messages off to the application, there may exist a -stack of extensions that transform the message somehow. - -In the parlance of this framework, a *session* refers to a single instance of an -extension, acting on a particular socket on either the server or the client -side. A session may transform messages both incoming to the application and -outgoing from the application, for example the `permessage-deflate` extension -compresses outgoing messages and decompresses incoming messages. Message streams -in either direction are independent; that is, incoming and outgoing messages -cannot be assumed to 'pair up' as in a request-response protocol. - -Asynchronous processing of messages poses a number of problems that this -pipeline construction is intended to solve. - - -## Overview - -Logically, we have the following: - - - +-------------+ out +---+ +---+ +---+ +--------+ - | |------>| |---->| |---->| |------>| | - | Application | | A | | B | | C | | Driver | - | |<------| |<----| |<----| |<------| | - +-------------+ in +---+ +---+ +---+ +--------+ - - \ / - +----------o----------+ - | - sessions - - -For outgoing messages, the driver receives the result of - - C.outgoing(B.outgoing(A.outgoing(message))) - - or, [A, B, C].reduce(((m, ext) => ext.outgoing(m)), message) - -For incoming messages, the application receives the result of - - A.incoming(B.incoming(C.incoming(message))) - - or, [C, B, A].reduce(((m, ext) => ext.incoming(m)), message) - -A session is of the following type, to borrow notation from pseudo-Haskell: - - type Session = { - incoming :: Message -> Message - outgoing :: Message -> Message - close :: () -> () - } - -(That `() -> ()` syntax is intended to mean that `close()` is a nullary void -method; I apologise to any Haskell readers for not using the right monad.) - -The `incoming()` and `outgoing()` methods perform message transformation in the -respective directions; `close()` is called when a socket closes so the session -can release any resources it's holding, for example a DEFLATE de/compression -context. - -However because this is JavaScript, the `incoming()` and `outgoing()` methods -may be asynchronous (indeed, `permessage-deflate` is based on `zlib`, whose API -is stream-based). So their interface is strictly: - - type Session = { - incoming :: Message -> Callback -> () - outgoing :: Message -> Callback -> () - close :: () -> () - } - - type Callback = Either Error Message -> () - -This means a message *m2* can be pushed into a session while it's still -processing the preceding message *m1*. The messages can be processed -concurrently but they *must* be given to the next session in line (or to the -application) in the same order they came in. Applications will expect to receive -messages in the order they arrived over the wire, and sessions require this too. -So ordering of messages must be preserved throughout the pipeline. - -Consider the following highly simplified extension that deflates messages on the -wire. `message` is a value conforming the type: - - type Message = { - rsv1 :: Boolean - rsv2 :: Boolean - rsv3 :: Boolean - opcode :: Number - data :: Buffer - } - -Here's the extension: - -```js -var zlib = require('zlib'); - -var deflate = { - outgoing: function(message, callback) { - zlib.deflateRaw(message.data, function(error, result) { - message.rsv1 = true; - message.data = result; - callback(error, message); - }); - }, - - incoming: function(message, callback) { - // decompress inbound messages (elided) - }, - - close: function() { - // no state to clean up - } -}; -``` - -We can call it with a large message followed by a small one, and the small one -will be returned first: - -```js -var crypto = require('crypto'), - large = crypto.randomBytes(1 << 14), - small = new Buffer('hi'); - -deflate.outgoing({ data: large }, function() { - console.log(1, 'large'); -}); - -deflate.outgoing({ data: small }, function() { - console.log(2, 'small'); -}); - -/* prints: 2 'small' - 1 'large' */ -``` - -So a session that processes messages asynchronously may fail to preserve message -ordering. - -Now, this extension is stateless, so it can process messages in any order and -still produce the same output. But some extensions are stateful and require -message order to be preserved. - -For example, when using `permessage-deflate` without `no_context_takeover` set, -the session retains a DEFLATE de/compression context between messages, which -accumulates state as it consumes data (later messages can refer to sections of -previous ones to improve compression). Reordering parts of the DEFLATE stream -will result in a failed decompression. Messages must be decompressed in the same -order they were compressed by the peer in order for the DEFLATE protocol to -work. - -Finally, there is the problem of closing a socket. When a WebSocket is closed by -the application, or receives a closing request from the other peer, there may be -messages outgoing from the application and incoming from the peer in the -pipeline. If we close the socket and pipeline immediately, two problems arise: - -* We may send our own closing frame to the peer before all prior messages we - sent have been written to the socket, and before we have finished processing - all prior messages from the peer -* The session may be instructed to close its resources (e.g. its de/compression - context) while it's in the middle of processing a message, or before it has - received messages that are upstream of it in the pipeline - -Essentially, we must defer closing the sessions and sending a closing frame -until after all prior messages have exited the pipeline. - - -## Design goals - -* Message order must be preserved between the protocol driver, the extension - sessions, and the application -* Messages should be handed off to sessions and endpoints as soon as possible, - to maximise throughput of stateless sessions -* The closing procedure should block any further messages from entering the - pipeline, and should allow all existing messages to drain -* Sessions should be closed as soon as possible to prevent them holding memory - and other resources when they have no more messages to handle -* The closing API should allow the caller to detect when the pipeline is empty - and it is safe to continue the WebSocket closing procedure -* Individual extensions should remain as simple as possible to facilitate - modularity and independent authorship - -The final point about modularity is an important one: this framework is designed -to facilitate extensions existing as plugins, by decoupling the protocol driver, -extensions, and application. In an ideal world, plugins should only need to -contain code for their specific functionality, and not solve these problems that -apply to all sessions. Also, solving some of these problems requires -consideration of all active sessions collectively, which an individual session -is incapable of doing. - -For example, it is entirely possible to take the simple `deflate` extension -above and wrap its `incoming()` and `outgoing()` methods in two `Transform` -streams, producing this type: - - type Session = { - incoming :: TransformStream - outtoing :: TransformStream - close :: () -> () - } - -The `Transform` class makes it easy to wrap an async function such that message -order is preserved: - -```js -var stream = require('stream'), - session = new stream.Transform({ objectMode: true }); - -session._transform = function(message, _, callback) { - var self = this; - deflate.outgoing(message, function(error, result) { - self.push(result); - callback(); - }); -}; -``` - -However, this has a negative impact on throughput: it works by deferring -`callback()` until the async function has 'returned', which blocks `Transform` -from passing further input into the `_transform()` method until the current -message is dealt with completely. This would prevent sessions from processing -messages concurrently, and would unnecessarily reduce the throughput of -stateless extensions. - -So, input should be handed off to sessions as soon as possible, and all we need -is a mechanism to reorder the output so that message order is preserved for the -next session in line. - - -## Solution - -We now describe the model implemented here and how it meets the above design -goals. The above diagram where a stack of extensions sit between the driver and -application describes the data flow, but not the object graph. That looks like -this: - - - +--------+ - | Driver | - +---o----+ - | - V - +------------+ +----------+ - | Extensions o----->| Pipeline | - +------------+ +-----o----+ - | - +---------------+---------------+ - | | | - +-----o----+ +-----o----+ +-----o----+ - | Cell [A] | | Cell [B] | | Cell [C] | - +----------+ +----------+ +----------+ - - -A driver using this framework holds an instance of the `Extensions` class, which -it uses to register extension plugins, negotiate headers and transform messages. -The `Extensions` instance itself holds a `Pipeline`, which contains an array of -`Cell` objects, each of which wraps one of the sessions. - - -### Message processing - -Both the `Pipeline` and `Cell` classes have `incoming()` and `outgoing()` -methods; the `Pipeline` interface pushes messages into the pipe, delegates the -message to each `Cell` in turn, then returns it back to the driver. Outgoing -messages pass through `A` then `B` then `C`, and incoming messages in the -reverse order. - -Internally, a `Cell` contains two `Functor` objects. A `Functor` wraps an async -function and makes sure its output messages maintain the order of its input -messages. This name is due to [@fronx](https://github.com/fronx), on the basis -that, by preserving message order, the abstraction preserves the *mapping* -between input and output messages. To use our simple `deflate` extension from -above: - -```js -var functor = new Functor(deflate, 'outgoing'); - -functor.call({ data: large }, function() { - console.log(1, 'large'); -}); - -functor.call({ data: small }, function() { - console.log(2, 'small'); -}); - -/* -> 1 'large' - 2 'small' */ -``` - -A `Cell` contains two of these, one for each direction: - - - +-----------------------+ - +---->| Functor [A, incoming] | - +----------+ | +-----------------------+ - | Cell [A] o------+ - +----------+ | +-----------------------+ - +---->| Functor [A, outgoing] | - +-----------------------+ - - -This satisfies the message transformation requirements: the `Pipeline` simply -loops over the cells in the appropriate direction to transform each message. -Because each `Cell` will preserve message order, we can pass a message to the -next `Cell` in line as soon as the current `Cell` returns it. This gives each -`Cell` all the messages in order while maximising throughput. - - -### Session closing - -We want to close each session as soon as possible, after all existing messages -have drained. To do this, each `Cell` begins with a pending message counter in -each direction, labelled `in` and `out` below. - - - +----------+ - | Pipeline | - +-----o----+ - | - +---------------+---------------+ - | | | - +-----o----+ +-----o----+ +-----o----+ - | Cell [A] | | Cell [B] | | Cell [C] | - +----------+ +----------+ +----------+ - in: 0 in: 0 in: 0 - out: 0 out: 0 out: 0 - - -When a message *m1* enters the pipeline, say in the `outgoing` direction, we -increment the `pending.out` counter on all cells immediately. - - - +----------+ - m1 => | Pipeline | - +-----o----+ - | - +---------------+---------------+ - | | | - +-----o----+ +-----o----+ +-----o----+ - | Cell [A] | | Cell [B] | | Cell [C] | - +----------+ +----------+ +----------+ - in: 0 in: 0 in: 0 - out: 1 out: 1 out: 1 - - -*m1* is handed off to `A`, meanwhile a second message `m2` arrives in the same -direction. All `pending.out` counters are again incremented. - - - +----------+ - m2 => | Pipeline | - +-----o----+ - | - +---------------+---------------+ - m1 | | | - +-----o----+ +-----o----+ +-----o----+ - | Cell [A] | | Cell [B] | | Cell [C] | - +----------+ +----------+ +----------+ - in: 0 in: 0 in: 0 - out: 2 out: 2 out: 2 - - -When the first cell's `A.outgoing` functor finishes processing *m1*, the first -`pending.out` counter is decremented and *m1* is handed off to cell `B`. - - - +----------+ - | Pipeline | - +-----o----+ - | - +---------------+---------------+ - m2 | m1 | | - +-----o----+ +-----o----+ +-----o----+ - | Cell [A] | | Cell [B] | | Cell [C] | - +----------+ +----------+ +----------+ - in: 0 in: 0 in: 0 - out: 1 out: 2 out: 2 - - - -As `B` finishes with *m1*, and as `A` finishes with *m2*, the `pending.out` -counters continue to decrement. - - - +----------+ - | Pipeline | - +-----o----+ - | - +---------------+---------------+ - | m2 | m1 | - +-----o----+ +-----o----+ +-----o----+ - | Cell [A] | | Cell [B] | | Cell [C] | - +----------+ +----------+ +----------+ - in: 0 in: 0 in: 0 - out: 0 out: 1 out: 2 - - - -Say `C` is a little slow, and begins processing *m2* while still processing -*m1*. That's fine, the `Functor` mechanism will keep *m1* ahead of *m2* in the -output. - - - +----------+ - | Pipeline | - +-----o----+ - | - +---------------+---------------+ - | | m2 | m1 - +-----o----+ +-----o----+ +-----o----+ - | Cell [A] | | Cell [B] | | Cell [C] | - +----------+ +----------+ +----------+ - in: 0 in: 0 in: 0 - out: 0 out: 0 out: 2 - - -Once all messages are dealt with, the counters return to `0`. - - - +----------+ - | Pipeline | - +-----o----+ - | - +---------------+---------------+ - | | | - +-----o----+ +-----o----+ +-----o----+ - | Cell [A] | | Cell [B] | | Cell [C] | - +----------+ +----------+ +----------+ - in: 0 in: 0 in: 0 - out: 0 out: 0 out: 0 - - -The same process applies in the `incoming` direction, the only difference being -that messages are passed to `C` first. - -This makes closing the sessions quite simple. When the driver wants to close the -socket, it calls `Pipeline.close()`. This *immediately* calls `close()` on all -the cells. If a cell has `in == out == 0`, then it immediately calls -`session.close()`. Otherwise, it stores the closing call and defers it until -`in` and `out` have both ticked down to zero. The pipeline will not accept new -messages after `close()` has been called, so we know the pending counts will not -increase after this point. - -This means each session is closed as soon as possible: `A` can close while the -slow `C` session is still working, because it knows there are no more messages -on the way. Similarly, `C` will defer closing if `close()` is called while *m1* -is still in `B`, and *m2* in `A`, because its pending count means it knows it -has work yet to do, even if it's not received those messages yet. This concern -cannot be addressed by extensions acting only on their own local state, unless -we pollute individual extensions by making them all implement this same -mechanism. - -The actual closing API at each level is slightly different: - - type Session = { - close :: () -> () - } - - type Cell = { - close :: () -> Promise () - } - - type Pipeline = { - close :: Callback -> () - } - -This might appear inconsistent so it's worth explaining. Remember that a -`Pipeline` holds a list of `Cell` objects, each wrapping a `Session`. The driver -talks (via the `Extensions` API) to the `Pipeline` interface, and it wants -`Pipeline.close()` to do two things: close all the sessions, and tell me when -it's safe to start the closing procedure (i.e. when all messages have drained -from the pipe and been handed off to the application or socket). A callback API -works well for that. - -At the other end of the stack, `Session.close()` is a nullary void method with -no callback or promise API because we don't care what it does, and whatever it -does do will not block the WebSocket protocol; we're not going to hold off -processing messages while a session closes its de/compression context. We just -tell it to close itself, and don't want to wait while it does that. - -In the middle, `Cell.close()` returns a promise rather than using a callback. -This is for two reasons. First, `Cell.close()` might not do anything -immediately, it might have to defer its effect while messages drain. So, if -given a callback, it would have to store it in a queue for later execution. -Callbacks work fine if your method does something and can then invoke the -callback itself, but if you need to store callbacks somewhere so another method -can execute them, a promise is a better fit. Second, it better serves the -purposes of `Pipeline.close()`: it wants to call `close()` on each of a list of -cells, and wait for all of them to finish. This is simple and idiomatic using -promises: - -```js -var closed = cells.map((cell) => cell.close()); -Promise.all(closed).then(callback); -``` - -(We don't actually use a full *Promises/A+* compatible promise here, we use a -much simplified construction that acts as a callback aggregater and resolves -synchronously and does not support chaining, but the principle is the same.) - - -### Error handling - -We've not mentioned error handling so far but it bears some explanation. The -above counter system still applies, but behaves slightly differently in the -presence of errors. - -Say we push three messages into the pipe in the outgoing direction: - - - +----------+ - m3, m2, m1 => | Pipeline | - +-----o----+ - | - +---------------+---------------+ - | | | - +-----o----+ +-----o----+ +-----o----+ - | Cell [A] | | Cell [B] | | Cell [C] | - +----------+ +----------+ +----------+ - in: 0 in: 0 in: 0 - out: 3 out: 3 out: 3 - - -They pass through the cells successfully up to this point: - - - +----------+ - | Pipeline | - +-----o----+ - | - +---------------+---------------+ - m3 | m2 | m1 | - +-----o----+ +-----o----+ +-----o----+ - | Cell [A] | | Cell [B] | | Cell [C] | - +----------+ +----------+ +----------+ - in: 0 in: 0 in: 0 - out: 1 out: 2 out: 3 - - -At this point, session `B` produces an error while processing *m2*, that is *m2* -becomes *e2*. *m1* is still in the pipeline, and *m3* is queued behind *m2*. -What ought to happen is that *m1* is handed off to the socket, then *m2* is -released to the driver, which will detect the error and begin closing the -socket. No further processing should be done on *m3* and it should not be -released to the driver after the error is emitted. - -To handle this, we allow errors to pass down the pipeline just like messages do, -to maintain ordering. But, once a cell sees its session produce an error, or it -receives an error from upstream, it should refuse to accept any further -messages. Session `B` might have begun processing *m3* by the time it produces -the error *e2*, but `C` will have been given *e2* before it receives *m3*, and -can simply drop *m3*. - -Now, say *e2* reaches the slow session `C` while *m1* is still present, -meanwhile *m3* has been dropped. `C` will never receive *m3* since it will have -been dropped upstream. Under the present model, its `out` counter will be `3` -but it is only going to emit two more values: *m1* and *e2*. In order for -closing to work, we need to decrement `out` to reflect this. The situation -should look like this: - - - +----------+ - | Pipeline | - +-----o----+ - | - +---------------+---------------+ - | | e2 | m1 - +-----o----+ +-----o----+ +-----o----+ - | Cell [A] | | Cell [B] | | Cell [C] | - +----------+ +----------+ +----------+ - in: 0 in: 0 in: 0 - out: 0 out: 0 out: 2 - - -When a cell sees its session emit an error, or when it receives an error from -upstream, it sets its pending count in the appropriate direction to equal the -number of messages it is *currently* processing. It will not accept any messages -after it sees the error, so this will allow the counter to reach zero. - -Note that while *e2* is in the pipeline, `Pipeline` should drop any further -messages in the outgoing direction, but should continue to accept incoming -messages. Until *e2* makes it out of the pipe to the driver, behind previous -successful messages, the driver does not know an error has happened, and a -message may arrive over the socket and make it all the way through the incoming -pipe in the meantime. We only halt processing in the affected direction to avoid -doing unnecessary work since messages arriving after an error should not be -processed. - -Some unnecessary work may happen, for example any messages already in the -pipeline following *m2* will be processed by `A`, since it's upstream of the -error. Those messages will be dropped by `B`. - - -## Alternative ideas - -I am considering implementing `Functor` as an object-mode transform stream -rather than what is essentially an async function. Being object-mode, a stream -would preserve message boundaries and would also possibly help address -back-pressure. I'm not sure whether this would require external API changes so -that such streams could be connected to the downstream driver's streams. - - -## Acknowledgements - -Credit is due to [@mnowster](https://github.com/mnowster) for helping with the -design and to [@fronx](https://github.com/fronx) for helping name things. diff --git a/frontend-old/node_modules/websocket-extensions/lib/pipeline/cell.js b/frontend-old/node_modules/websocket-extensions/lib/pipeline/cell.js deleted file mode 100644 index b2901ba..0000000 --- a/frontend-old/node_modules/websocket-extensions/lib/pipeline/cell.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -var Functor = require('./functor'), - Pledge = require('./pledge'); - -var Cell = function(tuple) { - this._ext = tuple[0]; - this._session = tuple[1]; - - this._functors = { - incoming: new Functor(this._session, 'processIncomingMessage'), - outgoing: new Functor(this._session, 'processOutgoingMessage') - }; -}; - -Cell.prototype.pending = function(direction) { - var functor = this._functors[direction]; - if (!functor._stopped) functor.pending += 1; -}; - -Cell.prototype.incoming = function(error, message, callback, context) { - this._exec('incoming', error, message, callback, context); -}; - -Cell.prototype.outgoing = function(error, message, callback, context) { - this._exec('outgoing', error, message, callback, context); -}; - -Cell.prototype.close = function() { - this._closed = this._closed || new Pledge(); - this._doClose(); - return this._closed; -}; - -Cell.prototype._exec = function(direction, error, message, callback, context) { - this._functors[direction].call(error, message, function(err, msg) { - if (err) err.message = this._ext.name + ': ' + err.message; - callback.call(context, err, msg); - this._doClose(); - }, this); -}; - -Cell.prototype._doClose = function() { - var fin = this._functors.incoming, - fout = this._functors.outgoing; - - if (!this._closed || fin.pending + fout.pending !== 0) return; - if (this._session) this._session.close(); - this._session = null; - this._closed.done(); -}; - -module.exports = Cell; diff --git a/frontend-old/node_modules/websocket-extensions/lib/pipeline/functor.js b/frontend-old/node_modules/websocket-extensions/lib/pipeline/functor.js deleted file mode 100644 index fadb49a..0000000 --- a/frontend-old/node_modules/websocket-extensions/lib/pipeline/functor.js +++ /dev/null @@ -1,72 +0,0 @@ -'use strict'; - -var RingBuffer = require('./ring_buffer'); - -var Functor = function(session, method) { - this._session = session; - this._method = method; - this._queue = new RingBuffer(Functor.QUEUE_SIZE); - this._stopped = false; - this.pending = 0; -}; - -Functor.QUEUE_SIZE = 8; - -Functor.prototype.call = function(error, message, callback, context) { - if (this._stopped) return; - - var record = { error: error, message: message, callback: callback, context: context, done: false }, - called = false, - self = this; - - this._queue.push(record); - - if (record.error) { - record.done = true; - this._stop(); - return this._flushQueue(); - } - - var handler = function(err, msg) { - if (!(called ^ (called = true))) return; - - if (err) { - self._stop(); - record.error = err; - record.message = null; - } else { - record.message = msg; - } - - record.done = true; - self._flushQueue(); - }; - - try { - this._session[this._method](message, handler); - } catch (err) { - handler(err); - } -}; - -Functor.prototype._stop = function() { - this.pending = this._queue.length; - this._stopped = true; -}; - -Functor.prototype._flushQueue = function() { - var queue = this._queue, record; - - while (queue.length > 0 && queue.peek().done) { - record = queue.shift(); - if (record.error) { - this.pending = 0; - queue.clear(); - } else { - this.pending -= 1; - } - record.callback.call(record.context, record.error, record.message); - } -}; - -module.exports = Functor; diff --git a/frontend-old/node_modules/websocket-extensions/lib/pipeline/index.js b/frontend-old/node_modules/websocket-extensions/lib/pipeline/index.js deleted file mode 100644 index 930bbc8..0000000 --- a/frontend-old/node_modules/websocket-extensions/lib/pipeline/index.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -var Cell = require('./cell'), - Pledge = require('./pledge'); - -var Pipeline = function(sessions) { - this._cells = sessions.map(function(session) { return new Cell(session) }); - this._stopped = { incoming: false, outgoing: false }; -}; - -Pipeline.prototype.processIncomingMessage = function(message, callback, context) { - if (this._stopped.incoming) return; - this._loop('incoming', this._cells.length - 1, -1, -1, message, callback, context); -}; - -Pipeline.prototype.processOutgoingMessage = function(message, callback, context) { - if (this._stopped.outgoing) return; - this._loop('outgoing', 0, this._cells.length, 1, message, callback, context); -}; - -Pipeline.prototype.close = function(callback, context) { - this._stopped = { incoming: true, outgoing: true }; - - var closed = this._cells.map(function(a) { return a.close() }); - if (callback) - Pledge.all(closed).then(function() { callback.call(context) }); -}; - -Pipeline.prototype._loop = function(direction, start, end, step, message, callback, context) { - var cells = this._cells, - n = cells.length, - self = this; - - while (n--) cells[n].pending(direction); - - var pipe = function(index, error, msg) { - if (index === end) return callback.call(context, error, msg); - - cells[index][direction](error, msg, function(err, m) { - if (err) self._stopped[direction] = true; - pipe(index + step, err, m); - }); - }; - pipe(start, null, message); -}; - -module.exports = Pipeline; diff --git a/frontend-old/node_modules/websocket-extensions/lib/pipeline/pledge.js b/frontend-old/node_modules/websocket-extensions/lib/pipeline/pledge.js deleted file mode 100644 index 8a1f45d..0000000 --- a/frontend-old/node_modules/websocket-extensions/lib/pipeline/pledge.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -var RingBuffer = require('./ring_buffer'); - -var Pledge = function() { - this._complete = false; - this._callbacks = new RingBuffer(Pledge.QUEUE_SIZE); -}; - -Pledge.QUEUE_SIZE = 4; - -Pledge.all = function(list) { - var pledge = new Pledge(), - pending = list.length, - n = pending; - - if (pending === 0) pledge.done(); - - while (n--) list[n].then(function() { - pending -= 1; - if (pending === 0) pledge.done(); - }); - return pledge; -}; - -Pledge.prototype.then = function(callback) { - if (this._complete) callback(); - else this._callbacks.push(callback); -}; - -Pledge.prototype.done = function() { - this._complete = true; - var callbacks = this._callbacks, callback; - while (callback = callbacks.shift()) callback(); -}; - -module.exports = Pledge; diff --git a/frontend-old/node_modules/websocket-extensions/lib/pipeline/ring_buffer.js b/frontend-old/node_modules/websocket-extensions/lib/pipeline/ring_buffer.js deleted file mode 100644 index 676ff94..0000000 --- a/frontend-old/node_modules/websocket-extensions/lib/pipeline/ring_buffer.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; - -var RingBuffer = function(bufferSize) { - this._bufferSize = bufferSize; - this.clear(); -}; - -RingBuffer.prototype.clear = function() { - this._buffer = new Array(this._bufferSize); - this._ringOffset = 0; - this._ringSize = this._bufferSize; - this._head = 0; - this._tail = 0; - this.length = 0; -}; - -RingBuffer.prototype.push = function(value) { - var expandBuffer = false, - expandRing = false; - - if (this._ringSize < this._bufferSize) { - expandBuffer = (this._tail === 0); - } else if (this._ringOffset === this._ringSize) { - expandBuffer = true; - expandRing = (this._tail === 0); - } - - if (expandBuffer) { - this._tail = this._bufferSize; - this._buffer = this._buffer.concat(new Array(this._bufferSize)); - this._bufferSize = this._buffer.length; - - if (expandRing) - this._ringSize = this._bufferSize; - } - - this._buffer[this._tail] = value; - this.length += 1; - if (this._tail < this._ringSize) this._ringOffset += 1; - this._tail = (this._tail + 1) % this._bufferSize; -}; - -RingBuffer.prototype.peek = function() { - if (this.length === 0) return void 0; - return this._buffer[this._head]; -}; - -RingBuffer.prototype.shift = function() { - if (this.length === 0) return void 0; - - var value = this._buffer[this._head]; - this._buffer[this._head] = void 0; - this.length -= 1; - this._ringOffset -= 1; - - if (this._ringOffset === 0 && this.length > 0) { - this._head = this._ringSize; - this._ringOffset = this.length; - this._ringSize = this._bufferSize; - } else { - this._head = (this._head + 1) % this._ringSize; - } - return value; -}; - -module.exports = RingBuffer; diff --git a/frontend-old/node_modules/websocket-extensions/lib/websocket_extensions.js b/frontend-old/node_modules/websocket-extensions/lib/websocket_extensions.js deleted file mode 100644 index 48adad8..0000000 --- a/frontend-old/node_modules/websocket-extensions/lib/websocket_extensions.js +++ /dev/null @@ -1,162 +0,0 @@ -'use strict'; - -var Parser = require('./parser'), - Pipeline = require('./pipeline'); - -var Extensions = function() { - this._rsv1 = this._rsv2 = this._rsv3 = null; - - this._byName = {}; - this._inOrder = []; - this._sessions = []; - this._index = {}; -}; - -Extensions.MESSAGE_OPCODES = [1, 2]; - -var instance = { - add: function(ext) { - if (typeof ext.name !== 'string') throw new TypeError('extension.name must be a string'); - if (ext.type !== 'permessage') throw new TypeError('extension.type must be "permessage"'); - - if (typeof ext.rsv1 !== 'boolean') throw new TypeError('extension.rsv1 must be true or false'); - if (typeof ext.rsv2 !== 'boolean') throw new TypeError('extension.rsv2 must be true or false'); - if (typeof ext.rsv3 !== 'boolean') throw new TypeError('extension.rsv3 must be true or false'); - - if (this._byName.hasOwnProperty(ext.name)) - throw new TypeError('An extension with name "' + ext.name + '" is already registered'); - - this._byName[ext.name] = ext; - this._inOrder.push(ext); - }, - - generateOffer: function() { - var sessions = [], - offer = [], - index = {}; - - this._inOrder.forEach(function(ext) { - var session = ext.createClientSession(); - if (!session) return; - - var record = [ext, session]; - sessions.push(record); - index[ext.name] = record; - - var offers = session.generateOffer(); - offers = offers ? [].concat(offers) : []; - - offers.forEach(function(off) { - offer.push(Parser.serializeParams(ext.name, off)); - }, this); - }, this); - - this._sessions = sessions; - this._index = index; - - return offer.length > 0 ? offer.join(', ') : null; - }, - - activate: function(header) { - var responses = Parser.parseHeader(header), - sessions = []; - - responses.eachOffer(function(name, params) { - var record = this._index[name]; - - if (!record) - throw new Error('Server sent an extension response for unknown extension "' + name + '"'); - - var ext = record[0], - session = record[1], - reserved = this._reserved(ext); - - if (reserved) - throw new Error('Server sent two extension responses that use the RSV' + - reserved[0] + ' bit: "' + - reserved[1] + '" and "' + ext.name + '"'); - - if (session.activate(params) !== true) - throw new Error('Server sent unacceptable extension parameters: ' + - Parser.serializeParams(name, params)); - - this._reserve(ext); - sessions.push(record); - }, this); - - this._sessions = sessions; - this._pipeline = new Pipeline(sessions); - }, - - generateResponse: function(header) { - var sessions = [], - response = [], - offers = Parser.parseHeader(header); - - this._inOrder.forEach(function(ext) { - var offer = offers.byName(ext.name); - if (offer.length === 0 || this._reserved(ext)) return; - - var session = ext.createServerSession(offer); - if (!session) return; - - this._reserve(ext); - sessions.push([ext, session]); - response.push(Parser.serializeParams(ext.name, session.generateResponse())); - }, this); - - this._sessions = sessions; - this._pipeline = new Pipeline(sessions); - - return response.length > 0 ? response.join(', ') : null; - }, - - validFrameRsv: function(frame) { - var allowed = { rsv1: false, rsv2: false, rsv3: false }, - ext; - - if (Extensions.MESSAGE_OPCODES.indexOf(frame.opcode) >= 0) { - for (var i = 0, n = this._sessions.length; i < n; i++) { - ext = this._sessions[i][0]; - allowed.rsv1 = allowed.rsv1 || ext.rsv1; - allowed.rsv2 = allowed.rsv2 || ext.rsv2; - allowed.rsv3 = allowed.rsv3 || ext.rsv3; - } - } - - return (allowed.rsv1 || !frame.rsv1) && - (allowed.rsv2 || !frame.rsv2) && - (allowed.rsv3 || !frame.rsv3); - }, - - processIncomingMessage: function(message, callback, context) { - this._pipeline.processIncomingMessage(message, callback, context); - }, - - processOutgoingMessage: function(message, callback, context) { - this._pipeline.processOutgoingMessage(message, callback, context); - }, - - close: function(callback, context) { - if (!this._pipeline) return callback.call(context); - this._pipeline.close(callback, context); - }, - - _reserve: function(ext) { - this._rsv1 = this._rsv1 || (ext.rsv1 && ext.name); - this._rsv2 = this._rsv2 || (ext.rsv2 && ext.name); - this._rsv3 = this._rsv3 || (ext.rsv3 && ext.name); - }, - - _reserved: function(ext) { - if (this._rsv1 && ext.rsv1) return [1, this._rsv1]; - if (this._rsv2 && ext.rsv2) return [2, this._rsv2]; - if (this._rsv3 && ext.rsv3) return [3, this._rsv3]; - return false; - } -}; - -for (var key in instance) - Extensions.prototype[key] = instance[key]; - -module.exports = Extensions; diff --git a/frontend-old/node_modules/websocket-extensions/package.json b/frontend-old/node_modules/websocket-extensions/package.json deleted file mode 100644 index e4f2f91..0000000 --- a/frontend-old/node_modules/websocket-extensions/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "websocket-extensions", - "description": "Generic extension manager for WebSocket connections", - "homepage": "http://github.com/faye/websocket-extensions-node", - "author": "James Coglan (http://jcoglan.com/)", - "keywords": [ - "websocket" - ], - "license": "Apache-2.0", - "version": "0.1.4", - "engines": { - "node": ">=0.8.0" - }, - "files": [ - "lib" - ], - "main": "./lib/websocket_extensions", - "devDependencies": { - "jstest": "*" - }, - "scripts": { - "test": "jstest spec/runner.js" - }, - "repository": { - "type": "git", - "url": "git://github.com/faye/websocket-extensions-node.git" - }, - "bugs": "http://github.com/faye/websocket-extensions-node/issues" -} -- cgit v1.2.3