Skip to content

Commit 610e2d6

Browse files
refactor and fix
Fixing several issues with the disconnect flow. Not removing the transport id until later. The server now only does this within OnClientDisconnectFromServer. When disconnecting a client with a reason, the client is not completely disconnected until the end of the frame when the server has finished sending all pending messages. Fixing some missed MessageDeliveryType replacements. Removing the MockSkippingApproval as it is no longer needed with the fixes in place.
1 parent cea8998 commit 610e2d6

File tree

3 files changed

+72
-54
lines changed

3 files changed

+72
-54
lines changed

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

Lines changed: 55 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -594,9 +594,11 @@ internal void DisconnectEventHandler(ulong transportClientId)
594594
// Check to see if the client has already been removed from the table but
595595
// do not remove it just yet.
596596
var (clientId, isConnectedClient) = TransportIdToClientId(transportClientId);
597-
if (!isConnectedClient)
597+
598+
// If the client is not registered and we are the server
599+
if (!isConnectedClient && NetworkManager.IsServer)
598600
{
599-
// If so, exit early
601+
// Then exit early
600602
return;
601603
}
602604

@@ -631,15 +633,6 @@ internal void DisconnectEventHandler(ulong transportClientId)
631633
{
632634
// We need to process the disconnection before notifying
633635
OnClientDisconnectFromServer(clientId);
634-
635-
// Now notify the client has disconnected.
636-
// (transport id cleanup is handled within)
637-
InvokeOnClientDisconnectCallback(clientId);
638-
639-
if (LocalClient.IsHost)
640-
{
641-
InvokeOnPeerDisconnectedCallback(clientId);
642-
}
643636
}
644637
else
645638
{
@@ -806,12 +799,15 @@ private IEnumerator ApprovalTimeout(ulong clientId)
806799
/// </summary>
807800
internal void ApproveConnection(ref ConnectionRequestMessage connectionRequestMessage, ref NetworkContext context)
808801
{
802+
if (ConnectionApprovalCallback == null)
803+
{
804+
return;
805+
}
809806
// Note: Delegate creation allocates.
810807
// Note: ToArray() also allocates. :(
811808
var response = new NetworkManager.ConnectionApprovalResponse();
812809
ClientsToApprove[context.SenderId] = response;
813-
814-
ConnectionApprovalCallback(
810+
ConnectionApprovalCallback?.Invoke(
815811
new NetworkManager.ConnectionApprovalRequest
816812
{
817813
Payload = connectionRequestMessage.ConnectionData,
@@ -865,13 +861,6 @@ internal void ProcessPendingApprovals()
865861
}
866862
}
867863

868-
/// <summary>
869-
/// Adding this because message hooks cannot happen fast enough under certain scenarios
870-
/// where the message is sent and responded to before the hook is in place.
871-
/// </summary>
872-
internal bool MockSkippingApproval;
873-
874-
875864
/// <summary>
876865
/// Server Side: Handles the denial of a client who sent a connection request
877866
/// </summary>
@@ -886,12 +875,36 @@ private void HandleConnectionDisconnect(ulong ownerClientId, string reason = "")
886875
{
887876
Reason = reason
888877
};
889-
SendMessage(ref disconnectReason, NetworkDelivery.Reliable, ownerClientId);
878+
SendMessage(ref disconnectReason, MessageDeliveryType<DisconnectReasonMessage>.DefaultDelivery, ownerClientId);
879+
m_ClientsToDisconnect.Add(ownerClientId);
880+
return;
890881
}
891882

892883
DisconnectRemoteClient(ownerClientId);
893884
}
894885

886+
private List<ulong> m_ClientsToDisconnect = new List<ulong>();
887+
888+
internal void ProcessClientsToDisconnect()
889+
{
890+
if (m_ClientsToDisconnect.Count == 0)
891+
{
892+
return;
893+
}
894+
foreach (var clientId in m_ClientsToDisconnect)
895+
{
896+
try
897+
{
898+
DisconnectRemoteClient(clientId);
899+
}
900+
catch (Exception ex)
901+
{
902+
Debug.LogException(ex);
903+
}
904+
}
905+
m_ClientsToDisconnect.Clear();
906+
}
907+
895908
/// <summary>
896909
/// Server Side: Handles the approval of a client
897910
/// </summary>
@@ -952,12 +965,6 @@ internal void HandleConnectionApproval(ulong ownerClientId, bool createPlayerObj
952965
// Server doesn't send itself the connection approved message
953966
if (ownerClientId != NetworkManager.ServerClientId)
954967
{
955-
if (MockSkippingApproval)
956-
{
957-
NetworkLog.LogInfo("Mocking server not responding with connection approved...");
958-
return;
959-
}
960-
961968
SendConnectionApprovedMessage(ownerClientId);
962969

963970
// If scene management is disabled, then we are done and notify the local host-server the client is connected
@@ -1053,7 +1060,7 @@ private void SendConnectionApprovedMessage(ulong approvedClientId)
10531060
}
10541061
}
10551062

1056-
SendMessage(ref message, NetworkDelivery.ReliableFragmentedSequenced, approvedClientId);
1063+
SendMessage(ref message, MessageDeliveryType<ConnectionApprovedMessage>.DefaultDelivery, approvedClientId);
10571064

10581065
message.MessageVersions.Dispose();
10591066
message.ConnectedClientIds.Dispose();
@@ -1124,13 +1131,9 @@ internal NetworkClient AddClient(ulong clientId)
11241131
return ConnectedClients[clientId];
11251132
}
11261133

1127-
var networkClient = LocalClient;
1128-
11291134
// If this is not the local client then create a new one
1130-
if (clientId != NetworkManager.LocalClientId)
1131-
{
1132-
networkClient = new NetworkClient();
1133-
}
1135+
var networkClient = clientId == NetworkManager.LocalClientId ? LocalClient : new NetworkClient();
1136+
11341137
networkClient.SetRole(clientId == NetworkManager.ServerClientId, isClient: true, NetworkManager);
11351138
networkClient.ClientId = clientId;
11361139
if (!ConnectedClients.ContainsKey(clientId))
@@ -1237,6 +1240,14 @@ internal void OnClientDisconnectFromServer(ulong clientId)
12371240
// clean up as everything that needs to be destroyed will be during shutdown.
12381241
if (NetworkManager.ShutdownInProgress && clientId == NetworkManager.ServerClientId)
12391242
{
1243+
// Now notify the client has disconnected.
1244+
// (transport id cleanup is handled within)
1245+
InvokeOnClientDisconnectCallback(clientId);
1246+
1247+
if (LocalClient.IsHost)
1248+
{
1249+
InvokeOnPeerDisconnectedCallback(clientId);
1250+
}
12401251
return;
12411252
}
12421253

@@ -1429,17 +1440,18 @@ internal void OnClientDisconnectFromServer(ulong clientId)
14291440
var (transportId, idExists) = ClientIdToTransportId(clientId);
14301441
if (idExists)
14311442
{
1432-
NetworkManager.NetworkConfig.NetworkTransport.DisconnectRemoteClient(transportId);
1433-
1434-
InvokeOnClientDisconnectCallback(clientId);
1435-
1436-
if (LocalClient.IsHost)
1443+
// Clean up the transport to client (and vice versa) mappings
1444+
var (transportIdDisconnected, wasRemoved) = TransportIdCleanUp(transportId);
1445+
if (wasRemoved)
14371446
{
1438-
InvokeOnPeerDisconnectedCallback(clientId);
1439-
}
1447+
NetworkManager.NetworkConfig.NetworkTransport.DisconnectRemoteClient(transportId);
1448+
InvokeOnClientDisconnectCallback(clientId);
14401449

1441-
// Clean up the transport to client (and vice versa) mappings
1442-
TransportIdCleanUp(transportId);
1450+
if (LocalClient.IsHost)
1451+
{
1452+
InvokeOnPeerDisconnectedCallback(clientId);
1453+
}
1454+
}
14431455
}
14441456

14451457
// Assure the client id is no longer in the pending clients list
@@ -1487,16 +1499,6 @@ internal void DisconnectClient(ulong clientId, string reason = null)
14871499
return;
14881500
}
14891501

1490-
if (!string.IsNullOrEmpty(reason))
1491-
{
1492-
var disconnectReason = new DisconnectReasonMessage
1493-
{
1494-
Reason = reason
1495-
};
1496-
SendMessage(ref disconnectReason, NetworkDelivery.Reliable, clientId);
1497-
}
1498-
1499-
Transport.ClosingRemoteConnection();
15001502
var transportId = ClientIdToTransportId(clientId);
15011503
if (transportId.Item2)
15021504
{

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,6 @@ public void NetworkUpdate(NetworkUpdateStage updateStage)
348348
AnticipationSystem.SetupForUpdate();
349349
MessageManager.ProcessIncomingMessageQueue();
350350

351-
MessageManager.CleanupDisconnectedClients();
352351
AnticipationSystem.ProcessReanticipation();
353352
#if COM_UNITY_MODULES_PHYSICS || COM_UNITY_MODULES_PHYSICS2D
354353
foreach (var networkObjectEntry in NetworkTransformFixedUpdate)
@@ -480,6 +479,18 @@ public void NetworkUpdate(NetworkUpdateStage updateStage)
480479
// This is "ok" to invoke when not processing messages since it is just cleaning up messages that never got handled within their timeout period.
481480
DeferredMessageManager.CleanupStaleTriggers();
482481

482+
if (IsServer)
483+
{
484+
// Process any pending clients that need to be disconnected.
485+
// This is typically a disconnect with reason scenario where
486+
// we want the disconnect reason message to be sent prior to
487+
// completely shutting down the endpoint.
488+
ConnectionManager.ProcessClientsToDisconnect();
489+
}
490+
491+
// Clean up disconnected clients last
492+
MessageManager.CleanupDisconnectedClients();
493+
483494
if (m_ShuttingDown)
484495
{
485496
// Host-server will disconnect any connected clients prior to finalizing its shutdown

com.unity.netcode.gameobjects/Runtime/Messaging/NetworkMessageManager.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,11 @@ private void CleanupDisconnectedClient(ulong clientId)
492492

493493
internal void CleanupDisconnectedClients()
494494
{
495+
if (m_DisconnectedClients.Count == 0)
496+
{
497+
return;
498+
}
499+
495500
foreach (var clientId in m_DisconnectedClients)
496501
{
497502
CleanupDisconnectedClient(clientId);

0 commit comments

Comments
 (0)