mirror of
https://github.com/gravitational/teleport
synced 2024-10-22 10:13:21 +00:00
(web) more xtermjs related changes and cleanup
This commit is contained in:
parent
2cb82a5dbe
commit
e969e55dc4
|
@ -15,16 +15,16 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PartyListPanel from './../partyListPanel';
|
||||
import { connect } from 'nuclear-js-react-addons';
|
||||
import { EventTypeEnum } from 'app/lib/term/enums';
|
||||
import Terminal from 'app/lib/term/terminal';
|
||||
import termGetters from 'app/flux/terminal/getters';
|
||||
import Indicator from './../indicator.jsx';
|
||||
import { initTerminal, updateRoute, close } from 'app/flux/terminal/actions';
|
||||
import { updateSession } from 'app/flux/sessions/actions';
|
||||
import { openPlayer } from 'app/flux/player/actions';
|
||||
import PartyListPanel from './../partyListPanel';
|
||||
import Indicator from './../indicator.jsx';
|
||||
import PartyList from './terminalPartyList';
|
||||
import { EventTypeEnum } from 'app/lib/term/enums';
|
||||
import { connect } from 'nuclear-js-react-addons';
|
||||
|
||||
class TerminalHost extends React.Component {
|
||||
|
||||
|
@ -117,25 +117,13 @@ class TerminalContainer extends React.Component {
|
|||
return ( <div ref="container"/> );
|
||||
}
|
||||
|
||||
receiveEvents(data) {
|
||||
// loop through events in reverse order to find the last resize event to sync the screen size.
|
||||
data.events.reverse().every(item => {
|
||||
let { event, size } = item;
|
||||
|
||||
// exit terminal if session is ended
|
||||
if (event === EventTypeEnum.END) {
|
||||
close();
|
||||
}
|
||||
|
||||
if (event === EventTypeEnum.RESIZE) {
|
||||
let [w, h] = size.split(':');
|
||||
this.terminal.resize(Number(w), Number(h));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
receiveEvents(data) {
|
||||
let hasEnded = data.events.some(item => item.event === EventTypeEnum.END);
|
||||
if (hasEnded) {
|
||||
close();
|
||||
}
|
||||
|
||||
// updates active sessin participant list
|
||||
updateSession({
|
||||
siteId: this.props.siteId,
|
||||
json: data.session
|
||||
|
|
|
@ -1,6 +1,26 @@
|
|||
/*
|
||||
Copyright 2015 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
export const EventTypeEnum = {
|
||||
START: 'session.start',
|
||||
END: 'session.end',
|
||||
PRINT: 'print',
|
||||
RESIZE: 'resize'
|
||||
}
|
||||
|
||||
export const StatusCodeEnum = {
|
||||
NORMAL: 1000
|
||||
}
|
|
@ -58,7 +58,7 @@ class TtyTerminal {
|
|||
open() {
|
||||
$(this._el).addClass(GRV_CLASS);
|
||||
|
||||
// render xtermjs with default values (will be used to calculate the character size)
|
||||
// render xtermjs with default values
|
||||
this.term = new Term({
|
||||
cols: 15,
|
||||
rows: 5,
|
||||
|
@ -68,20 +68,25 @@ class TtyTerminal {
|
|||
|
||||
this.term.open(this._el);
|
||||
|
||||
// resize to available space (by given container)
|
||||
// resize xterm to available space
|
||||
this.resize(this.cols, this.rows);
|
||||
|
||||
// subscribe xtermjs output
|
||||
// subscribe to xtermjs output
|
||||
this.term.on('data', data => this.tty.send(data));
|
||||
|
||||
// subscribe to tty events
|
||||
this.tty.on('resize', ({h, w}) => this.resize(w, h));
|
||||
|
||||
// subscribe to tty
|
||||
this.tty.on('reset', this.reset.bind(this));
|
||||
this.tty.on('close', this._processClose.bind(this));
|
||||
this.tty.on('data', this._processData.bind(this));
|
||||
|
||||
this.connect();
|
||||
this.tty.on('data', this._processData.bind(this));
|
||||
|
||||
// subscribe tty resize event (used by session player)
|
||||
this.tty.on('resize', ({h, w}) => this.resize(w, h));
|
||||
// subscribe to window resize events
|
||||
window.addEventListener('resize', this.debouncedResize);
|
||||
// subscribe to session resize events (triggered by other participants)
|
||||
this.ttyEvents.on('resize', ({h, w}) => this.resize(w, h));
|
||||
|
||||
this.connect();
|
||||
}
|
||||
|
||||
connect(){
|
||||
|
@ -113,7 +118,7 @@ class TtyTerminal {
|
|||
rows = dim.rows;
|
||||
}
|
||||
|
||||
if( cols === this.cols && rows === this.rows){
|
||||
if(cols === this.cols && rows === this.rows){
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -122,7 +127,7 @@ class TtyTerminal {
|
|||
|
||||
this.term.resize(cols, rows);
|
||||
} catch (err) {
|
||||
logger.info('resize', { w: cols, h: rows }, err);
|
||||
logger.error('resize', { w: cols, h: rows }, err);
|
||||
this.term.reset();
|
||||
}
|
||||
}
|
||||
|
@ -149,15 +154,11 @@ class TtyTerminal {
|
|||
this.term.write(displayText)
|
||||
}
|
||||
|
||||
_disconnect() {
|
||||
if(this.tty !== null){
|
||||
this.tty.disconnect();
|
||||
}
|
||||
|
||||
if(this.ttyEvents !== null){
|
||||
this.ttyEvents.disconnect();
|
||||
this.ttyEvents.removeAllListeners();
|
||||
}
|
||||
_disconnect() {
|
||||
this.tty.disconnect();
|
||||
this.tty.removeAllListeners();
|
||||
this.ttyEvents.disconnect();
|
||||
this.ttyEvents.removeAllListeners();
|
||||
}
|
||||
|
||||
_requestResize(){
|
||||
|
@ -174,7 +175,7 @@ class TtyTerminal {
|
|||
|
||||
logger.info('requesting new screen size', `w:${w} and h:${h}`);
|
||||
this.resize(w, h);
|
||||
api.put(`${url}/sessions/${sid}`, reqData)
|
||||
api.put(`${url}/sessions/${sid}`, reqData)
|
||||
.fail(err => logger.error('request new screen size', err));
|
||||
}
|
||||
|
||||
|
@ -221,11 +222,9 @@ class TtyTerminal {
|
|||
let urlPrefix = getWsHostName();
|
||||
|
||||
return `${urlPrefix}${url}/connect?access_token=${token}¶ms=${jsonEncoded}`;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getWsHostName(){
|
||||
var prefix = location.protocol == "https:"?"wss://":"ws://";
|
||||
var hostport = location.hostname+(location.port ? ':'+location.port: '');
|
||||
|
|
|
@ -15,7 +15,10 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import { EventEmitter } from 'events';
|
||||
import { StatusCodeEnum } from './ttyEnums';
|
||||
import { StatusCodeEnum } from './enums';
|
||||
import Logger from './../logger';
|
||||
|
||||
const logger = Logger.create('Tty');
|
||||
|
||||
const defaultOptions = {
|
||||
buffered: true
|
||||
|
@ -41,19 +44,12 @@ class Tty extends EventEmitter {
|
|||
this._onReceiveData = this._onReceiveData.bind(this);
|
||||
}
|
||||
|
||||
disconnect(reasonCode = StatusCodeEnum.NORMAL){
|
||||
this.socket.close(reasonCode);
|
||||
disconnect(reasonCode = StatusCodeEnum.NORMAL) {
|
||||
if (this.socket !== null) {
|
||||
this.socket.close(reasonCode);
|
||||
}
|
||||
}
|
||||
|
||||
reconnect(options){
|
||||
this.disconnect();
|
||||
this.socket.onopen = null;
|
||||
this.socket.onmessage = null;
|
||||
this.socket.onclose = null;
|
||||
this.socket = null;
|
||||
this.connect(options);
|
||||
}
|
||||
|
||||
|
||||
connect(connStr) {
|
||||
this.socket = new WebSocket(connStr);
|
||||
this.socket.onopen = this._onOpenConnection;
|
||||
|
@ -83,10 +79,16 @@ class Tty extends EventEmitter {
|
|||
|
||||
_onOpenConnection() {
|
||||
this.emit('open');
|
||||
logger.info('websocket is open');
|
||||
}
|
||||
|
||||
_onCloseConnection(e) {
|
||||
this.socket.onopen = null;
|
||||
this.socket.onmessage = null;
|
||||
this.socket.onclose = null;
|
||||
this.socket = null;
|
||||
this.emit('close', e);
|
||||
logger.info('websocket is closed');
|
||||
}
|
||||
|
||||
_onReceiveData(ev) {
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
Copyright 2015 Gravitational, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
const StatusCodeEnum = {
|
||||
NORMAL: 1000
|
||||
}
|
||||
|
||||
export {
|
||||
StatusCodeEnum
|
||||
}
|
|
@ -15,42 +15,70 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import { EventEmitter } from 'events';
|
||||
import { StatusCodeEnum } from './ttyEnums';
|
||||
import { StatusCodeEnum, EventTypeEnum } from './enums';
|
||||
import { sortBy } from 'lodash';
|
||||
|
||||
const logger = require('./../logger').create('TtyEvents');
|
||||
import Logger from './../logger';
|
||||
|
||||
const logger = Logger.create('TtyEvents');
|
||||
|
||||
class TtyEvents extends EventEmitter {
|
||||
|
||||
constructor(){
|
||||
super();
|
||||
super();
|
||||
this.socket = null;
|
||||
}
|
||||
|
||||
connect(connStr){
|
||||
this.socket = new WebSocket(connStr);
|
||||
|
||||
this.socket.onmessage = this._onReceiveMessage.bind(this);
|
||||
this.socket.onclose = this._onCloseConnection.bind(this);
|
||||
this.socket.onopen = () => {
|
||||
logger.info('Tty event stream is open');
|
||||
}
|
||||
|
||||
this.socket.onmessage = (event) => {
|
||||
try
|
||||
{
|
||||
let json = JSON.parse(event.data);
|
||||
this.emit('data', json);
|
||||
}
|
||||
catch(err){
|
||||
logger.error('failed to parse event stream data', err);
|
||||
}
|
||||
};
|
||||
|
||||
this.socket.onclose = () => {
|
||||
logger.info('Tty event stream is closed');
|
||||
};
|
||||
logger.info('websocket is open');
|
||||
}
|
||||
}
|
||||
|
||||
disconnect(reasonCode = StatusCodeEnum.NORMAL){
|
||||
this.socket.close(reasonCode);
|
||||
disconnect(reasonCode = StatusCodeEnum.NORMAL) {
|
||||
if (this.socket !== null) {
|
||||
this.socket.close(reasonCode);
|
||||
}
|
||||
}
|
||||
|
||||
_onCloseConnection(e) {
|
||||
this.socket.onmessage = null;
|
||||
this.socket.onopen = null;
|
||||
this.socket.onclose = null;
|
||||
this.emit('close', e);
|
||||
logger.info('websocket is closed');
|
||||
}
|
||||
|
||||
_onReceiveMessage(message) {
|
||||
try
|
||||
{
|
||||
let json = JSON.parse(message.data);
|
||||
this._processResize(json.events)
|
||||
this.emit('data', json);
|
||||
}
|
||||
catch(err){
|
||||
logger.error('failed to parse event stream data', err);
|
||||
}
|
||||
}
|
||||
|
||||
_processResize(events){
|
||||
events = events || [];
|
||||
// filter resize events
|
||||
let resizes = events.filter(
|
||||
item => item.event === EventTypeEnum.RESIZE);
|
||||
|
||||
sortBy(resizes, ['ms']);
|
||||
|
||||
if(resizes.length > 0){
|
||||
// get values from the last resize event
|
||||
let [w, h] = resizes[resizes.length-1].size.split(':');
|
||||
w = Number(w);
|
||||
h = Number(h);
|
||||
this.emit('resize', { w, h });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue