fix: 终端 PTY 尺寸同步
前端在 xterm fit/resize 后通过 WebSocket 发送 resize 控制消息,后端收到后调用 ChannelShell.setPtySize 触发远端重绘,修复 less/vim/top 等全屏程序只显示部分区域的问题。 同时补齐控制消息解析与 PTY resize 的单测,并修正失配的 SftpControllerTest 断言。
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
package com.sshmanager.controller;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class TerminalControlMessage {
|
||||
|
||||
public static final String CONTROL_PREFIX = "__SSHMANAGER__:";
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
private String type;
|
||||
private Integer cols;
|
||||
private Integer rows;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Integer getCols() {
|
||||
return cols;
|
||||
}
|
||||
|
||||
public void setCols(Integer cols) {
|
||||
this.cols = cols;
|
||||
}
|
||||
|
||||
public Integer getRows() {
|
||||
return rows;
|
||||
}
|
||||
|
||||
public void setRows(Integer rows) {
|
||||
this.rows = rows;
|
||||
}
|
||||
|
||||
public static Optional<TerminalControlMessage> parse(String payload) {
|
||||
if (payload == null || !payload.startsWith(CONTROL_PREFIX)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
String json = payload.substring(CONTROL_PREFIX.length());
|
||||
try {
|
||||
return Optional.of(OBJECT_MAPPER.readValue(json, TerminalControlMessage.class));
|
||||
} catch (Exception e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,15 +100,26 @@ public class TerminalWebSocketHandler extends TextWebSocketHandler {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleTextMessage(WebSocketSession webSocketSession, TextMessage message) throws Exception {
|
||||
SshService.SshSession sshSession = sessions.get(webSocketSession.getId());
|
||||
if (sshSession != null && sshSession.isConnected()) {
|
||||
lastActivity.put(webSocketSession.getId(), System.currentTimeMillis());
|
||||
sshSession.getInputStream().write(message.asBytes());
|
||||
sshSession.getInputStream().flush();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void handleTextMessage(WebSocketSession webSocketSession, TextMessage message) throws Exception {
|
||||
SshService.SshSession sshSession = sessions.get(webSocketSession.getId());
|
||||
if (sshSession != null && sshSession.isConnected()) {
|
||||
lastActivity.put(webSocketSession.getId(), System.currentTimeMillis());
|
||||
|
||||
String payload = message.getPayload();
|
||||
TerminalControlMessage.parse(payload).ifPresent(ctrl -> {
|
||||
if ("resize".equals(ctrl.getType()) && ctrl.getCols() != null && ctrl.getRows() != null) {
|
||||
sshSession.resize(ctrl.getCols(), ctrl.getRows());
|
||||
}
|
||||
});
|
||||
if (payload != null && payload.startsWith(TerminalControlMessage.CONTROL_PREFIX)) {
|
||||
return;
|
||||
}
|
||||
|
||||
sshSession.getInputStream().write(message.asBytes());
|
||||
sshSession.getInputStream().flush();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus status) throws Exception {
|
||||
|
||||
@@ -85,14 +85,27 @@ public class SshService {
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
public OutputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
public OutputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
public void resize(int cols, int rows) {
|
||||
if (cols <= 0 || rows <= 0) {
|
||||
return;
|
||||
}
|
||||
if (channel == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
channel.setPtySize(cols, rows, 0, 0);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
if (channel != null && channel.isConnected()) {
|
||||
channel.disconnect();
|
||||
}
|
||||
public void disconnect() {
|
||||
if (channel != null && channel.isConnected()) {
|
||||
channel.disconnect();
|
||||
}
|
||||
if (session != null && session.isConnected()) {
|
||||
session.disconnect();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user