105 lines
2.1 KiB
Go
105 lines
2.1 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
"unicode/utf8"
|
|
|
|
"next-terminal/server/dto"
|
|
"next-terminal/server/global/session"
|
|
"next-terminal/server/term"
|
|
|
|
"github.com/gorilla/websocket"
|
|
)
|
|
|
|
type TermHandler struct {
|
|
sessionId string
|
|
isRecording bool
|
|
ws *websocket.Conn
|
|
nextTerminal *term.NextTerminal
|
|
ctx context.Context
|
|
cancel context.CancelFunc
|
|
dataChan chan rune
|
|
tick *time.Ticker
|
|
}
|
|
|
|
func NewTermHandler(sessionId string, isRecording bool, ws *websocket.Conn, nextTerminal *term.NextTerminal) *TermHandler {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
tick := time.NewTicker(time.Millisecond * time.Duration(60))
|
|
return &TermHandler{
|
|
sessionId: sessionId,
|
|
isRecording: isRecording,
|
|
ws: ws,
|
|
nextTerminal: nextTerminal,
|
|
ctx: ctx,
|
|
cancel: cancel,
|
|
dataChan: make(chan rune),
|
|
tick: tick,
|
|
}
|
|
}
|
|
|
|
func (r TermHandler) Start() {
|
|
go r.readFormTunnel()
|
|
go r.writeToWebsocket()
|
|
}
|
|
|
|
func (r TermHandler) Stop() {
|
|
r.tick.Stop()
|
|
r.cancel()
|
|
}
|
|
|
|
func (r TermHandler) readFormTunnel() {
|
|
for {
|
|
select {
|
|
case <-r.ctx.Done():
|
|
return
|
|
default:
|
|
rn, size, err := r.nextTerminal.StdoutReader.ReadRune()
|
|
if err != nil {
|
|
return
|
|
}
|
|
if size > 0 {
|
|
r.dataChan <- rn
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (r TermHandler) writeToWebsocket() {
|
|
var buf []byte
|
|
for {
|
|
select {
|
|
case <-r.ctx.Done():
|
|
return
|
|
case <-r.tick.C:
|
|
if len(buf) > 0 {
|
|
s := string(buf)
|
|
if err := WriteMessage(r.ws, dto.NewMessage(Data, s)); err != nil {
|
|
return
|
|
}
|
|
// 录屏
|
|
if r.isRecording {
|
|
_ = r.nextTerminal.Recorder.WriteData(s)
|
|
}
|
|
nextSession := session.GlobalSessionManager.GetById(r.sessionId)
|
|
// 监控
|
|
if nextSession != nil && len(nextSession.Observer.All()) > 0 {
|
|
obs := nextSession.Observer.All()
|
|
for _, ob := range obs {
|
|
_ = WriteMessage(ob.WebSocket, dto.NewMessage(Data, s))
|
|
}
|
|
}
|
|
buf = []byte{}
|
|
}
|
|
case data := <-r.dataChan:
|
|
if data != utf8.RuneError {
|
|
p := make([]byte, utf8.RuneLen(data))
|
|
utf8.EncodeRune(p, data)
|
|
buf = append(buf, p...)
|
|
} else {
|
|
buf = append(buf, []byte("@")...)
|
|
}
|
|
}
|
|
}
|
|
}
|