Пример #1
0
        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);
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        /// <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);
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
        /// <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);
        }
Пример #7
0
        /// <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;
        }
Пример #8
0
        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;
        }
Пример #9
0
        /// <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;
        }