You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DepotDownloader/DepotDownloader/CDNClientPool.cs

94 lines
2.8 KiB
C#

// This file is subject to the terms and conditions defined
// in file 'LICENSE', which is part of this source code package.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using SteamKit2.CDN;
namespace DepotDownloader
{
/// <summary>
/// CDNClientPool provides a pool of connections to CDN endpoints, requesting CDN tokens as needed
/// </summary>
class CDNClientPool
{
private readonly Steam3Session steamSession;
private readonly uint appId;
public Client CDNClient { get; }
public Server ProxyServer { get; private set; }
private readonly List<Server> servers = [];
private int nextServer;
public CDNClientPool(Steam3Session steamSession, uint appId)
{
this.steamSession = steamSession;
this.appId = appId;
CDNClient = new Client(steamSession.steamClient);
}
public async Task UpdateServerList()
{
var servers = await this.steamSession.steamContent.GetServersForSteamPipe();
ProxyServer = servers.Where(x => x.UseAsProxy).FirstOrDefault();
var weightedCdnServers = servers
.Where(server =>
{
var isEligibleForApp = server.AllowedAppIds.Length == 0 || server.AllowedAppIds.Contains(appId);
return isEligibleForApp && (server.Type == "SteamCache" || server.Type == "CDN");
})
.Select(server =>
{
AccountSettingsStore.Instance.ContentServerPenalty.TryGetValue(server.Host, out var penalty);
return (server, penalty);
})
.OrderBy(pair => pair.penalty).ThenBy(pair => pair.server.WeightedLoad);
foreach (var (server, weight) in weightedCdnServers)
{
for (var i = 0; i < server.NumEntries; i++)
{
this.servers.Add(server);
}
}
if (this.servers.Count == 0)
{
throw new Exception("Failed to retrieve any download servers.");
}
}
public Server GetConnection()
{
return servers[nextServer % servers.Count];
}
public void ReturnConnection(Server server)
{
if (server == null) return;
// nothing to do, maybe remove from ContentServerPenalty?
}
public void ReturnBrokenConnection(Server server)
{
if (server == null) return;
lock (servers)
{
if (servers[nextServer % servers.Count] == server)
{
nextServer++;
// TODO: Add server to ContentServerPenalty
}
}
}
}
}