redo ptybuffer, move to wshutil to help with stdin processing. change wsh to use cobra

This commit is contained in:
sawka
2024-06-14 14:43:47 -07:00
parent 8a3a527343
commit 014c6fb2ec
10 changed files with 411 additions and 140 deletions
+17 -20
View File
@@ -46,10 +46,8 @@ type BlockController struct {
InputCh chan wshutil.BlockCommand
Status string
CreatedHtmlFile bool
PtyBuffer *PtyBuffer
ShellProc *shellexec.ShellProc
ShellInputCh chan *wshutil.BlockInputCommand
ShellProc *shellexec.ShellProc
ShellInputCh chan *wshutil.BlockInputCommand
}
func (bc *BlockController) WithLock(f func()) {
@@ -187,6 +185,17 @@ func (bc *BlockController) DoRunShellCommand(rc *RunShellOpts) error {
}
shellInputCh := make(chan *wshutil.BlockInputCommand)
bc.ShellInputCh = shellInputCh
commandCh := make(chan wshutil.BlockCommand, 32)
ptyBuffer := wshutil.MakePtyBuffer(bc.ShellProc.Pty, commandCh)
go func() {
for cmd := range commandCh {
if strings.HasPrefix(cmd.GetCommand(), "controller:") {
bc.InputCh <- cmd
} else {
ProcessStaticCommand(bc.BlockId, cmd)
}
}
}()
go func() {
defer func() {
// needs synchronization
@@ -197,12 +206,11 @@ func (bc *BlockController) DoRunShellCommand(rc *RunShellOpts) error {
}()
buf := make([]byte, 4096)
for {
nr, err := bc.ShellProc.Pty.Read(buf)
nr, err := ptyBuffer.Read(buf)
if nr > 0 {
bc.PtyBuffer.AppendData(buf[:nr])
if bc.PtyBuffer.Err != nil {
log.Printf("error processing pty data: %v\n", bc.PtyBuffer.Err)
break
err := handleAppendBlockFile(bc.BlockId, BlockFile_Main, buf[:nr])
if err != nil {
log.Printf("error appending to blockfile: %v\n", err)
}
}
if err == io.EOF {
@@ -303,17 +311,6 @@ func StartBlockController(ctx context.Context, blockId string) error {
Status: "init",
InputCh: make(chan wshutil.BlockCommand),
}
ptyBuffer := MakePtyBuffer(func(fileName string, data []byte) error {
return handleAppendBlockFile(blockId, fileName, data)
}, func(cmd wshutil.BlockCommand) error {
if strings.HasPrefix(cmd.GetCommand(), "controller:") {
bc.InputCh <- cmd
} else {
ProcessStaticCommand(blockId, cmd)
}
return nil
})
bc.PtyBuffer = ptyBuffer
blockControllerMap[blockId] = bc
go bc.Run(blockData)
return nil
-119
View File
@@ -1,119 +0,0 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
package blockcontroller
import (
"encoding/json"
"fmt"
"github.com/wavetermdev/thenextwave/pkg/wshutil"
)
const (
Mode_Normal = "normal"
Mode_Esc = "esc"
Mode_WaveEsc = "waveesc"
)
type PtyBuffer struct {
Mode string
EscSeqBuf []byte
DataOutputFn func(string, []byte) error
CommandOutputFn func(wshutil.BlockCommand) error
Err error
}
func MakePtyBuffer(dataOutputFn func(string, []byte) error, commandOutputFn func(wshutil.BlockCommand) error) *PtyBuffer {
return &PtyBuffer{
Mode: Mode_Normal,
DataOutputFn: dataOutputFn,
CommandOutputFn: commandOutputFn,
}
}
func (b *PtyBuffer) setErr(err error) {
if b.Err == nil {
b.Err = err
}
}
func (b *PtyBuffer) processWaveEscSeq(escSeq []byte) {
jmsg := make(map[string]any)
err := json.Unmarshal(escSeq, &jmsg)
if err != nil {
b.setErr(fmt.Errorf("error unmarshalling Wave OSC sequence data: %w", err))
return
}
cmd, err := wshutil.ParseCmdMap(jmsg)
if err != nil {
b.setErr(fmt.Errorf("error parsing Wave OSC command: %w", err))
return
}
err = b.CommandOutputFn(cmd)
if err != nil {
b.setErr(fmt.Errorf("error processing Wave OSC command: %w", err))
return
}
}
func (b *PtyBuffer) AppendData(data []byte) {
outputBuf := make([]byte, 0, len(data))
for _, ch := range data {
if b.Mode == Mode_WaveEsc {
if ch == wshutil.ESC {
// terminates the escape sequence (and the rest was invalid)
b.Mode = Mode_Normal
outputBuf = append(outputBuf, b.EscSeqBuf...)
outputBuf = append(outputBuf, ch)
b.EscSeqBuf = nil
} else if ch == wshutil.BEL || ch == wshutil.ST {
// terminates the escpae sequence (is a valid Wave OSC command)
b.Mode = Mode_Normal
waveEscSeq := b.EscSeqBuf[len(wshutil.WaveOSCPrefix):]
b.EscSeqBuf = nil
b.processWaveEscSeq(waveEscSeq)
} else {
b.EscSeqBuf = append(b.EscSeqBuf, ch)
}
continue
}
if b.Mode == Mode_Esc {
if ch == wshutil.ESC || ch == wshutil.BEL || ch == wshutil.ST {
// these all terminate the escape sequence (invalid, not a Wave OSC)
b.Mode = Mode_Normal
outputBuf = append(outputBuf, b.EscSeqBuf...)
outputBuf = append(outputBuf, ch)
} else {
if ch == wshutil.WaveOSCPrefixBytes[len(b.EscSeqBuf)] {
// we're still building what could be a Wave OSC sequence
b.EscSeqBuf = append(b.EscSeqBuf, ch)
} else {
// this is not a Wave OSC sequence, just an escape sequence
b.Mode = Mode_Normal
outputBuf = append(outputBuf, b.EscSeqBuf...)
outputBuf = append(outputBuf, ch)
continue
}
// check to see if we have a full Wave OSC prefix
if len(b.EscSeqBuf) == len(wshutil.WaveOSCPrefixBytes) {
b.Mode = Mode_WaveEsc
}
}
continue
}
// Mode_Normal
if ch == wshutil.ESC {
b.Mode = Mode_Esc
b.EscSeqBuf = []byte{ch}
continue
}
outputBuf = append(outputBuf, ch)
}
if len(outputBuf) > 0 {
err := b.DataOutputFn(BlockFile_Main, outputBuf)
if err != nil {
b.setErr(fmt.Errorf("error processing data output: %w", err))
}
}
}