private bool ReauthConnection(CDNClient client, CDNClient.Server server, uint depotId, byte[] depotKey) { DebugLog.Assert(server.Type == "CDN" || steamSession.AppTickets[depotId] == null, "CDNClientPool", "Re-authing a CDN or anonymous connection"); String cdnAuthToken = null; if (server.Type == "CDN") { steamSession.RequestCDNAuthToken(depotId, server.Host); cdnAuthToken = steamSession.CDNAuthTokens[Tuple.Create(depotId, server.Host)].Token; } try { client.AuthenticateDepot(depotId, depotKey, cdnAuthToken); activeClientAuthed[client] = Tuple.Create(depotId, server); return(true); } catch (Exception ex) { Console.WriteLine("Failed to reauth to content server {0}: {1}", server, ex.Message); } return(false); }
public void ReturnConnection(CDNClient.Server server) { if (server == null) { return; } activeConnectionPool.Push(server); }
public void ReturnServer(CDNClient.Server server, bool isFaulty) { if (isFaulty) { return; } _activeServerEndpoints.Push(server); }
public void ReturnBrokenConnection(CDNClient.Server server) { if (server == null) { return; } // Broken connections are not returned to the pool }
private CDNClient BuildConnection(uint depotId, byte[] depotKey, CDNClient.Server serverSeed, CancellationToken token) { CDNClient.Server server = null; CDNClient client = null; while (client == null) { // if we want to re-initialize a specific content server, try that one first if (serverSeed != null) { server = serverSeed; serverSeed = null; } else { if (availableServerEndpoints.Count < ServerEndpointMinimumSize) { populatePoolEvent.Set(); } server = availableServerEndpoints.Take(token); } client = new CDNClient(steamSession.steamClient, steamSession.AppTickets[depotId]); string cdnAuthToken = null; if (server.Type == "CDN") { steamSession.RequestCDNAuthToken(depotId, server.Host); cdnAuthToken = steamSession.CDNAuthTokens[Tuple.Create(depotId, server.Host)].Token; } try { client.Connect(server); client.AuthenticateDepot(depotId, depotKey, cdnAuthToken); } catch (Exception ex) { client = null; Console.WriteLine("Failed to connect to content server {0}: {1}", server, ex.Message); int penalty = 0; ConfigStore.TheConfig.ContentServerPenalty.TryGetValue(server.Host, out penalty); ConfigStore.TheConfig.ContentServerPenalty[server.Host] = penalty + 1; } } Console.WriteLine("Initialized connection to content server {0} with depot id {1}", server, depotId); activeClientAuthed[client] = Tuple.Create(depotId, server); return(client); }
private async Task <CDNClient> BuildConnection(uint appId, uint depotId, byte[] depotKey, CDNClient.Server serverSeed, CancellationToken token) { CDNClient.Server server = null; CDNClient client = null; while (client == null) { if (serverSeed != null) { server = serverSeed; serverSeed = null; } else { if (_availableServerEndpoints.Count < ServerEndpointMinimumSize) { _populateEvent.Set(); } server = _availableServerEndpoints.Take(token); } client = new CDNClient(_client); try { var cdnToken = ""; if (server.Type == "CDN" || server.Type == "SteamCache") { cdnToken = (await RequestCDNAuthToken(appId, depotId, server.Host))?.Token; } await client.ConnectAsync(server); await client.AuthenticateDepotAsync(depotId, depotKey, cdnToken); } catch (Exception ex) { client = null; Console.WriteLine("Failed to connect to content server {0}: {1}", server, ex.Message); _contentServerPenalty.TryGetValue(server.Host, out var penalty); _contentServerPenalty[server.Host] = ++penalty; } } Console.WriteLine("Initialized connection to content server {0} with depot id {1}", server, depotId); _activeClientAuthed[client] = Tuple.Create(depotId, server); return(client); }
private void RemoveErroredServer(CDNClient.Server server) { // Let the watchdog update the server list in next check LastServerRefreshTime = DateTime.MinValue; Log.WriteWarn("Depot Downloader", $"Removing {server} due to a download error"); CDNServers.Remove(server); // Always have one server in the list in case we run out if (CDNServers.Count == 0) { CDNServers.Add(new DnsEndPoint("valve500.steamcontent.com", 80)); } }
private async Task <string> AuthenticateConnection(uint appId, uint depotId, CDNClient.Server server) { var host = steamSession.ResolveCDNTopLevelHost(server.Host); var cdnKey = $"{depotId:D}:{host}"; var cdnAuthToken = await steamSession.RequestCDNAuthToken(appId, depotId, host, cdnKey); if (cdnAuthToken != null) { return(cdnAuthToken.Token); } else { throw new ContentDownloaderException($"Failed to retrieve CDN token for server {server.Host} depot {depotId}"); } }
private async Task <string> AuthenticateConnection(uint appId, uint depotId, CDNClient.Server server) { var host = steamSession.ResolveCDNTopLevelHost(server.Host); var cdnKey = $"{depotId:D}:{host}"; steamSession.RequestCDNAuthToken(appId, depotId, host, cdnKey); if (steamSession.CDNAuthTokens.TryGetValue(cdnKey, out var authTokenCallbackPromise)) { var result = await authTokenCallbackPromise.Task; return(result.Token); } else { throw new Exception($"Failed to retrieve CDN token for server {server.Host} depot {depotId}"); } }
public async Task <string> AuthenticateWithServerAsync(DepotId depotId, CDNClient.Server server) { string host = server.Host; if (host.EndsWith(".steampipe.steamcontent.com")) { host = "steampipe.steamcontent.com"; } else if (host.EndsWith(".steamcontent.com")) { host = "steamcontent.com"; } string cdnKey = $"{depotId.Id:D}:{host}"; return(await GetCdnAuthenticationTokenAsync(_appId, depotId, host, cdnKey)); }
private void RemoveErroredServer(CDNClient.Server server) { if (CDNServers.Count < 10) { // Let the watchdog update the server list in next check LastServerRefreshTime = DateTime.MinValue; } Log.WriteWarn(nameof(DepotProcessor), $"Removing {server} due to a download error"); CDNServers.Remove(server); // Always have one server in the list in case we run out if (CDNServers.Count == 0) { CDNServers.Add(new DnsEndPoint(DefaultServer, 80)); } }
private async Task <bool> ReauthConnectionAsync(CDNClient client, CDNClient.Server server, uint appId, uint depotId, byte[] depotKey) { DebugLog.Assert(server.Type == "CDN" || server.Type == "SteamCache" || steamSession.AppTickets[depotId] == null, "CDNClientPool", "Re-authing a CDN or anonymous connection"); String cdnAuthToken = null; try { if (DepotKeyStore.ContainsKey(depotId)) { ((ConcurrentDictionary <uint, byte[]>)(typeof(CDNClient).GetField("depotKeys", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(client))).GetOrAdd(depotId, depotKey); } else { if (server.Type == "CDN" || server.Type == "SteamCache") { steamSession.RequestCDNAuthToken(appId, depotId, server.Host); var cdnKey = string.Format("{0:D}:{1}", depotId, steamSession.ResolveCDNTopLevelHost(server.Host)); SteamApps.CDNAuthTokenCallback authTokenCallback; if (steamSession.CDNAuthTokens.TryGetValue(cdnKey, out authTokenCallback)) { cdnAuthToken = authTokenCallback.Token; } else { throw new Exception(String.Format("Failed to retrieve CDN token for server {0} depot {1}", server.Host, depotId)); } } await client.AuthenticateDepotAsync(depotId, depotKey, cdnAuthToken).ConfigureAwait(false); } activeClientAuthed[client] = Tuple.Create(depotId, server); return(true); } catch (Exception ex) { Console.WriteLine("Failed to reauth to content server {0}: {1}", server, ex.Message); } return(false); }
private async Task <bool> ReauthConnectionAsync(CDNClient client, CDNClient.Server server, uint appId, uint depotId, byte[] depotKey) { DebugLog.Assert(server.Type == "CDN" || server.Type == "SteamCache" || steamSession.AppTickets[depotId] == null, "CDNClientPool", "Re-authing a CDN or anonymous connection"); string cdnAuthToken = null; try { if (server.Type == "CDN" || server.Type == "SteamCache") { await steamSession.RequestCDNAuthToken(appId, depotId, server.Host); var cdnKey = string.Format("{0:D}:{1}", depotId, steamSession.ResolveCDNTopLevelHost(server.Host)); SteamApps.CDNAuthTokenCallback authTokenCallback; if (steamSession.CDNAuthTokens.TryGetValue(cdnKey, out authTokenCallback)) { cdnAuthToken = authTokenCallback.Token; } else { throw new Exception(String.Format("Failed to retrieve CDN token for server {0} depot {1}", server.Host, depotId)); } } await client.AuthenticateDepotAsync(depotId, depotKey, cdnAuthToken).ConfigureAwait(false); //await client.AuthenticateDepotAsync(depotId, depotKey, cdnAuthToken); activeClientAuthed[client] = Tuple.Create(depotId, server); return(true); } catch (Exception ex) { DebugLog.WriteLine("CDNClientPool", "Failed to reauth to content server " + server + ": " + ex.Message); } return(false); }
private async Task <bool> AuthenticateConnection(CDNClient client, CDNClient.Server server, uint appId, uint depotId, byte[] depotKey) { try { string cdnAuthToken = null; if (server.Type == "CDN" || server.Type == "SteamCache") { cdnAuthToken = (await RequestCDNAuthToken(appId, depotId, server.Host))?.Token; } await client.AuthenticateDepotAsync(depotId, depotKey, cdnAuthToken); _activeClientAuthed[client] = Tuple.Create(depotId, server); return(true); } catch (Exception ex) { Console.WriteLine("Failed to reauth to content server {0}: {1}", server, ex.Message); } return(false); }
private static async Task DownloadSteam3AsyncDepotFileChunk( CancellationTokenSource cts, uint appId, GlobalDownloadCounter downloadCounter, DepotFilesData depotFilesData, ProtoManifest.FileData file, FileStreamData fileStreamData, ProtoManifest.ChunkData chunk) { cts.Token.ThrowIfCancellationRequested(); var depot = depotFilesData.depotDownloadInfo; var depotDownloadCounter = depotFilesData.depotCounter; string chunkID = Util.EncodeHexString(chunk.ChunkID); 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; CDNClient.DepotChunk chunkData = null; do { cts.Token.ThrowIfCancellationRequested(); CDNClient.Server connection = null; try { connection = cdnPool.GetConnection(cts.Token); var cdnToken = await cdnPool.AuthenticateConnection(appId, depot.id, connection); chunkData = await cdnPool.CDNClient.DownloadDepotChunkAsync(depot.id, data, connection, cdnToken, depot.depotKey).ConfigureAwait(false); cdnPool.ReturnConnection(connection); } catch (TaskCanceledException) { Console.WriteLine("Connection timeout downloading chunk {0}", chunkID); } catch (SteamKitWebRequestException e) { cdnPool.ReturnBrokenConnection(connection); if (e.StatusCode == HttpStatusCode.Unauthorized || e.StatusCode == HttpStatusCode.Forbidden) { Console.WriteLine("Encountered 401 for chunk {0}. Aborting.", chunkID); break; } else { Console.WriteLine("Encountered error downloading chunk {0}: {1}", chunkID, e.StatusCode); } } catch (OperationCanceledException) { break; } catch (Exception e) { cdnPool.ReturnBrokenConnection(connection); Console.WriteLine("Encountered unexpected error downloading chunk {0}: {1}", chunkID, e.Message); } }while (chunkData == null); if (chunkData == null) { Console.WriteLine("Failed to find any server with chunk {0} for depot {1}. Aborting.", chunkID, depot.id); cts.Cancel(); } // Throw the cancellation exception if requested so that this task is marked failed cts.Token.ThrowIfCancellationRequested(); try { await fileStreamData.fileLock.WaitAsync().ConfigureAwait(false); fileStreamData.fileStream.Seek((long)chunkData.ChunkInfo.Offset, SeekOrigin.Begin); await fileStreamData.fileStream.WriteAsync(chunkData.Data, 0, chunkData.Data.Length); } finally { fileStreamData.fileLock.Release(); } int remainingChunks = Interlocked.Decrement(ref fileStreamData.chunksToDownload); if (remainingChunks == 0) { fileStreamData.fileStream.Dispose(); fileStreamData.fileLock.Dispose(); } ulong sizeDownloaded = 0; lock (depotDownloadCounter) { sizeDownloaded = depotDownloadCounter.SizeDownloaded + (ulong)chunkData.Data.Length; depotDownloadCounter.SizeDownloaded = sizeDownloaded; depotDownloadCounter.DepotBytesCompressed += chunk.CompressedLength; depotDownloadCounter.DepotBytesUncompressed += chunk.UncompressedLength; } lock (downloadCounter) { downloadCounter.TotalBytesCompressed += chunk.CompressedLength; downloadCounter.TotalBytesUncompressed += chunk.UncompressedLength; } if (remainingChunks == 0) { var fileFinalPath = Path.Combine(depot.installDir, file.FileName); Console.WriteLine("{0,6:#00.00}% {1}", ((float)sizeDownloaded / (float)depotDownloadCounter.CompleteDownloadSize) * 100.0f, fileFinalPath); } }
private async Task <CDNClient> BuildConnectionAsync(uint appId, uint depotId, byte[] depotKey, CDNClient.Server serverSeed, CancellationToken token) { CDNClient.Server server = null; CDNClient client = null; while (client == null) { // if we want to re-initialize a specific content server, try that one first if (serverSeed != null) { server = serverSeed; serverSeed = null; } else { if (availableServerEndpoints.Count < ServerEndpointMinimumSize) { populatePoolEvent.Set(); } server = availableServerEndpoints.Take(token); } client = new CDNClient(steamSession.steamClient, steamSession.AppTickets[depotId]); string cdnAuthToken = null; try { if (server.Type == "CDN" || server.Type == "SteamCache") { await steamSession.RequestCDNAuthToken(appId, depotId, server.Host); var cdnKey = string.Format("{0:D}:{1}", depotId, steamSession.ResolveCDNTopLevelHost(server.Host)); SteamApps.CDNAuthTokenCallback authTokenCallback; if (steamSession.CDNAuthTokens.TryGetValue(cdnKey, out authTokenCallback)) { cdnAuthToken = authTokenCallback.Token; } else { throw new Exception(String.Format("Failed to retrieve CDN token for server {0} depot {1}", server.Host, depotId)); } } await client.ConnectAsync(server).ConfigureAwait(false); //await client.ConnectAsync(server); await client.AuthenticateDepotAsync(depotId, depotKey, cdnAuthToken).ConfigureAwait(false); //await client.AuthenticateDepotAsync(depotId, depotKey, cdnAuthToken); } catch (Exception ex) { client = null; DebugLog.WriteLine("CDNClientPool", "Failed to connect to content server " + server + ": " + ex.Message); int penalty = 0; ConfigStore.TheConfig.ContentServerPenalty.TryGetValue(server.Host, out penalty); ConfigStore.TheConfig.ContentServerPenalty[server.Host] = penalty + 1; } } DebugLog.WriteLine("CDNClientPool", "Initialized connection to content server " + server + " with depot id " + depotId); activeClientAuthed[client] = Tuple.Create(depotId, server); return(client); }
private static async Task <DepotFilesData> ProcessDepotManifestAndFiles(CancellationTokenSource cts, UInt32 appId, DepotDownloadInfo depot, CDNClientPool cdnPool) { DepotDownloadCounter depotCounter = new DepotDownloadCounter(); FileLog.LogMessage("Processing depot {0} - {1}", depot.id, depot.contentName); ProtoManifest oldProtoManifest = null; ProtoManifest newProtoManifest = null; string configDir = Path.Combine(depot.installDir, CONFIG_DIR); ulong lastManifestId = INVALID_MANIFEST_ID; //DepotConfigStore.Instance.InstalledManifestIDs.TryGetValue(depot.id, out lastManifestId); //// In case we have an early exit, this will force equiv of verifyall next run. //DepotConfigStore.Instance.InstalledManifestIDs[depot.id] = INVALID_MANIFEST_ID; //DepotConfigStore.Save(); //if (lastManifestId != INVALID_MANIFEST_ID) //{ // var oldManifestFileName = Path.Combine(configDir, string.Format("{0}_{1}.bin", depot.id, lastManifestId)); // if (File.Exists(oldManifestFileName)) // { // byte[] expectedChecksum, currentChecksum; // try // { // expectedChecksum = File.ReadAllBytes(oldManifestFileName + ".sha"); // } // catch (IOException) // { // expectedChecksum = null; // } // oldProtoManifest = ProtoManifest.LoadFromFile(oldManifestFileName, out currentChecksum); // if (expectedChecksum == null || !expectedChecksum.SequenceEqual(currentChecksum)) // { // // We only have to show this warning if the old manifest ID was different // if (lastManifestId != depot.manifestId) // FileLog.LogMessage("Manifest {0} on disk did not match the expected checksum.", lastManifestId); // oldProtoManifest = null; // } // } //} if (lastManifestId == depot.manifestId && oldProtoManifest != null) { newProtoManifest = oldProtoManifest; FileLog.LogMessage("Already have manifest {0} for depot {1}.", depot.manifestId, depot.id); } else { var newManifestFileName = Path.Combine(configDir, string.Format("{0}_{1}.bin", depot.id, depot.manifestId)); if (newManifestFileName != null) { byte[] expectedChecksum, currentChecksum; try { expectedChecksum = File.ReadAllBytes(newManifestFileName + ".sha"); } catch (IOException) { expectedChecksum = null; } newProtoManifest = ProtoManifest.LoadFromFile(newManifestFileName, out currentChecksum); if (newProtoManifest != null && (expectedChecksum == null || !expectedChecksum.SequenceEqual(currentChecksum))) { FileLog.LogMessage("Manifest {0} on disk did not match the expected checksum.", depot.manifestId); newProtoManifest = null; } } if (newProtoManifest != null) { FileLog.LogMessage("Already have manifest {0} for depot {1}.", depot.manifestId, depot.id); } else { Console.Write("Downloading depot manifest..."); DepotManifest depotManifest = null; do { cts.Token.ThrowIfCancellationRequested(); CDNClient.Server connection = null; try { connection = cdnPool.GetConnection(cts.Token); var cdnToken = await cdnPool.AuthenticateConnection(appId, depot.id, connection); #if STEAMKIT_UNRELEASED depotManifest = await cdnPool.CDNClient.DownloadManifestAsync(depot.id, depot.manifestId, connection, cdnToken, depot.depotKey, proxyServer : cdnPool.ProxyServer).ConfigureAwait(false); #else depotManifest = await cdnPool.CDNClient.DownloadManifestAsync(depot.id, depot.manifestId, connection, cdnToken, depot.depotKey).ConfigureAwait(false); #endif cdnPool.ReturnConnection(connection); } catch (TaskCanceledException) { FileLog.LogMessage("Connection timeout downloading depot manifest {0} {1}", depot.id, depot.manifestId); } catch (SteamKitWebRequestException e) { cdnPool.ReturnBrokenConnection(connection); if (e.StatusCode == HttpStatusCode.Unauthorized || e.StatusCode == HttpStatusCode.Forbidden) { FileLog.LogMessage("Encountered 401 for depot manifest {0} {1}. Aborting.", depot.id, depot.manifestId); break; } else if (e.StatusCode == HttpStatusCode.NotFound) { FileLog.LogMessage("Encountered 404 for depot manifest {0} {1}. Aborting.", depot.id, depot.manifestId); break; } else { FileLog.LogMessage("Encountered error downloading depot manifest {0} {1}: {2}", depot.id, depot.manifestId, e.StatusCode); } } catch (OperationCanceledException) { break; } catch (Exception e) { cdnPool.ReturnBrokenConnection(connection); FileLog.LogMessage("Encountered error downloading manifest for depot {0} {1}: {2}", depot.id, depot.manifestId, e.Message); } }while (depotManifest == null); if (depotManifest == null) { FileLog.LogMessage("\nUnable to download manifest {0} for depot {1}", depot.manifestId, depot.id); cts.Cancel(); } // Throw the cancellation exception if requested so that this task is marked failed cts.Token.ThrowIfCancellationRequested(); byte[] checksum; newProtoManifest = new ProtoManifest(depotManifest, depot.manifestId); newProtoManifest.SaveToFile(newManifestFileName, out checksum); File.WriteAllBytes(newManifestFileName + ".sha", checksum); FileLog.LogMessage(" Done!"); } } newProtoManifest.Files.Sort((x, y) => string.Compare(x.FileName, y.FileName, StringComparison.Ordinal)); FileLog.LogMessage("Manifest {0} ({1})", depot.manifestId, newProtoManifest.CreationTime); //if (Config.DownloadManifestOnly) //{ // StringBuilder manifestBuilder = new StringBuilder(); // string txtManifest = Path.Combine(depot.installDir, string.Format("manifest_{0}_{1}.txt", depot.id, depot.manifestId)); // manifestBuilder.Append(string.Format("{0}\n\n", newProtoManifest.CreationTime)); // foreach (var file in newProtoManifest.Files) // { // if (file.Flags.HasFlag(EDepotFileFlag.Directory)) // continue; // manifestBuilder.Append(string.Format("{0}\n", file.FileName)); // manifestBuilder.Append(string.Format("\t{0}\n", file.TotalSize)); // manifestBuilder.Append(string.Format("\t{0}\n", BitConverter.ToString(file.FileHash).Replace("-", ""))); // } // File.WriteAllText(txtManifest, manifestBuilder.ToString()); // return null; //} string stagingDir = Path.Combine(depot.installDir, STAGING_DIR); var filesAfterExclusions = newProtoManifest.Files.AsParallel().Where(f => TestIsFileIncluded(f.FileName)).ToList(); var allFileNames = new HashSet <string>(filesAfterExclusions.Count); // Pre-process filesAfterExclusions.ForEach(file => { allFileNames.Add(file.FileName); var fileFinalPath = Path.Combine(depot.installDir, file.FileName); var fileStagingPath = Path.Combine(stagingDir, file.FileName); if (file.Flags.HasFlag(EDepotFileFlag.Directory)) { Directory.CreateDirectory(fileFinalPath); Directory.CreateDirectory(fileStagingPath); } else { // Some manifests don't explicitly include all necessary directories Directory.CreateDirectory(Path.GetDirectoryName(fileFinalPath)); Directory.CreateDirectory(Path.GetDirectoryName(fileStagingPath)); depotCounter.CompleteDownloadSize += file.TotalSize; } }); return(new DepotFilesData { depotDownloadInfo = depot, depotCounter = depotCounter, stagingDir = stagingDir, manifest = newProtoManifest, previousManifest = oldProtoManifest, filteredFiles = filesAfterExclusions, allFileNames = allFileNames }); }
public SteamCdnServer(CDNClient.Server internalServer) { InternalServer = internalServer; }
public CdnServerWrapper(CDNClient.Server server) { Server = server; }
private async Task <CDNClient> BuildConnectionAsync(uint appId, uint depotId, byte[] depotKey, CDNClient.Server serverSeed, CancellationToken token) { CDNClient.Server server = null; CDNClient client = null; while (client == null) { // if we want to re-initialize a specific content server, try that one first if (serverSeed != null) { server = serverSeed; serverSeed = null; } else { if (availableServerEndpoints.Count < ServerEndpointMinimumSize) { populatePoolEvent.Set(); } server = availableServerEndpoints.Take(token); } client = new CDNClient(steamSession.steamClient, steamSession.AppTickets[depotId]); string cdnAuthToken = null; try { if (DepotKeyStore.ContainsKey(depotId)) { ((ConcurrentDictionary <uint, byte[]>)(typeof(CDNClient).GetField("depotKeys", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(client))).GetOrAdd(depotId, depotKey); await client.ConnectAsync(server).ConfigureAwait(false); } else { if (server.Type == "CDN" || server.Type == "SteamCache") { steamSession.RequestCDNAuthToken(appId, depotId, server.Host); var cdnKey = string.Format("{0:D}:{1}", depotId, steamSession.ResolveCDNTopLevelHost(server.Host)); SteamApps.CDNAuthTokenCallback authTokenCallback; if (steamSession.CDNAuthTokens.TryGetValue(cdnKey, out authTokenCallback)) { cdnAuthToken = authTokenCallback.Token; } else { throw new Exception(String.Format("Failed to retrieve CDN token for server {0} depot {1}", server.Host, depotId)); } } await client.ConnectAsync(server).ConfigureAwait(false); await client.AuthenticateDepotAsync(depotId, depotKey, cdnAuthToken).ConfigureAwait(false); } } catch (Exception ex) { client = null; Console.WriteLine("Failed to connect to content server {0}: {1}", server, ex.Message); int penalty = 0; AccountSettingsStore.Instance.ContentServerPenalty.TryGetValue(server.Host, out penalty); AccountSettingsStore.Instance.ContentServerPenalty[server.Host] = penalty + 1; } } Console.WriteLine("Initialized connection to content server {0} with depot id {1}", server, depotId); activeClientAuthed[client] = Tuple.Create(depotId, server); return(client); }