aboutsummaryrefslogtreecommitdiff
path: root/hotline/client_manager.go
diff options
context:
space:
mode:
authorJeff Halter <868228+jhalter@users.noreply.github.com>2024-07-09 21:36:27 -0700
committerJeff Halter <868228+jhalter@users.noreply.github.com>2024-07-09 21:42:05 -0700
commitd9bc63a10d0978d9a5222cf7be74044e55f409b7 (patch)
tree1797c9593c279bf1334ed8285de8054a92a28dcb /hotline/client_manager.go
parent8fa166777cbcd92e871e937d9557f0f1a732c04d (diff)
Extensive refactor and clean up
Diffstat (limited to 'hotline/client_manager.go')
-rw-r--r--hotline/client_manager.go99
1 files changed, 99 insertions, 0 deletions
diff --git a/hotline/client_manager.go b/hotline/client_manager.go
new file mode 100644
index 0000000..ab6372c
--- /dev/null
+++ b/hotline/client_manager.go
@@ -0,0 +1,99 @@
+package hotline
+
+import (
+ "cmp"
+ "encoding/binary"
+ "github.com/stretchr/testify/mock"
+ "slices"
+ "sync"
+ "sync/atomic"
+)
+
+type ClientID [2]byte
+
+type ClientManager interface {
+ List() []*ClientConn // Returns list of sorted clients
+ Get(id ClientID) *ClientConn
+ Add(cc *ClientConn)
+ Delete(id ClientID)
+}
+
+type MockClientMgr struct {
+ mock.Mock
+}
+
+func (m *MockClientMgr) List() []*ClientConn {
+ args := m.Called()
+
+ return args.Get(0).([]*ClientConn)
+}
+
+func (m *MockClientMgr) Get(id ClientID) *ClientConn {
+ args := m.Called(id)
+
+ return args.Get(0).(*ClientConn)
+}
+
+func (m *MockClientMgr) Add(cc *ClientConn) {
+ m.Called(cc)
+}
+func (m *MockClientMgr) Delete(id ClientID) {
+ m.Called(id)
+}
+
+type MemClientMgr struct {
+ clients map[ClientID]*ClientConn
+
+ mu sync.Mutex
+ nextClientID atomic.Uint32
+}
+
+func NewMemClientMgr() *MemClientMgr {
+ return &MemClientMgr{
+ clients: make(map[ClientID]*ClientConn),
+ }
+}
+
+// List returns slice of sorted clients.
+func (cm *MemClientMgr) List() []*ClientConn {
+ cm.mu.Lock()
+ defer cm.mu.Unlock()
+
+ var clients []*ClientConn
+ for _, client := range cm.clients {
+ clients = append(clients, client)
+ }
+
+ slices.SortFunc(clients, func(a, b *ClientConn) int {
+ return cmp.Compare(
+ binary.BigEndian.Uint16(a.ID[:]),
+ binary.BigEndian.Uint16(b.ID[:]),
+ )
+ })
+
+ return clients
+}
+
+func (cm *MemClientMgr) Get(id ClientID) *ClientConn {
+ cm.mu.Lock()
+ defer cm.mu.Unlock()
+
+ return cm.clients[id]
+}
+
+func (cm *MemClientMgr) Add(cc *ClientConn) {
+ cm.mu.Lock()
+ defer cm.mu.Unlock()
+
+ cm.nextClientID.Add(1)
+ binary.BigEndian.PutUint16(cc.ID[:], uint16(cm.nextClientID.Load()))
+
+ cm.clients[cc.ID] = cc
+}
+
+func (cm *MemClientMgr) Delete(id ClientID) {
+ cm.mu.Lock()
+ defer cm.mu.Unlock()
+
+ delete(cm.clients, id)
+}