Skip to content
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
15 changes: 13 additions & 2 deletions proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import http from "http";
import https from "https";
import httpProxy from "http-proxy";
import { getNodeList, listen, Node, Action, cleanUpNode } from "./discovery";
import { TcpClient } from "./socket";
import { Console } from "console";

const HTTPS_PORT = 443;
const HTTP_PORT = Number(process.env.PORT || 80);
Expand All @@ -12,8 +14,9 @@ const SOCKET_TIMEOUT = Number(process.env.SOCKET_TIMEOUT || 30000); // 30 second
const processIds: { [id: string]: httpProxy } = {}

let currProxy: number = 0;
const proxies: httpProxy[] = [];

const proxies: httpProxy[] = [];
const clients: TcpClient[] = [];
http.globalAgent = new http.Agent({ keepAlive: true });
https.globalAgent = new https.Agent({ keepAlive: true });

Expand Down Expand Up @@ -85,6 +88,15 @@ function register(node: Node) {
proxies.push(proxy);

currProxy = proxies.length - 1;
const client = new TcpClient(+port, host);
clients.push(client)
client.on("close",()=>{
console.warn(`node ${node.processId}/${node.address} close, unregistering`);
unregister(node)
cleanUpNode(node)
clients.splice(clients.indexOf(client), 1);
})

}

function unregister(node: Node) {
Expand All @@ -94,7 +106,6 @@ function unregister(node: Node) {
if(idx > -1) {
proxies.splice(proxies.indexOf(proxy), 1);
delete processIds[node.processId];

currProxy = proxies.length - 1;
}
}
Expand Down
91 changes: 91 additions & 0 deletions socket.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import * as net from "net";
import { EventEmitter } from "events";

function connectCb1(){ return }

export class TcpClient extends EventEmitter {
die: boolean = false;
remoteAddress: string = "";
socket: net.Socket;
maxLen: number;
len: number = 0;
buffer: Buffer = Buffer.allocUnsafe(0);

constructor(port: number, host: string, maxLen: number=5, noDelay: boolean = false, connectCb: () => void = connectCb1) {
super();
this.socket = net.connect(port, host, () => {
this.remoteAddress = this.socket.remoteAddress as string;
connectCb();
});
this.socket.setNoDelay(noDelay);
this.maxLen = maxLen;
this.socket.on("close", (err) => {
if (!this.die) {
this.die = true;
this.emit("close", err);
}
});
this.socket.on("error", (err) => {
if (!this.die) {
this.die = true;
this.emit("close", err);
}
});
this.socket.on("data", (data) => {
if (!this.die) {
} else {
this.close();
}
});
}

send(data: Buffer) {
this.socket.write(data);
}

close() {
this.socket.destroy();
this.socket.emit("close");
}
}


/**
* Unpack
*/
export function decode(socket: TcpClient, msg: Buffer) {
let readLen = 0;
while (readLen < msg.length) {
if (socket.len === 0) //data length is unknown
{
socket.buffer = Buffer.concat([socket.buffer, Buffer.from([msg[readLen]])]);
if (socket.buffer.length === 4) {
socket.len = socket.buffer.readUInt32BE(0);
if (socket.len > socket.maxLen || socket.len === 0) {
socket.close();
throw new Error("socket data length is longer then " + socket.maxLen + ", close it, " + socket.remoteAddress);
return;
}
socket.buffer = Buffer.allocUnsafe(socket.len);
}
readLen++;
}
else if (msg.length - readLen < socket.len) // data not coming all
{
msg.copy(socket.buffer, socket.buffer.length - socket.len, readLen);
socket.len -= (msg.length - readLen);
readLen = msg.length;
}
else {
msg.copy(socket.buffer, socket.buffer.length - socket.len, readLen, readLen + socket.len);

readLen += socket.len;
socket.len = 0;
let data = socket.buffer;
socket.buffer = Buffer.allocUnsafe(0);

//data coming all
socket.emit("data", data);
}
}
}
9 changes: 6 additions & 3 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
{
"compilerOptions": {
"target": "es5",
"outDir": "lib",
"target": "es6",
"module": "commonjs",
"strict": true,
"esModuleInterop": true
"strict": false,
"esModuleInterop": true,
"sourceMap": true,
"experimentalDecorators": true
},
"include": [
"**.ts"
Expand Down