From 35b77b044ca485b18703d6ba78cc6123e48eed3a Mon Sep 17 00:00:00 2001 From: PopSlime Date: Sun, 16 Feb 2025 23:49:20 +0800 Subject: [PATCH] feat: Add gateway verification --- Assets/Cryville.EEW.Unity/SharedSettings.cs | 19 ++++++- Assets/Cryville.EEW.Unity/Worker.cs | 58 ++++++++++++++++++++- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/Assets/Cryville.EEW.Unity/SharedSettings.cs b/Assets/Cryville.EEW.Unity/SharedSettings.cs index df57357..957dc70 100644 --- a/Assets/Cryville.EEW.Unity/SharedSettings.cs +++ b/Assets/Cryville.EEW.Unity/SharedSettings.cs @@ -5,6 +5,8 @@ using Cryville.EEW.Map; using Cryville.EEW.Report; using Cryville.EEW.TTS; using System; +using System.Globalization; +using System.Runtime.InteropServices; using System.Security.Cryptography; using UnityEngine; using Color = System.Drawing.Color; @@ -23,10 +25,25 @@ namespace Cryville.EEW.Unity { public ILocationConverter LocationConverter => new FERegionLongConverter(); public TimeSpan NowcastWarningDelayTolerance => TimeSpan.MaxValue; + public string Id { get; private set; } public byte[] IdBytes { get; } = new byte[32]; + public string UnityUserAgent { get; private set; } public void Init() { + Id = SystemInfo.deviceUniqueIdentifier; using var hash = SHA256.Create(); - hash.ComputeHash(EEW.SharedSettings.Encoding.GetBytes(SystemInfo.deviceUniqueIdentifier)).CopyTo(IdBytes, 0); + hash.ComputeHash(EEW.SharedSettings.Encoding.GetBytes(Id)).CopyTo(IdBytes, 0); +#if UNITY_STANDALONE_WIN + UnityUserAgent = string.Format( + CultureInfo.InvariantCulture, + "{0} CysTerraUnity/{1} (Windows NT {2}; {3})", + EEW.SharedSettings.UserAgent, + Application.version, + Environment.OSVersion.Version, + RuntimeInformation.OSArchitecture.ToString().ToLowerInvariant() + ); +#else +#error No Unity User Agent +#endif } } } diff --git a/Assets/Cryville.EEW.Unity/Worker.cs b/Assets/Cryville.EEW.Unity/Worker.cs index b3370b6..b2a18be 100644 --- a/Assets/Cryville.EEW.Unity/Worker.cs +++ b/Assets/Cryville.EEW.Unity/Worker.cs @@ -15,6 +15,8 @@ using Cryville.EEW.Wolfx; using Cryville.EEW.Wolfx.TTS; using System; using System.Collections.Concurrent; +using System.Net.Http; +using System.Net; using System.Threading; using System.Threading.Tasks; using UnityEngine; @@ -55,8 +57,16 @@ namespace Cryville.EEW.Unity { _worker.Reported += OnReported; _worker.GroupUpdated += OnGroupUpdated; _worker.GroupRemoved += OnGroupRemoved; - Task.Run(() => _worker.RunAsync(_cancellationTokenSource.Token)); - Task.Run(() => _ongoingReportManager.RunAsync(_cancellationTokenSource.Token)); + Task.Run(() => GatewayVerify(_cancellationTokenSource.Token)).ContinueWith(task => { + if (task.IsFaulted) { + OnReported(this, new() { Title = task.Exception.Message }); + return; + } + _verified = true; + Task.Run(() => ScheduledGatewayVerify(_cancellationTokenSource, _cancellationTokenSource.Token)); + Task.Run(() => _worker.RunAsync(_cancellationTokenSource.Token)); + Task.Run(() => _ongoingReportManager.RunAsync(_cancellationTokenSource.Token)); + }, TaskScheduler.Current); } void OnDestroy() { @@ -92,6 +102,7 @@ namespace Cryville.EEW.Unity { worker.RegisterTTSMessageGenerator(new SichuanEEWTTSMessageGenerator()); } + bool _verified; WolfxWorker _wolfxWorker; JMAAtomWorker _jmaWorker; CWAReportWorker _cwa14Worker; @@ -158,5 +169,48 @@ namespace Cryville.EEW.Unity { m_cameraController.OnMapElementUpdated(); } } + + async Task ScheduledGatewayVerify(CancellationTokenSource source, CancellationToken cancellationToken) { + Exception lastEx = null; + for (int i = 0; i < 8; i++) { + await Task.Delay(TimeSpan.FromHours(3), cancellationToken).ConfigureAwait(true); + try { + await GatewayVerify(cancellationToken).ConfigureAwait(true); + i = -1; + } + catch (HttpRequestException ex) { + lastEx = ex; + } + catch (WebException ex) { + lastEx = ex; + } + catch (InvalidOperationException ex) { + lastEx = ex; + break; + } + } + if (lastEx != null) { + OnReported(this, new() { Title = lastEx.Message }); + _verified = false; + } + source.Cancel(); + } +#if UNITY_EDITOR +#pragma warning disable CS1998 +#endif + static async Task GatewayVerify(CancellationToken cancellationToken) { +#if !UNITY_EDITOR + using var client = new HttpClient(); + client.DefaultRequestHeaders.UserAgent.ParseAdd(SharedSettings.Instance.UnityUserAgent); + using var response = await client.GetAsync(new Uri("https://gateway.cryville.world/?rin=" + SharedSettings.Instance.Id), cancellationToken).ConfigureAwait(true); + if (response.StatusCode is >= ((HttpStatusCode)400) and < ((HttpStatusCode)500)) { + throw new InvalidOperationException(response.ReasonPhrase); + } + response.EnsureSuccessStatusCode(); +#endif + } +#if UNITY_EDITOR +#pragma warning restore CS1998 +#endif } }