Skip to content

Commit 1aa8d5b

Browse files
Merge branch 'develop-2.0.0' into bacport-information-in-pr-test-develop-2.0.0
2 parents d933c7a + 23412a0 commit 1aa8d5b

File tree

5 files changed

+99
-107
lines changed

5 files changed

+99
-107
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
2222

2323
### Fixed
2424

25+
- Fixed an issue in `UnityTransport` where the transport would accept sends on invalid connections, leading to a useless memory allocation and confusing error message. (#3382)
2526
- Fixed issue where the time delta that interpolators used would not be properly updated during multiple fixed update invocations within the same player loop frame. (#3355)
2627
- Fixed issue when using a distributed authority network topology and many clients attempt to connect simultaneously the session owner could max-out the maximum in-flight reliable messages allowed, start dropping packets, and some of the connecting clients would fail to fully synchronize. (#3350)
2728
- Fixed issue when using a distributed authority network topology and scene management was disabled clients would not be able to spawn any new network prefab instances until synchronization was complete. (#3350)

com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs

Lines changed: 75 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
using Unity.Networking.Transport.TLS;
1717
using Unity.Networking.Transport.Utilities;
1818
using UnityEngine;
19-
using NetcodeNetworkEvent = Unity.Netcode.NetworkEvent;
20-
using TransportNetworkEvent = Unity.Networking.Transport.NetworkEvent;
19+
20+
using NetcodeEvent = Unity.Netcode.NetworkEvent;
21+
using TransportError = Unity.Networking.Transport.Error.StatusCode;
22+
using TransportEvent = Unity.Networking.Transport.NetworkEvent.Type;
2123

2224
namespace Unity.Netcode.Transports.UTP
2325
{
@@ -42,56 +44,6 @@ void CreateDriver(
4244
out NetworkPipeline reliableSequencedPipeline);
4345
}
4446

45-
/// <summary>
46-
/// Helper utility class to convert <see cref="Networking.Transport"/> error codes to human readable error messages.
47-
/// </summary>
48-
public static class ErrorUtilities
49-
{
50-
private static readonly FixedString128Bytes k_NetworkSuccess = "Success";
51-
private static readonly FixedString128Bytes k_NetworkIdMismatch = "Invalid connection ID {0}.";
52-
private static readonly FixedString128Bytes k_NetworkVersionMismatch = "Connection ID is invalid. Likely caused by sending on stale connection {0}.";
53-
private static readonly FixedString128Bytes k_NetworkStateMismatch = "Connection state is invalid. Likely caused by sending on connection {0} which is stale or still connecting.";
54-
private static readonly FixedString128Bytes k_NetworkPacketOverflow = "Packet is too large to be allocated by the transport.";
55-
private static readonly FixedString128Bytes k_NetworkSendQueueFull = "Unable to queue packet in the transport. Likely caused by send queue size ('Max Send Queue Size') being too small.";
56-
57-
/// <summary>
58-
/// Convert a UTP error code to human-readable error message.
59-
/// </summary>
60-
/// <param name="error">UTP error code.</param>
61-
/// <param name="connectionId">ID of the connection on which the error occurred.</param>
62-
/// <returns>Human-readable error message.</returns>
63-
public static string ErrorToString(Networking.Transport.Error.StatusCode error, ulong connectionId)
64-
{
65-
return ErrorToString((int)error, connectionId);
66-
}
67-
68-
internal static string ErrorToString(int error, ulong connectionId)
69-
{
70-
return ErrorToFixedString(error, connectionId).ToString();
71-
}
72-
73-
internal static FixedString128Bytes ErrorToFixedString(int error, ulong connectionId)
74-
{
75-
switch ((Networking.Transport.Error.StatusCode)error)
76-
{
77-
case Networking.Transport.Error.StatusCode.Success:
78-
return k_NetworkSuccess;
79-
case Networking.Transport.Error.StatusCode.NetworkIdMismatch:
80-
return FixedString.Format(k_NetworkIdMismatch, connectionId);
81-
case Networking.Transport.Error.StatusCode.NetworkVersionMismatch:
82-
return FixedString.Format(k_NetworkVersionMismatch, connectionId);
83-
case Networking.Transport.Error.StatusCode.NetworkStateMismatch:
84-
return FixedString.Format(k_NetworkStateMismatch, connectionId);
85-
case Networking.Transport.Error.StatusCode.NetworkPacketOverflow:
86-
return k_NetworkPacketOverflow;
87-
case Networking.Transport.Error.StatusCode.NetworkSendQueueFull:
88-
return k_NetworkSendQueueFull;
89-
default:
90-
return FixedString.Format("Unknown error code {0}.", error);
91-
}
92-
}
93-
}
94-
9547
/// <summary>
9648
/// The Netcode for GameObjects NetworkTransport for UnityTransport.
9749
/// Note: This is highly recommended to use over UNet.
@@ -114,13 +66,6 @@ public enum ProtocolType
11466
RelayUnityTransport,
11567
}
11668

117-
private enum State
118-
{
119-
Disconnected,
120-
Listening,
121-
Connected,
122-
}
123-
12469
/// <summary>
12570
/// The default maximum (receive) packet queue size
12671
/// </summary>
@@ -421,17 +366,16 @@ private struct PacketLossCache
421366

422367
internal static event Action<int, NetworkDriver> TransportInitialized;
423368
internal static event Action<int> TransportDisposed;
424-
internal NetworkDriver NetworkDriver => m_Driver;
425369

426370
/// <summary>
427-
/// Provides access to the <see cref="Networking.Transport.NetworkDriver"/> for this <see cref="UnityTransport"/> instance.
371+
/// Provides access to the <see cref="NetworkDriver"/> for this instance.
428372
/// </summary>
429373
protected NetworkDriver m_Driver;
430374

431375
/// <summary>
432-
/// Gets a reference to the <see cref="Networking.Transport.NetworkDriver"/>.
376+
/// Gets a reference to the <see cref="NetworkDriver"/>.
433377
/// </summary>
434-
/// <returns>ref <see cref="Networking.Transport.NetworkDriver"/></returns>
378+
/// <returns>ref <see cref="NetworkDriver"/></returns>
435379
public ref NetworkDriver GetNetworkDriver()
436380
{
437381
return ref m_Driver;
@@ -455,7 +399,6 @@ public NetworkEndpoint GetLocalEndpoint()
455399

456400
private PacketLossCache m_PacketLossCache = new PacketLossCache();
457401

458-
private State m_State = State.Disconnected;
459402
private NetworkSettings m_NetworkSettings;
460403
private ulong m_ServerClientId;
461404

@@ -501,7 +444,7 @@ private void InitDriver()
501444
out m_UnreliableSequencedFragmentedPipeline,
502445
out m_ReliableSequencedPipeline);
503446

504-
TransportInitialized?.Invoke(GetInstanceID(), NetworkDriver);
447+
TransportInitialized?.Invoke(GetInstanceID(), m_Driver);
505448
}
506449

507450
private void DisposeInternals()
@@ -583,8 +526,7 @@ private bool ClientBindAndConnect()
583526
return false;
584527
}
585528

586-
var serverConnection = Connect(serverEndpoint);
587-
m_ServerClientId = ParseClientId(serverConnection);
529+
Connect(serverEndpoint);
588530

589531
return true;
590532
}
@@ -624,7 +566,6 @@ private bool ServerBindAndListen(NetworkEndpoint endPoint)
624566
return false;
625567
}
626568

627-
m_State = State.Listening;
628569
return true;
629570
}
630571

@@ -776,9 +717,9 @@ public void Execute()
776717
while (!Queue.IsEmpty)
777718
{
778719
var result = Driver.BeginSend(pipeline, connection, out var writer);
779-
if (result != (int)Networking.Transport.Error.StatusCode.Success)
720+
if (result != (int)TransportError.Success)
780721
{
781-
Debug.LogError($"Error sending message: {ErrorUtilities.ErrorToFixedString(result, clientId)}");
722+
Debug.LogError($"Send error on connection {clientId}: {ErrorUtilities.ErrorToFixedString(result)}");
782723
return;
783724
}
784725

@@ -803,9 +744,9 @@ public void Execute()
803744
// and we'll retry sending them later). Otherwise log the error and remove the
804745
// message from the queue (we don't want to resend it again since we'll likely
805746
// just get the same error again).
806-
if (result != (int)Networking.Transport.Error.StatusCode.NetworkSendQueueFull)
747+
if (result != (int)TransportError.NetworkSendQueueFull)
807748
{
808-
Debug.LogError($"Error sending the message: {ErrorUtilities.ErrorToFixedString(result, clientId)}");
749+
Debug.LogError($"Send error on connection {clientId}: {ErrorUtilities.ErrorToFixedString(result)}");
809750
Queue.Consume(written);
810751
}
811752

@@ -849,7 +790,7 @@ private bool AcceptConnection()
849790
return false;
850791
}
851792

852-
InvokeOnTransportEvent(NetcodeNetworkEvent.Connect,
793+
InvokeOnTransportEvent(NetcodeEvent.Connect,
853794
ParseClientId(connection),
854795
default,
855796
m_RealTimeProvider.RealTimeSinceStartup);
@@ -887,7 +828,7 @@ private void ReceiveMessages(ulong clientId, NetworkPipeline pipeline, DataStrea
887828
break;
888829
}
889830

890-
InvokeOnTransportEvent(NetcodeNetworkEvent.Data, clientId, message, m_RealTimeProvider.RealTimeSinceStartup);
831+
InvokeOnTransportEvent(NetcodeEvent.Data, clientId, message, m_RealTimeProvider.RealTimeSinceStartup);
891832
}
892833
}
893834

@@ -898,44 +839,38 @@ private bool ProcessEvent()
898839

899840
switch (eventType)
900841
{
901-
case TransportNetworkEvent.Type.Connect:
842+
case TransportEvent.Connect:
902843
{
903-
InvokeOnTransportEvent(NetcodeNetworkEvent.Connect,
844+
InvokeOnTransportEvent(NetcodeEvent.Connect,
904845
clientId,
905846
default,
906847
m_RealTimeProvider.RealTimeSinceStartup);
907848

908-
m_State = State.Connected;
849+
m_ServerClientId = clientId;
909850
return true;
910851
}
911-
case TransportNetworkEvent.Type.Disconnect:
852+
case TransportEvent.Disconnect:
912853
{
913-
// Handle cases where we're a client receiving a Disconnect event. The
914-
// meaning of the event depends on our current state. If we were connected
915-
// then it means we got disconnected. If we were disconnected means that our
916-
// connection attempt has failed.
917-
if (m_State == State.Connected)
918-
{
919-
m_State = State.Disconnected;
920-
m_ServerClientId = default;
921-
}
922-
else if (m_State == State.Disconnected)
854+
// If we're a client and had not yet set the server client ID, it means
855+
// our connection to the server failed to be established. Any other case
856+
// means a clean disconnect that doesn't require logging.
857+
if (!m_Driver.Listening && m_ServerClientId == default)
923858
{
924859
Debug.LogError("Failed to connect to server.");
925-
m_ServerClientId = default;
926860
}
927861

862+
m_ServerClientId = default;
928863
m_ReliableReceiveQueues.Remove(clientId);
929864
ClearSendQueuesForClientId(clientId);
930865

931-
InvokeOnTransportEvent(NetcodeNetworkEvent.Disconnect,
866+
InvokeOnTransportEvent(NetcodeEvent.Disconnect,
932867
clientId,
933868
default,
934869
m_RealTimeProvider.RealTimeSinceStartup);
935870

936871
return true;
937872
}
938-
case TransportNetworkEvent.Type.Data:
873+
case TransportEvent.Data:
939874
{
940875
ReceiveMessages(clientId, pipeline, reader);
941876
return true;
@@ -957,7 +892,7 @@ protected override void OnEarlyUpdate()
957892
Debug.LogError("Transport failure! Relay allocation needs to be recreated, and NetworkManager restarted. " +
958893
"Use NetworkManager.OnTransportFailure to be notified of such events programmatically.");
959894

960-
InvokeOnTransportEvent(NetcodeNetworkEvent.TransportFailure, 0, default, m_RealTimeProvider.RealTimeSinceStartup);
895+
InvokeOnTransportEvent(NetcodeEvent.TransportFailure, 0, default, m_RealTimeProvider.RealTimeSinceStartup);
961896
return;
962897
}
963898

@@ -1180,21 +1115,21 @@ private void FlushSendQueuesForClientId(ulong clientId)
11801115
/// </summary>
11811116
public override void DisconnectLocalClient()
11821117
{
1183-
if (m_State == State.Connected)
1118+
if (m_ServerClientId != default)
11841119
{
11851120
FlushSendQueuesForClientId(m_ServerClientId);
11861121

11871122
if (m_Driver.Disconnect(ParseClientId(m_ServerClientId)) == 0)
11881123
{
1189-
m_State = State.Disconnected;
1124+
m_ServerClientId = default;
11901125

11911126
m_ReliableReceiveQueues.Remove(m_ServerClientId);
11921127
ClearSendQueuesForClientId(m_ServerClientId);
11931128

11941129
// If we successfully disconnect we dispatch a local disconnect message
11951130
// this how uNET and other transports worked and so this is just keeping with the old behavior
11961131
// should be also noted on the client this will call shutdown on the NetworkManager and the Transport
1197-
InvokeOnTransportEvent(NetcodeNetworkEvent.Disconnect,
1132+
InvokeOnTransportEvent(NetcodeEvent.Disconnect,
11981133
m_ServerClientId,
11991134
default,
12001135
m_RealTimeProvider.RealTimeSinceStartup);
@@ -1209,14 +1144,14 @@ public override void DisconnectLocalClient()
12091144
public override void DisconnectRemoteClient(ulong clientId)
12101145
{
12111146
#if DEBUG
1212-
if (m_State != State.Listening)
1147+
if (!m_Driver.IsCreated)
12131148
{
12141149
Debug.LogWarning($"{nameof(DisconnectRemoteClient)} should only be called on a listening server!");
12151150
return;
12161151
}
12171152
#endif
12181153

1219-
if (m_State == State.Listening)
1154+
if (m_Driver.IsCreated)
12201155
{
12211156
FlushSendQueuesForClientId(clientId);
12221157

@@ -1331,12 +1266,12 @@ public override void Initialize(NetworkManager networkManager = null)
13311266
/// <param name="payload">The incoming data payload</param>
13321267
/// <param name="receiveTime">The time the event was received, as reported by m_RealTimeProvider.RealTimeSinceStartup.</param>
13331268
/// <returns>Returns the event type</returns>
1334-
public override NetcodeNetworkEvent PollEvent(out ulong clientId, out ArraySegment<byte> payload, out float receiveTime)
1269+
public override NetcodeEvent PollEvent(out ulong clientId, out ArraySegment<byte> payload, out float receiveTime)
13351270
{
13361271
clientId = default;
13371272
payload = default;
13381273
receiveTime = default;
1339-
return NetcodeNetworkEvent.Nothing;
1274+
return NetcodeEvent.Nothing;
13401275
}
13411276

13421277
/// <summary>
@@ -1347,8 +1282,13 @@ public override NetcodeNetworkEvent PollEvent(out ulong clientId, out ArraySegme
13471282
/// <param name="networkDelivery">The delivery type (QoS) to send data with</param>
13481283
public override void Send(ulong clientId, ArraySegment<byte> payload, NetworkDelivery networkDelivery)
13491284
{
1350-
var pipeline = SelectSendPipeline(networkDelivery);
1285+
var connection = ParseClientId(clientId);
1286+
if (!m_Driver.IsCreated || m_Driver.GetConnectionState(connection) != NetworkConnection.State.Connected)
1287+
{
1288+
return;
1289+
}
13511290

1291+
var pipeline = SelectSendPipeline(networkDelivery);
13521292
if (pipeline != m_ReliableSequencedPipeline && payload.Count > m_MaxPayloadSize)
13531293
{
13541294
Debug.LogError($"Unreliable payload of size {payload.Count} larger than configured 'Max Payload Size' ({m_MaxPayloadSize}).");
@@ -1399,7 +1339,7 @@ public override void Send(ulong clientId, ArraySegment<byte> payload, NetworkDel
13991339
DisconnectRemoteClient(clientId);
14001340

14011341
// DisconnectRemoteClient doesn't notify SDK of disconnection.
1402-
InvokeOnTransportEvent(NetcodeNetworkEvent.Disconnect,
1342+
InvokeOnTransportEvent(NetcodeEvent.Disconnect,
14031343
clientId,
14041344
default(ArraySegment<byte>),
14051345
m_RealTimeProvider.RealTimeSinceStartup);
@@ -1515,10 +1455,9 @@ public override void Shutdown()
15151455
DisposeInternals();
15161456

15171457
m_ReliableReceiveQueues.Clear();
1518-
m_State = State.Disconnected;
15191458

15201459
// We must reset this to zero because UTP actually re-uses clientIds if there is a clean disconnect
1521-
m_ServerClientId = 0;
1460+
m_ServerClientId = default;
15221461
}
15231462

15241463
private void ConfigureSimulator()
@@ -1781,4 +1720,37 @@ public override int GetHashCode()
17811720
}
17821721
}
17831722
}
1723+
1724+
/// <summary>
1725+
/// Utility class to convert Unity Transport error codes to human-readable error messages.
1726+
/// </summary>
1727+
public static class ErrorUtilities
1728+
{
1729+
/// <summary>
1730+
/// Convert a Unity Transport error code to human-readable error message.
1731+
/// </summary>
1732+
/// <param name="error">Unity Transport error code.</param>
1733+
/// <param name="connectionId">ID of connection on which error occurred (unused).</param>
1734+
/// <returns>Human-readable error message.</returns>
1735+
public static string ErrorToString(TransportError error, ulong connectionId)
1736+
{
1737+
return ErrorToFixedString((int)error).ToString();
1738+
}
1739+
1740+
internal static FixedString128Bytes ErrorToFixedString(int error)
1741+
{
1742+
switch ((TransportError)error)
1743+
{
1744+
case TransportError.NetworkVersionMismatch:
1745+
case TransportError.NetworkStateMismatch:
1746+
return "invalid connection state (likely stale/closed connection)";
1747+
case TransportError.NetworkPacketOverflow:
1748+
return "packet is too large for the transport (likely need to increase MTU)";
1749+
case TransportError.NetworkSendQueueFull:
1750+
return "send queue full (need to increase 'Max Send Queue Size' parameter)";
1751+
default:
1752+
return FixedString.Format("unexpected error code {0}", error);
1753+
}
1754+
}
1755+
}
17841756
}

com.unity.netcode.gameobjects/Tests/Editor/Transports/UnityTransportTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ public void UnityTransport_EmptySecurityStringsShouldThrow([Values("", null)] st
189189
networkManager.StartServer();
190190
});
191191
// Make sure StartServer failed
192-
Assert.False(transport.NetworkDriver.IsCreated);
192+
Assert.False(transport.GetNetworkDriver().IsCreated);
193193
Assert.False(networkManager.IsServer);
194194
Assert.False(networkManager.IsListening);
195195
}

0 commit comments

Comments
 (0)