DepotDownloader: Changes to support connection reuse when downloading Steam2 content.

pull/8/head
Nicholas Hastings 13 years ago
parent f1e2385e38
commit 37b31d032d

@ -24,6 +24,53 @@ namespace DepotDownloader
private static Steam3Session steam3; private static Steam3Session steam3;
private static Steam3Session.Credentials steam3Credentials; private static Steam3Session.Credentials steam3Credentials;
private static IPEndPoint lastSteam2ContentServer;
private abstract class IDepotDownloadInfo
{
public int id { get; protected set; }
public string installDir { get; protected set; }
public string contentName { get; protected set; }
public abstract DownloadSource GetDownloadType();
}
private sealed class DepotDownloadInfo2 : IDepotDownloadInfo
{
public int version { get; private set; }
public IPEndPoint[] contentServers = null;
public Steam2Manifest manifest = null;
public List<int> NodesToDownload = new List<int>();
public byte[] cryptKey = null;
public override DownloadSource GetDownloadType() { return DownloadSource.Steam2; }
public DepotDownloadInfo2(int id, int version, string installDir, string contentName)
{
this.id = id;
this.version = version;
this.installDir = installDir;
this.contentName = contentName;
}
}
private sealed class DepotDownloadInfo3 : IDepotDownloadInfo
{
public ulong manifestId { get; private set; }
public byte[] depotKey;
public override DownloadSource GetDownloadType() { return DownloadSource.Steam3; }
public DepotDownloadInfo3(int depotid, ulong manifestId, string installDir, string contentName)
{
this.id = depotid;
this.manifestId = manifestId;
this.installDir = installDir;
this.contentName = contentName;
}
}
static bool CreateDirectories( int depotId, uint depotVersion, out string installDir ) static bool CreateDirectories( int depotId, uint depotVersion, out string installDir )
{ {
installDir = null; installDir = null;
@ -404,6 +451,9 @@ namespace DepotDownloader
return; return;
} }
var infos2 = new List<DepotDownloadInfo2>();
var infos3 = new List<DepotDownloadInfo3>();
foreach (var depot in depotIDs) foreach (var depot in depotIDs)
{ {
int depotVersion = 0; int depotVersion = 0;
@ -419,11 +469,74 @@ namespace DepotDownloader
} }
} }
DownloadDepot(depot, depotVersion, appId); IDepotDownloadInfo info = GetDepotInfo(depot, depotVersion, appId);
if (info != null)
{
if (info.GetDownloadType() == DownloadSource.Steam2)
infos2.Add((DepotDownloadInfo2)info);
else if (info.GetDownloadType() == DownloadSource.Steam3)
infos3.Add((DepotDownloadInfo3)info);
}
}
if( infos2.Count() > 0 )
DownloadSteam2( infos2 );
if( infos3.Count() > 0 )
DownloadSteam3( infos3 );
}
public static void DownloadDepotsForGame(string game)
{
var infos2 = new List<DepotDownloadInfo2>();
var infos3 = new List<DepotDownloadInfo3>();
List<int> depotIDs = CDRManager.GetDepotIDsForGameserver(game, ContentDownloader.Config.DownloadAllPlatforms);
foreach (var depot in depotIDs)
{
int depotVersion = CDRManager.GetLatestDepotVersion(depot, ContentDownloader.Config.PreferBetaVersions);
if (depotVersion == -1)
{
Console.WriteLine("Error: Unable to find DepotID {0} in the CDR!", depot);
ContentDownloader.ShutdownSteam3();
continue;
}
IDepotDownloadInfo info = GetDepotInfo(depot, depotVersion, 0);
if (info.GetDownloadType() == DownloadSource.Steam2)
{
infos2.Add((DepotDownloadInfo2)info);
}
else if (info.GetDownloadType() == DownloadSource.Steam3)
{
infos3.Add((DepotDownloadInfo3)info);
}
}
if (infos2.Count() > 0)
DownloadSteam2(infos2);
if (infos3.Count() > 0)
DownloadSteam3(infos3);
}
public static void DownloadDepot(int depotId, int depotVersion, int appId = 0)
{
IDepotDownloadInfo info = GetDepotInfo(depotId, depotVersion, appId);
if (info.GetDownloadType() == DownloadSource.Steam2)
{
var infos = new List<DepotDownloadInfo2>();
infos.Add((DepotDownloadInfo2)info);
DownloadSteam2(infos);
}
else if (info.GetDownloadType() == DownloadSource.Steam3)
{
var infos = new List<DepotDownloadInfo3>();
infos.Add((DepotDownloadInfo3)info);
DownloadSteam3(infos);
} }
} }
public static void DownloadDepot(int depotId, int depotVersionRequested, int appId = 0 ) static IDepotDownloadInfo GetDepotInfo(int depotId, int depotVersion, int appId)
{ {
if(steam3 != null && appId > 0) if(steam3 != null && appId > 0)
steam3.RequestAppInfo((uint)appId); steam3.RequestAppInfo((uint)appId);
@ -434,25 +547,26 @@ namespace DepotDownloader
{ {
Console.WriteLine("Depot {0} ({1}) is not available from this account.", depotId, contentName); Console.WriteLine("Depot {0} ({1}) is not available from this account.", depotId, contentName);
return; return null;
} }
DownloadSource source = GetAppDownloadSource(appId); DownloadSource source = GetAppDownloadSource(appId);
uint depotVersion = (uint)depotVersionRequested;
uint uVersion = (uint)depotVersion;
if (source == DownloadSource.Steam3) if (source == DownloadSource.Steam3)
{ {
depotVersion = GetSteam3AppChangeNumber(appId); uVersion = GetSteam3AppChangeNumber(appId);
} }
string installDir; string installDir;
if (!CreateDirectories(depotId, depotVersion, out installDir)) if (!CreateDirectories(depotId, uVersion, out installDir))
{ {
Console.WriteLine("Error: Unable to create install directories!"); Console.WriteLine("Error: Unable to create install directories!");
return; return null;
} }
Console.WriteLine("Downloading \"{0}\" version {1} ...", contentName, depotVersion); Console.WriteLine("Downloading \"{0}\" version {1} ...", contentName, uVersion);
if(steam3 != null) if(steam3 != null)
steam3.RequestAppTicket((uint)depotId); steam3.RequestAppTicket((uint)depotId);
@ -463,213 +577,224 @@ namespace DepotDownloader
if (manifestID == 0) if (manifestID == 0)
{ {
Console.WriteLine("Depot {0} ({1}) missing public subsection or manifest section.", depotId, contentName); Console.WriteLine("Depot {0} ({1}) missing public subsection or manifest section.", depotId, contentName);
return; return null;
} }
steam3.RequestDepotKey( ( uint )depotId, ( uint )appId ); steam3.RequestDepotKey( ( uint )depotId, ( uint )appId );
byte[] depotKey = steam3.DepotKeys[(uint)depotId]; byte[] depotKey = steam3.DepotKeys[(uint)depotId];
DownloadSteam3(depotId, manifestID, depotKey, installDir); var info = new DepotDownloadInfo3( depotId, manifestID, installDir, contentName );
info.depotKey = depotKey;
return info;
} }
else else
{ {
// steam2 path // steam2 path
DownloadSteam2(depotId, depotVersionRequested, installDir); var info = new DepotDownloadInfo2(depotId, depotVersion, installDir, contentName);
return info;
} }
} }
private static void DownloadSteam3( int depotId, ulong depot_manifest, byte[] depotKey, string installDir ) private static void DownloadSteam3( List<DepotDownloadInfo3> depots )
{ {
Console.Write("Finding content servers..."); foreach (var depot in depots)
{
int depotId = depot.id;
ulong depot_manifest = depot.manifestId;
byte[] depotKey = depot.depotKey;
string installDir = depot.installDir;
List<IPEndPoint> serverList = steam3.steamClient.GetServersOfType(EServerType.CS); Console.WriteLine("Downloading depot {0} - {1}", depot.id, depot.contentName);
Console.Write("Finding content servers...");
List<CDNClient.ClientEndPoint> cdnServers = null; List<IPEndPoint> serverList = steam3.steamClient.GetServersOfType(EServerType.CS);
int tries = 0, counterDeferred = 0;
for(int i = 0; ; i++ ) List<CDNClient.ClientEndPoint> cdnServers = null;
{ int counterDeferred = 0;
IPEndPoint endpoint = serverList[i % serverList.Count];
cdnServers = CDNClient.FetchServerList(new CDNClient.ClientEndPoint(endpoint.Address.ToString(), endpoint.Port), Config.CellID); for (int i = 0; ; i++)
{
IPEndPoint endpoint = serverList[i % serverList.Count];
if (cdnServers == null) counterDeferred++; cdnServers = CDNClient.FetchServerList(new CDNClient.ClientEndPoint(endpoint.Address.ToString(), endpoint.Port), Config.CellID);
if (cdnServers != null && cdnServers.Count((ep) => { return ep.Type == "CS"; }) > 0) if (cdnServers == null) counterDeferred++;
break;
if (((i+1) % serverList.Count) == 0) if (cdnServers != null && cdnServers.Count((ep) => { return ep.Type == "CS"; }) > 0)
{ break;
if (++tries > MAX_CONNECT_RETRIES)
if (((i + 1) % serverList.Count) == 0)
{ {
Console.WriteLine("\nGiving up finding Steam3 content server."); Console.WriteLine("Unable to find any Steam3 content servers");
return; return;
} }
Console.Write("\nSearching for content servers... (deferred: {0})", counterDeferred);
counterDeferred = 0;
Thread.Sleep(1000);
} }
}
if (cdnServers == null || cdnServers.Count == 0)
{
Console.WriteLine("Unable to find any Steam3 content servers");
return;
}
Console.WriteLine(" Done!"); Console.WriteLine(" Done!");
Console.Write("Downloading depot manifest..."); Console.Write("Downloading depot manifest...");
List<CDNClient.ClientEndPoint> cdnEndpoints = cdnServers.Where((ep) => { return ep.Type == "CDN"; }).ToList(); List<CDNClient.ClientEndPoint> cdnEndpoints = cdnServers.Where((ep) => { return ep.Type == "CDN"; }).ToList();
List<CDNClient.ClientEndPoint> csEndpoints = cdnServers.Where((ep) => { return ep.Type == "CS"; }).ToList(); List<CDNClient.ClientEndPoint> csEndpoints = cdnServers.Where((ep) => { return ep.Type == "CS"; }).ToList();
List<CDNClient> cdnClients = new List<CDNClient>();
List<CDNClient> cdnClients = new List<CDNClient>(); foreach (var server in csEndpoints)
{
CDNClient client = new CDNClient(server, steam3.AppTickets[(uint)depotId]);
foreach (var server in csEndpoints) if (client.Connect())
{ {
CDNClient client = new CDNClient(server, steam3.AppTickets[(uint)depotId]); cdnClients.Add(client);
if (client.Connect()) if (cdnClients.Count >= NUM_STEAM3_CONNECTIONS)
break;
}
}
if (cdnClients.Count == 0)
{ {
cdnClients.Add(client); Console.WriteLine("\nCould not initialize connection with CDN.");
return;
if (cdnClients.Count >= NUM_STEAM3_CONNECTIONS)
break;
} }
}
if (cdnClients.Count == 0)
{
Console.WriteLine("\nCould not initialize connection with CDN.");
return;
}
DepotManifest depotManifest = cdnClients[0].DownloadDepotManifest( depotId, depot_manifest ); DepotManifest depotManifest = cdnClients[0].DownloadDepotManifest( depotId, depot_manifest );
if ( depotManifest == null ) if ( depotManifest == null )
{
// TODO: check for 401s
for (int i = 1; i < cdnClients.Count && depotManifest == null; i++)
{ {
depotManifest = cdnClients[i].DownloadDepotManifest( depotId, depot_manifest ); // TODO: check for 401s
for (int i = 1; i < cdnClients.Count && depotManifest == null; i++)
{
depotManifest = cdnClients[i].DownloadDepotManifest( depotId, depot_manifest );
}
if (depotManifest == null)
{
Console.WriteLine("\nUnable to download manifest {0} for depot {1}", depot_manifest, depotId);
return;
}
} }
if (depotManifest == null) if (!depotManifest.DecryptFilenames(depotKey))
{ {
Console.WriteLine("\nUnable to download manifest {0} for depot {1}", depot_manifest, depotId); Console.WriteLine("\nUnable to decrypt manifest for depot {0}", depotId);
return; return;
} }
}
if (!depotManifest.DecryptFilenames(depotKey))
{
Console.WriteLine("\nUnable to decrypt manifest for depot {0}", depotId);
return;
}
Console.WriteLine(" Done!"); Console.WriteLine(" Done!");
ulong complete_download_size = 0; ulong complete_download_size = 0;
ulong size_downloaded = 0; ulong size_downloaded = 0;
depotManifest.Files.RemoveAll((x) => !TestIsFileIncluded(x.FileName)); depotManifest.Files.RemoveAll((x) => !TestIsFileIncluded(x.FileName));
depotManifest.Files.Sort((x, y) => { return x.FileName.CompareTo(y.FileName); }); depotManifest.Files.Sort((x, y) => { return x.FileName.CompareTo(y.FileName); });
foreach (var file in depotManifest.Files) foreach (var file in depotManifest.Files)
{
complete_download_size += file.TotalSize;
}
foreach (var file in depotManifest.Files)
{
string download_path = Path.Combine(installDir, file.FileName);
if (file.Flags.HasFlag(EDepotFileFlag.Directory))
{ {
if (!Directory.Exists(download_path)) complete_download_size += file.TotalSize;
Directory.CreateDirectory(download_path);
continue;
} }
string dir_path = Path.GetDirectoryName(download_path); foreach (var file in depotManifest.Files)
if (!Directory.Exists(dir_path))
Directory.CreateDirectory(dir_path);
FileStream fs;
DepotManifest.ChunkData[] neededChunks;
FileInfo fi = new FileInfo(download_path);
if (!fi.Exists)
{ {
// create new file. need all chunks string download_path = Path.Combine(installDir, file.FileName);
fs = File.Create(download_path);
neededChunks = file.Chunks.ToArray(); if (file.Flags.HasFlag(EDepotFileFlag.Directory))
}
else
{
// open existing
fs = File.Open(download_path, FileMode.Open);
if ((ulong)fi.Length != file.TotalSize)
{ {
fs.SetLength((long)file.TotalSize); if (!Directory.Exists(download_path))
Directory.CreateDirectory(download_path);
continue;
} }
// find which chunks we need, in order so that we aren't seeking every which way string dir_path = Path.GetDirectoryName(download_path);
neededChunks = Util.ValidateSteam3FileChecksums(fs, file.Chunks.OrderBy(x => x.Offset).ToArray());
if (!Directory.Exists(dir_path))
Directory.CreateDirectory(dir_path);
if (neededChunks.Count() == 0) FileStream fs;
DepotManifest.ChunkData[] neededChunks;
FileInfo fi = new FileInfo(download_path);
if (!fi.Exists)
{ {
size_downloaded += file.TotalSize; // create new file. need all chunks
Console.WriteLine("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, download_path); fs = File.Create(download_path);
continue; neededChunks = file.Chunks.ToArray();
} }
else else
{ {
size_downloaded += (file.TotalSize - (ulong)neededChunks.Select(x => (int)x.UncompressedLength).Sum()); // open existing
} fs = File.Open(download_path, FileMode.Open);
} if ((ulong)fi.Length != file.TotalSize)
{
fs.SetLength((long)file.TotalSize);
}
Console.Write("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, download_path); // find which chunks we need, in order so that we aren't seeking every which way
neededChunks = Util.ValidateSteam3FileChecksums(fs, file.Chunks.OrderBy(x => x.Offset).ToArray());
foreach (var chunk in neededChunks) if (neededChunks.Count() == 0)
{ {
string chunkID = EncodeHexString(chunk.ChunkID); size_downloaded += file.TotalSize;
Console.WriteLine("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, download_path);
continue;
}
else
{
size_downloaded += (file.TotalSize - (ulong)neededChunks.Select(x => (int)x.UncompressedLength).Sum());
}
}
byte[] encrypted_chunk = cdnClients[0].DownloadDepotChunk(depotId, chunkID); Console.Write("{0,6:#00.00}% {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, download_path);
if (encrypted_chunk == null) foreach (var chunk in neededChunks)
{ {
for (int i = 1; i < cdnClients.Count && encrypted_chunk == null; i++) string chunkID = EncodeHexString(chunk.ChunkID);
{
encrypted_chunk = cdnClients[i].DownloadDepotChunk(depotId, chunkID); byte[] encrypted_chunk = cdnClients[0].DownloadDepotChunk(depotId, chunkID);
}
if (encrypted_chunk == null) if (encrypted_chunk == null)
{ {
Console.WriteLine("Unable to download chunk id {0} for depot {1}", chunkID, depotId); for (int i = 1; i < cdnClients.Count && encrypted_chunk == null; i++)
return; {
encrypted_chunk = cdnClients[i].DownloadDepotChunk(depotId, chunkID);
}
if (encrypted_chunk == null)
{
Console.WriteLine("Unable to download chunk id {0} for depot {1}", chunkID, depotId);
return;
}
} }
}
byte[] chunk_data = CDNClient.ProcessChunk(encrypted_chunk, depotKey); byte[] chunk_data = CDNClient.ProcessChunk(encrypted_chunk, depotKey);
fs.Seek((long)chunk.Offset, SeekOrigin.Begin); fs.Seek((long)chunk.Offset, SeekOrigin.Begin);
fs.Write(chunk_data, 0, chunk_data.Length); fs.Write(chunk_data, 0, chunk_data.Length);
size_downloaded += chunk.UncompressedLength; size_downloaded += chunk.UncompressedLength;
Console.CursorLeft = 0; Console.CursorLeft = 0;
Console.Write("{0,6:#00.00}%", ((float)size_downloaded / (float)complete_download_size) * 100.0f); Console.Write("{0,6:#00.00}%", ((float)size_downloaded / (float)complete_download_size) * 100.0f);
} }
Console.WriteLine(); Console.WriteLine();
}
} }
} }
private static ContentServerClient.StorageSession GetSteam2StorageSession(IPEndPoint [] contentServers, ContentServerClient csClient, int depotId, int depotVersion) private static ContentServerClient.StorageSession GetSteam2StorageSession(IPEndPoint [] contentServers, ContentServerClient csClient, int depotId, int depotVersion)
{ {
ContentServerClient.StorageSession session = null; ContentServerClient.StorageSession session = null;
if (csClient.IsConnected && contentServers.Contains(lastSteam2ContentServer))
{
try
{
session = csClient.OpenStorage( (uint)depotId, (uint)depotVersion, (uint)Config.CellID, null, false );
return session;
}
catch ( Steam2Exception )
{
csClient.Disconnect();
}
}
int tries = 0; int tries = 0;
int counterSocket = 0, counterSteam2 = 0; int counterSocket = 0, counterSteam2 = 0;
for (int i = 0; ; i++) for (int i = 0; ; i++)
@ -679,7 +804,8 @@ namespace DepotDownloader
try try
{ {
csClient.Connect( endpoint ); csClient.Connect( endpoint );
session = csClient.OpenStorage( (uint)depotId, (uint)depotVersion, (uint)Config.CellID, GetSteam2Credentials( (uint)depotId ) ); session = csClient.OpenStorage( (uint)depotId, (uint)depotVersion, (uint)Config.CellID, GetSteam2Credentials( (uint)depotId ), true );
lastSteam2ContentServer = endpoint;
break; break;
} }
catch ( SocketException ) catch ( SocketException )
@ -708,135 +834,146 @@ namespace DepotDownloader
} }
return session; return session;
} }
private static void DownloadSteam2( int depotId, int depotVersion, string installDir ) private static void DownloadSteam2( List<DepotDownloadInfo2> depots )
{ {
Console.Write("Finding content servers..."); Console.WriteLine("Found depots:");
IPEndPoint[] contentServers = GetStorageServer(depotId, depotVersion, Config.CellID); foreach (var depot in depots)
{
Console.WriteLine(" - {0}\t{1}", depot.id, depot.contentName);
}
if (contentServers == null || contentServers.Length == 0) Console.Write("Finding content servers...");
foreach( var depot in depots )
{ {
Console.WriteLine("\nError: Unable to find any Steam2 content servers for depot {0}, version {1}", depotId, depotVersion); depot.contentServers = GetStorageServer(depot.id, depot.version, Config.CellID);
return; if (depot.contentServers == null || depot.contentServers.Length == 0)
{
Console.WriteLine("\nError: Unable to find any Steam2 content servers for depot {0}, version {1}", depot.id, depot.version);
return;
}
} }
Console.WriteLine(" Done!"); Console.WriteLine(" Done!");
Console.Write("Downloading depot manifest...");
string txtManifest = Path.Combine(installDir, "manifest.txt"); if (!Config.DownloadManifestOnly)
Console.WriteLine("Building list of files to download and checking existing files...");
ContentServerClient csClient = new ContentServerClient(); ContentServerClient csClient = new ContentServerClient();
csClient.ConnectionTimeout = TimeSpan.FromSeconds(STEAM2_CONNECT_TIMEOUT_SECONDS); csClient.ConnectionTimeout = TimeSpan.FromSeconds(STEAM2_CONNECT_TIMEOUT_SECONDS);
ContentServerClient.StorageSession session = GetSteam2StorageSession(contentServers, csClient, depotId, depotVersion); ContentServerClient.StorageSession session;
if(session == null)
return;
Steam2Manifest manifest = null; foreach (var depot in depots)
Steam2ChecksumData checksums = null;
List<int> NodesToDownload = new List<int>();
StringBuilder manifestBuilder = new StringBuilder();
byte[] cryptKey = CDRManager.GetDepotEncryptionKey( depotId, depotVersion );
string[] excludeList = null;
using ( session )
{ {
manifest = session.DownloadManifest(); session = GetSteam2StorageSession(depot.contentServers, csClient, depot.id, depot.version);
if (session == null)
continue;
Console.WriteLine( " Done!" ); Console.Write(String.Format("Downloading manifest for depot {0}...", depot.id));
if(!Config.DownloadManifestOnly) string txtManifest = Path.Combine(depot.installDir, "manifest.txt");
{ Steam2ChecksumData checksums = null;
// Skip downloading checksums if we're only interested in manifests. StringBuilder manifestBuilder = new StringBuilder();
Console.Write("Downloading depot checksums..."); string[] excludeList = null;
checksums = session.DownloadChecksums(); depot.cryptKey = CDRManager.GetDepotEncryptionKey(depot.id, depot.version);
depot.manifest = session.DownloadManifest();
Console.WriteLine(" Done!"); Console.WriteLine(" Done!");
}
if ( Config.UsingExclusionList ) if (Config.UsingExclusionList)
excludeList = GetExcludeList( session, manifest ); excludeList = GetExcludeList(session, depot.manifest);
}
csClient.Disconnect();
if(!Config.DownloadManifestOnly) // Build a list of files that need downloading.
Console.WriteLine("Building list of files to download and checking existing files..."); for (int x = 0; x < depot.manifest.Nodes.Count; ++x)
// Build a list of files that need downloading.
for ( int x = 0 ; x < manifest.Nodes.Count ; ++x )
{
var dirEntry = manifest.Nodes[ x ];
string downloadPath = Path.Combine( installDir, dirEntry.FullName.ToLower() );
if ( Config.DownloadManifestOnly )
{ {
if ( dirEntry.FileID == -1 ) var dirEntry = depot.manifest.Nodes[x];
continue; string downloadPath = Path.Combine(depot.installDir, dirEntry.FullName.ToLower());
if (Config.DownloadManifestOnly)
{
if (dirEntry.FileID == -1)
continue;
manifestBuilder.Append( string.Format( "{0}\n", dirEntry.FullName ) ); manifestBuilder.Append(string.Format("{0}\n", dirEntry.FullName));
continue; continue;
} }
if (Config.UsingExclusionList && IsFileExcluded(dirEntry.FullName, excludeList)) if (Config.UsingExclusionList && IsFileExcluded(dirEntry.FullName, excludeList))
continue; continue;
if (!TestIsFileIncluded(dirEntry.FullName)) if (!TestIsFileIncluded(dirEntry.FullName))
continue; continue;
string path = Path.GetDirectoryName(downloadPath); string path = Path.GetDirectoryName(downloadPath);
if (path != "" && !Directory.Exists(path)) if (path != "" && !Directory.Exists(path))
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
if ( dirEntry.FileID == -1 ) if ( dirEntry.FileID == -1 )
{
if ( !Directory.Exists( downloadPath ) )
{ {
// this is a directory, so lets just create it if ( !Directory.Exists( downloadPath ) )
Directory.CreateDirectory( downloadPath ); {
// this is a directory, so lets just create it
Directory.CreateDirectory( downloadPath );
}
continue;
} }
continue; if (checksums == null)
} {
// Skip downloading checksums if we're only interested in manifests.
Console.Write(String.Format("Downloading checksums for depot {0}...", depot.id));
FileInfo fi = new FileInfo( downloadPath ); checksums = session.DownloadChecksums();
if (fi.Exists)
{ Console.WriteLine(" Done!");
float perc = ( ( float )x / ( float )manifest.Nodes.Count ) * 100.0f; }
Console.WriteLine("{0,6:#00.00}%\t{1}", perc, downloadPath);
// Similar file, let's check checksums FileInfo fi = new FileInfo(downloadPath);
if(fi.Length == dirEntry.SizeOrCount && if (fi.Exists)
Util.ValidateSteam2FileChecksums(fi, checksums.GetFileChecksums(dirEntry.FileID)))
{ {
// checksums OK float perc = ((float)x / (float)depot.manifest.Nodes.Count) * 100.0f;
continue; Console.WriteLine("{0,6:#00.00}%\t{1}", perc, downloadPath);
// Similar file, let's check checksums
if (fi.Length == dirEntry.SizeOrCount &&
Util.ValidateSteam2FileChecksums(fi, checksums.GetFileChecksums(dirEntry.FileID)))
{
// checksums OK
continue;
}
// Unlink the current file before we download a new one.
// This will keep symbolic/hard link targets from being overwritten.
fi.Delete();
} }
// Unlink the current file before we download a new one. depot.NodesToDownload.Add(x);
// This will keep symbolic/hard link targets from being overwritten.
fi.Delete();
} }
NodesToDownload.Add(x);
}
if ( Config.DownloadManifestOnly ) if (Config.DownloadManifestOnly)
{ {
File.WriteAllText( txtManifest, manifestBuilder.ToString() ); File.WriteAllText(txtManifest, manifestBuilder.ToString());
return; return;
}
} }
Console.WriteLine("Downloading selected files.");
foreach( var depot in depots )
{
if (depot.NodesToDownload.Count == 0)
continue;
session = GetSteam2StorageSession(contentServers, csClient, depotId, depotVersion); session = GetSteam2StorageSession(depot.contentServers, csClient, depot.id, depot.version);
if(session == null) if(session == null)
return; continue;
using ( session ) for ( int x = 0 ; x < depot.NodesToDownload.Count ; ++x )
{
Console.WriteLine("Downloading selected files.");
for ( int x = 0 ; x < NodesToDownload.Count ; ++x )
{ {
var dirEntry = manifest.Nodes[ NodesToDownload[ x ] ]; var dirEntry = depot.manifest.Nodes[ depot.NodesToDownload[ x ] ];
string downloadPath = Path.Combine( installDir, dirEntry.FullName.ToLower() ); string downloadPath = Path.Combine( depot.installDir, dirEntry.FullName.ToLower() );
float perc = ( ( float )x / ( float )NodesToDownload.Count ) * 100.0f; float perc = ( ( float )x / ( float )depot.NodesToDownload.Count ) * 100.0f;
Console.WriteLine("{0,6:#00.00}%\t{1}", perc, downloadPath); Console.WriteLine("{0,6:#00.00}%\t{1}", perc, downloadPath);
var file = session.DownloadFile( dirEntry, ContentServerClient.StorageSession.DownloadPriority.High, cryptKey ); var file = session.DownloadFile( dirEntry, ContentServerClient.StorageSession.DownloadPriority.High, depot.cryptKey );
File.WriteAllBytes( downloadPath, file ); File.WriteAllBytes( downloadPath, file );
} }
} }

Loading…
Cancel
Save