2020-05-09 22:16:16 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.IO.Compression;
|
2020-05-13 03:53:20 +00:00
|
|
|
|
using System.IO.MemoryMappedFiles;
|
2020-05-09 22:16:16 +00:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Wabbajack.Common;
|
|
|
|
|
using Wabbajack.Common.Serialization.Json;
|
|
|
|
|
using Wabbajack.Lib.AuthorApi;
|
|
|
|
|
using Wabbajack.Lib.Downloaders.UrlDownloaders;
|
|
|
|
|
using Wabbajack.Lib.Exceptions;
|
|
|
|
|
using Wabbajack.Lib.Validation;
|
|
|
|
|
|
|
|
|
|
namespace Wabbajack.Lib.Downloaders
|
|
|
|
|
{
|
2020-05-10 21:35:15 +00:00
|
|
|
|
public class WabbajackCDNDownloader : IDownloader, IUrlDownloader
|
2020-05-09 22:16:16 +00:00
|
|
|
|
{
|
|
|
|
|
public async Task<AbstractDownloadState?> GetDownloaderState(dynamic archiveINI, bool quickMode = false)
|
|
|
|
|
{
|
|
|
|
|
var url = (Uri)DownloaderUtils.GetDirectURL(archiveINI);
|
|
|
|
|
return url == null ? null : StateFromUrl(url);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task Prepare()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-10 21:35:15 +00:00
|
|
|
|
public AbstractDownloadState? GetDownloaderState(string url)
|
|
|
|
|
{
|
|
|
|
|
return StateFromUrl(new Uri(url));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-05-09 22:16:16 +00:00
|
|
|
|
public static AbstractDownloadState? StateFromUrl(Uri url)
|
|
|
|
|
{
|
|
|
|
|
if (url.Host == "wabbajacktest.b-cdn.net" || url.Host == "wabbajack.b-cdn.net")
|
|
|
|
|
{
|
|
|
|
|
return new State(url);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[JsonName("WabbajackCDNDownloader+State")]
|
|
|
|
|
public class State : AbstractDownloadState
|
|
|
|
|
{
|
|
|
|
|
public Uri Url { get; set; }
|
|
|
|
|
public State(Uri url)
|
|
|
|
|
{
|
|
|
|
|
Url = url;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override object[] PrimaryKey => new object[] {Url};
|
|
|
|
|
public override bool IsWhitelisted(ServerWhitelist whitelist)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task<bool> Download(Archive a, AbsolutePath destination)
|
|
|
|
|
{
|
2020-05-10 22:45:48 +00:00
|
|
|
|
destination.Parent.CreateDirectory();
|
2020-05-09 22:16:16 +00:00
|
|
|
|
var definition = await GetDefinition();
|
2020-05-13 03:53:20 +00:00
|
|
|
|
using var fs = destination.Create();
|
|
|
|
|
using var mmfile = MemoryMappedFile.CreateFromFile(fs, null, definition.Size, MemoryMappedFileAccess.ReadWrite, HandleInheritability.None, false);
|
2020-05-09 22:16:16 +00:00
|
|
|
|
var client = new Common.Http.Client();
|
2020-05-13 03:53:20 +00:00
|
|
|
|
using var queue = new WorkQueue();
|
|
|
|
|
await definition.Parts.PMap(queue, async part =>
|
2020-05-09 22:16:16 +00:00
|
|
|
|
{
|
2020-05-13 03:53:20 +00:00
|
|
|
|
Utils.Status($"Downloading {a.Name}", Percent.FactoryPutInRange(definition.Parts.Length - part.Index, definition.Parts.Length));
|
|
|
|
|
await using var ostream = mmfile.CreateViewStream(part.Offset, part.Size);
|
2020-05-09 22:16:16 +00:00
|
|
|
|
using var response = await client.GetAsync($"{Url}/parts/{part.Index}");
|
|
|
|
|
if (!response.IsSuccessStatusCode)
|
|
|
|
|
throw new HttpException((int)response.StatusCode, response.ReasonPhrase);
|
2020-05-13 03:53:20 +00:00
|
|
|
|
await response.Content.CopyToAsync(ostream);
|
2020-05-09 22:16:16 +00:00
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override async Task<bool> Verify(Archive archive)
|
|
|
|
|
{
|
|
|
|
|
var definition = await GetDefinition();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task<CDNFileDefinition> GetDefinition()
|
|
|
|
|
{
|
|
|
|
|
var client = new Common.Http.Client();
|
|
|
|
|
using var data = await client.GetAsync(Url + "/definition.json.gz");
|
|
|
|
|
await using var gz = new GZipStream(await data.Content.ReadAsStreamAsync(), CompressionMode.Decompress);
|
|
|
|
|
return gz.FromJson<CDNFileDefinition>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override IDownloader GetDownloader()
|
|
|
|
|
{
|
|
|
|
|
return DownloadDispatcher.GetInstance<WabbajackCDNDownloader>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string? GetManifestURL(Archive a)
|
|
|
|
|
{
|
|
|
|
|
return Url.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string[] GetMetaIni()
|
|
|
|
|
{
|
|
|
|
|
return new[] {"[General]", $"directURL={Url}"};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|