Files
eko/internal/server/session/session.go
Kyren223 180bb557b1 Fixed server hanging until the client closes the connection,
it now forcibly closes the connection when it's terminated
2024-11-27 18:40:19 +02:00

91 lines
1.7 KiB
Go

package session
import (
"context"
"crypto/ed25519"
"crypto/rand"
"net"
"sync"
"time"
"github.com/kyren223/eko/internal/packet"
"github.com/kyren223/eko/pkg/assert"
"github.com/kyren223/eko/pkg/snowflake"
)
type SessionManager interface {
AddSession(session *Session)
RemoveSession(id snowflake.ID)
Session(id snowflake.ID) (session *Session, ok bool)
Node() *snowflake.Node
}
type Session struct {
manager SessionManager
addr *net.TCPAddr
writeQueue chan packet.Packet
issuedTime time.Time
challenge []byte
PubKey ed25519.PublicKey
id snowflake.ID
mu sync.Mutex
}
func NewSession(manager SessionManager, addr *net.TCPAddr, id snowflake.ID, pubKey ed25519.PublicKey) *Session {
session := &Session{
writeQueue: make(chan packet.Packet, 10),
PubKey: pubKey,
manager: manager,
addr: addr,
id: id,
challenge: make([]byte, 32),
}
session.Challenge() // Make sure an initial nonce is generated
return session
}
func (s *Session) Addr() *net.TCPAddr {
return s.addr
}
func (s *Session) ID() snowflake.ID {
return s.id
}
func (s *Session) Manager() SessionManager {
return s.manager
}
func (s *Session) Challenge() []byte {
s.mu.Lock()
defer s.mu.Unlock()
if time.Since(s.issuedTime) > time.Minute {
s.issuedTime = time.Now()
_, err := rand.Read(s.challenge)
assert.NoError(err, "random should always produce a value")
}
return s.challenge
}
func (s *Session) Write(ctx context.Context, pkt packet.Packet) bool {
select {
case s.writeQueue <- pkt:
return true
case <-ctx.Done():
return false
}
}
func (s *Session) Read(ctx context.Context) (packet.Packet, bool) {
select {
case pkt := <-s.writeQueue:
return pkt, true
case <-ctx.Done():
return packet.Packet{}, false
}
}