diff --git a/Assets/NetworkLobbyClient/Runtime/LobbyClient.dll b/Assets/NetworkLobbyClient/Runtime/LobbyClient.dll index b750ab3..6a05c08 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 b270f47..1646bfd 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 3554cb2..b6c42dc 100644 --- a/LobbyClient/LobbyClient.cs +++ b/LobbyClient/LobbyClient.cs @@ -4,6 +4,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Net; +using System.Net.NetworkInformation; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; @@ -18,6 +19,8 @@ namespace Lobbies AutoResetEvent waitForExternalIp = new AutoResetEvent(false); + UdpEchoServer udpEchoServer = new UdpEchoServer(); + private Dictionary lobbyInformation = new Dictionary(); private string? host; private int port; @@ -75,6 +78,8 @@ namespace Lobbies public void HostLobby(Guid gameId, string name, int gameMode, int maxPlayerCount, string? password, string? ip, int port) { + udpEchoServer.Start(0); + byte[]? hash = null, salt = null; if(!string.IsNullOrEmpty(password)) @@ -91,8 +96,9 @@ namespace Lobbies PlayerCount = 0, PasswordHash = hash, PasswordSalt = salt, - HostIp = ip, - HostPort = port + HostIps = GatherLocalIpAddresses().ToArray(), + HostPort = port, + HostTryPort = udpEchoServer.Port }; byte[] messageData = bufferRental.Rent(); @@ -142,7 +148,7 @@ namespace Lobbies }); } - public void UpdateLobby(string name, int gameMode, int maxPlayerCount, int playerCount, string? password, string? ip, int port) + public void UpdateLobby(string name, int gameMode, int maxPlayerCount, int playerCount, string? password, int port) { byte[]? hash = null, salt = null; @@ -159,8 +165,9 @@ namespace Lobbies PlayerCount = playerCount, PasswordHash = hash, PasswordSalt = salt, - HostIp = ip, - HostPort = port + HostIps = GatherLocalIpAddresses().ToArray(), + HostPort = port, + HostTryPort = udpEchoServer.Port }; byte[] messageData = bufferRental.Rent(); @@ -170,6 +177,8 @@ namespace Lobbies public void CloseLobby() { + udpEchoServer.Stop(); + var lobbyDelete = new LobbyDelete() { @@ -207,6 +216,32 @@ namespace Lobbies _ = Task.Run(async () => { await tcpClient.Send(messageData, 0, len); bufferRental.Return(messageData); }); } + public async Task TryDirectConnection(IPAddress[] ipAddressesToTry, int tryPort) + { + return await Task.Run(() => + { + IPAddress? ret = null; + using (var udpEchoClient = new UdpEchoServer()) + { + udpEchoClient.Reached += (ep) => + { + ret = ep.Address; + }; + + udpEchoClient.Start(0); + + foreach (var ip in ipAddressesToTry) + { + udpEchoClient.CheckConnectionPossible(new IPEndPoint(ip, tryPort)); + } + + Thread.Sleep(500); + } + + return ret; + }); + } + public static IPAddress[] GetIPsByName(string hostName, bool ip4Wanted, bool ip6Wanted) { // Check if the hostname is already an IPAddress @@ -214,7 +249,7 @@ namespace Lobbies if (IPAddress.TryParse(hostName, out outIpAddress) == true) return new IPAddress[] { outIpAddress }; //<---------- - + IPAddress[] addresslist = Dns.GetHostAddresses(hostName); if (addresslist == null || addresslist.Length == 0) @@ -361,10 +396,24 @@ namespace Lobbies catch { } } + public IEnumerable GatherLocalIpAddresses() + { + foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces()) + { + IPInterfaceProperties ipProps = netInterface.GetIPProperties(); + + foreach (UnicastIPAddressInformation addr in ipProps.UnicastAddresses) + { + yield return addr.Address; + } + } + } + public void Dispose() { waitForExternalIp.Dispose(); tcpClient.Dispose(); + udpEchoServer.Dispose(); } } diff --git a/LobbyClient/UdpEchoServer.cs b/LobbyClient/UdpEchoServer.cs new file mode 100644 index 0000000..db63b30 --- /dev/null +++ b/LobbyClient/UdpEchoServer.cs @@ -0,0 +1,197 @@ +using System.Net.Sockets; +using System.Net; +using System.Threading.Tasks; +using System.Threading; +using System; + +namespace Lobbies +{ + /// + /// Small udp server to receive udp packets and echo the data back to source + /// + internal class UdpEchoServer : IDisposable + { + public const int SIO_UDP_CONNRESET = -1744830452; + + private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); + private bool running = false; + private bool isDisposed = false; + private UdpClient? serverSocketV4, serverSocketV6; + + public delegate void ReachableEventArgs(IPEndPoint remoteEndpoint); + /// + /// If a valid request for a ip and port query comes in call this event with the seen remote ip and port for a lobby server client id + /// + public event ReachableEventArgs? Reached; + + public int Port { get; private set; } + private bool isRunningV4 = false, isRunningV6 = false; + + public void CheckConnectionPossible(IPEndPoint remoteEndpoint) + { + if (!running || serverSocketV4 == null || serverSocketV6 == null) + throw new Exception("Listener not running!"); + + byte[] magicRequest = new byte[] { 0 }; + for (int i = 0; i < 16; i++) + if(remoteEndpoint.AddressFamily == AddressFamily.InterNetwork) + serverSocketV4.Send(magicRequest, magicRequest.Length, remoteEndpoint); + else + serverSocketV6.Send(magicRequest, magicRequest.Length, remoteEndpoint); + } + + /// + /// Listen to requests and fire events + /// + /// The port to listen on + private async void ListenV4(int port) + { + try + { + cancellationTokenSource.Token.ThrowIfCancellationRequested(); + serverSocketV4 = new UdpClient(port, AddressFamily.InterNetwork); + serverSocketV4.Client.IOControl( + (IOControlCode)SIO_UDP_CONNRESET, + new byte[] { 0, 0, 0, 0 }, + null + ); + Port = ((IPEndPoint)serverSocketV4.Client.LocalEndPoint).Port; + byte[] magicAnswer = new byte[] { 1 }; + using (cancellationTokenSource.Token.Register(() => { serverSocketV4.Close(); })) + { + isRunningV4 = true; + while (running) + { + var receiveResult = await serverSocketV4.ReceiveAsync(); + if (receiveResult.Buffer.Length == 1) + { + if (receiveResult.Buffer[0] == 0) + { + for (int i = 0; i < 16; i++) + serverSocketV4.Send(magicAnswer, magicAnswer.Length, receiveResult.RemoteEndPoint); + } + + if (receiveResult.Buffer[0] == 1) + { + Reached?.Invoke(receiveResult.RemoteEndPoint); + } + } + } + } + } + catch when (cancellationTokenSource.IsCancellationRequested || !running) //Cancel requested + { + + } + catch + { + throw; + } + finally + { + serverSocketV4?.Dispose(); + serverSocketV4 = null; + running = false; + isRunningV4 = false; + } + } + + /// + /// Listen to requests and fire events + /// + /// The port to listen on + private async void ListenV6(int port) + { + try + { + cancellationTokenSource.Token.ThrowIfCancellationRequested(); + serverSocketV6 = new UdpClient(port, AddressFamily.InterNetworkV6); + serverSocketV6.Client.IOControl( + (IOControlCode)SIO_UDP_CONNRESET, + new byte[] { 0, 0, 0, 0 }, + null + ); + byte[] magicAnswer = new byte[] { 1 }; + using (cancellationTokenSource.Token.Register(() => { serverSocketV6.Close(); })) + { + isRunningV6 = true; + while (running) + { + var receiveResult = await serverSocketV6.ReceiveAsync(); + if (receiveResult.Buffer.Length == 1) + { + if (receiveResult.Buffer[0] == 0) + { + Reached?.Invoke(receiveResult.RemoteEndPoint); + } + + if (receiveResult.Buffer[0] == 1) + { + for (int i = 0; i < 16; i++) + serverSocketV6.Send(magicAnswer, magicAnswer.Length, receiveResult.RemoteEndPoint); + } + } + } + } + } + catch when (cancellationTokenSource.IsCancellationRequested || !running) //Cancel requested + { + + } + catch + { + throw; + } + finally + { + serverSocketV6?.Dispose(); + serverSocketV6 = null; + running = false; + isRunningV6 = false; + } + } + + /// + /// Start udp listener + /// + /// The port to listen on + public void Start(int port) + { + isRunningV4 = false; + isRunningV6 = false; + running = true; + _ = Task.Run(() => ListenV4(port)); + while (running && !isRunningV4) + Thread.Yield(); + _ = Task.Run(() => ListenV6(Port)); + while (running && (!isRunningV4 || !isRunningV6)) + Thread.Yield(); + } + + /// + /// Stop udp listener + /// + public void Stop() + { + running = false; + cancellationTokenSource.Cancel(); + if (serverSocketV4 != null) + serverSocketV4?.Close(); + if (serverSocketV6 != null) + serverSocketV6?.Close(); + } + + public void Dispose() + { + if (!isDisposed) + { + Stop(); + while (isRunningV4 || isRunningV6) + Task.Yield(); + + cancellationTokenSource.Dispose(); + isDisposed = true; + } + } + } +} diff --git a/LobbyClientTest/Program.cs b/LobbyClientTest/Program.cs index 4d22e13..430252c 100644 --- a/LobbyClientTest/Program.cs +++ b/LobbyClientTest/Program.cs @@ -3,6 +3,7 @@ using Lobbies; using LobbyClientTest; using LobbyServerDto; using System.Net; +using System.Net.WebSockets; Console.WriteLine("Starting lobby client v0.7!"); var lobbyClient = new LobbyClient(); @@ -16,12 +17,11 @@ FakeGameHost fakeGameHost = new FakeGameHost(); int myPort = fakeGameHost.Server(0); string? myExternalIp = null; int myExternalPort = -1; -IPEndPoint? hostInfo = null; bool running = true; bool connected = false; -_ = Task.Run(() => +_ = Task.Run(async () => { while (running) { @@ -78,8 +78,23 @@ _ = Task.Run(() => var lobbyHostInfo = lobbyEvent.EventData as LobbyHostInfo; var p = Console.GetCursorPosition(); Console.SetCursorPosition(0, p.Top); - Console.WriteLine($"Host info for lobby {lobbyHostInfo!.LobbyId} is {lobbyHostInfo.HostIp}:{lobbyHostInfo.HostPort}!"); - hostInfo = new IPEndPoint(IPAddress.Parse(lobbyHostInfo.HostIp!), lobbyHostInfo.HostPort); + Console.WriteLine($"Host info for lobby {lobbyHostInfo!.LobbyId} is {(lobbyHostInfo.HostIps != null && lobbyHostInfo.HostIps.Length > 0 ? lobbyHostInfo.HostIps[0].ToString() : "")}:{lobbyHostInfo.HostPort}!"); + + //Try direct connection + if (lobbyHostInfo.HostIps != null && lobbyHostInfo.HostIps.Length > 0) + { + Console.WriteLine($"Trying direct connection to {string.Join(",", lobbyHostInfo.HostIps)} on port {lobbyHostInfo.HostTryPort}!"); + var reachableIp = await lobbyClient.TryDirectConnection(lobbyHostInfo.HostIps, lobbyHostInfo.HostTryPort); + if(reachableIp != null) + { + Console.WriteLine($"Direct connection to {reachableIp.ToString()} possible, using direct connection!"); + Console.WriteLine($"Connecting game client!"); + fakeGameHost.Send(new IPEndPoint(reachableIp, lobbyHostInfo.HostPort), "Hello from Game Client!"); + Console.Write(">"); + continue; + } + } + Console.WriteLine($"Requesting nat punch to me!"); lobbyClient.RequestLobbyNatPunch(lobbyHostInfo.LobbyId, null, (remoteEndpoint, messageBuffer, messageLength) => { fakeGameHost.Send(remoteEndpoint, messageBuffer, messageLength); @@ -111,7 +126,7 @@ _ = Task.Run(() => Console.SetCursorPosition(0, p.Top); Console.WriteLine($"Nat punch requested to {lobbyRequestNatPunch!.ClientIp}:{lobbyRequestNatPunch.ClientPort}!"); - Task.Run(() => + _ = Task.Run(() => { lobbyClient.QueryExternalIpAndPort((remoteEndpoint, messageData, messageLength) => { fakeGameHost.Send(remoteEndpoint, messageData, messageLength); @@ -140,7 +155,6 @@ _ = Task.Run(() => Console.SetCursorPosition(0, p.Top); Console.WriteLine($"Nat punch request done!"); Console.WriteLine($"Connecting game client!"); - fakeGameHost.Send(new IPEndPoint(IPAddress.Parse(lobbyNatPunchDone!.ExternalIp!), lobbyNatPunchDone.ExternalPort), "Hello from Game Client!"); Console.Write(">"); } diff --git a/LobbyServer/Lobby.cs b/LobbyServer/Lobby.cs index 5ba8b79..95eb0a2 100644 --- a/LobbyServer/Lobby.cs +++ b/LobbyServer/Lobby.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Text; using System.Threading.Tasks; @@ -24,7 +25,8 @@ namespace LobbyServer public int MaxPlayerCount { get; set; } public byte[]? PasswordHash { get; set; } public byte[]? PasswordSalt { get; set; } - public required string HostIp { get; set; } + public required IPAddress[] HostIps { get; set; } public int HostPort { get; set; } + public int HostTryPort { get; set; } } } diff --git a/LobbyServer/Program.cs b/LobbyServer/Program.cs index 7473bf0..9aa1bb6 100644 --- a/LobbyServer/Program.cs +++ b/LobbyServer/Program.cs @@ -1,7 +1,7 @@ using LobbyServer; using LobbyServerDto; using System.Collections.Concurrent; - +using System.Net; using var closing = new AutoResetEvent(false); using var tcpServer = new TcpServer(); @@ -42,6 +42,11 @@ tcpServer.DataReceived += (clientId, dataLength, data) => if (!GameGuids.ValidGuids.Contains(lobbyCreate.GameId)) throw new Exception("Invalid game guid!"); + List hostIpAddresses = new List(); + hostIpAddresses.Add(IPAddress.Parse(tcpServer.GetClientIp(clientId)!)); + if(lobbyCreate.HostIps != null) + hostIpAddresses.AddRange(lobbyCreate.HostIps); + var lobby = new Lobby { Name = lobbyCreate.Name, @@ -52,8 +57,9 @@ tcpServer.DataReceived += (clientId, dataLength, data) => PasswordHash = lobbyCreate.PasswordHash, PasswordSalt = lobbyCreate.PasswordSalt, HostClientId = clientId, - HostIp = lobbyCreate.HostIp == null ? tcpServer.GetClientIp(clientId)! : lobbyCreate.HostIp, + HostIps = hostIpAddresses.ToArray(), HostPort = lobbyCreate.HostPort, + HostTryPort = lobbyCreate.HostTryPort }; if(lobbiesByClientId.TryGetValue(clientId, out var existingLobby)) @@ -113,10 +119,17 @@ tcpServer.DataReceived += (clientId, dataLength, data) => existingLobby.PasswordHash = lobbyUpdate.PasswordHash; existingLobby.PasswordSalt = lobbyUpdate.PasswordSalt; - if (lobbyUpdate.HostIp != null) - existingLobby.HostIp = lobbyUpdate.HostIp; + List hostIpAddresses = new List(); + hostIpAddresses.Add(IPAddress.Parse(tcpServer.GetClientIp(clientId)!)); + if (lobbyUpdate.HostIps != null) + hostIpAddresses.AddRange(lobbyUpdate.HostIps); + + if (!Enumerable.SequenceEqual(existingLobby.HostIps, hostIpAddresses)) + existingLobby.HostIps = hostIpAddresses.ToArray(); existingLobby.HostPort = lobbyUpdate.HostPort; + existingLobby.HostTryPort = lobbyUpdate.HostTryPort; + _ = Task.Run(() => SendLobbyUpdate(Lobby.LobbyUpdateType.Update, existingLobby)); } } @@ -221,7 +234,7 @@ tcpServer.DataReceived += (clientId, dataLength, data) => { var messageData = bufferRental.Rent(); - var lobbyHostInfo = new LobbyHostInfo() { LobbyId = lobby.Id, HostIp = lobby.HostIp, HostPort = lobby.HostPort }; + var lobbyHostInfo = new LobbyHostInfo() { LobbyId = lobby.Id, HostIps = lobby.HostIps, HostPort = lobby.HostPort, HostTryPort = lobby.HostTryPort }; var messageDataLength = lobbyHostInfo.Serialize(messageData); _ = Task.Run(async () => { @@ -426,7 +439,7 @@ Console.CancelKeyPress += (sender, args) => args.Cancel = true; }; -Console.WriteLine($"{DateTime.Now}: Application started v0.7"); +Console.WriteLine($"{DateTime.Now}: Application started v0.8"); udpServer.Start(8088); tcpServer.Start(8088); diff --git a/LobbyServerDto/LobbyCreate.cs b/LobbyServerDto/LobbyCreate.cs index f3159a6..0a3a34d 100644 --- a/LobbyServerDto/LobbyCreate.cs +++ b/LobbyServerDto/LobbyCreate.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using System.Net; namespace LobbyServerDto { @@ -41,13 +42,17 @@ namespace LobbyServerDto [MaxLength(16)] public byte[]? PasswordSalt { get; set; } /// - /// The hosts ip. Used the the host information send to clients on their request. + /// The hosts ip addresses locally detected. Used the the host information send to clients on their request. /// [MaxLength(32)] - public string? HostIp { get; set; } + public IPAddress[]? HostIps { get; set; } /// /// The hosts port. Used the the host information send to clients on their request. /// public int HostPort { get; set; } + /// + /// The hosts echo port to try if a connection is possible. + /// + public int HostTryPort { get; set; } } } \ No newline at end of file diff --git a/LobbyServerDto/LobbyHostInfo.cs b/LobbyServerDto/LobbyHostInfo.cs index cbed3aa..83389b1 100644 --- a/LobbyServerDto/LobbyHostInfo.cs +++ b/LobbyServerDto/LobbyHostInfo.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using System.Net; namespace LobbyServerDto { @@ -13,13 +14,17 @@ namespace LobbyServerDto /// public Guid LobbyId { get; set; } /// - /// The hosts ip, this could be an internal address + /// The hosts ip addresses locally detected. Used the the host information send to clients on their request. /// [MaxLength(32)] - public string? HostIp { get; set; } + public IPAddress[]? HostIps { get; set; } /// /// The hosts port /// public int HostPort { get; set; } + /// + /// The hosts echo port to try if a connection is possible. + /// + public int HostTryPort { get; set; } } } \ No newline at end of file diff --git a/LobbyServerDto/LobbyUpdate.cs b/LobbyServerDto/LobbyUpdate.cs index d9dd5d1..281bf50 100644 --- a/LobbyServerDto/LobbyUpdate.cs +++ b/LobbyServerDto/LobbyUpdate.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using System.Net; namespace LobbyServerDto { @@ -7,7 +8,7 @@ namespace LobbyServerDto /// [LobbyMessage] public partial class LobbyUpdate - { + { /// /// The displayname of the lobby /// @@ -34,13 +35,17 @@ namespace LobbyServerDto [MaxLength(16)] public byte[]? PasswordSalt { get; set; } /// - /// The hosts ip + /// The hosts ip addresses locally detected. Used the the host information send to clients on their request. /// [MaxLength(32)] - public string? HostIp { get; set; } + public IPAddress[]? HostIps { get; set; } /// - /// The hosts port + /// The hosts port. Used the the host information send to clients on their request. /// public int HostPort { get; set; } + /// + /// The hosts echo port to try if a connection is possible. + /// + public int HostTryPort { get; set; } } } \ No newline at end of file diff --git a/LobbyServerSourceGenerator/LobbyMessageSourceGenerator.cs b/LobbyServerSourceGenerator/LobbyMessageSourceGenerator.cs index 973b5e4..cf0ff08 100644 --- a/LobbyServerSourceGenerator/LobbyMessageSourceGenerator.cs +++ b/LobbyServerSourceGenerator/LobbyMessageSourceGenerator.cs @@ -74,6 +74,7 @@ namespace LobbyServerDto s.Append(@$"// using System.Collections.Generic; using System.Text; +using System.Net; {(foundClass.Value.nameSpace is null ? null : $@"namespace {foundClass.Value.nameSpace} {{")} @@ -113,6 +114,34 @@ using System.Text; var name = p.Identifier.ToString(); switch(p.Type.ToString()) { + case "IPAddress[]": + case "IPAddress[]?": + s.Append($@" + if ({name} != null) + {{ + int maxLength = Math.Min({name}.Length, {maxLength}); + uint v = (uint)maxLength; + while (v >= 0x80) + {{ + buffer[offset++] = (byte)(v | 0x80); + v >>= 7; + }} + buffer[offset++] = (byte)v; + + for(int i = 0; i < maxLength; i++) + {{ + var ipBuffer = {name}[i].GetAddressBytes(); + buffer[offset++] = (byte)ipBuffer.Length; + Buffer.BlockCopy(ipBuffer, 0, buffer, offset, ipBuffer.Length); + offset += ipBuffer.Length; + }} + }} + else + {{ + buffer[offset++] = 0; + }} +"); + break; case "bool": s.Append($@" buffer[offset++] = (byte)({name} == true ? 1 : 0);"); @@ -226,6 +255,42 @@ using System.Text; var name = p.Identifier.ToString(); switch (p.Type.ToString()) { + case "IPAddress[]": + case "IPAddress[]?": + s.Append($@" + {{ + int arrayLen = 0; + int shift = 0; + byte b; + do {{ + // Check for a corrupted stream. Read a max of 5 bytes. + // In a future version, add a DataFormatException. + if (shift == 5 * 7) // 5 bytes max per Int32, shift += 7 + throw new FormatException(""Format_Bad7BitInt32""); + + // ReadByte handles end of stream cases for us. + b = buffer[offset++]; + arrayLen |= (b & 0x7F) << shift; + shift += 7; + }} while ((b & 0x80) != 0); + + if(arrayLen > {maxLength}) + throw new FormatException(""Format_IPAddressArrayToLong""); + + if(arrayLen > 0) + {{ + ret.{name} = new IPAddress[arrayLen]; + for(int i=0; i < arrayLen; i++) + {{ + var itemLen = buffer[offset++]; + if(itemLen > 16) + throw new FormatException(""Format_IPAddressBytesArrayToLong""); + ret.{name}[i] = new IPAddress(buffer.Slice(offset, itemLen).ToArray()); + offset += itemLen; + }} + }} + }}"); + break; case "bool": s.Append($@" ret.{name} = buffer[offset++] == 0 ? false : true;"); @@ -236,10 +301,10 @@ using System.Text; break; case "Guid": s.Append($@" - {{ - ret.{name} = new Guid(buffer.Slice(offset, 16).ToArray()); - offset+=16; - }}"); + {{ + ret.{name} = new Guid(buffer.Slice(offset, 16).ToArray()); + offset+=16; + }}"); break; case "string": case "string?": @@ -260,6 +325,9 @@ using System.Text; shift += 7; }} while ((b & 0x80) != 0); + if(strLen > {maxLength}) + throw new FormatException(""Format_StringToLong""); + if(strLen > 0) {{ ret.{name} = Encoding.UTF8.GetString(buffer.Slice(offset, strLen).ToArray()); @@ -271,7 +339,7 @@ using System.Text; case "byte[]?": s.Append($@" {{ - int strLen = 0; + int byteLen = 0; int shift = 0; byte b; do {{ @@ -282,14 +350,17 @@ using System.Text; // ReadByte handles end of stream cases for us. b = buffer[offset++]; - strLen |= (b & 0x7F) << shift; + byteLen |= (b & 0x7F) << shift; shift += 7; }} while ((b & 0x80) != 0); - if(strLen > 0) + if(byteLen > {maxLength}) + throw new FormatException(""Format_ByteArrayToLong""); + + if(byteLen > 0) {{ - ret.{name} = buffer.Slice(offset, strLen).ToArray(); - offset += strLen; + ret.{name} = buffer.Slice(offset, byteLen).ToArray(); + offset += byteLen; }} }}"); break; diff --git a/LobbyServerSourceGenerator/LobbyServerSourceGenerator.csproj b/LobbyServerSourceGenerator/LobbyServerSourceGenerator.csproj index 8845a69..a6941ba 100644 --- a/LobbyServerSourceGenerator/LobbyServerSourceGenerator.csproj +++ b/LobbyServerSourceGenerator/LobbyServerSourceGenerator.csproj @@ -15,10 +15,6 @@ - - - -