Unverified Commit 59bb6d40 authored by 老广's avatar 老广 Committed by GitHub

Koko (#81)

* [Update] 修改ws使用的库

* [Update] 去掉导入

* [Update] 修改ws

* [Update] 添加重连

* [Update] 添加ping机制

* [update] 去掉无用js

* [Update] 修改格式

* [Update] 兼容koko

* [update] 修改lock
parent 49a8cd28
This diff is collapsed.
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
"@swimlane/ngx-datatable": "^11.3.2", "@swimlane/ngx-datatable": "^11.3.2",
"@swimlane/ngx-ui": "^20.2.1", "@swimlane/ngx-ui": "^20.2.1",
"@types/jquery": "^3.3.6", "@types/jquery": "^3.3.6",
"@types/neffos.js": "^0.1.1",
"@types/socket.io-client": "^1.4.32", "@types/socket.io-client": "^1.4.32",
"ajv": "^6.5.0", "ajv": "^6.5.0",
"animate.css": "^3.6.1", "animate.css": "^3.6.1",
...@@ -49,6 +50,7 @@ ...@@ -49,6 +50,7 @@
"material-design-icons": "^3.0.1", "material-design-icons": "^3.0.1",
"materialize-css": "^0.100.2", "materialize-css": "^0.100.2",
"metismenu": "^2.7.9", "metismenu": "^2.7.9",
"neffos.js": "^0.1.19",
"ng2-charts": "^1.5.0", "ng2-charts": "^1.5.0",
"ngx-bootstrap": "^1.6.6", "ngx-bootstrap": "^1.6.6",
"ngx-cookie-service": "^1.0.10", "ngx-cookie-service": "^1.0.10",
...@@ -63,8 +65,8 @@ ...@@ -63,8 +65,8 @@
"roboto-fontface": "^0.8.0", "roboto-fontface": "^0.8.0",
"rxjs": "5.5.6", "rxjs": "5.5.6",
"sass-math": "^1.0.0", "sass-math": "^1.0.0",
"socket.io": "^2.1.0", "socket.io": "^1.4.32",
"socket.io-client": "^2.1.0", "socket.io-client": "^1.4.32",
"ssh-keygen": "^0.4.1", "ssh-keygen": "^0.4.1",
"tether": "^1.4.4", "tether": "^1.4.4",
"tslib": "^1.9.0", "tslib": "^1.9.0",
......
import {AfterViewInit, Component, Input, OnInit } from '@angular/core'; import {AfterViewInit, Component, Input, OnInit, OnDestroy } from '@angular/core';
import {Terminal} from 'xterm'; import {Terminal} from 'xterm';
import {NavList} from '../../pages/control/control/control.component'; import {NavList, View} from '../../pages/control/control/control.component';
import {UUIDService} from '../../app.service'; import {UUIDService} from '../../app.service';
import {CookieService} from 'ngx-cookie-service'; import {CookieService} from 'ngx-cookie-service';
import {TermWS} from '../../globals'; import {Socket} from '../../utils/socket';
import {getWsSocket} from '../../globals';
const ws = TermWS;
@Component({ @Component({
selector: 'elements-ssh-term', selector: 'elements-ssh-term',
templateUrl: './ssh-term.component.html', templateUrl: './ssh-term.component.html',
styleUrls: ['./ssh-term.component.scss'] styleUrls: ['./ssh-term.component.scss']
}) })
export class ElementSshTermComponent implements OnInit, AfterViewInit { export class ElementSshTermComponent implements OnInit, AfterViewInit, OnDestroy {
@Input() host: any; @Input() host: any;
@Input() userid: any; @Input() userid: any;
@Input() index: number; @Input() index: number;
...@@ -20,12 +20,27 @@ export class ElementSshTermComponent implements OnInit, AfterViewInit { ...@@ -20,12 +20,27 @@ export class ElementSshTermComponent implements OnInit, AfterViewInit {
term: Terminal; term: Terminal;
secret: string; secret: string;
ws: Socket;
roomID: string;
view: View;
constructor(private _uuid: UUIDService, private _cookie: CookieService) { constructor(private _uuid: UUIDService, private _cookie: CookieService) {
} }
ngOnInit() { ngOnInit() {
this.view = NavList.List[this.index];
this.secret = this._uuid.gen(); this.secret = this._uuid.gen();
this.newTerm();
getWsSocket().then(sock => {
this.ws = sock;
this.connectHost();
});
}
ngAfterViewInit() {
}
newTerm() {
const fontSize = localStorage.getItem('fontSize') || '14'; const fontSize = localStorage.getItem('fontSize') || '14';
this.term = new Terminal({ this.term = new Terminal({
fontFamily: 'monaco, Consolas, "Lucida Console", monospace', fontFamily: 'monaco, Consolas, "Lucida Console", monospace',
...@@ -35,73 +50,80 @@ export class ElementSshTermComponent implements OnInit, AfterViewInit { ...@@ -35,73 +50,80 @@ export class ElementSshTermComponent implements OnInit, AfterViewInit {
background: '#1f1b1b' background: '#1f1b1b'
} }
}); });
} this.view.Term = this.term;
ngAfterViewInit() {
this.joinRoom();
} }
changeWinSize(size: Array<number>) { changeWinSize(size: Array<number>) {
ws.emit('resize', {'cols': size[0], 'rows': size[1]}); if (this.ws) {
this.ws.emit('resize', {'cols': size[0], 'rows': size[1]});
}
} }
joinRoom() { connectHost() {
NavList.List[this.index].Term = this.term;
console.log(this.term);
console.log('Col: ', this.term.cols, 'rows', this.term.rows);
if (this.host) { if (this.host) {
ws.emit('host', { const data = {
'uuid': this.host.id, uuid: this.host.id,
'userid': this.userid, userid: this.userid,
'secret': this.secret, secret: this.secret,
'size': [this.term.cols, this.term.rows] size: [this.term.cols, this.term.rows]
}); };
this.ws.emit('host', data);
} }
if (this.token) { if (this.token) {
ws.emit('token', { const data = {
'token': this.token, 'secret': this.secret, 'token': this.token, 'secret': this.secret,
'size': [this.term.cols, this.term.rows] 'size': [this.term.cols, this.term.rows]
}); };
console.log('On token event trigger');
this.ws.emit('token', data);
} }
const that = this;
this.term.on('data', function (data) { this.term.on('data', data => {
ws.emit('data', {'data': data, 'room': NavList.List[that.index].room}); const d = {'data': data, 'room': this.roomID};
this.ws.emit('data', d);
}); });
ws.on('data', data => { this.ws.on('data', data => {
const view = NavList.List[that.index]; if (data.room === this.roomID) {
if (view && data['room'] === view.room) { this.term.write(data['data']);
that.term.write(data['data']);
} }
}); });
ws.on('disconnect', () => { // 服务器主动断开
that.close(); this.ws.on('disconnect', () => {
console.log('On disconnect event trigger');
this.close();
}); });
ws.on('logout', (data) => { this.ws.on('logout', data => {
if (data['room'] === NavList.List[that.index].room) { if (data.room === this.roomID) {
NavList.List[that.index].connected = false; console.log('On logout event trigger: ', data.room, this.roomID);
this.view.connected = false;
} }
}); });
ws.on('room', data => { this.ws.on('room', data => {
if (data['secret'] === this.secret) { if (data.secret === this.secret && data.room) {
NavList.List[that.index].room = data['room']; console.log('On room', data);
this.roomID = data.room;
this.view.room = data.room;
} }
}); });
} }
// 客户端主动关闭
close() { close() {
const view = NavList.List[this.index]; if (this.view && (this.view.room === this.roomID)) {
if (view) { this.view.connected = false;
NavList.List[this.index].connected = false; this.ws.emit('logout', this.roomID);
ws.emit('logout', NavList.List[this.index].room);
} }
} }
active() { active() {
this.term.focus(); this.term.focus();
} }
ngOnDestroy(): void {
this.close();
}
} }
'use strict'; 'use strict';
import {EventEmitter} from 'events/events';
import * as io from 'socket.io-client'; import * as io from 'socket.io-client';
import * as neffos from 'neffos.js';
import {Terminal} from 'xterm'; import {Terminal} from 'xterm';
// const abc = io.connect('/ssh');
import {getWsSock, Socket} from './utils/socket';
export const TermWS = io.connect('/ssh'); const scheme = document.location.protocol === 'https:' ? 'wss' : 'ws';
const port = document.location.port ? ':' + document.location.port : '';
const wsURL = scheme + '://' + document.location.hostname + port + '/socket.io/';
export let TermWS = null;
export const emitter = new(EventEmitter);
export const sep = '/'; export const sep = '/';
export let Video: { export let Video: {
id: string, id: string,
...@@ -93,7 +102,7 @@ export let DataStore: { ...@@ -93,7 +102,7 @@ export let DataStore: {
guacamole_token: string; guacamole_token: string;
guacamole_token_time: number; guacamole_token_time: number;
} = { } = {
socket: io.connect(), socket: TermWS,
Nav: [{}], Nav: [{}],
NavShow: true, NavShow: true,
Path: {}, Path: {},
...@@ -136,3 +145,18 @@ export let wsEvent: { ...@@ -136,3 +145,18 @@ export let wsEvent: {
}; };
export const i18n = new Map(); export const i18n = new Map();
export async function getWsSocket() {
if (TermWS) {
return TermWS;
}
TermWS = await getWsSock(wsURL, 'ssh');
if (!TermWS) {
console.log('Try to using socket.io protocol');
TermWS = io.connect('/ssh');
}
DataStore.socket = TermWS;
return TermWS;
}
import {EventEmitter} from 'events/events';
import {NSConn, marshal} from 'neffos.js';
import * as neffos from 'neffos.js';
export class Socket {
conn: NSConn;
emitter: EventEmitter;
constructor(conn: NSConn, emitter: EventEmitter) {
this.conn = conn;
this.emitter = emitter;
}
emit(type: string, obj: any) {
const msg = marshal(obj);
this.conn.emit(type, msg);
}
on(type: string, fn: Function, opt_scope?: any, opt_oneshot?: boolean) {
this.emitter.on(type, fn, opt_scope, opt_oneshot);
}
}
export async function getWsSock(url: string, namespace: string): Promise<Socket> {
const emitter = new EventEmitter();
const events = {
};
let interval;
events[namespace] = {
_OnNamespaceConnected: function (ns, msg) {
emitter.emit('connect', ns);
interval = setInterval(() => ns.emit('ping', ''), 10000);
},
_OnNamespaceDisconnect: function (ns, msg) {
emitter.emit('disconnect', ns);
if (interval) {
clearInterval(interval);
}
},
_OnAnyEvent: function (ns, msg) {
let data = '';
if (msg.Body) {
data = msg.unmarshal();
}
emitter.emit(msg.Event, data);
},
};
const options = {
reconnect: 5000,
};
const conn = <neffos.Conn>await neffos.dial(url, events, options)
.catch(err => {
return null;
});
if (!conn) {
return null;
}
const nsConn = <neffos.NSConn>await conn.connect(namespace);
const sock = new Socket(nsConn, emitter);
return sock;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment