- 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="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
/// after that the udp client will be disposed</param>
public void RequestLobbyNatPunch(Guid lobbyId, string? password, int port = 0)
/// after that the udp client will be disposed.</param>
public int RequestLobbyNatPunch(Guid lobbyId, string? password, int port = 0)
{
if(port < 0 && port > 65535)
throw new ArgumentOutOfRangeException(nameof(port));
byte[]? passwordHash = null;
if (!string.IsNullOrEmpty(password) && lobbyInformation.ContainsKey(lobbyId) && lobbyInformation[lobbyId].PasswordSalt != null)
passwordHash = PasswordHash.Hash(password, lobbyInformation[lobbyId].PasswordSalt!);
Task.Run(() =>
{
using (var udpEchoServer = new UdpEchoServer())
{
udpEchoServer.Start(port);
QueryExternalIpAndPort(udpEchoServer.Send);
}
var udpEchoServer = new UdpEchoServer();
udpEchoServer.Start(port);
Task.Run(() =>
{
QueryExternalIpAndPort(udpEchoServer.Send);
udpEchoServer.Dispose();
var lobbyRequestNatPunch = new LobbyRequestNatPunch()
{
LobbyId = lobbyId,
@ -200,6 +202,8 @@ namespace Lobbies
var len = lobbyRequestNatPunch.Serialize(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)
@ -381,6 +385,16 @@ namespace Lobbies
{
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:
{
var lobbyClientConnectionInfo = LobbyClientConnectionInfo.Deserialize(data.Span);

View File

@ -63,6 +63,10 @@
/// <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.
/// </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)
{
Stop();
while (isRunningV4 || isRunningV6)
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;

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; }
}
}