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;
        }
Ejemplo n.º 2
0
        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(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 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;
        }