package ws
import (
"context"
"fmt"
"wssrv/log"
"github.com/gorilla/websocket"
"golang.org/x/sys/unix"
)
const (
bufSize = 8
quitKey = 17 // Key '<c-q>'.
)
func sendRawStdin(ctx context.Context, cancel context.CancelCauseFunc, con *websocket.Conn, fd int) {
var (
err error
n int
buf, clean = make([]byte, bufSize), make([]byte, bufSize)
)
for {
select {
case <-ctx.Done():
return
default:
buf = clean
if n, err = unix.Read(fd, buf); err != nil {
cancel(fmt.Errorf("unable to read from descriptor '%d': %v", fd, err))
return
}
if n == 1 && buf[0] == quitKey {
cancel(nil)
return
}
fmt.Printf("> byte '%d'\n", buf[:n])
if err = con.WriteMessage(websocket.BinaryMessage, buf[:n]); err != nil {
cancel(fmt.Errorf("unable write on websocket on '%s': %v", con.RemoteAddr(), err))
return
}
}
}
}
func sendRawStdinStream(con *websocket.Conn) error {
var (
err error
fd int
term *unix.Termios
ctx, cancel = context.WithCancelCause(context.Background())
)
if fd, term, err = setupTerm(); err != nil {
return fmt.Errorf("unable to setup terminal for raw input: %v", err)
}
defer func(fd int, term *unix.Termios) {
var err error
if err = unix.IoctlSetTermios(fd, unix.TCSETS, term); err != nil {
log.Err.Printf("unable to restore terminal with descriptor '%d': %v", fd, err)
}
}(fd, term)
go readMessage(ctx, cancel, con)
go sendRawStdin(ctx, cancel, con, fd)
<-ctx.Done()
return context.Cause(ctx)
}
func SendRawStdinStream(con *websocket.Conn) error {
switch {
case con == nil:
return fmt.Errorf("nil connection parameter")
}
return sendRawStdinStream(con)
}