mirror of
https://github.com/Kyren223/eko.git
synced 2026-04-25 22:43:54 +00:00
87 lines
1.8 KiB
Go
87 lines
1.8 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 {
|
|
// Channel to directly write packets to the cient.
|
|
// Can be nil in cases where the connection is not available.
|
|
WriteQueue chan packet.Packet
|
|
PubKey ed25519.PublicKey
|
|
|
|
manager SessionManager
|
|
addr *net.TCPAddr
|
|
id snowflake.ID
|
|
|
|
mu sync.Mutex
|
|
challenge []byte
|
|
issuedTime time.Time
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
type key struct{}
|
|
|
|
var sessKey key
|
|
|
|
func NewContext(ctx context.Context, sess *Session) context.Context {
|
|
return context.WithValue(ctx, sessKey, sess)
|
|
}
|
|
|
|
func FromContext(ctx context.Context) (*Session, bool) {
|
|
sess, ok := ctx.Value(sessKey).(*Session)
|
|
return sess, ok
|
|
}
|