Add QoS beacon
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Prospect.Server.Api.Services.Qos;
|
||||
|
||||
public class QosServer : IAsyncDisposable
|
||||
{
|
||||
private readonly ILogger<QosServer> _logger;
|
||||
private readonly UdpClient _client;
|
||||
|
||||
private bool _isStopping;
|
||||
private Task? _runTask;
|
||||
|
||||
public QosServer(ILogger<QosServer> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_client = new UdpClient(new IPEndPoint(IPAddress.Any, 3075));
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
_runTask = RunAsync();
|
||||
}
|
||||
|
||||
public async Task StopAsync()
|
||||
{
|
||||
_isStopping = true;
|
||||
_client.Dispose();
|
||||
|
||||
if (_runTask != null)
|
||||
{
|
||||
await _runTask;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RunAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var result = await _client.ReceiveAsync();
|
||||
|
||||
_logger.LogInformation("Received {Data} from {Address}", result.Buffer, result.RemoteEndPoint);
|
||||
|
||||
if (result.Buffer.Length == 22)
|
||||
{
|
||||
// The server will reply with a single datagram, with the message contents having the
|
||||
// first 2 bytes "flipped" to 0x0000 (0000 0000 0000 0000).
|
||||
// The rest of the datagram contents will be copied from the initial ping.
|
||||
result.Buffer[0] = 0x00;
|
||||
result.Buffer[1] = 0x00;
|
||||
result.Buffer[2] = 0x00;
|
||||
result.Buffer[3] = 0x00;
|
||||
|
||||
await _client.SendAsync(result.Buffer, result.RemoteEndPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SocketException e) when (e.SocketErrorCode == SocketError.OperationAborted ||
|
||||
e.SocketErrorCode == SocketError.Interrupted ||
|
||||
e.SocketErrorCode == SocketError.InvalidArgument && !OperatingSystem.IsWindows())
|
||||
{
|
||||
if (!_isStopping)
|
||||
{
|
||||
_logger.LogError(e, "SocketException caught in QosServer");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, "Exception caught in QosServer");
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await StopAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace Prospect.Server.Api.Services.Qos;
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of a QoS beacon.
|
||||
/// https://docs.microsoft.com/en-us/gaming/playfab/features/multiplayer/servers/using-qos-beacons-to-measure-player-latency-to-azure#quality-of-service-beacons
|
||||
/// </summary>
|
||||
public class QosService : IHostedService
|
||||
{
|
||||
private readonly ILogger<QosService> _logger;
|
||||
private readonly QosServer _server;
|
||||
|
||||
public QosService(ILogger<QosService> logger, QosServer server)
|
||||
{
|
||||
_logger = logger;
|
||||
_server = server;
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Starting QoS beacon");
|
||||
_server.Start();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("Stopping QoS beacon");
|
||||
await _server.StopAsync();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user