143 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package v1
 | |
| 
 | |
| import (
 | |
| 	"net/http"
 | |
| 	"strconv"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
 | |
| 	"github.com/1Panel-dev/1Panel/backend/constant"
 | |
| 	"github.com/1Panel-dev/1Panel/backend/global"
 | |
| 	"github.com/1Panel-dev/1Panel/backend/utils/copier"
 | |
| 	"github.com/1Panel-dev/1Panel/backend/utils/ssh"
 | |
| 	"github.com/1Panel-dev/1Panel/backend/utils/terminal"
 | |
| 	"github.com/gin-gonic/gin"
 | |
| 	"github.com/gorilla/websocket"
 | |
| 	"github.com/pkg/errors"
 | |
| )
 | |
| 
 | |
| func (b *BaseApi) WsSsh(c *gin.Context) {
 | |
| 	id, err := strconv.Atoi(c.Query("id"))
 | |
| 	if err != nil {
 | |
| 		helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
 | |
| 		return
 | |
| 	}
 | |
| 	cols, err := strconv.Atoi(c.DefaultQuery("cols", "80"))
 | |
| 	if err != nil {
 | |
| 		helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
 | |
| 		return
 | |
| 	}
 | |
| 	rows, err := strconv.Atoi(c.DefaultQuery("rows", "40"))
 | |
| 	if err != nil {
 | |
| 		helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
 | |
| 		return
 | |
| 	}
 | |
| 	host, err := hostService.GetHostInfo(uint(id))
 | |
| 	if err != nil {
 | |
| 		helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
 | |
| 		return
 | |
| 	}
 | |
| 	var connInfo ssh.ConnInfo
 | |
| 	if err := copier.Copy(&connInfo, &host); err != nil {
 | |
| 		helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, constant.ErrStructTransform)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
 | |
| 	if err != nil {
 | |
| 		global.LOG.Errorf("gin context http handler failed, err: %v", err)
 | |
| 		return
 | |
| 	}
 | |
| 	defer wsConn.Close()
 | |
| 
 | |
| 	client, err := connInfo.NewClient()
 | |
| 	if wshandleError(wsConn, errors.WithMessage(err, "failed to set up the connection. Please check the host information")) {
 | |
| 		return
 | |
| 	}
 | |
| 	defer client.Close()
 | |
| 	ssConn, err := connInfo.NewSshConn(cols, rows)
 | |
| 	if wshandleError(wsConn, err) {
 | |
| 		return
 | |
| 	}
 | |
| 	defer ssConn.Close()
 | |
| 
 | |
| 	sws, err := terminal.NewLogicSshWsSession(cols, rows, true, connInfo.Client, wsConn)
 | |
| 	if wshandleError(wsConn, err) {
 | |
| 		return
 | |
| 	}
 | |
| 	defer sws.Close()
 | |
| 
 | |
| 	quitChan := make(chan bool, 3)
 | |
| 	sws.Start(quitChan)
 | |
| 	go sws.Wait(quitChan)
 | |
| 
 | |
| 	<-quitChan
 | |
| 
 | |
| 	global.LOG.Info("websocket finished")
 | |
| 	if wshandleError(wsConn, err) {
 | |
| 		return
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (b *BaseApi) LocalWsSsh(c *gin.Context) {
 | |
| 	cols, err := strconv.Atoi(c.DefaultQuery("cols", "80"))
 | |
| 	if err != nil {
 | |
| 		helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
 | |
| 		return
 | |
| 	}
 | |
| 	rows, err := strconv.Atoi(c.DefaultQuery("rows", "40"))
 | |
| 	if err != nil {
 | |
| 		helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
 | |
| 	if err != nil {
 | |
| 		global.LOG.Errorf("gin context http handler failed, err: %v", err)
 | |
| 		return
 | |
| 	}
 | |
| 	defer wsConn.Close()
 | |
| 
 | |
| 	slave, err := terminal.NewCommand()
 | |
| 	if wshandleError(wsConn, err) {
 | |
| 		return
 | |
| 	}
 | |
| 	defer slave.Close()
 | |
| 
 | |
| 	tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave)
 | |
| 	if wshandleError(wsConn, err) {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	quitChan := make(chan bool, 3)
 | |
| 	tty.Start(quitChan)
 | |
| 	go slave.Wait(quitChan)
 | |
| 
 | |
| 	<-quitChan
 | |
| 
 | |
| 	global.LOG.Info("websocket finished")
 | |
| 	if wshandleError(wsConn, err) {
 | |
| 		return
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func wshandleError(ws *websocket.Conn, err error) bool {
 | |
| 	if err != nil {
 | |
| 		global.LOG.Errorf("handler ws faled:, err: %v", err)
 | |
| 		dt := time.Now().Add(time.Second)
 | |
| 		if err := ws.WriteControl(websocket.CloseMessage, []byte(err.Error()), dt); err != nil {
 | |
| 			global.LOG.Errorf("websocket writes control message failed, err: %v", err)
 | |
| 		}
 | |
| 		return true
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| var upGrader = websocket.Upgrader{
 | |
| 	ReadBufferSize:  1024,
 | |
| 	WriteBufferSize: 1024 * 1024 * 10,
 | |
| 	CheckOrigin: func(r *http.Request) bool {
 | |
| 		return true
 | |
| 	},
 | |
| }
 | 
