2024-08-23 05:14:45 +07:00

115 lines
2.1 KiB
Go

package router
import (
"context"
"fmt"
"net/http"
"os"
"os/exec"
"github.com/coder/websocket"
)
type Terminal struct {
ws *websocket.Conn
remoteAddr string
cmd *exec.Cmd
}
func (c *Terminal) NewSession(w http.ResponseWriter, r *http.Request) {
cwd, err := os.Getwd()
if err != nil {
fmt.Printf("Failed to get current working directory: %v\n", err)
}
cmd := &exec.Cmd{
// Path: "/bin/bash",
Path: "/usr/bin/fish",
Dir: cwd,
}
c.cmd = cmd
stdin, err := cmd.StdinPipe()
if err != nil {
fmt.Printf("Failed to create stdin pipe: %v\n", err)
return
}
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Printf("Failed to create stdout pipe: %v\n", err)
return
}
cmd.Stderr = cmd.Stdout
cmd.Stdout = os.Stdout
if err := cmd.Start(); err != nil {
fmt.Printf("Failed to start command: %v\n", err)
return
}
go func() {
// if err := cmd.Wait(); err != nil {
// fmt.Printf("Shell exited with error: %v\n", err)
// }
// c.ws.CloseNow()
}()
go func() {
buf := make([]byte, 1024)
for {
n, err := stdout.Read(buf)
if err != nil {
return
}
fmt.Printf("Data from stdout: %s\n", string(buf[:n]))
err = c.ws.Write(context.Background(), websocket.MessageText, buf[:n])
if err != nil {
fmt.Printf("Failed to write data to websocket: %v\n", err)
return
}
}
}()
for {
_, data, err := c.ws.Read(context.Background())
if err != nil {
return
}
fmt.Printf("Data from websocket: %s\n", string(data))
if _, err := stdin.Write(data); err != nil {
fmt.Printf("Failed to write data to stdin: %v\n", err)
continue
}
}
}
func (c *Terminal) Close() {
if c.cmd != nil {
c.cmd.Process.Kill()
}
fmt.Println("Terminal session closed:", c.remoteAddr)
c.ws.Close(websocket.StatusInternalError, "the connection is closed")
}
func TerminalHandler(w http.ResponseWriter, r *http.Request) {
fmt.Printf("New terminal session: %s\n", r.RemoteAddr)
c, err := websocket.Accept(w, r, nil)
if err != nil {
fmt.Printf("Failed to accept websocket: %v\n", err)
return
}
term := &Terminal{ws: c, remoteAddr: r.RemoteAddr}
defer term.Close()
term.NewSession(w, r)
}