diff --git a/com.unity.netcode.adapter.utp/CHANGELOG.md b/com.unity.netcode.adapter.utp/CHANGELOG.md index 3c00f08c28..b4ae4dc9c0 100644 --- a/com.unity.netcode.adapter.utp/CHANGELOG.md +++ b/com.unity.netcode.adapter.utp/CHANGELOG.md @@ -6,11 +6,13 @@ All notable changes to this package will be documented in this file. The format ### Added -- Added new methods to set the relay server data: `SetHostRelayData` and `SetClientRelayData`. These are meant to be less error-prone than `SetRelayServerData` (which remains available). (#1609) +- A new 'Server Listen Address' field under 'Connection Data' in the inspector has been added to specify the address a server should listen to, in case it differs from the main 'Address' field. The `SetConnectionData` method has been updated accordingly to take an optional parameter to specify that listen address. (#1605) ### Changed -- Rename the 'Send Queue Batch Size' property to 'Max Payload Size' to better reflect its usage (#1584) +- Rename the 'Send Queue Batch Size' property to 'Max Payload Size' to better reflect its usage. (#1584) +- Implicit conversions between `ConnectionAddressData` and `NetworkEndPoint` are now deprecated, since their semantics are no longer clear with the introduction of the new `ServerListenAddress` field (see above). (#1605) +- Added new methods to set the relay server data: `SetHostRelayData` and `SetClientRelayData`. These are meant to be less error-prone than `SetRelayServerData` (which remains available). (#1609) - Updated Unity Transport package to 1.0.0-pre.12. (#1615) - Updated Burst package to 1.6.4. (#1615) diff --git a/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs b/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs index 65e4715ee2..f38199ab4d 100644 --- a/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs +++ b/com.unity.netcode.adapter.utp/Runtime/UnityTransport.cs @@ -90,7 +90,7 @@ private enum State public const int InitialMaxSendQueueSize = 16 * InitialMaxPayloadSize; private static ConnectionAddressData s_DefaultConnectionAddressData = new ConnectionAddressData() - { Address = "127.0.0.1", Port = 7777 }; + { Address = "127.0.0.1", Port = 7777, ServerListenAddress = null }; #pragma warning disable IDE1006 // Naming Styles public static INetworkStreamDriverConstructor s_DriverConstructor; @@ -131,22 +131,37 @@ private enum State [Serializable] public struct ConnectionAddressData { + [Tooltip("IP address of the server (address to which clients will connect to).")] [SerializeField] public string Address; - [SerializeField] public int Port; - public static implicit operator NetworkEndPoint(ConnectionAddressData d) + [Tooltip("UDP port of the server.")] + [SerializeField] public ushort Port; + + [Tooltip("IP address the server will listen on. If not provided, will use 'Address'.")] + [SerializeField] public string ServerListenAddress; + + private static NetworkEndPoint ParseNetworkEndpoint(string ip, ushort port) { - if (!NetworkEndPoint.TryParse(d.Address, (ushort)d.Port, out var networkEndPoint)) + if (!NetworkEndPoint.TryParse(ip, port, out var endpoint)) { - Debug.LogError($"Invalid address {d.Address}:{d.Port}"); + Debug.LogError($"Invalid network endpoint: {ip}:{port}."); return default; } - return networkEndPoint; + return endpoint; } + public NetworkEndPoint ServerEndPoint => ParseNetworkEndpoint(Address, Port); + + public NetworkEndPoint ListenEndPoint => ParseNetworkEndpoint(ServerListenAddress ?? Address, Port); + + [Obsolete("Use ServerEndPoint or ListenEndPoint properties instead.")] + public static implicit operator NetworkEndPoint(ConnectionAddressData d) => + ParseNetworkEndpoint(d.Address, d.Port); + + [Obsolete("Construct manually from NetworkEndPoint.Address and NetworkEndPoint.Port instead.")] public static implicit operator ConnectionAddressData(NetworkEndPoint d) => - new ConnectionAddressData() { Address = d.Address.Split(':')[0], Port = d.Port }; + new ConnectionAddressData() { Address = d.Address.Split(':')[0], Port = d.Port, ServerListenAddress = null }; } public ConnectionAddressData ConnectionData = s_DefaultConnectionAddressData; @@ -272,7 +287,7 @@ private bool ClientBindAndConnect() } else { - serverEndpoint = ConnectionData; + serverEndpoint = ConnectionData.ServerEndPoint; } InitDriver(); @@ -421,26 +436,36 @@ public void SetClientRelayData(string ipAddress, ushort port, byte[] allocationI /// /// Sets IP and Port information. This will be ignored if using the Unity Relay and you should call /// - public void SetConnectionData(string ipv4Address, ushort port) + public void SetConnectionData(string ipv4Address, ushort port, string listenAddress = null) { - if (!NetworkEndPoint.TryParse(ipv4Address, port, out var endPoint)) + ConnectionData = new ConnectionAddressData { - Debug.LogError($"Invalid address {ipv4Address}:{port}"); - ConnectionData = default; - - return; - } + Address = ipv4Address, + Port = port, + ServerListenAddress = listenAddress + }; - SetConnectionData(endPoint); + SetProtocol(ProtocolType.UnityTransport); } /// /// Sets IP and Port information. This will be ignored if using the Unity Relay and you should call /// - public void SetConnectionData(NetworkEndPoint endPoint) + public void SetConnectionData(NetworkEndPoint endPoint, NetworkEndPoint listenEndPoint = default) { - ConnectionData = endPoint; - SetProtocol(ProtocolType.UnityTransport); + string serverAddress = endPoint.Address.Split(':')[0]; + + string listenAddress = null; + if (listenEndPoint != default) + { + listenAddress = listenEndPoint.Address.Split(':')[0]; + if (endPoint.Port != listenEndPoint.Port) + { + Debug.LogError($"Port mismatch between server and listen endpoints ({endPoint.Port} vs {listenEndPoint.Port})."); + } + } + + SetConnectionData(serverAddress, endPoint.Port, listenAddress); } private bool StartRelayServer() @@ -829,7 +854,7 @@ public override bool StartServer() switch (m_ProtocolType) { case ProtocolType.UnityTransport: - return ServerBindAndListen(ConnectionData); + return ServerBindAndListen(ConnectionData.ListenEndPoint); case ProtocolType.RelayUnityTransport: return StartRelayServer(); default: diff --git a/com.unity.netcode.adapter.utp/Tests/Runtime/ConnectionTests.cs b/com.unity.netcode.adapter.utp/Tests/Runtime/ConnectionTests.cs index e8df91dc19..dc53cf5949 100644 --- a/com.unity.netcode.adapter.utp/Tests/Runtime/ConnectionTests.cs +++ b/com.unity.netcode.adapter.utp/Tests/Runtime/ConnectionTests.cs @@ -70,7 +70,6 @@ public IEnumerator Cleanup() [UnityTest] public IEnumerator ConnectSingleClient() { - InitializeTransport(out m_Server, out m_ServerEvents); InitializeTransport(out m_Clients[0], out m_ClientsEvents[0]); @@ -90,7 +89,6 @@ public IEnumerator ConnectSingleClient() [UnityTest] public IEnumerator ConnectMultipleClients() { - InitializeTransport(out m_Server, out m_ServerEvents); m_Server.StartServer(); @@ -251,7 +249,6 @@ public IEnumerator RepeatedServerDisconnectsNoop() [UnityTest] public IEnumerator RepeatedClientDisconnectsNoop() { - InitializeTransport(out m_Server, out m_ServerEvents); InitializeTransport(out m_Clients[0], out m_ClientsEvents[0]); @@ -278,6 +275,28 @@ public IEnumerator RepeatedClientDisconnectsNoop() yield return null; } + + // Check connection with different server/listen addresses. + [UnityTest] + public IEnumerator DifferentServerAndListenAddresses() + { + InitializeTransport(out m_Server, out m_ServerEvents); + InitializeTransport(out m_Clients[0], out m_ClientsEvents[0]); + + m_Server.SetConnectionData("127.0.0.1", 10042, "0.0.0.0"); + m_Clients[0].SetConnectionData("127.0.0.1", 10042); + + m_Server.StartServer(); + m_Clients[0].StartClient(); + + yield return WaitForNetworkEvent(NetworkEvent.Connect, m_ClientsEvents[0]); + + // Check we've received Connect event on server too. + Assert.AreEqual(1, m_ServerEvents.Count); + Assert.AreEqual(NetworkEvent.Connect, m_ServerEvents[0].Type); + + yield return null; + } } } #endif