优化连接失败时的提示

This commit is contained in:
dushixiang 2020-12-28 20:44:21 +08:00
parent 6153054287
commit 0dbdaf1489
8 changed files with 74 additions and 40 deletions

View File

@ -8,4 +8,4 @@ mysql:
sqlite: sqlite:
file: 'next-terminal.db' file: 'next-terminal.db'
server: server:
addr: 0.0.0.0:8089 addr: 0.0.0.0:8088

View File

@ -128,7 +128,7 @@ func Run() error {
return err return err
} }
// 启动定时任务 // 启动定时任务
//go handle.RunTicker() go handle.RunTicker()
go handle.RunDataFix() go handle.RunDataFix()
return e.Start(global.Config.Server.Addr) return e.Start(global.Config.Server.Addr)

View File

@ -91,6 +91,7 @@ func SetupRoutes() *echo.Echo {
sessions.DELETE("/:id/rm", SessionRmEndpoint) sessions.DELETE("/:id/rm", SessionRmEndpoint)
sessions.DELETE("/:id", SessionDeleteEndpoint) sessions.DELETE("/:id", SessionDeleteEndpoint)
sessions.GET("/:id/recording", SessionRecordingEndpoint) sessions.GET("/:id/recording", SessionRecordingEndpoint)
sessions.GET("/:id", SessionGetEndpoint)
} }
e.GET("/properties", PropertyGetEndpoint) e.GET("/properties", PropertyGetEndpoint)

View File

@ -91,7 +91,7 @@ func SessionDiscontentEndpoint(c echo.Context) error {
split := strings.Split(sessionIds, ",") split := strings.Split(sessionIds, ",")
for i := range split { for i := range split {
CloseSessionById(split[i], 2001, "管理员强制关闭了此次接入。") CloseSessionById(split[i], ForcedDisconnect, "管理员强制关闭了此次接入。")
} }
return Success(c, nil) return Success(c, nil)
} }
@ -105,10 +105,15 @@ func CloseSessionById(sessionId string, code int, reason string) {
global.Store.Del(sessionId) global.Store.Del(sessionId)
if code == Normal {
return
}
session := model.Session{} session := model.Session{}
session.ID = sessionId session.ID = sessionId
session.Status = model.Disconnected session.Status = model.Disconnected
session.DisconnectedTime = utils.NowJsonTime() session.DisconnectedTime = utils.NowJsonTime()
session.Code = code
session.Message = reason
model.UpdateSessionById(&session, sessionId) model.UpdateSessionById(&session, sessionId)
} }
@ -318,6 +323,15 @@ func SessionLsEndpoint(c echo.Context) error {
return errors.New("获取sftp客户端失败") return errors.New("获取sftp客户端失败")
} }
if tun.SftpClient == nil {
sftpClient, err := CreateSftpClient(session.AssetId)
if err != nil {
logrus.Errorf("创建sftp客户端失败%v", err.Error())
return err
}
tun.SftpClient = sftpClient
}
fileInfos, err := tun.SftpClient.ReadDir(remoteDir) fileInfos, err := tun.SftpClient.ReadDir(remoteDir)
if err != nil { if err != nil {
return err return err
@ -479,3 +493,12 @@ func SessionRecordingEndpoint(c echo.Context) error {
logrus.Debugf("读取录屏文件:%s", recording) logrus.Debugf("读取录屏文件:%s", recording)
return c.File(recording) return c.File(recording)
} }
func SessionGetEndpoint(c echo.Context) error {
sessionId := c.Param("id")
session, err := model.FindSessionById(sessionId)
if err != nil {
return err
}
return Success(c, session)
}

View File

@ -11,6 +11,14 @@ import (
"strconv" "strconv"
) )
const (
Normal int = 0
NotFoundSession int = 2000
NewTunnelError int = 2001
NewSftpClientError int = 2002
ForcedDisconnect int = 2003
)
func TunEndpoint(c echo.Context) error { func TunEndpoint(c echo.Context) error {
ws, err := UpGrader.Upgrade(c.Response().Writer, c.Request(), nil) ws, err := UpGrader.Upgrade(c.Response().Writer, c.Request(), nil)
@ -38,12 +46,14 @@ func TunEndpoint(c echo.Context) error {
if len(connectionId) > 0 { if len(connectionId) > 0 {
session, err = model.FindSessionByConnectionId(connectionId) session, err = model.FindSessionByConnectionId(connectionId)
if err != nil { if err != nil {
CloseSessionById(sessionId, NotFoundSession, "会话不存在")
return err return err
} }
configuration.ConnectionID = connectionId configuration.ConnectionID = connectionId
} else { } else {
session, err = model.FindSessionById(sessionId) session, err = model.FindSessionById(sessionId)
if err != nil { if err != nil {
CloseSessionById(sessionId, NotFoundSession, "会话不存在")
return err return err
} }
@ -95,13 +105,12 @@ func TunEndpoint(c echo.Context) error {
configuration.SetParameter(guacd.ColorScheme, propertyMap[guacd.ColorScheme]) configuration.SetParameter(guacd.ColorScheme, propertyMap[guacd.ColorScheme])
break break
case "vnc": case "vnc":
configuration.SetParameter("username", session.Username)
configuration.SetParameter("password", session.Password) configuration.SetParameter("password", session.Password)
configuration.SetParameter("enable-sftp", "")
break break
case "telnet": case "telnet":
configuration.SetParameter("username", session.Username) configuration.SetParameter("username", session.Username)
configuration.SetParameter("password", session.Password) configuration.SetParameter("password", session.Password)
configuration.SetParameter("enable-sftp", "")
break break
} }
@ -115,6 +124,8 @@ func TunEndpoint(c echo.Context) error {
tunnel, err := guacd.NewTunnel(addr, configuration) tunnel, err := guacd.NewTunnel(addr, configuration)
if err != nil { if err != nil {
CloseSessionById(sessionId, NewTunnelError, err.Error())
logrus.Printf("建立连接失败: %v", err.Error())
return err return err
} }
@ -129,35 +140,22 @@ func TunEndpoint(c echo.Context) error {
session.ConnectionId = tunnel.UUID session.ConnectionId = tunnel.UUID
session.Width = intWidth session.Width = intWidth
session.Height = intHeight session.Height = intHeight
session.Status = model.Connecting
session.Recording = configuration.GetParameter(guacd.RecordingPath) session.Recording = configuration.GetParameter(guacd.RecordingPath)
model.UpdateSessionById(&session, sessionId) model.UpdateSessionById(&session, sessionId)
} }
go func() {
sftpClient, err := CreateSftpClient(session.AssetId)
if err != nil {
CloseSessionById(sessionId, 2002, err.Error())
logrus.Errorf("创建sftp客户端失败%v", err.Error())
}
item, ok := global.Store.Get(sessionId)
if ok {
item.SftpClient = sftpClient
}
}()
go func() { go func() {
for true { for true {
instruction, err := tunnel.Read() instruction, err := tunnel.Read()
if err != nil { if err != nil {
CloseSessionById(sessionId, 523, err.Error()) CloseSessionById(sessionId, Normal, "")
logrus.Printf("WebSocket读取错误: %v", err)
break break
} }
err = ws.WriteMessage(websocket.TextMessage, instruction) err = ws.WriteMessage(websocket.TextMessage, instruction)
if err != nil { if err != nil {
CloseSessionById(sessionId, 523, err.Error()) CloseSessionById(sessionId, Normal, "")
logrus.Printf("WebSocket写入错误: %v", err)
break break
} }
} }
@ -166,14 +164,12 @@ func TunEndpoint(c echo.Context) error {
for true { for true {
_, message, err := ws.ReadMessage() _, message, err := ws.ReadMessage()
if err != nil { if err != nil {
CloseSessionById(sessionId, 523, err.Error()) CloseSessionById(sessionId, Normal, "")
logrus.Printf("隧道读取错误: %v", err)
break break
} }
_, err = tunnel.WriteAndFlush(message) _, err = tunnel.WriteAndFlush(message)
if err != nil { if err != nil {
CloseSessionById(sessionId, 523, err.Error()) CloseSessionById(sessionId, Normal, "")
logrus.Printf("隧道写入错误: %v", err)
break break
} }
} }

View File

@ -11,20 +11,17 @@ import (
func RunTicker() { func RunTicker() {
var ch chan int var ch chan int
//定时任务 //定时任务
ticker := time.NewTicker(time.Minute * 5) ticker := time.NewTicker(time.Minute * 60)
go func() { go func() {
for range ticker.C { for range ticker.C {
items, _ := model.FindAllAsset() sessions, _ := model.FindSessionByStatus(model.NoConnect)
if sessions != nil && len(sessions) > 0 {
for i := range items { now := time.Now()
item := items[i] for i := range sessions {
active := utils.Tcping(item.IP, item.Port) if now.Sub(sessions[i].ConnectedTime.Time) > time.Hour*1 {
model.DeleteSessionById(sessions[i].ID)
asset := model.Asset{ }
Active: active,
} }
model.UpdateAssetById(&asset, item.ID)
} }
} }
ch <- 1 ch <- 1

View File

@ -7,9 +7,10 @@ import (
) )
const ( const (
NoConnect = "no_connect"
Connecting = "connecting"
Connected = "connected" Connected = "connected"
Disconnected = "disconnected" Disconnected = "disconnected"
NoConnect = "no_connect"
) )
type Session struct { type Session struct {
@ -29,6 +30,8 @@ type Session struct {
Recording string `json:"recording"` Recording string `json:"recording"`
PrivateKey string `json:"privateKey"` PrivateKey string `json:"privateKey"`
Passphrase string `json:"passphrase"` Passphrase string `json:"passphrase"`
Code int `json:"code"`
Message string `json:"message"`
ConnectedTime utils.JsonTime `json:"connectedTime"` ConnectedTime utils.JsonTime `json:"connectedTime"`
DisconnectedTime utils.JsonTime `json:"disconnectedTime"` DisconnectedTime utils.JsonTime `json:"disconnectedTime"`
} }

View File

@ -266,10 +266,11 @@ class Access extends Component {
} }
}; };
showMessage(message) { showMessage(msg) {
message.destroy();
Modal.error({ Modal.error({
title: '提示', title: '提示',
content: message, content: msg,
}); });
} }
@ -464,11 +465,24 @@ class Access extends Component {
keyboard.onkeydown = this.onKeyDown; keyboard.onkeydown = this.onKeyDown;
keyboard.onkeyup = this.onKeyUp; keyboard.onkeyup = this.onKeyUp;
let stateChecker = setInterval(async () => {
let result = await request.get(`/sessions/${sessionId}`);
if (result['code'] !== 1) {
message.error(result['message']);
} else {
let session = result['data'];
if (session['status'] === 'disconnected') {
this.showMessage(session['message']);
clearInterval(stateChecker);
}
}
}, 1000)
this.setState({ this.setState({
client: client, client: client,
containerWidth: width, containerWidth: width,
containerHeight: height, containerHeight: height,
keyboard: keyboard keyboard: keyboard,
}); });
} }