Skip to content

Commit bde16e5

Browse files
committed
feat: WebDavStorage
1 parent 32e9a2a commit bde16e5

File tree

6 files changed

+317
-15
lines changed

6 files changed

+317
-15
lines changed

CSharp-OpenBMCLAPI/Modules/Cluster.cs

+14-12
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public Cluster(ClusterRequiredData requiredData) : base()
6161
client = HttpRequest.client;
6262
client.DefaultRequestHeaders.Authorization = new("Bearer", requiredData.Token?.Token.token);
6363

64-
this.storage = new CachedStorage(new FileStorage(ClusterRequiredData.Config.clusterFileDirectory));
64+
this.storage = new WebDavStorage();//new CachedStorage(new FileStorage(ClusterRequiredData.Config.clusterFileDirectory));
6565
this.files = new List<ApiFileInfo>();
6666
this.counter = new();
6767
InitializeSocket();
@@ -119,6 +119,8 @@ protected async Task<int> AsyncRun()
119119
{
120120
int returns = 0;
121121

122+
this.storage.Initialize();
123+
122124
// 检查文件
123125
// if (!ClusterRequiredData.Config.noEnable)
124126
Connect();
@@ -136,8 +138,8 @@ protected async Task<int> AsyncRun()
136138

137139
while (!ClusterRequiredData.Config.noEnable)
138140
{
139-
if (File.Exists(Path.Combine(ClusterRequiredData.Config.clusterFileDirectory, $"certifications/key.pem")) &&
140-
File.Exists(Path.Combine(ClusterRequiredData.Config.clusterFileDirectory, $"certifications/cert.pem")))
141+
if (File.Exists(Path.Combine(ClusterRequiredData.Config.clusterWorkingDirectory, $"certifications/key.pem")) &&
142+
File.Exists(Path.Combine(ClusterRequiredData.Config.clusterWorkingDirectory, $"certifications/cert.pem")))
141143
{
142144
break;
143145
}
@@ -255,12 +257,12 @@ private void InitializeService()
255257
/// </returns>
256258
protected X509Certificate2 LoadAndConvertCert()
257259
{
258-
X509Certificate2 cert = X509Certificate2.CreateFromPemFile(Path.Combine(ClusterRequiredData.Config.clusterFileDirectory, $"certifications/cert.pem"),
259-
Path.Combine(ClusterRequiredData.Config.clusterFileDirectory, $"certifications/key.pem"));
260+
X509Certificate2 cert = X509Certificate2.CreateFromPemFile(Path.Combine(ClusterRequiredData.Config.clusterWorkingDirectory, $"certifications/cert.pem"),
261+
Path.Combine(ClusterRequiredData.Config.clusterWorkingDirectory, $"certifications/key.pem"));
260262
//return cert;
261263
byte[] pfxCert = cert.Export(X509ContentType.Pfx);
262264
Logger.Instance.LogDebug($"将 PEM 格式的证书转换为 PFX 格式");
263-
using (var file = File.Create(Path.Combine(ClusterRequiredData.Config.clusterFileDirectory, $"certifications/cert.pfx")))
265+
using (var file = File.Create(Path.Combine(ClusterRequiredData.Config.clusterWorkingDirectory, $"certifications/cert.pfx")))
264266
{
265267
file.Write(pfxCert);
266268
}
@@ -423,16 +425,16 @@ protected async Task CheckFiles(bool skipCheck, FileVerificationMode mode)
423425
object countLock = new();
424426
int count = 0;
425427

426-
Parallel.ForEach(files, file =>
427-
//foreach (var file in files)
428+
//Parallel.ForEach(files, file =>
429+
foreach (var file in files)
428430
{
429431
CheckSingleFile(file);
430432
lock (countLock)
431433
{
432434
count++;
433435
}
434436
Logger.Instance.LogInfoNoNewLine($"\r{count}/{files.Count}");
435-
});
437+
}//);
436438

437439
files = null!;
438440
countLock = null!;
@@ -614,10 +616,10 @@ await socket.EmitAsync("request-cert", (SocketIOResponse resp) =>
614616
string? certString = cert.GetString();
615617
string? keyString = key.GetString();
616618

617-
string certPath = Path.Combine(ClusterRequiredData.Config.clusterFileDirectory, $"certifications/cert.pem");
618-
string keyPath = Path.Combine(ClusterRequiredData.Config.clusterFileDirectory, $"certifications/key.pem");
619+
string certPath = Path.Combine(ClusterRequiredData.Config.clusterWorkingDirectory, $"certifications/cert.pem");
620+
string keyPath = Path.Combine(ClusterRequiredData.Config.clusterWorkingDirectory, $"certifications/key.pem");
619621

620-
Directory.CreateDirectory(Path.Combine(ClusterRequiredData.Config.clusterFileDirectory, $"certifications"));
622+
Directory.CreateDirectory(Path.Combine(ClusterRequiredData.Config.clusterWorkingDirectory, $"certifications"));
621623

622624
using (var file = File.Create(certPath))
623625
{

CSharp-OpenBMCLAPI/Modules/Config.cs

+6-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ [注] 当此项启用时,"startupCheckMode"无效
3131
[YamlMember(Description = "指示应该将要服务的文件放在哪里(服务路径)", Order = 1)]
3232
public string clusterFileDirectory;
3333

34+
[YamlMember(Description = "指示节点的工作路径", Order = 1)]
35+
public string clusterWorkingDirectory;
36+
3437
[YamlIgnore]
3538
[YamlMember(Description = "指示节点端的版本,不应由用户更改")]
3639
public string clusterVersion;
@@ -58,7 +61,7 @@ [注] 当此项启用时,"startupCheckMode"无效
5861
internal double maxCachedMemory;
5962

6063
[YamlIgnore]
61-
public string cacheDirectory { get => Path.Combine(this.clusterFileDirectory, "cache"); }
64+
public string cacheDirectory { get => Path.Combine(this.clusterWorkingDirectory, "cache"); }
6265

6366
[YamlMember(Description = "指示登录存储池需要的凭据,如果存储池不需要则可以忽略", Order = 1)]
6467
public StorageUser storageUser;
@@ -72,7 +75,8 @@ public Config()
7275
this.skipCheck = false;
7376

7477
this.refreshTokenTime = 1800000;
75-
this.clusterFileDirectory = "./";
78+
this.clusterWorkingDirectory = "./";
79+
this.clusterWorkingDirectory = "./";
7680
this.clusterVersion = "1.10.4";
7781

7882
this.HOST = "";

CSharp-OpenBMCLAPI/Modules/HttpServiceProvider.cs

+7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using CSharpOpenBMCLAPI.Modules.WebServer;
44
using Newtonsoft.Json;
55
using System.Diagnostics;
6+
using System.Runtime.CompilerServices;
67
using System.Security.Cryptography.X509Certificates;
78
using System.Text;
89
using TeraIO.Extension;
@@ -78,6 +79,12 @@ public static async Task<FileAccessInfo> DownloadHash(HttpContext context, Clust
7879

7980
bool valid = Utils.CheckSign(hash, cluster.clusterInfo.ClusterSecret, s, e);
8081

82+
if (!context.Request.Header["user-agent"].Contains("got") && !context.Request.Header["user-agent"].Contains("bmclapi"))
83+
{
84+
context.Response.StatusCode = 500;
85+
return new FileAccessInfo { hits = 0, bytes = 0 };
86+
}
87+
8188
if (valid && hash != null && s != null && e != null)
8289
{
8390
long from, to;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
using CSharpOpenBMCLAPI.Modules.WebServer;
2+
using Newtonsoft.Json;
3+
using System;
4+
using TeraIO.Network.WebDav;
5+
6+
namespace CSharpOpenBMCLAPI.Modules.Storage
7+
{
8+
public class WebDavStorage : IStorage
9+
{
10+
protected WebDavClient client;
11+
protected string baseAddr;
12+
private object writeLock;
13+
protected StorageUser user;
14+
15+
public WebDavStorage()
16+
{
17+
this.client = new(ClusterRequiredData.Config.clusterFileDirectory);
18+
this.baseAddr = "BMCLAPI/cache";
19+
this.writeLock = new object();
20+
this.user = ClusterRequiredData.Config.storageUser;
21+
}
22+
23+
public bool Exists(string hashPath)
24+
{
25+
return this.client.Exists(GetAbsolutePath(hashPath)).Result;
26+
}
27+
28+
public void GarbageCollect(IEnumerable<ApiFileInfo> files)
29+
{
30+
var remoteFileHashes = this.client.ListFilesAndFolders(this.baseAddr).Result.Select(f => f.Split('/').Last());
31+
var fileHashes = files.Select(f => f.hash);
32+
foreach (var item in remoteFileHashes)
33+
{
34+
if (!fileHashes.Contains(item))
35+
{
36+
this.client.Delete(item).Wait();
37+
Logger.Instance.LogDebug($"Expired file {item} deleted.");
38+
}
39+
}
40+
}
41+
42+
public string GetAbsolutePath(string path)
43+
{
44+
return Path.Combine(baseAddr, path);
45+
}
46+
47+
public long GetFileSize(string hashPath)
48+
{
49+
return this.client.GetFileSize(GetAbsolutePath(hashPath)).Result;
50+
}
51+
52+
public IEnumerable<ApiFileInfo> GetMissingFiles(IEnumerable<ApiFileInfo> files)
53+
{
54+
var remoteFileHashes = this.client.ListFilesAndFolders(this.baseAddr).Result.Select(f => f.Split('/').Last());
55+
foreach (var item in files)
56+
{
57+
if (!remoteFileHashes.Contains(item.hash))
58+
{
59+
yield return item;
60+
}
61+
}
62+
}
63+
64+
public async Task<FileAccessInfo> HandleRequest(string hashPath, HttpContext context)
65+
{
66+
string file = GetAbsolutePath(hashPath);
67+
context.Response.StatusCode = 302;
68+
context.Response.Header["Location"] = this.client.GetFileDownloadLink(file);
69+
await context.Response.WriteAsync(Array.Empty<byte>());
70+
return new FileAccessInfo
71+
{
72+
hits = 1,
73+
bytes = this.GetFileSize(file)
74+
};
75+
}
76+
77+
public void Initialize()
78+
{
79+
this.client.SetUser(this.user.UserName, this.user.Password);
80+
}
81+
82+
public byte[] ReadFile(string hashPath)
83+
{
84+
return this.client.GetFile(GetAbsolutePath(hashPath)).Result;
85+
}
86+
87+
public Stream ReadFileStream(string hashPath)
88+
{
89+
return this.client.GetFileStream(GetAbsolutePath(hashPath)).Result;
90+
}
91+
92+
public void WriteFile(string hashPath, byte[] buffer)
93+
{
94+
lock (writeLock) // 由于多线程会炸所以加一个互斥锁
95+
{
96+
this.client.Delete(GetAbsolutePath(hashPath)).Wait();
97+
this.client.Lock(GetAbsolutePath(hashPath)).Wait();
98+
this.client.PutFile(GetAbsolutePath(hashPath), buffer).Wait();
99+
this.client.Unlock(GetAbsolutePath(hashPath)).Wait();
100+
}
101+
}
102+
103+
public void WriteFileStream(string hashPath, Stream stream)
104+
{
105+
lock (writeLock) // 由于多线程会炸所以加一个互斥锁
106+
{
107+
this.client.Delete(GetAbsolutePath(hashPath)).Wait();
108+
this.client.Lock(GetAbsolutePath(hashPath)).Wait();
109+
this.client.PutFile(GetAbsolutePath(hashPath), stream).Wait();
110+
this.client.Unlock(GetAbsolutePath(hashPath)).Wait();
111+
}
112+
}
113+
}
114+
}

0 commit comments

Comments
 (0)