Skip to content

Commit e02cad1

Browse files
update
This update is a work in progress resolution to the issue where disconnect event notifications were too vague and did not provide any way to know what the cause of the disconnect was.
1 parent 2a5de93 commit e02cad1

File tree

4 files changed

+152
-19
lines changed

4 files changed

+152
-19
lines changed

com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -373,10 +373,14 @@ private ulong GetServerTransportId()
373373
{
374374
if (NetworkManager != null)
375375
{
376-
var transport = NetworkManager.NetworkConfig.NetworkTransport;
377-
if (transport != null)
376+
if (Transport == null && NetworkManager.NetworkConfig.NetworkTransport != null)
377+
{
378+
Transport = NetworkManager.NetworkConfig.NetworkTransport;
379+
}
380+
381+
if (Transport)
378382
{
379-
return transport.ServerClientId;
383+
return Transport.ServerClientId;
380384
}
381385

382386
throw new NullReferenceException($"The transport in the active {nameof(NetworkConfig)} is null");
@@ -412,7 +416,7 @@ internal void PollAndHandleNetworkEvents()
412416
NetworkEvent networkEvent;
413417
do
414418
{
415-
networkEvent = NetworkManager.NetworkConfig.NetworkTransport.PollEvent(out ulong transportClientId, out ArraySegment<byte> payload, out float receiveTime);
419+
networkEvent = Transport.PollEvent(out ulong transportClientId, out ArraySegment<byte> payload, out float receiveTime);
416420
HandleNetworkEvent(networkEvent, transportClientId, payload, receiveTime);
417421
if (networkEvent == NetworkEvent.Disconnect || networkEvent == NetworkEvent.TransportFailure)
418422
{
@@ -520,6 +524,22 @@ internal void DataEventHandler(ulong transportClientId, ref ArraySegment<byte> p
520524
#endif
521525
}
522526

527+
private void GenerateDisconnectInformation(ulong clientId, ulong transportClientId, string reason = null)
528+
{
529+
var header = $"[Disconnect Event][Client-{clientId}]";
530+
var existingDisconnectReason = DisconnectReason;
531+
var defaultMessage = reason ?? $"Disconnected.";
532+
// Just go ahead and set this whether client or server so any subscriptions to a disconnect event can check the DisconnectReason
533+
// to determine why the client disconnected
534+
DisconnectReason = Transport.DisconnectEvent == NetworkTransport.DisconnectEvents.Disconnected ? $"{header} {defaultMessage}" :
535+
$"{header}[{Transport.DisconnectEvent}] {defaultMessage}";
536+
DisconnectReason = $"{DisconnectReason}\n{existingDisconnectReason}";
537+
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
538+
{
539+
NetworkLog.LogInfo($"{DisconnectReason}");
540+
}
541+
}
542+
523543
/// <summary>
524544
/// Handles a <see cref="NetworkEvent.Disconnect"/> event.
525545
/// </summary>
@@ -528,11 +548,8 @@ internal void DisconnectEventHandler(ulong transportClientId)
528548
#if DEVELOPMENT_BUILD || UNITY_EDITOR
529549
s_TransportDisconnect.Begin();
530550
#endif
531-
var clientId = TransportIdCleanUp(transportClientId);
532-
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
533-
{
534-
NetworkLog.LogInfo($"Disconnect Event From {clientId}");
535-
}
551+
var clientId = TransportIdToClientId(transportClientId);
552+
TransportIdCleanUp(transportClientId);
536553

537554
// If we are a client and we have gotten the ServerClientId back, then use our assigned local id as the client that was
538555
// disconnected (either the user disconnected or the server disconnected, but the client that disconnected is the LocalClientId)
@@ -541,6 +558,8 @@ internal void DisconnectEventHandler(ulong transportClientId)
541558
clientId = NetworkManager.LocalClientId;
542559
}
543560

561+
GenerateDisconnectInformation(clientId, transportClientId);
562+
544563
// Process the incoming message queue so that we get everything from the server disconnecting us or, if we are the server, so we got everything from that client.
545564
MessageManager.ProcessIncomingMessageQueue();
546565

@@ -1327,7 +1346,7 @@ internal void OnClientDisconnectFromServer(ulong clientId)
13271346
if (ClientIdToTransportIdMap.ContainsKey(clientId))
13281347
{
13291348
var transportId = ClientIdToTransportId(clientId);
1330-
NetworkManager.NetworkConfig.NetworkTransport.DisconnectRemoteClient(transportId);
1349+
Transport.DisconnectRemoteClient(transportId);
13311350

13321351
InvokeOnClientDisconnectCallback(clientId);
13331352

@@ -1393,10 +1412,15 @@ internal void DisconnectClient(ulong clientId, string reason = null)
13931412
};
13941413
SendMessage(ref disconnectReason, NetworkDelivery.Reliable, clientId);
13951414
}
1415+
Transport.SetDisconnectEvent((byte)Networking.Transport.Error.DisconnectReason.Default);
13961416

1417+
GenerateDisconnectInformation(clientId, ClientIdToTransportId(clientId), reason);
13971418
DisconnectRemoteClient(clientId);
13981419
}
13991420

1421+
internal NetworkTransport Transport;
1422+
internal NetworkTransport.DisconnectEvents DisconnectEvent => Transport ? Transport.DisconnectEvent : NetworkTransport.DisconnectEvents.Disconnected;
1423+
14001424
/// <summary>
14011425
/// Should be invoked when starting a server-host or client
14021426
/// </summary>
@@ -1418,10 +1442,14 @@ internal void Initialize(NetworkManager networkManager)
14181442
NetworkManager = networkManager;
14191443
MessageManager = networkManager.MessageManager;
14201444

1421-
NetworkManager.NetworkConfig.NetworkTransport.NetworkMetrics = NetworkManager.MetricsManager.NetworkMetrics;
1422-
1423-
NetworkManager.NetworkConfig.NetworkTransport.OnTransportEvent += HandleNetworkEvent;
1424-
NetworkManager.NetworkConfig.NetworkTransport.Initialize(networkManager);
1445+
Transport = NetworkManager.NetworkConfig.NetworkTransport;
1446+
if (Transport)
1447+
{
1448+
Transport.NetworkMetrics = NetworkManager.MetricsManager.NetworkMetrics;
1449+
Transport.OnTransportEvent += HandleNetworkEvent;
1450+
Transport.Initialize(networkManager);
1451+
Transport.CreateDisconnectEventMap();
1452+
}
14251453
}
14261454

14271455
/// <summary>
@@ -1435,7 +1463,7 @@ internal void Shutdown()
14351463
var disconnectedIds = new HashSet<ulong>();
14361464

14371465
//Don't know if I have to disconnect the clients. I'm assuming the NetworkTransport does all the cleaning on shutdown. But this way the clients get a disconnect message from server (so long it does't get lost)
1438-
var serverTransportId = NetworkManager.NetworkConfig.NetworkTransport.ServerClientId;
1466+
var serverTransportId = GetServerTransportId();
14391467
foreach (KeyValuePair<ulong, NetworkClient> pair in ConnectedClients)
14401468
{
14411469
if (!disconnectedIds.Contains(pair.Key))
@@ -1478,7 +1506,7 @@ internal void Shutdown()
14781506
// Client only, send disconnect and if transport throws and exception, log the exception and continue the shutdown sequence (or forever be shutting down)
14791507
try
14801508
{
1481-
NetworkManager.NetworkConfig.NetworkTransport.DisconnectLocalClient();
1509+
Transport.DisconnectLocalClient();
14821510
}
14831511
catch (Exception ex)
14841512
{
@@ -1508,6 +1536,11 @@ internal void Shutdown()
15081536
var transport = NetworkManager.NetworkConfig?.NetworkTransport;
15091537
if (transport != null)
15101538
{
1539+
if (LocalClient.IsServer)
1540+
{
1541+
GenerateDisconnectInformation(NetworkManager.ServerClientId, Transport.ServerClientId, "Disconnecting due to shutdown.");
1542+
}
1543+
transport.CleanDisconnectEventMap();
15111544
transport.Shutdown();
15121545

15131546
if (NetworkManager.LogLevel <= LogLevel.Developer)

com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
using System.Collections.Generic;
33
using Unity.Collections;
44
using System.Linq;
5+
using Unity.Netcode.Components;
56
using UnityEngine;
67
#if UNITY_EDITOR
78
using UnityEditor;
89
using PackageInfo = UnityEditor.PackageManager.PackageInfo;
910
#endif
1011
using UnityEngine.SceneManagement;
1112
using Debug = UnityEngine.Debug;
12-
using Unity.Netcode.Components;
1313

1414
namespace Unity.Netcode
1515
{
@@ -611,6 +611,16 @@ public ulong LocalClientId
611611
/// </summary>
612612
public string DisconnectReason => ConnectionManager.DisconnectReason;
613613

614+
/// <summary>
615+
/// If supported by the <see cref="NetworkTransport"/>, this <see cref="NetworkTransport.DisconnectEvents"/> property will be set for each disconnect event.
616+
/// If not supported, then this remain as the default <see cref="Networking.Transport.Error.DisconnectReason"/> value.
617+
/// </summary>
618+
/// <remarks>
619+
/// A server/host will receive notifications for remote clients disconnecting and will update this <see cref="Networking.Transport.Error.DisconnectReason"/> property
620+
/// upon each disconnect event.<br />
621+
/// </remarks>
622+
public NetworkTransport.DisconnectEvents DisconnectEvent => ConnectionManager.DisconnectEvent;
623+
614624
/// <summary>
615625
/// Is true when a server or host is listening for connections.
616626
/// Is true when a client is connecting or connected to a network session.
@@ -1485,7 +1495,7 @@ private void HostServerInitialize()
14851495
/// Disconnects the remote client.
14861496
/// </summary>
14871497
/// <param name="clientId">The ClientId to disconnect</param>
1488-
public void DisconnectClient(ulong clientId) => ConnectionManager.DisconnectClient(clientId);
1498+
public void DisconnectClient(ulong clientId) => ConnectionManager.DisconnectClient(clientId, $"Client-{clientId} disconnected by server.");
14891499

14901500
/// <summary>
14911501
/// Disconnects the remote client.

com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using UnityEngine;
34

45
namespace Unity.Netcode
@@ -164,6 +165,79 @@ internal NetworkTopologyTypes CurrentTopology()
164165
{
165166
return OnCurrentTopology();
166167
}
168+
169+
170+
public enum DisconnectEvents : byte
171+
{
172+
Disconnected,
173+
ProtocolTimeout,
174+
MaxConnectionAttempts,
175+
ClosedByRemote,
176+
ClosedRemoteConnection,
177+
AuthenticationFailure,
178+
ProtocolError,
179+
}
180+
181+
public DisconnectEvents DisconnectEvent { get; private set; }
182+
private Dictionary<byte, DisconnectEvents> m_DisconnectEventMap = new Dictionary<byte, DisconnectEvents>();
183+
184+
/// <summary>
185+
/// This should be invoked by the <see cref="NetworkTransport"/> derived class when a transport level disconnect event occurs.<br />
186+
/// If there is a map for the specific transport event id, then <see cref="DisconnectEvent"/> will be set to the equivalent <see cref="DisconnectEvents"/> value.
187+
/// </summary>
188+
/// <param name="disconnectEventId">The transport's disconnect event identifer.</param>
189+
public void SetDisconnectEvent(byte disconnectEventId)
190+
{
191+
if (m_DisconnectEventMap.ContainsKey(disconnectEventId))
192+
{
193+
DisconnectEvent = m_DisconnectEventMap[disconnectEventId];
194+
}
195+
else // If there are no maps, then this will always report just disconnected.
196+
{
197+
DisconnectEvent = DisconnectEvents.Disconnected;
198+
}
199+
}
200+
201+
internal void SetDisconnectEvent(DisconnectEvents disconnectEvent)
202+
{
203+
DisconnectEvent = disconnectEvent;
204+
}
205+
206+
/// <summary>
207+
/// Adds a map between the <see cref="DisconnectEvents"/> value and the transports equivalent event identifier.
208+
/// </summary>
209+
/// <param name="disconnectEvents">The <see cref="DisconnectEvents"/> value to be mapped.</param>
210+
/// <param name="targetEventId">The transport's equivalent event identifier value.</param>
211+
protected void AddDisconnectEventMap(DisconnectEvents disconnectEvents, byte targetEventId)
212+
{
213+
if (!m_DisconnectEventMap.ContainsKey(targetEventId))
214+
{
215+
m_DisconnectEventMap.Add(targetEventId, disconnectEvents);
216+
}
217+
}
218+
219+
/// <summary>
220+
/// Override this method to create a disconnect event mapping table that will translate the transport's equivalent for each enum in <see cref="DisconnectEvents"/>.<br />
221+
/// This method is invoked during <see cref="NetworkConnectionManager.Initialize(NetworkManager)"/> just after <see cref="Initialize(NetworkManager)"/> has been invoked.
222+
/// </summary>
223+
/// <remarks>
224+
/// You can use <see cref="AddDisconnectEventMap"/> to register a map between <see cref="DisconnectEvents"/> and the transport's disconnect event equivalent.
225+
/// </remarks>
226+
protected virtual void OnCreateDisconnectEventMap()
227+
{
228+
229+
}
230+
231+
internal void CreateDisconnectEventMap()
232+
{
233+
OnCreateDisconnectEventMap();
234+
}
235+
236+
internal void CleanDisconnectEventMap()
237+
{
238+
DisconnectEvent = DisconnectEvents.Disconnected;
239+
m_DisconnectEventMap.Clear();
240+
}
167241
}
168242

169243
/// <summary>

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
using Unity.Collections.LowLevel.Unsafe;
1616
using Unity.Jobs;
1717
using Unity.Networking.Transport;
18+
using Unity.Networking.Transport.Error;
1819
using Unity.Networking.Transport.Relay;
1920
using Unity.Networking.Transport.TLS;
2021
using Unity.Networking.Transport.Utilities;
22+
using UnityEditor.PackageManager;
2123
using UnityEngine;
2224

2325
using NetcodeEvent = Unity.Netcode.NetworkEvent;
@@ -1056,6 +1058,9 @@ private bool ProcessEvent()
10561058
Debug.LogError("Failed to connect to server.");
10571059
}
10581060

1061+
// Set the disconnect event error code
1062+
SetDisconnectEvent(reader.ReadByte());
1063+
10591064
m_ServerClientId = default;
10601065
m_ReliableReceiveQueues.Remove(clientId);
10611066
ClearSendQueuesForClientId(clientId);
@@ -1348,7 +1353,7 @@ public override void DisconnectRemoteClient(ulong clientId)
13481353
}
13491354
#endif
13501355

1351-
if (m_Driver.IsCreated)
1356+
if (m_NetworkManager.IsServer && m_Driver.IsCreated)
13521357
{
13531358
FlushSendQueuesForClientId(clientId);
13541359

@@ -1363,6 +1368,17 @@ public override void DisconnectRemoteClient(ulong clientId)
13631368
}
13641369
}
13651370

1371+
protected override void OnCreateDisconnectEventMap()
1372+
{
1373+
AddDisconnectEventMap(DisconnectEvents.Disconnected, (byte)DisconnectReason.Default);
1374+
AddDisconnectEventMap(DisconnectEvents.ProtocolTimeout, (byte)DisconnectReason.Timeout);
1375+
AddDisconnectEventMap(DisconnectEvents.MaxConnectionAttempts, (byte)DisconnectReason.MaxConnectionAttempts);
1376+
AddDisconnectEventMap(DisconnectEvents.ClosedByRemote, (byte)DisconnectReason.ClosedByRemote);
1377+
AddDisconnectEventMap(DisconnectEvents.AuthenticationFailure, (byte)DisconnectReason.AuthenticationFailure);
1378+
AddDisconnectEventMap(DisconnectEvents.ProtocolError, (byte)DisconnectReason.ProtocolError);
1379+
base.OnCreateDisconnectEventMap();
1380+
}
1381+
13661382
/// <summary>
13671383
/// Gets the current RTT for a specific client
13681384
/// </summary>

0 commit comments

Comments
 (0)