From 776727b9c25fc435a4000a2cc92fe3d3132d4779 Mon Sep 17 00:00:00 2001 From: sven-n Date: Tue, 3 Sep 2024 19:37:08 +0200 Subject: [PATCH 1/2] Improvements for the connect server ip resolve --- .../PacketHandler/ServerInfoRequestHandler.cs | 28 ++++++++++++++++++- src/Network/Connection.cs | 4 +++ src/Network/IConnection.cs | 5 ++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/ConnectServer/PacketHandler/ServerInfoRequestHandler.cs b/src/ConnectServer/PacketHandler/ServerInfoRequestHandler.cs index eef4366fd..316a22c7a 100644 --- a/src/ConnectServer/PacketHandler/ServerInfoRequestHandler.cs +++ b/src/ConnectServer/PacketHandler/ServerInfoRequestHandler.cs @@ -4,6 +4,7 @@ namespace MUnique.OpenMU.ConnectServer.PacketHandler; +using System.Net; using Microsoft.Extensions.Logging; using MUnique.OpenMU.Network; using MUnique.OpenMU.Network.Packets.ConnectServer; @@ -15,6 +16,7 @@ internal class ServerInfoRequestHandler : IPacketHandler { private readonly IConnectServer _connectServer; private readonly ILogger _logger; + private readonly HashSet _localIpAddresses; /// /// Initializes a new instance of the class. @@ -25,6 +27,7 @@ public ServerInfoRequestHandler(IConnectServer connectServer, ILogger @@ -38,8 +41,31 @@ public async ValueTask HandlePacketAsync(Client client, Memory packet) await client.Connection.DisconnectAsync().ConfigureAwait(false); } - if (this._connectServer.ConnectInfos.TryGetValue(serverId, out var connectInfo)) + // First we look, if we can just use the IP address which the client connected to. + // If the game server is running on the same ip as the connect server, we can use that. + // This way, we can be sure, that the client can connect to it, too. + if (this._connectServer.ServerList.GetItem(serverId) is { } serverItem + && this._localIpAddresses.Contains(serverItem.EndPoint.Address) + && client.Connection.LocalEndPoint is IPEndPoint localIpEndPoint + && !object.Equals(client.Address, localIpEndPoint.Address)) // only if we can't use the cached data { + int WritePacket() + { + var data = client.Connection.Output.GetSpan(ConnectionInfoRef.Length)[..ConnectionInfoRef.Length]; + _ = new ConnectionInfoRef(data) + { + IpAddress = localIpEndPoint.Address.ToString(), + Port = (ushort)serverItem.EndPoint.Port + }; + return data.Length; + } + + await client.Connection.SendAsync(WritePacket).ConfigureAwait(false); + } + else if (this._connectServer.ConnectInfos.TryGetValue(serverId, out var connectInfo)) + { + // more optimal way, because the serialized data was cached. + int WritePacket() { var span = client.Connection.Output.GetSpan(connectInfo.Length)[..connectInfo.Length]; diff --git a/src/Network/Connection.cs b/src/Network/Connection.cs index e258b1371..1149f238d 100644 --- a/src/Network/Connection.cs +++ b/src/Network/Connection.cs @@ -62,6 +62,7 @@ public Connection(IDuplexPipe duplexPipe, IPipelinedDecryptor? decryptionPipe, I this._logger = logger; this.Source = decryptionPipe?.Reader ?? this._duplexPipe!.Input; this._remoteEndPoint = this.SocketConnection?.Socket.RemoteEndPoint ?? new IPEndPoint(IPAddress.Any, 0); + this.LocalEndPoint = this.SocketConnection?.Socket.LocalEndPoint; this.OutputLock = new(); } @@ -77,6 +78,9 @@ public Connection(IDuplexPipe duplexPipe, IPipelinedDecryptor? decryptionPipe, I /// public EndPoint? EndPoint => this._remoteEndPoint; + /// + public EndPoint? LocalEndPoint { get; } + /// public PipeWriter Output => this._outputWriter ??= new ExtendedPipeWriter(this._encryptionPipe?.Writer ?? this._duplexPipe!.Output, OutgoingBytesCounter); diff --git a/src/Network/IConnection.cs b/src/Network/IConnection.cs index 173ec7ebc..7ef9c79b8 100644 --- a/src/Network/IConnection.cs +++ b/src/Network/IConnection.cs @@ -42,6 +42,11 @@ public interface IConnection : IDisposable /// EndPoint? EndPoint { get; } + /// + /// Gets the local endpoint of the connection. + /// + EndPoint? LocalEndPoint { get; } + /// /// Gets the pipe writer to send data. /// From 1dc20feaa243be86d3afe96aa3daf2ab8dd85950 Mon Sep 17 00:00:00 2001 From: sven-n Date: Tue, 3 Sep 2024 21:14:19 +0200 Subject: [PATCH 2/2] Improved readability --- .../PacketHandler/ServerInfoRequestHandler.cs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/ConnectServer/PacketHandler/ServerInfoRequestHandler.cs b/src/ConnectServer/PacketHandler/ServerInfoRequestHandler.cs index 316a22c7a..c02433c75 100644 --- a/src/ConnectServer/PacketHandler/ServerInfoRequestHandler.cs +++ b/src/ConnectServer/PacketHandler/ServerInfoRequestHandler.cs @@ -44,18 +44,22 @@ public async ValueTask HandlePacketAsync(Client client, Memory packet) // First we look, if we can just use the IP address which the client connected to. // If the game server is running on the same ip as the connect server, we can use that. // This way, we can be sure, that the client can connect to it, too. - if (this._connectServer.ServerList.GetItem(serverId) is { } serverItem - && this._localIpAddresses.Contains(serverItem.EndPoint.Address) - && client.Connection.LocalEndPoint is IPEndPoint localIpEndPoint - && !object.Equals(client.Address, localIpEndPoint.Address)) // only if we can't use the cached data + var localIpEndPoint = client.Connection.LocalEndPoint as IPEndPoint; + var serverItem = this._connectServer.ServerList.GetItem(serverId); + var isGameServerOnSameMachineAsConnectServer = serverItem is not null + && this._localIpAddresses.Contains(serverItem.EndPoint.Address); + var isClientConnectedOnNonRegisteredAddress = localIpEndPoint is not null + && !object.Equals(client.Address, localIpEndPoint.Address); + if (isGameServerOnSameMachineAsConnectServer + && isClientConnectedOnNonRegisteredAddress) // only if we can't use the cached data { int WritePacket() { var data = client.Connection.Output.GetSpan(ConnectionInfoRef.Length)[..ConnectionInfoRef.Length]; _ = new ConnectionInfoRef(data) { - IpAddress = localIpEndPoint.Address.ToString(), - Port = (ushort)serverItem.EndPoint.Port + IpAddress = localIpEndPoint!.Address.ToString(), + Port = (ushort)serverItem!.EndPoint.Port }; return data.Length; }