feat: 关闭主机回调.
This commit is contained in:
@@ -24,7 +24,7 @@ public enum InputTypeEnum {
|
|||||||
*/
|
*/
|
||||||
CHECK("ck",
|
CHECK("ck",
|
||||||
TerminalCheckHandler.class,
|
TerminalCheckHandler.class,
|
||||||
new String[]{"type", "session", "hostId"},
|
new String[]{"type", "sessionId", "hostId"},
|
||||||
TerminalCheckRequest.class),
|
TerminalCheckRequest.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,7 +32,7 @@ public enum InputTypeEnum {
|
|||||||
*/
|
*/
|
||||||
CONNECT("co",
|
CONNECT("co",
|
||||||
TerminalConnectHandler.class,
|
TerminalConnectHandler.class,
|
||||||
new String[]{"type", "session", "cols", "rows"},
|
new String[]{"type", "sessionId", "cols", "rows"},
|
||||||
TerminalConnectRequest.class),
|
TerminalConnectRequest.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,7 +40,7 @@ public enum InputTypeEnum {
|
|||||||
*/
|
*/
|
||||||
CLOSE("cl",
|
CLOSE("cl",
|
||||||
TerminalCloseHandler.class,
|
TerminalCloseHandler.class,
|
||||||
new String[]{"type", "session"},
|
new String[]{"type", "sessionId"},
|
||||||
TerminalBasePayload.class),
|
TerminalBasePayload.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,7 +56,7 @@ public enum InputTypeEnum {
|
|||||||
*/
|
*/
|
||||||
RESIZE("rs",
|
RESIZE("rs",
|
||||||
TerminalResizeHandler.class,
|
TerminalResizeHandler.class,
|
||||||
new String[]{"type", "session", "cols", "rows"},
|
new String[]{"type", "sessionId", "cols", "rows"},
|
||||||
TerminalResizeRequest.class),
|
TerminalResizeRequest.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,7 +64,7 @@ public enum InputTypeEnum {
|
|||||||
*/
|
*/
|
||||||
EXEC("e",
|
EXEC("e",
|
||||||
TerminalExecHandler.class,
|
TerminalExecHandler.class,
|
||||||
new String[]{"type", "session", "command"},
|
new String[]{"type", "sessionId", "command"},
|
||||||
TerminalExecRequest.class),
|
TerminalExecRequest.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,7 +72,7 @@ public enum InputTypeEnum {
|
|||||||
*/
|
*/
|
||||||
INPUT("i",
|
INPUT("i",
|
||||||
TerminalInputHandler.class,
|
TerminalInputHandler.class,
|
||||||
new String[]{"type", "session", "command"},
|
new String[]{"type", "sessionId", "command"},
|
||||||
TerminalInputRequest.class),
|
TerminalInputRequest.class),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -18,12 +18,17 @@ public enum OutputTypeEnum {
|
|||||||
/**
|
/**
|
||||||
* 主机连接检查
|
* 主机连接检查
|
||||||
*/
|
*/
|
||||||
CHECK("ck", "${type}|${session}|${result}|${errorMessage}"),
|
CHECK("ck", "${type}|${sessionId}|${result}|${msg}"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主机连接
|
* 主机连接
|
||||||
*/
|
*/
|
||||||
CONNECT("co", "${type}|${session}|${result}|${errorMessage}"),
|
CONNECT("co", "${type}|${sessionId}|${result}|${msg}"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭连接
|
||||||
|
*/
|
||||||
|
CLOSE("cl", "${type}|${sessionId}|${msg}"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pong
|
* pong
|
||||||
@@ -33,7 +38,7 @@ public enum OutputTypeEnum {
|
|||||||
/**
|
/**
|
||||||
* 输出
|
* 输出
|
||||||
*/
|
*/
|
||||||
OUTPUT("o", "${type}|${session}|${body}"),
|
OUTPUT("o", "${type}|${sessionId}|${body}"),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public class TerminalCheckHandler extends AbstractTerminalHandler<TerminalCheckR
|
|||||||
Long hostId = payload.getHostId();
|
Long hostId = payload.getHostId();
|
||||||
Long userId = this.getAttr(channel, ExtraFieldConst.USER_ID);
|
Long userId = this.getAttr(channel, ExtraFieldConst.USER_ID);
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
String sessionId = payload.getSession();
|
String sessionId = payload.getSessionId();
|
||||||
log.info("TerminalCheckHandler-handle start userId: {}, hostId: {}, sessionId: {}", userId, hostId, sessionId);
|
log.info("TerminalCheckHandler-handle start userId: {}, hostId: {}, sessionId: {}", userId, hostId, sessionId);
|
||||||
// 检查 session 是否存在
|
// 检查 session 是否存在
|
||||||
if (this.checkSession(channel, payload)) {
|
if (this.checkSession(channel, payload)) {
|
||||||
@@ -89,9 +89,9 @@ public class TerminalCheckHandler extends AbstractTerminalHandler<TerminalCheckR
|
|||||||
this.send(channel,
|
this.send(channel,
|
||||||
OutputTypeEnum.CHECK,
|
OutputTypeEnum.CHECK,
|
||||||
TerminalCheckResponse.builder()
|
TerminalCheckResponse.builder()
|
||||||
.session(payload.getSession())
|
.sessionId(payload.getSessionId())
|
||||||
.result(BooleanBit.of(ex == null).getValue())
|
.result(BooleanBit.of(ex == null).getValue())
|
||||||
.errorMessage(ex == null ? null : ex.getMessage())
|
.msg(ex == null ? null : ex.getMessage())
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ public class TerminalCheckHandler extends AbstractTerminalHandler<TerminalCheckR
|
|||||||
* @return 是否存在
|
* @return 是否存在
|
||||||
*/
|
*/
|
||||||
private boolean checkSession(WebSocketSession channel, TerminalCheckRequest payload) {
|
private boolean checkSession(WebSocketSession channel, TerminalCheckRequest payload) {
|
||||||
ITerminalSession terminalSession = terminalManager.getSession(channel.getId(), payload.getSession());
|
ITerminalSession terminalSession = terminalManager.getSession(channel.getId(), payload.getSessionId());
|
||||||
if (terminalSession != null) {
|
if (terminalSession != null) {
|
||||||
this.sendCheckFailedMessage(channel, payload, ErrorMessage.SESSION_PRESENT);
|
this.sendCheckFailedMessage(channel, payload, ErrorMessage.SESSION_PRESENT);
|
||||||
return true;
|
return true;
|
||||||
@@ -137,13 +137,13 @@ public class TerminalCheckHandler extends AbstractTerminalHandler<TerminalCheckR
|
|||||||
* @param msg msg
|
* @param msg msg
|
||||||
*/
|
*/
|
||||||
private void sendCheckFailedMessage(WebSocketSession channel, TerminalCheckRequest payload, String msg) {
|
private void sendCheckFailedMessage(WebSocketSession channel, TerminalCheckRequest payload, String msg) {
|
||||||
TerminalCheckResponse build = TerminalCheckResponse.builder()
|
TerminalCheckResponse resp = TerminalCheckResponse.builder()
|
||||||
.session(payload.getSession())
|
.sessionId(payload.getSessionId())
|
||||||
.result(BooleanBit.FALSE.getValue())
|
.result(BooleanBit.FALSE.getValue())
|
||||||
.errorMessage(msg)
|
.msg(msg)
|
||||||
.build();
|
.build();
|
||||||
// 发送
|
// 发送
|
||||||
this.send(channel, OutputTypeEnum.CHECK, build);
|
this.send(channel, OutputTypeEnum.CHECK, resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ public class TerminalCloseHandler extends AbstractTerminalHandler<TerminalBasePa
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(WebSocketSession channel, TerminalBasePayload payload) {
|
public void handle(WebSocketSession channel, TerminalBasePayload payload) {
|
||||||
log.info("TerminalCloseHandler-handle start session: {}", payload.getSession());
|
log.info("TerminalCloseHandler-handle start session: {}", payload.getSessionId());
|
||||||
// 关闭会话
|
// 关闭会话
|
||||||
terminalManager.closeSession(channel.getId(), payload.getSession());
|
terminalManager.closeSession(channel.getId(), payload.getSessionId());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public class TerminalConnectHandler extends AbstractTerminalHandler<TerminalConn
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(WebSocketSession channel, TerminalConnectRequest payload) {
|
public void handle(WebSocketSession channel, TerminalConnectRequest payload) {
|
||||||
String sessionId = payload.getSession();
|
String sessionId = payload.getSessionId();
|
||||||
log.info("TerminalConnectHandler-handle start sessionId: {}", sessionId);
|
log.info("TerminalConnectHandler-handle start sessionId: {}", sessionId);
|
||||||
// 获取主机连接信息
|
// 获取主机连接信息
|
||||||
HostTerminalConnectDTO connect = this.getAttr(channel, sessionId);
|
HostTerminalConnectDTO connect = this.getAttr(channel, sessionId);
|
||||||
@@ -57,9 +57,9 @@ public class TerminalConnectHandler extends AbstractTerminalHandler<TerminalConn
|
|||||||
this.send(channel,
|
this.send(channel,
|
||||||
OutputTypeEnum.CONNECT,
|
OutputTypeEnum.CONNECT,
|
||||||
TerminalConnectResponse.builder()
|
TerminalConnectResponse.builder()
|
||||||
.session(payload.getSession())
|
.sessionId(payload.getSessionId())
|
||||||
.result(BooleanBit.FALSE.getValue())
|
.result(BooleanBit.FALSE.getValue())
|
||||||
.errorMessage(ErrorMessage.SESSION_ABSENT)
|
.msg(ErrorMessage.SESSION_ABSENT)
|
||||||
.build());
|
.build());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -80,9 +80,9 @@ public class TerminalConnectHandler extends AbstractTerminalHandler<TerminalConn
|
|||||||
this.send(channel,
|
this.send(channel,
|
||||||
OutputTypeEnum.CONNECT,
|
OutputTypeEnum.CONNECT,
|
||||||
TerminalConnectResponse.builder()
|
TerminalConnectResponse.builder()
|
||||||
.session(payload.getSession())
|
.sessionId(payload.getSessionId())
|
||||||
.result(BooleanBit.of(ex == null).getValue())
|
.result(BooleanBit.of(ex == null).getValue())
|
||||||
.errorMessage(this.getConnectErrorMessage(ex))
|
.msg(this.getConnectErrorMessage(ex))
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class TerminalExecHandler extends AbstractTerminalHandler<TerminalExecReq
|
|||||||
@Override
|
@Override
|
||||||
public void handle(WebSocketSession channel, TerminalExecRequest payload) {
|
public void handle(WebSocketSession channel, TerminalExecRequest payload) {
|
||||||
// 获取会话
|
// 获取会话
|
||||||
ITerminalSession terminalSession = terminalManager.getSession(channel.getId(), payload.getSession());
|
ITerminalSession terminalSession = terminalManager.getSession(channel.getId(), payload.getSessionId());
|
||||||
if (terminalSession != null) {
|
if (terminalSession != null) {
|
||||||
// 执行命令
|
// 执行命令
|
||||||
terminalSession.write(payload.getCommand());
|
terminalSession.write(payload.getCommand());
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class TerminalInputHandler extends AbstractTerminalHandler<TerminalInputR
|
|||||||
@Override
|
@Override
|
||||||
public void handle(WebSocketSession channel, TerminalInputRequest payload) {
|
public void handle(WebSocketSession channel, TerminalInputRequest payload) {
|
||||||
// 获取会话
|
// 获取会话
|
||||||
ITerminalSession terminalSession = terminalManager.getSession(channel.getId(), payload.getSession());
|
ITerminalSession terminalSession = terminalManager.getSession(channel.getId(), payload.getSessionId());
|
||||||
if (terminalSession != null) {
|
if (terminalSession != null) {
|
||||||
// 处理输入
|
// 处理输入
|
||||||
terminalSession.write(payload.getCommand());
|
terminalSession.write(payload.getCommand());
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
package com.orion.ops.module.asset.handler.host.terminal.handler;
|
package com.orion.ops.module.asset.handler.host.terminal.handler;
|
||||||
|
|
||||||
|
import com.orion.lang.utils.collect.Maps;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
|
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.session.ITerminalSession;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.socket.WebSocketSession;
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ping 处理器
|
* ping 处理器
|
||||||
*
|
*
|
||||||
@@ -17,10 +23,20 @@ import org.springframework.web.socket.WebSocketSession;
|
|||||||
@Component
|
@Component
|
||||||
public class TerminalPingHandler extends AbstractTerminalHandler<TerminalBasePayload> {
|
public class TerminalPingHandler extends AbstractTerminalHandler<TerminalBasePayload> {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TerminalManager terminalManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(WebSocketSession channel, TerminalBasePayload payload) {
|
public void handle(WebSocketSession channel, TerminalBasePayload payload) {
|
||||||
// 发送 pong
|
// 发送 pong
|
||||||
this.send(channel, OutputTypeEnum.PONG.getType());
|
this.send(channel, OutputTypeEnum.PONG.getType());
|
||||||
|
// 活跃 terminal
|
||||||
|
Map<String, ITerminalSession> sessions = terminalManager.getSession(channel.getId());
|
||||||
|
if (!Maps.isEmpty(sessions)) {
|
||||||
|
for (ITerminalSession session : sessions.values()) {
|
||||||
|
session.keepAlive();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class TerminalResizeHandler extends AbstractTerminalHandler<TerminalResiz
|
|||||||
@Override
|
@Override
|
||||||
public void handle(WebSocketSession channel, TerminalResizeRequest payload) {
|
public void handle(WebSocketSession channel, TerminalResizeRequest payload) {
|
||||||
// 获取会话
|
// 获取会话
|
||||||
ITerminalSession terminalSession = terminalManager.getSession(channel.getId(), payload.getSession());
|
ITerminalSession terminalSession = terminalManager.getSession(channel.getId(), payload.getSessionId());
|
||||||
if (terminalSession != null) {
|
if (terminalSession != null) {
|
||||||
// 修改大小
|
// 修改大小
|
||||||
terminalSession.resize(payload.getCols(), payload.getRows());
|
terminalSession.resize(payload.getCols(), payload.getRows());
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.orion.ops.module.asset.handler.host.terminal.session.ITerminalSession
|
|||||||
import com.orion.ops.module.asset.handler.host.terminal.session.TerminalSession;
|
import com.orion.ops.module.asset.handler.host.terminal.session.TerminalSession;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,17 +34,6 @@ public class TerminalManager {
|
|||||||
channelSessions.put(session.getChannel().getId(), session.getSessionId(), session);
|
channelSessions.put(session.getChannel().getId(), session.getSessionId(), session);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取会话
|
|
||||||
*
|
|
||||||
* @param channelId channelId
|
|
||||||
* @param sessionId sessionId
|
|
||||||
* @return session
|
|
||||||
*/
|
|
||||||
public ITerminalSession getSession(String channelId, String sessionId) {
|
|
||||||
return channelSessions.get(channelId, sessionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭会话
|
* 关闭会话
|
||||||
*
|
*
|
||||||
@@ -58,6 +48,27 @@ public class TerminalManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会话
|
||||||
|
*
|
||||||
|
* @param channelId channelId
|
||||||
|
* @param sessionId sessionId
|
||||||
|
* @return session
|
||||||
|
*/
|
||||||
|
public ITerminalSession getSession(String channelId, String sessionId) {
|
||||||
|
return channelSessions.get(channelId, sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会话
|
||||||
|
*
|
||||||
|
* @param channelId channelId
|
||||||
|
* @return session
|
||||||
|
*/
|
||||||
|
public Map<String, ITerminalSession> getSession(String channelId) {
|
||||||
|
return channelSessions.get(channelId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭全部会话
|
* 关闭全部会话
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import lombok.experimental.SuperBuilder;
|
|||||||
public class TerminalBasePayload {
|
public class TerminalBasePayload {
|
||||||
|
|
||||||
@Schema(description = "会话id")
|
@Schema(description = "会话id")
|
||||||
private String session;
|
private String sessionId;
|
||||||
|
|
||||||
@Schema(description = "消息类型")
|
@Schema(description = "消息类型")
|
||||||
private String type;
|
private String type;
|
||||||
|
|||||||
@@ -27,6 +27,6 @@ public class TerminalCheckResponse extends TerminalBasePayload {
|
|||||||
private Integer result;
|
private Integer result;
|
||||||
|
|
||||||
@Schema(description = "错误信息")
|
@Schema(description = "错误信息")
|
||||||
private String errorMessage;
|
private String msg;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.orion.ops.module.asset.handler.host.terminal.model.response;
|
||||||
|
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主机连接关闭响应 实体对象
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023/12/29 16:20
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(name = "TerminalCloseResponse", description = "主机连接关闭响应 实体对象")
|
||||||
|
public class TerminalCloseResponse extends TerminalBasePayload {
|
||||||
|
|
||||||
|
@Schema(description = "关闭信息")
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -27,6 +27,6 @@ public class TerminalConnectResponse extends TerminalBasePayload {
|
|||||||
private Integer result;
|
private Integer result;
|
||||||
|
|
||||||
@Schema(description = "错误信息")
|
@Schema(description = "错误信息")
|
||||||
private String errorMessage;
|
private String msg;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,4 +41,9 @@ public interface ITerminalSession extends SafeCloseable {
|
|||||||
*/
|
*/
|
||||||
void write(byte[] b);
|
void write(byte[] b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 活跃回话
|
||||||
|
*/
|
||||||
|
void keepAlive();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,15 @@ package com.orion.ops.module.asset.handler.host.terminal.session;
|
|||||||
|
|
||||||
import com.orion.lang.utils.io.Streams;
|
import com.orion.lang.utils.io.Streams;
|
||||||
import com.orion.net.host.SessionStore;
|
import com.orion.net.host.SessionStore;
|
||||||
import com.orion.net.host.ssh.TerminalType;
|
|
||||||
import com.orion.net.host.ssh.shell.ShellExecutor;
|
import com.orion.net.host.ssh.shell.ShellExecutor;
|
||||||
import com.orion.ops.framework.common.constant.Const;
|
import com.orion.ops.framework.common.constant.Const;
|
||||||
import com.orion.ops.framework.websocket.core.utils.WebSockets;
|
import com.orion.ops.framework.websocket.core.utils.WebSockets;
|
||||||
import com.orion.ops.module.asset.define.AssetThreadPools;
|
import com.orion.ops.module.asset.define.AssetThreadPools;
|
||||||
import com.orion.ops.module.asset.enums.HostConnectStatusEnum;
|
import com.orion.ops.module.asset.enums.HostConnectStatusEnum;
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.constant.TerminalMessage;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
|
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalConfig;
|
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalConfig;
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.model.response.TerminalCloseResponse;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.model.response.TerminalOutputResponse;
|
import com.orion.ops.module.asset.handler.host.terminal.model.response.TerminalOutputResponse;
|
||||||
import com.orion.ops.module.asset.service.HostConnectLogService;
|
import com.orion.ops.module.asset.service.HostConnectLogService;
|
||||||
import com.orion.spring.SpringHolder;
|
import com.orion.spring.SpringHolder;
|
||||||
@@ -64,9 +65,9 @@ public class TerminalSession implements ITerminalSession {
|
|||||||
config.setRows(rows);
|
config.setRows(rows);
|
||||||
// 打开 shell
|
// 打开 shell
|
||||||
this.executor = sessionStore.getShellExecutor();
|
this.executor = sessionStore.getShellExecutor();
|
||||||
executor.terminalType(TerminalType.XTERM_256_COLOR);
|
|
||||||
executor.size(cols, rows);
|
executor.size(cols, rows);
|
||||||
executor.streamHandler(this::streamHandler);
|
executor.streamHandler(this::streamHandler);
|
||||||
|
executor.callback(this::eofCallback);
|
||||||
executor.connect();
|
executor.connect();
|
||||||
// 开始监听输出
|
// 开始监听输出
|
||||||
AssetThreadPools.TERMINAL_SCHEDULER.execute(executor);
|
AssetThreadPools.TERMINAL_SCHEDULER.execute(executor);
|
||||||
@@ -97,8 +98,19 @@ public class TerminalSession implements ITerminalSession {
|
|||||||
executor.write(b);
|
executor.write(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keepAlive() {
|
||||||
|
try {
|
||||||
|
// 发送个信号 保证 socket 不自动关闭
|
||||||
|
executor.sendSignal(Const.EMPTY);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("terminal keep-alive error {}", sessionId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
|
log.info("terminal close {}", sessionId);
|
||||||
if (close) {
|
if (close) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -128,8 +140,8 @@ public class TerminalSession implements ITerminalSession {
|
|||||||
String body = lastLine = new String(bs, 0, read, config.getCharset());
|
String body = lastLine = new String(bs, 0, read, config.getCharset());
|
||||||
// 响应
|
// 响应
|
||||||
TerminalOutputResponse resp = TerminalOutputResponse.builder()
|
TerminalOutputResponse resp = TerminalOutputResponse.builder()
|
||||||
.session(sessionId)
|
|
||||||
.type(OutputTypeEnum.OUTPUT.getType())
|
.type(OutputTypeEnum.OUTPUT.getType())
|
||||||
|
.sessionId(sessionId)
|
||||||
.body(body)
|
.body(body)
|
||||||
.build();
|
.build();
|
||||||
WebSockets.sendText(channel, OutputTypeEnum.OUTPUT.format(resp));
|
WebSockets.sendText(channel, OutputTypeEnum.OUTPUT.format(resp));
|
||||||
@@ -137,10 +149,22 @@ public class TerminalSession implements ITerminalSession {
|
|||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
log.error("terminal 读取流失败", ex);
|
log.error("terminal 读取流失败", ex);
|
||||||
}
|
}
|
||||||
// eof
|
}
|
||||||
if (close) {
|
|
||||||
log.info("terminal eof回调 {}", sessionId);
|
/**
|
||||||
}
|
* eof 回调
|
||||||
|
*/
|
||||||
|
private void eofCallback() {
|
||||||
|
log.info("terminal eof回调 {}, forClose: {}", sessionId, this.close);
|
||||||
|
// 发送关闭信息
|
||||||
|
TerminalCloseResponse resp = TerminalCloseResponse.builder()
|
||||||
|
.type(OutputTypeEnum.CLOSE.getType())
|
||||||
|
.sessionId(this.sessionId)
|
||||||
|
.msg(TerminalMessage.CLOSED_CONNECTION)
|
||||||
|
.build();
|
||||||
|
WebSockets.sendText(channel, OutputTypeEnum.CLOSE.format(resp));
|
||||||
|
// 需要调用关闭 - 可能是 logout 需要手动触发
|
||||||
|
this.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class TerminalPreferenceStrategy implements IPreferenceStrategy<TerminalP
|
|||||||
.newConnectionType("group")
|
.newConnectionType("group")
|
||||||
.displaySetting(TerminalPreferenceModel.DisplaySettingModel.builder()
|
.displaySetting(TerminalPreferenceModel.DisplaySettingModel.builder()
|
||||||
.fontFamily("_")
|
.fontFamily("_")
|
||||||
.fontSize(15)
|
.fontSize(12)
|
||||||
.lineHeight(1.00)
|
.lineHeight(1.00)
|
||||||
.fontWeight("normal")
|
.fontWeight("normal")
|
||||||
.fontWeightBold("bold")
|
.fontWeightBold("bold")
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type {
|
|||||||
InputPayload,
|
InputPayload,
|
||||||
ITerminalChannel,
|
ITerminalChannel,
|
||||||
ITerminalOutputProcessor,
|
ITerminalOutputProcessor,
|
||||||
|
ITerminalSessionManager,
|
||||||
OutputPayload,
|
OutputPayload,
|
||||||
Protocol,
|
Protocol,
|
||||||
} from '../types/terminal.type';
|
} from '../types/terminal.type';
|
||||||
@@ -9,6 +10,7 @@ import { OutputProtocol } from '../types/terminal.protocol';
|
|||||||
import { getHostTerminalAccessToken } from '@/api/asset/host-terminal';
|
import { getHostTerminalAccessToken } from '@/api/asset/host-terminal';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import { sleep } from '@/utils';
|
import { sleep } from '@/utils';
|
||||||
|
import TerminalOutputProcessor from './terminal-output-processor';
|
||||||
|
|
||||||
export const wsBase = import.meta.env.VITE_WS_BASE_URL;
|
export const wsBase = import.meta.env.VITE_WS_BASE_URL;
|
||||||
|
|
||||||
@@ -17,10 +19,10 @@ export default class TerminalChannel implements ITerminalChannel {
|
|||||||
|
|
||||||
private client?: WebSocket;
|
private client?: WebSocket;
|
||||||
|
|
||||||
private readonly processor;
|
private readonly processor: ITerminalOutputProcessor;
|
||||||
|
|
||||||
constructor(processor: ITerminalOutputProcessor) {
|
constructor(sessionManager: ITerminalSessionManager) {
|
||||||
this.processor = processor;
|
this.processor = new TerminalOutputProcessor(sessionManager, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
@@ -68,26 +70,14 @@ export default class TerminalChannel implements ITerminalChannel {
|
|||||||
if (!payload) {
|
if (!payload) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 消息调度
|
// 获取消息处理方法
|
||||||
switch (payload.type) {
|
const processMethod = Object.values(OutputProtocol)
|
||||||
case OutputProtocol.CHECK.type:
|
.find(protocol => protocol.type === payload.type)
|
||||||
// 检查 回调
|
?.processMethod;
|
||||||
this.processor.processCheck.call(this.processor, payload);
|
// 处理消息
|
||||||
break;
|
if (processMethod) {
|
||||||
case OutputProtocol.CONNECT.type:
|
const processMethodFn = this.processor[processMethod as keyof ITerminalOutputProcessor] as Function;
|
||||||
// 连接 回调
|
processMethodFn && processMethodFn.call(this.processor, payload);
|
||||||
this.processor.processConnect.call(this.processor, payload);
|
|
||||||
break;
|
|
||||||
case OutputProtocol.PONG.type:
|
|
||||||
// pong 回调
|
|
||||||
this.processor.processPong.call(this.processor, payload);
|
|
||||||
break;
|
|
||||||
case OutputProtocol.OUTPUT.type:
|
|
||||||
// 输出 回调
|
|
||||||
this.processor.processOutput.call(this.processor, payload);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import {
|
||||||
|
ITerminalChannel,
|
||||||
|
ITerminalOutputProcessor,
|
||||||
|
ITerminalSessionManager,
|
||||||
|
OutputPayload
|
||||||
|
} from '../types/terminal.type';
|
||||||
|
import { InputProtocol } from '../types/terminal.protocol';
|
||||||
|
|
||||||
|
// 终端输出消息体处理器实现
|
||||||
|
export default class TerminalOutputProcessor implements ITerminalOutputProcessor {
|
||||||
|
|
||||||
|
private readonly sessionManager: ITerminalSessionManager;
|
||||||
|
|
||||||
|
private readonly channel: ITerminalChannel;
|
||||||
|
|
||||||
|
constructor(sessionManager: ITerminalSessionManager, channel: ITerminalChannel) {
|
||||||
|
this.sessionManager = sessionManager;
|
||||||
|
this.channel = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理检查消息
|
||||||
|
processCheck({ sessionId, result, msg }: OutputPayload): void {
|
||||||
|
const success = !!Number.parseInt(result);
|
||||||
|
const session = this.sessionManager.getSession(sessionId);
|
||||||
|
// 未成功展示错误信息
|
||||||
|
if (!success) {
|
||||||
|
session.write(`[91m${msg || ''}[0m`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 发送 connect 命令
|
||||||
|
this.channel.send(InputProtocol.CONNECT, { sessionId, cols: session.inst.cols, rows: session.inst.rows });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理连接消息
|
||||||
|
processConnect({ sessionId, result, msg }: OutputPayload): void {
|
||||||
|
const success = !!Number.parseInt(result);
|
||||||
|
const session = this.sessionManager.getSession(sessionId);
|
||||||
|
// 未成功展示错误信息
|
||||||
|
if (!success) {
|
||||||
|
session.write(`[91m${msg || ''}[0m`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 设置可写
|
||||||
|
session.setCanWrite(true);
|
||||||
|
// 执行连接逻辑
|
||||||
|
session.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理关闭消息
|
||||||
|
processClose({ sessionId, msg }: OutputPayload): void {
|
||||||
|
const session = this.sessionManager.getSession(sessionId);
|
||||||
|
// 关闭 tab 则无需处理
|
||||||
|
if (session) {
|
||||||
|
// 提示消息
|
||||||
|
session.write(`\r\n[91m${msg || ''}[0m`);
|
||||||
|
// 设置状态
|
||||||
|
session.connected = false;
|
||||||
|
// 设置不可写
|
||||||
|
session.setCanWrite(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理 pong 消息
|
||||||
|
processPong(payload: OutputPayload): void {
|
||||||
|
console.log('pong');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理输出消息
|
||||||
|
processOutput({ sessionId, body }: OutputPayload): void {
|
||||||
|
const session = this.sessionManager.getSession(sessionId);
|
||||||
|
session && session.write(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,20 +1,13 @@
|
|||||||
import type {
|
import type { ITerminalChannel, ITerminalSession, ITerminalSessionManager, TerminalTabItem } from '../types/terminal.type';
|
||||||
ITerminalChannel,
|
|
||||||
ITerminalSession,
|
|
||||||
ITerminalSessionManager,
|
|
||||||
ITerminalOutputProcessor,
|
|
||||||
OutputPayload,
|
|
||||||
TerminalTabItem
|
|
||||||
} from '../types/terminal.type';
|
|
||||||
import { sleep } from '@/utils';
|
import { sleep } from '@/utils';
|
||||||
import { InputProtocol } from '../types/terminal.protocol';
|
import { InputProtocol } from '../types/terminal.protocol';
|
||||||
import TerminalSession from './terminal-session';
|
|
||||||
import { useDebounceFn } from '@vueuse/core';
|
import { useDebounceFn } from '@vueuse/core';
|
||||||
import TerminalChannel from '@/views/host/terminal/handler/terminal-channel';
|
|
||||||
import { addEventListen, removeEventListen } from '@/utils/event';
|
import { addEventListen, removeEventListen } from '@/utils/event';
|
||||||
|
import TerminalSession from './terminal-session';
|
||||||
|
import TerminalChannel from './terminal-channel';
|
||||||
|
|
||||||
// 终端会话管理器实现
|
// 终端会话管理器实现
|
||||||
export default class TerminalSessionManager implements ITerminalSessionManager, ITerminalOutputProcessor {
|
export default class TerminalSessionManager implements ITerminalSessionManager {
|
||||||
|
|
||||||
private readonly channel: ITerminalChannel;
|
private readonly channel: ITerminalChannel;
|
||||||
|
|
||||||
@@ -50,11 +43,33 @@ export default class TerminalSessionManager implements ITerminalSessionManager,
|
|||||||
this.sessions[sessionId] = session;
|
this.sessions[sessionId] = session;
|
||||||
// 发送会话初始化请求
|
// 发送会话初始化请求
|
||||||
this.channel.send(InputProtocol.CHECK, {
|
this.channel.send(InputProtocol.CHECK, {
|
||||||
session: sessionId,
|
sessionId,
|
||||||
hostId: hostId
|
hostId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取终端会话
|
||||||
|
getSession(sessionId: string): ITerminalSession {
|
||||||
|
return this.sessions[sessionId];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭终端会话
|
||||||
|
closeSession(sessionId: string): void {
|
||||||
|
// 发送关闭消息
|
||||||
|
this.channel?.send(InputProtocol.CLOSE, { sessionId });
|
||||||
|
// 关闭 session
|
||||||
|
const session = this.sessions[sessionId];
|
||||||
|
if (session) {
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
// 移除 session
|
||||||
|
this.sessions[sessionId] = undefined as unknown as ITerminalSession;
|
||||||
|
// session 全部关闭后 关闭 channel
|
||||||
|
if (Object.values(this.sessions).filter(Boolean).every(s => !s?.connected)) {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化 channel
|
// 初始化 channel
|
||||||
private async initChannel() {
|
private async initChannel() {
|
||||||
// 检查 channel 是否已经初始化
|
// 检查 channel 是否已经初始化
|
||||||
@@ -71,28 +86,6 @@ export default class TerminalSessionManager implements ITerminalSessionManager,
|
|||||||
}, 15000);
|
}, 15000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取终端会话
|
|
||||||
getSession(sessionId: string): ITerminalSession {
|
|
||||||
return this.sessions[sessionId];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关闭终端会话
|
|
||||||
closeSession(sessionId: string): void {
|
|
||||||
// 发送关闭消息
|
|
||||||
this.channel?.send(InputProtocol.CLOSE, { session: sessionId });
|
|
||||||
// 关闭 session
|
|
||||||
const session = this.sessions[sessionId];
|
|
||||||
if (session) {
|
|
||||||
session.close();
|
|
||||||
}
|
|
||||||
// 移除 session
|
|
||||||
this.sessions[sessionId] = undefined as unknown as ITerminalSession;
|
|
||||||
// session 全部关闭后 关闭 channel
|
|
||||||
if (Object.values(this.sessions).filter(Boolean).every(s => !s?.connected)) {
|
|
||||||
this.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调度重置大小
|
// 调度重置大小
|
||||||
private dispatchResize() {
|
private dispatchResize() {
|
||||||
// 对所有已连接的会话重置大小
|
// 对所有已连接的会话重置大小
|
||||||
@@ -101,45 +94,6 @@ export default class TerminalSessionManager implements ITerminalSessionManager,
|
|||||||
.forEach(h => h.fit());
|
.forEach(h => h.fit());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理检查消息
|
|
||||||
processCheck({ session: sessionId, result, errorMessage }: OutputPayload): void {
|
|
||||||
const success = !!Number.parseInt(result);
|
|
||||||
const session = this.sessions[sessionId];
|
|
||||||
// 未成功展示错误信息
|
|
||||||
if (!success) {
|
|
||||||
session.write('[91m' + errorMessage + '[0m');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 发送 connect 命令
|
|
||||||
this.channel.send(InputProtocol.CONNECT, { session: sessionId, cols: session.inst.cols, rows: session.inst.rows });
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理连接消息
|
|
||||||
processConnect({ session: sessionId, result, errorMessage }: OutputPayload): void {
|
|
||||||
const success = !!Number.parseInt(result);
|
|
||||||
const session = this.sessions[sessionId];
|
|
||||||
// 未成功展示错误信息
|
|
||||||
if (!success) {
|
|
||||||
session.write('[91m' + errorMessage + '[0m');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 设置可写
|
|
||||||
session.setCanWrite(true);
|
|
||||||
// 执行连接逻辑
|
|
||||||
session.connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理 pong 消息
|
|
||||||
processPong(payload: OutputPayload): void {
|
|
||||||
console.log('pong');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理输出消息
|
|
||||||
processOutput({ session: sessionId, body }: OutputPayload): void {
|
|
||||||
const session = this.sessions[sessionId];
|
|
||||||
session && session.write(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重置
|
// 重置
|
||||||
reset(): void {
|
reset(): void {
|
||||||
this.sessions = {};
|
this.sessions = {};
|
||||||
|
|||||||
@@ -73,14 +73,14 @@ export default class TerminalSession implements ITerminalSession {
|
|||||||
}
|
}
|
||||||
// 输入
|
// 输入
|
||||||
this.channel.send(InputProtocol.INPUT, {
|
this.channel.send(InputProtocol.INPUT, {
|
||||||
session: this.sessionId,
|
sessionId: this.sessionId,
|
||||||
command: s
|
command: s
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// 注册 resize 事件
|
// 注册 resize 事件
|
||||||
this.inst.onResize(({ cols, rows }) => {
|
this.inst.onResize(({ cols, rows }) => {
|
||||||
this.channel.send(InputProtocol.RESIZE, {
|
this.channel.send(InputProtocol.RESIZE, {
|
||||||
session: this.sessionId,
|
sessionId: this.sessionId,
|
||||||
cols,
|
cols,
|
||||||
rows
|
rows
|
||||||
});
|
});
|
||||||
@@ -90,6 +90,11 @@ export default class TerminalSession implements ITerminalSession {
|
|||||||
// 设置是否可写
|
// 设置是否可写
|
||||||
setCanWrite(canWrite: boolean): void {
|
setCanWrite(canWrite: boolean): void {
|
||||||
this.canWrite = canWrite;
|
this.canWrite = canWrite;
|
||||||
|
if (canWrite) {
|
||||||
|
this.inst.options.cursorBlink = useTerminalStore().preference.displaySetting.cursorBlink;
|
||||||
|
} else {
|
||||||
|
this.inst.options.cursorBlink = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 写入数据
|
// 写入数据
|
||||||
|
|||||||
@@ -3,17 +3,17 @@ export const InputProtocol = {
|
|||||||
// 主机连接检查
|
// 主机连接检查
|
||||||
CHECK: {
|
CHECK: {
|
||||||
type: 'ck',
|
type: 'ck',
|
||||||
template: ['type', 'session', 'hostId']
|
template: ['type', 'sessionId', 'hostId']
|
||||||
},
|
},
|
||||||
// 连接主机
|
// 连接主机
|
||||||
CONNECT: {
|
CONNECT: {
|
||||||
type: 'co',
|
type: 'co',
|
||||||
template: ['type', 'session', 'cols', 'rows']
|
template: ['type', 'sessionId', 'cols', 'rows']
|
||||||
},
|
},
|
||||||
// 关闭连接
|
// 关闭连接
|
||||||
CLOSE: {
|
CLOSE: {
|
||||||
type: 'cl',
|
type: 'cl',
|
||||||
template: ['type', 'session']
|
template: ['type', 'sessionId']
|
||||||
},
|
},
|
||||||
// ping
|
// ping
|
||||||
PING: {
|
PING: {
|
||||||
@@ -23,17 +23,17 @@ export const InputProtocol = {
|
|||||||
// 修改大小
|
// 修改大小
|
||||||
RESIZE: {
|
RESIZE: {
|
||||||
type: 'rs',
|
type: 'rs',
|
||||||
template: ['type', 'session', 'cols', 'rows']
|
template: ['type', 'sessionId', 'cols', 'rows']
|
||||||
},
|
},
|
||||||
// 执行
|
// 执行
|
||||||
EXEC: {
|
EXEC: {
|
||||||
type: 'e',
|
type: 'e',
|
||||||
template: ['type', 'session', 'command']
|
template: ['type', 'sessionId', 'command']
|
||||||
},
|
},
|
||||||
// 输入
|
// 输入
|
||||||
INPUT: {
|
INPUT: {
|
||||||
type: 'i',
|
type: 'i',
|
||||||
template: ['type', 'session', 'command']
|
template: ['type', 'sessionId', 'command']
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,21 +42,31 @@ export const OutputProtocol = {
|
|||||||
// 主机连接检查
|
// 主机连接检查
|
||||||
CHECK: {
|
CHECK: {
|
||||||
type: 'ck',
|
type: 'ck',
|
||||||
template: ['type', 'session', 'result', 'errorMessage']
|
template: ['type', 'sessionId', 'result', 'msg'],
|
||||||
|
processMethod: 'processCheck'
|
||||||
},
|
},
|
||||||
// 主机连接
|
// 主机连接
|
||||||
CONNECT: {
|
CONNECT: {
|
||||||
type: 'co',
|
type: 'co',
|
||||||
template: ['type', 'session', 'result', 'errorMessage']
|
template: ['type', 'sessionId', 'result', 'msg'],
|
||||||
|
processMethod: 'processConnect'
|
||||||
|
},
|
||||||
|
// 主机连接关闭
|
||||||
|
CLOSE: {
|
||||||
|
type: 'cl',
|
||||||
|
template: ['type', 'sessionId', 'msg'],
|
||||||
|
processMethod: 'processClose'
|
||||||
},
|
},
|
||||||
// pong
|
// pong
|
||||||
PONG: {
|
PONG: {
|
||||||
type: 'p',
|
type: 'p',
|
||||||
template: ['type']
|
template: ['type'],
|
||||||
|
processMethod: 'processPong'
|
||||||
},
|
},
|
||||||
// 输出
|
// 输出
|
||||||
OUTPUT: {
|
OUTPUT: {
|
||||||
type: 'o',
|
type: 'o',
|
||||||
template: ['type', 'session', 'body']
|
template: ['type', 'sessionId', 'body'],
|
||||||
|
processMethod: 'processOutput'
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ export interface TerminalTabItem {
|
|||||||
export interface Protocol {
|
export interface Protocol {
|
||||||
type: string;
|
type: string;
|
||||||
template: string[];
|
template: string[];
|
||||||
|
|
||||||
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 终端输入消息内容
|
// 终端输入消息内容
|
||||||
export interface InputPayload {
|
export interface InputPayload {
|
||||||
type?: string;
|
type?: string;
|
||||||
session?: string;
|
sessionId?: string;
|
||||||
|
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
@@ -26,7 +28,7 @@ export interface InputPayload {
|
|||||||
// 终端输出消息内容
|
// 终端输出消息内容
|
||||||
export interface OutputPayload {
|
export interface OutputPayload {
|
||||||
type: string;
|
type: string;
|
||||||
session: string;
|
sessionId: string;
|
||||||
|
|
||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
}
|
}
|
||||||
@@ -78,6 +80,8 @@ export interface ITerminalOutputProcessor {
|
|||||||
processCheck: (payload: OutputPayload) => void;
|
processCheck: (payload: OutputPayload) => void;
|
||||||
// 处理连接消息
|
// 处理连接消息
|
||||||
processConnect: (payload: OutputPayload) => void;
|
processConnect: (payload: OutputPayload) => void;
|
||||||
|
// 处理关闭消息
|
||||||
|
processClose: (payload: OutputPayload) => void;
|
||||||
// 处理 pong 消息
|
// 处理 pong 消息
|
||||||
processPong: (payload: OutputPayload) => void;
|
processPong: (payload: OutputPayload) => void;
|
||||||
// 处理输出消息
|
// 处理输出消息
|
||||||
|
|||||||
Reference in New Issue
Block a user