diff --git a/SteamKit2/SteamKit2/Steam/CDNClient.cs b/SteamKit2/SteamKit2/Steam/CDNClient.cs
index 2e7020970..d521274b0 100644
--- a/SteamKit2/SteamKit2/Steam/CDNClient.cs
+++ b/SteamKit2/SteamKit2/Steam/CDNClient.cs
@@ -64,6 +64,11 @@ public enum ConnectionProtocol
///
public string Type { get; internal set; }
+ ///
+ /// Gets the SourceID this server belongs to.
+ ///
+ public int SourceID { get; internal set; }
+
///
/// Gets the CellID this server belongs to.
///
@@ -370,7 +375,7 @@ public async Task ConnectAsync( Server csServer )
}
// Nothing needs to be done to initialize a session to a CDN server
- if ( csServer.Type == "CDN" )
+ if ( csServer.Type == "CDN" || csServer.Type == "SteamCache" )
{
connectedServer = csServer;
return;
@@ -426,7 +431,7 @@ public async Task AuthenticateDepotAsync( uint depotid, byte[] depotKey = null,
string data;
- if ( connectedServer.Type != "CDN" || cdnAuthToken == null )
+ if ( (connectedServer.Type != "CDN" && connectedServer.Type != "SteamCache") || cdnAuthToken == null )
{
if ( appTicket == null )
{
diff --git a/SteamKit2/SteamKit2/Steam/WebAPI/ContentServerDirectoryService.cs b/SteamKit2/SteamKit2/Steam/WebAPI/ContentServerDirectoryService.cs
new file mode 100644
index 000000000..97b943e05
--- /dev/null
+++ b/SteamKit2/SteamKit2/Steam/WebAPI/ContentServerDirectoryService.cs
@@ -0,0 +1,120 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using SteamKit2.Discovery;
+
+namespace SteamKit2
+{
+ ///
+ /// Helper class to load servers from the Content Server Directory Service Web API.
+ ///
+ public static class ContentServerDirectoryService
+ {
+ ///
+ /// Load a list of servers from the Content Server Directory Service.
+ ///
+ /// Configuration Object
+ /// A with the Result set to an enumerable list of s.
+ public static Task> LoadAsync( SteamConfiguration configuration )
+ => LoadCoreAsync( configuration, null, null, CancellationToken.None );
+
+ ///
+ /// Load a list of servers from the Content Server Directory Service.
+ ///
+ /// Configuration Object
+ /// Cancellation Token
+ /// A with the Result set to an enumerable list of s.
+ public static Task> LoadAsync( SteamConfiguration configuration, CancellationToken cancellationToken )
+ => LoadCoreAsync( configuration, null, null, cancellationToken );
+
+ ///
+ /// Load a list of servers from the Content Server Directory Service.
+ ///
+ /// Configuration Object
+ /// Preferred steam cell id
+ /// Cancellation Token
+ /// A with the Result set to an enumerable list of s.
+ public static Task> LoadAsync( SteamConfiguration configuration, int cellId, CancellationToken cancellationToken )
+ => LoadCoreAsync( configuration, cellId, null, cancellationToken );
+
+ ///
+ /// Load a list of servers from the Content Server Directory Service.
+ ///
+ /// Configuration Object
+ /// Preferred steam cell id
+ /// Max number of servers to return.
+ /// Cancellation Token
+ /// A with the Result set to an enumerable list of s.
+ public static Task> LoadAsync( SteamConfiguration configuration, int cellId, int maxNumServers, CancellationToken cancellationToken )
+ => LoadCoreAsync( configuration, cellId, maxNumServers, cancellationToken );
+
+ static async Task> LoadCoreAsync( SteamConfiguration configuration, int? cellId, int? maxNumServers, CancellationToken cancellationToken )
+ {
+ if ( configuration == null )
+ {
+ throw new ArgumentNullException( nameof( configuration ) );
+ }
+
+ var directory = configuration.GetAsyncWebAPIInterface( "IContentServerDirectoryService" );
+ var args = new Dictionary();
+
+ if ( cellId.HasValue )
+ {
+ args[ "cell_id" ] = cellId.Value.ToString( CultureInfo.InvariantCulture );
+ }
+ else
+ {
+ args[ "cell_id" ] = configuration.CellID.ToString( CultureInfo.InvariantCulture );
+ }
+
+ if ( maxNumServers.HasValue )
+ {
+ args[ "max_servers" ] = maxNumServers.Value.ToString( CultureInfo.InvariantCulture );
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var response = await directory.CallAsync( HttpMethod.Get, "GetServersForSteamPipe", version: 1, args: args ).ConfigureAwait( false );
+
+ var result = ( EResult )response[ "result" ].AsInteger( ( int )EResult.OK );
+ if ( result != EResult.OK || response["servers"] == KeyValue.Invalid )
+ {
+ throw new InvalidOperationException( string.Format( "Steam Web API returned EResult.{0}", result ) );
+ }
+
+ var serverList = response[ "servers" ];
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var serverRecords = new List( capacity: serverList.Children.Count );
+
+ foreach ( var child in serverList.Children )
+ {
+ string httpsSupport = child[ "https_support" ].AsString();
+ var protocol = ( httpsSupport == "optional" || httpsSupport == "mandatory" ) ? CDNClient.Server.ConnectionProtocol.HTTPS : CDNClient.Server.ConnectionProtocol.HTTP;
+
+ serverRecords.Add( new CDNClient.Server
+ {
+ Protocol = protocol,
+ Host = child[ "host" ].AsString(),
+ VHost = child[ "vhost" ].AsString(),
+ Port = protocol == CDNClient.Server.ConnectionProtocol.HTTPS ? 443 : 80,
+
+ Type = child[ "type" ].AsString(),
+ SourceID = child[ "source_id"].AsInteger(),
+ CellID = (uint)child[ "cell" ].AsInteger(),
+
+ Load = child[ "load" ].AsInteger(),
+ WeightedLoad = child[ "weighted_load" ].AsInteger(),
+ NumEntries = child[ "num_entries_in_client_list" ].AsInteger( 1 )
+ }
+ );
+ }
+
+ return serverRecords.AsReadOnly();
+ }
+ }
+}