Files
be.ems/src/modules/ws/controller/ws_view.go

112 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package controller
import (
"encoding/json"
"fmt"
"time"
"be.ems/src/framework/i18n"
"be.ems/src/framework/logger"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
neService "be.ems/src/modules/ne/service"
"github.com/gin-gonic/gin"
)
// ShellView 终端交互式文件内容查看
//
// GET /view
//
// @Tags ws
// @Accept json
// @Produce json
// @Param neType query string true "NE Type" Enums(IMS,AMF,AUSF,UDM,SMF,PCF,NSSF,NRF,UPF,MME,CBC,OMC,SGWC,SMSC)
// @Param neId query string true "NE ID" default(001)
// @Param cols query number false "Terminal line characters" default(120)
// @Param rows query number false "Terminal display lines" default(40)
// @Param access_token query string true "Authorization tokens are used when it is inconvenient to pass parameters through the header."
// @Success 200 {object} object "Response Results"
// @Summary (ws://) Terminal Interactive File Content Viewing
// @Description (ws://) Terminal Interactive File Content Viewing
// @Router /ws/view [get]
func (s *WSController) ShellView(c *gin.Context) {
language := reqctx.AcceptLanguage(c)
var query struct {
CoreUid string `form:"coreUid" binding:"required"` // 核心网唯一资源标识
NeUid string `form:"neUid" binding:"required"` // 网元唯一资源标识
Cols int `form:"cols"` // 终端单行字符数
Rows int `form:"rows"` // 终端显示行数
}
if err := c.ShouldBindQuery(&query); err != nil {
errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, errMsgs))
return
}
if query.Cols < 120 || query.Cols > 400 {
query.Cols = 120
}
if query.Rows < 40 || query.Rows > 1200 {
query.Rows = 40
}
// 登录用户信息
loginUser, err := reqctx.LoginUser(c)
if err != nil {
c.JSON(401, resp.CodeMsg(resp.CODE_AUTH_INVALID, i18n.TKey(language, err.Error())))
return
}
// 网元主机的SSH客户端
sshClient, err := neService.NewNeInfo.NeRunSSHClient(query.CoreUid, query.NeUid)
if err != nil {
c.JSON(200, resp.ErrMsg(err.Error()))
return
}
defer sshClient.Close()
// ssh连接会话
clientSession, err := sshClient.NewClientSession(query.Cols, query.Rows)
if err != nil {
c.JSON(200, resp.ErrMsg("neinfo ssh client session new err"))
return
}
defer clientSession.Close()
// 将 HTTP 连接升级为 WebSocket 连接
wsConn := s.wsService.UpgraderWs(c.Writer, c.Request)
if wsConn == nil {
return
}
defer wsConn.Close()
wsClient := s.wsService.ClientCreate(loginUser.UserId, nil, wsConn, clientSession)
go s.wsService.ClientWriteListen(wsClient)
go s.wsService.ClientReadListen(wsClient, s.wsReceiveService.ShellView)
// 等待1秒排空首次消息
time.Sleep(1 * time.Second)
_ = clientSession.Read()
// 实时读取SSH消息直接输出
msTicker := time.NewTicker(100 * time.Millisecond)
defer msTicker.Stop()
for {
select {
case ms := <-msTicker.C:
outputByte := clientSession.Read()
if len(outputByte) > 0 {
outputStr := string(outputByte)
msgByte, _ := json.Marshal(resp.Ok(map[string]any{
"requestId": fmt.Sprintf("view_%d", ms.UnixMilli()),
"data": outputStr,
}))
wsClient.MsgChan <- msgByte
}
case <-wsClient.StopChan: // 等待停止信号
s.wsService.ClientClose(wsClient.ID)
logger.Infof("ws Stop Client UID %d", wsClient.BindUid)
return
}
}
}