diff --git a/DepotDownloader/CDNClientPool.cs b/DepotDownloader/CDNClientPool.cs
index 2f85d69c..adccd7e7 100644
--- a/DepotDownloader/CDNClientPool.cs
+++ b/DepotDownloader/CDNClientPool.cs
@@ -5,91 +5,46 @@ using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
-using SteamKit2;
-using SteamKit2.CDN;
+using SteamPrefill.Handlers;
-namespace DepotDownloader
+namespace LancachePrefill.Common
{
- ///
- /// CDNClientPool provides a pool of connections to CDN endpoints, requesting CDN tokens as needed
- ///
- class CDNClientPool
+ public class CDNClientPool
{
private const int ServerEndpointMinimumSize = 8;
- private readonly Steam3Session steamSession;
- private readonly uint appId;
- public Client CDNClient { get; }
- public Server ProxyServer { get; private set; }
-
- private readonly ConcurrentStack activeConnectionPool = new ConcurrentStack();
- private readonly BlockingCollection availableServerEndpoints = new BlockingCollection();
-
- private readonly AutoResetEvent populatePoolEvent = new AutoResetEvent(true);
- private readonly Task monitorTask;
- private readonly CancellationTokenSource shutdownToken = new CancellationTokenSource();
+ private readonly IAnsiConsole _ansiConsole;
+ private readonly string _cdnUrl;
+ private readonly ConcurrentStack _activeConnectionPool = new ConcurrentStack();
+ private readonly BlockingCollection _availableServerEndpoints = new BlockingCollection();
+ private readonly AutoResetEvent _populatePoolEvent = new AutoResetEvent(true);
+ private readonly Task _monitorTask;
+ private readonly CancellationTokenSource _shutdownToken = new CancellationTokenSource();
public CancellationTokenSource ExhaustedToken { get; set; }
- public CDNClientPool(Steam3Session steamSession, uint appId)
+ public CDNClientPool(IAnsiConsole ansiConsole, string cdnUrl)
{
- this.steamSession = steamSession;
- this.appId = appId;
- CDNClient = new Client(steamSession.steamClient);
+ _ansiConsole = ansiConsole;
+ _cdnUrl = cdnUrl;
- monitorTask = Task.Factory.StartNew(ConnectionPoolMonitorAsync, TaskCreationOptions.LongRunning);
+ _monitorTask = Task.Factory.StartNew(ConnectionPoolMonitorAsync, TaskCreationOptions.LongRunning);
}
public void Shutdown()
{
- shutdownToken.Cancel();
- monitorTask.Wait();
- }
-
- private async Task> FetchBootstrapServerListAsync()
- {
- try
- {
- var cdnServers = await steamSession.steamContent.GetServersForSteamPipe().ConfigureAwait(false);
- return cdnServers;
- }
- catch (Exception ex)
- {
- Console.WriteLine("Failed to retrieve content server list: {0}", ex.Message);
- return null;
- }
- }
-
- private async Task ResolveLancacheIpAsync(string hostname)
- {
- try
- {
- var hostEntry = await Dns.GetHostEntryAsync(hostname).ConfigureAwait(false);
- return hostEntry.AddressList.FirstOrDefault(ip => IsPrivateIp(ip));
- }
- catch (Exception ex)
- {
- Console.WriteLine("Failed to resolve Lancache IP: {0}", ex.Message);
- return null;
- }
- }
-
- private bool IsPrivateIp(IPAddress ip)
- {
- byte[] bytes = ip.GetAddressBytes();
- return bytes[0] == 10 ||
- (bytes[0] == 172 && bytes[1] >= 16 && bytes[1] <= 31) ||
- (bytes[0] == 192 && bytes[1] == 168);
+ _shutdownToken.Cancel();
+ _monitorTask.Wait();
}
private async Task ConnectionPoolMonitorAsync()
{
var didPopulate = false;
- while (!shutdownToken.IsCancellationRequested)
+ while (!_shutdownToken.IsCancellationRequested)
{
- populatePoolEvent.WaitOne(TimeSpan.FromSeconds(1));
+ _populatePoolEvent.WaitOne(TimeSpan.FromSeconds(1));
- if (availableServerEndpoints.Count < ServerEndpointMinimumSize && steamSession.steamClient.IsConnected)
+ if (_availableServerEndpoints.Count < ServerEndpointMinimumSize)
{
var servers = await FetchBootstrapServerListAsync().ConfigureAwait(false);
@@ -99,45 +54,29 @@ namespace DepotDownloader
return;
}
- ProxyServer = servers.FirstOrDefault(x => x.UseAsProxy);
-
foreach (var server in servers)
{
- if (server.Type == "SteamCache")
+ var resolvedIp = await ResolveLancacheIpAsync(server.Host).ConfigureAwait(false);
+ if (resolvedIp != null && IsPrivateIp(resolvedIp))
{
- var lancacheIp = await ResolveLancacheIpAsync(server.Host).ConfigureAwait(false);
- if (lancacheIp != null && IsPrivateIp(lancacheIp))
+ var lancacheServer = new Server
{
- var lancacheServer = new Server
- {
- Host = lancacheIp.ToString(),
- Type = server.Type,
- NumEntries = server.NumEntries,
- WeightedLoad = server.WeightedLoad,
- AllowedAppIds = server.AllowedAppIds.ToArray(),
- Protocol = Server.ConnectionProtocol.HTTP // Downgrade to HTTP
- };
-
- Console.WriteLine($"Found Lancache Server: {lancacheServer.Host}. Downgrading connection to HTTP.");
- availableServerEndpoints.Add(lancacheServer);
- }
- }
- else
- {
- var isEligibleForApp = server.AllowedAppIds.Length == 0 || server.AllowedAppIds.Contains(appId);
- if (isEligibleForApp && (server.Type == "SteamCache" || server.Type == "CDN"))
- {
- for (var i = 0; i < server.NumEntries; i++)
- {
- availableServerEndpoints.Add(server);
- }
- }
+ Host = resolvedIp.ToString(),
+ Type = server.Type,
+ NumEntries = server.NumEntries,
+ WeightedLoad = server.WeightedLoad,
+ AllowedAppIds = server.AllowedAppIds.ToArray(),
+ Protocol = Server.ConnectionProtocol.HTTP // Downgrade to HTTP
+ };
+
+ _ansiConsole.MarkupLine($"Found Lancache Server: {_cdnUrl}. Downgrading connection to HTTP.");
+ _availableServerEndpoints.Add(lancacheServer);
}
}
didPopulate = true;
}
- else if (availableServerEndpoints.Count == 0 && !steamSession.steamClient.IsConnected && didPopulate)
+ else if (_availableServerEndpoints.Count == 0 && didPopulate)
{
ExhaustedToken?.Cancel();
return;
@@ -145,39 +84,39 @@ namespace DepotDownloader
}
}
- private Server BuildConnection(CancellationToken token)
+ private async Task> FetchBootstrapServerListAsync()
{
- if (availableServerEndpoints.Count < ServerEndpointMinimumSize)
- {
- populatePoolEvent.Set();
- }
-
- return availableServerEndpoints.Take(token);
+ // Implement logic to fetch the CDN server list
+ return null;
}
- public async Task DownloadDepotChunkAsync(uint depotId, DepotManifest.ChunkData chunkData, Server connection, byte[] depotKey)
+ private async Task ResolveLancacheIpAsync(string hostname)
{
try
{
- // Call the DownloadDepotChunkAsync method of CDNClient
- var chunk = await CDNClient.DownloadDepotChunkAsync(depotId, chunkData, connection, depotKey);
-
- // Return the downloaded chunk
- return chunk;
+ var hostEntry = await Dns.GetHostEntryAsync(hostname).ConfigureAwait(false);
+ return hostEntry.AddressList.FirstOrDefault(ip => IsPrivateIp(ip));
}
catch (Exception ex)
{
- // Handle any exceptions that occur during chunk download
- Console.WriteLine($"Error downloading chunk: {ex.Message}");
+ _ansiConsole.MarkupLine($"Failed to resolve Lancache IP: {ex.Message}");
return null;
}
}
+ private bool IsPrivateIp(IPAddress ip)
+ {
+ byte[] bytes = ip.GetAddressBytes();
+ return bytes[0] == 10 ||
+ (bytes[0] == 172 && bytes[1] >= 16 && bytes[1] <= 31) ||
+ (bytes[0] == 192 && bytes[1] == 168);
+ }
+
public Server GetConnection(CancellationToken token)
{
- if (!activeConnectionPool.TryPop(out var connection))
+ if (!_activeConnectionPool.TryPop(out var connection))
{
- connection = BuildConnection(token);
+ connection = _availableServerEndpoints.Take(token);
}
return connection;
@@ -187,14 +126,12 @@ namespace DepotDownloader
{
if (server == null) return;
- activeConnectionPool.Push(server);
+ _activeConnectionPool.Push(server);
}
public void ReturnBrokenConnection(Server server)
{
- if (server == null) return;
-
- // Broken connections are not returned to the pool
+ // Implement logic to handle broken connections
}
}
}
diff --git a/DepotDownloader/DepotDownloader.csproj b/DepotDownloader/DepotDownloader.csproj
index 85fe1a3d..275a540c 100644
--- a/DepotDownloader/DepotDownloader.csproj
+++ b/DepotDownloader/DepotDownloader.csproj
@@ -16,11 +16,6 @@
-
-
-
-
- ..\..\SteamKit\SteamKit2\SteamKit2\bin\Debug\net8.0\SteamKit2.dll
-
+