mirror of
https://github.com/azukaar/Cosmos-Server.git
synced 2026-05-04 10:20:21 -05:00
[release] v0.17.0-unstable10
This commit is contained in:
@@ -49,15 +49,29 @@ const TerminalComponent = ({refresh, connectButtons}) => {
|
||||
|
||||
ws.current = connectFunction();
|
||||
|
||||
ws.current.onmessage = (event) => {
|
||||
if(event.data === '_PONG_') {
|
||||
ws.current.onmessage = async (event) => {
|
||||
console.log('Received:', event);
|
||||
|
||||
if (event.data === '_PONG_') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
terminal.write(event.data);
|
||||
let data;
|
||||
if (event.data instanceof Blob) {
|
||||
// Handle Blob data
|
||||
data = await event.data.text();
|
||||
} else if (event.data instanceof ArrayBuffer) {
|
||||
// Handle ArrayBuffer data
|
||||
data = new TextDecoder().decode(event.data);
|
||||
} else {
|
||||
// Assume it's already a string
|
||||
data = event.data;
|
||||
}
|
||||
|
||||
terminal.write(data);
|
||||
} catch (e) {
|
||||
console.error("error", e);
|
||||
console.error("Error processing message:", e);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@ require (
|
||||
github.com/cloudflare/cloudflare-go v0.86.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/cpu/goacmedns v0.1.1 // indirect
|
||||
github.com/creack/pty v1.1.23 // indirect
|
||||
github.com/cristalhq/jwt/v4 v4.0.2 // indirect
|
||||
github.com/dave/jennifer v1.4.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
|
||||
@@ -246,6 +246,8 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0=
|
||||
github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
|
||||
github.com/cristalhq/jwt/v4 v4.0.2 h1:g/AD3h0VicDamtlM70GWGElp8kssQEv+5wYd7L9WOhU=
|
||||
github.com/cristalhq/jwt/v4 v4.0.2/go.mod h1:HnYraSNKDRag1DZP92rYHyrjyQHnVEHPNqesmzs+miQ=
|
||||
github.com/cucumber/godog v0.8.1/go.mod h1:vSh3r/lM+psC1BPXvdkSEuNjmXfpVqrMGYAElF6hxnA=
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cosmos-server",
|
||||
"version": "0.17.0-unstable9",
|
||||
"version": "0.17.0-unstable10",
|
||||
"description": "",
|
||||
"main": "test-server.js",
|
||||
"bugs": {
|
||||
|
||||
+120
-86
@@ -1,13 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
// "context"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
// "syscall"
|
||||
"time"
|
||||
"io"
|
||||
// "os"
|
||||
// "os/signal"
|
||||
|
||||
"github.com/creack/pty"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/azukaar/cosmos-server/src/utils"
|
||||
)
|
||||
@@ -50,101 +53,132 @@ func HostTerminalRoute(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
ws.SetReadDeadline(time.Now().Add(timeoutDuration))
|
||||
ws.SetWriteDeadline(time.Now().Add(timeoutDuration))
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
// Create arbitrary command.
|
||||
c := exec.Command("bash")
|
||||
// Set environment variables for better terminal emulation
|
||||
// env := os.Environ()
|
||||
env := []string{}
|
||||
env = append(env, "TERM=xterm-256color")
|
||||
env = append(env, "LINES=24", "COLUMNS=80")
|
||||
c.Env = env
|
||||
|
||||
// Start the command with a pty.
|
||||
ptmx, err := pty.StartWithSize(c, &pty.Winsize{
|
||||
Rows: 24,
|
||||
Cols: 80,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Make sure to close the pty at the end.
|
||||
defer func() { _ = ptmx.Close() }() // Best effort.
|
||||
|
||||
// Handle pty size.
|
||||
// ch := make(chan os.Signal, 1)
|
||||
// signal.Notify(ch, syscall.SIGWINCH)
|
||||
// go func() {
|
||||
// for range ch {
|
||||
// if err := pty.InheritSize(os.Stdin, ptmx); err != nil {
|
||||
// utils.Error("error resizing pty", err)
|
||||
// }
|
||||
// }
|
||||
// }()
|
||||
// ch <- syscall.SIGWINCH // Initial resize.
|
||||
// defer func() { signal.Stop(ch); close(ch) }() // Cleanup signals when done.
|
||||
|
||||
|
||||
// Set stdin in raw mode.
|
||||
// oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// defer func() { _ = term.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort.
|
||||
|
||||
// Copy stdin to the pty and the pty to stdout.
|
||||
// NOTE: The goroutine will keep reading until the next keystroke before returning.
|
||||
// go func() { _, _ = io.Copy(ptmx, os.Stdin) }()
|
||||
// _, _ = io.Copy(os.Stdout, ptmx)
|
||||
|
||||
// Specify the UID you want to run the command as
|
||||
uid := uint32(1000) // Replace with the desired UID
|
||||
gid := uint32(1000) // Replace with the primary GID of the user
|
||||
|
||||
cmd := exec.CommandContext(ctx, "/bin/sh")
|
||||
|
||||
stdin, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
utils.Error("Failed to create stdin pipe: ", err)
|
||||
http.Error(w, "Failed to create stdin pipe: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
utils.Error("Failed to create stdout pipe: ", err)
|
||||
http.Error(w, "Failed to create stdout pipe: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// uid := uint32(1000) // Replace with the desired UID
|
||||
// gid := uint32(1000) // Replace with the primary GID of the user
|
||||
// Set the user and group ID of the process
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Credential: &syscall.Credential{
|
||||
Uid: uid,
|
||||
Gid: gid,
|
||||
},
|
||||
}
|
||||
// cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
// Credential: &syscall.Credential{
|
||||
// Uid: uid,
|
||||
// Gid: gid,
|
||||
// },
|
||||
// }
|
||||
|
||||
// stdin, err := cmd.StdinPipe()
|
||||
// if err != nil {
|
||||
// utils.Error("Failed to create stdin pipe: ", err)
|
||||
// http.Error(w, "Failed to create stdin pipe: "+err.Error(), http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
|
||||
// Start the command
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
utils.Error("Failed to start command: ", err)
|
||||
http.Error(w, "Failed to start command: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
// stdout, err := cmd.StdoutPipe()
|
||||
// if err != nil {
|
||||
// utils.Error("Failed to create stdout pipe: ", err)
|
||||
// http.Error(w, "Failed to create stdout pipe: "+err.Error(), http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
utils.Error("Failed to create stderr pipe: ", err)
|
||||
http.Error(w, "Failed to create stderr pipe: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
// stderr, err := cmd.StderrPipe()
|
||||
// if err != nil {
|
||||
// utils.Error("Failed to create stderr pipe: ", err)
|
||||
// http.Error(w, "Failed to create stderr pipe: "+err.Error(), http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
utils.Error("Failed to start command: ", err)
|
||||
http.Error(w, "Failed to start command: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
// Goroutine to handle pty output
|
||||
go func() {
|
||||
buf := make([]byte, 1024)
|
||||
for {
|
||||
n, err := ptmx.Read(buf)
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
utils.Error("Error reading from pty: ", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
ws.SetWriteDeadline(time.Now().Add(timeoutDuration))
|
||||
ws.SetReadDeadline(time.Now().Add(timeoutDuration))
|
||||
if err := ws.WriteMessage(websocket.BinaryMessage, buf[:n]); err != nil {
|
||||
utils.Error("Failed to write to websocket: ", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
utils.Log("Attached to host terminal")
|
||||
|
||||
go func() {
|
||||
defer cmd.Process.Kill()
|
||||
for {
|
||||
// Main loop to handle websocket input
|
||||
for {
|
||||
_, message, err := ws.ReadMessage()
|
||||
if err != nil {
|
||||
if websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway) {
|
||||
return
|
||||
}
|
||||
utils.Error("Failed to read from websocket: ", err)
|
||||
return
|
||||
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
|
||||
utils.Error("Websocket error: ", err)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
ws.SetWriteDeadline(time.Now().Add(timeoutDuration))
|
||||
ws.SetReadDeadline(time.Now().Add(timeoutDuration))
|
||||
|
||||
if string(message) == "_PING_" {
|
||||
ws.SetWriteDeadline(time.Now().Add(timeoutDuration))
|
||||
ws.WriteMessage(websocket.TextMessage, []byte("_PONG_"))
|
||||
ws.WriteMessage(websocket.TextMessage, []byte("_PONG_"))
|
||||
} else {
|
||||
stdin.Write(message)
|
||||
_, err := ptmx.Write(message)
|
||||
if err != nil {
|
||||
utils.Error("Failed to write to pty: ", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
go func() {
|
||||
combined := io.MultiReader(stdout, stderr)
|
||||
buf := make([]byte, 1024)
|
||||
for {
|
||||
n, err := combined.Read(buf)
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
utils.Error("Failed to read from command output: ", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
messages := splitIntoChunks(string(buf[:n]))
|
||||
for _, messageSplit := range messages {
|
||||
ws.SetWriteDeadline(time.Now().Add(timeoutDuration))
|
||||
if err := ws.WriteMessage(websocket.TextMessage, []byte(messageSplit)); err != nil {
|
||||
utils.Error("Failed to write to websocket: ", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
cmd.Wait()
|
||||
// Cleanup
|
||||
|
||||
utils.Log("Terminal session ended")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user