实现可运行的xterm.js方案

This commit is contained in:
dushixiang
2021-02-01 00:37:56 +08:00
committed by dushixiang
parent 86ef89ff21
commit 29fb520e48
11 changed files with 165 additions and 58 deletions

View File

@ -4,6 +4,7 @@ import (
"encoding/json"
"next-terminal/pkg/utils"
"os"
"path"
"time"
)
@ -26,22 +27,29 @@ type Recorder struct {
timestamp int
}
func NewRecorder(filename string) (recorder *Recorder, err error) {
func NewRecorder(dir string) (recorder *Recorder, filename string, err error) {
recorder = &Recorder{}
if utils.FileExists(filename) {
if err := os.RemoveAll(filename); err != nil {
return nil, err
if utils.FileExists(dir) {
if err := os.RemoveAll(dir); err != nil {
return nil, "", err
}
}
if err = os.MkdirAll(dir, 0777); err != nil {
return
}
filename = path.Join(dir, "recording.cast")
var file *os.File
file, err = os.Create(filename)
if err != nil {
return nil, err
return nil, "", err
}
recorder.file = file
return recorder, nil
return recorder, filename, nil
}
func (recorder *Recorder) Close() {

View File

@ -38,7 +38,13 @@ func SessionPagingEndpoint(c echo.Context) error {
for i := 0; i < len(items); i++ {
if status == model.Disconnected && len(items[i].Recording) > 0 {
recording := items[i].Recording + "/recording"
var recording string
if items[i].Protocol == "rdp" || items[i].Protocol == "vnc" {
recording = items[i].Recording + "/recording"
} else {
recording = items[i].Recording
}
if utils.FileExists(recording) {
logrus.Debugf("检测到录屏文件[%v]存在", recording)
@ -107,12 +113,14 @@ func CloseSessionById(sessionId string, code int, reason string) {
observable, _ := global.Store.Get(sessionId)
if observable != nil {
logrus.Debugf("会话%v创建者退出", observable.Subject.Tunnel.UUID)
_ = observable.Subject.Tunnel.Close()
observable.Subject.Close()
for i := 0; i < len(observable.Observers); i++ {
_ = observable.Observers[i].Tunnel.Close()
observable.Observers[i].Close()
CloseWebSocket(observable.Observers[i].WebSocket, code, reason)
logrus.Debugf("强制踢出会话%v的观察者", observable.Observers[i].Tunnel.UUID)
}
CloseWebSocket(observable.Subject.WebSocket, code, reason)
}
global.Store.Del(sessionId)
@ -529,8 +537,15 @@ func SessionRecordingEndpoint(c echo.Context) error {
if err != nil {
return err
}
recording := path.Join(session.Recording, "recording")
logrus.Debugf("读取录屏文件:%s", recording)
var recording string
if session.Protocol == "rdp" || session.Protocol == "vnc" {
recording = session.Recording + "/recording"
} else {
recording = session.Recording
}
logrus.Debugf("读取录屏文件:%v,是否存在: %v, 是否为文件: %v", recording, utils.FileExists(recording), utils.IsFile(recording))
return c.File(recording)
}

View File

@ -10,8 +10,10 @@ import (
"github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh"
"net/http"
"next-terminal/pkg/guacd"
"next-terminal/pkg/model"
"next-terminal/pkg/utils"
"path"
"strconv"
"sync"
"time"
@ -65,7 +67,7 @@ type WindowSize struct {
Rows int `json:"rows"`
}
func SSHEndpoint(c echo.Context) error {
func SSHEndpoint(c echo.Context) (err error) {
ws, err := UpGrader.Upgrade(c.Response().Writer, c.Request(), nil)
if err != nil {
logrus.Errorf("升级为WebSocket协议失败%v", err.Error())
@ -149,30 +151,44 @@ func SSHEndpoint(c echo.Context) error {
return err
}
var recorder *Recorder
var recording string
property, _ := model.FindPropertyByName(guacd.RecordingPath)
if property.Value != "" {
dir := path.Join(property.Value, sessionId)
recorder, recording, err = NewRecorder(dir)
if err != nil {
msg := Message{
Type: Closed,
Content: "创建录屏文件失败 :( " + err.Error(),
}
return WriteMessage(ws, msg)
}
header := &Header{
Title: "test",
Version: 2,
Height: height,
Width: width,
Env: Env{Shell: "/bin/bash", Term: "xterm-256color"},
Timestamp: int(time.Now().Unix()),
}
if err := recorder.WriteHeader(header); err != nil {
return err
}
if err := model.UpdateSessionById(&model.Session{Recording: recording}, sessionId); err != nil {
return err
}
}
msg := Message{
Type: Connected,
Content: "Connect to server successfully.\r\n",
}
_ = WriteMessage(ws, msg)
recorder, err := NewRecorder("./" + sessionId + ".cast")
if err != nil {
return err
}
header := &Header{
Title: "test",
Version: 2,
Height: height,
Width: width,
Env: Env{Shell: "/bin/bash", Term: "xterm-256color"},
Timestamp: int(time.Now().Unix()),
}
if err := recorder.WriteHeader(header); err != nil {
return err
}
var mut sync.Mutex
var active = true
@ -181,7 +197,10 @@ func SSHEndpoint(c echo.Context) error {
mut.Lock()
if !active {
logrus.Debugf("会话: %v -> %v 关闭", sshClient.LocalAddr().String(), sshClient.RemoteAddr().String())
recorder.Close()
if recorder != nil {
recorder.Close()
}
CloseSessionById(sessionId, Normal, "正常退出")
break
}
mut.Unlock()
@ -192,8 +211,10 @@ func SSHEndpoint(c echo.Context) error {
}
if n > 0 {
s := string(p)
// 录屏
_ = recorder.WriteData(s)
if recorder != nil {
// 录屏
_ = recorder.WriteData(s)
}
msg := Message{
Type: Data,
Content: s,

View File

@ -145,6 +145,7 @@ func TunEndpoint(c echo.Context) error {
}
tun := global.Tun{
Protocol: configuration.Protocol,
Tunnel: tunnel,
WebSocket: ws,
}