diff --git a/Assets/NetworkLobbyClient/Runtime/LobbyClient.dll b/Assets/NetworkLobbyClient/Runtime/LobbyClient.dll
index f867f38..8956247 100644
Binary files a/Assets/NetworkLobbyClient/Runtime/LobbyClient.dll and b/Assets/NetworkLobbyClient/Runtime/LobbyClient.dll differ
diff --git a/Assets/NetworkLobbyClient/Runtime/LobbyServerDto.dll b/Assets/NetworkLobbyClient/Runtime/LobbyServerDto.dll
index 1646bfd..7b5acc4 100644
Binary files a/Assets/NetworkLobbyClient/Runtime/LobbyServerDto.dll and b/Assets/NetworkLobbyClient/Runtime/LobbyServerDto.dll differ
diff --git a/LobbyClient/LobbyClient.cs b/LobbyClient/LobbyClient.cs
index caf24bf..c5ed145 100644
--- a/LobbyClient/LobbyClient.cs
+++ b/LobbyClient/LobbyClient.cs
@@ -173,21 +173,23 @@ namespace Lobbies
/// The lobby to request a nat punch for
/// Optional password of lobby
/// 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
- public void RequestLobbyNatPunch(Guid lobbyId, string? password, int port = 0)
+ /// after that the udp client will be disposed.
+ 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);
diff --git a/LobbyClient/LobbyClientEvent.cs b/LobbyClient/LobbyClientEvent.cs
index 69f78f5..430631e 100644
--- a/LobbyClient/LobbyClientEvent.cs
+++ b/LobbyClient/LobbyClientEvent.cs
@@ -63,6 +63,10 @@
///
/// A direct connection test without a nat punch was testet. EventData is with information if a direct connection was possible and on what address.
///
- DirectConnectionTestComplete
+ DirectConnectionTestComplete,
+ ///
+ /// A join request to a lobby has failed. EventData is with information about the failure.
+ ///
+ LobbyJoinFailed,
}
}
diff --git a/LobbyClient/LobbyJoinFailReason.cs b/LobbyClient/LobbyJoinFailReason.cs
new file mode 100644
index 0000000..f2b14c2
--- /dev/null
+++ b/LobbyClient/LobbyJoinFailReason.cs
@@ -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; }
+ }
+}
diff --git a/LobbyClient/UdpEchoServer.cs b/LobbyClient/UdpEchoServer.cs
index b00d937..81020cf 100644
--- a/LobbyClient/UdpEchoServer.cs
+++ b/LobbyClient/UdpEchoServer.cs
@@ -198,6 +198,7 @@ namespace Lobbies
if (!isDisposed)
{
Stop();
+
while (isRunningV4 || isRunningV6)
Task.Yield();
diff --git a/LobbyServer/Program.cs b/LobbyServer/Program.cs
index 9aa1bb6..67fd490 100644
--- a/LobbyServer/Program.cs
+++ b/LobbyServer/Program.cs
@@ -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;
diff --git a/LobbyServerDto/LobbyNotFound.cs b/LobbyServerDto/LobbyNotFound.cs
new file mode 100644
index 0000000..8682f7d
--- /dev/null
+++ b/LobbyServerDto/LobbyNotFound.cs
@@ -0,0 +1,14 @@
+namespace LobbyServerDto
+{
+ ///
+ /// Send if a client requests information about a password protected lobby with an invalid password hash
+ ///
+ [LobbyMessage]
+ public partial class LobbyNotFound
+ {
+ ///
+ /// Id of the lobby
+ ///
+ public Guid LobbyId { get; set; }
+ }
+}
\ No newline at end of file