Skip to content

fix: 重新实现socket.io-stream,修复依赖的npm package debug安全问题 #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@
"dependencies": {
"@tencent-sdk/capi": "^0.2.15-alpha.0",
"dijkstrajs": "^1.0.1",
"dot-qs": "0.2.0",
"duplexify": "^4.1.1",
"end-of-stream": "^1.4.4",
"https-proxy-agent": "^5.0.0",
"socket.io-client": "^2.3.0",
"socket.io-stream": "^0.9.1",
"winston": "^3.2.1",
"dot-qs": "0.2.0"
"component-bind": "~1.0.0",
"debug": "~2.6.9",
"winston": "^3.2.1"
},
"devDependencies": {
"babel-eslint": "9.0.0",
Expand All @@ -36,4 +37,4 @@
"eslint-plugin-prettier": "^3.0.1",
"prettier": "^1.18.2"
}
}
}
2 changes: 1 addition & 1 deletion sdk/debug/lib/wshub-client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ var __spreadArrays = (this && this.__spreadArrays) || function () {
};
Object.defineProperty(exports, "__esModule", { value: true });
var socketIo = require("socket.io-client");
var socketIoStream = require("socket.io-stream");
var socketIoStream = require("../wshub-socket.io-stream");
var net_1 = require("net");
var wshub_bipipe_1 = require("../wshub-bipipe");
var wshub_proxy_1 = require("../wshub-proxy");
Expand Down
64 changes: 64 additions & 0 deletions sdk/debug/lib/wshub-socket.io-stream/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
var Socket = require('./socket');
var IOStream = require('./iostream');


exports = module.exports = lookup;

/**
* Expose Node Buffer for browser.
*
* @api public
*/
exports.Buffer = Buffer;

/**
* Expose Socket constructor.
*
* @api public
*/
exports.Socket = Socket;

/**
* Expose IOStream constructor.
*
* @api public
*/
exports.IOStream = IOStream;

/**
* Forces base 64 encoding when emitting. Must be set to true for Socket.IO v0.9 or lower.
*
* @api public
*/
exports.forceBase64 = false;

/**
* Look up an existing Socket.
*
* @param {socket.io#Socket} socket.io
* @param {Object} options
* @return {Socket} Socket instance
* @api public
*/
function lookup(sio, options) {
options = options || {};
if (null == options.forceBase64) {
options.forceBase64 = exports.forceBase64;
}

if (!sio._streamSocket) {
sio._streamSocket = new Socket(sio, options);
}
return sio._streamSocket;
}

/**
* Creates a new duplex stream.
*
* @param {Object} options
* @return {IOStream} duplex stream
* @api public
*/
exports.createStream = function(options) {
return new IOStream(options);
};
265 changes: 265 additions & 0 deletions sdk/debug/lib/wshub-socket.io-stream/iostream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
var util = require('util');
var Duplex = require('stream').Duplex;
var bind = require('component-bind');
var uuid = require('./uuid');
var debug = require('debug')('socket.io-stream:iostream');


module.exports = IOStream;

util.inherits(IOStream, Duplex);

/**
* Duplex
*
* @param {Object} options
* @api private
*/
function IOStream(options) {
if (!(this instanceof IOStream)) {
return new IOStream(options);
}

IOStream.super_.call(this, options);

this.options = options;
this.id = uuid();
this.socket = null;

// Buffers
this.pushBuffer = [];
this.writeBuffer = [];

// Op states
this._readable = false;
this._writable = false;
this.destroyed = false;

// default to *not* allowing half open sockets
this.allowHalfOpen = options && options.allowHalfOpen || false;

this.on('finish', this._onfinish);
this.on('end', this._onend);
this.on('error', this._onerror);
}

/**
* Ensures that no more I/O activity happens on this stream.
* Not necessary in the usual case.
*
* @api public
*/
IOStream.prototype.destroy = function() {
debug('destroy');

if (this.destroyed) {
debug('already destroyed');
return;
}

this.readable = this.writable = false;

if (this.socket) {
debug('clean up');
this.socket.cleanup(this.id);
this.socket = null;
}

this.destroyed = true;
};

/**
* Local read
*
* @api private
*/
IOStream.prototype._read = function(size) {
var push;

// We can not read from the socket if it's destroyed obviously ...
if (this.destroyed) return;

if (this.pushBuffer.length) {
// flush buffer and end if it exists.
while (push = this.pushBuffer.shift()) {
if (!push()) break;
}
return;
}

this._readable = true;

// Go get data from remote stream
// Calls
// ._onread remotely
// then
// ._onwrite locally
this.socket._read(this.id, size);
};


/**
* Read from remote stream
*
* @api private
*/
IOStream.prototype._onread = function(size) {
var write = this.writeBuffer.shift();
if (write) return write();

this._writable = true;
};

/**
* Write local data to remote stream
* Calls
* remtote ._onwrite
*
* @api private
*/
IOStream.prototype._write = function(chunk, encoding, callback) {
var self = this;

function write() {
// We can not write to the socket if it's destroyed obviously ...
if (self.destroyed) return;

self._writable = false;
self.socket._write(self.id, chunk, encoding, callback);
}

if (this._writable) {
write();
} else {
this.writeBuffer.push(write);
}
};

/**
* Write the data fetched remotely
* so that we can now read locally
*
* @api private
*/
IOStream.prototype._onwrite = function(chunk, encoding, callback) {
var self = this;

function push() {
self._readable = false;
var ret = self.push(chunk || '', encoding);
callback();
return ret;
}

if (this._readable) {
push();
} else {
this.pushBuffer.push(push);
}
};

/**
* When ending send 'end' event to remote stream
*
* @api private
*/
IOStream.prototype._end = function() {
if (this.pushBuffer.length) {
// end after flushing buffer.
this.pushBuffer.push(bind(this, '_done'));
} else {
this._done();
}
};

/**
* Remote stream just ended
*
* @api private
*/
IOStream.prototype._done = function() {
this._readable = false;

// signal the end of the data.
return this.push(null);
};

/**
* the user has called .end(), and all the bytes have been
* sent out to the other side.
* If allowHalfOpen is false, or if the readable side has
* ended already, then destroy.
* If allowHalfOpen is true, then we need to set writable false,
* so that only the writable side will be cleaned up.
*
* @api private
*/
IOStream.prototype._onfinish = function() {
debug('_onfinish');
// Local socket just finished
// send 'end' event to remote
if (this.socket) {
this.socket._end(this.id);
}

this.writable = false;
this._writableState.ended = true;

if (!this.readable || this._readableState.ended) {
debug('_onfinish: ended, destroy %s', this._readableState);
return this.destroy();
}

debug('_onfinish: not ended');

if (!this.allowHalfOpen) {
this.push(null);

// just in case we're waiting for an EOF.
if (this.readable && !this._readableState.endEmitted) {
this.read(0);
}
}
};

/**
* the EOF has been received, and no more bytes are coming.
* if the writable side has ended already, then clean everything
* up.
*
* @api private
*/
IOStream.prototype._onend = function() {
debug('_onend');
this.readable = false;
this._readableState.ended = true;

if (!this.writable || this._writableState.finished) {
debug('_onend: %s', this._writableState);
return this.destroy();
}

debug('_onend: not finished');

if (!this.allowHalfOpen) {
this.end();
}
};

/**
* When error in local stream
* notyify remote
* if err.remote = true
* then error happened on remote stream
*
* @api private
*/
IOStream.prototype._onerror = function(err) {
// check if the error came from remote stream.
if (!err.remote && this.socket) {
// notify the error to the corresponding remote stream.
this.socket._error(this.id, err);
}

this.destroy();
};
Loading