golang-lib/websocket/session.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)
}
}