Files
SVSimServer/SVSim.EmulatedEntrypoint/Middlewares/ShadowverseTranslationMiddleware.cs
gamer147 ee7e276036 Updates
2024-09-05 08:32:54 -04:00

65 lines
3.3 KiB
C#

using System.Text;
using MessagePack;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using SVSim.EmulatedEntrypoint.Security;
namespace SVSim.EmulatedEntrypoint.Middlewares;
/// <summary>
/// Translates incoming requests and outgoing responses from the Shadowverse client into the messagepack format.
/// </summary>
public class ShadowverseTranslationMiddleware : IMiddleware
{
private readonly IActionDescriptorCollectionProvider _actionDescriptorCollectionProvider;
public ShadowverseTranslationMiddleware(IActionDescriptorCollectionProvider actionDescriptorCollectionProvider)
{
_actionDescriptorCollectionProvider = actionDescriptorCollectionProvider;
}
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
bool isUnity = context.Request.Headers.UserAgent.Any(agent => agent?.Contains("UnityPlayer") ?? false);
string path = context.Request.Path;
var endpointDescriptor =
_actionDescriptorCollectionProvider.ActionDescriptors.Items.FirstOrDefault(ad =>
$"/{ad.AttributeRouteInfo.Template}".Equals(path, StringComparison.InvariantCultureIgnoreCase));
if (!isUnity || endpointDescriptor == null)
{
await next.Invoke(context);
return;
}
using var requestBytesStream = new MemoryStream();
using var tempResponseBody = new MemoryStream();
var originalResponsebody = context.Response.Body;
context.Response.Body = tempResponseBody;
await context.Request.Body.CopyToAsync(requestBytesStream);
byte[] requestBytes = requestBytesStream.ToArray();
// Decrypt incoming data. Placeholder.
requestBytes = Encryption.Decrypt(requestBytes, Encryption.Decode(context.Request.Headers["UDID"]));
object? data = MessagePackSerializer.Deserialize(endpointDescriptor.Parameters.FirstOrDefault().ParameterType,
requestBytes);
var json = JsonConvert.SerializeObject(data);
var newStream = new StringContent(json, Encoding.UTF8, "application/json");
context.Request.Body = newStream.ReadAsStream();
context.Request.Headers.ContentType = new StringValues("application/json");
await next.Invoke(context);
var responseType = ((ControllerActionDescriptor)endpointDescriptor).MethodInfo.ReturnType;
if (responseType.IsGenericType && responseType.GetGenericTypeDefinition() == typeof(Task<>))
{
responseType = responseType.GetGenericArguments()[0];
}
using var responseBytesStream = new MemoryStream();
context.Response.Body.Seek(0, SeekOrigin.Begin);
await context.Response.Body.CopyToAsync(responseBytesStream);
var responseBytes = responseBytesStream.ToArray();
var responseData = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(responseBytes), responseType);
var packedData = MessagePackSerializer.Serialize(responseType, responseData);
packedData = Encryption.Encrypt(packedData, Encryption.Decode(context.Request.Headers["UDID"]));
await originalResponsebody.WriteAsync(Encoding.UTF8.GetBytes(Convert.ToBase64String(packedData)));
context.Response.Body = originalResponsebody;
}
}