mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 18:35:51 +02:00
refactor: project directory structure
This commit is contained in:
parent
c1193a5b8c
commit
e5a5889931
367 changed files with 710 additions and 756 deletions
162
internal/pty/pipeline.go
Normal file
162
internal/pty/pipeline.go
Normal file
|
@ -0,0 +1,162 @@
|
|||
package pty
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/creack/pty"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/pkg/errors"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type Pipeline struct {
|
||||
Pty *os.File
|
||||
cmd *exec.Cmd
|
||||
ws *websocket.Conn
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
Type MsgType
|
||||
Data json.RawMessage
|
||||
}
|
||||
|
||||
const bufferSize = 2048
|
||||
|
||||
func NewPipeLine(conn *websocket.Conn) (p *Pipeline, err error) {
|
||||
c := exec.Command(settings.ServerSettings.StartCmd)
|
||||
|
||||
ptmx, err := pty.StartWithSize(c, &pty.Winsize{Cols: 90, Rows: 60})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "start pty error")
|
||||
}
|
||||
|
||||
p = &Pipeline{
|
||||
Pty: ptmx,
|
||||
cmd: c,
|
||||
ws: conn,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Pipeline) ReadWsAndWritePty(errorChan chan error) {
|
||||
for {
|
||||
msgType, payload, err := p.ws.ReadMessage()
|
||||
if err != nil && websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseNoStatusReceived,
|
||||
websocket.CloseNormalClosure) {
|
||||
errorChan <- errors.Wrap(err, "Error ReadWsAndWritePty unexpected close")
|
||||
return
|
||||
}
|
||||
if msgType != websocket.TextMessage {
|
||||
errorChan <- errors.Errorf("Error ReadWsAndWritePty Invalid msgType: %v", msgType)
|
||||
return
|
||||
}
|
||||
|
||||
var msg Message
|
||||
err = json.Unmarshal(payload, &msg)
|
||||
if err != nil {
|
||||
errorChan <- errors.Wrap(err, "Error ReadWsAndWritePty json.Unmarshal")
|
||||
return
|
||||
}
|
||||
|
||||
switch msg.Type {
|
||||
case TypeData:
|
||||
var data string
|
||||
err = json.Unmarshal(msg.Data, &data)
|
||||
if err != nil {
|
||||
errorChan <- errors.Wrap(err, "Error ReadWsAndWritePty json.Unmarshal msg.Data")
|
||||
return
|
||||
}
|
||||
|
||||
_, err = p.Pty.Write([]byte(data))
|
||||
|
||||
if err != nil {
|
||||
errorChan <- errors.Wrap(err, "Error ReadWsAndWritePty write pty")
|
||||
return
|
||||
}
|
||||
case TypeResize:
|
||||
var win struct {
|
||||
Cols uint16
|
||||
Rows uint16
|
||||
}
|
||||
|
||||
err = json.Unmarshal(msg.Data, &win)
|
||||
if err != nil {
|
||||
errorChan <- errors.Wrap(err, "Error ReadSktAndWritePty Invalid resize message")
|
||||
return
|
||||
}
|
||||
err = pty.Setsize(p.Pty, &pty.Winsize{Rows: win.Rows, Cols: win.Cols})
|
||||
if err != nil {
|
||||
errorChan <- errors.Wrap(err, "Error ReadSktAndWritePty set pty size")
|
||||
return
|
||||
}
|
||||
case TypePing:
|
||||
err = p.ws.WriteControl(websocket.PongMessage, []byte{}, time.Now().Add(time.Second))
|
||||
if err != nil {
|
||||
errorChan <- errors.Wrap(err, "Error ReadSktAndWritePty write pong")
|
||||
return
|
||||
}
|
||||
default:
|
||||
errorChan <- errors.Errorf("Error ReadWsAndWritePty unknown msg.Type %v", msg.Type)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Pipeline) ReadPtyAndWriteWs(errorChan chan error) {
|
||||
buf := make([]byte, bufferSize)
|
||||
for {
|
||||
n, err := p.Pty.Read(buf)
|
||||
if err != nil {
|
||||
errorChan <- errors.Wrap(err, "Error ReadPtyAndWriteWs read pty")
|
||||
return
|
||||
}
|
||||
processedOutput := validString(string(buf[:n]))
|
||||
err = p.ws.WriteMessage(websocket.TextMessage, []byte(processedOutput))
|
||||
if err != nil && websocket.IsUnexpectedCloseError(err, websocket.CloseNormalClosure) {
|
||||
errorChan <- errors.Wrap(err, "Error ReadPtyAndWriteWs websocket write")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Pipeline) Close() {
|
||||
err := p.Pty.Close()
|
||||
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
|
||||
err = p.cmd.Process.Kill()
|
||||
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
|
||||
_, err = p.cmd.Process.Wait()
|
||||
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func validString(s string) string {
|
||||
if !utf8.ValidString(s) {
|
||||
v := make([]rune, 0, len(s))
|
||||
for i, r := range s {
|
||||
if r == utf8.RuneError {
|
||||
_, size := utf8.DecodeRuneInString(s[i:])
|
||||
if size == 1 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
v = append(v, r)
|
||||
}
|
||||
s = string(v)
|
||||
}
|
||||
return s
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue