From bb1724746bd9837d43629dd1d50f3d1eb5d56887 Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Thu, 24 Oct 2013 13:13:00 -0400 Subject: [PATCH] Hack in support for multiple servers and retry logic with concurrent downloading. --- DepotDownloader/ContentDownloader.cs | 69 ++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/DepotDownloader/ContentDownloader.cs b/DepotDownloader/ContentDownloader.cs index 59b79595..98ded980 100644 --- a/DepotDownloader/ContentDownloader.cs +++ b/DepotDownloader/ContentDownloader.cs @@ -443,38 +443,49 @@ namespace DepotDownloader Console.WriteLine("Downloading depot {0} - {1}", depot.id, depot.contentName); Console.Write("Finding content servers..."); - CDNClient client = new CDNClient(steam3.steamClient, depot.id, steam3.AppTickets[depot.id], depot.depotKey); - var cdnServers = client.FetchServerList(cellId: (uint)Config.CellID); + var cdnClients = new List(); + CDNClient initialClient = new CDNClient(steam3.steamClient, depot.id, steam3.AppTickets[depot.id], depot.depotKey); + var cdnServers = initialClient.FetchServerList(cellId: (uint)Config.CellID); if (cdnServers.Count == 0) { Console.WriteLine("\nUnable to find any content servers for depot {0} - {1}", depot.id, depot.contentName); - return; + continue; } - Console.WriteLine(" Done!"); - Console.Write("Downloading depot manifest..."); - - for (int i = 0; i < cdnServers.Count; ++i) + // Grab the six best servers + Enumerable.Range(0, Math.Min(cdnServers.Count, 6)).ToList().ForEach(s => { - var server = cdnServers[i]; + CDNClient c; + if( s == 0 ) + { + c = initialClient; + } + else + { + c = new CDNClient(steam3.steamClient, depot.id, steam3.AppTickets[depot.id], depot.depotKey); + } + try { - client.Connect(server); - break; + c.Connect(cdnServers[s]); + cdnClients.Add(c); } catch { - Console.WriteLine("\nFailed to connect to content server {0}. Remaining content servers for depot: {1}.", server, cdnServers.Count - i - 1); + Console.WriteLine("\nFailed to connect to content server {0}. Remaining content servers for depot: {1}.", cdnServers[s], cdnServers.Count - s - 1); } - } + }); + + Console.WriteLine(" Done!"); + Console.Write("Downloading depot manifest..."); DepotManifest depotManifest = null; - foreach (var server in cdnServers) + foreach (var c in cdnClients) { try { - depotManifest = client.DownloadManifest(depot.manifestId); + depotManifest = c.DownloadManifest(depot.manifestId); break; } catch (WebException) { } @@ -537,8 +548,12 @@ namespace DepotDownloader complete_download_size += file.TotalSize; } + var rand = new Random(); + depotManifest.Files.AsParallel().WithDegreeOfParallelism(4).ForAll(file => { + var clientIndex = rand.Next(0, cdnClients.Count); + string download_path = Path.Combine(depot.installDir, file.FileName); string fileStagingPath = Path.Combine(stagingDir, file.FileName); @@ -663,7 +678,31 @@ namespace DepotDownloader { string chunkID = Util.EncodeHexString(chunk.ChunkID); - var chunkData = client.DownloadDepotChunk(chunk); + CDNClient.DepotChunk chunkData = null; + int idx = clientIndex; + while (true) + { + try + { + chunkData = cdnClients[idx].DownloadDepotChunk(chunk); + break; + } + catch + { + if (++idx >= cdnClients.Count) + idx = 0; + + if (idx == clientIndex) + break; + } + } + + if (chunkData == null) + { + Console.WriteLine("Failed to find any server with chunk {0} for depot {1}. Aborting.", chunkID, depot); + return; + } + TotalBytesCompressed += chunk.CompressedLength; DepotBytesCompressed += chunk.CompressedLength; TotalBytesUncompressed += chunk.UncompressedLength;