internal StorageSession(ContentServerClient cli, uint depotId, uint depotVersion, Credentials credentials) { this.DepotID = depotId; this.DepotVersion = depotVersion; this.client = cli; bool bRet = false; if (credentials == null) { bRet = this.SendCommand( 9, // open storage ConnectionID, MessageID, depotId, depotVersion ); } else { byte[] serverTgt = credentials.Steam2Ticket.Entries[14].Data; // god help this never change bRet = this.SendCommand( 10, // open storage with login ConnectionID, MessageID, depotId, depotVersion, ( ushort )serverTgt.Length, serverTgt, NetHelpers.EndianSwap(credentials.SessionToken), ( byte )credentials.AppTicket.Length, credentials.AppTicket ); } // the server sends us back the connection and message ids // the client probably performs a sanity check? uint connId = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint msgId = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); byte hasDepot = this.Socket.Reader.ReadByte(); // the server gives us 0x1 if the depot doesn't exist or requires authentication if (hasDepot != 0) { throw new Steam2Exception("Content server does not have depot, or valid credentials were not given"); } StorageID = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); uint storageChecksum = NetHelpers.EndianSwap(this.Socket.Reader.ReadUInt32()); this.ConnectionID++; }
static string[] GetExcludeList( ContentServerClient.StorageSession session, Steam2Manifest manifest ) { string[] excludeList = null; for ( int x = 0 ; x < manifest.Nodes.Count ; ++x ) { var dirEntry = manifest.Nodes[ x ]; if ( dirEntry.Name == "exclude.lst" && dirEntry.FullName.StartsWith( "reslists" + Path.DirectorySeparatorChar ) && ( dirEntry.Attributes & Steam2Manifest.Node.Attribs.EncryptedFile ) == 0 ) { string excludeFile = Encoding.UTF8.GetString( session.DownloadFile( dirEntry ) ); if ( Environment.OSVersion.Platform == PlatformID.Win32NT ) excludeFile = excludeFile.Replace( '/', Path.DirectorySeparatorChar ); else excludeFile = excludeFile.Replace( '\\', Path.DirectorySeparatorChar ); excludeList = excludeFile.Split( new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries ); break; } } return excludeList; }
private static void DownloadSteam2( List<DepotDownloadInfo2> depots ) { Console.WriteLine("Found depots:"); foreach (var depot in depots) { Console.WriteLine("- {0}\t{1} (version {2})", depot.id, depot.contentName, depot.version); } Console.Write("Finding content servers..."); foreach( var depot in depots ) { depot.contentServers = GetStorageServer(depot.id, depot.version, Config.CellID); 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!"); ContentServerClient csClient = new ContentServerClient(); csClient.ConnectionTimeout = TimeSpan.FromSeconds(STEAM2_CONNECT_TIMEOUT_SECONDS); ContentServerClient.StorageSession session; foreach (var depot in depots) { session = GetSteam2StorageSession(depot.contentServers, csClient, depot.id, depot.version); if (session == null) continue; Console.Write(String.Format("Downloading manifest for depot {0}...", depot.id)); string txtManifest = Path.Combine(depot.installDir, string.Format("manifest_{0}.txt", depot.id)); Steam2ChecksumData checksums = null; StringBuilder manifestBuilder = new StringBuilder(); string[] excludeList = null; depot.cryptKey = CDRManager.GetDepotEncryptionKey(depot.id, depot.version); depot.manifest = session.DownloadManifest(); Console.WriteLine(" Done!"); if (Config.UsingExclusionList) excludeList = GetExcludeList(session, depot.manifest); // Build a list of files that need downloading. for (int x = 0; x < depot.manifest.Nodes.Count; ++x) { var dirEntry = depot.manifest.Nodes[x]; 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)); continue; } if (Config.UsingExclusionList && IsFileExcluded(dirEntry.FullName, excludeList)) continue; if (!TestIsFileIncluded(dirEntry.FullName)) continue; string path = Path.GetDirectoryName(downloadPath); if (path != "" && !Directory.Exists(path)) Directory.CreateDirectory(path); if ( dirEntry.FileID == -1 ) { if ( !Directory.Exists( downloadPath ) ) { // this is a directory, so lets just create it Directory.CreateDirectory( downloadPath ); } 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)); checksums = session.DownloadChecksums(); Console.WriteLine(" Done!"); } FileInfo fi = new FileInfo(downloadPath); if (fi.Exists) { // Similar file, let's check checksums if (fi.Length == dirEntry.SizeOrCount && Util.ValidateSteam2FileChecksums(fi, checksums.GetFileChecksums(dirEntry.FileID))) { // checksums OK float perc = ((float)x / (float)depot.manifest.Nodes.Count) * 100.0f; Console.WriteLine("{0,6:#00.00}%\t{1}", perc, downloadPath); continue; } // Unlink the current file before we download a new one. // This will keep symbolic/hard link targets from being overwritten. fi.Delete(); } depot.NodesToDownload.Add(x); } if (Config.DownloadManifestOnly) { File.WriteAllText(txtManifest, manifestBuilder.ToString()); return; } } foreach( var depot in depots ) { Console.Write("Downloading requested files from depot {0}... ", depot.id); if ( depot.NodesToDownload.Count == 0 ) Console.WriteLine("none needed."); else Console.WriteLine(); session = GetSteam2StorageSession(depot.contentServers, csClient, depot.id, depot.version); if(session == null) continue; for ( int x = 0 ; x < depot.NodesToDownload.Count ; ++x ) { var dirEntry = depot.manifest.Nodes[ depot.NodesToDownload[ x ] ]; string downloadPath = Path.Combine( depot.installDir, dirEntry.FullName.ToLower() ); float perc = ( ( float )x / ( float )depot.NodesToDownload.Count ) * 100.0f; Console.WriteLine("{0,6:#00.00}%\t{1}", perc, downloadPath); using (var fs = new FileStream(downloadPath, FileMode.Create)) { session.DownloadFileToStream(dirEntry, fs, ContentServerClient.StorageSession.DownloadPriority.High, depot.cryptKey); } } } csClient.Disconnect(); }
private static ContentServerClient.StorageSession GetSteam2StorageSession(IPEndPoint [] contentServers, ContentServerClient csClient, int depotId, int depotVersion) { 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 counterSocket = 0, counterSteam2 = 0; for (int i = 0; ; i++) { IPEndPoint endpoint = contentServers[i % contentServers.Length]; try { csClient.Connect( endpoint ); session = csClient.OpenStorage( (uint)depotId, (uint)depotVersion, (uint)Config.CellID, GetSteam2Credentials( (uint)depotId ), true ); lastSteam2ContentServer = endpoint; break; } catch ( SocketException ) { counterSocket++; } catch ( Steam2Exception ) { csClient.Disconnect(); counterSteam2++; } if (((i + 1) % contentServers.Length) == 0) { if (++tries > MAX_CONNECT_RETRIES) { Console.WriteLine("\nGiving up finding Steam2 content server."); return null; } Console.WriteLine("\nSearching for content servers... (socket error: {0}, steam2 error: {1})", counterSocket, counterSteam2); counterSocket = 0; counterSteam2 = 0; Thread.Sleep(1000); } } return session; }
private static void DownloadSteam2( int depotId, int depotVersion, string installDir ) { Console.Write("Finding content servers..."); IPEndPoint[] contentServers = GetStorageServer(depotId, depotVersion, Config.CellID); if (contentServers == null || contentServers.Length == 0) { Console.WriteLine("\nError: Unable to find any Steam2 content servers for depot {0}, version {1}", depotId, depotVersion); return; } Console.WriteLine(" Done!"); Console.Write("Downloading depot manifest..."); string txtManifest = Path.Combine(installDir, "manifest.txt"); ContentServerClient csClient = new ContentServerClient(); ContentServerClient.StorageSession session = GetSteam2StorageSession(contentServers, csClient, depotId, depotVersion); if(session == null) return; Steam2Manifest manifest = null; 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(); Console.WriteLine( " Done!" ); if(!Config.DownloadManifestOnly) { // Skip downloading checksums if we're only interested in manifests. Console.Write("Downloading depot checksums..."); checksums = session.DownloadChecksums(); Console.WriteLine(" Done!"); } if ( Config.UsingExclusionList ) excludeList = GetExcludeList( session, manifest ); } csClient.Disconnect(); if(!Config.DownloadManifestOnly) Console.WriteLine("Building list of files to download and checking existing files..."); // 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 ) continue; manifestBuilder.Append( string.Format( "{0}\n", dirEntry.FullName ) ); continue; } if (Config.UsingExclusionList && IsFileExcluded(dirEntry.FullName, excludeList)) continue; if (!TestIsFileIncluded(dirEntry.FullName)) continue; string path = Path.GetDirectoryName(downloadPath); if (!Directory.Exists(path)) Directory.CreateDirectory(path); if ( dirEntry.FileID == -1 ) { if ( !Directory.Exists( downloadPath ) ) { // this is a directory, so lets just create it Directory.CreateDirectory( downloadPath ); } continue; } FileInfo fi = new FileInfo( downloadPath ); if (fi.Exists) { 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 if(fi.Length == dirEntry.SizeOrCount && Util.ValidateFileChecksums(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(); } NodesToDownload.Add(x); } if ( Config.DownloadManifestOnly ) { File.WriteAllText( txtManifest, manifestBuilder.ToString() ); return; } session = GetSteam2StorageSession(contentServers, csClient, depotId, depotVersion); if(session == null) return; using ( session ) { Console.WriteLine("Downloading selected files."); for ( int x = 0 ; x < NodesToDownload.Count ; ++x ) { var dirEntry = manifest.Nodes[ NodesToDownload[ x ] ]; string downloadPath = Path.Combine( installDir, dirEntry.FullName.ToLower() ); float perc = ( ( float )x / ( float )NodesToDownload.Count ) * 100.0f; Console.WriteLine("{0,6:#00.00}%\t{1}", perc, downloadPath); var file = session.DownloadFile( dirEntry, ContentServerClient.StorageSession.DownloadPriority.High, cryptKey ); File.WriteAllBytes( downloadPath, file ); } } csClient.Disconnect(); }
internal PackageSession( ContentServerClient cli, uint cellId ) { this.client = cli; this.CellID = cellId; }
internal StorageSession( ContentServerClient cli, uint depotId, uint depotVersion, Credentials credentials ) { this.DepotID = depotId; this.DepotVersion = depotVersion; this.client = cli; bool bRet = false; if ( credentials == null ) { bRet = this.SendCommand( 9, // open storage ConnectionID, MessageID, depotId, depotVersion ); } else { byte[] serverTgt = credentials.Steam2Ticket.Entries[ 14 ].Data; // god help this never change bRet = this.SendCommand( 10, // open storage with login ConnectionID, MessageID, depotId, depotVersion, ( ushort )serverTgt.Length, serverTgt, NetHelpers.EndianSwap( credentials.SessionToken ), ( byte )credentials.AppTicket.Length, credentials.AppTicket ); } // the server sends us back the connection and message ids // the client probably performs a sanity check? uint connId = NetHelpers.EndianSwap( this.Socket.Reader.ReadUInt32() ); uint msgId = NetHelpers.EndianSwap( this.Socket.Reader.ReadUInt32() ); byte hasDepot = this.Socket.Reader.ReadByte(); // the server gives us 0x1 if the depot doesn't exist or requires authentication if ( hasDepot != 0 ) throw new Steam2Exception( "Content server does not have depot, or valid credentials were not given" ); StorageID = NetHelpers.EndianSwap( this.Socket.Reader.ReadUInt32() ); uint storageChecksum = NetHelpers.EndianSwap( this.Socket.Reader.ReadUInt32() ); this.ConnectionID++; }
internal PackageSession(ContentServerClient cli, uint cellId) { this.client = cli; this.CellID = cellId; }