Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
## [1.3.2] - 2023-03-09

### Fixes
* Fixed issue where UWP Xbox builds were crashing because the split buffer fix was not including UWP defines.
* Fixed an issue where `IPCNetworkInterface` would perform useless work for each packet received.
* Fixed an issue where `ReliableSequencedPipelineStage` could end up duplicating packets when sending reliable packets while the send queue is full.
  • Loading branch information
Unity Technologies committed Mar 9, 2023
1 parent 7854e5e commit 620351c
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 19 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Change log

## [1.3.2] - 2023-03-09

### Fixes
* Fixed issue where UWP Xbox builds were crashing because the split buffer fix was not including UWP defines.
* Fixed an issue where `IPCNetworkInterface` would perform useless work for each packet received.
* Fixed an issue where `ReliableSequencedPipelineStage` could end up duplicating packets when sending reliable packets while the send queue is full.

## [1.3.1] - 2022-12-09

### Changes
Expand Down
6 changes: 3 additions & 3 deletions Runtime/BaselibNetworkArray.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#if UNITY_STANDALONE_WIN || UNITY_GAMECORE || UNITY_XBOXONE || UNITY_EDITOR_WIN
#define BASELIB_USE_SPLIT_BUFFERS
#if UNITY_STANDALONE_WIN || UNITY_GAMECORE || UNITY_XBOXONE || UNITY_EDITOR_WIN || UNITY_WSA || UNITY_WSA_10_0
#define BASELIB_USE_SPLIT_BUFFERS
#else
#undef BASELIB_USE_SPLIT_BUFFERS
#undef BASELIB_USE_SPLIT_BUFFERS
#endif

using System;
Expand Down
2 changes: 1 addition & 1 deletion Runtime/IPCNetworkInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public unsafe void Execute()
return;
}

var resultAppend = receiver.AppendPacket(ptr, ref endpoint, resultReceive);
var resultAppend = receiver.AppendPacket(ptr, ref endpoint, resultReceive, NetworkPacketReceiver.AppendPacketMode.NoCopyNeeded);
if (resultAppend == false)
return;
}
Expand Down
12 changes: 9 additions & 3 deletions Runtime/NetworkDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,15 +226,21 @@ public unsafe int BeginSend(NetworkPipeline pipe, NetworkConnection id,
totalCapacity -= extraCapacity;
}

var result = 0;
if ((result = m_NetworkSendInterface.BeginSendMessage.Ptr.Invoke(out var sendHandle, m_NetworkSendInterface.UserData, totalCapacity)) != 0)
var sendHandle = default(NetworkInterfaceSendHandle);
if (totalCapacity > NetworkParameterConstants.MTU)
{
sendHandle.data = (IntPtr)UnsafeUtility.Malloc(totalCapacity, 8, Allocator.Temp);
sendHandle.capacity = totalCapacity;
sendHandle.id = 0;
sendHandle.size = 0;
sendHandle.flags = SendHandleFlags.AllocatedByDriver;
}
else
{
var result = m_NetworkSendInterface.BeginSendMessage.Ptr.Invoke(out sendHandle, m_NetworkSendInterface.UserData, totalCapacity);
if (result != 0)
return result;
}

if (sendHandle.capacity < totalCapacity)
return (int)Error.StatusCode.NetworkPacketOverflow;
Expand Down Expand Up @@ -364,7 +370,7 @@ internal unsafe int CompleteSend(NetworkConnection sendConnection, NetworkInterf
{
var ret = 0;
NetworkInterfaceSendHandle originalHandle = sendHandle;
if ((ret = m_NetworkSendInterface.BeginSendMessage.Ptr.Invoke(out sendHandle, m_NetworkSendInterface.UserData, originalHandle.size)) != 0)
if ((ret = m_NetworkSendInterface.BeginSendMessage.Ptr.Invoke(out sendHandle, m_NetworkSendInterface.UserData, NetworkParameterConstants.MTU)) != 0)
{
return ret;
}
Expand Down
6 changes: 3 additions & 3 deletions Runtime/Pipelines/ReliableUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ public static unsafe InboundRecvBuffer ResumeReceive(NetworkPipelineContext cont
inBuffer.bufferLength = info->Size;
reliable->Delivered = startSequence;

if ((ushort)(startSequence + 1) <= latestReceivedPacket)
if (SequenceHelpers.LessThan16((ushort)startSequence, (ushort)latestReceivedPacket))
{
reliable->Resume = (ushort)(startSequence + 1);
needsResume = true;
Expand Down Expand Up @@ -902,7 +902,7 @@ internal static unsafe int Read(NetworkPipelineContext context, ReliableHeader h
}

var window = reliable->WindowSize - 1;
if (SequenceHelpers.GreaterThan16((ushort)(header.SequenceId + 1), (ushort)reliable->ReceivedPackets.Sequence))
if (SequenceHelpers.GreaterThan16(header.SequenceId, (ushort)reliable->ReceivedPackets.Sequence))
{
int distance = SequenceHelpers.AbsDistance(header.SequenceId, (ushort)reliable->ReceivedPackets.Sequence);

Expand All @@ -927,7 +927,7 @@ internal static unsafe int Read(NetworkPipelineContext context, ReliableHeader h

reliable->ReceivedPackets.Sequence = header.SequenceId;
}
else if (SequenceHelpers.LessThan16(header.SequenceId, (ushort)reliable->ReceivedPackets.Sequence))
else
{
int distance = SequenceHelpers.AbsDistance(header.SequenceId, (ushort)reliable->ReceivedPackets.Sequence);
// If this is a resent packet the distance will seem very big and needs to be calculated again with adjustment for wrapping
Expand Down
104 changes: 104 additions & 0 deletions Tests/Runtime/SendMessageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,5 +283,109 @@ public void SendMessage_ReceiveAfterConnectionClose([ValueSource("s_SecureModePa
});
}
}

[Test]
public void SendMessage_ReliableStressTest()
{
const int TotalPackets = 500;

for (uint seed = 1; seed <= 5; seed++)
{
Debug.Log($"Testing with random seed {seed}...");

var settings = new NetworkSettings();
settings.WithSimulatorStageParameters(
maxPacketCount: 1000,
maxPacketSize: NetworkParameterConstants.MTU,
packetDelayMs: 0,
packetJitterMs: 5,
packetDropPercentage: 5,
randomSeed: seed);
settings.WithReliableStageParameters(windowSize: 64);

var dummyData = new NativeArray<byte>(1000, Allocator.Temp);
var expectedPacketLength = dummyData.Length + sizeof(int);

using (var server = CreateServer(SecureProtocolMode.SecureProtocolDisabled, settings, new IPCNetworkInterface()))
using (var client = CreateClient(SecureProtocolMode.SecureProtocolDisabled, settings, new IPCNetworkInterface()))
{
var serverPipeline = server.CreatePipeline(typeof(ReliableSequencedPipelineStage), typeof(SimulatorPipelineStage), typeof(SimulatorPipelineStageInSend));
var clientPipeline = client.CreatePipeline(typeof(ReliableSequencedPipelineStage), typeof(SimulatorPipelineStage), typeof(SimulatorPipelineStageInSend));

ConnectServerAndClient(NetworkEndPoint.LoopbackIpv4, server, client, out var s2cConnection, out var c2sConnection);

var numServerDataEvents = 0;
var numClientDataEvents = 0;

var numServerPacketsSent = 0;
var numClientPacketsSent = 0;

WaitForCondition(() =>
{
while (numServerPacketsSent < TotalPackets)
{
Assert.AreEqual(0, server.BeginSend(serverPipeline, s2cConnection, out var serverWriter));
serverWriter.WriteInt(numServerPacketsSent);
serverWriter.WriteBytes(dummyData);

var result = server.EndSend(serverWriter);
if (result != expectedPacketLength)
{
Assert.AreEqual((int)Error.StatusCode.NetworkSendQueueFull, result);
break;
}
numServerPacketsSent++;
}

while (numClientPacketsSent < TotalPackets)
{
Assert.AreEqual(0, client.BeginSend(clientPipeline, c2sConnection, out var clientWriter));
clientWriter.WriteInt(numClientPacketsSent + 42000);
clientWriter.WriteBytes(dummyData);

var result = client.EndSend(clientWriter);
if (result != expectedPacketLength)
{
Assert.AreEqual((int)Error.StatusCode.NetworkSendQueueFull, result);
break;
}
numClientPacketsSent++;
}

server.ScheduleUpdate().Complete();
client.ScheduleUpdate().Complete();

NetworkEvent.Type ev;
NetworkConnection connection;
DataStreamReader reader;
NetworkPipeline pipeline;

while ((ev = server.PopEvent(out connection, out reader, out pipeline)) != NetworkEvent.Type.Empty)
{
Assert.AreEqual(NetworkEvent.Type.Data, ev);
Assert.AreEqual(s2cConnection, connection);
Assert.AreEqual(serverPipeline, pipeline);
Assert.AreEqual(expectedPacketLength, reader.Length);
Assert.AreEqual(numServerDataEvents + 42000, reader.ReadInt());

numServerDataEvents++;
}

while ((ev = client.PopEvent(out connection, out reader, out pipeline)) != NetworkEvent.Type.Empty)
{
Assert.AreEqual(NetworkEvent.Type.Data, ev);
Assert.AreEqual(c2sConnection, connection);
Assert.AreEqual(clientPipeline, pipeline);
Assert.AreEqual(expectedPacketLength, reader.Length);
Assert.AreEqual(numClientDataEvents, reader.ReadInt());

numClientDataEvents++;
}

return numServerDataEvents == TotalPackets && numClientDataEvents == TotalPackets;
}, "Timed out waiting for all reliable packets.", 10000);
}
}
}
}
}
10 changes: 5 additions & 5 deletions ValidationExceptions.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,27 @@
{
"ValidationTest": "Restricted File Type Validation",
"ExceptionMessage": "/Samples~/CustomNetworkInterface/Scripts/network.bindings~/build.bat cannot be included in a package.",
"PackageVersion": "1.3.1"
"PackageVersion": "1.3.2"
},
{
"ValidationTest": "Restricted File Type Validation",
"ExceptionMessage": "/Samples~/CustomNetworkInterface/Scripts/network.bindings~/shell.bat cannot be included in a package.",
"PackageVersion": "1.3.1"
"PackageVersion": "1.3.2"
},
{
"ValidationTest": "API Validation",
"ExceptionMessage": "Additions require a new minor or major version.",
"PackageVersion": "1.3.1"
"PackageVersion": "1.3.2"
},
{
"ValidationTest": "API Validation",
"ExceptionMessage": "New assembly \"Unity.Networking.Transport.RuntimeTests\" may only be added in a new minor or major version.",
"PackageVersion": "1.3.1"
"PackageVersion": "1.3.2"
},
{
"ValidationTest": "API Validation",
"ExceptionMessage": "New assembly \"Unity.Networking.Transport.EditorTests\" may only be added in a new minor or major version.",
"PackageVersion": "1.3.1"
"PackageVersion": "1.3.2"
}
],
"WarningExceptions": []
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "com.unity.transport",
"displayName": "Unity Transport",
"version": "1.3.1",
"version": "1.3.2",
"unity": "2020.3",
"unityRelease": "0f1",
"description": "Unity network transport layer - the low-level interface for sending UDP data",
Expand All @@ -11,16 +11,16 @@
"com.unity.mathematics": "1.2.6"
},
"_upm": {
"changelog": "### Changes\n* It is now possible to set a window size of up to 64 for `ReliableSequencedPipelineStage` (use `NetworkSettings.WithReliableStageParameters` to modify the value). Doing so increases the packet header size by 4 bytes though, so the default value remains at 32.\n\n### Fixes\n* Fixed an issue where if one end of a reliable pipeline stopped sending any traffic and its latest ACK message was lost, then the other end would stall.\n* Fixed a crash when using DTLS if an update was delayed for long enough that both the disconnection and heartbeat timeouts expire."
"changelog": "### Fixes\n* Fixed issue where UWP Xbox builds were crashing because the split buffer fix was not including UWP defines.\n* Fixed an issue where `IPCNetworkInterface` would perform useless work for each packet received.\n* Fixed an issue where `ReliableSequencedPipelineStage` could end up duplicating packets when sending reliable packets while the send queue is full."
},
"upmCi": {
"footprint": "d5689bea7cfc3808f75e8306def417c52e04f307"
"footprint": "98182eeaea2fd3b091f4a2b16b9c9471598db23b"
},
"documentationUrl": "https://docs.unity3d.com/Packages/[email protected]/manual/index.html",
"repository": {
"url": "https://github.cds.internal.unity3d.com/unity/com.unity.transport.git",
"type": "git",
"revision": "80ac568c7067b2af506786cefbe8a71e4025d032"
"revision": "21ae74bd7af3124f937100ff2cf8d2130fcd9307"
},
"samples": [
{
Expand Down

0 comments on commit 620351c

Please sign in to comment.