package controllers
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"log"
"strconv"
"strings"
"vmcmdi/ssh"
)
type WebsocketReceive struct {
Cmd string `json:"cmd"`
}
type WebsocketSend struct {
Stdout string `json:"stdout"`
Msg string `json:"msg"`
Err error `json:"err"`
}
func DeploySocket(ctx *gin.Context) {
// create websocket connect
conn := ctx.MustGet("conn").(*websocket.Conn)
defer func() { _ = conn.Close() }()
// validate params
host := ctx.DefaultQuery("host", "")
port, err := strconv.Atoi(ctx.DefaultQuery("port", "0"))
if err != nil {
_ = conn.WriteJSON(WebsocketSend{Stdout: fmt.Sprintf("(port param) string type to int type err: %s", err.Error())})
return
}
username := ctx.DefaultQuery("username", "")
password := ctx.DefaultQuery("password", "")
if host == "" || username == "" || port == 0 {
_ = conn.WriteJSON(WebsocketSend{Stdout: "params: host or username or port cannot empty"})
return
}
inChan := make(chan []byte, 5)
outputChan := make(chan string)
exit := make(chan bool, 5)
defer func() {
close(inChan)
close(outputChan)
close(exit)
}()
// create SSH client
cliConf := new(ssh.ClientConfig)
if err := cliConf.CreateSshClient(host, int64(port), username, password); err != nil {
log.Printf("create ssh client err: %+v", err)
_ = conn.WriteJSON(WebsocketSend{Stdout: fmt.Sprintf("create ssh client err: %s", err.Error())})
return
}
defer func() { _ = cliConf.SshClient.Close() }()
// create shell session and
session, err := cliConf.RunShellTerminal(inChan, outputChan)
defer func() { _ = session.Close() }()
if err != nil {
log.Printf("create sessioon or run shell err: %v", err)
_ = conn.WriteJSON(WebsocketSend{Stdout: fmt.Sprintf("create sessioon or run shell err: %s", err.Error())})
return
}
go func() {
defer func() {recover()}()
for {
_, msg, err := conn.ReadMessage() // first connect, check the socket
if err != nil {
if strings.Contains(err.Error(), "websocket: close 1005") {
log.Printf("web site active disconnect: %v", err)
}else if strings.Contains(err.Error(), "use of closed network connection") {
log.Printf("backend server active disconnect: %v", err)
}else {
log.Printf("unknown error: %v", err)
}
exit <- true
outputChan <- ""
break
}
if string(msg) == "" {
continue
}
for _, b := range []byte("\n") {
msg = append(msg, b)
}
inChan <- msg
}
}()
//sessionExit := make(chan bool)
go func() {
defer func() {recover()}()
_ = session.Wait()
exit <- true
outputChan <- ""
return
}()
for m := range outputChan {
select {
case <-exit:
log.Println("websocket send message loop end")
return
default:
if err := conn.WriteJSON(WebsocketSend{Stdout: m}); err != nil {
log.Printf("websocket send mesaage err: %s", err.Error())
}
}
}
}