- Get port from nat punch service

main
Thomas Woischnig 2023-12-04 17:03:27 +01:00
parent 3b43758054
commit 6ff97d7db0
8 changed files with 74 additions and 10 deletions

View File

@ -173,21 +173,23 @@ namespace Lobbies
/// <param name="lobbyId">The lobby to request a nat punch for</param> /// <param name="lobbyId">The lobby to request a nat punch for</param>
/// <param name="password">Optional password of lobby</param> /// <param name="password">Optional password of lobby</param>
/// <param name="port">The port the game client will later use. We create a udp socket on it and send a packet to the lobby server to get the firewall to map that port for a short period of time /// <param name="port">The port the game client will later use. We create a udp socket on it and send a packet to the lobby server to get the firewall to map that port for a short period of time
/// after that the udp client will be disposed</param> /// after that the udp client will be disposed.</param>
public void RequestLobbyNatPunch(Guid lobbyId, string? password, int port = 0) public int RequestLobbyNatPunch(Guid lobbyId, string? password, int port = 0)
{ {
if(port < 0 && port > 65535)
throw new ArgumentOutOfRangeException(nameof(port));
byte[]? passwordHash = null; byte[]? passwordHash = null;
if (!string.IsNullOrEmpty(password) && lobbyInformation.ContainsKey(lobbyId) && lobbyInformation[lobbyId].PasswordSalt != null) if (!string.IsNullOrEmpty(password) && lobbyInformation.ContainsKey(lobbyId) && lobbyInformation[lobbyId].PasswordSalt != null)
passwordHash = PasswordHash.Hash(password, lobbyInformation[lobbyId].PasswordSalt!); passwordHash = PasswordHash.Hash(password, lobbyInformation[lobbyId].PasswordSalt!);
var udpEchoServer = new UdpEchoServer();
udpEchoServer.Start(port);
Task.Run(() => Task.Run(() =>
{ {
using (var udpEchoServer = new UdpEchoServer()) QueryExternalIpAndPort(udpEchoServer.Send);
{ udpEchoServer.Dispose();
udpEchoServer.Start(port);
QueryExternalIpAndPort(udpEchoServer.Send);
}
var lobbyRequestNatPunch = new LobbyRequestNatPunch() var lobbyRequestNatPunch = new LobbyRequestNatPunch()
{ {
LobbyId = lobbyId, LobbyId = lobbyId,
@ -200,6 +202,8 @@ namespace Lobbies
var len = lobbyRequestNatPunch.Serialize(messageData); var len = lobbyRequestNatPunch.Serialize(messageData);
_ = Task.Run(async () => { await tcpClient.Send(messageData, 0, len); bufferRental.Return(messageData); }); _ = Task.Run(async () => { await tcpClient.Send(messageData, 0, len); bufferRental.Return(messageData); });
}); });
return udpEchoServer.Port;
} }
public void UpdateLobby(string name, int gameMode, int maxPlayerCount, int playerCount, string? password, int port) public void UpdateLobby(string name, int gameMode, int maxPlayerCount, int playerCount, string? password, int port)
@ -381,6 +385,16 @@ namespace Lobbies
{ {
switch (LobbyMessageIdentifier.ReadLobbyMessageIdentifier(data.Span)) switch (LobbyMessageIdentifier.ReadLobbyMessageIdentifier(data.Span))
{ {
case LobbyNotFound.TypeId:
{
events.Enqueue(new LobbyClientEvent { EventType = LobbyClientEventTypes.LobbyJoinFailed, EventData = new LobbyJoinFailReason { Reason = LobbyJoinFailReason.FailReasons.LobbyNotFound, ErrorMessage = string.Empty } });
}
break;
case LobbyWrongPassword.TypeId:
{
events.Enqueue(new LobbyClientEvent { EventType = LobbyClientEventTypes.LobbyJoinFailed, EventData = new LobbyJoinFailReason { Reason = LobbyJoinFailReason.FailReasons.WrongPassword, ErrorMessage = string.Empty } });
}
break;
case LobbyClientConnectionInfo.TypeId: case LobbyClientConnectionInfo.TypeId:
{ {
var lobbyClientConnectionInfo = LobbyClientConnectionInfo.Deserialize(data.Span); var lobbyClientConnectionInfo = LobbyClientConnectionInfo.Deserialize(data.Span);

View File

@ -63,6 +63,10 @@
/// <summary> /// <summary>
/// A direct connection test without a nat punch was testet. EventData is <see cref="DirectConnectionResultTest"/> with information if a direct connection was possible and on what address. /// A direct connection test without a nat punch was testet. EventData is <see cref="DirectConnectionResultTest"/> with information if a direct connection was possible and on what address.
/// </summary> /// </summary>
DirectConnectionTestComplete DirectConnectionTestComplete,
/// <summary>
/// A join request to a lobby has failed. EventData is <see cref="LobbyJoinFailReason"/> with information about the failure.
/// </summary>
LobbyJoinFailed,
} }
} }

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Lobbies
{
public class LobbyJoinFailReason
{
public enum FailReasons
{
WrongPassword,
LobbyNotFound,
LobbyFull
}
public FailReasons Reason { get; internal set; }
public string? ErrorMessage { get; internal set; }
}
}

View File

@ -198,6 +198,7 @@ namespace Lobbies
if (!isDisposed) if (!isDisposed)
{ {
Stop(); Stop();
while (isRunningV4 || isRunningV6) while (isRunningV4 || isRunningV6)
Task.Yield(); Task.Yield();

View File

@ -243,6 +243,18 @@ tcpServer.DataReceived += (clientId, dataLength, data) =>
}); });
} }
} }
else
{
var messageData = bufferRental.Rent();
var lobbyNotFound = new LobbyNotFound() { LobbyId = lobbyRequestHostInfo.LobbyId };
var messageDataLength = lobbyNotFound.Serialize(messageData);
_ = Task.Run(async () => {
await tcpServer.Send(clientId, messageData, 0, messageDataLength);
bufferRental.Return(messageData);
});
return;
}
} }
} }
break; break;

View File

@ -0,0 +1,14 @@
namespace LobbyServerDto
{
/// <summary>
/// Send if a client requests information about a password protected lobby with an invalid password hash
/// </summary>
[LobbyMessage]
public partial class LobbyNotFound
{
/// <summary>
/// Id of the lobby
/// </summary>
public Guid LobbyId { get; set; }
}
}