@bbk47/toolbox 1.0.7 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +4 -0
- package/lib/proxy.js +62 -0
- package/lib/server.js +61 -0
- package/lib/timeout.js +3 -0
- package/lib/transport/creater.js +64 -0
- package/lib/transport/helper.js +62 -0
- package/lib/transport/index.js +11 -0
- package/lib/transport/transport.js +38 -0
- package/package.json +3 -2
package/lib/index.js
CHANGED
|
@@ -6,3 +6,7 @@ exports.uuid = require('./uuid');
|
|
|
6
6
|
exports.retry = require('./retry');
|
|
7
7
|
exports.deferred = require('./deferred');
|
|
8
8
|
exports.merge = require('./merge');
|
|
9
|
+
exports.timeout = require('./timeout');
|
|
10
|
+
exports.transport = require('./transport');
|
|
11
|
+
exports.proxy = require('./proxy');
|
|
12
|
+
exports.server = require('./server');
|
package/lib/proxy.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const net = require('net');
|
|
2
|
+
const socks5 = require('./socks5');
|
|
3
|
+
|
|
4
|
+
exports.createSocks5Proxy = function (cSock, onConnect) {
|
|
5
|
+
var stage = 'INIT';
|
|
6
|
+
cSock.on('data', function dataListener(data) {
|
|
7
|
+
if (stage === 'INIT') {
|
|
8
|
+
cSock.write('\x05\x00');
|
|
9
|
+
stage = 'ADDR';
|
|
10
|
+
return;
|
|
11
|
+
} else if (stage === 'ADDR') {
|
|
12
|
+
onConnect(data.slice(3), (err) => {
|
|
13
|
+
if (!err) {
|
|
14
|
+
stage = 'STREAM';
|
|
15
|
+
cSock.write('\x05\x00\x00\x01\x00\x00\x00\x00\x00\x00');
|
|
16
|
+
cSock.removeAllListeners('data');
|
|
17
|
+
cSock.pause(); // for pipe start stream
|
|
18
|
+
} else {
|
|
19
|
+
cSock.destroy();
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
cSock.on('error', function (error) {
|
|
27
|
+
cSock.destroy();
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
exports.createConnectProxy = function (cSock, onConnect) {
|
|
32
|
+
var stage = 'INIT';
|
|
33
|
+
cSock.on('data', (data) => {
|
|
34
|
+
if (stage === 'INIT') {
|
|
35
|
+
const str = data.toString('ascii');
|
|
36
|
+
const lines = str.split(/\s/g);
|
|
37
|
+
if (lines[0] !== 'CONNECT') {
|
|
38
|
+
cSock.destroy();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const hoststr = lines[1];
|
|
42
|
+
const reqhost = hoststr.split(':');
|
|
43
|
+
const hostname = reqhost[0];
|
|
44
|
+
const port = Number(reqhost[1]);
|
|
45
|
+
const socksAddrInfo = socks5.buildSocks5Addr(hostname, port);
|
|
46
|
+
onConnect(socksAddrInfo, (err) => {
|
|
47
|
+
if (!err) {
|
|
48
|
+
cSock.write(Buffer.from('HTTP/1.1 200 Connection Established\r\n\r\n'));
|
|
49
|
+
stage = 'STREAM';
|
|
50
|
+
cSock.removeAllListeners('data');
|
|
51
|
+
cSock.pause(); // for pipe start stream
|
|
52
|
+
} else {
|
|
53
|
+
cSock.destroy();
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
cSock.on('error', function (error) {
|
|
60
|
+
cSock.destroy();
|
|
61
|
+
});
|
|
62
|
+
};
|
package/lib/server.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const net = require('net');
|
|
2
|
+
const http = require('http');
|
|
3
|
+
const tls = require('tls');
|
|
4
|
+
const http2 = require('http2');
|
|
5
|
+
const url = require('url');
|
|
6
|
+
const WebSocket = require('ws');
|
|
7
|
+
|
|
8
|
+
exports.createWsServer = function (workPath, handler, httpHandler) {
|
|
9
|
+
const server = http.createServer(function (req, res) {
|
|
10
|
+
if (httpHandler) {
|
|
11
|
+
httpHandler(req, res);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
const wss = new WebSocket.Server({ noServer: true, clientTracking: false });
|
|
15
|
+
wss.on('connection', function (wsconn) {
|
|
16
|
+
handler(wsconn);
|
|
17
|
+
});
|
|
18
|
+
server.on('upgrade', function (request, socket, head) {
|
|
19
|
+
const pathname = url.parse(request.url).pathname;
|
|
20
|
+
if (pathname === workPath) {
|
|
21
|
+
wss.handleUpgrade(request, socket, head, function done(ws) {
|
|
22
|
+
wss.emit('connection', ws, request);
|
|
23
|
+
});
|
|
24
|
+
} else {
|
|
25
|
+
socket.destroy();
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
return server;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
exports.createHttp2Server = function (tlsOpts, workPath, handler, httpHandler) {
|
|
32
|
+
const http2Opts = Object.assign({ allowHTTP1: true }, tlsOpts);
|
|
33
|
+
const server = http2.createSecureServer(http2Opts, function (req, res) {
|
|
34
|
+
if (httpHandler) {
|
|
35
|
+
httpHandler(req, res);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
server.on('stream', function (stream, headers) {
|
|
39
|
+
const path = headers[':path'];
|
|
40
|
+
if (path === workPath) {
|
|
41
|
+
handler(stream);
|
|
42
|
+
} else {
|
|
43
|
+
stream.destroy();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return server;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
exports.createTcpServer = function (handler) {
|
|
50
|
+
const server = net.createServer(function (conn) {
|
|
51
|
+
handler(conn);
|
|
52
|
+
});
|
|
53
|
+
return server;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
exports.createTlsServer = function (tlsOpts, handler) {
|
|
57
|
+
const server = tls.createServer(tlsOpts, function (conn) {
|
|
58
|
+
handler(conn);
|
|
59
|
+
});
|
|
60
|
+
return server;
|
|
61
|
+
};
|
package/lib/timeout.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const WebSocket = require('ws');
|
|
2
|
+
const net = require('net');
|
|
3
|
+
const http2 = require('http2');
|
|
4
|
+
const tls = require('tls');
|
|
5
|
+
|
|
6
|
+
const Transport = require('./transport');
|
|
7
|
+
|
|
8
|
+
exports.createWebsocketTransport = function (params, onOpen) {
|
|
9
|
+
let tunnelWsUrl = `${params.secure ? 'wss' : 'ws'}://${params.host}:${params.port}${params.path}`;
|
|
10
|
+
const ws = new WebSocket(tunnelWsUrl, { perMessageDeflate: false, handshakeTimeout: 3000 });
|
|
11
|
+
const ts = new Transport({ type: 'ws', conn: ws });
|
|
12
|
+
ws.on('open', onOpen);
|
|
13
|
+
return ts;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
exports.createHttp2Transport = function (params, onOpen) {
|
|
17
|
+
const http2Url = `https://${params.host}:${params.port}`;
|
|
18
|
+
const client = http2.connect(http2Url, {
|
|
19
|
+
rejectUnauthorized: false,
|
|
20
|
+
requestCert: true,
|
|
21
|
+
});
|
|
22
|
+
const http2stream = client.request({
|
|
23
|
+
':method': 'POST',
|
|
24
|
+
':path': params.path || '/',
|
|
25
|
+
'Content-Type': 'octet-stream',
|
|
26
|
+
});
|
|
27
|
+
http2stream.on('response', onOpen);
|
|
28
|
+
const ts = new Transport({ type: 'h2', conn: http2stream });
|
|
29
|
+
return ts;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
exports.createTlsTransport = function (params, onOpen) {
|
|
33
|
+
const tlsOpts = {
|
|
34
|
+
rejectUnauthorized: false,
|
|
35
|
+
host: params.host,
|
|
36
|
+
port: params.port,
|
|
37
|
+
};
|
|
38
|
+
const tlsConn = tls.connect(tlsOpts, function () {
|
|
39
|
+
onOpen();
|
|
40
|
+
});
|
|
41
|
+
const ts = new Transport({ type: 'tls', conn: tlsConn });
|
|
42
|
+
return ts;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
exports.createTcpTransport = function (params, onOpen) {
|
|
46
|
+
const socket = new net.Socket();
|
|
47
|
+
socket.connect(params.port, params.host, function () {
|
|
48
|
+
onOpen();
|
|
49
|
+
});
|
|
50
|
+
return new Transport({ type: 'tcp', conn: socket });
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
exports.createUnixsocketTransport = function (params, onOpen) {
|
|
54
|
+
const socket = new net.Socket();
|
|
55
|
+
socket.connect(params.path, function () {
|
|
56
|
+
onOpen();
|
|
57
|
+
});
|
|
58
|
+
const ts = new Transport({ type: 'domainsocket', conn: socket });
|
|
59
|
+
return ts;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
exports.wrapSocket = function (type, conn) {
|
|
63
|
+
return new Transport({ type, conn });
|
|
64
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const WebSocket = require('ws');
|
|
2
|
+
|
|
3
|
+
function bindStreamSocket(stream, onData, onError, onClose) {
|
|
4
|
+
var buffcache = Buffer.from([]);
|
|
5
|
+
stream.on('data', function (data) {
|
|
6
|
+
buffcache = Buffer.concat([buffcache, data]);
|
|
7
|
+
var datalen = 0;
|
|
8
|
+
var pack;
|
|
9
|
+
while (true) {
|
|
10
|
+
if (buffcache.length <= 2) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
datalen = buffcache[0] * 256 + buffcache[1];
|
|
14
|
+
if (buffcache.length < datalen + 2) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
pack = buffcache.slice(2, datalen + 2);
|
|
18
|
+
buffcache = buffcache.slice(datalen + 2);
|
|
19
|
+
onData(pack);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
stream.on('close', function (code) {
|
|
23
|
+
onClose(code);
|
|
24
|
+
});
|
|
25
|
+
stream.on('error', function (err) {
|
|
26
|
+
stream.destroy();
|
|
27
|
+
onError(err);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function bindWebsocket(ws, onData, onError, onClose) {
|
|
32
|
+
ws.on('message', onData);
|
|
33
|
+
ws.on('close', (code) => {
|
|
34
|
+
onClose(code);
|
|
35
|
+
});
|
|
36
|
+
ws.on('error', (err) => {
|
|
37
|
+
ws.close();
|
|
38
|
+
onError(err);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function tcpsocketSend(socket, data) {
|
|
43
|
+
var datalen = data.length;
|
|
44
|
+
if (socket.writable) {
|
|
45
|
+
socket.write(Buffer.concat([Buffer.from([datalen >> 8, datalen % 256]), data]));
|
|
46
|
+
} else {
|
|
47
|
+
throw Error('socket cannot writeable!');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function websocketSend(ws, data) {
|
|
52
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
53
|
+
ws.send(data, { binary: true });
|
|
54
|
+
} else {
|
|
55
|
+
throw Error('ws socket not open!' + ws.readyState);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
exports.websocketSend = websocketSend;
|
|
60
|
+
exports.tcpsocketSend = tcpsocketSend;
|
|
61
|
+
exports.bindStreamSocket = bindStreamSocket;
|
|
62
|
+
exports.bindWebsocket = bindWebsocket;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const Transport = require('./transport');
|
|
2
|
+
const creater = require('./creater');
|
|
3
|
+
const helper = require('./helper');
|
|
4
|
+
|
|
5
|
+
exports.Transport = Transport;
|
|
6
|
+
exports.creater = creater;
|
|
7
|
+
exports.helper = helper;
|
|
8
|
+
|
|
9
|
+
exports.wrapSocket = function (type, conn) {
|
|
10
|
+
return new Transport({ type, conn });
|
|
11
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const { websocketSend, tcpsocketSend, bindWebsocket, bindStreamSocket } = require('./helper');
|
|
2
|
+
|
|
3
|
+
class Transport {
|
|
4
|
+
constructor(opts) {
|
|
5
|
+
this.type = opts.type;
|
|
6
|
+
this.conn = opts.conn;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
sendPacket(binarydata) {
|
|
10
|
+
if (this.type === 'ws') {
|
|
11
|
+
websocketSend(this.conn, binarydata);
|
|
12
|
+
} else {
|
|
13
|
+
tcpsocketSend(this.conn, binarydata);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
bindEvents(onData, onError, onClose) {
|
|
18
|
+
if (this.type === 'ws') {
|
|
19
|
+
bindWebsocket(this.conn, onData, onError, onClose);
|
|
20
|
+
} else {
|
|
21
|
+
bindStreamSocket(this.conn, onData, onError, onClose);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
close() {
|
|
26
|
+
try {
|
|
27
|
+
if (this.type === 'ws' || this.type === 'h2') {
|
|
28
|
+
this.conn.close();
|
|
29
|
+
} else {
|
|
30
|
+
this.conn.destroy();
|
|
31
|
+
}
|
|
32
|
+
} catch (err) {
|
|
33
|
+
// ignore
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = Transport;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bbk47/toolbox",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "toolbox for bbk",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
},
|
|
18
18
|
"homepage": "https://github.com/bbk47/toolboxjs#readme",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"date-format": "^3.0.0"
|
|
20
|
+
"date-format": "^3.0.0",
|
|
21
|
+
"ws": "2.3.x"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
23
24
|
"mocha": "^5.2.0"
|