-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBundleDlInterceptor.cs
More file actions
105 lines (88 loc) · 3.89 KB
/
BundleDlInterceptor.cs
File metadata and controls
105 lines (88 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using ReMod.Loader;
namespace ReMod.BundleVerifier
{
internal class BundleDlInterceptor
{
internal static volatile bool ShouldIntercept = false;
private static readonly ConcurrentDictionary<IntPtr, BundleDlContext> ourInterceptedContext = new();
[ThreadStatic] private static byte[] ourTransferBuffer;
internal static unsafe void CreateCachedPatchPostfix(IntPtr thisPtr, NativePatchUtils.NativeString* urlPtr)
{
if (ShouldIntercept)
{
var url = BundleDownloadMethods.ExtractString(urlPtr);
var cleanedUrl = BundleVerifierMod.SanitizeUrl(url);
if (BundleVerifierMod.ForceAllowedCache.Contains(url))
{
return;
}
ourInterceptedContext[thisPtr] = new BundleDlContext(thisPtr, url);
}
}
internal static int PreparePatch(IntPtr thisPtr)
{
if (ourInterceptedContext.TryGetValue(thisPtr, out var context) && context.IsBadUrl)
{
var cleanedUrl = BundleVerifierMod.SanitizeUrl(context.Url);
ReLogger.Msg($"Bundle for ptr {thisPtr} uid={cleanedUrl.Item1}+{cleanedUrl.Item2} is pre-marked as bad, faking failed download");
// indicate that it should use the DL stream
Marshal.WriteInt32(thisPtr + 0x90, 1);
// and then indicate the downloader that we don't want the download
return 1;
}
return BundleDownloadMethods.OriginalPrepare(thisPtr);
}
internal static IntPtr DestructorPatch(IntPtr thisPtr, long unk)
{
RemoveInterceptor(thisPtr);
return BundleDownloadMethods.OriginalDestructor(thisPtr, unk);
}
internal static void CancelIntercept(BundleDlContext context)
{
RemoveInterceptor(context.OriginalBundleDownload);
}
private static void RemoveInterceptor(IntPtr thisPtr)
{
if (ourInterceptedContext.TryRemove(thisPtr, out var removed))
removed.Dispose();
}
internal static unsafe int ReceivePatch(IntPtr thisPtr, IntPtr bytes, int byteCount)
{
if (!ourInterceptedContext.TryGetValue(thisPtr, out var intercepted))
return BundleDownloadMethods.OriginalReceiveBytes(thisPtr, bytes, byteCount);
if (!intercepted.PreProcessBytes())
{
RemoveInterceptor(thisPtr);
return BundleDownloadMethods.OriginalReceiveBytes(thisPtr, bytes, byteCount);
}
if (ourTransferBuffer == null || ourTransferBuffer.Length < byteCount)
ourTransferBuffer = new byte[byteCount];
Marshal.Copy(bytes, ourTransferBuffer, 0, byteCount);
var processedByteCount = intercepted.ProcessBytes(ourTransferBuffer, 0, byteCount);
var bundleOperationPtr = *(IntPtr*)(thisPtr + 0x80);
if (bundleOperationPtr != IntPtr.Zero)
{
*(long*)(thisPtr + 0x40) = intercepted.GetDownloadedSize();
*(float*)(bundleOperationPtr + 0x430) = intercepted.GetDownloadedSize() / (float)GetTotalSize(thisPtr);
}
return processedByteCount;
}
internal static unsafe int GetTotalSize(IntPtr thisPtr) => *(int*)(thisPtr + 0x48);
internal static void CompletePatch(IntPtr thisPtr)
{
if (ourInterceptedContext.TryGetValue(thisPtr, out var intercepted))
{
intercepted.CompleteDownload();
return;
}
BundleDownloadMethods.OriginalCompleteDownload(thisPtr);
}
}
}