github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/app/utils/classes/exec-socket-xterm-adapter.js (about) 1 const ANSI_UI_GRAY_400 = '\x1b[38;2;142;150;163m'; 2 3 import { base64DecodeString, base64EncodeString } from 'nomad-ui/utils/encode'; 4 5 export const HEARTBEAT_INTERVAL = 10000; // ten seconds 6 7 export default class ExecSocketXtermAdapter { 8 constructor(terminal, socket, token) { 9 this.terminal = terminal; 10 this.socket = socket; 11 this.token = token; 12 13 socket.onopen = () => { 14 this.sendWsHandshake(); 15 this.sendTtySize(); 16 this.startHeartbeat(); 17 18 terminal.onData((data) => { 19 this.handleData(data); 20 }); 21 }; 22 23 socket.onmessage = (e) => { 24 let json = JSON.parse(e.data); 25 26 // stderr messages will not be produced as the socket is opened with the tty flag 27 if (json.stdout && json.stdout.data) { 28 terminal.write(base64DecodeString(json.stdout.data)); 29 } 30 }; 31 32 socket.onclose = () => { 33 this.stopHeartbeat(); 34 this.terminal.writeln(''); 35 this.terminal.write(ANSI_UI_GRAY_400); 36 this.terminal.writeln('The connection has closed.'); 37 // Issue to add interpretation of close events: https://github.com/hashicorp/nomad/issues/7464 38 }; 39 40 terminal.resized = () => { 41 this.sendTtySize(); 42 }; 43 } 44 45 sendTtySize() { 46 this.socket.send( 47 JSON.stringify({ 48 tty_size: { width: this.terminal.cols, height: this.terminal.rows }, 49 }) 50 ); 51 } 52 53 sendWsHandshake() { 54 this.socket.send( 55 JSON.stringify({ version: 1, auth_token: this.token || '' }) 56 ); 57 } 58 59 startHeartbeat() { 60 this.heartbeatTimer = setInterval(() => { 61 this.socket.send(JSON.stringify({})); 62 }, HEARTBEAT_INTERVAL); 63 } 64 65 stopHeartbeat() { 66 clearInterval(this.heartbeatTimer); 67 } 68 69 handleData(data) { 70 this.socket.send( 71 JSON.stringify({ stdin: { data: base64EncodeString(data) } }) 72 ); 73 } 74 }