| @@ -120,9 +120,9 @@ public sealed class FileCacheManager : IDisposable | |||||||
|  |  | ||||||
|     public List<FileCacheEntity> GetAllFileCaches() => _fileCaches.Values.SelectMany(v => v).ToList(); |     public List<FileCacheEntity> GetAllFileCaches() => _fileCaches.Values.SelectMany(v => v).ToList(); | ||||||
|  |  | ||||||
|     public string GetCacheFilePath(string hash, string extension, bool isTemporaryFile) |     public string GetCacheFilePath(string hash, string extension) | ||||||
|     { |     { | ||||||
|         return Path.Combine(_configService.Current.CacheFolder, hash + "." + extension + (isTemporaryFile ? ".tmp" : string.Empty)); |         return Path.Combine(_configService.Current.CacheFolder, hash + "." + extension); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public FileCacheEntity? GetFileCacheByHash(string hash) |     public FileCacheEntity? GetFileCacheByHash(string hash) | ||||||
|   | |||||||
| @@ -77,17 +77,35 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase | |||||||
|         base.Dispose(disposing); |         base.Dispose(disposing); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private static byte MungeByte(int byteOrEof) | ||||||
|  |     { | ||||||
|  |         if (byteOrEof == -1) | ||||||
|  |         { | ||||||
|  |             throw new EndOfStreamException(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return (byte)(byteOrEof ^ 42); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static void MungeBuffer(Span<byte> buffer) | ||||||
|  |     { | ||||||
|  |         for (int i = 0; i < buffer.Length; ++i) | ||||||
|  |         { | ||||||
|  |             buffer[i] ^= 42; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private static (string fileHash, long fileLengthBytes) ReadBlockFileHeader(FileStream fileBlockStream) |     private static (string fileHash, long fileLengthBytes) ReadBlockFileHeader(FileStream fileBlockStream) | ||||||
|     { |     { | ||||||
|         List<char> hashName = new(); |         List<char> hashName = new(); | ||||||
|         List<char> fileLength = new(); |         List<char> fileLength = new(); | ||||||
|         var separator = (char)fileBlockStream.ReadByte(); |         var separator = (char)MungeByte(fileBlockStream.ReadByte()); | ||||||
|         if (separator != '#') throw new InvalidDataException("Data is invalid, first char is not #"); |         if (separator != '#') throw new InvalidDataException("Data is invalid, first char is not #"); | ||||||
|  |  | ||||||
|         bool readHash = false; |         bool readHash = false; | ||||||
|         while (true) |         while (true) | ||||||
|         { |         { | ||||||
|             var readChar = (char)fileBlockStream.ReadByte(); |             var readChar = (char)MungeByte(fileBlockStream.ReadByte()); | ||||||
|             if (readChar == ':') |             if (readChar == ':') | ||||||
|             { |             { | ||||||
|                 readHash = true; |                 readHash = true; | ||||||
| @@ -100,7 +118,7 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase | |||||||
|         return (string.Join("", hashName), long.Parse(string.Join("", fileLength))); |         return (string.Join("", hashName), long.Parse(string.Join("", fileLength))); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private async Task DownloadFileHttpClient(string downloadGroup, Guid requestId, List<DownloadFileTransfer> fileTransfer, string tempPath, IProgress<long> progress, CancellationToken ct) |     private async Task DownloadAndMungeFileHttpClient(string downloadGroup, Guid requestId, List<DownloadFileTransfer> fileTransfer, string tempPath, IProgress<long> progress, CancellationToken ct) | ||||||
|     { |     { | ||||||
|         Logger.LogDebug("GUID {requestId} on server {uri} for files {files}", requestId, fileTransfer[0].DownloadUri, string.Join(", ", fileTransfer.Select(c => c.Hash).ToList())); |         Logger.LogDebug("GUID {requestId} on server {uri} for files {files}", requestId, fileTransfer[0].DownloadUri, string.Join(", ", fileTransfer.Select(c => c.Hash).ToList())); | ||||||
|  |  | ||||||
| @@ -139,6 +157,8 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase | |||||||
|                 { |                 { | ||||||
|                     ct.ThrowIfCancellationRequested(); |                     ct.ThrowIfCancellationRequested(); | ||||||
|  |  | ||||||
|  |                     MungeBuffer(buffer.AsSpan(0, bytesRead)); | ||||||
|  |  | ||||||
|                     await fileStream.WriteAsync(buffer.AsMemory(0, bytesRead), ct).ConfigureAwait(false); |                     await fileStream.WriteAsync(buffer.AsMemory(0, bytesRead), ct).ConfigureAwait(false); | ||||||
|  |  | ||||||
|                     progress.Report(bytesRead); |                     progress.Report(bytesRead); | ||||||
| @@ -216,7 +236,7 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase | |||||||
|  |  | ||||||
|             Logger.LogDebug("GUID {requestId} for {n} files on server {uri}", requestId, fileGroup.Count(), fileGroup.First().DownloadUri); |             Logger.LogDebug("GUID {requestId} for {n} files on server {uri}", requestId, fileGroup.Count(), fileGroup.First().DownloadUri); | ||||||
|  |  | ||||||
|             var blockFile = _fileDbManager.GetCacheFilePath(requestId.ToString("N"), "blk", true); |             var blockFile = _fileDbManager.GetCacheFilePath(requestId.ToString("N"), "blk"); | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 _downloadStatus[fileGroup.Key].DownloadStatus = DownloadStatus.WaitingForSlot; |                 _downloadStatus[fileGroup.Key].DownloadStatus = DownloadStatus.WaitingForSlot; | ||||||
| @@ -234,7 +254,7 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase | |||||||
|                         Logger.LogWarning(ex, "Could not set download progress"); |                         Logger.LogWarning(ex, "Could not set download progress"); | ||||||
|                     } |                     } | ||||||
|                 }); |                 }); | ||||||
|                 await DownloadFileHttpClient(fileGroup.Key, requestId, fileGroup.ToList(), blockFile, progress, token).ConfigureAwait(false); |                 await DownloadAndMungeFileHttpClient(fileGroup.Key, requestId, fileGroup.ToList(), blockFile, progress, token).ConfigureAwait(false); | ||||||
|             } |             } | ||||||
|             catch (OperationCanceledException) |             catch (OperationCanceledException) | ||||||
|             { |             { | ||||||
| @@ -270,9 +290,10 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase | |||||||
|  |  | ||||||
|                         byte[] compressedFileContent = new byte[fileLengthBytes]; |                         byte[] compressedFileContent = new byte[fileLengthBytes]; | ||||||
|                         _ = await fileBlockStream.ReadAsync(compressedFileContent, token).ConfigureAwait(false); |                         _ = await fileBlockStream.ReadAsync(compressedFileContent, token).ConfigureAwait(false); | ||||||
|  |                         MungeBuffer(compressedFileContent); | ||||||
|  |  | ||||||
|                         var decompressedFile = LZ4Codec.Unwrap(compressedFileContent); |                         var decompressedFile = LZ4Codec.Unwrap(compressedFileContent); | ||||||
|                         var filePath = _fileDbManager.GetCacheFilePath(fileHash, fileExtension, false); |                         var filePath = _fileDbManager.GetCacheFilePath(fileHash, fileExtension); | ||||||
|                         await File.WriteAllBytesAsync(filePath, decompressedFile, token).ConfigureAwait(false); |                         await File.WriteAllBytesAsync(filePath, decompressedFile, token).ConfigureAwait(false); | ||||||
|  |  | ||||||
|                         PersistFileToStorage(fileHash, filePath); |                         PersistFileToStorage(fileHash, filePath); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 N. Lo
					N. Lo