public void DownloadFile(string remoteFileName, string localFileName) { if (string.IsNullOrEmpty(localFileName)) { localFileName = Path.GetFileName(remoteFileName.Replace("\\", "/")); } if (string.IsNullOrEmpty(localFileName)) { return; } var completeFilePath = Path.Combine(Scanner.Configuration.Proxy.MirrorRoot, VersionName, localFileName); var fileDirectory = Path.GetDirectoryName(completeFilePath); if (string.IsNullOrEmpty(fileDirectory)) { return; } if (!Directory.CreateDirectory(fileDirectory).Exists) { return; } if (File.Exists(completeFilePath)) { return; } var fileEntry = GetEntry(remoteFileName); if (fileEntry == null) { return; } using (var blte = new BLTE(CDN.Hosts[0])) { if (fileEntry.ArchiveIndex != -1) { blte.AddHeader("Range", $"bytes={fileEntry.Offset}-{fileEntry.Offset + fileEntry.Size - 1}"); } var archiveName = fileEntry.Hash.ToHexString(); if (fileEntry.ArchiveIndex != -1) { archiveName = Indices.Archives[fileEntry.ArchiveIndex].ToHexString(); } blte.Send($"/{CDN.Path}/data/{archiveName.Substring(0, 2)}/{archiveName.Substring(2, 2)}/{archiveName}"); Scanner.WriteLine($"[{VersionName}] Downloading {localFileName} from {blte.URL} ..."); using (var fileStream = File.OpenWrite(completeFilePath)) blte.PipeTo(fileStream); } }
private static void Process(HttpListenerContext context) { var tokens = context.Request.Url.AbsolutePath.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length == 0) { WriteError(context, "Badly formatted request.", HttpStatusCode.BadRequest); return; } var buildName = tokens[0]; var fileHash = ulong.Parse(tokens[1]); var fileName = tokens[2]; var buildInfo = RemoteBuildManager.GetBuild(buildName); if (buildInfo == null) { WriteError(context, "Unknown build.", HttpStatusCode.BadRequest); return; } var fileEntry = buildInfo.GetEntry(fileHash); if (fileEntry == null) { WriteError(context, "This build is currently loading. Try again later.", HttpStatusCode.BadRequest); return; } try { using (var blte = new BLTE(buildInfo.CDN.Hosts[0])) { if (fileEntry.ArchiveIndex != -1) { blte.AddHeader("Range", $"bytes={fileEntry.Offset}-{fileEntry.Offset + fileEntry.Size - 1}"); } var archiveName = fileEntry.Hash.ToHexString(); if (fileEntry.ArchiveIndex != -1) { archiveName = buildInfo.Indices.Archives[fileEntry.ArchiveIndex].ToHexString(); } blte.Send($"/{buildInfo.CDN.Path}/data/{archiveName.Substring(0, 2)}/{archiveName.Substring(2, 2)}/{archiveName}"); Scanner.WriteLine($"[PROXY] Serving {fileName} through {blte.URL}."); if (!blte.Failed) { context.Response.ContentType = "application/octet-stream"; context.Response.ContentLength64 = blte.DecompressedLength; context.Response.AddHeader("Date", blte.ResponseHeaders.Get("Date")); context.Response.AddHeader("ETag", blte.ResponseHeaders.Get("ETag")); context.Response.AddHeader("Last-Modified", DateTime.Now.ToString("r")); context.Response.AddHeader("Connection", "Keep-Alive"); context.Response.StatusCode = (int)HttpStatusCode.OK; Scanner.WriteLine($"[PROXY] Serving {fileName} to {context.Request.RemoteEndPoint} - {archiveName}"); blte.PipeTo(context.Response.OutputStream); } else { var sBuilder = new StringBuilder(); sBuilder.AppendLine($"File {fileName} cannot be downloaded - it might be an encrypted archive..."); sBuilder.AppendLine(); sBuilder.AppendLine($"Requested archive: {blte.URL}"); if (fileEntry.ArchiveIndex != -1) { sBuilder.AppendLine($"Range: {fileEntry.Offset}-{fileEntry.Offset + fileEntry.Size - 1}"); } WriteError(context, sBuilder.ToString(), HttpStatusCode.InternalServerError); } } } catch (IOException ioe) { Scanner.WriteLine("[PROXY] Remote client closed the connection."); } catch (Exception e) { Scanner.WriteLine(e.ToString()); WriteError(context, e.ToString(), HttpStatusCode.InternalServerError); } }