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,6 +1,5 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Convai.Scripts.Runtime.LoggerSystem;
@ -29,7 +28,6 @@ namespace Convai.Scripts.Runtime.Multiplayer
public event Action<ConnectionState> OnConnectionStateChanged;
// Network components
private UdpClient _udpClient;
private bool _isRunning = false;
private int _listenPort;
private CancellationTokenSource _cancellationTokenSource;
@ -134,19 +132,20 @@ namespace Convai.Scripts.Runtime.Multiplayer
try
{
// Create UDP client with port reuse for shared port
_udpClient = new UdpClient();
_udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, _listenPort));
_udpClient.EnableBroadcast = true;
// 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;
_isRunning = true;
SetConnectionState(ConnectionState.Discovering);
ConvaiLogger.Info($"🔍 Peer Discovery started - Player {localPlayerID} on port {_listenPort}", ConvaiLogger.LogCategory.Character);
// Start listening for discovery packets
_ = ListenForDiscoveryPackets(_cancellationTokenSource.Token);
ConvaiLogger.Info($" Peer Discovery subscribed to shared listener - Player {localPlayerID}, listening for magic 0x{DISCOVERY_MAGIC:X}", ConvaiLogger.LogCategory.Character);
// Start broadcasting discovery requests
_ = BroadcastDiscoveryRequests(_cancellationTokenSource.Token);
@ -165,36 +164,27 @@ namespace Convai.Scripts.Runtime.Multiplayer
if (!_isRunning) return;
_isRunning = false;
_udpClient?.Close();
_udpClient?.Dispose();
_udpClient = null;
// Unsubscribe from shared listener
if (SharedUDPListener.Instance != null)
{
SharedUDPListener.Instance.OnPacketReceived -= HandlePacketReceived;
}
SetConnectionState(ConnectionState.Disconnected);
ConvaiLogger.Info("Peer Discovery stopped", ConvaiLogger.LogCategory.Character);
}
private async Task ListenForDiscoveryPackets(CancellationToken cancellationToken)
private void HandlePacketReceived(byte[] data, IPEndPoint senderEndPoint)
{
while (_isRunning && !cancellationToken.IsCancellationRequested)
{
try
{
var result = await _udpClient.ReceiveAsync();
await ProcessDiscoveryPacket(result.Buffer, result.RemoteEndPoint);
}
catch (ObjectDisposedException)
{
// Normal when stopping
break;
}
catch (Exception ex)
{
if (_isRunning)
{
ConvaiLogger.Error($"Error receiving discovery packet: {ex.Message}", ConvaiLogger.LogCategory.Character);
}
}
}
// Check if this is a discovery packet (by magic number)
if (data.Length < 14) return;
uint magic = BitConverter.ToUInt32(data, 0);
if (magic != DISCOVERY_MAGIC) return;
// Process discovery packet
_ = ProcessDiscoveryPacket(data, senderEndPoint);
}
private async Task BroadcastDiscoveryRequests(CancellationToken cancellationToken)
@ -256,9 +246,8 @@ namespace Convai.Scripts.Runtime.Multiplayer
{
byte[] packet = CreateDiscoveryPacket(PACKET_TYPE_REQUEST);
// Broadcast to subnet (will be blocked by AP isolation but we try anyway)
var broadcastEndPoint = new IPEndPoint(IPAddress.Broadcast, _listenPort);
await _udpClient.SendAsync(packet, packet.Length, broadcastEndPoint);
// Broadcast to subnet using shared listener
await SharedUDPListener.Instance.SendBroadcastAsync(packet, _listenPort);
if (enableDebugLogging && UnityEngine.Random.value < 0.1f) // Log 10% of broadcasts to reduce spam
{
@ -276,7 +265,7 @@ namespace Convai.Scripts.Runtime.Multiplayer
try
{
byte[] packet = CreateDiscoveryPacket(PACKET_TYPE_RESPONSE);
await _udpClient.SendAsync(packet, packet.Length, targetEndPoint);
await SharedUDPListener.Instance.SendAsync(packet, targetEndPoint);
if (enableDebugLogging)
{
@ -297,7 +286,7 @@ namespace Convai.Scripts.Runtime.Multiplayer
byte[] packet = CreateDiscoveryPacket(PACKET_TYPE_HEARTBEAT);
var peerEndPoint = new IPEndPoint(IPAddress.Parse(_peerIP), _listenPort);
await _udpClient.SendAsync(packet, packet.Length, peerEndPoint);
await SharedUDPListener.Instance.SendAsync(packet, peerEndPoint);
}
catch (Exception ex)
{