From 32b2e6b75475246156df3bf6bcaa4071c70eaec9 Mon Sep 17 00:00:00 2001 From: azuisleet Date: Fri, 2 Dec 2011 00:29:46 -0700 Subject: [PATCH] Initial support for Steam3 HTTP CDN. Incomplete. --- DepotDownloader/ContentDownloader.cs | 131 +++++++++++++++++++++---- DepotDownloader/DepotDownloader.csproj | 2 + DepotDownloader/Steam3Session.cs | 20 +++- 3 files changed, 134 insertions(+), 19 deletions(-) diff --git a/DepotDownloader/ContentDownloader.cs b/DepotDownloader/ContentDownloader.cs index 80f59bef..2d6970f2 100644 --- a/DepotDownloader/ContentDownloader.cs +++ b/DepotDownloader/ContentDownloader.cs @@ -123,6 +123,35 @@ namespace DepotDownloader return false; } + static bool DepotHasSteam3Manifest( int depotId, out string manifest_id ) + { + if (steam3 == null || steam3.AppInfo == null) + { + manifest_id = null; + return false; + } + + foreach (var app in steam3.AppInfo) + { + KeyValue depots; + if (app.AppID == depotId && app.Sections.TryGetValue((int)EAppInfoSection.AppInfoSectionDepots, out depots)) + { + string key = depotId.ToString(); + var node = depots.Children.Where(a => a.Name == key).First().Children + .Where(b => b.Name == key).First().Children + .Where(c => c.Name == "manifests").First().Children + .Where(d => d.Name == "Public").First(); + + manifest_id = node.AsString(null); + + return true; + } + } + + manifest_id = null; + return false; + } + public static void Download( int depotId, int depotVersion, int cellId, string username, string password, bool onlyManifest, bool gameServer, bool exclude, string installDir, string[] fileList ) { if ( !CreateDirectories( depotId, depotVersion, ref installDir ) ) @@ -131,37 +160,81 @@ namespace DepotDownloader return; } - Console.Write( "Finding content servers..." ); - IPEndPoint contentServer = GetStorageServer( depotId, depotVersion, cellId ); + ContentServerClient.Credentials credentials = null; + + if (username != null) + { + // ServerCache.BuildAuthServers( username ); + credentials = GetCredentials((uint)depotId, username, password); + } - if ( contentServer == null ) + if (!AccountHasAccess(depotId)) { - Console.WriteLine( "\nError: Unable to find any content servers for depot {0}, version {1}", depotId, depotVersion ); + string contentName = CDRManager.GetDepotName(depotId); + Console.WriteLine("Depot {0} ({1}) is not available from this account.", depotId, contentName); + + if (steam3 != null) + steam3.Disconnect(); + return; } - Console.WriteLine( " Done!" ); + string steam3_manifest = null; + if ( DepotHasSteam3Manifest( depotId, out steam3_manifest ) ) + { + DownloadSteam3( credentials, depotId, depotVersion, cellId ); + } + else + { + DownloadSteam2( credentials, depotId, depotVersion, cellId, username, password, onlyManifest, gameServer, exclude, installDir, fileList ); + } + + if ( steam3 != null ) + steam3.Disconnect(); + } - ContentServerClient.Credentials credentials = null; + private static void DownloadSteam3( ContentServerClient.Credentials credentials, int depotId, int depotVersion, int cellId ) + { + Console.Write("Finding content servers..."); +/* IPEndPoint contentServer = GetAnyStorageServer(); - if ( username != null ) + if (contentServer == null) { - credentials = GetCredentials( ( uint )depotId, username, password ); + Console.WriteLine("\nError: Unable to find any content servers"); + return; } +*/ + + // find a proper bootstrap... + IPEndPoint contentServer1 = new IPEndPoint(IPAddress.Parse("4.28.20.42"), 80); + List cdnServers = CDNClient.FetchServerList(contentServer1, cellId); + + Console.WriteLine(" Done!"); - if ( !AccountHasAccess( depotId ) ) + CDNClient cdnClient = new CDNClient(cdnServers[0], credentials.AppTicket); + + if (!cdnClient.Connect()) { - string contentName = CDRManager.GetDepotName( depotId ); - Console.WriteLine( "Depot {0} ({1}) is not available from this account.", depotId, contentName ); + Console.WriteLine("\nCould not initialize connection with CDN."); + return; + } + } - if ( steam3 != null ) - steam3.Disconnect(); + private static void DownloadSteam2( ContentServerClient.Credentials credentials, int depotId, int depotVersion, int cellId, string username, string password, bool onlyManifest, bool gameServer, bool exclude, string installDir, string[] fileList ) + { + Console.Write("Finding content servers..."); + IPEndPoint contentServer = GetStorageServer(depotId, depotVersion, cellId); + if (contentServer == null) + { + Console.WriteLine("\nError: Unable to find any content servers for depot {0}, version {1}", depotId, depotVersion); return; } - string manifestFile = Path.Combine( installDir, "manifest.bin" ); - string txtManifest = Path.Combine( installDir, "manifest.txt" ); + Console.WriteLine(" Done!"); + + string manifestFile = Path.Combine(installDir, "manifest.bin"); + string txtManifest = Path.Combine(installDir, "manifest.txt"); ContentServerClient csClient = new ContentServerClient(); @@ -313,9 +386,6 @@ namespace DepotDownloader csClient.Disconnect(); - if ( steam3 != null ) - steam3.Disconnect(); - } static ContentServerClient.Credentials GetCredentials( uint depotId, string username, string password ) @@ -374,6 +444,31 @@ namespace DepotDownloader return null; } + + static IPEndPoint GetAnyStorageServer() + { + foreach (IPEndPoint csdServer in ServerCache.CSDSServers) + { + ContentServerDSClient csdsClient = new ContentServerDSClient(); + csdsClient.Connect(csdServer); + + IPEndPoint[] servers = csdsClient.GetContentServerList(); + + if (servers == null) + { + Console.WriteLine("Warning: CSDS {0} returned empty server list.", csdServer); + continue; + } + + if (servers.Length == 0) + continue; + + return servers[PsuedoRandom.GetRandomInt(0, servers.Length - 1)]; + } + + return null; + } + static IPEndPoint GetAuthServer() { if ( ServerCache.AuthServers.Count > 0 ) diff --git a/DepotDownloader/DepotDownloader.csproj b/DepotDownloader/DepotDownloader.csproj index f952909c..e1bdb42d 100644 --- a/DepotDownloader/DepotDownloader.csproj +++ b/DepotDownloader/DepotDownloader.csproj @@ -41,6 +41,7 @@ prompt 4 AllRules.ruleset + x86 pdbonly @@ -50,6 +51,7 @@ prompt 4 AllRules.ruleset + x86 diff --git a/DepotDownloader/Steam3Session.cs b/DepotDownloader/Steam3Session.cs index 3302baa2..c3bcb62d 100644 --- a/DepotDownloader/Steam3Session.cs +++ b/DepotDownloader/Steam3Session.cs @@ -27,6 +27,8 @@ namespace DepotDownloader private set; } + public ReadOnlyCollection AppInfo { get; private set; } + SteamClient steamClient; SteamUser steamUser; @@ -99,7 +101,7 @@ namespace DepotDownloader if ( diff > STEAM3_TIMEOUT && !bConnected ) break; - if ( credentials.HasSessionToken && credentials.AppTicket != null && Licenses != null && credentials.Steam2Ticket != null ) + if ( credentials.HasSessionToken && credentials.AppTicket != null && Licenses != null && credentials.Steam2Ticket != null && AppInfo != null ) break; if ( callback == null ) @@ -141,6 +143,7 @@ namespace DepotDownloader Console.WriteLine( "Got Steam2 Ticket!" ); credentials.Steam2Ticket = msg.Steam2Ticket; + steamApps.GetAppInfo( depotId ); steamApps.GetAppOwnershipTicket( depotId ); } @@ -186,6 +189,21 @@ namespace DepotDownloader Console.WriteLine( "Got {0} licenses for account!", msg.LicenseList.Count ); Licenses = msg.LicenseList; } + + if ( callback.IsType() ) + { + var msg = callback as SteamApps.AppInfoCallback; + + if (msg.AppsPending > 0 || msg.Apps.Count == 0 || msg.Apps[0].Status == SteamApps.AppInfoCallback.AppInfo.AppInfoStatus.Unknown) + { + Console.WriteLine("AppInfo did not contain the requested app id {0}", depotId); + steamUser.LogOff(); + break; + } + + Console.WriteLine("Got AppInfo for {0}", msg.Apps[0].AppID); + AppInfo = msg.Apps; + } } credentialHandle.Set();