diff --git a/AimeNet/DllMain.cs b/AimeNet/DllMain.cs index eb0fa18..5dada3f 100644 --- a/AimeNet/DllMain.cs +++ b/AimeNet/DllMain.cs @@ -1,9 +1,7 @@ using System; using System.Globalization; -using System.IO; using System.Linq; using System.Runtime.InteropServices; -using System.Text; using System.Text.Json; using System.Threading; using Windows.Win32; @@ -11,7 +9,6 @@ using Windows.Win32.Foundation; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace AimeNet; @@ -25,10 +22,11 @@ public static class DllMain private static string[] _serverAddresses; private static string _serverName; + private static string _gameId; private static (byte[] IdBytes, string OriginalId, long Expires)? _currentCard; - private static readonly object CardLock = new(); + private static readonly object _cardLock = new(); static DllMain() { @@ -63,25 +61,42 @@ public static class DllMain catch (JsonException e) { ctx.Response.StatusCode = 400; + await ctx.Response.WriteAsync(e.Message); + + return; + } + + if (string.IsNullOrEmpty(request?.MatrixCode)) + { + ctx.Response.StatusCode = 400; + await ctx.Response.WriteAsync("Card id not provided."); + return; + } + + if (request.MatrixCode.Length is 0 or < 20) + { + ctx.Response.StatusCode = 422; + await ctx.Response.WriteAsync("Invalid card id length."); + return; + } + + if (request.MatrixCode.Any(x => !char.IsNumber(x))) + { + ctx.Response.StatusCode = 422; + await ctx.Response.WriteAsync("Invalid card id format."); return; } lock (_cardLock) { - // don't allow multiple writes in quick succession + // ratelimit check if (_currentCard?.Expires > Environment.TickCount64) { ctx.Response.StatusCode = 429; - ctx.Response.Headers.RetryAfter = ((int)TimeSpan.FromTicks(_currentCard.Value.Expires - Environment.TickCount64).TotalSeconds).ToString(); + ctx.Response.Headers.RetryAfter = ((int)TimeSpan.FromMilliseconds(_currentCard.Value.Expires - Environment.TickCount64).TotalSeconds).ToString(); return; } - if (request.MatrixCode.Length < 20) - { - ctx.Response.StatusCode = 400; - return; - } - // ensure the matrix code is 20-digits long, otherwise pad with zeros var matrixCode = request.MatrixCode.PadLeft(20, '0'); var bytes = new byte[10]; @@ -92,16 +107,17 @@ public static class DllMain bytes[i] = byte.Parse(value, NumberStyles.HexNumber); } - _currentCard = (bytes, matrixCode, Environment.TickCount64 + 5000000); + // it's called a tick count, but it uses milliseconds despite having a unit of time called a tick??? + _currentCard = (bytes, matrixCode, Environment.TickCount64 + 5000); } - ctx.Response.StatusCode = 204; + ctx.Response.StatusCode = 202; }); CancellationTokenRegistration cancellationRegistration = default; cancellationRegistration = app.Lifetime.ApplicationStarted.Register(() => { - _serverLogger.LogInformation("AimeNet started successfully."); + _serverLogger.LogInformation("AMNet Server ({gameId}) started successfully.", _gameId); _serverLogger.LogInformation("Visit {addr} from a mobile device on the same network to get started.", WebAddress); cancellationRegistration.Dispose(); @@ -170,15 +186,20 @@ public static class DllMain { const string configFileName = @".\segatools.ini"; + var gameId = stackalloc char[5]; + var gameIdStr = new PWSTR(gameId); + var serverName = stackalloc char[64]; var serverNameStr = new PWSTR(serverName); var serverAddress = stackalloc char[1024]; var serverAddressStr = new PWSTR(serverAddress); + PInvoke.GetPrivateProfileString("aimeio", "gameId", string.Empty, gameIdStr, 5, configFileName); PInvoke.GetPrivateProfileString("aimeio", "serverName", Environment.MachineName, serverNameStr, 64, configFileName); PInvoke.GetPrivateProfileString("aimeio", "serverAddress", "http://+:6070", serverAddressStr, 1024, configFileName); + _gameId = gameIdStr.ToString(); _serverName = serverNameStr.ToString(); _serverAddresses = serverAddressStr.ToString().Split(';'); }