update
This commit is contained in:
@@ -16,8 +16,10 @@ import {
|
||||
SshSuspendEntryRemovedResponse,
|
||||
SshSuspendNameEditedResponse,
|
||||
SshSuspendAutoTerminatedNotification,
|
||||
SshMarkForSuspendRequest, // +++ 新增导入
|
||||
SshMarkedForSuspendAck, // +++ 新增导入
|
||||
SshMarkForSuspendRequest,
|
||||
SshMarkedForSuspendAck,
|
||||
SshUnmarkForSuspendRequest, // +++ 新增导入 +++
|
||||
SshUnmarkedForSuspendAck, // +++ 新增导入 +++
|
||||
ClientState
|
||||
} from './types';
|
||||
import { SshSuspendService } from '../services/ssh-suspend.service';
|
||||
@@ -317,7 +319,8 @@ export function initializeConnectionHandler(wss: WebSocketServer, sshSuspendServ
|
||||
case 'SSH_MARK_FOR_SUSPEND': {
|
||||
const markPayload = payload as SshMarkForSuspendRequest['payload'];
|
||||
const sessionToMarkId = markPayload.sessionId;
|
||||
console.log(`[WebSocket Handler] Received SSH_MARK_FOR_SUSPEND. UserID: ${ws.userId}, TargetSessionID: ${sessionToMarkId}`);
|
||||
const initialBuffer = markPayload.initialBuffer; // +++ 获取 initialBuffer +++
|
||||
console.log(`[WebSocket Handler] Received SSH_MARK_FOR_SUSPEND. UserID: ${ws.userId}, TargetSessionID: ${sessionToMarkId}, InitialBuffer provided: ${!!initialBuffer}`);
|
||||
|
||||
if (!ws.userId) {
|
||||
console.error(`[SSH_MARK_FOR_SUSPEND] 用户 ID 未定义。`);
|
||||
@@ -346,8 +349,16 @@ export function initializeConnectionHandler(wss: WebSocketServer, sshSuspendServ
|
||||
|
||||
// 确保日志目录存在 (服务内部通常会做,但这里也可以调用一次)
|
||||
await temporaryLogStorageService.ensureLogDirectoryExists();
|
||||
// 可以在这里预先写入一个标记,表明日志开始记录
|
||||
await temporaryLogStorageService.writeToLog(logPathSuffix, `--- Log recording started for session ${sessionToMarkId} at ${new Date().toISOString()} ---\n`);
|
||||
|
||||
// +++ 如果有 initialBuffer,先写入它 +++
|
||||
if (initialBuffer) {
|
||||
// 确保 initialBuffer 后有一个换行符,以便后续日志在新行开始
|
||||
const formattedInitialBuffer = initialBuffer.endsWith('\n') ? initialBuffer : `${initialBuffer}\n`;
|
||||
await temporaryLogStorageService.writeToLog(logPathSuffix, formattedInitialBuffer);
|
||||
console.log(`[SSH_MARK_FOR_SUSPEND] 已将初始缓冲区写入日志 (会话: ${sessionToMarkId})。`);
|
||||
}
|
||||
// --- 移除自动添加的日志标记行 ---
|
||||
// await temporaryLogStorageService.writeToLog(logPathSuffix, `--- Log recording continued for session ${sessionToMarkId} at ${new Date().toISOString()} ---\n`);
|
||||
|
||||
console.log(`[SSH_MARK_FOR_SUSPEND] 会话 ${sessionToMarkId} 已成功标记待挂起。日志将记录到与 ${logPathSuffix} 关联的文件。`);
|
||||
const response: SshMarkedForSuspendAck = {
|
||||
@@ -365,6 +376,59 @@ export function initializeConnectionHandler(wss: WebSocketServer, sshSuspendServ
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'SSH_UNMARK_FOR_SUSPEND': {
|
||||
const unmarkPayload = payload as SshUnmarkForSuspendRequest['payload'];
|
||||
const sessionToUnmarkId = unmarkPayload.sessionId;
|
||||
console.log(`[WebSocket Handler] Received SSH_UNMARK_FOR_SUSPEND. UserID: ${ws.userId}, TargetSessionID: ${sessionToUnmarkId}`);
|
||||
const ackPayloadBase = { sessionId: sessionToUnmarkId };
|
||||
|
||||
if (!ws.userId) {
|
||||
console.error(`[SSH_UNMARK_FOR_SUSPEND] 用户 ID 未定义。`);
|
||||
if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'SSH_UNMARKED_FOR_SUSPEND_ACK', payload: { ...ackPayloadBase, success: false, error: '用户认证失败' } as SshUnmarkedForSuspendAck['payload'] }));
|
||||
break;
|
||||
}
|
||||
|
||||
const activeSessionState = clientStates.get(sessionToUnmarkId);
|
||||
if (!activeSessionState) {
|
||||
console.warn(`[SSH_UNMARK_FOR_SUSPEND] 未找到会话: ${sessionToUnmarkId}`);
|
||||
if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'SSH_UNMARKED_FOR_SUSPEND_ACK', payload: { ...ackPayloadBase, success: false, error: '未找到要取消标记的会话' } as SshUnmarkedForSuspendAck['payload'] }));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!activeSessionState.isMarkedForSuspend) {
|
||||
console.warn(`[SSH_UNMARK_FOR_SUSPEND] 会话 ${sessionToUnmarkId} 并未被标记为待挂起。`);
|
||||
// 即使未标记,也回复成功,因为最终状态是“未标记”
|
||||
if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'SSH_UNMARKED_FOR_SUSPEND_ACK', payload: { ...ackPayloadBase, success: true, error: '会话本就未标记' } as SshUnmarkedForSuspendAck['payload'] }));
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
activeSessionState.isMarkedForSuspend = false;
|
||||
const logPathToDelete = activeSessionState.suspendLogPath;
|
||||
activeSessionState.suspendLogPath = undefined; // 清除日志路径
|
||||
|
||||
if (logPathToDelete) {
|
||||
await temporaryLogStorageService.deleteLog(logPathToDelete);
|
||||
console.log(`[SSH_UNMARK_FOR_SUSPEND] 已删除会话 ${sessionToUnmarkId} 的临时挂起日志: ${logPathToDelete}`);
|
||||
}
|
||||
|
||||
console.log(`[SSH_UNMARK_FOR_SUSPEND] 会话 ${sessionToUnmarkId} 已成功取消标记。`);
|
||||
const response: SshUnmarkedForSuspendAck = {
|
||||
type: 'SSH_UNMARKED_FOR_SUSPEND_ACK',
|
||||
payload: { ...ackPayloadBase, success: true }
|
||||
};
|
||||
if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify(response));
|
||||
} catch (error: any) {
|
||||
console.error(`[SSH_UNMARK_FOR_SUSPEND] 取消标记会话 ${sessionToUnmarkId} 失败:`, error);
|
||||
// 尝试回滚状态(尽管可能意义不大,因为错误可能在删除日志时发生)
|
||||
if (activeSessionState) {
|
||||
activeSessionState.isMarkedForSuspend = true; // 保持标记状态
|
||||
// activeSessionState.suspendLogPath = logPathToDelete; // 如果需要,可以恢复路径,但删除失败更可能是问题
|
||||
}
|
||||
if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'SSH_UNMARKED_FOR_SUSPEND_ACK', payload: { ...ackPayloadBase, success: false, error: error.message || '取消标记会话失败' } as SshUnmarkedForSuspendAck['payload'] }));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
console.warn(`WebSocket:收到来自 ${ws.username} (会话: ${sessionId}) 的未知消息类型: ${type}`);
|
||||
if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'error', payload: `不支持的消息类型: ${type}` }));
|
||||
|
||||
@@ -23,8 +23,8 @@ export interface ClientState { // 导出以便 Service 可以导入
|
||||
isShellReady?: boolean; // 新增:标记 Shell 是否已准备好处理输入和调整大小
|
||||
isSuspendedByService?: boolean; // 新增:标记此会话是否已被 SshSuspendService 接管
|
||||
isMarkedForSuspend?: boolean; // 新增:标记此会话是否已被用户请求挂起(等待断开连接)
|
||||
suspendLogPath?: string; // 新增:如果标记挂起,则存储日志路径
|
||||
suspendLogWritableStream?: NodeJS.WritableStream; // 新增:用于写入挂起日志的流
|
||||
suspendLogPath?: string; // 新增:如果标记挂起,则存储日志路径 (基于原始 sessionId)
|
||||
// suspendLogWritableStream?: NodeJS.WritableStream; // 移除,将直接使用 temporaryLogStorageService.writeToLog
|
||||
}
|
||||
|
||||
export interface PortInfo {
|
||||
@@ -110,6 +110,14 @@ export interface SshMarkForSuspendRequest {
|
||||
type: "SSH_MARK_FOR_SUSPEND";
|
||||
payload: {
|
||||
sessionId: string; // The ID of the active SSH session to be marked
|
||||
initialBuffer?: string; // +++ 新增:可选的初始屏幕缓冲区内容 +++
|
||||
};
|
||||
}
|
||||
|
||||
export interface SshUnmarkForSuspendRequest {
|
||||
type: "SSH_UNMARK_FOR_SUSPEND";
|
||||
payload: {
|
||||
sessionId: string; // The ID of the active SSH session to be unmarked
|
||||
};
|
||||
}
|
||||
|
||||
@@ -197,6 +205,15 @@ export interface SshMarkedForSuspendAck {
|
||||
};
|
||||
}
|
||||
|
||||
export interface SshUnmarkedForSuspendAck { // +++ 新增 S2C 类型 +++
|
||||
type: "SSH_UNMARKED_FOR_SUSPEND_ACK";
|
||||
payload: {
|
||||
sessionId: string; // The ID of the session that was unmarked
|
||||
success: boolean;
|
||||
error?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SshSuspendAutoTerminatedNotification {
|
||||
type: "SSH_SUSPEND_AUTO_TERMINATED";
|
||||
payload: {
|
||||
@@ -213,7 +230,8 @@ export type SshSuspendClientToServerMessages =
|
||||
| SshSuspendTerminateRequest
|
||||
| SshSuspendRemoveEntryRequest
|
||||
| SshSuspendEditNameRequest
|
||||
| SshMarkForSuspendRequest; // Added new request type
|
||||
| SshMarkForSuspendRequest
|
||||
| SshUnmarkForSuspendRequest; // +++ 新增到联合类型 +++
|
||||
|
||||
// Union type for all server-to-client messages for SSH Suspend
|
||||
export type SshSuspendServerToClientMessages =
|
||||
@@ -225,7 +243,8 @@ export type SshSuspendServerToClientMessages =
|
||||
| SshSuspendEntryRemovedResponse
|
||||
| SshSuspendNameEditedResponse
|
||||
| SshSuspendAutoTerminatedNotification
|
||||
| SshMarkedForSuspendAck; // Added new response type
|
||||
| SshMarkedForSuspendAck
|
||||
| SshUnmarkedForSuspendAck; // +++ 新增到联合类型 +++
|
||||
|
||||
// It might be useful to have a general type for incoming messages if not already present
|
||||
// For example, if you have a main message handler:
|
||||
|
||||
Reference in New Issue
Block a user