xterm.js icon indicating copy to clipboard operation
xterm.js copied to clipboard

Destructive console output after exiting vim editor

Open DmG-tech opened this issue 3 years ago • 5 comments

I am developing a remote terminal.
UI: Thymeleaf, xterm.js.
Back: Java, Spring boot, Apache sshd-core.
Connection between front and back - websocket (implement xterm-addon-attach from ui and TextWebSocketHandler from back).
Coonection between back and remote server/console - apache sshd-core.

Code for init and config terminal from UI:

    function initTerminal() {
        const protocol = "ws://";
        const host = document.location.host;
        const endpoint = contextPath + "/server/" + getServerId();
        const url = protocol + host + endpoint;
        websocket = new WebSocket(url);
        websocket.onmessage = function (data) {
            terminal.clear();
        };

        terminal = new Terminal(terminalOption);
        const attachAddon = new AttachAddon.AttachAddon(websocket);
        terminal.loadAddon(attachAddon);
        terminal.open(terminalContainer);
        terminal.focus();
    }

Copy, paste, backspace and other command and function work is correct, but if i am run VIM editor, I have many problems.

  1. When I am running VIM editor i have a log message from xterm.js in debug mode. Char in the example may be different. Example: xterm.js: Unknown CSI code: {"identifier": "H", "params": [1,1]}

  2. I have a very stranger output from remote server when i execute exit from VIM editor (use :q!command). Output can be different and depened from TERM env.

TERM=xterm-256colors output: 2RR0;276;0c10;rgb:cccc/cccc/cccc11;rgb:1c1c/2424/31312RR0;276;0c10;rgb:cccc/cccc/cccc11;rgb:1c1c/2424/31312RR0;276;0c10;rgb:cccc/cccc/cccc11;rgb:1c1c/2424/31312RR0;276;0c10;rgb:cccc/cccc/cccc11;rgb:1c1c/2424/31312RR0;276;0c10;rgb:cccc/cccc/cccc11;rgb:1c1c/2424/31312RR0;276;0c10;rgb:cccc/cccc/cccc11;rgb:1c1c/2424/31312RR0;276;0c10;rgb:cccc/cccc/cccc11;rgb:1c1c/2424/31312RR0;...

TERM=vt220 ouput: 2RR2RR2RR2RR2RR2RR2RR2RR2R...

If i use TERM=vt100, output is absent, but I don't have colors and many features like that mouse track control and other.

I want to have all features xterm's type terminal (include colors) work is correct. How i can configure TERM variable, UI or back for it and correct work? изображение_2022-09-19_171609 изображение_2022-09-19_171642

DmG-tech avatar Sep 19 '22 14:09 DmG-tech

@DmG-tech There is something really broken with your setup - the error message xterm.js: Unknown CSI code: {"identifier": "H", "params": [1,1]} basically means that xterm.js did not understand a CUP action. To my knowledge there is no version of xterm.js not supporting CUP. Either something screwed up your terminal instance, or your stream data contains opaque control codes not shown in the error message.

I suggest to start bytelevel debugging/inspecting of what was sent to the terminal. E.g. for CUP the byte sequence should exactly match \x1b[1;1H. You can get a hold of byte content sent to the terminal by setting its log level to 'debug' (as you already did above).

jerch avatar Sep 19 '22 21:09 jerch

@jerch I did an experiment. I dropped the websocket connection between the server and the client after exiting the vim editor, but the unrecognized output to the console in the form of "2RR..." continued to go. It seems to me that this sequence is related to mouse tracking, since it is it that turns on when opening vim. how can i disable sending mouse events but keep the terminal scrollable?

DmG-tech avatar Sep 20 '22 08:09 DmG-tech

Imho there are multiple issues hidden in your errors:

  • xterm.js: Unknown CSI code: {"identifier": "H", "params": [1,1]} - This should never have happened, if the backend was really sending a clean CUP sequence. Therefore you should check the exact byte content of the CUP sequence.
  • spurious output from different TERM settings: Those are control sequences sent by vim or any other advanced terminal app (e.g. curses apps) to configure the terminal. Idk where the ESC R and ESC 2 R come from, but 0;276;0c is part of DA2 report, and 10;rgb:cccc/cccc/cccc part of OSC 10 (both request and report). So this looks like your backend wrongly echoes those reports back to the terminal, thus you have an issue with termios attributes on a PTY between vim <--> several layers <--> terminal.
  • The mouse tracking may need onBinary event, if it uses X10 encoding.

All that being said, your issue is most likely not the frontend (browser side with xterm.js), but on server side and how you bind to the data stream from/to vim.

jerch avatar Sep 20 '22 10:09 jerch

Stream from client side implement with xterm-addon-attach (I didn't custom config for it). I send bytes array to remote console: if it's text i get bytes as UTF-8 charsets, else I send clear bytes array. Strem on server:

  1. handlers for websocket message:
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) {
        String serverId = getServerId(session);
        consoleService.sendCommand(serverId, message.getPayload());
    }

    @Override
    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
        String serverId = getServerId(session);
        consoleService.sendCommand(serverId, message.getPayload().array());
    }

2:

    public void sendCommand(String serverId, String command) {
        Optional<BaseRemoteConsole> optional = remoteConsoleRegistry.getRemoteConsole(serverId);
        if (optional.isPresent()) {
            BaseRemoteConsole console = optional.get();
            console.sendData(command.getBytes(StandardCharsets.UTF_8));
        } else {
            throw new ServerNotFoundException(serverId);
        }
    }

    public void sendCommand(String serverId, byte[] data) {
        Optional<BaseRemoteConsole> optional = remoteConsoleRegistry.getRemoteConsole(serverId);
        if (optional.isPresent()) {
            BaseRemoteConsole console = optional.get();
            console.sendData(data);
        } else {
            throw new ServerNotFoundException(serverId);
        }
    }

3:

public void sendData(byte[] data) {
        try {
            OutputStream invertedIn;
            if (this.channel != null) {
                invertedIn = this.channel.getInvertedIn();
            } else {
                throw new SshUtilException("Channel can not be null.");
            }
            invertedIn.write(data);
            invertedIn.flush();
        } catch (IOException e) {
            log.error(e.getMessage());
            throw new SshUtilException(e);
        }
    }

About X10 encoding: in start config mouseTrackingMode: "none". Wneh i open vim mouseTrackingMode: "vt200". How i set it to x10?

DmG-tech avatar Sep 20 '22 10:09 DmG-tech

Well idk anything about your ssh-lib or how to integrate that for terminal emulation. But could it be that the ssh client side is meant to run behind a PTY? It seems you send the ssh output directly to the terminal, which therefore lacks any PTY transformations on client side (ssh client side == your server integration).

How i set it to x10?

You dont set this as a terminal integrator, the app running on the PTY does that (its the responsibility of app side). But it looks like you already deal with binary chunks from the websocket.

jerch avatar Sep 20 '22 11:09 jerch