using System.Net; using System.Net.Sockets; using System.Threading.Tasks; using Xunit; using XWorld.Framework.Protocol; using XWorld.Server.Gateway; namespace XWorld.Server.Gateway.Tests { public class DevDiscoveryResponderTests { private static async Task QueryAsync(int port, string token, uint nonce, int timeoutMs) { using var client = new UdpClient(AddressFamily.InterNetwork); byte[] q = DevDiscoveryCodec.EncodeQuery(new DevDiscoveryQuery { ProtoVersion = DevDiscovery.ProtoVersion, Nonce = nonce, Token = token, }); await client.SendAsync(q, q.Length, new IPEndPoint(IPAddress.Loopback, port)); var recv = client.ReceiveAsync(); var done = await Task.WhenAny(recv, Task.Delay(timeoutMs)); if (done != recv) return null; UdpReceiveResult result = await recv; if (!DevDiscoveryCodec.TryDecodeReply(result.Buffer, out var reply)) return null; return reply; } [Fact] public async Task ValidQuery_ReceivesReply_WithAdvertisedAddresses() { var responder = new DevDiscoveryResponder( "dev-pc", "ws://192.168.1.23:5005/ws", "http://192.168.1.23:15081/minigame/", token: "secret", listenPort: 0); responder.Start(); try { var reply = await QueryAsync(responder.Port, "secret", nonce: 7, timeoutMs: 2000); Assert.NotNull(reply); Assert.Equal("ws://192.168.1.23:5005/ws", reply.Value.GatewayUrl); Assert.Equal("http://192.168.1.23:15081/minigame/", reply.Value.ResourceBaseUrl); Assert.Equal("dev-pc", reply.Value.ServerName); Assert.Equal(7u, reply.Value.Nonce); } finally { await responder.StopAsync(); } } [Fact] public async Task WrongToken_NoReply() { var responder = new DevDiscoveryResponder("dev-pc", "ws://x", "http://y", token: "secret", listenPort: 0); responder.Start(); try { var reply = await QueryAsync(responder.Port, "WRONG", nonce: 1, timeoutMs: 800); Assert.Null(reply); } finally { await responder.StopAsync(); } } [Fact] public async Task GarbagePacket_Ignored_LoopStillAnswers() { var responder = new DevDiscoveryResponder("dev-pc", "ws://x", "http://y", token: "secret", listenPort: 0); responder.Start(); try { using (var raw = new UdpClient(AddressFamily.InterNetwork)) { byte[] junk = { 1, 2, 3 }; await raw.SendAsync(junk, junk.Length, new IPEndPoint(IPAddress.Loopback, responder.Port)); } var reply = await QueryAsync(responder.Port, "secret", nonce: 9, timeoutMs: 2000); Assert.NotNull(reply); Assert.Equal(9u, reply.Value.Nonce); } finally { await responder.StopAsync(); } } } }