private void recv(IAsyncResult res)
        {
            int bytesRev = 0;

            try
            {
                bytesRev = UdpSocket.EndReceive(res);
            }
            catch (ObjectDisposedException)
            {
                return;
            }
            var endpoints = MasterUtil.ProcessPacket(recvData.Take(bytesRev).ToArray());

            //ThreadPool.QueueUserWorkItem(x => Callback(endpoints));
            Callback(endpoints);
            if (!endpoints.Last().Equals(SeedEndpoint))
            {
                Msg = MasterUtil.BuildPacket(endpoints.Last().ToString(), RegionCode, Filter);
                UdpSocket.Send(Msg);
                UdpSocket.BeginReceive(recvData, 0, recvData.Length, SocketFlags.None, recv, null);
            }
            else
            {
                IsListening = false;
            }
        }
Пример #2
0
        const string SteamWebApiKey = "B7D245299F6F990504A86FF91EC9D6BD"; // create an account and get a steam web api key at http://steamcommunity.com/dev/apikey

        /// <summary>
        /// Gets a server list from the Steam master server.
        /// The callback is invoked from a background thread every time a batch of servers is received.
        /// The end of the list is marked with an IPEndPoint of 0.0.0.0:0
        /// In case of a timeout or an exception, the callback is invoked with a NULL parameter value.
        /// </summary>
        /// <exception cref="InvalidOperationException">Thrown if the object is still busy handling a previous call to GetAddresses</exception>
        public override void GetAddresses(Region region, MasterIpCallback callback, IpFilter filter)
        {
            ThreadPool.QueueUserWorkItem(x =>
            {
                try
                {
                    using (var cli = new XWebClient())
                    {
                        var filters = MasterUtil.ProcessFilter(filter);
                        var url     = $"https://api.steampowered.com/IGameServersService/GetServerList/v1/?key={SteamWebApiKey}&format=xml&filter={filters}&limit={GetAddressesLimit}";
                        var xml     = cli.DownloadString(url);
                        var ser     = new XmlSerializer(typeof(Response));

                        // replace invalid XML chars ( < 32 ) with char reference
                        var sb = new StringBuilder(xml);
                        for (int i = 0, c = xml.Length; i < c; i++)
                        {
                            if (sb[i] < 32 && !char.IsWhiteSpace(sb[i]))
                            {
                                //{
                                //  sb.Insert(i+1, "#" + ((int)sb[i]).ToString() + ";");
                                //  sb[i] = '&';
                                //}
                                sb[i] = ' ';
                            }
                        }
                        xml = sb.ToString();

                        var resp = (Response)ser.Deserialize(new StringReader(xml));

                        var endpoints = new List <Tuple <IPEndPoint, ServerInfo> >();
                        foreach (var msg in resp.Servers)
                        {
                            try
                            {
                                int i = msg.addr.IndexOf(':');
                                if (i > 0)
                                {
                                    var info = ConvertToServerInfo(msg);
                                    endpoints.Add(new Tuple <IPEndPoint, ServerInfo>(info.EndPoint, info));
                                }
                            }
                            catch
                            {
                            }
                        }
                        callback(new ReadOnlyCollection <Tuple <IPEndPoint, ServerInfo> >(endpoints), null, false);
                    }
                }
                catch (Exception ex)
                {
                    callback(null, ex, false);
                }
            });
        }
Пример #3
0
        private ReadOnlyCollection <IPEndPoint> SendAndReceive(Socket udpSocket, byte[] recvData, Region region, IpFilter filter, IPEndPoint seed)
        {
            var msg = MasterUtil.BuildPacket(seed.ToString(), region, filter);

            udpSocket.Send(msg);

            int len = udpSocket.Receive(recvData, 0, recvData.Length, SocketFlags.None);

            byte[] data = new byte[len];
            Array.Copy(recvData, data, data.Length);
            return(MasterUtil.ProcessPacket(data));
        }
        /// <summary>
        /// Starts receiving socket addresses of servers.
        /// </summary>
        /// <param name="region">The region of the world that you wish to find servers in.</param>
        /// <param name="callback">Called when a batch of Socket addresses are received.</param>
        /// <param name="filter">Used to set filter on the type of server required.</param>
        public void GetAddresses(Region region, MasterIpCallback callback, IpFilter filter = null)
        {
            if (IsListening)
            {
                return;
            }

            RegionCode  = region;
            Callback    = callback;
            Filter      = filter;
            IsListening = true;
            IPEndPoint endPoint = SeedEndpoint;

            Msg = MasterUtil.BuildPacket(endPoint.ToString(), RegionCode, Filter);
            UdpSocket.Send(Msg);
            recvData = new byte[1400];
            UdpSocket.BeginReceive(recvData, 0, recvData.Length, SocketFlags.None, recv, null);
        }
Пример #5
0
        const string SteamWebApiKey = "B7D245299F6F990504A86FF91EC9D6BD"; // create an account and get a steam web api key at http://steamcommunity.com/dev/apikey

        /// <summary>
        /// Gets a server list from the Steam master server.
        /// The callback is invoked from a background thread every time a batch of servers is received.
        /// The end of the list is marked with an IPEndPoint of 0.0.0.0:0
        /// In case of a timeout or an exception, the callback is invoked with a NULL parameter value.
        /// </summary>
        /// <exception cref="InvalidOperationException">Thrown if the object is still busy handling a previous call to GetAddresses</exception>
        public override void GetAddresses(Region region, MasterIpCallback callback, IpFilter filter)
        {
            ThreadPool.QueueUserWorkItem(x =>
            {
                try
                {
                    using (var cli = new XWebClient())
                    {
                        var filters = MasterUtil.ProcessFilter(filter);
                        var url     = $"https://api.steampowered.com/IGameServersService/GetServerList/v1/?key={SteamWebApiKey}&format=xml&filter={filters}&limit={GetAddressesLimit}";
                        var xml     = cli.DownloadString(url);
                        var ser     = new XmlSerializer(typeof(Response));
                        var resp    = (Response)ser.Deserialize(new StringReader(xml));

                        var endpoints = new List <Tuple <IPEndPoint, ServerInfo> >();
                        foreach (var msg in resp.Servers)
                        {
                            try
                            {
                                int i = msg.addr.IndexOf(':');
                                if (i > 0)
                                {
                                    var info = ConvertToServerInfo(msg);
                                    endpoints.Add(new Tuple <IPEndPoint, ServerInfo>(info.EndPoint, info));
                                }
                            }
                            catch
                            {
                            }
                        }
                        callback(new ReadOnlyCollection <Tuple <IPEndPoint, ServerInfo> >(endpoints), null, false);
                    }
                }
                catch (Exception ex)
                {
                    callback(null, ex, false);
                }
            });
        }
Пример #6
0
        /// <summary>
        /// Gets a server list from the Steam master server.
        /// The callback is invoked from a background thread every time a batch of servers is received.
        /// The end of the list is marked with an IPEndPoint of 0.0.0.0:0
        /// In case of a timeout or an exception, the callback is invoked with a NULL parameter value.
        /// </summary>
        /// <exception cref="InvalidOperationException">Thrown if the object is still busy handling a previous call to GetAddresses</exception>
        public void GetAddresses(Region region, MasterIpCallback callback, IpFilter filter)
        {
            ThreadPool.QueueUserWorkItem(x =>
            {
#if true
                try
                {
                    using (var cli = new XWebClient())
                    {
                        var filters = MasterUtil.ProcessFilter(filter);
                        var url     = $"https://api.steampowered.com/IGameServersService/GetServerList/v1/?key={SteamWebApiKey}&format=xml&filter={filters}&limit={GetAddressesLimit}";
                        var xml     = cli.DownloadString(url);
                        var ser     = new XmlSerializer(typeof(Response));
                        var resp    = (Response)ser.Deserialize(new StringReader(xml));

                        var endpoints = new List <Tuple <IPEndPoint, ServerInfo> >();
                        foreach (var msg in resp.Servers)
                        {
                            try
                            {
                                int i = msg.addr.IndexOf(':');
                                if (i > 0)
                                {
                                    var info = ConvertToServerInfo(msg);
                                    endpoints.Add(new Tuple <IPEndPoint, ServerInfo>(info.EndPoint, info));
                                }
                            }
                            catch
                            {
                            }
                        }
                        callback(new ReadOnlyCollection <Tuple <IPEndPoint, ServerInfo> >(endpoints), null);
                    }
                }
                catch (Exception ex)
                {
                    callback(null, ex);
                }
#else
                var udpSocket            = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, ProtocolType.Udp);
                udpSocket.SendTimeout    = 500;
                udpSocket.ReceiveTimeout = 500;
                udpSocket.Connect(endPoint);
                byte[] recvData = new byte[1400];

                try
                {
                    var nextSeed   = SeedEndpoint;
                    int totalCount = 0;
                    do
                    {
                        var curSeed   = nextSeed;
                        var endpoints = Util.RunWithRetries(() => SendAndReceive(udpSocket, recvData, region, filter, curSeed), this.Retries);
                        if (endpoints == null)
                        {
                            callback(null);
                            break;
                        }
                        ThreadPool.QueueUserWorkItem(y => callback(endpoints, null));
                        totalCount += endpoints.Count;
                        nextSeed    = endpoints.Last();
                    } while (!nextSeed.Equals(SeedEndpoint) && totalCount < GetAddressesLimit);
                }
                catch (Exception ex)
                {
                    callback(null, ex);
                }
                finally
                {
                    try { udpSocket.Close(); }
                    catch { }
                }
#endif
            });
        }