protected async Task <List <ServerAddress> > RetrieveAsync(int limit, IPEndPoint remote = null, int tried = -1) { var cur = -1; var servers = new List <ServerAddress>(); if (remote == null) { var hosts = Dns.GetHostAddresses("hl2master.steampowered.com"); if (tried == -1) { cur = new Random().Next(hosts.Length); } else { cur = (tried + 1) % hosts.Length; } var host = hosts[cur]; const int port = 27011; #if DEBUG this.Logger().Debug("Contacting master server {0}:{1}", host, port); #endif remote = new IPEndPoint(host, port); //TODO: alternate ip and ports availability } var e = new IPEndPoint(IPAddress.Any, 0); var udpClient = new UdpClient(e) { Client = { ReceiveTimeout = DefaultReceiveTimeout, SendTimeout = DefaultSendTimeout } }; udpClient.Connect(remote); var i = 0; const int maxIterations = 30; string lastSeed; var seed = "0.0.0.0:0"; do { lastSeed = seed; var msg = BuildMessage(seed); if (await udpClient.SendAsync(msg, msg.Length).ConfigureAwait(false) != msg.Length) { throw new Exception("Send failed."); } byte[] response = null; var timedOut = false; try { response = (await udpClient.ReceiveWithTimeoutAfter(DefaultReceiveTimeout).ConfigureAwait(false)).Buffer; } catch (TimeoutException) { timedOut = true; if (cur == -1 || tried != -1 || i != 0) { throw new TimeoutException($"Received timeout on try: {(tried == -1 ? 1 : 2)} packet: {i}"); } } //only retries when remote was not passed in, on the first try, and when the first packet was never received if (timedOut) { return(await RetrieveAsync(limit, null, cur)); } seed = ParseResponse(servers, response, limit); if (seed == null) { throw new Exception("Bad packet recieved."); } i++; } while (i < maxIterations && !seed.Equals("0.0.0.0:0") && !seed.Equals(lastSeed)); #if DEBUG this.Logger().Debug("Found {0} servers in {1} packets.", servers.Count, i); #endif return(servers); }
public async Task <List <IPEndPoint> > GetParsedServers(CancellationToken cancelToken, int limit = -1, IPEndPoint remote = null, int tried = -1) { var cur = -1; var servers = new List <IPEndPoint>(); if (remote == null) { var hosts = await Dns.GetHostAddressesAsync("hl2master.steampowered.com").ConfigureAwait(false); if (tried == -1) { cur = new Random().Next(hosts.Length); } else { cur = (tried + 1) % hosts.Length; } var host = hosts[cur]; const int port = 27011; remote = new IPEndPoint(host, port); //TODO: alternate ip and ports availability } var e = new IPEndPoint(IPAddress.Any, 0); var udpClient = new UdpClient(e) { Client = { ReceiveTimeout = Consts.DefaultReceiveTimeout, SendTimeout = Consts.DefaultSendTimeout } }; var i = 0; const int maxIterations = 30; string lastSeed; var seed = "0.0.0.0:0"; do { cancelToken.ThrowIfCancellationRequested(); lastSeed = seed; var msg = BuildMessage(seed); if (await udpClient.SendAsync(msg, msg.Length, remote).ConfigureAwait(false) != msg.Length) { throw new Exception("Send failed."); } byte[] response = null; var timedOut = false; try { response = (await udpClient.ReceiveWithTimeoutAfter(Consts.DefaultReceiveTimeout, cancelToken).ConfigureAwait(false)) .Buffer; } catch (TimeoutException) { timedOut = true; if ((cur == -1) || (tried != -1) || (i != 0)) { throw new TimeoutException(string.Format("Received timeout on try: {0} packet: {1}", tried == -1 ? 1 : 2, i)); } } //only retries when remote was not passed in, on the first try, and when the first packet was never received if (timedOut) { return(await GetParsedServers(cancelToken, limit, null, cur).ConfigureAwait(false)); } seed = ParseResponse(servers, response, limit); if (seed == null) { throw new Exception("Bad packet recieved."); } i++; } while ((i < maxIterations) && !seed.Equals("0.0.0.0:0") && !seed.Equals(lastSeed)); return(servers); }