diff --git a/internal/msggateway/context.go b/internal/msggateway/context.go index 5baa11fdd..cd395e7e0 100644 --- a/internal/msggateway/context.go +++ b/internal/msggateway/context.go @@ -91,6 +91,9 @@ func (c *UserConnContext) GetPlatformID() string { func (c *UserConnContext) GetOperationID() string { return c.Req.URL.Query().Get(OperationID) } +func (c *UserConnContext) GetToken() string { + return c.Req.URL.Query().Get(Token) +} func (c *UserConnContext) GetBackground() bool { b, err := strconv.ParseBool(c.Req.URL.Query().Get(BackgroundStatus)) if err != nil { diff --git a/internal/msggateway/n_ws_server.go b/internal/msggateway/n_ws_server.go index b093395e8..de2788cb0 100644 --- a/internal/msggateway/n_ws_server.go +++ b/internal/msggateway/n_ws_server.go @@ -13,6 +13,7 @@ import ( "time" "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" + redis "github.com/go-redis/redis/v8" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/log" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/tokenverify" @@ -187,13 +188,35 @@ func (ws *WsServer) multiTerminalLoginChecker(info *kickHandler) { fallthrough case constant.AllLoginButSameTermKick: if info.clientOK { + ws.clients.deleteClients(info.newClient.UserID, info.oldClients) for _, c := range info.oldClients { err := c.KickOnlineMessage() if err != nil { - log.ZError(c.ctx, "KickOnlineMessage", err) + log.ZWarn(c.ctx, "KickOnlineMessage", err) } } - ws.cache.GetTokensWithoutError(info.newClient.ctx, info.newClient.UserID, info.newClient.PlatformID) + m, err := ws.cache.GetTokensWithoutError(info.newClient.ctx, info.newClient.UserID, info.newClient.PlatformID) + if err != nil && err != redis.Nil { + log.ZWarn(info.newClient.ctx, "get token from redis err", err, "userID", info.newClient.UserID, "platformID", info.newClient.PlatformID) + return + } + if m == nil { + log.ZWarn(info.newClient.ctx, "m is nil", errors.New("m is nil"), "userID", info.newClient.UserID, "platformID", info.newClient.PlatformID) + return + } + log.ZDebug(info.newClient.ctx, "get token from redis", "userID", info.newClient.UserID, "platformID", info.newClient.PlatformID, "tokenMap", m) + + for k, _ := range m { + if k != info.newClient.ctx.GetToken() { + m[k] = constant.KickedToken + } + } + log.ZDebug(info.newClient.ctx, "set token map is ", "token map", m, "userID", info.newClient.UserID) + err = ws.cache.SetTokenMapByUidPid(info.newClient.ctx, info.newClient.UserID, info.newClient.PlatformID, m) + if err != nil { + log.ZWarn(info.newClient.ctx, "SetTokenMapByUidPid err", err, "userID", info.newClient.UserID, "platformID", info.newClient.PlatformID) + return + } } } diff --git a/internal/msggateway/user_map.go b/internal/msggateway/user_map.go index e482f7cea..63881bc1a 100644 --- a/internal/msggateway/user_map.go +++ b/internal/msggateway/user_map.go @@ -3,6 +3,7 @@ package msggateway import ( "context" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/log" + "github.com/OpenIMSDK/Open-IM-Server/pkg/utils" "sync" ) @@ -71,6 +72,29 @@ func (u *UserMap) delete(key string, connRemoteAddr string) (isDeleteUser bool) } return existed } +func (u *UserMap) deleteClients(key string, clients []*Client) (isDeleteUser bool) { + m := utils.SliceToMapAny(clients, func(c *Client) (string, struct{}) { + return c.ctx.GetRemoteAddr(), struct{}{} + }) + allClients, existed := u.m.Load(key) + if existed { + oldClients := allClients.([]*Client) + var a []*Client + for _, client := range oldClients { + if _, ok := m[client.ctx.GetRemoteAddr()]; !ok { + a = append(a, client) + } + } + if len(a) == 0 { + u.m.Delete(key) + return true + } else { + u.m.Store(key, a) + return false + } + } + return existed +} func (u *UserMap) DeleteAll(key string) { u.m.Delete(key) }