mirror of
https://github.com/gnh1201/welsonjs.git
synced 2025-05-07 12:16:04 +00:00
commit
46d0244c34
|
@ -5,6 +5,7 @@ using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -23,6 +24,7 @@ namespace WelsonJS.Launcher
|
||||||
private List<IResourceTool> _tools = new List<IResourceTool>();
|
private List<IResourceTool> _tools = new List<IResourceTool>();
|
||||||
private const int _blobTimeout = 5000;
|
private const int _blobTimeout = 5000;
|
||||||
private readonly HttpClient _blobClient = new HttpClient();
|
private readonly HttpClient _blobClient = new HttpClient();
|
||||||
|
private readonly string _defaultMimeType = "application/octet-stream";
|
||||||
|
|
||||||
public ResourceServer(string prefix, string resourceName)
|
public ResourceServer(string prefix, string resourceName)
|
||||||
{
|
{
|
||||||
|
@ -128,8 +130,28 @@ namespace WelsonJS.Launcher
|
||||||
|
|
||||||
private async Task<bool> ServeBlob(HttpListenerContext context, string path)
|
private async Task<bool> ServeBlob(HttpListenerContext context, string path)
|
||||||
{
|
{
|
||||||
|
byte[] data;
|
||||||
|
string mimeType;
|
||||||
|
|
||||||
|
// Try serve data from the cached blob
|
||||||
|
if (TryGetCachedBlob(path, out mimeType, true))
|
||||||
|
{
|
||||||
|
if (TryGetCachedBlob(path, out data))
|
||||||
|
{
|
||||||
|
if (String.IsNullOrEmpty(mimeType))
|
||||||
|
{
|
||||||
|
mimeType = _defaultMimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServeResource(context, data, mimeType);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not cached yet
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
string blobServerPrefix = Program.GetAppConfig("BlobServerPrefix");
|
string blobServerPrefix = Program.GetAppConfig("BlobServerPrefix");
|
||||||
string url = $"{blobServerPrefix}{path}";
|
string url = $"{blobServerPrefix}{path}";
|
||||||
|
|
||||||
|
@ -143,16 +165,106 @@ namespace WelsonJS.Launcher
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] data = await response.Content.ReadAsByteArrayAsync();
|
data = await response.Content.ReadAsByteArrayAsync();
|
||||||
string mimeType = response.Content.Headers.ContentType?.MediaType ?? "application/octet-stream";
|
mimeType = response.Content.Headers.ContentType?.MediaType ?? _defaultMimeType;
|
||||||
|
|
||||||
ServeResource(context, data, mimeType);
|
ServeResource(context, data, mimeType);
|
||||||
|
_ = TrySaveCachedBlob(path, data, mimeType);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Trace.TraceError($"Failed to serve blob. Exception: {ex.ToString()}");
|
Trace.TraceError($"Failed to serve blob. Exception: {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetCachedBlobPath(string path)
|
||||||
|
{
|
||||||
|
// Get a hash from the path
|
||||||
|
string hashedPath;
|
||||||
|
using (MD5 md5 = MD5.Create())
|
||||||
|
{
|
||||||
|
byte[] bHashedPath = md5.ComputeHash(Encoding.UTF8.GetBytes(path));
|
||||||
|
hashedPath = BitConverter.ToString(bHashedPath).Replace("-", "").ToLowerInvariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a sub-directory paths from the hashed path
|
||||||
|
string[] subDirectoryPaths = new string[] {
|
||||||
|
hashedPath.Substring(0, 2),
|
||||||
|
hashedPath.Substring(2, 2),
|
||||||
|
hashedPath.Substring(4, 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the cache path
|
||||||
|
return Path.Combine(Program.GetAppDataPath(), "BlobCache", String.Join("\\", subDirectoryPaths), hashedPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryGetCachedBlob(string path, out byte[] data, bool isMetadata = false)
|
||||||
|
{
|
||||||
|
string cachePath = GetCachedBlobPath(path);
|
||||||
|
if (isMetadata)
|
||||||
|
{
|
||||||
|
cachePath = $"{cachePath}.meta";
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists(cachePath))
|
||||||
|
{
|
||||||
|
data = File.ReadAllBytes(cachePath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Trace.TraceError($"Error: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
data = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryGetCachedBlob(string path, out string data, bool isMetadata = false)
|
||||||
|
{
|
||||||
|
byte[] bData;
|
||||||
|
if (TryGetCachedBlob(path, out bData, isMetadata))
|
||||||
|
{
|
||||||
|
data = Encoding.UTF8.GetString(bData);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> TrySaveCachedBlob(string path, byte[] data, string mimeType)
|
||||||
|
{
|
||||||
|
await Task.Delay(0);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string cachePath = GetCachedBlobPath(path);
|
||||||
|
string cacheDirectory = Path.GetDirectoryName(cachePath);
|
||||||
|
|
||||||
|
// Is exists the cached blob directory
|
||||||
|
if (!Directory.Exists(cacheDirectory))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(cacheDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the cache
|
||||||
|
File.WriteAllBytes(cachePath, data);
|
||||||
|
|
||||||
|
// Save the cache meta
|
||||||
|
File.WriteAllBytes($"{cachePath}.meta", Encoding.UTF8.GetBytes(mimeType));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Trace.TraceError($"Error: {ex.Message}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,8 @@ namespace WelsonJS.Launcher.ResourceTools
|
||||||
|
|
||||||
public async Task HandleAsync(HttpListenerContext context, string path)
|
public async Task HandleAsync(HttpListenerContext context, string path)
|
||||||
{
|
{
|
||||||
|
await Task.Delay(0);
|
||||||
|
|
||||||
string word = path.Substring(Prefix.Length);
|
string word = path.Substring(Prefix.Length);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -67,8 +69,6 @@ namespace WelsonJS.Launcher.ResourceTools
|
||||||
{
|
{
|
||||||
Server.ServeResource(context, $"<error>Failed to process completion request. {ex.Message}</error>", "application/xml", 500);
|
Server.ServeResource(context, $"<error>Failed to process completion request. {ex.Message}</error>", "application/xml", 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<string> GetInstalledSoftwareExecutables()
|
private List<string> GetInstalledSoftwareExecutables()
|
||||||
|
|
|
@ -21,6 +21,8 @@ namespace WelsonJS.Launcher.ResourceTools
|
||||||
|
|
||||||
public async Task HandleAsync(HttpListenerContext context, string path)
|
public async Task HandleAsync(HttpListenerContext context, string path)
|
||||||
{
|
{
|
||||||
|
await Task.Delay(0);
|
||||||
|
|
||||||
string configName = path.Substring(Prefix.Length);
|
string configName = path.Substring(Prefix.Length);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -32,8 +34,6 @@ namespace WelsonJS.Launcher.ResourceTools
|
||||||
{
|
{
|
||||||
Server.ServeResource(context, $"<error>Failed to process Config request. {ex.Message}</error>", "application/xml", 500);
|
Server.ServeResource(context, $"<error>Failed to process Config request. {ex.Message}</error>", "application/xml", 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ namespace WelsonJS.Launcher.ResourceTools
|
||||||
|
|
||||||
public async Task HandleAsync(HttpListenerContext context, string path)
|
public async Task HandleAsync(HttpListenerContext context, string path)
|
||||||
{
|
{
|
||||||
|
await Task.Delay(0);
|
||||||
|
|
||||||
string query = path.Substring(Prefix.Length);
|
string query = path.Substring(Prefix.Length);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(query) || query.Length > 255)
|
if (string.IsNullOrWhiteSpace(query) || query.Length > 255)
|
||||||
|
@ -59,8 +61,6 @@ namespace WelsonJS.Launcher.ResourceTools
|
||||||
{
|
{
|
||||||
Server.ServeResource(context, $"<error>Failed to process DNS query. {ex.Message}</error>", "application/xml", 500);
|
Server.ServeResource(context, $"<error>Failed to process DNS query. {ex.Message}</error>", "application/xml", 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> QueryA(string domain) => QueryDns(domain, 1);
|
public List<string> QueryA(string domain) => QueryDns(domain, 1);
|
||||||
|
|
|
@ -25,6 +25,8 @@ namespace WelsonJS.Launcher.ResourceTools
|
||||||
|
|
||||||
public async Task HandleAsync(HttpListenerContext context, string path)
|
public async Task HandleAsync(HttpListenerContext context, string path)
|
||||||
{
|
{
|
||||||
|
await Task.Delay(0);
|
||||||
|
|
||||||
string endpoint = path.Substring(Prefix.Length);
|
string endpoint = path.Substring(Prefix.Length);
|
||||||
|
|
||||||
if (endpoint.Equals("pubkey"))
|
if (endpoint.Equals("pubkey"))
|
||||||
|
@ -34,8 +36,6 @@ namespace WelsonJS.Launcher.ResourceTools
|
||||||
}
|
}
|
||||||
|
|
||||||
Server.ServeResource(context);
|
Server.ServeResource(context);
|
||||||
|
|
||||||
await Task.Delay(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetOtp(string key)
|
public int GetOtp(string key)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user