This commit is contained in:
ACoolName 2024-05-15 10:31:32 +03:00
parent 343e16a4db
commit 4bffae63b7
3 changed files with 121 additions and 0 deletions

1
go.mod
View File

@ -17,6 +17,7 @@ require (
github.com/go-playground/validator/v10 v10.14.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/leodido/go-urn v1.2.4 // indirect

2
go.sum
View File

@ -31,6 +31,8 @@ github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzq
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=

View File

@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"strings"
"time"
@ -22,6 +23,7 @@ import (
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
@ -49,6 +51,14 @@ type ImageLabels struct {
Type string `json:"type"`
}
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func (con Connection) getServerInfo(volume volume.Volume) (*models.ServerInfo, error) {
var volumeLabels VolumeLabels
jsonData, err := json.Marshal(volume.Labels)
@ -428,6 +438,113 @@ func (con Connection) RunCommand(ctx *gin.Context) {
ctx.JSON(200, "OK")
}
type Commands struct {
CommandType string `json:"command_type"`
Arguments []string `json:"arguments"`
}
func (con Connection) AttachServer(ctx *gin.Context) {
serverId := ctx.Param("server_id")
stop := false
websocketRead := make(chan Commands)
containerRead := make(chan string)
defer func() {
close(websocketRead)
close(containerRead)
}()
containers, err := con.apiClient.ContainerList(context.TODO(), container.ListOptions{Filters: filters.NewArgs(filters.Arg("label", "volume_id="+serverId))})
if err != nil {
ctx.AbortWithError(500, err)
return
}
if len(containers) == 0 {
ctx.AbortWithStatus(404)
return
}
hijacked, err := con.apiClient.ContainerAttach(context.Background(), containers[0].ID, container.AttachOptions{Stream: true, Stdin: true, Stdout: true, Stderr: true, Logs: true})
if err != nil {
ctx.AbortWithError(500, err)
return
}
defer hijacked.Close()
ws, err := upgrader.Upgrade(ctx.Writer, ctx.Request, nil)
if err != nil {
return
}
defer ws.Close()
go func() {
data := make([]byte, 0, 1024)
for {
if stop {
break
}
count, err := hijacked.Reader.Read(data)
if err != nil {
stop = true
break
}
if count > 0 {
log.Println("Got ", count, " bytes: ", data)
}
containerRead <- string(data)
}
}()
go func() {
var command Commands
for {
if stop {
break
}
err := ws.ReadJSON(&command)
if err != nil {
command.CommandType = "close"
websocketRead <- command
break
}
websocketRead <- command
}
}()
if err != nil {
ctx.AbortWithError(500, err)
return
}
for {
select {
case Command := <-websocketRead:
switch Command.CommandType {
case "insert":
_, err = hijacked.Conn.Write([]byte(Command.Arguments[0]))
if err != nil {
stop = true
break
}
case "close":
stop = true
break
}
case data := <-containerRead:
err := ws.WriteJSON(data)
if err != nil {
stop = true
break
}
}
}
}
func (con Connection) serverAuthorized(permissions models.Permission) func(*gin.Context) bool {
return func(ctx *gin.Context) bool {
claims, exists := ctx.Get("claims")
@ -472,4 +589,5 @@ func LoadGroup(group *gin.RouterGroup, mongo_client *mongo.Client) {
group.POST("/:server_id/stop", auth.AuthorizedTo(models.Stop, connection.serverAuthorized(models.Stop)), connection.StopServer)
group.POST("/:server_id/delete", auth.AuthorizedTo(models.Delete, connection.serverAuthorized(models.Delete)), connection.DeleteServer)
group.POST("/:server_id/run_command", auth.AuthorizedTo(models.RunCommand, connection.serverAuthorized(models.RunCommand)), connection.RunCommand)
group.GET("/:server_id/attach", auth.AuthorizedTo(models.RunCommand, connection.serverAuthorized(models.RunCommand)), connection.AttachServer)
}