bdy 1.8.3-dev → 1.8.4-dev
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/distTs/bin/cli.js +5 -0
- package/distTs/src/agent/linux.js +119 -0
- package/distTs/src/agent/manager.js +395 -0
- package/distTs/src/agent/osx.js +139 -0
- package/distTs/src/agent/socket/tunnel.js +212 -0
- package/distTs/src/agent/socket.js +220 -0
- package/distTs/src/agent/system.js +177 -0
- package/distTs/src/agent/wait.js +23 -0
- package/distTs/src/agent/windows.js +159 -0
- package/distTs/src/agent.js +237 -0
- package/distTs/src/api/agent.js +84 -0
- package/distTs/src/api/buddy.js +117 -0
- package/distTs/src/api/socket.js +133 -0
- package/distTs/src/cfg.js +238 -0
- package/distTs/src/command/agent/install.js +106 -0
- package/distTs/src/command/agent/restart.js +27 -0
- package/distTs/src/command/agent/run.js +19 -0
- package/distTs/src/command/agent/start.js +28 -0
- package/distTs/src/command/agent/status.js +35 -0
- package/distTs/src/command/agent/stop.js +28 -0
- package/distTs/src/command/agent/tunnel/http.js +44 -0
- package/distTs/src/command/agent/tunnel/list.js +27 -0
- package/distTs/src/command/agent/tunnel/remove.js +28 -0
- package/distTs/src/command/agent/tunnel/start.js +34 -0
- package/distTs/src/command/agent/tunnel/status.js +31 -0
- package/distTs/src/command/agent/tunnel/tcp.js +43 -0
- package/distTs/src/command/agent/tunnel/tls.js +43 -0
- package/distTs/src/command/agent/tunnel.js +23 -0
- package/distTs/src/command/agent/uninstall.js +38 -0
- package/distTs/src/command/agent/update.js +38 -0
- package/distTs/src/command/agent/version.js +21 -0
- package/distTs/src/command/agent.js +29 -0
- package/distTs/src/command/config/add/http.js +25 -0
- package/distTs/src/command/config/add/tcp.js +25 -0
- package/distTs/src/command/config/add/tls.js +25 -0
- package/distTs/src/command/config/add.js +15 -0
- package/distTs/src/command/config/get/region.js +15 -0
- package/distTs/src/command/config/get/timeout.js +15 -0
- package/distTs/src/command/config/get/token.js +15 -0
- package/distTs/src/command/config/get/tunnel.js +19 -0
- package/distTs/src/command/config/get/tunnels.js +15 -0
- package/distTs/src/command/config/get/whitelist.js +15 -0
- package/distTs/src/command/config/get.js +21 -0
- package/distTs/src/command/config/remove/tunnel.js +19 -0
- package/distTs/src/command/config/remove.js +11 -0
- package/distTs/src/command/config/set/region.js +17 -0
- package/distTs/src/command/config/set/timeout.js +17 -0
- package/distTs/src/command/config/set/token.js +16 -0
- package/distTs/src/command/config/set/whitelist.js +17 -0
- package/distTs/src/command/config/set.js +17 -0
- package/distTs/src/command/config.js +17 -0
- package/distTs/src/command/http.js +30 -0
- package/distTs/src/command/pre.js +49 -0
- package/distTs/src/command/start.js +28 -0
- package/distTs/src/command/tcp.js +30 -0
- package/distTs/src/command/tls.js +30 -0
- package/distTs/src/command/version.js +13 -0
- package/distTs/src/command/vt/close.js +28 -0
- package/distTs/src/command/vt/exec.js +79 -0
- package/distTs/src/command/vt/storybook.js +90 -0
- package/distTs/src/command/vt.js +15 -0
- package/distTs/src/format.js +172 -0
- package/distTs/src/index.js +40 -0
- package/distTs/src/input.js +286 -0
- package/distTs/src/logger.js +93 -0
- package/distTs/src/output/interactive/tunnel.js +860 -0
- package/distTs/src/output/noninteractive/agent/tunnels.js +43 -0
- package/distTs/src/output/noninteractive/config/tunnel.js +67 -0
- package/distTs/src/output/noninteractive/config/tunnels.js +18 -0
- package/distTs/src/output/noninteractive/tunnel.js +59 -0
- package/distTs/src/output.js +138 -0
- package/distTs/src/server/cert.js +52 -0
- package/distTs/src/server/http1.js +74 -0
- package/distTs/src/server/http2.js +74 -0
- package/distTs/src/server/sftp.js +487 -0
- package/distTs/src/server/ssh.js +112 -0
- package/distTs/src/server/tls.js +41 -0
- package/distTs/src/ssh/client.js +191 -0
- package/distTs/src/texts.js +345 -0
- package/distTs/src/tunnel/agent.js +100 -0
- package/distTs/src/tunnel/compression.js +41 -0
- package/distTs/src/tunnel/dns.js +54 -0
- package/distTs/src/tunnel/html.js +30 -0
- package/distTs/src/tunnel/http/log.js +196 -0
- package/distTs/src/tunnel/http/serve.js +132 -0
- package/distTs/src/tunnel/http/stream.js +45 -0
- package/distTs/src/tunnel/http.js +405 -0
- package/distTs/src/tunnel/identification.js +96 -0
- package/distTs/src/tunnel/latency.js +71 -0
- package/distTs/src/tunnel/tcp.js +92 -0
- package/distTs/src/tunnel.js +647 -0
- package/distTs/src/types/ciInfo.js +10 -0
- package/distTs/src/types/options.js +2 -0
- package/distTs/src/types/plugin.js +2 -0
- package/distTs/src/types/queue.js +2 -0
- package/distTs/src/types/requests.js +2 -0
- package/distTs/src/types/resources.js +2 -0
- package/distTs/src/types/snapshots.js +2 -0
- package/distTs/src/types/storybook.js +2 -0
- package/distTs/src/utils.js +437 -0
- package/distTs/src/visualTest/browser.js +32 -0
- package/distTs/src/visualTest/ci.js +206 -0
- package/distTs/src/visualTest/context.js +44 -0
- package/distTs/src/visualTest/exec.js +51 -0
- package/distTs/src/visualTest/queue.js +43 -0
- package/distTs/src/visualTest/requests.js +197 -0
- package/distTs/src/visualTest/resources.js +195 -0
- package/distTs/src/visualTest/server.js +33 -0
- package/distTs/src/visualTest/snapshots.js +109 -0
- package/distTs/src/visualTest/utils/parseDom.js +238 -0
- package/distTs/src/visualTest/validation.js +18 -0
- package/package.json +1 -1
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const system_1 = __importDefault(require("./system"));
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const fs_1 = require("fs");
|
|
10
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
11
|
+
const texts_1 = require("../texts");
|
|
12
|
+
class AgentWindows extends system_1.default {
|
|
13
|
+
hasAdminRights() {
|
|
14
|
+
return new Promise((resolve) => {
|
|
15
|
+
(0, child_process_1.exec)('net session', (err) => {
|
|
16
|
+
resolve(!err);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
isSupported() {
|
|
21
|
+
return Promise.resolve(process.arch === 'x64');
|
|
22
|
+
}
|
|
23
|
+
isEnabled() {
|
|
24
|
+
return new Promise((resolve) => {
|
|
25
|
+
this.sc('query bdy')
|
|
26
|
+
.then(() => {
|
|
27
|
+
resolve(true);
|
|
28
|
+
})
|
|
29
|
+
.catch(() => {
|
|
30
|
+
resolve(false);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
getBinaryArchive() {
|
|
35
|
+
return 'win-x64.zip';
|
|
36
|
+
}
|
|
37
|
+
getSystemConfigDir() {
|
|
38
|
+
return 'C:\\ProgramData\\bdy';
|
|
39
|
+
}
|
|
40
|
+
getSystemConfigPath() {
|
|
41
|
+
return path_1.default.join(this.getSystemConfigDir(), 'agent.json');
|
|
42
|
+
}
|
|
43
|
+
getNssmArchivePath() {
|
|
44
|
+
return path_1.default.join(this.getSystemConfigDir(), 'nssm.zip');
|
|
45
|
+
}
|
|
46
|
+
downloadNssm() {
|
|
47
|
+
return this.downloadFile('https://es.buddy.works/bdy/nssm.zip', this.getNssmArchivePath());
|
|
48
|
+
}
|
|
49
|
+
extractNssm() {
|
|
50
|
+
return this.extractArchive(this.getNssmArchivePath(), this.getSystemConfigDir());
|
|
51
|
+
}
|
|
52
|
+
clearNssmExtract() {
|
|
53
|
+
(0, fs_1.rmSync)(path_1.default.join(this.getSystemConfigDir(), '__MACOSX'), {
|
|
54
|
+
force: true,
|
|
55
|
+
recursive: true,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
getNssmBinaryPath() {
|
|
59
|
+
return path_1.default.join(this.getSystemConfigDir(), 'nssm', 'win64', 'nssm.exe');
|
|
60
|
+
}
|
|
61
|
+
getSystemBinaryPath() {
|
|
62
|
+
return path_1.default.join(this.getSystemConfigDir(), 'bdy.exe');
|
|
63
|
+
}
|
|
64
|
+
clearSystemFiles() {
|
|
65
|
+
(0, fs_1.rmSync)(this.getSystemBinaryPath(), { force: true });
|
|
66
|
+
(0, fs_1.rmSync)(this.getSystemConfigPath(), { force: true });
|
|
67
|
+
(0, fs_1.rmSync)(path_1.default.join(this.getSystemConfigDir(), 'nssm'), {
|
|
68
|
+
force: true,
|
|
69
|
+
recursive: true,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async update() {
|
|
73
|
+
try {
|
|
74
|
+
logger_1.default.info(texts_1.LOG_AGENT_STOPPING_SYSTEM);
|
|
75
|
+
await this.nssm('stop bdy');
|
|
76
|
+
logger_1.default.info(texts_1.LOG_AGENT_SYSTEM_DIR);
|
|
77
|
+
await this.ensureSystemConfigDir();
|
|
78
|
+
logger_1.default.info(texts_1.LOG_AGENT_DOWNLOADING_ARCHIVE);
|
|
79
|
+
await this.downloadBinaryArchive();
|
|
80
|
+
logger_1.default.info(texts_1.LOG_AGENT_EXTRACTING_ARCHIVE);
|
|
81
|
+
await this.extractBinaryArchive();
|
|
82
|
+
try {
|
|
83
|
+
logger_1.default.info(texts_1.LOG_AGENT_STARTING_SYSTEM);
|
|
84
|
+
await this.nssm('start bdy');
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// do nothing, it will throw operation pending
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
logger_1.default.error(err);
|
|
92
|
+
throw err;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async enable(id, host, token, port, start, user, pass, debug) {
|
|
96
|
+
try {
|
|
97
|
+
logger_1.default.info(texts_1.LOG_AGENT_SYSTEM_DIR);
|
|
98
|
+
await this.ensureSystemConfigDir();
|
|
99
|
+
logger_1.default.info(texts_1.LOG_AGENT_NSSM_DOWNLOADING);
|
|
100
|
+
await this.downloadNssm();
|
|
101
|
+
logger_1.default.info(texts_1.LOG_AGENT_NSSM_EXTRACTING);
|
|
102
|
+
await this.extractNssm();
|
|
103
|
+
logger_1.default.info(texts_1.LOG_AGENT_NSSM_CLEARING);
|
|
104
|
+
this.clearNssmExtract();
|
|
105
|
+
logger_1.default.info(texts_1.LOG_AGENT_DOWNLOADING_ARCHIVE);
|
|
106
|
+
await this.downloadBinaryArchive();
|
|
107
|
+
logger_1.default.info(texts_1.LOG_AGENT_EXTRACTING_ARCHIVE);
|
|
108
|
+
await this.extractBinaryArchive();
|
|
109
|
+
logger_1.default.info(texts_1.LOG_AGENT_ENABLING_SYSTEM);
|
|
110
|
+
await this.nssm(`install bdy ${this.getSystemBinaryPath()}`);
|
|
111
|
+
await this.nssm(`set bdy AppParameters agent run --id="${id}" --host="${host}" --token="${token}" --port=${port} --start=${!!start}`);
|
|
112
|
+
await this.nssm('set bdy DisplayName Buddy Tunnel Agent');
|
|
113
|
+
await this.nssm('set bdy AppThrottle 5000');
|
|
114
|
+
await this.nssm('set bdy AppRestartDelay 0');
|
|
115
|
+
await this.nssm('set bdy AppExit Default Restart');
|
|
116
|
+
await this.nssm('set bdy Start SERVICE_AUTO_START');
|
|
117
|
+
await this.nssm(`set bdy AppEnvironmentExtra DEBUG=${debug ? 1 : 0}`);
|
|
118
|
+
if (user && pass) {
|
|
119
|
+
await this.nssm(`set bdy ObjectName ${user} ${pass}`);
|
|
120
|
+
}
|
|
121
|
+
this.nssm('start bdy').then().catch();
|
|
122
|
+
logger_1.default.info(texts_1.LOG_AGENT_ENABLED);
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
logger_1.default.info(err);
|
|
126
|
+
throw err;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async disable() {
|
|
130
|
+
try {
|
|
131
|
+
await this.nssm('stop bdy');
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// do nothing
|
|
135
|
+
}
|
|
136
|
+
await this.nssm('remove bdy confirm');
|
|
137
|
+
}
|
|
138
|
+
nssm(cmd) {
|
|
139
|
+
return new Promise((resolve, reject) => {
|
|
140
|
+
(0, child_process_1.exec)(`${this.getNssmBinaryPath()} ${cmd}`, (err, stdout, stderr) => {
|
|
141
|
+
if (!err)
|
|
142
|
+
resolve(stdout, stderr);
|
|
143
|
+
else
|
|
144
|
+
reject(err, stderr);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
sc(cmd) {
|
|
149
|
+
return new Promise((resolve, reject) => {
|
|
150
|
+
(0, child_process_1.exec)(`sc ${cmd}`, (err, stdout, stderr) => {
|
|
151
|
+
if (!err)
|
|
152
|
+
resolve(stdout, stderr);
|
|
153
|
+
else
|
|
154
|
+
reject(err, stderr);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
exports.default = AgentWindows;
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const events_1 = __importDefault(require("events"));
|
|
7
|
+
const logger_js_1 = __importDefault(require("./logger.js"));
|
|
8
|
+
const texts_js_1 = require("./texts.js");
|
|
9
|
+
const utils_js_1 = require("./utils.js");
|
|
10
|
+
const tunnel_js_1 = __importDefault(require("./tunnel.js"));
|
|
11
|
+
const output_js_1 = __importDefault(require("./output.js"));
|
|
12
|
+
const socket_1 = __importDefault(require("./api/socket"));
|
|
13
|
+
class Agent extends events_1.default {
|
|
14
|
+
constructor(id, host, token, service, api) {
|
|
15
|
+
super();
|
|
16
|
+
this.id = id;
|
|
17
|
+
this.host = host;
|
|
18
|
+
this.token = token;
|
|
19
|
+
this.service = service;
|
|
20
|
+
this.tunnels = [];
|
|
21
|
+
this.started = false;
|
|
22
|
+
this.api = api;
|
|
23
|
+
this.manager = null;
|
|
24
|
+
this.onRefresh = null;
|
|
25
|
+
this.socket = new socket_1.default(host, id, token);
|
|
26
|
+
this.socket.on(utils_js_1.SOCKET_IO_EVENT_FETCH_SUCCESS, (data) => this._onSocketFetch(data));
|
|
27
|
+
this.socket.on(utils_js_1.SOCKET_IO_EVENT_FETCH_FAILED, (err) => this._onSocketFetchFailed(err));
|
|
28
|
+
this.socket.on(utils_js_1.SOCKET_IO_EVENT_CONNECTED, () => this._onSocketConnected());
|
|
29
|
+
this.socket.on(utils_js_1.SOCKET_IO_EVENT_DISCONNECTED, () => this._onSocketDisconnected());
|
|
30
|
+
this.socket.on(utils_js_1.SOCKET_IO_EVENT_TUNNEL, (tunnel, action) => this._onSocketTunnel(tunnel, action));
|
|
31
|
+
this.socket.on(utils_js_1.SOCKET_IO_EVENT_AGENT, (agent, action) => this._onSocketAgent(agent, action));
|
|
32
|
+
}
|
|
33
|
+
_onSocketTunnel(data, action) {
|
|
34
|
+
if (action === 'DEL') {
|
|
35
|
+
this.destroyTunnel(data.id);
|
|
36
|
+
if (!this.service && this.tunnels.length <= 0)
|
|
37
|
+
output_js_1.default.exitError(texts_js_1.ERR_TUNNEL_REMOVED);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
logger_js_1.default.debug('Socket fetch tunnel after sync push');
|
|
41
|
+
this.socket.fetch(this.started, null, false, []);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async _onSocketAgent(data, action) {
|
|
45
|
+
if (action === 'DEL') {
|
|
46
|
+
if (this.manager)
|
|
47
|
+
return this.manager.disableAgentAndExit(texts_js_1.ERR_AGENT_REMOVED);
|
|
48
|
+
output_js_1.default.exitError(texts_js_1.ERR_AGENT_REMOVED);
|
|
49
|
+
}
|
|
50
|
+
else if (data.action) {
|
|
51
|
+
try {
|
|
52
|
+
await this.makeAction(data.action);
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
logger_js_1.default.error('Agent sync error');
|
|
56
|
+
logger_js_1.default.error(err);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
_onSocketConnected() {
|
|
61
|
+
if (this.onRefresh)
|
|
62
|
+
this.onRefresh(true);
|
|
63
|
+
}
|
|
64
|
+
_onSocketDisconnected() {
|
|
65
|
+
if (this.onRefresh)
|
|
66
|
+
this.onRefresh(false);
|
|
67
|
+
}
|
|
68
|
+
async _onSocketFetch(data) {
|
|
69
|
+
try {
|
|
70
|
+
if (data.agent.action)
|
|
71
|
+
await this.makeAction(data.agent.action);
|
|
72
|
+
this.refreshTunnels(data.tunnels || []);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
logger_js_1.default.error('Fetch error');
|
|
76
|
+
logger_js_1.default.error(err);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
_onSocketFetchFailed(err) {
|
|
80
|
+
if (err instanceof utils_js_1.ApiErrorAgentNotFound) {
|
|
81
|
+
if (this.manager)
|
|
82
|
+
return this.manager.disableAgentAndExit(texts_js_1.ERR_AGENT_REMOVED);
|
|
83
|
+
output_js_1.default.exitError(texts_js_1.ERR_AGENT_REMOVED);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
logger_js_1.default.error(texts_js_1.LOG_ERROR_WHILE_REFRESHING_AGENT);
|
|
87
|
+
logger_js_1.default.error(err);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
startRefreshingConfiguration(onRefresh) {
|
|
91
|
+
this.onRefresh = onRefresh;
|
|
92
|
+
if (this.onRefresh)
|
|
93
|
+
this.onRefresh(this.socket.connected);
|
|
94
|
+
this.refreshIn15();
|
|
95
|
+
}
|
|
96
|
+
async start() {
|
|
97
|
+
this.started = true;
|
|
98
|
+
this.tunnels.forEach((t) => {
|
|
99
|
+
t.start();
|
|
100
|
+
});
|
|
101
|
+
this.socket.fetch(this.started, '', true, this.getTunnelsUpdate());
|
|
102
|
+
}
|
|
103
|
+
async stop(clearAction = true) {
|
|
104
|
+
this.started = false;
|
|
105
|
+
this.tunnels.forEach((t) => {
|
|
106
|
+
t.stop();
|
|
107
|
+
});
|
|
108
|
+
this.socket.fetch(this.started, clearAction ? '' : null, false, this.getTunnelsUpdate());
|
|
109
|
+
}
|
|
110
|
+
async restart() {
|
|
111
|
+
await this.stop(false);
|
|
112
|
+
await this.start();
|
|
113
|
+
}
|
|
114
|
+
async delete() {
|
|
115
|
+
try {
|
|
116
|
+
await this.api.unregister(this.id, this.host, this.token);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// do nothing
|
|
120
|
+
}
|
|
121
|
+
process.exit(0);
|
|
122
|
+
}
|
|
123
|
+
refreshIn15(fetch = true) {
|
|
124
|
+
setTimeout(async () => {
|
|
125
|
+
if (fetch)
|
|
126
|
+
this.socket.fetch(this.started, null, false, this.getTunnelsUpdate());
|
|
127
|
+
else
|
|
128
|
+
this.update();
|
|
129
|
+
this.refreshIn15(false);
|
|
130
|
+
}, 15000);
|
|
131
|
+
}
|
|
132
|
+
httpRequest(tunnelId, logRequest) {
|
|
133
|
+
this.socket.request(tunnelId, logRequest);
|
|
134
|
+
}
|
|
135
|
+
update(force = false) {
|
|
136
|
+
this.socket.update(this.started, this.getTunnelsUpdate(), force);
|
|
137
|
+
}
|
|
138
|
+
async makeAction(action) {
|
|
139
|
+
if (action === utils_js_1.AGENT_ACTION_STOP) {
|
|
140
|
+
if (this.manager)
|
|
141
|
+
return this.manager.agentStop();
|
|
142
|
+
else
|
|
143
|
+
return this.stop();
|
|
144
|
+
}
|
|
145
|
+
if (action === utils_js_1.AGENT_ACTION_START) {
|
|
146
|
+
if (this.manager)
|
|
147
|
+
return this.manager.agentStart();
|
|
148
|
+
else
|
|
149
|
+
return this.start();
|
|
150
|
+
}
|
|
151
|
+
if (action === utils_js_1.AGENT_ACTION_RESTART) {
|
|
152
|
+
if (this.manager)
|
|
153
|
+
return this.manager.agentRestart();
|
|
154
|
+
else
|
|
155
|
+
return this.restart();
|
|
156
|
+
}
|
|
157
|
+
if (action === utils_js_1.AGENT_ACTION_DELETE) {
|
|
158
|
+
if (this.manager)
|
|
159
|
+
return this.manager.disableAgentAndExit(texts_js_1.ERR_AGENT_REMOVED);
|
|
160
|
+
else
|
|
161
|
+
return this.delete();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
refreshTunnels(tunnels) {
|
|
165
|
+
const tt = this.tunnels;
|
|
166
|
+
const hasTunnels = tt.length > 0;
|
|
167
|
+
const haveTunnels = tunnels.length > 0;
|
|
168
|
+
if (hasTunnels) {
|
|
169
|
+
tt.forEach((tunnel) => {
|
|
170
|
+
if (!tunnels.find((t) => t.id === tunnel.id)) {
|
|
171
|
+
this.destroyTunnel(tunnel.id);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
if (haveTunnels) {
|
|
176
|
+
tunnels.forEach((data) => {
|
|
177
|
+
let sshHostKey;
|
|
178
|
+
if (this.manager)
|
|
179
|
+
sshHostKey = this.manager.sshHostKey;
|
|
180
|
+
const tunnel = tt.find((tunnel) => data.id === tunnel.id);
|
|
181
|
+
if (!tunnel) {
|
|
182
|
+
this.addTunnel(new tunnel_js_1.default({
|
|
183
|
+
...data,
|
|
184
|
+
sshHostKey,
|
|
185
|
+
}));
|
|
186
|
+
}
|
|
187
|
+
else if (tunnel.hasChanged(data)) {
|
|
188
|
+
tunnel.recreate(data);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
if (!this.service && hasTunnels && !haveTunnels) {
|
|
193
|
+
output_js_1.default.exitError(texts_js_1.ERR_TUNNEL_REMOVED);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
getTunnelsUpdate() {
|
|
197
|
+
const update = [];
|
|
198
|
+
this.tunnels.forEach((t) => {
|
|
199
|
+
update.push({
|
|
200
|
+
id: t.id,
|
|
201
|
+
active: t.status === utils_js_1.TUNNEL_OPEN,
|
|
202
|
+
regionLatency: t.regionLatency ? t.regionLatency.latency : -1,
|
|
203
|
+
targetLatency: t.targetLatency ? t.targetLatency.latency : -1,
|
|
204
|
+
totalConnections: t.totalConnections,
|
|
205
|
+
currentConnections: Object.keys(t.connections).length,
|
|
206
|
+
httpIdentified: t.identify ? t.identify.type : '',
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
return update;
|
|
210
|
+
}
|
|
211
|
+
addTunnel(tunnel) {
|
|
212
|
+
this.tunnels.push(tunnel);
|
|
213
|
+
if (this.started)
|
|
214
|
+
tunnel.start();
|
|
215
|
+
tunnel.on(utils_js_1.TUNNEL_EVENT_OPEN, () => this.update(true));
|
|
216
|
+
tunnel.on(utils_js_1.TUNNEL_EVENT_CLOSED, () => this.update());
|
|
217
|
+
tunnel.on(utils_js_1.TUNNEL_EVENT_TCP_OPEN, () => this.update());
|
|
218
|
+
tunnel.on(utils_js_1.TUNNEL_EVENT_TCP_CLOSED, () => this.update());
|
|
219
|
+
tunnel.on(utils_js_1.TUNNEL_EVENT_TLS_OPEN, () => this.update());
|
|
220
|
+
tunnel.on(utils_js_1.TUNNEL_EVENT_TLS_CLOSED, () => this.update());
|
|
221
|
+
tunnel.on(utils_js_1.TUNNEL_EVENT_HTTP_IDENTIFIED, () => this.update());
|
|
222
|
+
tunnel.on(utils_js_1.TUNNEL_EVENT_HTTP_OPEN, () => this.update());
|
|
223
|
+
tunnel.on(utils_js_1.TUNNEL_EVENT_HTTP_CLOSED, () => this.update());
|
|
224
|
+
tunnel.on(utils_js_1.TUNNEL_EVENT_STOPPED, () => this.update());
|
|
225
|
+
tunnel.on(utils_js_1.TUNNEL_EVENT_HTTP_REQUEST, (t, logRequest) => this.httpRequest(t.id, logRequest));
|
|
226
|
+
}
|
|
227
|
+
destroyTunnel(id) {
|
|
228
|
+
let tunnel = this.tunnels.find((t) => t.id === id);
|
|
229
|
+
if (!tunnel)
|
|
230
|
+
return null;
|
|
231
|
+
this.tunnels = this.tunnels.filter((t) => t.id !== tunnel.id);
|
|
232
|
+
tunnel.stop();
|
|
233
|
+
tunnel.removeAllListeners();
|
|
234
|
+
return tunnel;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
exports.default = Agent;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const logger_js_1 = __importDefault(require("../logger.js"));
|
|
7
|
+
const texts_js_1 = require("../texts.js");
|
|
8
|
+
const ws_1 = require("ws");
|
|
9
|
+
const TIMEOUT = 120000;
|
|
10
|
+
const openSocket = (port, path) => {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
const ws = new ws_1.WebSocket(`ws://localhost:${port}${path}`);
|
|
13
|
+
ws.on('error', () => {
|
|
14
|
+
reject(new Error(texts_js_1.ERR_FAILED_TO_CONNECT_TO_AGENT));
|
|
15
|
+
});
|
|
16
|
+
ws.on('open', () => {
|
|
17
|
+
resolve(ws);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
const makeRequest = async (port, path, body) => {
|
|
22
|
+
const c = new AbortController();
|
|
23
|
+
setTimeout(() => {
|
|
24
|
+
c.abort();
|
|
25
|
+
}, TIMEOUT);
|
|
26
|
+
const response = await fetch(`http://localhost:${port}${path}`, {
|
|
27
|
+
body: body ? JSON.stringify(body) : null,
|
|
28
|
+
headers: { 'Content-Type': 'application/json' },
|
|
29
|
+
method: 'POST',
|
|
30
|
+
signal: c.signal,
|
|
31
|
+
});
|
|
32
|
+
if (response.status === 404) {
|
|
33
|
+
throw new Error(texts_js_1.ERR_NOT_FOUND);
|
|
34
|
+
}
|
|
35
|
+
if (response.status === 400) {
|
|
36
|
+
const data = await response.json();
|
|
37
|
+
throw new Error(data.message);
|
|
38
|
+
}
|
|
39
|
+
if (response.status !== 200) {
|
|
40
|
+
throw new Error(texts_js_1.ERR_SWW);
|
|
41
|
+
}
|
|
42
|
+
let data;
|
|
43
|
+
try {
|
|
44
|
+
data = await response.json();
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
logger_js_1.default.error(texts_js_1.LOG_ERROR);
|
|
48
|
+
logger_js_1.default.error(err);
|
|
49
|
+
throw new Error(texts_js_1.ERR_FAILED_TO_CONNECT_TO_AGENT);
|
|
50
|
+
}
|
|
51
|
+
return data;
|
|
52
|
+
};
|
|
53
|
+
class ApiAgent {
|
|
54
|
+
constructor(port) {
|
|
55
|
+
this.port = port;
|
|
56
|
+
}
|
|
57
|
+
async fetchStatus() {
|
|
58
|
+
return makeRequest(this.port, '/status');
|
|
59
|
+
}
|
|
60
|
+
async addTunnel(data) {
|
|
61
|
+
return makeRequest(this.port, '/tunnel/add', data);
|
|
62
|
+
}
|
|
63
|
+
async fetchTunnels() {
|
|
64
|
+
return makeRequest(this.port, '/tunnels');
|
|
65
|
+
}
|
|
66
|
+
async stopTunnel(id) {
|
|
67
|
+
return makeRequest(this.port, '/tunnel/stop', {
|
|
68
|
+
id,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
async startAgent() {
|
|
72
|
+
return makeRequest(this.port, '/agent/start');
|
|
73
|
+
}
|
|
74
|
+
async restartAgent() {
|
|
75
|
+
return makeRequest(this.port, '/agent/restart');
|
|
76
|
+
}
|
|
77
|
+
async stopAgent() {
|
|
78
|
+
return makeRequest(this.port, '/agent/stop');
|
|
79
|
+
}
|
|
80
|
+
async socketTunnel(id) {
|
|
81
|
+
return openSocket(this.port, `/tunnel?id=${encodeURIComponent(id)}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.default = ApiAgent;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const https_1 = require("https");
|
|
7
|
+
const tunnel_js_1 = __importDefault(require("../tunnel.js"));
|
|
8
|
+
const logger_js_1 = __importDefault(require("../logger.js"));
|
|
9
|
+
const agent_js_1 = __importDefault(require("../agent.js"));
|
|
10
|
+
const utils_1 = require("../utils");
|
|
11
|
+
const texts_js_1 = require("../texts.js");
|
|
12
|
+
const TIMEOUT = 120000;
|
|
13
|
+
const nodeFetch = (url, opts) => {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
import('node-fetch')
|
|
16
|
+
.then(({ default: fetch }) => {
|
|
17
|
+
fetch(url, opts).then(resolve).catch(reject);
|
|
18
|
+
})
|
|
19
|
+
.catch(reject);
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
const makeRequest = async (host, path, body, method = 'POST', respAsJson = true, timeout = TIMEOUT) => {
|
|
23
|
+
let data;
|
|
24
|
+
try {
|
|
25
|
+
const c = new AbortController();
|
|
26
|
+
setTimeout(() => {
|
|
27
|
+
c.abort();
|
|
28
|
+
}, timeout);
|
|
29
|
+
const response = await nodeFetch(`${host}${path}`, {
|
|
30
|
+
body: body ? JSON.stringify(body) : null,
|
|
31
|
+
headers: body ? { 'Content-Type': 'application/json' } : null,
|
|
32
|
+
method,
|
|
33
|
+
signal: c.signal,
|
|
34
|
+
agent: new https_1.Agent({
|
|
35
|
+
rejectUnauthorized: false,
|
|
36
|
+
}),
|
|
37
|
+
});
|
|
38
|
+
if (respAsJson)
|
|
39
|
+
data = await response.json();
|
|
40
|
+
else
|
|
41
|
+
data = await response.text();
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
throw new utils_1.ApiErrorFailedToConnect(host);
|
|
45
|
+
}
|
|
46
|
+
if (respAsJson) {
|
|
47
|
+
if (data.code !== 200) {
|
|
48
|
+
throw (0, utils_1.apiErrorCodeToClass)(data.result.code, host);
|
|
49
|
+
}
|
|
50
|
+
return data.result;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
return data;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
class ApiBuddyClass {
|
|
57
|
+
async register(service, host, token, onDefaultRegion) {
|
|
58
|
+
const version = (0, utils_1.getVersion)();
|
|
59
|
+
const hostname = (0, utils_1.getHostname)();
|
|
60
|
+
const platform = (0, utils_1.getPlatform)();
|
|
61
|
+
logger_js_1.default.info(texts_js_1.LOG_REGISTERING_AGENT);
|
|
62
|
+
const r = await makeRequest(host, '/tunnel/agent/add', {
|
|
63
|
+
token,
|
|
64
|
+
version,
|
|
65
|
+
hostname,
|
|
66
|
+
platform,
|
|
67
|
+
service,
|
|
68
|
+
});
|
|
69
|
+
logger_js_1.default.info((0, texts_js_1.LOG_AGENT_REGISTERED)(r.id));
|
|
70
|
+
logger_js_1.default.info((0, texts_js_1.LOG_REGION_DETECTED)(r.region));
|
|
71
|
+
if (onDefaultRegion)
|
|
72
|
+
onDefaultRegion(r.region);
|
|
73
|
+
return new agent_js_1.default(r.id, host, r.token, service, this);
|
|
74
|
+
}
|
|
75
|
+
async unregister(id, host, token) {
|
|
76
|
+
logger_js_1.default.info(texts_js_1.LOG_UNREGISTERING_AGENT);
|
|
77
|
+
await makeRequest(host, '/tunnel/agent/remove', {
|
|
78
|
+
token,
|
|
79
|
+
id,
|
|
80
|
+
});
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
async fetchAgent(id, host, token) {
|
|
84
|
+
logger_js_1.default.info(texts_js_1.LOG_GETTING_AGENT);
|
|
85
|
+
const r = await makeRequest(host, '/tunnel/agent/fetch', {
|
|
86
|
+
token,
|
|
87
|
+
id,
|
|
88
|
+
});
|
|
89
|
+
return new agent_js_1.default(r.id, host, token, r.service, this);
|
|
90
|
+
}
|
|
91
|
+
async addTunnel(agentId, host, token, prepared, sshHostKey) {
|
|
92
|
+
logger_js_1.default.info(texts_js_1.LOG_REGISTERING_TUNNEL);
|
|
93
|
+
const config = await makeRequest(host, '/tunnel/add', {
|
|
94
|
+
...prepared,
|
|
95
|
+
token,
|
|
96
|
+
agentId,
|
|
97
|
+
});
|
|
98
|
+
logger_js_1.default.info((0, texts_js_1.LOG_TUNNEL_REGISTERED)(config.id));
|
|
99
|
+
return new tunnel_js_1.default({
|
|
100
|
+
...config,
|
|
101
|
+
sshHostKey,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
async removeTunnel(agentId, tunnelId, host, token) {
|
|
105
|
+
logger_js_1.default.info(texts_js_1.LOG_REMOVING_TUNNEL);
|
|
106
|
+
await makeRequest(host, '/tunnel/remove', {
|
|
107
|
+
agentId,
|
|
108
|
+
tunnelId,
|
|
109
|
+
token,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
async fetchMyIp() {
|
|
113
|
+
return makeRequest('https://es.buddy.works', '/ip', null, 'GET', false);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const ApiBuddy = new ApiBuddyClass();
|
|
117
|
+
exports.default = ApiBuddy;
|