package ws import ( "context" "fmt" "wssrv/log" "github.com/gorilla/websocket" "golang.org/x/sys/unix" ) const ( bufSize = 8 quitKey = 17 // Key ''. ) 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) }