Skip to content

Commit 02d98e2

Browse files
committed
fix: Corrected wrong clientId on receive by keeping SDK internal mapping of client ID to transport ID so we can ensure no overlap (#1368)
1 parent a3e9350 commit 02d98e2

File tree

4 files changed

+141
-7
lines changed

4 files changed

+141
-7
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Additional documentation and release notes are available at [Multiplayer Documen
1616

1717
- Overflow exception when syncing Animator state. (#1327)
1818
- Added `try`/`catch` around RPC calls, preventing exception from causing further RPC calls to fail (#1329)
19+
- Fixed an issue where ServerClientId and LocalClientId could have the same value, causing potential confusion, and also fixed an issue with the UNet where the server could be identified with two different values, one of which might be the same as LocalClientId, and the other of which would not.(#1368)
20+
- IL2CPP would not properly compile (#1359)
1921

2022
## [1.0.0-pre.2] - 2021-10-19
2123

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

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ public void Send(ulong clientId, NetworkDelivery delivery, FastBufferWriter batc
151151
{
152152
var sendBuffer = batchData.ToTempByteArray();
153153

154-
m_NetworkManager.NetworkConfig.NetworkTransport.Send(clientId, sendBuffer, delivery);
154+
m_NetworkManager.NetworkConfig.NetworkTransport.Send(m_NetworkManager.ClientIdToTransportId(clientId), sendBuffer, delivery);
155155
}
156156
}
157157

@@ -223,10 +223,12 @@ public GameObject GetNetworkPrefabOverride(GameObject gameObject)
223223

224224
public NetworkSceneManager SceneManager { get; private set; }
225225

226+
public readonly ulong ServerClientId = 0;
227+
226228
/// <summary>
227229
/// Gets the networkId of the server
228230
/// </summary>
229-
public ulong ServerClientId => NetworkConfig.NetworkTransport?.ServerClientId ??
231+
private ulong m_ServerTransportId => NetworkConfig.NetworkTransport?.ServerClientId ??
230232
throw new NullReferenceException(
231233
$"The transport in the active {nameof(NetworkConfig)} is null");
232234

@@ -243,6 +245,10 @@ public ulong LocalClientId
243245

244246
private Dictionary<ulong, NetworkClient> m_ConnectedClients = new Dictionary<ulong, NetworkClient>();
245247

248+
private ulong m_NextClientId = 1;
249+
private Dictionary<ulong, ulong> m_ClientIdToTransportIdMap = new Dictionary<ulong, ulong>();
250+
private Dictionary<ulong, ulong> m_TransportIdToClientIdMap = new Dictionary<ulong, ulong>();
251+
246252
private List<NetworkClient> m_ConnectedClientsList = new List<NetworkClient>();
247253

248254
private List<ulong> m_ConnectedClientIds = new List<ulong>();
@@ -980,6 +986,12 @@ private void OnDestroy()
980986
}
981987
}
982988

989+
private void DisconnectRemoteClient(ulong clientId)
990+
{
991+
var transportId = ClientIdToTransportId(clientId);
992+
NetworkConfig.NetworkTransport.DisconnectRemoteClient(transportId);
993+
}
994+
983995
/// <summary>
984996
/// Globally shuts down the library.
985997
/// Disconnects clients if connected and stops server if running.
@@ -1014,7 +1026,7 @@ public void Shutdown()
10141026
continue;
10151027
}
10161028

1017-
NetworkConfig.NetworkTransport.DisconnectRemoteClient(pair.Key);
1029+
DisconnectRemoteClient(pair.Key);
10181030
}
10191031
}
10201032

@@ -1028,7 +1040,7 @@ public void Shutdown()
10281040
continue;
10291041
}
10301042

1031-
NetworkConfig.NetworkTransport.DisconnectRemoteClient(pair.Key);
1043+
DisconnectRemoteClient(pair.Key);
10321044
}
10331045
}
10341046
}
@@ -1098,6 +1110,9 @@ public void Shutdown()
10981110
NetworkConfig?.NetworkTransport?.Shutdown();
10991111
}
11001112

1113+
m_ClientIdToTransportIdMap.Clear();
1114+
m_TransportIdToClientIdMap.Clear();
1115+
11011116
IsListening = false;
11021117
}
11031118

@@ -1224,14 +1239,30 @@ private IEnumerator ApprovalTimeout(ulong clientId)
12241239
}
12251240
}
12261241

1242+
private ulong TransportIdToClientId(ulong transportId)
1243+
{
1244+
return transportId == m_ServerTransportId ? ServerClientId : m_TransportIdToClientIdMap[transportId];
1245+
}
1246+
1247+
private ulong ClientIdToTransportId(ulong clientId)
1248+
{
1249+
return clientId == ServerClientId ? m_ServerTransportId : m_ClientIdToTransportIdMap[clientId];
1250+
}
1251+
12271252
private void HandleRawTransportPoll(NetworkEvent networkEvent, ulong clientId, ArraySegment<byte> payload, float receiveTime)
12281253
{
1254+
var transportId = clientId;
12291255
switch (networkEvent)
12301256
{
12311257
case NetworkEvent.Connect:
12321258
#if DEVELOPMENT_BUILD || UNITY_EDITOR
12331259
s_TransportConnect.Begin();
12341260
#endif
1261+
1262+
clientId = m_NextClientId++;
1263+
m_ClientIdToTransportIdMap[clientId] = transportId;
1264+
m_TransportIdToClientIdMap[transportId] = clientId;
1265+
12351266
MessagingSystem.ClientConnected(clientId);
12361267
if (IsServer)
12371268
{
@@ -1270,13 +1301,19 @@ private void HandleRawTransportPoll(NetworkEvent networkEvent, ulong clientId, A
12701301
NetworkLog.LogInfo($"Incoming Data From {clientId}: {payload.Count} bytes");
12711302
}
12721303

1304+
clientId = TransportIdToClientId(clientId);
1305+
12731306
HandleIncomingData(clientId, payload, receiveTime);
12741307
break;
12751308
}
12761309
case NetworkEvent.Disconnect:
12771310
#if DEVELOPMENT_BUILD || UNITY_EDITOR
12781311
s_TransportDisconnect.Begin();
12791312
#endif
1313+
clientId = TransportIdToClientId(clientId);
1314+
1315+
m_TransportIdToClientIdMap.Remove(transportId);
1316+
m_ClientIdToTransportIdMap.Remove(clientId);
12801317

12811318
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
12821319
{
@@ -1400,8 +1437,7 @@ public void DisconnectClient(ulong clientId)
14001437
}
14011438

14021439
OnClientDisconnectFromServer(clientId);
1403-
1404-
NetworkConfig.NetworkTransport.DisconnectRemoteClient(clientId);
1440+
DisconnectRemoteClient(clientId);
14051441
}
14061442

14071443
private void OnClientDisconnectFromServer(ulong clientId)
@@ -1575,7 +1611,7 @@ internal void HandleApproval(ulong ownerClientId, bool createPlayerObject, uint?
15751611
else
15761612
{
15771613
PendingClients.Remove(ownerClientId);
1578-
NetworkConfig.NetworkTransport.DisconnectRemoteClient(ownerClientId);
1614+
DisconnectRemoteClient(ownerClientId);
15791615
}
15801616
}
15811617

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using System;
2+
using System.Collections;
3+
using Unity.Netcode;
4+
using Unity.Netcode.RuntimeTests;
5+
using NUnit.Framework;
6+
using Unity.Collections;
7+
using UnityEngine;
8+
using UnityEngine.TestTools;
9+
10+
namespace TestProject.RuntimeTests
11+
{
12+
public class SenderIdTests : BaseMultiInstanceTest
13+
{
14+
protected override int NbClients => 2;
15+
16+
private NetworkManager FirstClient => m_ClientNetworkManagers[0];
17+
private NetworkManager SecondClient => m_ClientNetworkManagers[1];
18+
19+
[UnityTest]
20+
public IEnumerator WhenSendingMessageFromServerToClient_SenderIdIsCorrect()
21+
{
22+
var messageContent = Guid.NewGuid();
23+
var writer = new FastBufferWriter(1300, Allocator.Temp);
24+
using (writer)
25+
{
26+
writer.WriteValueSafe(messageContent);
27+
m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessageToAll(writer);
28+
}
29+
30+
bool firstReceived = false;
31+
FirstClient.CustomMessagingManager.OnUnnamedMessage +=
32+
(sender, reader) =>
33+
{
34+
firstReceived = true;
35+
Assert.AreEqual(sender, FirstClient.ServerClientId);
36+
Assert.AreNotEqual(sender, FirstClient.LocalClientId);
37+
};
38+
39+
bool secondReceived = false;
40+
SecondClient.CustomMessagingManager.OnUnnamedMessage +=
41+
(sender, reader) =>
42+
{
43+
secondReceived = true;
44+
Assert.AreEqual(sender, FirstClient.ServerClientId);
45+
Assert.AreNotEqual(sender, FirstClient.LocalClientId);
46+
};
47+
48+
yield return new WaitForSeconds(0.2f);
49+
50+
Assert.IsTrue(firstReceived);
51+
Assert.IsTrue(secondReceived);
52+
}
53+
[UnityTest]
54+
public IEnumerator WhenSendingMessageFromClientToServer_SenderIdIsCorrect()
55+
{
56+
var messageContent = Guid.NewGuid();
57+
var writer = new FastBufferWriter(1300, Allocator.Temp);
58+
using (writer)
59+
{
60+
FirstClient.CustomMessagingManager.SendNamedMessage("FirstClient", FirstClient.ServerClientId, writer);
61+
SecondClient.CustomMessagingManager.SendNamedMessage("SecondClient", SecondClient.ServerClientId, writer);
62+
63+
}
64+
65+
bool firstReceived = false;
66+
m_ServerNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler(
67+
"FirstClient",
68+
(sender, reader) =>
69+
{
70+
firstReceived = true;
71+
Assert.AreEqual(sender, FirstClient.LocalClientId);
72+
Assert.AreNotEqual(sender, SecondClient.LocalClientId);
73+
Assert.AreNotEqual(sender, m_ServerNetworkManager.LocalClientId);
74+
});
75+
76+
bool secondReceived = false;
77+
m_ServerNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler(
78+
"SecondClient",
79+
(sender, reader) =>
80+
{
81+
secondReceived = true;
82+
Assert.AreNotEqual(sender, FirstClient.LocalClientId);
83+
Assert.AreEqual(sender, SecondClient.LocalClientId);
84+
Assert.AreNotEqual(sender, m_ServerNetworkManager.LocalClientId);
85+
});
86+
87+
yield return new WaitForSeconds(0.2f);
88+
89+
Assert.IsTrue(firstReceived);
90+
Assert.IsTrue(secondReceived);
91+
}
92+
}
93+
}

testproject/Assets/Tests/Runtime/SenderIdTests.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)