// Package tcp // @Link https://github.com/bufanyun/hotgo // @Copyright Copyright (c) 2023 HotGo CLI // @Author Ms <133814250@qq.com> // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE package tcp import ( "context" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" "hotgo/internal/consts" "hotgo/internal/model/entity" "hotgo/internal/model/input/msgin" "hotgo/utility/convert" ) func (server *Server) onServerLogin(ctx context.Context, args ...interface{}) { var ( in = new(msgin.ServerLogin) user = GetCtx(ctx) res = new(msgin.ResponseServerLogin) models *entity.SysServeLicense ) if err := gconv.Scan(args[0], &in); err != nil { server.Logger.Warningf(ctx, "onServerLogin message Scan failed:%+v, args:%+v", err, args) return } err := g.Model("sys_serve_license").Ctx(ctx). Where("appid = ?", in.AppId). Scan(&models) if err != nil { res.Code = 1 res.Message = err.Error() server.Write(user.Conn, res) return } if models == nil { res.Code = 2 res.Message = "授权信息不存在" server.Write(user.Conn, res) return } // 验证签名 if _, err = VerifySign(in, models.Appid, models.SecretKey); err != nil { res.Code = 3 res.Message = "签名错误,请联系管理员" server.Write(user.Conn, res) return } if models.Status != consts.StatusEnabled { res.Code = 4 res.Message = "授权已禁用,请联系管理员" server.Write(user.Conn, res) return } if models.Group != in.Group { res.Code = 5 res.Message = "你登录的授权分组未得到授权,请联系管理员" server.Write(user.Conn, res) return } if models.EndAt.Before(gtime.Now()) { res.Code = 6 res.Message = "授权已过期,请联系管理员" server.Write(user.Conn, res) return } allowedIps := convert.IpFilterStrategy(models.AllowedIps) if _, ok := allowedIps["*"]; !ok { ip := gstr.StrTillEx(user.Conn.RemoteAddr().String(), ":") if _, ok2 := allowedIps[ip]; !ok2 { res.Code = 7 res.Message = "IP(" + ip + ")未授权,请联系管理员" server.Write(user.Conn, res) return } } // 检查是否存在多地登录,如果连接超出上限,直接将所有已连接断开 clients := server.getAppIdClients(models.Appid) online := len(clients) + 1 if online > models.OnlineLimit { online = 0 res2 := new(msgin.ResponseServerLogin) res2.Code = 8 res2.Message = "授权登录端超出上限已进行记录。请立即终止操作。如有疑问请联系管理员" for _, client := range clients { server.Write(client.Conn, res2) client.Conn.Close() } // 当前连接也踢掉 server.Write(user.Conn, res2) user.Conn.Close() return } server.mutexConns.Lock() server.clients[user.Conn.RemoteAddr().String()] = &ClientConn{ Conn: user.Conn, Auth: &AuthMeta{ Group: in.Group, Name: in.Name, AppId: in.AppId, SecretKey: models.SecretKey, EndAt: models.EndAt, }, heartbeat: gtime.Timestamp(), } server.mutexConns.Unlock() _, err = g.Model("sys_serve_license").Ctx(ctx). Where("id = ?", models.Id).Data(g.Map{ "online": online, "login_times": models.LoginTimes + 1, "last_login_at": gtime.Now(), "last_active_at": gtime.Now(), "remote_addr": user.Conn.RemoteAddr().String(), }).Update() if err != nil { server.Logger.Warningf(ctx, "onServerLogin Update err:%+v", err) } res.AppId = in.AppId res.Code = consts.TCPMsgCodeSuccess server.Write(user.Conn, res) } func (server *Server) onServerHeartbeat(ctx context.Context, args ...interface{}) { var ( in *msgin.ServerHeartbeat res = new(msgin.ResponseServerHeartbeat) ) if err := gconv.Scan(args[0], &in); err != nil { server.Logger.Warningf(ctx, "onServerHeartbeat message Scan failed:%+v, args:%+v", err, args) return } client := args[1].(*ClientConn) client.heartbeat = gtime.Timestamp() _, err := g.Model("sys_serve_license").Ctx(ctx). Where("appid = ?", client.Auth.AppId).Data(g.Map{ "last_active_at": gtime.Now(), }).Update() if err != nil { server.Logger.Warningf(ctx, "onServerHeartbeat Update err:%+v", err) } res.Code = consts.TCPMsgCodeSuccess server.Write(client.Conn, res) }