Files
Novaria/Novaria.GameServer/Controllers/Api/GatewayController.cs

147 lines
5.8 KiB
C#

using Microsoft.AspNetCore.Mvc;
using Novaria.Common.Crypto;
using System.Text.Json;
using Serilog;
using Novaria.Common.Core;
using Proto;
using Google.Protobuf;
using Novaria.GameServer.Controllers.Api.ProtocolHandlers;
using Novaria.Common.Util;
namespace Novaria.GameServer.Controllers.Api
{
[Route("/agent-zone-1")]
public class GatewayController : ControllerBase
{
private readonly IProtocolHandlerFactory protocolHandlerFactory;
private readonly ILogger<GatewayController> logger;
public GatewayController(IProtocolHandlerFactory _protocolHandlerFactory, ILogger<GatewayController> _logger)
{
protocolHandlerFactory = _protocolHandlerFactory;
logger = _logger;
}
[HttpPost]
public IActionResult PostRequest()
{
Log.Information("Received Gateway Post Request, Payload");
using var memoryStream = new MemoryStream();
Request.Body.CopyTo(memoryStream); // Copy request body to MemoryStream
byte[] rawPayload = memoryStream.ToArray(); // Get raw bytes from MemoryStream
Utils.PrintByteArray(rawPayload);
Packet requestPacket = HttpNetworkManager.Instance.ParseRequest(rawPayload);
Log.Information("");
Log.Information("msgs body: ");
Utils.PrintByteArray(requestPacket.msgBody.ToArray());
Log.Information("Sucessfully parsed request packet, id: " + requestPacket.msgId);
byte[] responsePackeBytes = null;
NetMsgId msgid = (NetMsgId)requestPacket.msgId;
Log.Information("Received protocol msgid: " + msgid);
Type requestType = ProtocolHandlerFactory.GetRequestPacketTypeByProtocol(msgid);
if (requestType is null)
{
Log.Error($"MsgId {msgid} doesn't have corresponding type registered");
throw new InvalidDataException("invalid protocol msgid");
}
IMessage decodedPayload = HttpNetworkManager.Instance.DecodePacket(requestType, requestPacket);
// originally i returned a IMessage from handlers,
// but since in this game apprently one req can return diff resp msgids thus they can not be hardcoded in the packet or increments,
// so we just return packet, bit tedius but inside handlers will determine the response msgid
var responsePacketObj = protocolHandlerFactory.Invoke(msgid, decodedPayload);
if (responsePacketObj is null)
{
Log.Error($"Protocol {msgid}: {ProtocolHandlerFactory.NetMsgIdToNameMappings[(short)msgid]} is unimplemented and left unhandled");
//throw new ArgumentNullException("handler does not exist");
return new EmptyResult();
}
// -- changed to manually set in handler
// succeed_ack = req_msg_id + 1, failed_ack = req_msg_id - 1, for special stuff like gm its -1/-2
//NetMsgId respMsgId = msgid + 1; // this is probably good for most cases but idk if theres any that doesnt follow this
Packet responsePacket = (Packet)responsePacketObj;
// maybe just change invoke to return Packet
Log.Information($"Response Packet msgid: {responsePacket.msgId}: {(short)responsePacket.msgId}");
responsePackeBytes = HttpNetworkManager.Instance.BuildResponse(responsePacket);
if (responsePackeBytes == null)
{
Log.Error("Unable to build response for packet msgid: " + responsePacket.msgId);
throw new InvalidOperationException("something went wrong during building the response packet!");
}
Log.Information("Sucessfully responsed with a respone packet msgid: " + (short)responsePacket.msgId);
Response.Body.Write(responsePackeBytes, 0, responsePackeBytes.Length);
return new EmptyResult();
}
[HttpOptions] // Ike
public IActionResult OptionsRequest()
{
Log.Information("Received Gateway Ike Options Request, Payload: ");
// store key which is used in AeadTool
using var memoryStream = new MemoryStream();
Request.Body.CopyTo(memoryStream); // Copy request body to MemoryStream
byte[] rawPayload = memoryStream.ToArray(); // Get raw bytes from MemoryStream
Utils.PrintByteArray(rawPayload);
IKEReq ikeRequest = HttpNetworkManager.Instance.ParseIkeRequest(rawPayload);
Log.Information("Decoded Packet: " + JsonSerializer.Serialize(ikeRequest));
byte[] clientPublicKey = ikeRequest.PubKey.ToArray();
Log.Information("RECEIVED client public key: ");
Utils.PrintByteArray(clientPublicKey);
AeadTool.key3 = DiffieHellman.Instance.CalculateKey(clientPublicKey);
Log.Information("KEY3 (chacha20 key) calculated: ");
Utils.PrintByteArray(AeadTool.key3);
IKEResp ikeResponse = new IKEResp()
{
PubKey = ByteString.CopyFrom(AeadTool.PS_PUBLIC_KEY.Reverse().ToArray()),
Token = AeadTool.TOKEN
};
Log.Information("Sending ps server public key: ");
Utils.PrintByteArray(AeadTool.PS_PUBLIC_KEY);
Packet ikePacket = new Packet()
{
msgId = 2,
msgBody = ikeResponse.ToByteArray()
};
var responsePayload = HttpNetworkManager.Instance. BuildIkeResponse(ikePacket);
Log.Information("Sending ike response packet: " + JsonSerializer.Serialize(ikeResponse));
Log.Information("Built bytes: ");
Utils.PrintByteArray(responsePayload);
Response.Body.Write(responsePayload, 0, responsePayload.Length);
return new EmptyResult();
}
}
}