TigerEmu/Networking/Game/GameTcpServer.cs

75 lines
2.6 KiB
C#

using System.Net;
using System.Net.Sockets;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Tiger.Networking.Game.Sessions;
using System.Text;
using HabboEncoding;
using Tiger.Communication.Messages;
using Tiger.Communication.Messages.Outgoing.Handshake;
using Tiger.Communication.Messages.Types;
using Tiger.Utils;
namespace Tiger.Networking.Game;
public sealed class GameTcpServer : TcpServer
{
private readonly IGameSessionManager _gameSessionManager;
private readonly ILogger<GameTcpServer> _logger;
private readonly IMessageHandler _messageHandler;
public GameTcpServer(IGameSessionManager gameSessionManager, IConfiguration configuration,
ILogger<GameTcpServer> logger, IMessageHandler messageHandler)
: base(configuration["Network:Game:Ip"] ?? "0.0.0.0",
int.TryParse(configuration["Network:Game:Port"], out var port) ? port : 30000)
{
_gameSessionManager = gameSessionManager;
_logger = logger;
_messageHandler = messageHandler;
}
protected override async Task ConnectionCallbackAsync(TcpClient client)
{
var gameSession = _gameSessionManager.AddSession(client);
var buffer = new byte[1024];
_logger.LogInformation("Client {Id} connected ({EndPoint}", gameSession.SessionId,
gameSession.Client.Client.RemoteEndPoint);
await gameSession.SendComposerAsync(new HelloComposer());
while (true)
{
var bytesRead = await gameSession.Stream.ReadAsync(buffer);
if (bytesRead == 0) break;
var actualBytes = ByteUtils.CopyArray(buffer, 0, bytesRead);
if (gameSession.Rc4 != null)
{
actualBytes = gameSession.Rc4.Decipher(actualBytes);
}
var readerIndex = 0;
while (actualBytes.Length - readerIndex >= 5)
{
var length = Base64Encoding.DecodeInt32(ByteUtils.CopyArray(actualBytes, readerIndex, 3));
var packet = ByteUtils.CopyArray(actualBytes, readerIndex + 3, length);
await _messageHandler.TryHandleAsync(gameSession, new ClientMessage(packet));
readerIndex += 3 + length;
}
}
await _gameSessionManager.CloseAsync(gameSession);
_logger.LogInformation("Client {Id} disconnected ({EndPoint}", gameSession.SessionId,
gameSession.Client.Client.RemoteEndPoint);
}
public override void Start()
{
base.Start();
_logger.LogInformation("Started Game Tcp Server on {EndPoint}", Server.LocalEndpoint);
}
}