Skip to content

Instantly share code, notes, and snippets.

@webcarrot
Last active May 28, 2018 09:34
Show Gist options
  • Select an option

  • Save webcarrot/353c2f275ab234f5dc68f9c7b32d40ea to your computer and use it in GitHub Desktop.

Select an option

Save webcarrot/353c2f275ab234f5dc68f9c7b32d40ea to your computer and use it in GitHub Desktop.
nodejs http2 pre-read connection stream wrapper
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _stream = require("stream");
const kWait = Symbol("wait");
const kNread = Symbol("nread");
const kSocket = Symbol("socket");
const kBuffer = Symbol("buffer");
class SocketProxy extends _stream.Duplex {
constructor(socket, buffer) {
super({
allowHalfOpen: true,
decodeStrings: false
});
this[kWait] = true;
this[kNread] = -1;
this[kSocket] = socket;
this[kBuffer] = buffer;
const handleError = () => this.destroy();
const handleData = chunk => this._checkSocket() && this.addChunk(chunk);
socket.addListener("error", handleError);
socket.addListener("data", handleData);
socket.once("close", err => this.emit("close", err));
socket.once("end", () => {
this[kWait] = false;
this.tryRead();
this.emit("end");
this.destroy();
});
}
_checkSocket() {
const socket = this[kSocket];
if (socket && !socket.destroyed) {
return true;
} else if (socket) {
this[kWait] = false;
delete this[kSocket];
delete this[kBuffer];
}
return false;
}
_write(data, encoding, cb) {
if (this._checkSocket()) {
try {
this[kSocket].write(data, encoding);
cb();
} catch (err) {
cb(err);
}
} else {
cb();
}
}
_destroy(e, cb) {
if (this[kSocket]) {
this[kWait] = false;
this[kNread] = -1;
if (!this[kSocket].destroyed) {
this[kSocket].destroy();
}
delete this[kSocket];
delete this[kBuffer];
}
cb();
}
_read(nread) {
if (this._checkSocket()) {
if (this[kBuffer] && this[kBuffer].length > 0) {
const data = this[kBuffer].slice(0, nread);
this[kBuffer] = this[kBuffer].slice(nread);
return this.push(data);
} else if (this[kWait]) {
this[kNread] = nread;
} else {
return this.push(null);
}
}
}
addChunk(chunk) {
this[kBuffer] = Buffer.concat([this[kBuffer], chunk]);
this.tryRead();
}
tryRead() {
const nread = this[kNread];
if (nread !== -1) {
this[kNread] = -1;
this._read(nread);
}
}
get remoteAddress() {
return this._checkSocket() && this[kSocket].remoteAddress;
}
get remotePort() {
return this._checkSocket() && this[kSocket].remotePort;
}
setTimeout(timeout, callback) {
return this._checkSocket() && this[kSocket].setTimeout(timeout, callback);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment