96 lines
2.2 KiB
Go
96 lines
2.2 KiB
Go
package websocket
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// SessionMessageInit subject in messages
|
|
const SessionMessageInit = "session_init"
|
|
|
|
// SessionManager to handle reconnected websocket
|
|
type SessionManager struct {
|
|
sessionToClient map[uuid.UUID]map[string]*Client
|
|
clientToSession map[string]uuid.UUID
|
|
sync.Mutex
|
|
}
|
|
|
|
// NewSessionManager to get a new SessionManager
|
|
func NewSessionManager() *SessionManager {
|
|
return &SessionManager{
|
|
sessionToClient: make(map[uuid.UUID]map[string]*Client),
|
|
clientToSession: make(map[string]uuid.UUID),
|
|
}
|
|
}
|
|
|
|
// Init Session for given Client
|
|
func (s *SessionManager) Init(c *Client) {
|
|
c.Write(&Message{
|
|
From: c,
|
|
Subject: SessionMessageInit,
|
|
})
|
|
}
|
|
|
|
// HandleMessage of client for Session
|
|
func (s *SessionManager) HandleMessage(msg *Message) bool {
|
|
if msg == nil {
|
|
return false
|
|
}
|
|
if msg.ID != uuid.Nil && msg.Subject == SessionMessageInit && msg.From != nil {
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
list := s.sessionToClient[msg.ID]
|
|
if list == nil {
|
|
list = make(map[string]*Client)
|
|
}
|
|
id := msg.From.GetID()
|
|
list[id] = msg.From
|
|
s.clientToSession[id] = msg.ID
|
|
s.sessionToClient[msg.ID] = list
|
|
return true
|
|
}
|
|
if msg.From != nil {
|
|
id := msg.From.GetID()
|
|
msg.Session = s.clientToSession[id]
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// Remove clients from SessionManagerer
|
|
// - 1. result: clients removed from session manager
|
|
// - 2. result: session closed and all clients removed
|
|
func (s *SessionManager) Remove(c *Client) (client bool, session bool) {
|
|
if c == nil {
|
|
return false, false
|
|
}
|
|
if id := c.GetID(); id != "" {
|
|
session := s.clientToSession[id]
|
|
defer delete(s.clientToSession, id)
|
|
if session != uuid.Nil {
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
clients := s.sessionToClient[session]
|
|
delete(clients, id)
|
|
if len(clients) > 0 {
|
|
s.sessionToClient[session] = clients
|
|
return true, false
|
|
}
|
|
delete(s.sessionToClient, session)
|
|
return true, true
|
|
}
|
|
}
|
|
return false, false
|
|
}
|
|
|
|
// Send a message to a specific Session (and all his Websocket clients)
|
|
func (s *SessionManager) Send(id uuid.UUID, msg *Message) {
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
clients := s.sessionToClient[id]
|
|
for _, c := range clients {
|
|
c.Write(msg)
|
|
}
|
|
}
|