Compare commits

...
6 Commits
Author SHA1 Message Date
Aigio Liu ef627692ef v2.8.3 rev.1
fix SettingsHost.Load
2022-08-15 12:32:18 +08:00
Aigio Liu 6f28ce0993 Get_Nullable remove throw 2022-08-15 12:17:07 +08:00
RMBGAME 2dbb13db87 #1888 #1897 2022-08-15 12:12:20 +08:00
Aigio Liu 40d3c0e669 Build Android versionCode="20220814" 2022-08-14 21:58:22 +08:00
RMBGAME 6be424dc5f ReverseProxyHttpClientHandler in Server 2022-08-14 16:57:49 +08:00
Aigio Liu 6babd615cd Use ReverseProxyHttpClientHandler in Server 2022-08-14 16:41:10 +08:00
5 changed files with 163 additions and 18 deletions
@@ -49,28 +49,91 @@ public static class SettingsHost
}
}
/// <summary>
/// 尝试备份配置
/// </summary>
/// <param name="bakLocalFilePath"></param>
static void TryBackup(string bakLocalFilePath)
{
try
{
var localFilePath = SettingsHostBase.LocalFilePath;
if (File.Exists(localFilePath))
{
File.Copy(localFilePath, bakLocalFilePath, true);
}
}
catch (Exception ex)
{
Log.Error(nameof(SettingsHost), ex, "Config TryBackUp");
}
}
/// <summary>
/// 尝试还原备份配置,返回是否有备份文件
/// </summary>
/// <param name="bakLocalFilePath"></param>
/// <returns></returns>
static bool TryRestoreBackup(string bakLocalFilePath)
{
try
{
var exists = File.Exists(bakLocalFilePath);
if (exists)
{
var localFilePath = SettingsHostBase.LocalFilePath;
File.Copy(bakLocalFilePath, localFilePath, true);
}
return exists;
}
catch (Exception ex)
{
Log.Error(nameof(SettingsHost), ex, "Config TryRestoreBackup");
}
return false;
}
/// <summary>
/// 尝试删除配置
/// </summary>
static void TryDelete()
{
try
{
var localFilePath = SettingsHostBase.LocalFilePath;
if (File.Exists(localFilePath))
{
File.Delete(localFilePath);
}
}
catch (Exception ex)
{
Log.Error(nameof(SettingsHost), ex, "Config TryDelete");
}
}
public static void Load()
{
var isLoad = false;
var bakLocalFilePath = $"{SettingsHostBase.LocalFilePath}.bak";
try
{
SettingsHostBase.Local.Load();
isLoad = true;
File.Copy(SettingsHostBase.LocalFilePath, bakLocalFilePath, true);
TryBackup(bakLocalFilePath);
}
catch (Exception ex)
{
if (File.Exists(bakLocalFilePath))
if (!TryRestoreBackup(bakLocalFilePath))
{
File.Copy(bakLocalFilePath, SettingsHostBase.LocalFilePath, true);
// 还原备份文件失败,删除当前配置
TryDelete();
}
else
{
File.Delete(SettingsHostBase.LocalFilePath);
}
Log.Error(nameof(SettingsHost), ex, "Config Load");
SettingsHostBase.Local.Load();
Log.Error(nameof(SettingsHost), ex, $"Config Load, isLoad: {isLoad}");
if (!isLoad) SettingsHostBase.Local.Load();
}
}
}
+2 -8
View File
@@ -77,10 +77,7 @@ public static partial class DI
/// <inheritdoc cref="Get{T}"/>
public static T? Get_Nullable<T>() where T : notnull
{
if (value == null)
{
throw GetDIGetFailException(typeof(T));
}
if (value == null) return default;
return value.GetService<T>();
}
@@ -97,10 +94,7 @@ public static partial class DI
/// <inheritdoc cref="Get_Nullable{T}"/>
public static object? Get_Nullable(Type serviceType)
{
if (value == null)
{
throw GetDIGetFailException(serviceType);
}
if (value == null) return default;
return value.GetService(serviceType);
}
+4
View File
@@ -291,6 +291,10 @@ public static class IOPath
{
paths[i] = item;
}
else
{
DirCreateByNotExists(paths[i]);
}
}
InitFileSystem(GetAppDataDirectory, GetCacheDirectory);
@@ -0,0 +1,84 @@
using System.Net.Security;
using System.Net.Sockets;
namespace System.Net.Http;
public sealed class ReverseProxyHttpClientHandler : DelegatingHandler
{
readonly TimeSpan connectTimeout = TimeSpan.FromSeconds(10d);
public ReverseProxyHttpClientHandler()
{
InnerHandler = new SocketsHttpHandler()
{
Proxy = GeneralHttpClientFactory.HttpNoProxy.Instance,
UseProxy = false,
UseCookies = false,
AllowAutoRedirect = false,
AutomaticDecompression = DecompressionMethods.None,
ConnectCallback = ConnectCallback,
};
}
/// <summary>
/// 连接回调
/// </summary>
/// <param name="context"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
async ValueTask<Stream> ConnectCallback(SocketsHttpConnectionContext context, CancellationToken cancellationToken)
{
var innerExceptions = new List<Exception>();
var ipEndPoints = (await Dns.GetHostAddressesAsync("steamcommunity.rmbgame.net", cancellationToken)).Select(s => new IPEndPoint(s, context.DnsEndPoint.Port));
foreach (var ipEndPoint in ipEndPoints)
{
try
{
using var timeoutTokenSource = new CancellationTokenSource(connectTimeout);
using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutTokenSource.Token, cancellationToken);
return await ConnectAsync(context, ipEndPoint, linkedTokenSource.Token);
}
catch (OperationCanceledException)
{
cancellationToken.ThrowIfCancellationRequested();
innerExceptions.Add(new TimeoutException(
$"HTTP connection to {ipEndPoint.Address} timed out."));
}
catch (Exception ex)
{
innerExceptions.Add(ex);
}
}
throw new AggregateException("Could not find any IP that can be successfully connected.", innerExceptions);
}
/// <summary>
/// 建立连接
/// </summary>
/// <param name="context"></param>
/// <param name="ipEndPoint"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
static async ValueTask<Stream> ConnectAsync(SocketsHttpConnectionContext context, IPEndPoint ipEndPoint, CancellationToken cancellationToken)
{
var socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
await socket.ConnectAsync(ipEndPoint, cancellationToken);
var stream = new NetworkStream(socket, ownsSocket: true);
if (context.DnsEndPoint.Port != 443)
{
return stream;
}
var sslStream = new SslStream(stream, leaveInnerStreamOpen: false);
await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
{
TargetHost = string.Empty,
RemoteCertificateValidationCallback = (_, _, _, _) => true,
}, cancellationToken);
return sslStream;
}
}
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="20220803" android:versionName="2.8.3" package="net.steampp.app" android:installLocation="auto">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="20220814" android:versionName="2.8.3" package="net.steampp.app" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
<application android:fullBackupContent="@xml/auto_backup_rules"></application>
<!-- Required for API Level 30 to make sure the app can detect browsers and other apps where communication is needed.-->