async Task <DepotChunk> DownloadDepotChunkCoreAsync(uint depotId, DepotManifest.ChunkData chunk, Server server, string cdnAuthToken, byte[] depotKey) { var chunkID = Utils.EncodeHexString(chunk.ChunkID); var chunkData = await DoRawCommandAsync(server, HttpMethod.Get, "depot", doAuth : true, args : string.Format("{0}/chunk/{1}", depotId, chunkID), authtoken : cdnAuthToken).ConfigureAwait(false); // assert that lengths match only if the chunk has a length assigned. if (chunk.CompressedLength != default(uint) && chunkData.Length != chunk.CompressedLength) { throw new InvalidDataException($"Length mismatch after downloading depot chunk! (was {chunkData.Length}, but should be {chunk.CompressedLength})"); } var depotChunk = new DepotChunk { ChunkInfo = chunk, Data = chunkData, }; if (depotKey != null) { // if we have the depot key, we can process the chunk immediately depotChunk.Process(depotKey); } return(depotChunk); }
/// <summary> /// Downloads the specified depot chunk, and optionally processes the chunk and verifies the checksum if the depot decryption key has been provided. /// </summary> /// <remarks> /// This function will also validate the length of the downloaded chunk with the value of <see cref="DepotManifest.ChunkData.CompressedLength"/>, /// if it has been assigned a value. /// </remarks> /// <param name="chunk"> /// A <see cref="DepotManifest.ChunkData"/> instance that represents the chunk to download. /// This value should come from a manifest downloaded with <see cref="CDNClient.DownloadManifest"/>. /// </param> /// <returns>A <see cref="DepotChunk"/> instance that contains the data for the given chunk.</returns> /// <exception cref="System.ArgumentNullException">chunk's <see cref="DepotManifest.ChunkData.ChunkID"/> was null.</exception> public DepotChunk DownloadDepotChunk(DepotManifest.ChunkData chunk) { if (chunk.ChunkID == null) { throw new ArgumentNullException("chunk.ChunkID"); } string chunkId = Utils.EncodeHexString(chunk.ChunkID); byte[] chunkData = DoRawCommand(connectedServer, "depot", doAuth: true, args: string.Format("{0}/chunk/{1}", depotId, chunkId)); if (chunk.CompressedLength != default(uint)) { // assert that lengths match only if the chunk has a length assigned. DebugLog.Assert(chunkData.Length == chunk.CompressedLength, "CDNClient", "Length mismatch after downloading depot chunk!"); } var depotChunk = new DepotChunk { ChunkInfo = chunk, Data = chunkData, }; if (depotKey != null) { // if we have the depot key, we can process the chunk immediately depotChunk.Process(depotKey); } return(depotChunk); }
DepotChunk DownloadDepotChunkCore(uint depotId, DepotManifest.ChunkData chunk, Server server, string cdnAuthToken, byte[] depotKey) { var chunkID = Utils.EncodeHexString(chunk.ChunkID); byte[] chunkData = DoRawCommand(server, "depot", doAuth: true, args: string.Format("{0}/chunk/{1}", depotId, chunkID), authtoken: cdnAuthToken); if (chunk.CompressedLength != default(uint)) { // assert that lengths match only if the chunk has a length assigned. DebugLog.Assert(chunkData.Length == chunk.CompressedLength, "CDNClient", "Length mismatch after downloading depot chunk!"); } var depotChunk = new DepotChunk { ChunkInfo = chunk, Data = chunkData, }; if (depotKey != null) { // if we have the depot key, we can process the chunk immediately depotChunk.Process(depotKey); } return(depotChunk); }
/// <summary> /// Downloads the specified depot chunk as a stream, does not processes the chunk and verifies the checksum if the depot decryption key has been provided yet. /// </summary> /// <remarks> /// This function will also validate the length of the downloaded chunk with the value of <see cref="DepotManifest.ChunkData.CompressedLength"/>, /// if it has been assigned a value. /// </remarks> /// <param name="depotId">The id of the depot being accessed.</param> /// <param name="chunk"> /// A <see cref="DepotManifest.ChunkData"/> instance that represents the chunk to download. /// This value should come from a manifest downloaded with <see cref="o:DownloadManifestAsync"/>. /// </param> /// <returns>A <see cref="DepotChunk"/> instance that contains the data for the given chunk.</returns> /// <param name="server">The content server to connect to.</param> /// <param name="cdnAuthToken">CDN auth token for CDN content server endpoints.</param> /// <param name="depotKey"> /// The depot decryption key for the depot that will be downloaded. /// This is used for decrypting filenames (if needed) in depot manifests, and processing depot chunks. /// </param> /// <exception cref="System.ArgumentNullException">chunk's <see cref="DepotManifest.ChunkData.ChunkID"/> was null.</exception> /// <exception cref="System.IO.InvalidDataException">Thrown if the downloaded data does not match the expected length.</exception> /// <exception cref="HttpRequestException">An network error occurred when performing the request.</exception> /// <exception cref="SteamKitWebRequestException">A network error occurred when performing the request.</exception> public async Task <DepotChunk> DownloadDepotChunkAsStreamAsync(uint depotId, DepotManifest.ChunkData chunk, Server server, string cdnAuthToken, byte[] depotKey) { if (server == null) { throw new ArgumentNullException(nameof(server)); } if (chunk == null) { throw new ArgumentNullException(nameof(chunk)); } if (chunk.ChunkID == null) { throw new ArgumentException("Chunk must have a ChunkID.", nameof(chunk)); } var chunkID = Utils.EncodeHexString(chunk.ChunkID); Stream stream = await DoRawCommandAsStreamAsync(server, HttpMethod.Get, "depot", doAuth : true, args : string.Format("{0}/chunk/{1}", depotId, chunkID), authtoken : cdnAuthToken).ConfigureAwait(false); long fullStreamLength = 0; //using ( stream ) //{ while (stream.ReadByte() > -1) { fullStreamLength++; } stream.Position = 0; //} // assert that lengths match only if the chunk has a length assigned. if (chunk.CompressedLength != default(uint) && fullStreamLength != chunk.CompressedLength) { throw new InvalidDataException($"Length mismatch after downloading depot chunk! (was {fullStreamLength}, but should be {chunk.CompressedLength})"); } var depotChunk = new DepotChunk { ChunkInfo = chunk, //Data = chunkData, DataStream = stream, }; //I'll need to do some extra work to process the stream with the depot key. Will come back to this later. if (depotKey != null) { // if we have the depot key, we can process the chunk immediately depotChunk.Process(depotKey); } return(depotChunk); }
/// <summary> /// Downloads the specified depot chunk, and optionally processes the chunk and verifies the checksum if the depot decryption key has been provided. /// </summary> /// <param name="chunk"> /// A <see cref="DepotManifest.ChunkData"/> instance that represents the chunk to download. /// This value should come from a manifest downloaded with <see cref="CDNClient.DownloadManifest"/>. /// </param> /// <returns>A <see cref="DepotChunk"/> instance that contains the data for the given chunk.</returns> public DepotChunk DownloadDepotChunk(DepotManifest.ChunkData chunk) { string chunkId = Utils.EncodeHexString(chunk.ChunkID); byte[] chunkData = DoRawCommand(connectedServer, "depot", doAuth: true, args: string.Format("{0}/chunk/{1}", depotId, chunkId)); DebugLog.Assert(chunkData.Length == chunk.CompressedLength, "CDNClient", "Length mismatch after downloading depot chunk!"); var depotChunk = new DepotChunk { ChunkInfo = chunk, Data = chunkData, }; if (depotKey != null) { // if we have the depot key, we can process the chunk immediately depotChunk.Process(depotKey); } return(depotChunk); }
/// <summary> /// Downloads the specified depot chunk, and optionally processes the chunk and verifies the checksum if the depot decryption key has been provided. /// </summary> /// <remarks> /// This function will also validate the length of the downloaded chunk with the value of <see cref="DepotManifest.ChunkData.CompressedLength"/>, /// if it has been assigned a value. /// </remarks> /// <param name="depotId">The id of the depot being accessed.</param> /// <param name="chunk"> /// A <see cref="DepotManifest.ChunkData"/> instance that represents the chunk to download. /// This value should come from a manifest downloaded with <see cref="o:DownloadManifestAsync"/>. /// </param> /// <returns>A <see cref="DepotChunk"/> instance that contains the data for the given chunk.</returns> /// <param name="server">The content server to connect to.</param> /// <param name="cdnAuthToken">CDN auth token for CDN content server endpoints.</param> /// <param name="depotKey"> /// The depot decryption key for the depot that will be downloaded. /// This is used for decrypting filenames (if needed) in depot manifests, and processing depot chunks. /// </param> /// <param name="proxyServer">Optional content server marked as UseAsProxy which transforms the request.</param> /// <exception cref="System.ArgumentNullException">chunk's <see cref="DepotManifest.ChunkData.ChunkID"/> was null.</exception> /// <exception cref="System.IO.InvalidDataException">Thrown if the downloaded data does not match the expected length.</exception> /// <exception cref="HttpRequestException">An network error occurred when performing the request.</exception> /// <exception cref="SteamKitWebRequestException">A network error occurred when performing the request.</exception> public async Task <DepotChunk> DownloadDepotChunkAsync(uint depotId, DepotManifest.ChunkData chunk, Server server, string?cdnAuthToken, byte[]?depotKey, Server?proxyServer = null) { if (server == null) { throw new ArgumentNullException(nameof(server)); } if (chunk == null) { throw new ArgumentNullException(nameof(chunk)); } if (chunk.ChunkID == null) { throw new ArgumentException("Chunk must have a ChunkID.", nameof(chunk)); } var chunkID = Utils.EncodeHexString(chunk.ChunkID); var chunkData = await DoRawCommandAsync(server, string.Format("depot/{0}/chunk/{1}", depotId, chunkID), cdnAuthToken, proxyServer).ConfigureAwait(false); // assert that lengths match only if the chunk has a length assigned. if (chunk.CompressedLength != default(uint) && chunkData.Length != chunk.CompressedLength) { throw new InvalidDataException($"Length mismatch after downloading depot chunk! (was {chunkData.Length}, but should be {chunk.CompressedLength})"); } var depotChunk = new DepotChunk(chunk, chunkData); if (depotKey != null) { // if we have the depot key, we can process the chunk immediately depotChunk.Process(depotKey); } return(depotChunk); }
/// <summary> /// Downloads the specified depot chunk, and optionally processes the chunk and verifies the checksum if the depot decryption key has been provided. /// </summary> /// <param name="chunk"> /// A <see cref="DepotManifest.ChunkData"/> instance that represents the chunk to download. /// This value should come from a manifest downloaded with <see cref="CDNClient.DownloadManifest"/>. /// </param> /// <returns>A <see cref="DepotChunk"/> instance that contains the data for the given chunk.</returns> public DepotChunk DownloadDepotChunk( DepotManifest.ChunkData chunk ) { string chunkId = Utils.EncodeHexString( chunk.ChunkID ); byte[] chunkData = DoRawCommand( connectedServer, "depot", doAuth: true, args: string.Format( "{0}/chunk/{1}", depotId, chunkId ) ); DebugLog.Assert( chunkData.Length == chunk.CompressedLength, "CDNClient", "Length mismatch after downloading depot chunk!" ); var depotChunk = new DepotChunk { ChunkInfo = chunk, Data = chunkData, }; if ( depotKey != null ) { // if we have the depot key, we can process the chunk immediately depotChunk.Process( depotKey ); } return depotChunk; }
DepotChunk DownloadDepotChunkCore( uint depotId, DepotManifest.ChunkData chunk, Server server, string cdnAuthToken, byte[] depotKey ) { var chunkID = Utils.EncodeHexString( chunk.ChunkID ); byte[] chunkData = DoRawCommand( server, "depot", doAuth: true, args: string.Format( "{0}/chunk/{1}", depotId, chunkID ), authtoken: cdnAuthToken ); if ( chunk.CompressedLength != default( uint ) ) { // assert that lengths match only if the chunk has a length assigned. DebugLog.Assert( chunkData.Length == chunk.CompressedLength, "CDNClient", "Length mismatch after downloading depot chunk!" ); } var depotChunk = new DepotChunk { ChunkInfo = chunk, Data = chunkData, }; if ( depotKey != null ) { // if we have the depot key, we can process the chunk immediately depotChunk.Process( depotKey ); } return depotChunk; }
/// <summary> /// Downloads the specified depot chunk, and optionally processes the chunk and verifies the checksum if the depot decryption key has been provided. /// </summary> /// <remarks> /// This function will also validate the length of the downloaded chunk with the value of <see cref="DepotManifest.ChunkData.CompressedLength"/>, /// if it has been assigned a value. /// </remarks> /// <param name="depotId">The id of the depot being accessed.</param> /// <param name="chunk"> /// A <see cref="DepotManifest.ChunkData"/> instance that represents the chunk to download. /// This value should come from a manifest downloaded with <see cref="CDNClient.DownloadManifest"/>. /// </param> /// <returns>A <see cref="DepotChunk"/> instance that contains the data for the given chunk.</returns> /// <exception cref="System.ArgumentNullException">chunk's <see cref="DepotManifest.ChunkData.ChunkID"/> was null.</exception> public DepotChunk DownloadDepotChunk( uint depotId, DepotManifest.ChunkData chunk ) { if ( chunk.ChunkID == null ) throw new ArgumentNullException( "chunk.ChunkID" ); string chunkId = Utils.EncodeHexString( chunk.ChunkID ); string cdnToken = null; depotCdnAuthKeys.TryGetValue(depotId, out cdnToken); byte[] chunkData = DoRawCommand( connectedServer, "depot", doAuth: true, args: string.Format( "{0}/chunk/{1}", depotId, chunkId ), authtoken: cdnToken ); if ( chunk.CompressedLength != default( uint ) ) { // assert that lengths match only if the chunk has a length assigned. DebugLog.Assert( chunkData.Length == chunk.CompressedLength, "CDNClient", "Length mismatch after downloading depot chunk!" ); } var depotChunk = new DepotChunk { ChunkInfo = chunk, Data = chunkData, }; byte[] depotKey; if ( depotKeys.TryGetValue( depotId, out depotKey ) ) { // if we have the depot key, we can process the chunk immediately depotChunk.Process( depotKey ); } return depotChunk; }