diff --git a/Assets/Mirror/Transports/Ignorance/Core/IgnoranceClient.cs b/Assets/Mirror/Transports/Ignorance/Core/IgnoranceClient.cs index 1a04989..ae0a511 100644 --- a/Assets/Mirror/Transports/Ignorance/Core/IgnoranceClient.cs +++ b/Assets/Mirror/Transports/Ignorance/Core/IgnoranceClient.cs @@ -36,6 +36,29 @@ public class IgnoranceClient public int ConnectionEventBufferSize = 100; // Client connection address public string ConnectAddress = "127.0.0.1"; + // The local end-point that the client connects from + public bool BindToRandomLocalEndPoint = true; + private string UnsafeBindAddress = "127.0.0.1"; + public string BindAddress { + get { + lock (BindAddressLock) return UnsafeBindAddress; + } + set { + lock (BindAddressLock) UnsafeBindAddress = value; + } + } + private ushort UnsafeBindPort = 0; + public ushort BindPort + { + get + { + lock (BindPortLock) return UnsafeBindPort; + } + set + { + lock (BindPortLock) UnsafeBindPort = value; + } + } // Queues public RingBuffer Incoming; @@ -49,6 +72,9 @@ public class IgnoranceClient private volatile bool CeaseOperation = false; private Thread WorkerThread; + private object BindAddressLock = new object(); + private object BindPortLock = new object(); + public void Start() { if (WorkerThread != null && WorkerThread.IsAlive) @@ -70,7 +96,10 @@ public void Start() MaxNativeTimeout = MaxClientNativeTimeout > 0 ? MaxClientNativeTimeout : 0, PollTime = PollTime, PacketSizeLimit = MaximumPacketSize, - Verbosity = Verbosity + Verbosity = Verbosity, + BindToRandomLocalEndPoint = BindToRandomLocalEndPoint, + BindAddress = UnsafeBindAddress, + BindPort = UnsafeBindPort }; // Drain queues. @@ -139,13 +168,31 @@ private void ThreadWorker(Object parameters) { try { - clientHost.Create(); + if (BindToRandomLocalEndPoint) + { + clientHost.Create(); + } + else + { + Address explicitBindAddress = new Address(); + explicitBindAddress.SetHost(setupInfo.BindAddress); + explicitBindAddress.Port = (ushort)setupInfo.BindPort; + clientHost.Create(explicitBindAddress, 1); + } Debug.Log($"Ignorance: Client worker thread attempting connection to '{setupInfo.Address}:{setupInfo.Port}'."); clientPeer = clientHost.Connect(clientAddress, setupInfo.Channels); + if (setupInfo.BindToRandomLocalEndPoint) + { + // Store the local endpoint, useful for implementing port-forwarding, nat traversal, ice, turn, stun, etc. + // This is thread safe since the properties lock + BindAddress = clientPeer.IP; + BindPort = clientPeer.Port; + } + // Apply the custom native timeout if needed. - if(setupInfo.MaxNativeTimeout > 0) + if (setupInfo.MaxNativeTimeout > 0) { clientPeer.Timeout(Library.timeoutLimit, Library.timeoutMinimum, (uint)MaxClientNativeTimeout * 1000); } @@ -356,6 +403,9 @@ private void SetupRingBuffersIfNull() private struct ThreadParamInfo { + public bool BindToRandomLocalEndPoint; + public string BindAddress; + public int BindPort; public int Channels; public int PollTime; public int MaxNativeTimeout; diff --git a/Assets/Mirror/Transports/Ignorance/Ignorance.cs b/Assets/Mirror/Transports/Ignorance/Ignorance.cs index 0e556cc..3064e7f 100644 --- a/Assets/Mirror/Transports/Ignorance/Ignorance.cs +++ b/Assets/Mirror/Transports/Ignorance/Ignorance.cs @@ -9,6 +9,7 @@ using Mirror; using System; using System.Collections.Generic; +using System.Net; using UnityEngine; namespace IgnoranceTransport @@ -322,6 +323,18 @@ public override Uri ServerUri() return builder.Uri; } + public IPEndPoint GetLocalEndPoint() + { + if (Server != null) + { + return new IPEndPoint(IPAddress.Parse(Server.BindAddress), Server.BindPort); + } + else + { + return new IPEndPoint(IPAddress.Parse(Client.BindAddress), Client.BindPort); + } + } + public override void Shutdown() { // TODO: Nothing needed here?