91 lines
1.5 KiB
Go
91 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/panjf2000/gnet/v2"
|
|
"zombiezen.com/go/sqlite/sqlitex"
|
|
)
|
|
|
|
type ClientState int
|
|
|
|
const (
|
|
StateConnected ClientState = iota
|
|
StateAuthenticated
|
|
StateCharacterSelect
|
|
StateDisconnected
|
|
)
|
|
|
|
type Client struct {
|
|
conn gnet.Conn
|
|
address string
|
|
connected time.Time
|
|
lastActive time.Time
|
|
state ClientState
|
|
accountID uint32
|
|
accountName string
|
|
version int16
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
type ClientManager struct {
|
|
clients map[int]*Client
|
|
db *sqlitex.Pool
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
func NewClientManager(db *sqlitex.Pool) *ClientManager {
|
|
return &ClientManager{
|
|
clients: make(map[int]*Client),
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
func (cm *ClientManager) AddClient(fd int, client *Client) {
|
|
cm.mu.Lock()
|
|
defer cm.mu.Unlock()
|
|
cm.clients[fd] = client
|
|
}
|
|
|
|
func (cm *ClientManager) RemoveClient(fd int) {
|
|
cm.mu.Lock()
|
|
defer cm.mu.Unlock()
|
|
delete(cm.clients, fd)
|
|
}
|
|
|
|
func (cm *ClientManager) GetClient(fd int) *Client {
|
|
cm.mu.RLock()
|
|
defer cm.mu.RUnlock()
|
|
return cm.clients[fd]
|
|
}
|
|
|
|
func (cm *ClientManager) CleanupExpired() {
|
|
cm.mu.Lock()
|
|
defer cm.mu.Unlock()
|
|
|
|
cutoff := time.Now().Add(-30 * time.Minute)
|
|
for fd, client := range cm.clients {
|
|
if client.lastActive.Before(cutoff) {
|
|
client.conn.Close()
|
|
delete(cm.clients, fd)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (cm *ClientManager) GetStats() (int, int) {
|
|
cm.mu.RLock()
|
|
defer cm.mu.RUnlock()
|
|
|
|
total := len(cm.clients)
|
|
authenticated := 0
|
|
|
|
for _, client := range cm.clients {
|
|
if client.state == StateAuthenticated {
|
|
authenticated++
|
|
}
|
|
}
|
|
|
|
return total, authenticated
|
|
}
|