208 lines
6.7 KiB
Go
208 lines
6.7 KiB
Go
package nakama
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"seanime/internal/events"
|
|
"time"
|
|
)
|
|
|
|
// registerDefaultHandlers registers the default message handlers
|
|
func (m *Manager) registerDefaultHandlers() {
|
|
m.messageHandlers[MessageTypeAuth] = m.handleAuthMessage
|
|
m.messageHandlers[MessageTypeAuthReply] = m.handleAuthReplyMessage
|
|
m.messageHandlers[MessageTypePing] = m.handlePingMessage
|
|
m.messageHandlers[MessageTypePong] = m.handlePongMessage
|
|
m.messageHandlers[MessageTypeError] = m.handleErrorMessage
|
|
m.messageHandlers[MessageTypeCustom] = m.handleCustomMessage
|
|
|
|
// Watch party handlers
|
|
m.messageHandlers[MessageTypeWatchPartyCreated] = m.handleWatchPartyMessage
|
|
m.messageHandlers[MessageTypeWatchPartyStopped] = m.handleWatchPartyMessage
|
|
m.messageHandlers[MessageTypeWatchPartyJoin] = m.handleWatchPartyMessage
|
|
m.messageHandlers[MessageTypeWatchPartyLeave] = m.handleWatchPartyMessage
|
|
m.messageHandlers[MessageTypeWatchPartyStateChanged] = m.handleWatchPartyMessage
|
|
m.messageHandlers[MessageTypeWatchPartyPlaybackStatus] = m.handleWatchPartyMessage
|
|
m.messageHandlers[MessageTypeWatchPartyPlaybackStopped] = m.handleWatchPartyMessage
|
|
m.messageHandlers[MessageTypeWatchPartyPeerStatus] = m.handleWatchPartyMessage
|
|
m.messageHandlers[MessageTypeWatchPartyBufferUpdate] = m.handleWatchPartyMessage
|
|
m.messageHandlers[MessageTypeWatchPartyRelayModeOriginStreamStarted] = m.handleWatchPartyMessage
|
|
m.messageHandlers[MessageTypeWatchPartyRelayModeOriginPlaybackStatus] = m.handleWatchPartyMessage
|
|
m.messageHandlers[MessageTypeWatchPartyRelayModePeersReady] = m.handleWatchPartyMessage
|
|
m.messageHandlers[MessageTypeWatchPartyRelayModePeerBuffering] = m.handleWatchPartyMessage
|
|
m.messageHandlers[MessageTypeWatchPartyRelayModeOriginPlaybackStopped] = m.handleWatchPartyMessage
|
|
}
|
|
|
|
// handleMessage routes messages to the appropriate handler
|
|
func (m *Manager) handleMessage(message *Message, senderID string) error {
|
|
m.handlerMu.RLock()
|
|
handler, exists := m.messageHandlers[message.Type]
|
|
m.handlerMu.RUnlock()
|
|
|
|
if !exists {
|
|
return errors.New("unknown message type: " + string(message.Type))
|
|
}
|
|
|
|
return handler(message, senderID)
|
|
}
|
|
|
|
// handleAuthMessage handles authentication requests from peers
|
|
func (m *Manager) handleAuthMessage(message *Message, senderID string) error {
|
|
if !m.settings.IsHost {
|
|
return errors.New("not acting as host")
|
|
}
|
|
|
|
// Parse auth payload
|
|
authData, err := json.Marshal(message.Payload)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var authPayload AuthPayload
|
|
if err := json.Unmarshal(authData, &authPayload); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Get peer connection
|
|
peerConn, exists := m.peerConnections.Get(senderID)
|
|
if !exists {
|
|
return errors.New("peer connection not found")
|
|
}
|
|
|
|
// Verify password
|
|
success := authPayload.Password == m.settings.HostPassword
|
|
var replyMessage string
|
|
if success {
|
|
// Update the peer connection with the PeerID from auth payload if not already set
|
|
if peerConn.PeerId == "" && authPayload.PeerId != "" {
|
|
peerConn.PeerId = authPayload.PeerId
|
|
}
|
|
|
|
peerConn.Authenticated = true
|
|
replyMessage = "Authentication successful"
|
|
m.logger.Info().Str("peerID", peerConn.PeerId).Str("senderID", senderID).Msg("nakama: Peer authenticated successfully")
|
|
|
|
// Send event to client about new peer connection
|
|
m.wsEventManager.SendEvent(events.NakamaPeerConnected, map[string]interface{}{
|
|
"peerId": peerConn.PeerId, // Use PeerID for events
|
|
"authenticated": true,
|
|
})
|
|
} else {
|
|
replyMessage = "Authentication failed"
|
|
m.logger.Warn().Str("peerId", peerConn.PeerId).Str("senderID", senderID).Msg("nakama: Peer authentication failed")
|
|
}
|
|
|
|
// Send auth reply
|
|
authReply := &Message{
|
|
Type: MessageTypeAuthReply,
|
|
Payload: AuthReplyPayload{
|
|
Success: success,
|
|
Message: replyMessage,
|
|
Username: m.username,
|
|
PeerId: peerConn.PeerId, // Echo back the peer's UUID
|
|
},
|
|
Timestamp: time.Now(),
|
|
}
|
|
|
|
return peerConn.SendMessage(authReply)
|
|
}
|
|
|
|
// handleAuthReplyMessage handles authentication replies from hosts
|
|
func (m *Manager) handleAuthReplyMessage(message *Message, senderID string) error {
|
|
// This should only be received by clients, and is handled in the client connection logic
|
|
// We can log it here for debugging purposes
|
|
m.logger.Debug().Str("senderID", senderID).Msg("nakama: Received auth reply")
|
|
return nil
|
|
}
|
|
|
|
// handlePingMessage handles ping messages
|
|
func (m *Manager) handlePingMessage(message *Message, senderID string) error {
|
|
// Send pong response
|
|
pongMessage := &Message{
|
|
Type: MessageTypePong,
|
|
Payload: nil,
|
|
Timestamp: time.Now(),
|
|
}
|
|
|
|
if m.settings.IsHost {
|
|
// We're the host, send pong to peer
|
|
peerConn, exists := m.peerConnections.Get(senderID)
|
|
if !exists {
|
|
return errors.New("peer connection not found")
|
|
}
|
|
return peerConn.SendMessage(pongMessage)
|
|
} else {
|
|
// We're a client, send pong to host
|
|
m.hostMu.RLock()
|
|
defer m.hostMu.RUnlock()
|
|
if m.hostConnection == nil {
|
|
return errors.New("not connected to host")
|
|
}
|
|
return m.hostConnection.SendMessage(pongMessage)
|
|
}
|
|
}
|
|
|
|
// handlePongMessage handles pong messages
|
|
func (m *Manager) handlePongMessage(message *Message, senderID string) error {
|
|
// Update last ping time
|
|
if m.settings.IsHost {
|
|
// Update peer's last ping time
|
|
peerConn, exists := m.peerConnections.Get(senderID)
|
|
if exists {
|
|
peerConn.LastPing = time.Now()
|
|
}
|
|
} else {
|
|
// Update host's last ping time
|
|
m.hostMu.Lock()
|
|
if m.hostConnection != nil {
|
|
m.hostConnection.LastPing = time.Now()
|
|
}
|
|
m.hostMu.Unlock()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// handleErrorMessage handles error messages
|
|
func (m *Manager) handleErrorMessage(message *Message, senderID string) error {
|
|
// Parse error payload
|
|
errorData, err := json.Marshal(message.Payload)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var errorPayload ErrorPayload
|
|
if err := json.Unmarshal(errorData, &errorPayload); err != nil {
|
|
return err
|
|
}
|
|
|
|
m.logger.Error().Str("senderID", senderID).Str("errorMessage", errorPayload.Message).Str("errorCode", errorPayload.Code).Msg("nakama: Received error message")
|
|
|
|
// Send event to client about the error
|
|
m.wsEventManager.SendEvent(events.NakamaError, map[string]interface{}{
|
|
"senderID": senderID,
|
|
"message": errorPayload.Message,
|
|
"code": errorPayload.Code,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// handleCustomMessage handles custom messages
|
|
func (m *Manager) handleCustomMessage(message *Message, senderID string) error {
|
|
m.logger.Debug().Str("senderID", senderID).Msg("nakama: Received custom message")
|
|
|
|
// Send event to client with the custom message
|
|
m.wsEventManager.SendEvent(events.NakamaCustomMessage, map[string]interface{}{
|
|
"senderID": senderID,
|
|
"payload": message.Payload,
|
|
"requestID": message.RequestID,
|
|
"timestamp": message.Timestamp,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *Manager) handleWatchPartyMessage(message *Message, senderID string) error {
|
|
return m.watchPartyManager.handleMessage(message, senderID)
|
|
}
|