diff --git a/DepotDownloader/CDNClientPool.cs b/DepotDownloader/CDNClientPool.cs index be45e167..8747243d 100644 --- a/DepotDownloader/CDNClientPool.cs +++ b/DepotDownloader/CDNClientPool.cs @@ -25,7 +25,7 @@ namespace DepotDownloader private BlockingCollection availableServerEndpoints; private AutoResetEvent populatePoolEvent; - private Thread monitorThread; + private Task monitorTask; public CDNClientPool(Steam3Session steamSession) { @@ -37,13 +37,10 @@ namespace DepotDownloader populatePoolEvent = new AutoResetEvent(true); - monitorThread = new Thread(ConnectionPoolMonitor); - monitorThread.Name = "CDNClient Pool Monitor"; - monitorThread.IsBackground = true; - monitorThread.Start(); + monitorTask = Task.Factory.StartNew(ConnectionPoolMonitorAsync).Unwrap(); } - private List FetchBootstrapServerList() + private async Task> FetchBootstrapServerListAsync() { CDNClient bootstrap = new CDNClient(steamSession.steamClient); @@ -51,7 +48,7 @@ namespace DepotDownloader { try { - var cdnServers = bootstrap.FetchServerList(cellId: (uint)ContentDownloader.Config.CellID); + var cdnServers = await bootstrap.FetchServerListAsync(cellId: (uint)ContentDownloader.Config.CellID).ConfigureAwait(false); if (cdnServers != null) { return cdnServers; @@ -64,7 +61,7 @@ namespace DepotDownloader } } - private void ConnectionPoolMonitor() + private async Task ConnectionPoolMonitorAsync() { while(true) { @@ -75,7 +72,7 @@ namespace DepotDownloader steamSession.steamClient.IsConnected && steamSession.steamClient.GetServersOfType(EServerType.CS).Count > 0) { - var servers = FetchBootstrapServerList(); + var servers = await FetchBootstrapServerListAsync(); var weightedCdnServers = servers.Select(x => { @@ -101,7 +98,7 @@ namespace DepotDownloader activeClientAuthed.TryRemove(client, out authData); } - private CDNClient BuildConnection(uint appId, uint depotId, byte[] depotKey, CDNClient.Server serverSeed, CancellationToken token) + private async Task BuildConnectionAsync(uint appId, uint depotId, byte[] depotKey, CDNClient.Server serverSeed, CancellationToken token) { CDNClient.Server server = null; CDNClient client = null; @@ -147,8 +144,8 @@ namespace DepotDownloader } } - client.Connect(server); - client.AuthenticateDepot(depotId, depotKey, cdnAuthToken); + await client.ConnectAsync(server).ConfigureAwait(false); + await client.AuthenticateDepotAsync(depotId, depotKey, cdnAuthToken).ConfigureAwait(false); } catch (Exception ex) { @@ -168,7 +165,7 @@ namespace DepotDownloader return client; } - private bool ReauthConnection(CDNClient client, CDNClient.Server server, uint appId, uint depotId, byte[] depotKey) + private async Task ReauthConnectionAsync(CDNClient client, CDNClient.Server server, uint appId, uint depotId, byte[] depotKey) { DebugLog.Assert(server.Type == "CDN" || steamSession.AppTickets[depotId] == null, "CDNClientPool", "Re-authing a CDN or anonymous connection"); @@ -193,7 +190,7 @@ namespace DepotDownloader } } - client.AuthenticateDepot(depotId, depotKey, cdnAuthToken); + await client.AuthenticateDepotAsync(depotId, depotKey, cdnAuthToken).ConfigureAwait(false); activeClientAuthed[client] = Tuple.Create(depotId, server); return true; } @@ -205,7 +202,7 @@ namespace DepotDownloader return false; } - public CDNClient GetConnectionForDepot(uint appId, uint depotId, byte[] depotKey, CancellationToken token) + public async Task GetConnectionForDepotAsync(uint appId, uint depotId, byte[] depotKey, CancellationToken token) { CDNClient client = null; @@ -216,24 +213,24 @@ namespace DepotDownloader // if we couldn't find a connection, make one now if (client == null) { - client = BuildConnection(appId, depotId, depotKey, null, token); + client = await BuildConnectionAsync(appId, depotId, depotKey, null, token).ConfigureAwait(false); } // if we couldn't find the authorization data or it's not authed to this depotid, re-initialize if (!activeClientAuthed.TryGetValue(client, out authData) || authData.Item1 != depotId) { - if (authData.Item2.Type == "CDN" && ReauthConnection(client, authData.Item2, appId, depotId, depotKey)) + if (authData.Item2.Type == "CDN" && await ReauthConnectionAsync(client, authData.Item2, appId, depotId, depotKey).ConfigureAwait(false)) { Console.WriteLine("Re-authed CDN connection to content server {0} from {1} to {2}", authData.Item2, authData.Item1, depotId); } - else if (authData.Item2.Type == "CS" && steamSession.AppTickets[depotId] == null && ReauthConnection(client, authData.Item2, appId, depotId, depotKey)) + else if (authData.Item2.Type == "CS" && steamSession.AppTickets[depotId] == null && await ReauthConnectionAsync(client, authData.Item2, appId, depotId, depotKey).ConfigureAwait(false)) { Console.WriteLine("Re-authed anonymous connection to content server {0} from {1} to {2}", authData.Item2, authData.Item1, depotId); } else { ReleaseConnection(client); - client = BuildConnection(appId, depotId, depotKey, authData.Item2, token); + client = await BuildConnectionAsync(appId, depotId, depotKey, authData.Item2, token).ConfigureAwait(false); } } diff --git a/DepotDownloader/ContentDownloader.cs b/DepotDownloader/ContentDownloader.cs index 564b63c4..07e33815 100644 --- a/DepotDownloader/ContentDownloader.cs +++ b/DepotDownloader/ContentDownloader.cs @@ -238,62 +238,62 @@ namespace DepotDownloader if (branch != "Public" && node == KeyValue.Invalid) { var node_encrypted = manifests_encrypted[branch]; - if (node_encrypted != KeyValue.Invalid) - { - string password = Config.BetaPassword; - if (password == null) - { - Console.Write("Please enter the password for branch {0}: ", branch); - Config.BetaPassword = password = Console.ReadLine(); - } - - var encrypted_v1 = node_encrypted["encrypted_gid"]; - var encrypted_v2 = node_encrypted["encrypted_gid_2"]; - - if (encrypted_v1 != KeyValue.Invalid) - { - byte[] input = Util.DecodeHexString(encrypted_v1.Value); - byte[] manifest_bytes = CryptoHelper.VerifyAndDecryptPassword(input, password); - - if (manifest_bytes == null) - { - Console.WriteLine("Password was invalid for branch {0}", branch); - return INVALID_MANIFEST_ID; - } - - return BitConverter.ToUInt64(manifest_bytes, 0); - } - else if (encrypted_v2 != KeyValue.Invalid) - { - // Submit the password to Steam now to get encryption keys - steam3.CheckAppBetaPassword(appId, Config.BetaPassword); - - if (!steam3.AppBetaPasswords.ContainsKey(branch)) - { - Console.WriteLine("Password was invalid for branch {0}", branch); - return INVALID_MANIFEST_ID; - } - - byte[] input = Util.DecodeHexString(encrypted_v2.Value); - byte[] manifest_bytes; - try - { - manifest_bytes = CryptoHelper.SymmetricDecryptECB(input, steam3.AppBetaPasswords[branch]); - } - catch (Exception e) - { - Console.WriteLine("Failed to decrypt branch {0}: {1}", branch, e.Message); - return INVALID_MANIFEST_ID; - } - - return BitConverter.ToUInt64(manifest_bytes, 0); - } - else - { - Console.WriteLine("Unhandled depot encryption for depotId {0}", depotId); - return INVALID_MANIFEST_ID; - } - + if (node_encrypted != KeyValue.Invalid) + { + string password = Config.BetaPassword; + if (password == null) + { + Console.Write("Please enter the password for branch {0}: ", branch); + Config.BetaPassword = password = Console.ReadLine(); + } + + var encrypted_v1 = node_encrypted["encrypted_gid"]; + var encrypted_v2 = node_encrypted["encrypted_gid_2"]; + + if (encrypted_v1 != KeyValue.Invalid) + { + byte[] input = Util.DecodeHexString(encrypted_v1.Value); + byte[] manifest_bytes = CryptoHelper.VerifyAndDecryptPassword(input, password); + + if (manifest_bytes == null) + { + Console.WriteLine("Password was invalid for branch {0}", branch); + return INVALID_MANIFEST_ID; + } + + return BitConverter.ToUInt64(manifest_bytes, 0); + } + else if (encrypted_v2 != KeyValue.Invalid) + { + // Submit the password to Steam now to get encryption keys + steam3.CheckAppBetaPassword(appId, Config.BetaPassword); + + if (!steam3.AppBetaPasswords.ContainsKey(branch)) + { + Console.WriteLine("Password was invalid for branch {0}", branch); + return INVALID_MANIFEST_ID; + } + + byte[] input = Util.DecodeHexString(encrypted_v2.Value); + byte[] manifest_bytes; + try + { + manifest_bytes = CryptoHelper.SymmetricDecryptECB(input, steam3.AppBetaPasswords[branch]); + } + catch (Exception e) + { + Console.WriteLine("Failed to decrypt branch {0}: {1}", branch, e.Message); + return INVALID_MANIFEST_ID; + } + + return BitConverter.ToUInt64(manifest_bytes, 0); + } + else + { + Console.WriteLine("Unhandled depot encryption for depotId {0}", depotId); + return INVALID_MANIFEST_ID; + } + } return INVALID_MANIFEST_ID; @@ -362,22 +362,22 @@ namespace DepotDownloader steam3.Disconnect(); } - public static void DownloadApp(uint appId, uint depotId, string branch, bool forceDepot = false) + public static async Task DownloadAppAsync(uint appId, uint depotId, string branch, bool forceDepot = false) { if(steam3 != null) steam3.RequestAppInfo(appId); if (!AccountHasAccess(appId)) { - if (steam3.RequestFreeAppLicense(appId)) - { - Console.WriteLine("Obtained FreeOnDemand license for app {0}", appId); + if (steam3.RequestFreeAppLicense(appId)) + { + Console.WriteLine("Obtained FreeOnDemand license for app {0}", appId); } - else - { - string contentName = GetAppOrDepotName(INVALID_DEPOT_ID, appId); - Console.WriteLine("App {0} ({1}) is not available from this account.", appId, contentName); - return; + else + { + string contentName = GetAppOrDepotName(INVALID_DEPOT_ID, appId); + Console.WriteLine("App {0} ({1}) is not available from this account.", appId, contentName); + return; } } @@ -451,7 +451,7 @@ namespace DepotDownloader try { - DownloadSteam3(appId, infos); + await DownloadSteam3Async(appId, infos).ConfigureAwait(false); } catch (OperationCanceledException) { @@ -524,7 +524,7 @@ namespace DepotDownloader public ProtoManifest.ChunkData NewChunk { get; private set; } } - private static void DownloadSteam3( uint appId, List depots ) + private static async Task DownloadSteam3Async( uint appId, List depots ) { ulong TotalBytesCompressed = 0; ulong TotalBytesUncompressed = 0; @@ -583,9 +583,9 @@ namespace DepotDownloader { CDNClient client = null; try { - client = cdnPool.GetConnectionForDepot(appId, depot.id, depot.depotKey, CancellationToken.None); + client = await cdnPool.GetConnectionForDepotAsync(appId, depot.id, depot.depotKey, CancellationToken.None).ConfigureAwait(false); - depotManifest = client.DownloadManifest(depot.id, depot.manifestId); + depotManifest = await client.DownloadManifestAsync(depot.id, depot.manifestId).ConfigureAwait(false); cdnPool.ReturnConnection(client); } @@ -677,200 +677,210 @@ namespace DepotDownloader } }); + var semaphore = new SemaphoreSlim(Config.MaxDownloads); filesAfterExclusions.Where(f => !f.Flags.HasFlag(EDepotFileFlag.Directory)) .AsParallel().WithCancellation(cts.Token).WithDegreeOfParallelism(Config.MaxDownloads) - .ForAll(file => + .ForAll(async file => { - string fileFinalPath = Path.Combine(depot.installDir, file.FileName); - string fileStagingPath = Path.Combine(stagingDir, file.FileName); - - // This may still exist if the previous run exited before cleanup - if (File.Exists(fileStagingPath)) + try { - File.Delete(fileStagingPath); - } + await semaphore.WaitAsync().ConfigureAwait(false); - FileStream fs = null; - List neededChunks; - FileInfo fi = new FileInfo(fileFinalPath); - if (!fi.Exists) - { - // create new file. need all chunks - fs = File.Create(fileFinalPath); - fs.SetLength((long)file.TotalSize); - neededChunks = new List(file.Chunks); - } - else - { - // open existing - ProtoManifest.FileData oldManifestFile = null; - if (oldProtoManifest != null) + string fileFinalPath = Path.Combine(depot.installDir, file.FileName); + string fileStagingPath = Path.Combine(stagingDir, file.FileName); + + // This may still exist if the previous run exited before cleanup + if (File.Exists(fileStagingPath)) { - oldManifestFile = oldProtoManifest.Files.SingleOrDefault(f => f.FileName == file.FileName); + File.Delete(fileStagingPath); } - if (oldManifestFile != null) + FileStream fs = null; + List neededChunks; + FileInfo fi = new FileInfo(fileFinalPath); + if (!fi.Exists) { - neededChunks = new List(); - - if (Config.VerifyAll || !oldManifestFile.FileHash.SequenceEqual(file.FileHash)) + // create new file. need all chunks + fs = File.Create(fileFinalPath); + fs.SetLength((long)file.TotalSize); + neededChunks = new List(file.Chunks); + } + else + { + // open existing + ProtoManifest.FileData oldManifestFile = null; + if (oldProtoManifest != null) { - // we have a version of this file, but it doesn't fully match what we want + oldManifestFile = oldProtoManifest.Files.SingleOrDefault(f => f.FileName == file.FileName); + } - var matchingChunks = new List(); + if (oldManifestFile != null) + { + neededChunks = new List(); - foreach (var chunk in file.Chunks) + if (Config.VerifyAll || !oldManifestFile.FileHash.SequenceEqual(file.FileHash)) { - var oldChunk = oldManifestFile.Chunks.FirstOrDefault(c => c.ChunkID.SequenceEqual(chunk.ChunkID)); - if (oldChunk != null) - { - matchingChunks.Add(new ChunkMatch(oldChunk, chunk)); - } - else - { - neededChunks.Add(chunk); - } - } + // we have a version of this file, but it doesn't fully match what we want - File.Move(fileFinalPath, fileStagingPath); + var matchingChunks = new List(); - fs = File.Open(fileFinalPath, FileMode.Create); - fs.SetLength((long)file.TotalSize); - - using (var fsOld = File.Open(fileStagingPath, FileMode.Open)) - { - foreach (var match in matchingChunks) + foreach (var chunk in file.Chunks) { - fsOld.Seek((long)match.OldChunk.Offset, SeekOrigin.Begin); - - byte[] tmp = new byte[match.OldChunk.UncompressedLength]; - fsOld.Read(tmp, 0, tmp.Length); - - byte[] adler = Util.AdlerHash(tmp); - if (!adler.SequenceEqual(match.OldChunk.Checksum)) + var oldChunk = oldManifestFile.Chunks.FirstOrDefault(c => c.ChunkID.SequenceEqual(chunk.ChunkID)); + if (oldChunk != null) { - neededChunks.Add(match.NewChunk); + matchingChunks.Add(new ChunkMatch(oldChunk, chunk)); } else { - fs.Seek((long)match.NewChunk.Offset, SeekOrigin.Begin); - fs.Write(tmp, 0, tmp.Length); + neededChunks.Add(chunk); } } - } - File.Delete(fileStagingPath); - } - } - else - { - // No old manifest or file not in old manifest. We must validate. + File.Move(fileFinalPath, fileStagingPath); - fs = File.Open(fileFinalPath, FileMode.Open); - if ((ulong)fi.Length != file.TotalSize) - { - fs.SetLength((long)file.TotalSize); - } + fs = File.Open(fileFinalPath, FileMode.Create); + fs.SetLength((long)file.TotalSize); - neededChunks = Util.ValidateSteam3FileChecksums(fs, file.Chunks.OrderBy(x => x.Offset).ToArray()); - } - - if (neededChunks.Count() == 0) - { - size_downloaded += file.TotalSize; - Console.WriteLine("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, fileFinalPath); - if (fs != null) - fs.Close(); - return; - } - else - { - size_downloaded += (file.TotalSize - (ulong)neededChunks.Select(x => (long)x.UncompressedLength).Sum()); - } - } + using (var fsOld = File.Open(fileStagingPath, FileMode.Open)) + { + foreach (var match in matchingChunks) + { + fsOld.Seek((long)match.OldChunk.Offset, SeekOrigin.Begin); + + byte[] tmp = new byte[match.OldChunk.UncompressedLength]; + fsOld.Read(tmp, 0, tmp.Length); + + byte[] adler = Util.AdlerHash(tmp); + if (!adler.SequenceEqual(match.OldChunk.Checksum)) + { + neededChunks.Add(match.NewChunk); + } + else + { + fs.Seek((long)match.NewChunk.Offset, SeekOrigin.Begin); + fs.Write(tmp, 0, tmp.Length); + } + } + } - foreach (var chunk in neededChunks) - { - if (cts.IsCancellationRequested) break; + File.Delete(fileStagingPath); + } + } + else + { + // No old manifest or file not in old manifest. We must validate. - string chunkID = Util.EncodeHexString(chunk.ChunkID); - CDNClient.DepotChunk chunkData = null; + fs = File.Open(fileFinalPath, FileMode.Open); + if ((ulong)fi.Length != file.TotalSize) + { + fs.SetLength((long)file.TotalSize); + } - while (!cts.IsCancellationRequested) - { - CDNClient client; - try + neededChunks = Util.ValidateSteam3FileChecksums(fs, file.Chunks.OrderBy(x => x.Offset).ToArray()); + } + + if (neededChunks.Count() == 0) { - client = cdnPool.GetConnectionForDepot(appId, depot.id, depot.depotKey, cts.Token); + size_downloaded += file.TotalSize; + Console.WriteLine("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, fileFinalPath); + if (fs != null) + fs.Dispose(); + return; } - catch (OperationCanceledException) + else { - break; + size_downloaded += (file.TotalSize - (ulong)neededChunks.Select(x => (long)x.UncompressedLength).Sum()); } + } - DepotManifest.ChunkData data = new DepotManifest.ChunkData(); - data.ChunkID = chunk.ChunkID; - data.Checksum = chunk.Checksum; - data.Offset = chunk.Offset; - data.CompressedLength = chunk.CompressedLength; - data.UncompressedLength = chunk.UncompressedLength; + foreach (var chunk in neededChunks) + { + if (cts.IsCancellationRequested) break; - try - { - chunkData = client.DownloadDepotChunk(depot.id, data); - cdnPool.ReturnConnection(client); - break; - } - catch (WebException e) + string chunkID = Util.EncodeHexString(chunk.ChunkID); + CDNClient.DepotChunk chunkData = null; + + while (!cts.IsCancellationRequested) { - cdnPool.ReturnBrokenConnection(client); + CDNClient client; + try + { + client = await cdnPool.GetConnectionForDepotAsync(appId, depot.id, depot.depotKey, cts.Token).ConfigureAwait(false); + } + catch (OperationCanceledException) + { + break; + } - if (e.Status == WebExceptionStatus.ProtocolError) + DepotManifest.ChunkData data = new DepotManifest.ChunkData(); + data.ChunkID = chunk.ChunkID; + data.Checksum = chunk.Checksum; + data.Offset = chunk.Offset; + data.CompressedLength = chunk.CompressedLength; + data.UncompressedLength = chunk.UncompressedLength; + + try { - var response = e.Response as HttpWebResponse; - if (response.StatusCode == HttpStatusCode.Unauthorized || response.StatusCode == HttpStatusCode.Forbidden) + chunkData = await client.DownloadDepotChunkAsync(depot.id, data).ConfigureAwait(false); + cdnPool.ReturnConnection(client); + break; + } + catch (WebException e) + { + cdnPool.ReturnBrokenConnection(client); + + if (e.Status == WebExceptionStatus.ProtocolError) { - Console.WriteLine("Encountered 401 for chunk {0}. Aborting.", chunkID); - cts.Cancel(); - break; + var response = e.Response as HttpWebResponse; + if (response.StatusCode == HttpStatusCode.Unauthorized || response.StatusCode == HttpStatusCode.Forbidden) + { + Console.WriteLine("Encountered 401 for chunk {0}. Aborting.", chunkID); + cts.Cancel(); + break; + } + else + { + Console.WriteLine("Encountered error downloading chunk {0}: {1}", chunkID, response.StatusCode); + } } else { - Console.WriteLine("Encountered error downloading chunk {0}: {1}", chunkID, response.StatusCode); + Console.WriteLine("Encountered error downloading chunk {0}: {1}", chunkID, e.Status); } } - else + catch (Exception e) { - Console.WriteLine("Encountered error downloading chunk {0}: {1}", chunkID, e.Status); + cdnPool.ReturnBrokenConnection(client); + Console.WriteLine("Encountered unexpected error downloading chunk {0}: {1}", chunkID, e.Message); } } - catch (Exception e) + + if (chunkData == null) { - cdnPool.ReturnBrokenConnection(client); - Console.WriteLine("Encountered unexpected error downloading chunk {0}: {1}", chunkID, e.Message); + Console.WriteLine("Failed to find any server with chunk {0} for depot {1}. Aborting.", chunkID, depot.id); + return; } - } - - if (chunkData == null) - { - Console.WriteLine("Failed to find any server with chunk {0} for depot {1}. Aborting.", chunkID, depot.id); - return; - } - TotalBytesCompressed += chunk.CompressedLength; - DepotBytesCompressed += chunk.CompressedLength; - TotalBytesUncompressed += chunk.UncompressedLength; - DepotBytesUncompressed += chunk.UncompressedLength; + TotalBytesCompressed += chunk.CompressedLength; + DepotBytesCompressed += chunk.CompressedLength; + TotalBytesUncompressed += chunk.UncompressedLength; + DepotBytesUncompressed += chunk.UncompressedLength; - fs.Seek((long)chunk.Offset, SeekOrigin.Begin); - fs.Write(chunkData.Data, 0, chunkData.Data.Length); + fs.Seek((long)chunk.Offset, SeekOrigin.Begin); + fs.Write(chunkData.Data, 0, chunkData.Data.Length); - size_downloaded += chunk.UncompressedLength; - } + size_downloaded += chunk.UncompressedLength; + } - fs.Close(); + fs.Dispose(); - Console.WriteLine("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, fileFinalPath); + Console.WriteLine("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, fileFinalPath); + } + finally + { + semaphore.Release(); + } }); ConfigStore.TheConfig.LastManifests[depot.id] = depot.manifestId; diff --git a/DepotDownloader/DepotDownloader.csproj b/DepotDownloader/DepotDownloader.csproj index fdac4a25..b8b56e07 100644 --- a/DepotDownloader/DepotDownloader.csproj +++ b/DepotDownloader/DepotDownloader.csproj @@ -1,124 +1,14 @@ - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {39159C47-ACD3-449F-96CA-4F30C8ED147A} - Exe - Properties - DepotDownloader - DepotDownloader - v4.5 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - ..\ - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - x86 - false - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - AllRules.ruleset - AnyCPU - false - - - - True - ..\packages\protobuf-net.2.0.0.668\lib\net40\protobuf-net.dll - - - ..\packages\SteamKit2.1.8.1\lib\net45\SteamKit2.dll - True - - - - 3.5 - - - 3.5 - - - 3.5 - - - - - - - - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - - - + + + Exe + netcoreapp1.1;net46 + false + + + + + + + + \ No newline at end of file diff --git a/DepotDownloader/Program.cs b/DepotDownloader/Program.cs index 88020251..20eedb8a 100644 --- a/DepotDownloader/Program.cs +++ b/DepotDownloader/Program.cs @@ -4,12 +4,16 @@ using System.IO; using System.Text.RegularExpressions; using SteamKit2; using System.ComponentModel; +using System.Threading.Tasks; namespace DepotDownloader { class Program { static void Main( string[] args ) + => MainAsync(args).GetAwaiter().GetResult(); + + static async Task MainAsync( string[] args ) { if ( args.Length == 0 ) { @@ -19,7 +23,7 @@ namespace DepotDownloader DebugLog.Enabled = false; - ConfigStore.LoadFromFile(Path.Combine(Environment.CurrentDirectory, "DepotDownloader.config")); + ConfigStore.LoadFromFile(Path.Combine(Directory.GetCurrentDirectory(), "DepotDownloader.config")); bool bDumpManifest = HasParameter( args, "-manifest-only" ); uint appId = GetParameter( args, "-app", ContentDownloader.INVALID_APP_ID ); @@ -110,7 +114,7 @@ namespace DepotDownloader if (ContentDownloader.InitializeSteam3(username, password)) { - ContentDownloader.DownloadApp(appId, depotId, branch, forceDepot); + await ContentDownloader.DownloadAppAsync(appId, depotId, branch, forceDepot).ConfigureAwait(false); ContentDownloader.ShutdownSteam3(); } } diff --git a/DepotDownloader/Properties/AssemblyInfo.cs b/DepotDownloader/Properties/AssemblyInfo.cs index b23587fd..7a49f3ef 100644 --- a/DepotDownloader/Properties/AssemblyInfo.cs +++ b/DepotDownloader/Properties/AssemblyInfo.cs @@ -31,4 +31,4 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.2.1.*")] +[assembly: AssemblyVersion("2.2.2.0")] diff --git a/DepotDownloader/Util.cs b/DepotDownloader/Util.cs index 60369688..02b8bc8c 100644 --- a/DepotDownloader/Util.cs +++ b/DepotDownloader/Util.cs @@ -11,60 +11,19 @@ namespace DepotDownloader { static class Util { - [DllImport( "libc" )] - static extern int uname( IntPtr buf ); - - static int _isMacOSX = -1; - - // Environment.OSVersion.Platform returns PlatformID.Unix under Mono on OS X - // Code adapted from Mono: mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUI.cs - private static bool IsMacOSX() + public static string GetSteamOS() { - if ( _isMacOSX != -1 ) - return _isMacOSX == 1; - - IntPtr buf = IntPtr.Zero; - - try + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - // The size of the utsname struct varies from system to system, but this _seems_ more than enough - buf = Marshal.AllocHGlobal( 4096 ); - - if ( uname( buf ) == 0 ) - { - string sys = Marshal.PtrToStringAnsi( buf ); - if ( sys == "Darwin" ) - { - _isMacOSX = 1; - return true; - } - } + return "windows"; } - catch + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { - // Do nothing? + return "macos"; } - finally + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { - if ( buf != IntPtr.Zero ) - Marshal.FreeHGlobal( buf ); - } - - _isMacOSX = 0; - return false; - } - - public static string GetSteamOS() - { - switch (Environment.OSVersion.Platform) - { - case PlatformID.Win32NT: - case PlatformID.Win32Windows: - return "windows"; - case PlatformID.MacOSX: - return "macos"; - case PlatformID.Unix: - return IsMacOSX() ? "macos" : "linux"; + return "linux"; } return "unknown"; @@ -141,13 +100,12 @@ namespace DepotDownloader public static byte[] SHAHash( byte[] input ) { - SHA1Managed sha = new SHA1Managed(); - - byte[] output = sha.ComputeHash( input ); - - sha.Clear(); + using (var sha = SHA1.Create()) + { + var output = sha.ComputeHash( input ); - return output; + return output; + } } public static byte[] DecodeHexString( string hex )