This commit is contained in:
Baobhan Sith
2025-04-29 19:09:19 +08:00
parent 1b4896a1f0
commit 03d3df88e9
2 changed files with 52 additions and 12 deletions
+48 -10
View File
@@ -136,16 +136,54 @@ export const establishSshConnection = (
};
const errorHandler = (err: Error) => {
// Ensure this handler only runs once effectively
sshClient.removeListener('ready', readyHandler);
sshClient.removeListener('error', errorHandler); // Remove itself
sshClient.removeListener('close', closeHandler); // Remove close handler if attached
console.error(`SshService: SSH 连接到 ${connDetails.host}:${connDetails.port} (ID: ${connDetails.id}) 失败:`, err);
sshClient.removeListener('ready', readyHandler); // 失败后移除成功监听器
sshClient.end(); // 确保关闭客户端
reject(err);
// Try ending the client gracefully, but don't wait for it if it hangs
try {
sshClient.end();
} catch (endError) {
console.error(`SshService: Error while calling sshClient.end() during error handling:`, endError);
}
reject(err); // Reject the promise
};
sshClient.once('ready', readyHandler);
sshClient.once('error', errorHandler);
const closeHandler = () => {
// Handle unexpected close events if needed, or just ensure listeners are removed
sshClient.removeListener('ready', readyHandler);
sshClient.removeListener('error', errorHandler);
sshClient.removeListener('close', closeHandler);
// console.log(`SshService: SSH connection closed unexpectedly during connection phase for ${connDetails.id}`);
// Avoid rejecting here, let the 'error' handler manage rejection on failure.
};
// Modify readyHandler to remove error and close listeners
const originalReadyHandler = readyHandler; // Keep original logic
const enhancedReadyHandler = async () => {
sshClient.removeListener('error', errorHandler); // Remove error listener on success
sshClient.removeListener('close', closeHandler); // Remove close listener on success
await originalReadyHandler(); // Execute original logic (updates DB, resolves promise)
};
sshClient.once('ready', enhancedReadyHandler); // Use enhanced handler
sshClient.on('error', errorHandler); // Use 'on' but handler removes itself
sshClient.on('close', closeHandler); // Add a handler for close events during connection phase
// --- 处理代理 ---
// Make sure the proxy error handling also calls the main errorHandler
const handleProxyError = (proxyError: Error) => {
console.error(`SshService: Proxy setup failed for ${connDetails.host}:${connDetails.port} (ID: ${connDetails.id})`, proxyError);
// Call the main error handler to ensure consistent cleanup and rejection
errorHandler(proxyError);
};
if (connDetails.proxy) {
const proxy = connDetails.proxy;
console.log(`SshService: 应用代理 ${proxy.name} (${proxy.type}) 连接到 ${connDetails.host}:${connDetails.port}`);
@@ -163,7 +201,7 @@ export const establishSshConnection = (
sshClient.connect(connectConfig);
})
.catch(socksError => {
errorHandler(new Error(`SOCKS5 代理 ${proxy.host}:${proxy.port} 连接失败: ${socksError.message}`));
handleProxyError(new Error(`SOCKS5 代理 ${proxy.host}:${proxy.port} 连接失败: ${socksError.message}`));
});
} else if (proxy.type === 'HTTP') {
@@ -188,19 +226,19 @@ export const establishSshConnection = (
sshClient.connect(connectConfig);
} else {
socket.destroy();
errorHandler(new Error(`HTTP 代理 ${proxy.host}:${proxy.port} 连接失败 (状态码: ${res.statusCode})`));
handleProxyError(new Error(`HTTP 代理 ${proxy.host}:${proxy.port} 连接失败 (状态码: ${res.statusCode})`));
}
});
req.on('error', (err) => {
errorHandler(new Error(`HTTP 代理 ${proxy.host}:${proxy.port} 请求错误: ${err.message}`));
handleProxyError(new Error(`HTTP 代理 ${proxy.host}:${proxy.port} 请求错误: ${err.message}`));
});
req.on('timeout', () => {
req.destroy();
errorHandler(new Error(`HTTP 代理 ${proxy.host}:${proxy.port} 连接超时`));
handleProxyError(new Error(`HTTP 代理 ${proxy.host}:${proxy.port} 连接超时`));
});
req.end();
} else {
errorHandler(new Error(`不支持的代理类型: ${proxy.type}`));
handleProxyError(new Error(`不支持的代理类型: ${proxy.type}`));
}
} else {
// 无代理,直接连接
+4 -2
View File
@@ -831,9 +831,11 @@ export const initializeWebSocket = async (server: http.Server, sessionParser: Re
reason: connectError.message
});
ws.send(JSON.stringify({ type: 'ssh:error', payload: `连接失败: ${connectError.message}` }));
}
// 在 SSH 连接建立失败时关闭 WebSocket
ws.close(1011, `SSH Connection Failed: ${connectError.message}`);
}
break;
}
}
// --- SSH 输入 ---
case 'ssh:input': {