mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-30 07:05:24 +00:00
feat: convert ssh tunnels into a plugin
This commit is contained in:
1 parent
c85c1fdb86
commit
1682861853
220 files changed
+36928
-11374
No files matched your search
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Tunnel names, shared by the backend and every frontend view so the two
|
||||
* sides can never build the same tunnel under different names.
|
||||
*/
|
||||
|
||||
/** A host's saved server tunnel: `<hostId>::<index>::<label>::<port>::<endpoint>::<port>`. */
|
||||
export function buildTunnelName(
|
||||
hostId: number | string,
|
||||
tunnelIndex: number,
|
||||
hostLabel: string,
|
||||
sourcePort: number | string,
|
||||
endpointHost: string,
|
||||
endpointPort: number | string,
|
||||
): string {
|
||||
return `${hostId}::${tunnelIndex}::${hostLabel}::${sourcePort}::${endpointHost}::${endpointPort}`;
|
||||
}
|
||||
|
||||
/** The label a server tunnel name carries for its source host. */
|
||||
export function tunnelHostLabel(host: {
|
||||
name?: string | null;
|
||||
username?: string | null;
|
||||
ip: string;
|
||||
}): string {
|
||||
return host.name || `${host.username ?? ""}@${host.ip}`;
|
||||
}
|
||||
|
||||
/** A saved server tunnel's name, from its host and position in the list. */
|
||||
export function serverTunnelName(
|
||||
host: {
|
||||
id: number | string;
|
||||
name?: string | null;
|
||||
username?: string | null;
|
||||
ip: string;
|
||||
},
|
||||
index: number,
|
||||
tunnel: {
|
||||
sourcePort: number | string;
|
||||
endpointHost?: string | null;
|
||||
endpointPort?: number | string | null;
|
||||
},
|
||||
): string {
|
||||
return buildTunnelName(
|
||||
host.id,
|
||||
index,
|
||||
tunnelHostLabel(host),
|
||||
tunnel.sourcePort,
|
||||
(tunnel.endpointHost ?? "").trim(),
|
||||
tunnel.endpointPort ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
/** A desktop client tunnel's name, as the Electron main process tracks it. */
|
||||
export function clientTunnelName(
|
||||
tunnel: {
|
||||
sourceHostId?: number;
|
||||
mode?: string;
|
||||
tunnelType?: string;
|
||||
localAddress?: string;
|
||||
remoteAddress?: string;
|
||||
sourcePort: number;
|
||||
endpointPort?: number;
|
||||
},
|
||||
index: number,
|
||||
): string {
|
||||
const address = (value?: string) => value?.trim() || "127.0.0.1";
|
||||
return [
|
||||
"c2s",
|
||||
index,
|
||||
tunnel.sourceHostId || 0,
|
||||
tunnel.mode || tunnel.tunnelType || "local",
|
||||
address(tunnel.localAddress),
|
||||
address(tunnel.remoteAddress),
|
||||
tunnel.sourcePort,
|
||||
tunnel.endpointPort || 0,
|
||||
].join("::");
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
export type TunnelScope = "s2s" | "c2s";
|
||||
export type TunnelMode = "local" | "remote" | "dynamic";
|
||||
|
||||
export const CONNECTION_STATES = {
|
||||
DISCONNECTED: "disconnected",
|
||||
CONNECTING: "connecting",
|
||||
CONNECTED: "connected",
|
||||
VERIFYING: "verifying",
|
||||
FAILED: "failed",
|
||||
UNSTABLE: "unstable",
|
||||
RETRYING: "retrying",
|
||||
WAITING: "waiting",
|
||||
DISCONNECTING: "disconnecting",
|
||||
} as const;
|
||||
|
||||
export type ConnectionState =
|
||||
(typeof CONNECTION_STATES)[keyof typeof CONNECTION_STATES];
|
||||
|
||||
export type TunnelErrorType =
|
||||
| "CONNECTION_FAILED"
|
||||
| "AUTHENTICATION_FAILED"
|
||||
| "TIMEOUT"
|
||||
| "NETWORK_ERROR"
|
||||
| "UNKNOWN";
|
||||
|
||||
/** One saved tunnel, as a host's tunnelConnections setting or a C2S preset holds it. */
|
||||
export interface TunnelConnection {
|
||||
scope?: TunnelScope;
|
||||
mode?: TunnelMode;
|
||||
tunnelType?: "local" | "remote";
|
||||
localAddress?: string;
|
||||
remoteAddress?: string;
|
||||
bindHost?: string;
|
||||
sourceHostId?: number;
|
||||
sourceHostSyncId?: string;
|
||||
sourceHostName?: string;
|
||||
sourcePort: number;
|
||||
endpointPort: number;
|
||||
endpointHost?: string;
|
||||
targetHost?: string;
|
||||
/** Seconds. */
|
||||
retryInterval: number;
|
||||
maxRetries: number;
|
||||
autoStart: boolean;
|
||||
displayName?: string;
|
||||
}
|
||||
|
||||
/** What POST /connect takes. Credentials are always resolved server side. */
|
||||
export interface TunnelConnectRequest {
|
||||
name: string;
|
||||
sourceHostId: number;
|
||||
tunnelIndex: number;
|
||||
scope?: TunnelScope;
|
||||
mode?: TunnelMode;
|
||||
tunnelType?: "local" | "remote";
|
||||
bindHost?: string;
|
||||
targetHost?: string;
|
||||
endpointHost?: string;
|
||||
sourcePort: number;
|
||||
endpointPort: number;
|
||||
maxRetries?: number;
|
||||
/** Seconds. */
|
||||
retryInterval?: number;
|
||||
autoStart?: boolean;
|
||||
}
|
||||
|
||||
export interface TunnelStatus {
|
||||
connected: boolean;
|
||||
status: ConnectionState;
|
||||
retryCount?: number;
|
||||
maxRetries?: number;
|
||||
nextRetryIn?: number;
|
||||
reason?: string;
|
||||
errorType?: TunnelErrorType;
|
||||
manualDisconnect?: boolean;
|
||||
retryExhausted?: boolean;
|
||||
}
|
||||
|
||||
export interface C2STunnelPreset {
|
||||
id: number;
|
||||
userId: string;
|
||||
name: string;
|
||||
config: TunnelConnection[];
|
||||
platform?: string | null;
|
||||
computerName?: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
Reference in new issue
Block a user