proxy-protocol-js
Version:
A PROXY protocol builder and parser for JavaScript
162 lines • 6.63 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.V1BinaryProxyProtocolParseError = exports.V1BinaryProxyProtocol = void 0;
var util_1 = require("util");
var INETProtocol_1 = require("./enum/INETProtocol");
var Peer_1 = require("./Peer");
var V1BinaryProxyProtocol = (function () {
function V1BinaryProxyProtocol(inetProtocol, source, destination, data) {
this.inetProtocol = inetProtocol;
this.source = source;
this.destination = destination;
this.data = data;
}
V1BinaryProxyProtocol.prototype.build = function () {
var proto = Buffer.from("PROXY ".concat(this.inetProtocol, " ").concat(this.source.ipAddress, " ").concat(this.destination.ipAddress, " ").concat(this.source.port, " ").concat(this.destination.port, "\r\n"), 'utf8');
return this.data ? Buffer.concat([proto, this.data]) : proto;
};
V1BinaryProxyProtocol.parse = function (input) {
return new V1BinaryProxyProtocolParser(input).parse();
};
V1BinaryProxyProtocol.isValidProtocolSignature = function (input) {
try {
new V1BinaryProxyProtocolParser(input).matchSignature();
}
catch (err) {
return false;
}
return true;
};
return V1BinaryProxyProtocol;
}());
exports.V1BinaryProxyProtocol = V1BinaryProxyProtocol;
var V1BinaryProxyProtocolParseError = (function () {
function V1BinaryProxyProtocolParseError(message) {
this.message = message;
this.name = this.constructor.name;
}
return V1BinaryProxyProtocolParseError;
}());
exports.V1BinaryProxyProtocolParseError = V1BinaryProxyProtocolParseError;
var V1BinaryProxyProtocolParser = (function () {
function V1BinaryProxyProtocolParser(input) {
this.input = input;
this.cursor = -1;
}
V1BinaryProxyProtocolParser.prototype.parse = function () {
this.matchSignature();
var inetProtocol = this.getINETProtocol();
var srcAddr = this.getIPAddress();
var dstAddr = this.getIPAddress();
var srcPort = this.getSrcPort();
var dstPort = this.getDstPort();
var data = this.getData();
return new V1BinaryProxyProtocol(inetProtocol, new Peer_1.Peer(srcAddr, srcPort), new Peer_1.Peer(dstAddr, dstPort), data);
};
V1BinaryProxyProtocolParser.prototype.matchSignature = function () {
for (var i = 0; i < V1BinaryProxyProtocolParser.protocolSignature.length; i++) {
if (this.next() !== V1BinaryProxyProtocolParser.protocolSignature[i]) {
throw new V1BinaryProxyProtocolParseError("doesn't match with protocol signature");
}
}
};
V1BinaryProxyProtocolParser.prototype.getINETProtocol = function () {
var inetProtocolArray = [];
while (true) {
var b = this.next();
if (b === V1BinaryProxyProtocolParser.whitespace) {
break;
}
inetProtocolArray.push(this.current());
}
switch (new util_1.TextDecoder('utf8').decode(Uint8Array.from(inetProtocolArray))) {
case INETProtocol_1.INETProtocol.TCP4:
return INETProtocol_1.INETProtocol.TCP4;
case INETProtocol_1.INETProtocol.TCP6:
return INETProtocol_1.INETProtocol.TCP6;
case INETProtocol_1.INETProtocol.UNKNOWN:
return INETProtocol_1.INETProtocol.UNKNOWN;
default:
throw new V1BinaryProxyProtocolParseError('unexpected INET protocol has come');
}
};
V1BinaryProxyProtocolParser.prototype.getIPAddress = function () {
var addrArray = [];
while (true) {
var b = this.next();
if (b === V1BinaryProxyProtocolParser.whitespace) {
break;
}
addrArray.push(b);
}
if (addrArray.length <= 0) {
throw new V1BinaryProxyProtocolParseError('address information is missing');
}
return new util_1.TextDecoder('utf8').decode(Uint8Array.from(addrArray));
};
V1BinaryProxyProtocolParser.prototype.getPort = function (isTerminated) {
var i = 0;
var portArray = [];
while (true) {
var b = this.next();
if (isTerminated(b)) {
break;
}
var num = b - V1BinaryProxyProtocolParser.zeroChar;
if (num < 0 || num > 9) {
throw new V1BinaryProxyProtocolParseError('invalid port information has come');
}
portArray[i++] = num;
}
if (portArray.length <= 0) {
throw new V1BinaryProxyProtocolParseError('port information is missing');
}
var port = 0;
var coef = 1;
for (var _i = 0, _a = portArray.reverse(); _i < _a.length; _i++) {
var num = _a[_i];
port += num * coef;
coef *= 10;
}
return port;
};
V1BinaryProxyProtocolParser.prototype.getSrcPort = function () {
return this.getPort(function (b) { return b === V1BinaryProxyProtocolParser.whitespace; });
};
V1BinaryProxyProtocolParser.prototype.getDstPort = function () {
var _this = this;
return this.getPort(function (b) {
if (b === V1BinaryProxyProtocolParser.cr) {
if (_this.next() === V1BinaryProxyProtocolParser.lf) {
return true;
}
throw new V1BinaryProxyProtocolParseError('invalid port information has come');
}
return false;
});
};
V1BinaryProxyProtocolParser.prototype.getData = function () {
var data = this.input.slice(++this.cursor);
if (data.length <= 0) {
return new Uint8Array();
}
return data;
};
V1BinaryProxyProtocolParser.prototype.current = function () {
return this.input[this.cursor];
};
V1BinaryProxyProtocolParser.prototype.next = function () {
var b = this.input[++this.cursor];
if (b === undefined) {
throw new V1BinaryProxyProtocolParseError('protocol payload has been terminated unexpectedly');
}
return b;
};
V1BinaryProxyProtocolParser.protocolSignature = Buffer.from('PROXY ', 'utf8');
V1BinaryProxyProtocolParser.whitespace = 0x20;
V1BinaryProxyProtocolParser.lf = 0x0a;
V1BinaryProxyProtocolParser.cr = 0x0d;
V1BinaryProxyProtocolParser.zeroChar = 0x30;
return V1BinaryProxyProtocolParser;
}());
//# sourceMappingURL=V1BinaryProxyProtocol.js.map