Skip to content

Commit dfabbed

Browse files
chore: refactor session version serialization and configuration (#3138)
* update Re-organizing how we handle session versioning and how service features are determined during a connected session. * update Updates to ConnectionRequestMessage that implement the new SessionConfig serialization pattern. * update Minor adjustments and clean up to the SessionConfig and SessionVersion implementation. * test Validation test for the SessionConfig and SessionVersion check (mocking the service-side handling logic for invalid session version).
1 parent 17f7f25 commit dfabbed

File tree

9 files changed

+318
-106
lines changed

9 files changed

+318
-106
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
namespace Unity.Netcode
2+
{
3+
internal class SessionConfig
4+
{
5+
/// <summary>
6+
/// The running list of session versions
7+
/// </summary>
8+
public const uint NoFeatureCompatibility = 0;
9+
public const uint BypassFeatureCompatible = 1;
10+
public const uint ServerDistributionCompatible = 2;
11+
12+
// The most current session version (!!!!set this when you increment!!!!!)
13+
public static uint PackageSessionVersion => ServerDistributionCompatible;
14+
15+
internal uint SessionVersion;
16+
17+
public bool ServiceSideDistribution;
18+
19+
20+
/// <summary>
21+
/// Service to client
22+
/// Set when the client receives a <see cref="ConnectionApprovedMessage"/>
23+
/// </summary>
24+
/// <param name="serviceConfig">the session's settings</param>
25+
public SessionConfig(ServiceConfig serviceConfig)
26+
{
27+
SessionVersion = serviceConfig.SessionVersion;
28+
ServiceSideDistribution = serviceConfig.ServerRedistribution;
29+
}
30+
31+
/// <summary>
32+
/// Can be used to directly set the version.
33+
/// </summary>
34+
/// <remarks>
35+
/// If a client connects that does not support session configuration then
36+
/// this will be invoked. The default values set in the constructor should
37+
/// assume that no features are available.
38+
/// Can also be used for mock/integration testing version handling.
39+
/// </remarks>
40+
/// <param name="version">version to set</param>
41+
public SessionConfig(uint version)
42+
{
43+
SessionVersion = version;
44+
ServiceSideDistribution = false;
45+
}
46+
47+
/// <summary>
48+
/// Client to Service
49+
/// Default package constructor set when <see cref="NetworkManager.Initialize(bool)"/> is invoked.
50+
/// </summary>
51+
public SessionConfig()
52+
{
53+
// The current
54+
SessionVersion = PackageSessionVersion;
55+
ServiceSideDistribution = false;
56+
}
57+
}
58+
}

com.unity.netcode.gameobjects/Runtime/Configuration/SessionConfig.cs.meta

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

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -563,16 +563,17 @@ private void SendConnectionRequest()
563563
{
564564
var message = new ConnectionRequestMessage
565565
{
566-
CMBServiceConnection = NetworkManager.CMBServiceConnection,
566+
DistributedAuthority = NetworkManager.DistributedAuthorityMode,
567567
// Since only a remote client will send a connection request, we should always force the rebuilding of the NetworkConfig hash value
568568
ConfigHash = NetworkManager.NetworkConfig.GetConfig(false),
569569
ShouldSendConnectionData = NetworkManager.NetworkConfig.ConnectionApproval,
570570
ConnectionData = NetworkManager.NetworkConfig.ConnectionData,
571571
MessageVersions = new NativeArray<MessageVersionData>(MessageManager.MessageHandlers.Length, Allocator.Temp)
572572
};
573573

574-
if (NetworkManager.CMBServiceConnection)
574+
if (NetworkManager.DistributedAuthorityMode)
575575
{
576+
message.ClientConfig.SessionConfig = NetworkManager.SessionConfig;
576577
message.ClientConfig.TickRate = NetworkManager.NetworkConfig.TickRate;
577578
message.ClientConfig.EnableSceneManagement = NetworkManager.NetworkConfig.EnableSceneManagement;
578579
}

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,18 @@ internal static void LogSerializedTypeNotOptimized<T>()
8080
}
8181
#endif
8282

83+
internal SessionConfig SessionConfig;
84+
85+
/// <summary>
86+
/// Used for internal testing purposes
87+
/// </summary>
88+
internal delegate SessionConfig OnGetSessionConfigHandler();
89+
internal OnGetSessionConfigHandler OnGetSessionConfig;
90+
private SessionConfig GetSessionConfig()
91+
{
92+
return OnGetSessionConfig != null ? OnGetSessionConfig.Invoke() : new SessionConfig();
93+
}
94+
8395
internal static bool IsDistributedAuthority;
8496

8597
/// <summary>
@@ -1179,6 +1191,12 @@ internal void Initialize(bool server)
11791191

11801192
UpdateTopology();
11811193

1194+
// Always create a default session config when starting a NetworkManager instance
1195+
if (DistributedAuthorityMode)
1196+
{
1197+
SessionConfig = GetSessionConfig();
1198+
}
1199+
11821200
// Make sure the ServerShutdownState is reset when initializing
11831201
if (server)
11841202
{

com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ConnectionApprovedMessage.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ namespace Unity.Netcode
55
{
66
internal struct ServiceConfig : INetworkSerializable
77
{
8-
private const int k_AddServerRedistribution = 1;
9-
10-
public uint Version;
8+
public uint SessionVersion;
119
public bool IsRestoredSession;
1210
public ulong CurrentSessionOwner;
1311
public bool ServerRedistribution;
@@ -16,25 +14,29 @@ public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReade
1614
{
1715
if (serializer.IsWriter)
1816
{
19-
BytePacker.WriteValueBitPacked(serializer.GetFastBufferWriter(), Version);
17+
BytePacker.WriteValueBitPacked(serializer.GetFastBufferWriter(), SessionVersion);
2018
serializer.SerializeValue(ref IsRestoredSession);
2119
BytePacker.WriteValueBitPacked(serializer.GetFastBufferWriter(), CurrentSessionOwner);
2220

23-
if (Version >= k_AddServerRedistribution)
21+
if (SessionVersion >= SessionConfig.ServerDistributionCompatible)
2422
{
2523
serializer.SerializeValue(ref ServerRedistribution);
2624
}
2725
}
2826
else
2927
{
30-
ByteUnpacker.ReadValueBitPacked(serializer.GetFastBufferReader(), out Version);
28+
ByteUnpacker.ReadValueBitPacked(serializer.GetFastBufferReader(), out SessionVersion);
3129
serializer.SerializeValue(ref IsRestoredSession);
3230
ByteUnpacker.ReadValueBitPacked(serializer.GetFastBufferReader(), out CurrentSessionOwner);
3331

34-
if (Version >= k_AddServerRedistribution)
32+
if (SessionVersion >= SessionConfig.ServerDistributionCompatible)
3533
{
3634
serializer.SerializeValue(ref ServerRedistribution);
3735
}
36+
else
37+
{
38+
ServerRedistribution = false;
39+
}
3840
}
3941
}
4042
}
@@ -203,11 +205,13 @@ public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int
203205
if (receivedMessageVersion >= k_AddCMBServiceConfig)
204206
{
205207
reader.ReadNetworkSerializable(out ServiceConfig);
208+
networkManager.SessionConfig = new SessionConfig(ServiceConfig);
206209
}
207210
else
208211
{
209212
reader.ReadValueSafe(out IsRestoredSession);
210213
ByteUnpacker.ReadValueBitPacked(reader, out CurrentSessionOwner);
214+
networkManager.SessionConfig = new SessionConfig(SessionConfig.NoFeatureCompatibility);
211215
}
212216
}
213217

com.unity.netcode.gameobjects/Runtime/Messaging/Messages/ConnectionRequestMessage.cs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,28 @@ namespace Unity.Netcode
77
/// </summary>
88
internal struct ClientConfig : INetworkSerializable
99
{
10-
/// <summary>
11-
/// We start at version 1, where anything less than version 1 on the service side
12-
/// is not bypass feature compatible.
13-
/// </summary>
14-
private const int k_BypassFeatureCompatible = 1;
15-
private const int k_ServerDistributionCompatible = k_BypassFeatureCompatible + 1;
16-
public int Version => k_ServerDistributionCompatible;
10+
public SessionConfig SessionConfig;
11+
public uint SessionVersion => SessionConfig.SessionVersion;
1712
public uint TickRate;
1813
public bool EnableSceneManagement;
1914

2015
// Only gets deserialized but should never be used unless testing
21-
public int RemoteClientVersion;
16+
public uint RemoteClientSessionVersion;
2217

2318
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
2419
{
20+
// Clients always write
2521
if (serializer.IsWriter)
2622
{
2723
var writer = serializer.GetFastBufferWriter();
28-
BytePacker.WriteValueBitPacked(writer, Version);
24+
BytePacker.WriteValueBitPacked(writer, SessionVersion);
2925
BytePacker.WriteValueBitPacked(writer, TickRate);
3026
writer.WriteValueSafe(EnableSceneManagement);
3127
}
3228
else
3329
{
3430
var reader = serializer.GetFastBufferReader();
35-
ByteUnpacker.ReadValueBitPacked(reader, out RemoteClientVersion);
31+
ByteUnpacker.ReadValueBitPacked(reader, out RemoteClientSessionVersion);
3632
ByteUnpacker.ReadValueBitPacked(reader, out TickRate);
3733
reader.ReadValueSafe(out EnableSceneManagement);
3834
}
@@ -41,14 +37,16 @@ public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReade
4137

4238
internal struct ConnectionRequestMessage : INetworkMessage
4339
{
40+
internal const string InvalidSessionVersionMessage = "The client version is not compatible with the session version.";
41+
4442
// This version update is unidirectional (client to service) and version
4543
// handling occurs on the service side. This serialized data is never sent
4644
// to a host or server.
4745
private const int k_SendClientConfigToService = 1;
4846
public int Version => k_SendClientConfigToService;
4947

5048
public ulong ConfigHash;
51-
public bool CMBServiceConnection;
49+
public bool DistributedAuthority;
5250
public ClientConfig ClientConfig;
5351

5452
public byte[] ConnectionData;
@@ -73,7 +71,7 @@ public void Serialize(FastBufferWriter writer, int targetVersion)
7371
// END FORBIDDEN SEGMENT
7472
// ============================================================
7573

76-
if (CMBServiceConnection)
74+
if (DistributedAuthority)
7775
{
7876
writer.WriteNetworkSerializable(ClientConfig);
7977
}
@@ -121,6 +119,11 @@ public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int
121119
// END FORBIDDEN SEGMENT
122120
// ============================================================
123121

122+
if (networkManager.DAHost)
123+
{
124+
reader.ReadNetworkSerializable(out ClientConfig);
125+
}
126+
124127
if (networkManager.NetworkConfig.ConnectionApproval)
125128
{
126129
if (!reader.TryBeginRead(FastBufferWriter.GetWriteSize(ConfigHash) + FastBufferWriter.GetWriteSize<int>()))
@@ -183,6 +186,17 @@ public void Handle(ref NetworkContext context)
183186
var networkManager = (NetworkManager)context.SystemOwner;
184187
var senderId = context.SenderId;
185188

189+
// DAHost mocking the service logic to disconnect clients trying to connect with a lower session version
190+
if (networkManager.DAHost)
191+
{
192+
if (ClientConfig.RemoteClientSessionVersion < networkManager.SessionConfig.SessionVersion)
193+
{
194+
//Disconnect with reason
195+
networkManager.ConnectionManager.DisconnectClient(senderId, InvalidSessionVersionMessage);
196+
return;
197+
}
198+
}
199+
186200
if (networkManager.ConnectionManager.PendingClients.TryGetValue(senderId, out PendingClient client))
187201
{
188202
// Set to pending approval to prevent future connection requests from being approved

0 commit comments

Comments
 (0)