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); } }); }
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); } }); }
/// <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 }); }