From 49e857b4e813aaf31ee470383f2f77157cd663b9 Mon Sep 17 00:00:00 2001 From: Ryan Kistner Date: Fri, 1 Dec 2017 00:45:03 -0700 Subject: [PATCH] Include protocol and vhost for proper HTTPS support in CDNClient. --- SteamKit2/SteamKit2/Steam/CDNClient.cs | 45 +++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/SteamKit2/SteamKit2/Steam/CDNClient.cs b/SteamKit2/SteamKit2/Steam/CDNClient.cs index a6d273675..5fd8d9e83 100644 --- a/SteamKit2/SteamKit2/Steam/CDNClient.cs +++ b/SteamKit2/SteamKit2/Steam/CDNClient.cs @@ -27,11 +27,33 @@ public sealed class CDNClient : IDisposable /// public sealed class Server { + /// The protocol used to connect to this server + /// + public enum ConnectionProtocol + { + /// + /// Server does not advertise HTTPS support, connect over HTTP + /// + HTTP = 0, + /// + /// Server advertises it supports HTTPS, connection made over HTTPS + /// + HTTPS = 1 + } + + /// + /// Gets the supported connection protocol of the server. + /// + public ConnectionProtocol Protocol { get; internal set; } /// /// Gets the hostname of the server. /// public string Host { get; internal set; } /// + /// Gets the virtual hostname of the server. + /// + public string VHost { get; internal set; } + /// /// Gets the port of the server. /// public int Port { get; internal set; } @@ -70,7 +92,9 @@ public static implicit operator Server( IPEndPoint endPoint ) { return new Server { + Protocol = endPoint.Port == 443 ? ConnectionProtocol.HTTPS : ConnectionProtocol.HTTP, Host = endPoint.Address.ToString(), + VHost = endPoint.Address.ToString(), Port = endPoint.Port, }; } @@ -86,7 +110,9 @@ public static implicit operator Server( DnsEndPoint endPoint ) { return new Server { + Protocol = endPoint.Port == 443 ? ConnectionProtocol.HTTPS : ConnectionProtocol.HTTP, Host = endPoint.Host, + VHost = endPoint.Host, Port = endPoint.Port, }; } @@ -273,6 +299,7 @@ public async Task> FetchServerListAsync( IPEndPoint csServer = nul { string type = server[ "type" ].AsString(); string host = server[ "host" ].AsString(); + string vhost = server[ "vhost" ].AsString(); string[] hostSplits = host.Split( ':' ); @@ -291,6 +318,7 @@ public async Task> FetchServerListAsync( IPEndPoint csServer = nul int weightedLoad = server[ "weightedload" ].AsInteger(); int entries = server[ "NumEntriesInClientList" ].AsInteger( 1 ); int useTokenAuth = server[ "usetokenauth" ].AsInteger(); + string httpsSupport = server[ "https_support" ].AsString(); // If usetokenauth is specified, we can treat this server as a CDN and request tokens if ( useTokenAuth > 0 ) @@ -298,10 +326,14 @@ public async Task> FetchServerListAsync( IPEndPoint csServer = nul type = "CDN"; } + Server.ConnectionProtocol protocol = ( httpsSupport == "optional" || httpsSupport == "mandatory" ) ? Server.ConnectionProtocol.HTTPS : Server.ConnectionProtocol.HTTP; + serverList.Add( new Server { + Protocol = protocol, Host = host, - Port = port, + VHost = vhost, + Port = protocol == Server.ConnectionProtocol.HTTPS ? 443 : port, Type = type, @@ -437,7 +469,9 @@ public async Task DownloadManifestAsync( uint depotId, ulong mani { var server = new Server { + Protocol = Server.ConnectionProtocol.HTTP, Host = host, + VHost = host, Port = 80 }; @@ -528,7 +562,9 @@ public async Task DownloadDepotChunkAsync( uint depotId, DepotManife var server = new Server { + Protocol = Server.ConnectionProtocol.HTTP, Host = host, + VHost = host, Port = 80 }; @@ -545,7 +581,8 @@ public void Dispose() string BuildCommand( Server server, string command, string args, string authtoken = null ) { - return string.Format( "http://{0}:{1}/{2}/{3}{4}", server.Host, server.Port, command, args, authtoken ?? "" ); + string protocol = server.Protocol == Server.ConnectionProtocol.HTTP ? "http" : "https"; + return string.Format( "{0}://{1}:{2}/{3}/{4}{5}", protocol, server.VHost, server.Port, command, args, authtoken ?? "" ); } async Task DoRawCommandAsync( Server server, HttpMethod method, string command, string data = null, bool doAuth = false, string args = "", string authtoken = null ) @@ -584,15 +621,13 @@ async Task DoRawCommandAsync( Server server, HttpMethod method, string c request.Content.Headers.ContentType = new MediaTypeHeaderValue( "application/x-www-form-urlencoded" ); } - - HttpResponseMessage response; using ( var cts = new CancellationTokenSource() ) { cts.CancelAfter( RequestTimeout ); try { - response = await httpClient.SendAsync( request, cts.Token ).ConfigureAwait( false ); + var response = await httpClient.SendAsync( request, cts.Token ).ConfigureAwait( false ); var responseData = await response.Content.ReadAsByteArrayAsync().ConfigureAwait( false ); return responseData;