pinggy 0.6.0 → 0.6.3
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/ARCHITECTURE.md +335 -10
- package/CLAUDE.md +20 -2
- package/README.md +90 -0
- package/dist/TunnelManager-NGSUBZYI.js +13 -0
- package/dist/{TunnelTui-OZ6AVGTY.js → TunnelTui-UCG2YSLX.js} +6 -18
- package/dist/{chunk-I4HXBP5G.js → chunk-7EQKHVQX.js} +34 -2
- package/dist/{chunk-GBYF2H4H.js → chunk-AFMTIELL.js} +4 -0
- package/dist/{chunk-2HGC37SK.js → chunk-GESMZQHI.js} +47 -119
- package/dist/{chunk-76SOSXXR.js → chunk-MV56U3E6.js} +2 -2
- package/dist/{chunk-MT44NAXX.js → chunk-PD7HXVQ3.js} +1 -1
- package/dist/{chunk-J2U6P376.js → chunk-QNUVQ6KD.js} +204 -21
- package/dist/{chunk-4G6SPMMV.js → chunk-TG6LBCPG.js} +3486 -236
- package/dist/chunk-XZ64ZAGO.js +18 -0
- package/dist/{chunk-H5XJMFNT.js → chunk-Y435RMHQ.js} +7 -3
- package/dist/{configStore-LLWSTN6X.js → configStore-RR5ZU4E3.js} +3 -3
- package/dist/{daemonChild-CV2UTL6T.js → daemonChild-E73NFWKE.js} +13 -8
- package/dist/{daemonConfig-G6S46GPJ.js → daemonConfig-QVXQ47XH.js} +2 -2
- package/dist/index.cjs +3924 -281
- package/dist/index.d.cts +135 -53
- package/dist/index.d.ts +135 -53
- package/dist/index.js +13 -10
- package/dist/ipcClient-XGF2KCQO.js +10 -0
- package/dist/{main-WQ7NUQL4.js → main-M6MACH7D.js} +9 -8
- package/dist/workers/file_serve_worker.js +1 -1
- package/package.json +5 -2
- package/scripts/install/install.ps1 +261 -0
- package/scripts/install/install.sh +387 -0
- package/dist/TunnelManager-I3NW6UXU.js +0 -11
- package/dist/ipcClient-URHJKNEH.js +0 -6
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
getLogLevel,
|
|
6
6
|
logger
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-MV56U3E6.js";
|
|
8
8
|
import {
|
|
9
9
|
getTunnelLogPath
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-AFMTIELL.js";
|
|
11
11
|
|
|
12
12
|
// src/tunnel_manager/TunnelManager.ts
|
|
13
13
|
import { TunnelInstance, LogLevel as SdkLogLevel } from "@pinggy/pinggy";
|
|
@@ -94,6 +94,114 @@ function maybeRotate(file, maxBytes = DEFAULT_MAX_BYTES, maxArchives = DEFAULT_M
|
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
// src/types.ts
|
|
98
|
+
var TunnelStateType = /* @__PURE__ */ ((TunnelStateType2) => {
|
|
99
|
+
TunnelStateType2["New"] = "idle";
|
|
100
|
+
TunnelStateType2["Starting"] = "starting";
|
|
101
|
+
TunnelStateType2["Running"] = "running";
|
|
102
|
+
TunnelStateType2["Live"] = "live";
|
|
103
|
+
TunnelStateType2["Closed"] = "closed";
|
|
104
|
+
TunnelStateType2["Exited"] = "exited";
|
|
105
|
+
return TunnelStateType2;
|
|
106
|
+
})(TunnelStateType || {});
|
|
107
|
+
var TunnelErrorCodeType = /* @__PURE__ */ ((TunnelErrorCodeType2) => {
|
|
108
|
+
TunnelErrorCodeType2["NonResponsive"] = "non_responsive";
|
|
109
|
+
TunnelErrorCodeType2["FailedToConnect"] = "failed_to_connect";
|
|
110
|
+
TunnelErrorCodeType2["ErrorInAdditionalForwarding"] = "additional_forwarding_error";
|
|
111
|
+
TunnelErrorCodeType2["WebdebuggerError"] = "webdebugger_error";
|
|
112
|
+
TunnelErrorCodeType2["NoError"] = "";
|
|
113
|
+
return TunnelErrorCodeType2;
|
|
114
|
+
})(TunnelErrorCodeType || {});
|
|
115
|
+
var TunnelWarningCode = /* @__PURE__ */ ((TunnelWarningCode3) => {
|
|
116
|
+
TunnelWarningCode3["InvalidTunnelServePath"] = "INVALID_TUNNEL_SERVE_PATH";
|
|
117
|
+
TunnelWarningCode3["UnknownWarning"] = "UNKNOWN_WARNING";
|
|
118
|
+
return TunnelWarningCode3;
|
|
119
|
+
})(TunnelWarningCode || {});
|
|
120
|
+
var ErrorCode = {
|
|
121
|
+
InvalidRequestMethodError: "INVALID_REQUEST_METHOD",
|
|
122
|
+
InvalidRequestBodyError: "COULD_NOT_READ_BODY",
|
|
123
|
+
InternalServerError: "INTERNAL_SERVER_ERROR",
|
|
124
|
+
InvalidBodyFormatError: "INVALID_DATA_FORMAT",
|
|
125
|
+
ErrorStartingTunnel: "ERROR_STARTING_TUNNEL",
|
|
126
|
+
TunnelNotFound: "TUNNEL_WITH_ID_OR_CONFIG_ID_NOT_FOUND",
|
|
127
|
+
TunnelAlreadyRunningError: "TUNNEL_WITH_ID_OR_CONFIG_ID_ALREADY_RUNNING",
|
|
128
|
+
WebsocketUpgradeFailError: "WEBSOCKET_UPGRADE_FAILED",
|
|
129
|
+
RemoteManagementAlreadyRunning: "REMOTE_MANAGEMENT_ALREADY_RUNNING",
|
|
130
|
+
RemoteManagementNotRunning: "REMOTE_MANAGEMENT_NOT_RUNNING",
|
|
131
|
+
RemoteManagementDeserializationFailed: "REMOTE_MANAGEMENT_DESERIALIZATION_FAILED",
|
|
132
|
+
DeviceNotEnrolled: "DEVICE_NOT_ENROLLED"
|
|
133
|
+
};
|
|
134
|
+
function isErrorResponse(obj) {
|
|
135
|
+
return typeof obj === "object" && obj !== null && "code" in obj && "message" in obj && typeof obj.message === "string" && Object.values(ErrorCode).includes(obj.code);
|
|
136
|
+
}
|
|
137
|
+
function newErrorResponse(codeOrError, message) {
|
|
138
|
+
if (typeof codeOrError === "object") {
|
|
139
|
+
return codeOrError;
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
code: codeOrError,
|
|
143
|
+
message
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function NewResponseObject(data) {
|
|
147
|
+
const encoder = new TextEncoder();
|
|
148
|
+
const bytes = encoder.encode(JSON.stringify(data));
|
|
149
|
+
return {
|
|
150
|
+
response: bytes,
|
|
151
|
+
requestid: "",
|
|
152
|
+
command: "",
|
|
153
|
+
error: false,
|
|
154
|
+
errorresponse: {}
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function NewErrorResponseObject(errorResponse) {
|
|
158
|
+
return {
|
|
159
|
+
response: new Uint8Array(),
|
|
160
|
+
requestid: "",
|
|
161
|
+
command: "",
|
|
162
|
+
error: true,
|
|
163
|
+
errorresponse: errorResponse
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function newStatus(tunnelState, errorCode, errorMsg) {
|
|
167
|
+
let assignedState = tunnelState;
|
|
168
|
+
if (tunnelState === "live" /* Live */) {
|
|
169
|
+
assignedState = "running" /* Running */;
|
|
170
|
+
} else if (tunnelState === "idle" /* New */) {
|
|
171
|
+
assignedState = "idle" /* New */;
|
|
172
|
+
} else if (tunnelState === "closed" /* Closed */) {
|
|
173
|
+
assignedState = "exited" /* Exited */;
|
|
174
|
+
}
|
|
175
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
176
|
+
return {
|
|
177
|
+
state: assignedState,
|
|
178
|
+
errorcode: errorCode,
|
|
179
|
+
errormsg: errorMsg,
|
|
180
|
+
createdtimestamp: now,
|
|
181
|
+
starttimestamp: now,
|
|
182
|
+
endtimestamp: now,
|
|
183
|
+
warnings: []
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function newStats() {
|
|
187
|
+
return {
|
|
188
|
+
numLiveConnections: 0,
|
|
189
|
+
numTotalConnections: 0,
|
|
190
|
+
numTotalReqBytes: 0,
|
|
191
|
+
numTotalResBytes: 0,
|
|
192
|
+
numTotalTxBytes: 0,
|
|
193
|
+
elapsedTime: 0
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
var RemoteManagementStatus = {
|
|
197
|
+
Connecting: "CONNECTING",
|
|
198
|
+
Disconnecting: "DISCONNECTING",
|
|
199
|
+
Reconnecting: "RECONNECTING",
|
|
200
|
+
Running: "RUNNING",
|
|
201
|
+
NotRunning: "NOT_RUNNING",
|
|
202
|
+
Error: "ERROR"
|
|
203
|
+
};
|
|
204
|
+
|
|
97
205
|
// src/tunnel_manager/TunnelManager.ts
|
|
98
206
|
import path2 from "path";
|
|
99
207
|
import { Worker } from "worker_threads";
|
|
@@ -268,6 +376,7 @@ function getLocalAddress(config) {
|
|
|
268
376
|
// src/tunnel_manager/TunnelManager.ts
|
|
269
377
|
var __filename3 = fileURLToPath2(import.meta.url);
|
|
270
378
|
var __dirname3 = path2.dirname(__filename3);
|
|
379
|
+
var START_FAILED_MESSAGE = "Failed to start tunnel";
|
|
271
380
|
function mapToSdkLogLevel(level) {
|
|
272
381
|
if (level === "debug") return SdkLogLevel.DEBUG;
|
|
273
382
|
if (level === "error") return SdkLogLevel.ERROR;
|
|
@@ -282,6 +391,13 @@ var TunnelAlreadyRunningError = class extends Error {
|
|
|
282
391
|
this.name = "TunnelAlreadyRunningError";
|
|
283
392
|
}
|
|
284
393
|
};
|
|
394
|
+
var TunnelRebuildInProgressError = class extends Error {
|
|
395
|
+
constructor(tunnelId) {
|
|
396
|
+
super(`Tunnel "${tunnelId}" is already restarting`);
|
|
397
|
+
this.tunnelId = tunnelId;
|
|
398
|
+
this.name = "TunnelRebuildInProgressError";
|
|
399
|
+
}
|
|
400
|
+
};
|
|
285
401
|
var TunnelManager = class _TunnelManager {
|
|
286
402
|
constructor() {
|
|
287
403
|
this.tunnelsByTunnelId = /* @__PURE__ */ new Map();
|
|
@@ -326,7 +442,7 @@ var TunnelManager = class _TunnelManager {
|
|
|
326
442
|
throw new Error("configId is required and must be a non-empty string");
|
|
327
443
|
}
|
|
328
444
|
const existing = this.tunnelsByConfigId.get(configId);
|
|
329
|
-
if (existing && !existing.isStopped) {
|
|
445
|
+
if (existing && (!existing.isStopped || existing.rebuild)) {
|
|
330
446
|
throw new TunnelAlreadyRunningError(configId, existing.tunnelid);
|
|
331
447
|
}
|
|
332
448
|
return this._createTunnelWithProcessedConfig({
|
|
@@ -348,14 +464,15 @@ var TunnelManager = class _TunnelManager {
|
|
|
348
464
|
* @private
|
|
349
465
|
*/
|
|
350
466
|
async _createTunnelWithProcessedConfig(params) {
|
|
351
|
-
const
|
|
467
|
+
const tunnelConfig = { ...params.originalConfig, maxReconnectAttempts: 0 };
|
|
468
|
+
const tunnelLogName = params.tunnelName || tunnelConfig?.name;
|
|
352
469
|
const tunnelLogPath = getTunnelLogPath(params.tunnelid, params.origin, tunnelLogName);
|
|
353
470
|
maybeRotate(tunnelLogPath);
|
|
354
471
|
attachTunnelLogger(params.tunnelid, params.origin, tunnelLogName);
|
|
355
472
|
let instance;
|
|
356
473
|
try {
|
|
357
|
-
logger.debug("Creating tunnel instance with processed config",
|
|
358
|
-
instance = await TunnelInstance.create(
|
|
474
|
+
logger.debug("Creating tunnel instance with processed config", tunnelConfig);
|
|
475
|
+
instance = await TunnelInstance.create(tunnelConfig, {
|
|
359
476
|
enabled: true,
|
|
360
477
|
logLevel: mapToSdkLogLevel(getLogLevel()),
|
|
361
478
|
logFilePath: tunnelLogPath,
|
|
@@ -373,7 +490,7 @@ var TunnelManager = class _TunnelManager {
|
|
|
373
490
|
tunnelName: params.tunnelName,
|
|
374
491
|
origin: params.origin,
|
|
375
492
|
instance,
|
|
376
|
-
tunnelConfig
|
|
493
|
+
tunnelConfig,
|
|
377
494
|
serve: params.serve,
|
|
378
495
|
warnings: [],
|
|
379
496
|
isStopped: false,
|
|
@@ -413,11 +530,12 @@ var TunnelManager = class _TunnelManager {
|
|
|
413
530
|
try {
|
|
414
531
|
urls = await managed.instance.start();
|
|
415
532
|
} catch (error) {
|
|
416
|
-
|
|
533
|
+
const reason = errorMessage(error) || START_FAILED_MESSAGE;
|
|
534
|
+
logger.warn("Failed to start tunnel", { tunnelId, error: reason });
|
|
417
535
|
managed.isStopped = true;
|
|
418
536
|
managed.stoppedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
419
537
|
managed.lastError = {
|
|
420
|
-
message:
|
|
538
|
+
message: reason,
|
|
421
539
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
422
540
|
isFatal: true
|
|
423
541
|
};
|
|
@@ -588,6 +706,9 @@ var TunnelManager = class _TunnelManager {
|
|
|
588
706
|
logger.error(`Tunnel "${tunnelId}" not found when fetching status`);
|
|
589
707
|
throw new Error(`Tunnel "${tunnelId}" not found`);
|
|
590
708
|
}
|
|
709
|
+
if (managed.rebuild?.startsAfter) {
|
|
710
|
+
return "starting" /* Starting */;
|
|
711
|
+
}
|
|
591
712
|
if (managed.isStopped) {
|
|
592
713
|
return "exited";
|
|
593
714
|
}
|
|
@@ -638,6 +759,10 @@ var TunnelManager = class _TunnelManager {
|
|
|
638
759
|
logger.warn("Attempted to remove tunnel that is not stopped", { tunnelId });
|
|
639
760
|
return false;
|
|
640
761
|
}
|
|
762
|
+
if (managed.rebuild) {
|
|
763
|
+
logger.warn("Attempted to remove tunnel that is restarting", { tunnelId });
|
|
764
|
+
return false;
|
|
765
|
+
}
|
|
641
766
|
this._cleanupTunnelRecords(managed);
|
|
642
767
|
logger.info("Removed stopped tunnel records", { tunnelId, configId: managed.configId });
|
|
643
768
|
return true;
|
|
@@ -717,17 +842,27 @@ var TunnelManager = class _TunnelManager {
|
|
|
717
842
|
if (!managed) {
|
|
718
843
|
return Promise.reject(new Error(`Tunnel with configId "${configId}" not found`));
|
|
719
844
|
}
|
|
720
|
-
return
|
|
845
|
+
return this.currentConfig(managed);
|
|
721
846
|
}
|
|
722
847
|
if (tunnelId) {
|
|
723
848
|
const managed = this.tunnelsByTunnelId.get(tunnelId);
|
|
724
849
|
if (!managed) {
|
|
725
850
|
return Promise.reject(new Error(`Tunnel with tunnelId "${tunnelId}" not found`));
|
|
726
851
|
}
|
|
727
|
-
return
|
|
852
|
+
return this.currentConfig(managed);
|
|
728
853
|
}
|
|
729
854
|
return Promise.reject(new Error(`Either configId or tunnelId must be provided`));
|
|
730
855
|
}
|
|
856
|
+
/**
|
|
857
|
+
* The instance's config, asked of its worker. A stopped instance has let its worker go, so a stopped
|
|
858
|
+
* tunnel, including one a restart is replacing, answers with the config it was built from.
|
|
859
|
+
*/
|
|
860
|
+
currentConfig(managed) {
|
|
861
|
+
if (managed.isStopped) {
|
|
862
|
+
return Promise.resolve(managed.tunnelConfig);
|
|
863
|
+
}
|
|
864
|
+
return Promise.resolve(managed.instance.getConfig());
|
|
865
|
+
}
|
|
731
866
|
/**
|
|
732
867
|
* Stop a tunnel instance and wait for the stop to settle, capped by a
|
|
733
868
|
* timeout. Failure is logged, not thrown: the caller replaces the
|
|
@@ -751,6 +886,46 @@ var TunnelManager = class _TunnelManager {
|
|
|
751
886
|
if (timer) clearTimeout(timer);
|
|
752
887
|
}
|
|
753
888
|
}
|
|
889
|
+
/**
|
|
890
|
+
* Marks the entry a restart or config update replaces. It stays in both maps until
|
|
891
|
+
* `_createTunnelWithProcessedConfig` sets the new entry under the same ids. When the new entry
|
|
892
|
+
* starts, the entry reports `starting`, and an error from an earlier run no longer describes it.
|
|
893
|
+
*/
|
|
894
|
+
beginRebuild(managed, startsAfter) {
|
|
895
|
+
if (managed.rebuild) {
|
|
896
|
+
throw new TunnelRebuildInProgressError(managed.tunnelid);
|
|
897
|
+
}
|
|
898
|
+
managed.rebuild = { startsAfter };
|
|
899
|
+
if (startsAfter) {
|
|
900
|
+
managed.lastError = {};
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
/** Stops the instance being replaced, and marks it stopped so no reader calls it again. */
|
|
904
|
+
async stopForRebuild(managed) {
|
|
905
|
+
if (managed.isStopped) {
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
await this.stopInstanceGuarded(managed);
|
|
909
|
+
managed.isStopped = true;
|
|
910
|
+
managed.stoppedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Ends a failed rebuild. When the old entry is still in the maps, it stays listed as stopped with
|
|
914
|
+
* the reason. A new entry that failed to start already holds its own error.
|
|
915
|
+
*/
|
|
916
|
+
failRebuild(managed, error) {
|
|
917
|
+
managed.rebuild = void 0;
|
|
918
|
+
if (this.tunnelsByTunnelId.get(managed.tunnelid) !== managed) {
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
managed.isStopped = true;
|
|
922
|
+
managed.stoppedAt = managed.stoppedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
923
|
+
managed.lastError = {
|
|
924
|
+
message: errorMessage(error) || START_FAILED_MESSAGE,
|
|
925
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
926
|
+
isFatal: true
|
|
927
|
+
};
|
|
928
|
+
}
|
|
754
929
|
/**
|
|
755
930
|
* Restarts a tunnel with its current configuration.
|
|
756
931
|
* This function will stop the tunnel if it's running and start it again.
|
|
@@ -761,6 +936,7 @@ var TunnelManager = class _TunnelManager {
|
|
|
761
936
|
if (!existingTunnel) {
|
|
762
937
|
throw new Error(`Tunnel "${tunnelid}" not found`);
|
|
763
938
|
}
|
|
939
|
+
this.beginRebuild(existingTunnel, true);
|
|
764
940
|
logger.info("Initiating tunnel restart", {
|
|
765
941
|
tunnelId: tunnelid,
|
|
766
942
|
configId: existingTunnel.configId
|
|
@@ -772,11 +948,7 @@ var TunnelManager = class _TunnelManager {
|
|
|
772
948
|
const currentServe = existingTunnel.serve;
|
|
773
949
|
const autoReconnect = existingTunnel.autoReconnect || false;
|
|
774
950
|
const currentOrigin = existingTunnel.origin;
|
|
775
|
-
|
|
776
|
-
await this.stopInstanceGuarded(existingTunnel);
|
|
777
|
-
}
|
|
778
|
-
this.tunnelsByTunnelId.delete(tunnelid);
|
|
779
|
-
this.tunnelsByConfigId.delete(existingTunnel.configId);
|
|
951
|
+
await this.stopForRebuild(existingTunnel);
|
|
780
952
|
this.tunnelStats.delete(tunnelid);
|
|
781
953
|
this.tunnelStatsListeners.delete(tunnelid);
|
|
782
954
|
this.tunnelErrorListeners.delete(tunnelid);
|
|
@@ -802,6 +974,7 @@ var TunnelManager = class _TunnelManager {
|
|
|
802
974
|
}
|
|
803
975
|
await this.startTunnel(newTunnel.tunnelid);
|
|
804
976
|
} catch (error) {
|
|
977
|
+
this.failRebuild(existingTunnel, error);
|
|
805
978
|
logger.error("Failed to restart tunnel", {
|
|
806
979
|
tunnelid,
|
|
807
980
|
error: error instanceof Error ? error.message : "Unknown error"
|
|
@@ -859,12 +1032,9 @@ var TunnelManager = class _TunnelManager {
|
|
|
859
1032
|
const currentStartedAt = existingTunnel.startedAt;
|
|
860
1033
|
const currentStoppedAt = existingTunnel.stoppedAt;
|
|
861
1034
|
const requestedServe = this.resolveServePath(newConfig);
|
|
1035
|
+
this.beginRebuild(existingTunnel, !isStopped);
|
|
862
1036
|
try {
|
|
863
|
-
|
|
864
|
-
await this.stopInstanceGuarded(existingTunnel);
|
|
865
|
-
}
|
|
866
|
-
this.tunnelsByTunnelId.delete(currentTunnelId);
|
|
867
|
-
this.tunnelsByConfigId.delete(currentTunnelConfigId);
|
|
1037
|
+
await this.stopForRebuild(existingTunnel);
|
|
868
1038
|
const mergedBaseConfig = {
|
|
869
1039
|
...newConfig,
|
|
870
1040
|
configId,
|
|
@@ -925,6 +1095,7 @@ var TunnelManager = class _TunnelManager {
|
|
|
925
1095
|
error: errorMessage(restoreError)
|
|
926
1096
|
});
|
|
927
1097
|
}
|
|
1098
|
+
this.failRebuild(existingTunnel, error);
|
|
928
1099
|
throw error;
|
|
929
1100
|
}
|
|
930
1101
|
}
|
|
@@ -1738,11 +1909,23 @@ export {
|
|
|
1738
1909
|
setTunnelLoggingEnabled,
|
|
1739
1910
|
isTunnelLoggingEnabled,
|
|
1740
1911
|
detachAllTunnelLoggers,
|
|
1912
|
+
TunnelStateType,
|
|
1913
|
+
TunnelErrorCodeType,
|
|
1914
|
+
TunnelWarningCode,
|
|
1915
|
+
ErrorCode,
|
|
1916
|
+
isErrorResponse,
|
|
1917
|
+
newErrorResponse,
|
|
1918
|
+
NewResponseObject,
|
|
1919
|
+
NewErrorResponseObject,
|
|
1920
|
+
newStatus,
|
|
1921
|
+
newStats,
|
|
1922
|
+
RemoteManagementStatus,
|
|
1741
1923
|
getRandomId,
|
|
1742
1924
|
isValidPort,
|
|
1743
1925
|
errorMessage,
|
|
1744
1926
|
getVersion,
|
|
1745
1927
|
getLocalAddress,
|
|
1746
1928
|
TunnelAlreadyRunningError,
|
|
1929
|
+
TunnelRebuildInProgressError,
|
|
1747
1930
|
TunnelManager
|
|
1748
1931
|
};
|