created centralized UDP Listener

This commit is contained in:
tom.hempel
2025-10-25 14:58:22 +02:00
parent 4ddb89d011
commit 3f72973ff5
10 changed files with 585 additions and 534 deletions

View File

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Convai.Scripts.Runtime.LoggerSystem;
@ -39,7 +38,6 @@ namespace Convai.Scripts.Runtime.Multiplayer
[SerializeField] private bool showTranscripts = true;
// Network components
private UdpClient _udpListener;
private IPEndPoint _remoteEndPoint;
private bool _isListening = false;
private int listenPort;
@ -211,20 +209,22 @@ namespace Convai.Scripts.Runtime.Multiplayer
try
{
// Create UDP client with port reuse to allow sharing with UDPPeerDiscovery
_udpListener = new UdpClient();
_udpListener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_udpListener.Client.Bind(new IPEndPoint(IPAddress.Any, listenPort));
// Wait for shared listener to be ready
if (SharedUDPListener.Instance == null)
{
ConvaiLogger.Error("SharedUDPListener not found! Make sure it's in the scene.", ConvaiLogger.LogCategory.Character);
return;
}
// Subscribe to shared listener
SharedUDPListener.Instance.OnPacketReceived += HandlePacketReceived;
_isListening = true;
ConvaiLogger.Info($"UDP Speech Receiver listening on port {listenPort} (shared)", ConvaiLogger.LogCategory.Character);
// Start listening for incoming packets
_ = ListenForSpeechPackets(_cancellationTokenSource.Token);
ConvaiLogger.Info($" Speech Receiver subscribed to shared listener, listening for magic 0x{MAGIC_NUMBER:X}", ConvaiLogger.LogCategory.Character);
}
catch (Exception ex)
{
ConvaiLogger.Error($"Failed to start UDP speech receiver: {ex.Message}", ConvaiLogger.LogCategory.Character);
ConvaiLogger.Error($"❌ FAILED to subscribe Speech Receiver: {ex.Message}", ConvaiLogger.LogCategory.Character);
}
}
@ -234,9 +234,12 @@ namespace Convai.Scripts.Runtime.Multiplayer
return;
_isListening = false;
_udpListener?.Close();
_udpListener?.Dispose();
_udpListener = null;
// Unsubscribe from shared listener
if (SharedUDPListener.Instance != null)
{
SharedUDPListener.Instance.OnPacketReceived -= HandlePacketReceived;
}
// Stop any ongoing playback
StopSpeechPlayback();
@ -244,26 +247,19 @@ namespace Convai.Scripts.Runtime.Multiplayer
ConvaiLogger.Info("Stopped UDP Speech Receiver", ConvaiLogger.LogCategory.Character);
}
private async Task ListenForSpeechPackets(CancellationToken cancellationToken)
private void HandlePacketReceived(byte[] data, IPEndPoint senderEndPoint)
{
try
{
while (_isListening && !cancellationToken.IsCancellationRequested)
{
var result = await _udpListener.ReceiveAsync();
_remoteEndPoint = result.RemoteEndPoint;
await ProcessReceivedPacket(result.Buffer, result.RemoteEndPoint);
}
}
catch (ObjectDisposedException)
{
// Normal when stopping
}
catch (Exception ex)
{
ConvaiLogger.Error($"Error in UDP speech listener: {ex.Message}", ConvaiLogger.LogCategory.Character);
}
// Check if this is a speech packet (by magic number)
if (data.Length < 4) return;
uint magic = BitConverter.ToUInt32(data, 0);
if (magic != MAGIC_NUMBER) return;
// Update remote endpoint
_remoteEndPoint = senderEndPoint;
// Process speech packet
_ = ProcessReceivedPacket(data, senderEndPoint);
}
private Task ProcessReceivedPacket(byte[] data, IPEndPoint sender)