Large refactor to support steam3 appinfo

pull/8/head
azuisleet 14 years ago
parent 9a92d8b203
commit d6850b8f33

@ -16,31 +16,35 @@ namespace DepotDownloader
const string DEFAULT_DIR = "depots";
const int MAX_STORAGE_RETRIES = 500;
static Steam3Session steam3;
public static DownloadConfig Config = new DownloadConfig();
static bool CreateDirectories( int depotId, int depotVersion, ref string installDir )
private static Steam3Session steam3;
private static Steam3Session.Credentials steam3Credentials;
static bool CreateDirectories( int depotId, int depotVersion, out string installDir )
{
installDir = null;
try
{
if ( installDir == null || installDir == "" )
if (ContentDownloader.Config.InstallDirectory == null || ContentDownloader.Config.InstallDirectory == "")
{
Directory.CreateDirectory( DEFAULT_DIR );
string depotPath = Path.Combine( DEFAULT_DIR, depotId.ToString() );
Directory.CreateDirectory( depotPath );
installDir = Path.Combine( depotPath, depotVersion.ToString() );
Directory.CreateDirectory( installDir );
installDir = Path.Combine(depotPath, depotVersion.ToString());
Directory.CreateDirectory(installDir);
}
else
{
Directory.CreateDirectory( installDir );
Directory.CreateDirectory(ContentDownloader.Config.InstallDirectory);
string serverFolder = CDRManager.GetDedicatedServerFolder( depotId );
if ( serverFolder != null && serverFolder != "" )
{
installDir = Path.Combine( installDir, serverFolder );
Directory.CreateDirectory( installDir );
installDir = Path.Combine(ContentDownloader.Config.InstallDirectory, serverFolder);
Directory.CreateDirectory(installDir);
}
}
}
@ -109,6 +113,28 @@ namespace DepotDownloader
return false;
}
static bool TestIsFileIncluded(string filename)
{
if (!Config.UsingFileList)
return true;
foreach (string fileListEntry in Config.FilesToDownload)
{
if (fileListEntry.Equals(filename, StringComparison.OrdinalIgnoreCase))
return true;
}
foreach (Regex rgx in Config.FilesToDownloadRegex)
{
Match m = rgx.Match(filename);
if (m.Success)
return true;
}
return false;
}
static bool AccountHasAccess( int depotId )
{
if ( steam3 == null || steam3.Licenses == null )
@ -116,6 +142,7 @@ namespace DepotDownloader
foreach ( var license in steam3.Licenses )
{
// TODO: support PackageInfoRequest/Response, this is a steam2 dependency
if ( CDRManager.SubHasDepot( ( int )license.PackageID, depotId ) )
return true;
}
@ -123,84 +150,223 @@ namespace DepotDownloader
return false;
}
static bool DepotHasSteam3Manifest( int depotId, int appId, out ulong manifest_id )
static bool AppIsSteam3(int appId)
{
if (steam3 == null || steam3.AppInfo == null)
if (steam3 == null || steam3.AppInfoOverridesCDR == null)
{
manifest_id = 0;
return false;
}
string appkey = appId.ToString();
string depotkey = depotId.ToString();
foreach (var app in steam3.AppInfo)
steam3.RequestAppInfo((uint)appId);
bool app_override;
if(!steam3.AppInfoOverridesCDR.TryGetValue((uint)appId, out app_override))
return false;
return app_override;
}
static KeyValue GetSteam3AppSection(int appId, EAppInfoSection section)
{
if (steam3 == null || steam3.AppInfo == null)
{
return null;
}
SteamApps.AppInfoCallback.AppInfo app;
if (!steam3.AppInfo.TryGetValue((uint)appId, out app))
{
KeyValue depots;
if (app.AppID == appId && app.Sections.TryGetValue((int)EAppInfoSection.AppInfoSectionDepots, out depots))
{
// check depots for app
foreach (var depotkv in depots[appkey].Children)
{
if(depotkv.Name != depotkey)
continue;
return null;
}
KeyValue section_kv;
if (!app.Sections.TryGetValue((int)section, out section_kv))
{
return null;
}
var node = depotkv.Children
.Where(c => c.Name == "manifests").First().Children
.Where(d => d.Name == "Public").First();
return section_kv;
}
static ulong GetSteam3DepotManifest(int depotId, int appId)
{
if (appId == -1 || !AppIsSteam3(appId))
return 0;
KeyValue depots = GetSteam3AppSection(appId, EAppInfoSection.AppInfoSectionDepots);
KeyValue depotChild = depots[appId.ToString()][depotId.ToString()];
if (depotChild == null)
return 0;
var node = depotChild["manifests"]["Public"];
return UInt64.Parse(node.Value);
}
static string GetAppOrDepotName(int depotId, int appId)
{
if (appId == -1 || !AppIsSteam3(appId))
{
return CDRManager.GetDepotName(depotId);
}
else if (depotId == -1)
{
KeyValue info = GetSteam3AppSection(appId, EAppInfoSection.AppInfoSectionCommon);
if (info == null)
return String.Empty;
return info[appId.ToString()]["name"].AsString();
}
else
{
KeyValue depots = GetSteam3AppSection(appId, EAppInfoSection.AppInfoSectionDepots);
if (depots == null)
return String.Empty;
KeyValue depotChild = depots[appId.ToString()][depotId.ToString()];
if (depotChild == null)
return String.Empty;
return depotChild["name"].AsString();
}
}
public static void InitializeSteam3(string username, string password)
{
steam3 = new Steam3Session(
new SteamUser.LogOnDetails()
{
Username = username,
Password = password,
manifest_id = UInt64.Parse(node.Value);
return true;
}
}
);
steam3Credentials = steam3.WaitForCredentials();
if (!steam3Credentials.HasSessionToken)
{
Console.WriteLine("Unable to get steam3 credentials.");
return;
}
}
manifest_id = 0;
return false;
private static ContentServerClient.Credentials GetSteam2Credentials(uint appId)
{
if (steam3 == null || !steam3Credentials.HasSessionToken)
{
return null;
}
return new ContentServerClient.Credentials()
{
Steam2Ticket = new Steam2Ticket(steam3Credentials.Steam2Ticket),
AppTicket = steam3.AppTickets[appId],
SessionToken = steam3Credentials.SessionToken,
};
}
public static void Download( int depotId, int appId, int depotVersion, int cellId, string username, string password, bool onlyManifest, bool gameServer, bool exclude, string installDir, string[] fileList )
public static void DownloadApp(int appId)
{
if ( !CreateDirectories( depotId, depotVersion, ref installDir ) )
if(steam3 != null)
steam3.RequestAppInfo((uint)appId);
if (!AccountHasAccess(appId))
{
Console.WriteLine( "Error: Unable to create install directories!" );
string contentName = GetAppOrDepotName(-1, appId);
Console.WriteLine("App {0} ({1}) is not available from this account.", appId, contentName);
return;
}
ContentServerClient.Credentials credentials = null;
List<int> depotIDs = null;
if (username != null)
if (AppIsSteam3(appId))
{
// ServerCache.BuildAuthServers( username );
credentials = GetCredentials((uint)depotId, (uint)appId, username, password);
depotIDs = new List<int>();
KeyValue depots = GetSteam3AppSection(appId, EAppInfoSection.AppInfoSectionDepots);
if (depots != null)
{
depots = depots[appId.ToString()];
foreach (var child in depots.Children)
{
if (child.Children.Count > 0)
{
depotIDs.Add(int.Parse(child.Name));
}
}
}
}
else
{
// steam2 path
depotIDs = CDRManager.GetDepotIDsForApp(appId, Config.DownloadAllPlatforms);
}
if (!AccountHasAccess(depotId))
if (depotIDs == null || depotIDs.Count == 0)
{
Console.WriteLine("Couldn't find any depots to download for app {0}", appId);
return;
}
foreach (var depot in depotIDs)
{
string contentName = CDRManager.GetDepotName(depotId);
// Steam2 dependency
int depotVersion = CDRManager.GetLatestDepotVersion(depot, Config.PreferBetaVersions);
if (depotVersion == -1)
{
Console.WriteLine("Error: Unable to find DepotID {0} in the CDR!", depot);
return;
}
DownloadDepot(depot, appId, depotVersion);
}
}
public static void DownloadDepot(int depotId, int appId, int depotVersion)
{
if(steam3 != null && appId > 0)
steam3.RequestAppInfo((uint)appId);
string contentName = GetAppOrDepotName(depotId, appId);
if (!AccountHasAccess(depotId))
{
Console.WriteLine("Depot {0} ({1}) is not available from this account.", depotId, contentName);
if (steam3 != null)
steam3.Disconnect();
return;
}
string installDir;
if (!CreateDirectories(depotId, depotVersion, out installDir))
{
Console.WriteLine("Error: Unable to create install directories!");
return;
}
ulong steam3_manifest;
if ( DepotHasSteam3Manifest( depotId, appId, out steam3_manifest ) )
Console.WriteLine("Downloading \"{0}\" version {1} ...", contentName, depotVersion);
ulong manifestID = GetSteam3DepotManifest(depotId, appId);
if (manifestID > 0)
{
DownloadSteam3( credentials, depotId, depotVersion, cellId, steam3_manifest, installDir );
DownloadSteam3(depotId, depotVersion, manifestID, installDir);
}
else
{
DownloadSteam2( credentials, depotId, depotVersion, cellId, username, password, onlyManifest, gameServer, exclude, installDir, fileList );
// steam2 path
DownloadSteam2(depotId, depotVersion, installDir);
}
if ( steam3 != null )
steam3.Disconnect();
}
private static void DownloadSteam3( ContentServerClient.Credentials credentials, int depotId, int depotVersion, int cellId, ulong depot_manifest, string installDir )
private static void DownloadSteam3( int depotId, int depotVersion, ulong depot_manifest, string installDir )
{
steam3.RequestAppTicket((uint)depotId);
steam3.RequestDepotKey((uint)depotId);
Console.Write("Finding content servers...");
List<IPEndPoint> serverList = steam3.steamClient.GetServersOfType(EServerType.ServerTypeCS);
@ -209,7 +375,7 @@ namespace DepotDownloader
foreach(var endpoint in serverList)
{
cdnServers = CDNClient.FetchServerList(new CDNClient.ClientEndPoint(endpoint.Address.ToString(), endpoint.Port), cellId);
cdnServers = CDNClient.FetchServerList(new CDNClient.ClientEndPoint(endpoint.Address.ToString(), endpoint.Port), Config.CellID);
if (cdnServers != null && cdnServers.Count > 0)
break;
@ -217,14 +383,14 @@ namespace DepotDownloader
if (cdnServers == null || cdnServers.Count == 0)
{
Console.WriteLine("Unable to find any steam3 content servers");
Console.WriteLine("Unable to find any Steam3 content servers");
return;
}
Console.WriteLine(" Done!");
Console.Write("Downloading depot manifest...");
CDNClient cdnClient = new CDNClient(cdnServers[0], credentials.AppTicket);
CDNClient cdnClient = new CDNClient(cdnServers[0], steam3.AppTickets[(uint)depotId]);
if (!cdnClient.Connect())
{
@ -241,13 +407,11 @@ namespace DepotDownloader
}
string manifestFile = Path.Combine(installDir, "manifest.bin");
string keyFile = Path.Combine(installDir, "depotkey.bin");
File.WriteAllBytes(manifestFile, manifest);
File.WriteAllBytes(keyFile, steam3.DepotKey);
DepotManifest depotManifest = new DepotManifest(manifest);
if (!depotManifest.DecryptFilenames(steam3.DepotKey))
if (!depotManifest.DecryptFilenames(steam3.DepotKeys[(uint)depotId]))
{
Console.WriteLine("\nUnable to decrypt manifest for depot {0}", depotId);
return;
@ -258,6 +422,8 @@ namespace DepotDownloader
ulong complete_download_size = 0;
ulong size_downloaded = 0;
depotManifest.Files.Sort((x, y) => { return x.FileName.CompareTo(y.FileName); });
foreach (var file in depotManifest.Files)
{
complete_download_size += file.TotalSize;
@ -276,10 +442,7 @@ namespace DepotDownloader
string dir_path = Path.GetDirectoryName(download_path);
int top = Console.CursorTop;
Console.WriteLine("00.00% Downloading {0}", download_path);
int top_post = Console.CursorTop;
Console.CursorTop = top;
Console.Write("{0:00.00}% Downloading {1}", ((float)size_downloaded / (float)complete_download_size) * 100.0f, download_path);
if (!Directory.Exists(dir_path))
Directory.CreateDirectory(dir_path);
@ -292,7 +455,7 @@ namespace DepotDownloader
string chunkID = Utils.BinToHex(chunk.ChunkID);
byte[] encrypted_chunk = cdnClient.DownloadDepotChunk(depotId, chunkID);
byte[] chunk_data = cdnClient.ProcessChunk(encrypted_chunk, steam3.DepotKey);
byte[] chunk_data = cdnClient.ProcessChunk(encrypted_chunk, steam3.DepotKeys[(uint)depotId]);
fs.Seek((long)chunk.Offset, SeekOrigin.Begin);
fs.Write(chunk_data, 0, chunk_data.Length);
@ -303,19 +466,18 @@ namespace DepotDownloader
Console.Write("{0:00.00}", ((float)size_downloaded / (float)complete_download_size) * 100.0f);
}
Console.CursorTop = top_post;
Console.CursorLeft = 0;
Console.WriteLine();
}
}
private static void DownloadSteam2( ContentServerClient.Credentials credentials, int depotId, int depotVersion, int cellId, string username, string password, bool onlyManifest, bool gameServer, bool exclude, string installDir, string[] fileList )
private static void DownloadSteam2( int depotId, int depotVersion, string installDir )
{
Console.Write("Finding content servers...");
IPEndPoint[] contentServers = GetStorageServer(depotId, depotVersion, cellId);
IPEndPoint[] contentServers = GetStorageServer(depotId, depotVersion, Config.CellID);
if (contentServers.Length == 0)
if (contentServers == null || contentServers.Length == 0)
{
Console.WriteLine("\nError: Unable to find any content servers for depot {0}, version {1}", depotId, depotVersion);
Console.WriteLine("\nError: Unable to find any Steam2 content servers for depot {0}, version {1}", depotId, depotVersion);
return;
}
@ -335,7 +497,7 @@ namespace DepotDownloader
try
{
csClient.Connect( contentServers[server] );
session = csClient.OpenStorage( ( uint )depotId, ( uint )depotVersion, ( uint )cellId, credentials );
session = csClient.OpenStorage( ( uint )depotId, ( uint )depotVersion, ( uint )Config.CellID, GetSteam2Credentials((uint)depotId) );
}
catch ( Steam2Exception ex )
{
@ -367,29 +529,12 @@ namespace DepotDownloader
Console.WriteLine( " Done!" );
if ( onlyManifest )
File.Delete( txtManifest );
StringBuilder manifestBuilder = new StringBuilder();
List<Regex> rgxList = new List<Regex>();
if ( fileList != null )
{
foreach ( string fileListentry in fileList )
{
try
{
Regex rgx = new Regex( fileListentry, RegexOptions.Compiled | RegexOptions.IgnoreCase );
rgxList.Add( rgx );
}
catch { continue; }
}
}
byte[] cryptKey = CDRManager.GetDepotEncryptionKey( depotId, depotVersion );
string[] excludeList = null;
if ( gameServer && exclude )
if ( Config.UsingExclusionList )
excludeList = GetExcludeList( session, manifest );
for ( int x = 0 ; x < manifest.Nodes.Count ; ++x )
@ -398,7 +543,7 @@ namespace DepotDownloader
string downloadPath = Path.Combine( installDir, dirEntry.FullName.ToLower() );
if ( onlyManifest )
if ( Config.DownloadManifestOnly )
{
if ( dirEntry.FileID == -1 )
continue;
@ -407,44 +552,16 @@ namespace DepotDownloader
continue;
}
if ( gameServer && exclude && IsFileExcluded( dirEntry.FullName, excludeList ) )
if (Config.UsingExclusionList && IsFileExcluded(dirEntry.FullName, excludeList))
continue;
if ( fileList != null )
{
bool bMatched = false;
foreach ( string fileListEntry in fileList )
{
if ( fileListEntry.Equals( dirEntry.FullName, StringComparison.OrdinalIgnoreCase ) )
{
bMatched = true;
break;
}
}
if ( !bMatched )
{
foreach ( Regex rgx in rgxList )
{
Match m = rgx.Match( dirEntry.FullName );
if ( m.Success )
{
bMatched = true;
break;
}
}
}
if ( !bMatched )
continue;
if (!TestIsFileIncluded(dirEntry.FullName))
continue;
string path = Path.GetDirectoryName( downloadPath );
string path = Path.GetDirectoryName(downloadPath);
if ( !Directory.Exists( path ) )
Directory.CreateDirectory( path );
}
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
if ( dirEntry.FileID == -1 )
{
@ -470,7 +587,7 @@ namespace DepotDownloader
File.WriteAllBytes( downloadPath, file );
}
if ( onlyManifest )
if ( Config.DownloadManifestOnly )
File.WriteAllText( txtManifest, manifestBuilder.ToString() );
}
@ -478,40 +595,6 @@ namespace DepotDownloader
}
static ContentServerClient.Credentials GetCredentials( uint depotId, uint appId, string username, string password )
{
steam3 = new Steam3Session(
new SteamUser.LogOnDetails()
{
Username = username,
Password = password,
},
depotId,
appId
);
var steam3Credentials = steam3.WaitForCredentials();
if ( !steam3Credentials.HasSessionToken || steam3Credentials.AppTicket == null || steam3Credentials.Steam2Ticket == null )
{
Console.WriteLine( "Unable to get steam3 credentials." );
return null;
}
Steam2Ticket s2Ticket = new Steam2Ticket( steam3Credentials.Steam2Ticket );
ContentServerClient.Credentials credentials = new ContentServerClient.Credentials()
{
Steam2Ticket = s2Ticket,
AppTicket = steam3Credentials.AppTicket,
SessionToken = steam3Credentials.SessionToken,
};
return credentials;
}
static IPEndPoint[] GetStorageServer( int depotId, int depotVersion, int cellId )
{
foreach ( IPEndPoint csdServer in ServerCache.CSDSServers )
@ -536,30 +619,6 @@ namespace DepotDownloader
return null;
}
static IPEndPoint GetAnyStorageServer()
{
foreach (IPEndPoint csdServer in ServerCache.CSDSServers)
{
ContentServerDSClient csdsClient = new ContentServerDSClient();
csdsClient.Connect(csdServer);
IPEndPoint[] servers = csdsClient.GetContentServerList();
if (servers == null)
{
Console.WriteLine("Warning: CSDS {0} returned empty server list.", csdServer);
continue;
}
if (servers.Length == 0)
continue;
return servers[PsuedoRandom.GetRandomInt(0, servers.Length - 1)];
}
return null;
}
static IPEndPoint GetAuthServer()
{
if ( ServerCache.AuthServers.Count > 0 )

@ -70,6 +70,7 @@
<ItemGroup>
<Compile Include="CDRManager.cs" />
<Compile Include="ContentDownloader.cs" />
<Compile Include="DownloadConfig.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServerCache.cs" />

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace DepotDownloader
{
class DownloadConfig
{
public int CellID { get; set; }
public bool DownloadAllPlatforms { get; set; }
public bool PreferBetaVersions { get; set; }
public bool DownloadManifestOnly { get; set; }
public string InstallDirectory { get; set; }
public bool UsingFileList { get; set; }
public List<string> FilesToDownload { get; set; }
public List<Regex> FilesToDownloadRegex { get; set; }
public bool UsingExclusionList { get; set; }
}
}

@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using SteamKit2;
using System.IO;
using System.Text.RegularExpressions;
namespace DepotDownloader
{
@ -40,41 +41,62 @@ namespace DepotDownloader
return;
}
bool bDebot = true;
bool bManifest = false;
bool bGameserver = true;
bool bApp = true;
bool bApp = false;
int appId = -1;
int depotId = -1;
string gameName = GetStringParameter( args, "-game" );
if ( gameName == null )
{
depotId = GetIntParameter( args, "-app" );
appId = GetIntParameter( args, "-app" );
bGameserver = false;
if ( depotId == -1 )
depotId = GetIntParameter(args, "-depot");
if (depotId == -1)
{
depotId = GetIntParameter( args, "-depot" );
bApp = false;
if ( depotId == -1 )
{
depotId = GetIntParameter( args, "-manifest" );
bDebot = false;
depotId = GetIntParameter(args, "-manifest");
if ( depotId == -1 )
{
Console.WriteLine( "Error: -game, -app, -depot or -manifest not specified!" );
return;
}
if (depotId == -1 && appId == -1)
{
Console.WriteLine("Error: -game, -app, -depot or -manifest not specified!");
return;
}
else if (depotId >= 0)
{
bManifest = true;
}
else if (appId >= 0)
{
bApp = true;
}
}
}
ContentDownloader.Config.DownloadManifestOnly = bManifest;
int cellId = GetIntParameter(args, "-cellid");
if (cellId == -1)
{
cellId = 0;
Console.WriteLine(
"Warning: Using default CellID of 0! This may lead to slow downloads. " +
"You can specify the CellID using the -cellid parameter");
}
ContentDownloader.Config.CellID = cellId;
int depotVersion = GetIntParameter( args, "-version" );
bool bBeta = HasParameter( args, "-beta" );
ContentDownloader.Config.PreferBetaVersions = HasParameter( args, "-beta" );
// this is a Steam2 option
if ( !bGameserver && !bApp && depotVersion == -1 )
{
int latestVer = CDRManager.GetLatestDepotVersion( depotId, bBeta );
int latestVer = CDRManager.GetLatestDepotVersion(depotId, ContentDownloader.Config.PreferBetaVersions);
if ( latestVer == -1 )
{
@ -104,16 +126,6 @@ namespace DepotDownloader
}
}
int cellId = GetIntParameter( args, "-cellid" );
if ( cellId == -1 )
{
cellId = 0;
Console.WriteLine(
"Warning: Using default CellID of 0! This may lead to slow downloads. " +
"You can specify the CellID using the -cellid parameter" );
}
string fileList = GetStringParameter( args, "-filelist" );
string[] files = null;
@ -124,6 +136,24 @@ namespace DepotDownloader
string fileListData = File.ReadAllText( fileList );
files = fileListData.Split( new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries );
ContentDownloader.Config.UsingFileList = true;
ContentDownloader.Config.FilesToDownload = new List<string>();
ContentDownloader.Config.FilesToDownloadRegex = new List<Regex>();
foreach (var fileEntry in files)
{
try
{
Regex rgx = new Regex(fileEntry, RegexOptions.Compiled | RegexOptions.IgnoreCase);
ContentDownloader.Config.FilesToDownloadRegex.Add(rgx);
}
catch
{
ContentDownloader.Config.FilesToDownload.Add(fileEntry);
continue;
}
}
Console.WriteLine( "Using filelist: '{0}'.", fileList );
}
catch ( Exception ex )
@ -132,50 +162,51 @@ namespace DepotDownloader
}
}
string username = GetStringParameter( args, "-username" );
string password = GetStringParameter( args, "-password" );
string installDir = GetStringParameter( args, "-dir" );
bool bNoExclude = HasParameter( args, "-no-exclude" );
bool bAllPlatforms = HasParameter( args, "-all-platforms" );
string username = GetStringParameter(args, "-username");
string password = GetStringParameter(args, "-password");
ContentDownloader.Config.InstallDirectory = GetStringParameter(args, "-dir");
bool bNoExclude = HasParameter(args, "-no-exclude");
ContentDownloader.Config.DownloadAllPlatforms = HasParameter(args, "-all-platforms");
if (username != null && password == null)
{
Console.Write( "Enter account password: " );
Console.Write("Enter account password: ");
password = Util.ReadPassword();
Console.WriteLine();
}
if ( !bGameserver && !bApp )
if (username != null)
{
ContentDownloader.InitializeSteam3(username, password);
}
if (bApp)
{
ContentDownloader.DownloadApp(appId);
}
else if ( !bGameserver )
{
ContentDownloader.Download( depotId, depotId, depotVersion, cellId, username, password, !bDebot, false, false, installDir, files );
ContentDownloader.DownloadDepot(depotId, appId, depotVersion);
}
else
{
List<int> depotIDs;
if (!bNoExclude)
{
ContentDownloader.Config.UsingExclusionList = true;
}
if ( bGameserver )
depotIDs = CDRManager.GetDepotIDsForGameserver( gameName, bAllPlatforms );
else
depotIDs = CDRManager.GetDepotIDsForApp( depotId, bAllPlatforms );
List<int> depotIDs = CDRManager.GetDepotIDsForGameserver( gameName, ContentDownloader.Config.DownloadAllPlatforms );
foreach ( int currentDepotId in depotIDs )
{
depotVersion = CDRManager.GetLatestDepotVersion( currentDepotId, bBeta );
depotVersion = CDRManager.GetLatestDepotVersion(currentDepotId, ContentDownloader.Config.PreferBetaVersions);
if ( depotVersion == -1 )
{
Console.WriteLine( "Error: Unable to find DepotID {0} in the CDR!", currentDepotId );
return;
}
string depotName = CDRManager.GetDepotName( currentDepotId );
Console.WriteLine( "Downloading \"{0}\" version {1} ...", depotName, depotVersion );
int sourceId = depotId;
if (bGameserver)
sourceId = currentDepotId;
ContentDownloader.Download( currentDepotId, sourceId, depotVersion, cellId, username, password, false, bGameserver, !bNoExclude, installDir, files );
ContentDownloader.DownloadDepot(currentDepotId, -1, depotVersion);
}
}
}

@ -15,9 +15,6 @@ namespace DepotDownloader
{
public bool HasSessionToken { get; set; }
public ulong SessionToken { get; set; }
public byte[] AppTicket { get; set; }
public byte[] Steam2Ticket { get; set; }
}
@ -27,25 +24,21 @@ namespace DepotDownloader
private set;
}
public byte[] DepotKey { get; private set; }
public ReadOnlyCollection<SteamApps.AppInfoCallback.AppInfo> AppInfo { get; private set; }
public Dictionary<uint, byte[]> AppTickets { get; private set; }
public Dictionary<uint, byte[]> DepotKeys { get; private set; }
public Dictionary<uint, SteamApps.AppInfoCallback.AppInfo> AppInfo { get; private set; }
public Dictionary<uint, bool> AppInfoOverridesCDR { get; private set; }
public SteamClient steamClient;
SteamUser steamUser;
SteamApps steamApps;
Thread callbackThread;
ManualResetEvent credentialHandle;
bool bConnected;
bool bKeyResponse;
bool bAborted;
DateTime connectTime;
// input
uint depotId;
uint appId; // base
SteamUser.LogOnDetails logonDetails;
// output
@ -54,25 +47,24 @@ namespace DepotDownloader
static readonly TimeSpan STEAM3_TIMEOUT = TimeSpan.FromSeconds( 30 );
public Steam3Session( SteamUser.LogOnDetails details, uint depotId, uint appId )
public Steam3Session( SteamUser.LogOnDetails details )
{
this.depotId = depotId;
this.appId = appId;
this.logonDetails = details;
this.credentials = new Credentials();
this.credentialHandle = new ManualResetEvent( false );
this.bConnected = false;
this.bKeyResponse = false;
this.bAborted = false;
this.AppTickets = new Dictionary<uint, byte[]>();
this.DepotKeys = new Dictionary<uint, byte[]>();
this.AppInfo = new Dictionary<uint, SteamApps.AppInfoCallback.AppInfo>();
this.AppInfoOverridesCDR = new Dictionary<uint, bool>();
this.steamClient = new SteamClient();
this.steamUser = this.steamClient.GetHandler<SteamUser>();
this.steamApps = this.steamClient.GetHandler<SteamApps>();
this.callbackThread = new Thread( HandleCallbacks );
this.callbackThread.Start();
Console.Write( "Connecting to Steam3..." );
Connect();
@ -80,20 +72,74 @@ namespace DepotDownloader
public Credentials WaitForCredentials()
{
this.credentialHandle.WaitOne();
do
{
HandleCallbacks();
}
while (!bAborted && (credentials.SessionToken == 0 || credentials.Steam2Ticket == null));
return credentials;
}
public void RequestAppInfo(uint appId)
{
if (bAborted || AppInfo.ContainsKey(appId))
return;
steamApps.GetAppInfo(appId);
do
{
HandleCallbacks();
}
while (!bAborted && !AppInfo.ContainsKey(appId));
}
public void RequestAppTicket(uint appId)
{
if (bAborted || AppTickets.ContainsKey(appId))
return;
steamApps.GetAppOwnershipTicket(appId);
do
{
HandleCallbacks();
}
while (!bAborted && !AppTickets.ContainsKey(appId));
}
public void RequestDepotKey(uint depotId)
{
if (bAborted || DepotKeys.ContainsKey(depotId))
return;
steamApps.GetDepotDecryptionKey(depotId);
do
{
HandleCallbacks();
}
while (!bAborted && !DepotKeys.ContainsKey(depotId));
}
void Connect()
{
this.connectTime = DateTime.Now;
this.steamClient.Connect();
}
private void Abort()
{
bAborted = true;
Disconnect();
}
public void Disconnect()
{
steamUser.LogOff();
steamClient.Disconnect();
bConnected = false;
}
void HandleCallbacks()
@ -104,14 +150,14 @@ namespace DepotDownloader
TimeSpan diff = DateTime.Now - connectTime;
if ( diff > STEAM3_TIMEOUT && !bConnected )
break;
if ( credentials.HasSessionToken && credentials.AppTicket != null && Licenses != null && credentials.Steam2Ticket != null && AppInfo != null && bKeyResponse )
if (diff > STEAM3_TIMEOUT && !bConnected)
{
Abort();
break;
}
if ( callback == null )
continue;
break;
if ( callback.IsType<SteamClient.ConnectCallback>() )
{
@ -121,8 +167,7 @@ namespace DepotDownloader
Console.Write( "Logging '{0}' into Steam3...", logonDetails.Username );
}
if ( callback.IsType<SteamUser.LogOnCallback>() )
else if ( callback.IsType<SteamUser.LogOnCallback>() )
{
var msg = callback as SteamUser.LogOnCallback;
@ -140,7 +185,7 @@ namespace DepotDownloader
else if ( msg.Result != EResult.OK )
{
Console.WriteLine( "Unable to login to Steam3: {0}", msg.Result );
steamUser.LogOff();
Abort();
break;
}
@ -148,32 +193,23 @@ namespace DepotDownloader
Console.WriteLine( "Got Steam2 Ticket!" );
credentials.Steam2Ticket = msg.Steam2Ticket;
steamApps.GetAppInfo( appId );
steamApps.GetAppOwnershipTicket( depotId );
steamApps.GetDepotDecryptionKey( depotId );
}
if ( callback.IsType<SteamApps.AppOwnershipTicketCallback>() )
else if (callback.IsType<SteamApps.AppOwnershipTicketCallback>())
{
var msg = callback as SteamApps.AppOwnershipTicketCallback;
if ( msg.AppID != depotId )
continue;
if ( msg.Result != EResult.OK )
{
Console.WriteLine( "Unable to get appticket for {0}: {1}", depotId, msg.Result );
steamUser.LogOff();
Console.WriteLine( "Unable to get appticket for {0}: {1}", msg.AppID, msg.Result );
Abort();
break;
}
Console.WriteLine( "Got appticket for {0}!", depotId );
credentials.AppTicket = msg.Ticket;
Console.WriteLine( "Got appticket for {0}!", msg.AppID );
AppTickets[msg.AppID] = msg.Ticket;
}
if ( callback.IsType<SteamUser.SessionTokenCallback>() )
else if (callback.IsType<SteamUser.SessionTokenCallback>())
{
var msg = callback as SteamUser.SessionTokenCallback;
@ -181,50 +217,47 @@ namespace DepotDownloader
credentials.SessionToken = msg.SessionToken;
credentials.HasSessionToken = true;
}
if ( callback.IsType<SteamApps.LicenseListCallback>() )
else if (callback.IsType<SteamApps.LicenseListCallback>())
{
var msg = callback as SteamApps.LicenseListCallback;
if ( msg.Result != EResult.OK )
{
Console.WriteLine( "Unable to get license list: {0} ", msg.Result );
steamUser.LogOff();
Abort();
break;
}
Console.WriteLine( "Got {0} licenses for account!", msg.LicenseList.Count );
Licenses = msg.LicenseList;
}
if ( callback.IsType<SteamApps.AppInfoCallback>() )
else if (callback.IsType<SteamApps.AppInfoCallback>())
{
var msg = callback as SteamApps.AppInfoCallback;
if (msg.AppsPending > 0 || msg.Apps.Count == 0 || msg.Apps[0].Status == SteamApps.AppInfoCallback.AppInfo.AppInfoStatus.Unknown)
foreach (var app in msg.Apps)
{
Console.WriteLine("AppInfo did not contain the requested app id {0}", depotId);
steamUser.LogOff();
break;
Console.WriteLine("Got AppInfo for {0}: {1}", app.AppID, app.Status);
AppInfo.Add(app.AppID, app);
KeyValue depots;
if (app.Sections.TryGetValue((int)EAppInfoSection.AppInfoSectionDepots, out depots))
{
if (depots[app.AppID.ToString()]["OverridesCDDB"].AsBoolean(false))
{
AppInfoOverridesCDR[app.AppID] = true;
}
}
}
Console.WriteLine("Got AppInfo for {0}", msg.Apps[0].AppID);
AppInfo = msg.Apps;
}
if (callback.IsType<SteamApps.DepotKeyCallback>())
else if (callback.IsType<SteamApps.DepotKeyCallback>())
{
var msg = callback as SteamApps.DepotKeyCallback;
DepotKey = msg.DepotKey;
Console.WriteLine("Got depot key for {0} result: {1}", msg.DepotID, msg.Result);
bKeyResponse = true;
DepotKeys[msg.DepotID] = msg.DepotKey;
}
}
credentialHandle.Set();
}
}

Loading…
Cancel
Save