diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/TerminalMessageDispatcher.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/TerminalMessageDispatcher.java index 1b2d7bb5..86c45e45 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/TerminalMessageDispatcher.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/TerminalMessageDispatcher.java @@ -1,9 +1,7 @@ package com.orion.ops.module.asset.handler.host.terminal; -import com.alibaba.fastjson.JSON; import com.orion.ops.framework.websocket.core.handler.TextWebSocketHandler; -import com.orion.ops.module.asset.handler.host.terminal.entity.Message; -import com.orion.ops.module.asset.handler.host.terminal.enums.InputOperatorTypeEnum; +import com.orion.ops.module.asset.handler.host.terminal.enums.InputTypeEnum; import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -30,11 +28,10 @@ public class TerminalMessageDispatcher extends TextWebSocketHandler { public void onMessage(WebSocketSession session, String payload) { try { // 解析类型 - Message message = JSON.parseObject(payload, Message.class); - InputOperatorTypeEnum type = InputOperatorTypeEnum.of(message.getType()); + InputTypeEnum type = InputTypeEnum.of(payload); if (type != null) { - // 处理消息 - type.getHandler().process(session, message); + // 解析并处理消息 + type.getHandler().handle(session, type.parse(payload)); } } catch (Exception e) { log.error("TerminalDispatchHandler-handleMessage-error id: {}, msg: {}", session.getId(), payload, e); diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/Message.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/Message.java deleted file mode 100644 index 9236ec01..00000000 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/Message.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.orion.ops.module.asset.handler.host.terminal.entity; - -import com.alibaba.fastjson.annotation.JSONField; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 消息体包装 - * - * @author Jiahang Li - * @version 1.0.0 - * @since 2023/12/29 16:24 - */ -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -@Schema(name = "MessageWrapper", description = "消息体包装") -public class Message { - - @JSONField(name = "s") - @Schema(description = "会话id") - private String session; - - @JSONField(name = "t") - @Schema(description = "消息类型") - private String type; - - @JSONField(name = "b") - @Schema(description = "消息体") - private T body; - -} diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/enums/InputOperatorTypeEnum.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/enums/InputOperatorTypeEnum.java deleted file mode 100644 index 4d22199c..00000000 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/enums/InputOperatorTypeEnum.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.orion.ops.module.asset.handler.host.terminal.enums; - -import com.orion.ops.module.asset.handler.host.terminal.handler.ITerminalHandler; -import com.orion.ops.module.asset.handler.host.terminal.handler.TerminalCheckHandler; -import com.orion.ops.module.asset.handler.host.terminal.handler.TerminalConnectHandler; -import com.orion.spring.SpringHolder; -import lombok.Getter; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; - -/** - * 输入操作类型枚举 - * - * @author Jiahang Li - * @version 1.0.0 - * @since 2023/12/29 15:33 - */ -public enum InputOperatorTypeEnum { - - /** - * 主机连接检查 (临时 token 换实际 token / 检查权限) - */ - CHECK("ck", TerminalCheckHandler.class), - - /** - * 连接主机 - */ - CONNECT("co", TerminalConnectHandler.class), - - /** - * 关闭连接 - */ - CLOSE("cl", TerminalConnectHandler.class), - - /** - * ping - */ - PING("p", TerminalConnectHandler.class), - - /** - * 修改大小 - */ - RESIZE("rs", TerminalConnectHandler.class), - - /** - * 执行 - */ - EXEC("e", TerminalConnectHandler.class), - - /** - * 输入 - */ - INPUT("i", TerminalConnectHandler.class), - - ; - - @Getter - private final String type; - - private final Class handlerBean; - - @Getter - private ITerminalHandler handler; - - InputOperatorTypeEnum(String type, Class handlerBean) { - this.type = type; - this.handlerBean = handlerBean; - } - - public static InputOperatorTypeEnum of(String type) { - if (type == null) { - return null; - } - for (InputOperatorTypeEnum value : values()) { - if (value.type.equals(type)) { - return value; - } - } - return null; - } - - /** - * 类型字段定义 - */ - @Component - static class TypeFieldDefinition { - - @PostConstruct - public void init() { - for (InputOperatorTypeEnum value : InputOperatorTypeEnum.values()) { - value.handler = SpringHolder.getBean(value.handlerBean); - } - } - - } - -} diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/enums/InputTypeEnum.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/enums/InputTypeEnum.java new file mode 100644 index 00000000..c78c4cda --- /dev/null +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/enums/InputTypeEnum.java @@ -0,0 +1,168 @@ +package com.orion.ops.module.asset.handler.host.terminal.enums; + +import com.alibaba.fastjson.JSONObject; +import com.orion.ops.module.asset.handler.host.terminal.handler.ITerminalHandler; +import com.orion.ops.module.asset.handler.host.terminal.handler.TerminalCheckHandler; +import com.orion.ops.module.asset.handler.host.terminal.handler.TerminalConnectHandler; +import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload; +import com.orion.ops.module.asset.handler.host.terminal.model.request.TerminalCheckRequest; +import com.orion.ops.module.asset.handler.host.terminal.model.request.TerminalConnectRequest; +import com.orion.spring.SpringHolder; +import lombok.Getter; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * 输入操作类型枚举 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2023/12/29 15:33 + */ +public enum InputTypeEnum { + + /** + * 主机连接检查 置换token / 检查权限 + */ + CHECK("ck", + TerminalCheckHandler.class, + new String[]{"type", "session", "hostId"}, + TerminalCheckRequest.class), + + /** + * 连接主机 + */ + CONNECT("co", + TerminalConnectHandler.class, + new String[]{"type", "session", "cols", "rows"}, + TerminalConnectRequest.class), + + /** + * 关闭连接 + */ + CLOSE("cl", + TerminalConnectHandler.class, + new String[]{"type", "session"}, + TerminalConnectRequest.class), + + /** + * ping + */ + PING("p", + TerminalConnectHandler.class, + new String[]{"type", "session"}, + TerminalConnectRequest.class), + + /** + * 修改大小 + */ + RESIZE("rs", + TerminalConnectHandler.class, + new String[]{"type", "session", "cols", "rows"}, + TerminalConnectRequest.class), + + /** + * 执行 + */ + EXEC("e", + TerminalConnectHandler.class, + new String[]{"type", "session", "command"}, + TerminalConnectRequest.class), + + /** + * 输入 + */ + INPUT("i", + TerminalConnectHandler.class, + new String[]{"type", "session", "command"}, + TerminalConnectRequest.class), + + ; + + private static final char SEPARATOR = '|'; + + @Getter + private final String type; + + private final Class> handlerBean; + + private final String[] payloadDefine; + + private final Class payloadClass; + + @Getter + private ITerminalHandler handler; + + InputTypeEnum(String type, + Class> handlerBean, + String[] payloadDefine, + Class payloadClass) { + this.type = type; + this.handlerBean = handlerBean; + this.payloadDefine = payloadDefine; + this.payloadClass = payloadClass; + } + + public static InputTypeEnum of(String payload) { + if (payload == null) { + return null; + } + for (InputTypeEnum value : values()) { + if (payload.startsWith(value.type + SEPARATOR)) { + return value; + } + } + return null; + } + + /** + * 解析请求 + * + * @param payload payload + * @param T + * @return payload + */ + @SuppressWarnings("unchecked") + public T parse(String payload) { + JSONObject object = new JSONObject(); + int curr = 0; + int len = payload.length(); + for (int i = 0, pl = payloadDefine.length; i < pl; i++) { + if (i == pl - 1) { + // 最后一次 + object.put(payloadDefine[i], payload.substring(curr, len)); + } else { + // 非最后一次 + StringBuilder tmp = new StringBuilder(); + for (; curr < len; curr++) { + char c = payload.charAt(curr); + if (c == SEPARATOR) { + object.put(payloadDefine[i], tmp.toString()); + curr++; + break; + } else { + tmp.append(c); + } + } + } + } + return (T) object.toJavaObject(payloadClass); + } + + /** + * 类型字段定义 + */ + @Component + static class TypeFieldDefinition { + + @PostConstruct + public void init() { + for (InputTypeEnum value : InputTypeEnum.values()) { + value.handler = SpringHolder.getBean(value.handlerBean); + } + } + + } + +} diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/enums/OutputOperatorTypeEnum.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/enums/OutputOperatorTypeEnum.java deleted file mode 100644 index cb9c3ffa..00000000 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/enums/OutputOperatorTypeEnum.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.orion.ops.module.asset.handler.host.terminal.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 输出操作类型枚举 - * - * @author Jiahang Li - * @version 1.0.0 - * @since 2023/12/29 15:33 - */ -@Getter -@AllArgsConstructor -public enum OutputOperatorTypeEnum { - - /** - * 主机连接检查 - */ - CHECK("ck"), - - /** - * 主机连接 - */ - CONNECT("co"), - - /** - * pong - */ - PONG("p"), - - /** - * 输出 - */ - OUTPUT("o"), - - /** - * 发生错误 - */ - ERROR("e"), - - ; - - private final String type; - - public static OutputOperatorTypeEnum of(String type) { - if (type == null) { - return null; - } - for (OutputOperatorTypeEnum value : values()) { - if (value.type.equals(type)) { - return value; - } - } - return null; - } - -} diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/enums/OutputTypeEnum.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/enums/OutputTypeEnum.java new file mode 100644 index 00000000..9cd3d9c0 --- /dev/null +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/enums/OutputTypeEnum.java @@ -0,0 +1,73 @@ +package com.orion.ops.module.asset.handler.host.terminal.enums; + +import com.orion.lang.utils.json.matcher.ReplacementFormatters; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 输出操作类型枚举 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2023/12/29 15:33 + */ +@Getter +@AllArgsConstructor +public enum OutputTypeEnum { + + /** + * 主机连接检查 + */ + CHECK("ck", "${type}|${session}|${token}|${result}|${errorMessage}"), + + /** + * 主机连接 + */ + CONNECT("co", "${type}|${session}|${result}|${errorMessage}"), + + /** + * pong + */ + PONG("p", "${type}|${session}"), + + /** + * 输出 + */ + OUTPUT("o", "${type}|${session}|${body}"), + + /** + * 发生错误 + */ + ERROR("e", "${type}|${session}"), + + ; + + private static final char SEPARATOR = '|'; + + private final String type; + + private final String template; + + /** + * 格式化 + * + * @param o o + * @return 格式化 + */ + public String format(Object o) { + return ReplacementFormatters.format(this.template, o); + } + + public static OutputTypeEnum of(String type) { + if (type == null) { + return null; + } + for (OutputTypeEnum value : values()) { + if (value.type.equals(type)) { + return value; + } + } + return null; + } + +} diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/AbstractTerminalHandler.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/AbstractTerminalHandler.java index 316b9d29..0d58ae91 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/AbstractTerminalHandler.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/AbstractTerminalHandler.java @@ -1,9 +1,8 @@ package com.orion.ops.module.asset.handler.host.terminal.handler; -import com.alibaba.fastjson.JSONObject; import com.orion.ops.framework.websocket.core.utils.WebSockets; -import com.orion.ops.module.asset.handler.host.terminal.entity.Message; -import com.orion.ops.module.asset.handler.host.terminal.enums.OutputOperatorTypeEnum; +import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum; +import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload; import org.springframework.web.socket.WebSocketSession; /** @@ -13,61 +12,20 @@ import org.springframework.web.socket.WebSocketSession; * @version 1.0.0 * @since 2023/12/29 18:59 */ -public abstract class AbstractTerminalHandler implements ITerminalHandler { - - /** - * 类型 - */ - private final Class convert; - - public AbstractTerminalHandler(Class convert) { - this.convert = convert; - } - - @Override - @SuppressWarnings("unchecked") - public void process(WebSocketSession session, Message message) { - Message res = (Message) message; - res.setBody(((JSONObject) message.getBody()).toJavaObject(convert)); - this.handle(session, res); - } - - /** - * 处理消息 - * - * @param session session - * @param msg msg - */ - protected abstract void handle(WebSocketSession session, Message msg); - - /** - * 获取响应结构 - * - * @param in in - * @param type type - * @param body body - * @param E - * @return out - */ - public Message out(Message in, OutputOperatorTypeEnum type, E body) { - return Message.builder() - .session(in.getSession()) - .type(type.getType()) - .body(body) - .build(); - } +public abstract class AbstractTerminalHandler implements ITerminalHandler { /** * 发送消息 * * @param session session - * @param in in * @param type type * @param body body + * @param E */ - public void send(WebSocketSession session, Message in, OutputOperatorTypeEnum type, Object body) { + public void send(WebSocketSession session, OutputTypeEnum type, E body) { + body.setType(type.getType()); // 发送消息 - this.send(session, this.out(in, type, body)); + this.send(session, type.format(body)); } /** @@ -76,8 +34,8 @@ public abstract class AbstractTerminalHandler implements ITerminalHandler { * @param session session * @param message message */ - protected void send(WebSocketSession session, Message message) { - WebSockets.sendJson(session, message); + protected void send(WebSocketSession session, String message) { + WebSockets.sendText(session, message); } /** diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/ITerminalHandler.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/ITerminalHandler.java index a280d418..a42bee2a 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/ITerminalHandler.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/ITerminalHandler.java @@ -1,6 +1,6 @@ package com.orion.ops.module.asset.handler.host.terminal.handler; -import com.orion.ops.module.asset.handler.host.terminal.entity.Message; +import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload; import org.springframework.web.socket.WebSocketSession; /** @@ -10,14 +10,14 @@ import org.springframework.web.socket.WebSocketSession; * @version 1.0.0 * @since 2023/12/29 18:53 */ -public interface ITerminalHandler { +public interface ITerminalHandler { /** * 处理消息 * * @param session session - * @param message message + * @param payload payload */ - void process(WebSocketSession session, Message message); + void handle(WebSocketSession session, T payload); } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/TerminalCheckHandler.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/TerminalCheckHandler.java index d8d66b2e..293352cd 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/TerminalCheckHandler.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/handler/TerminalCheckHandler.java @@ -15,10 +15,9 @@ import com.orion.ops.module.asset.entity.dto.HostTerminalConnectDTO; import com.orion.ops.module.asset.entity.request.host.HostConnectLogCreateRequest; import com.orion.ops.module.asset.enums.HostConnectStatusEnum; import com.orion.ops.module.asset.enums.HostConnectTypeEnum; -import com.orion.ops.module.asset.handler.host.terminal.entity.Message; -import com.orion.ops.module.asset.handler.host.terminal.entity.request.TerminalCheckRequest; -import com.orion.ops.module.asset.handler.host.terminal.entity.response.TerminalCheckResponse; -import com.orion.ops.module.asset.handler.host.terminal.enums.OutputOperatorTypeEnum; +import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum; +import com.orion.ops.module.asset.handler.host.terminal.model.request.TerminalCheckRequest; +import com.orion.ops.module.asset.handler.host.terminal.model.response.TerminalCheckResponse; import com.orion.ops.module.asset.service.HostConnectLogService; import com.orion.ops.module.asset.service.HostTerminalService; import lombok.extern.slf4j.Slf4j; @@ -51,25 +50,26 @@ public class TerminalCheckHandler extends AbstractTerminalHandler msg) { - Long hostId = msg.getBody().getHostId(); + public void handle(WebSocketSession session, TerminalCheckRequest payload) { + Long hostId = payload.getHostId(); Long userId = this.getAttr(session, ExtraFieldConst.USER_ID); long startTime = System.currentTimeMillis(); - String terminalToken = UUIds.random15(); - log.info("TerminalCheckHandler-handle start userId: {}, hostId: {}, terminalToken: {}", userId, hostId, terminalToken); + String token = UUIds.random15(); + log.info("TerminalCheckHandler-handle start userId: {}, hostId: {}, token: {}", userId, hostId, token); // 查询主机信息 HostDO host = hostDAO.selectById(hostId); // 不存在返回错误信息 if (host == null) { log.info("TerminalCheckHandler-handle unknown host userId: {}, hostId: {}", userId, hostId); - this.send(session, msg, - OutputOperatorTypeEnum.CHECK, - new TerminalCheckResponse(terminalToken, BooleanBit.FALSE.getValue(), ErrorMessage.HOST_ABSENT)); + this.send(session, + OutputTypeEnum.CHECK, + TerminalCheckResponse.builder() + .session(payload.getSession()) + .token(token) + .result(BooleanBit.FALSE.getValue()) + .errorMessage(ErrorMessage.HOST_ABSENT) + .build()); return; } Exception ex = null; @@ -77,19 +77,20 @@ public class TerminalCheckHandler extends AbstractTerminalHandler msg) { - String token = msg.getSession(); + public void handle(WebSocketSession session, TerminalConnectRequest payload) { + String token = payload.getSession(); log.info("TerminalConnectHandler-handle start token: {}", token); // 获取主机连接信息 HostTerminalConnectDTO connect = this.getAttr(session, token); if (connect == null) { log.info("TerminalConnectHandler-handle unknown token: {}", token); - this.send(session, msg, - OutputOperatorTypeEnum.CONNECT, - new TerminalConnectResponse(BooleanBit.FALSE.getValue(), ErrorMessage.SESSION_ABSENT)); + this.send(session, + OutputTypeEnum.CONNECT, + TerminalConnectResponse.builder() + .session(payload.getSession()) + .result(BooleanBit.FALSE.getValue()) + .errorMessage(ErrorMessage.SESSION_ABSENT) + .build()); return; } // 移除会话连接信息 @@ -68,7 +68,7 @@ public class TerminalConnectHandler extends AbstractTerminalHandler + * ck|eff00a1|1 * * @author Jiahang Li * @version 1.0.0 * @since 2023/12/29 16:20 */ @Data -@Builder +@SuperBuilder @NoArgsConstructor @AllArgsConstructor +@EqualsAndHashCode(callSuper = true) @Schema(name = "TerminalConnectRequest", description = "主机连接检查请求 实体对象") -public class TerminalCheckRequest { +public class TerminalCheckRequest extends TerminalBasePayload { - // 连接主机 {"t":"ck","s": "1001","b":{"h":1}} - - @JSONField(name = "h") @Schema(description = "主机id") private Long hostId; diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/request/TerminalConnectRequest.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/model/request/TerminalConnectRequest.java similarity index 58% rename from orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/request/TerminalConnectRequest.java rename to orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/model/request/TerminalConnectRequest.java index 90fec032..06264ac2 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/request/TerminalConnectRequest.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/model/request/TerminalConnectRequest.java @@ -1,33 +1,33 @@ -package com.orion.ops.module.asset.handler.host.terminal.entity.request; +package com.orion.ops.module.asset.handler.host.terminal.model.request; -import com.alibaba.fastjson.annotation.JSONField; +import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; /** * 终端连接请求 实体对象 + *

+ * co|eff00a1|100|20 * * @author Jiahang Li * @version 1.0.0 * @since 2023/12/29 16:20 */ @Data -@Builder +@SuperBuilder @NoArgsConstructor @AllArgsConstructor +@EqualsAndHashCode(callSuper = true) @Schema(name = "TerminalConnectRequest", description = "终端连接请求 实体对象") -public class TerminalConnectRequest { +public class TerminalConnectRequest extends TerminalBasePayload { - // 连接主机 {"t":"co","s": "1001","b":{"c":100,"r":20}} - - @JSONField(name = "c") @Schema(description = "列数") private Integer cols; - @JSONField(name = "r") @Schema(description = "行数") private Integer rows; diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/request/TerminalResizeRequest.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/model/request/TerminalResizeRequest.java similarity index 58% rename from orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/request/TerminalResizeRequest.java rename to orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/model/request/TerminalResizeRequest.java index 10338586..16574560 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/request/TerminalResizeRequest.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/model/request/TerminalResizeRequest.java @@ -1,33 +1,33 @@ -package com.orion.ops.module.asset.handler.host.terminal.entity.request; +package com.orion.ops.module.asset.handler.host.terminal.model.request; -import com.alibaba.fastjson.annotation.JSONField; +import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; /** * 修改大小请求 实体对象 + *

+ * rs|eff00a1|100|20 * * @author Jiahang Li * @version 1.0.0 * @since 2023/12/29 16:20 */ @Data -@Builder +@SuperBuilder @NoArgsConstructor @AllArgsConstructor +@EqualsAndHashCode(callSuper = true) @Schema(name = "TerminalResizeRequest", description = "修改大小请求 实体对象") -public class TerminalResizeRequest { +public class TerminalResizeRequest extends TerminalBasePayload { - // 连接主机 {"t":"rs","s": "1001","b":{"c":100,"r":20}} - - @JSONField(name = "c") @Schema(description = "列数") private Integer cols; - @JSONField(name = "r") @Schema(description = "行数") private Integer rows; diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/response/TerminalCheckResponse.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/model/response/TerminalCheckResponse.java similarity index 57% rename from orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/response/TerminalCheckResponse.java rename to orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/model/response/TerminalCheckResponse.java index ff83054b..e8d0b826 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/response/TerminalCheckResponse.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/model/response/TerminalCheckResponse.java @@ -1,11 +1,12 @@ -package com.orion.ops.module.asset.handler.host.terminal.entity.response; +package com.orion.ops.module.asset.handler.host.terminal.model.response; -import com.alibaba.fastjson.annotation.JSONField; +import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; /** * 主机连接检查响应 实体对象 @@ -15,21 +16,19 @@ import lombok.NoArgsConstructor; * @since 2023/12/29 16:20 */ @Data -@Builder +@SuperBuilder @NoArgsConstructor @AllArgsConstructor +@EqualsAndHashCode(callSuper = true) @Schema(name = "TerminalCheckResponse", description = "主机连接检查响应 实体对象") -public class TerminalCheckResponse { +public class TerminalCheckResponse extends TerminalBasePayload { - @JSONField(name = "s") - @Schema(description = "会话id") - private String session; + @Schema(description = "token") + private String token; - @JSONField(name = "r") @Schema(description = "检查结果") private Integer result; - @JSONField(name = "em") @Schema(description = "错误信息") private String errorMessage; diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/response/TerminalConnectResponse.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/model/response/TerminalConnectResponse.java similarity index 60% rename from orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/response/TerminalConnectResponse.java rename to orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/model/response/TerminalConnectResponse.java index 5229d202..db20cd11 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/entity/response/TerminalConnectResponse.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/model/response/TerminalConnectResponse.java @@ -1,11 +1,12 @@ -package com.orion.ops.module.asset.handler.host.terminal.entity.response; +package com.orion.ops.module.asset.handler.host.terminal.model.response; -import com.alibaba.fastjson.annotation.JSONField; +import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; /** * 终端连接响应 实体对象 @@ -15,17 +16,16 @@ import lombok.NoArgsConstructor; * @since 2023/12/29 16:20 */ @Data -@Builder +@SuperBuilder @NoArgsConstructor @AllArgsConstructor +@EqualsAndHashCode(callSuper = true) @Schema(name = "TerminalConnectResponse", description = "终端连接响应 实体对象") -public class TerminalConnectResponse { +public class TerminalConnectResponse extends TerminalBasePayload { - @JSONField(name = "r") @Schema(description = "检查结果") private Integer result; - @JSONField(name = "em") @Schema(description = "错误信息") private String errorMessage; diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/model/response/TerminalOutputResponse.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/model/response/TerminalOutputResponse.java new file mode 100644 index 00000000..01efddc7 --- /dev/null +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/model/response/TerminalOutputResponse.java @@ -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 = "TerminalOutputResponse", description = "主机输出响应 实体对象") +public class TerminalOutputResponse extends TerminalBasePayload { + + @Schema(description = "body") + private String body; + +} diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/session/TerminalSession.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/session/TerminalSession.java index 77a6348d..4fda68de 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/session/TerminalSession.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/session/TerminalSession.java @@ -1,7 +1,5 @@ package com.orion.ops.module.asset.handler.host.terminal.session; -import com.alibaba.fastjson.JSON; -import com.orion.lang.utils.awt.Clipboards; import com.orion.lang.utils.io.Streams; import com.orion.net.host.SessionStore; import com.orion.net.host.ssh.TerminalType; @@ -9,8 +7,9 @@ import com.orion.net.host.ssh.shell.ShellExecutor; import com.orion.ops.framework.common.constant.Const; import com.orion.ops.framework.websocket.core.utils.WebSockets; import com.orion.ops.module.asset.define.AssetThreadPools; -import com.orion.ops.module.asset.handler.host.terminal.entity.Message; -import com.orion.ops.module.asset.handler.host.terminal.enums.OutputOperatorTypeEnum; +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.response.TerminalOutputResponse; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.web.socket.WebSocketSession; @@ -18,7 +17,6 @@ import org.springframework.web.socket.WebSocketSession; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; -import java.nio.charset.StandardCharsets; /** * 终端会话 @@ -36,22 +34,32 @@ public class TerminalSession implements ITerminalSession { @Getter private final WebSocketSession session; + private final TerminalConfig config; + private final SessionStore sessionStore; private ShellExecutor executor; + @Getter + private String lastLine; + private volatile boolean close; public TerminalSession(String token, WebSocketSession session, - SessionStore sessionStore) { + SessionStore sessionStore, + TerminalConfig config) { this.token = token; this.session = session; this.sessionStore = sessionStore; + this.config = config; } @Override public void connect(int cols, int rows) { + config.setCols(cols); + config.setRows(rows); + // 打开 shell this.executor = sessionStore.getShellExecutor(); executor.terminalType(TerminalType.XTERM_256_COLOR); executor.size(cols, rows); @@ -66,6 +74,8 @@ public class TerminalSession implements ITerminalSession { if (!executor.isConnected()) { executor.connect(); } + config.setCols(cols); + config.setRows(rows); executor.size(cols, rows); executor.resize(); } @@ -90,7 +100,7 @@ public class TerminalSession implements ITerminalSession { Streams.close(executor); Streams.close(sessionStore); } catch (Exception e) { - log.error("terminal 断开连接 失败 token: {}, {}", token, e); + log.error("terminal 断开连接 失败 token: {}", token, e); } } @@ -105,16 +115,14 @@ public class TerminalSession implements ITerminalSession { int read; try { while (session.isOpen() && (read = in.read(bs)) != -1) { + String body = lastLine = new String(bs, 0, read, config.getCharset()); // 响应 - String body = new String(bs, 0, read, StandardCharsets.UTF_8); - // TODO lastline - Message msg = Message.builder() + TerminalOutputResponse resp = TerminalOutputResponse.builder() .session(token) - .type(OutputOperatorTypeEnum.OUTPUT.getType()) - // FIXME TERMINAL charset + .type(OutputTypeEnum.OUTPUT.getType()) .body(body) .build(); - WebSockets.sendJson(session, msg); + WebSockets.sendText(session, OutputTypeEnum.OUTPUT.format(resp)); } } catch (IOException ex) { log.error("terminal 读取流失败", ex);