From 875001016476805cb29ac997bb48b3e5f27947af Mon Sep 17 00:00:00 2001
From: Unity Technologies <@unity>
Date: Tue, 23 Mar 2021 00:00:00 +0000
Subject: [PATCH] com.unity.transport@0.8.0-preview.8 ## [0.8.0] - 2021-03-23
### New features * Added overloads of `PopEvent` and `PopEventForConnection`
which return the pipeline used as an out parameter.
### Changes
### Fixes
* Fixed some compatility issues with tiny.
* Fixed a crash when sending messages slightly less than one MTU using the fragmentation pipeline.
* Fixed a bug causing `NetworkDriver.RemoteEndPoint` to return an invalid value when using the default network interface.
### Upgrade guide
## [0.7.0] - 2021-02-05
### New features
* Added `DataStreamWriter.WriteRawbits` and `DataStreamWriter.ReadRawBits` for reading and writing raw bits from a data stream.
### Changes
* Optimized the `NetworkCompressionModel` to find buckets in constant time.
* Changed the error behavior of `DataStreamReader` to be consistent between the editor and players.
### Fixes
* Fixed a crash when receiving a packet with an invalid pipeline identifier
### Upgrade guide
## [0.6.0] - 2020-11-26
### New features
* An error handling pass has been made and `Error.StatusCode` have been added to indicate more specific errors.
* `Error.DisconnectReason` has been added, so when NetworkDriver.PopEvent returns a `NetworkEvent.Type.Disconnect` the reader returned contains 1 byte of data indicating the reason.
### Changes
* The function signature for NetworkDriver.BeginSend has changed. It now returns a `int` value indicating if the function succeeded or not and the DataStreamWriter now instead is returned as a `out` parameter.
* The function signature for INetworkInterface.Initialize has changed. It now requires you to return a `int` value indicating if the function succeeded or not.
* The function signature for INetworkInterface.CreateInterfaceEndPoint has changed. It now requires you to return a `int` value indicating if the function succeeded or not, and NetworkInterfaceEndPoint is now returned as a `out` parameter.
### Fixes
* Fixed a potential crash when receiving a malformated packet.
* Fixed an issue where the DataStream could sometimes fail writing packet uints before the buffer was full.
### Upgrade guide
* `NetworkDriver.BeginSend` now returns a `int` indicating a `Error.StatusCode`, and the `DataStreamWriter` is passed as an `out` parameter.
---
CHANGELOG.md | 26 +++
DESIGN.md | 20 ++
DESIGN.md.meta | 7 +
Runtime/BaselibNetworkInterface.cs | 22 ++-
Runtime/DataStream.cs | 183 +++++++++++-------
Runtime/IPCManager.cs | 9 +-
Runtime/IPCNetworkInterface.cs | 7 +-
Runtime/NetworkCompressionModel.cs | 10 +-
Runtime/NetworkConnection.cs | 12 +-
Runtime/NetworkDriver.cs | 59 ++++--
Runtime/NetworkEndPoint.cs | 8 +-
Runtime/NetworkEventQueue.cs | 34 +++-
Runtime/NetworkPipeline.cs | 24 +--
.../Pipelines/FragmentationPipelineStage.cs | 15 +-
Runtime/Pipelines/NullPipelineStage.cs | 6 +-
.../ReliableSequencedPipelineStage.cs | 6 +-
Runtime/Pipelines/ReliableUtility.cs | 5 +-
Runtime/Pipelines/SimulatorPipelineStage.cs | 12 +-
.../UnreliableSequencedPipelineStage.cs | 6 +-
Runtime/Utilities.cs | 21 +-
Tests/Editor/DataStreamTests.cs | 5 +-
Tests/Editor/FragmentationPipelineTests.cs | 138 ++++++++++++-
Tests/Editor/NetworkPipelineTest.cs | 42 ++--
Tests/Editor/ReliablePipelineTests.cs | 12 +-
...ty.Networking.Transport.EditorTests.asmdef | 2 +-
package.json | 13 +-
26 files changed, 508 insertions(+), 196 deletions(-)
create mode 100644 DESIGN.md
create mode 100644 DESIGN.md.meta
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4b0e438..6771044 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,31 @@
# Change log
+## [0.8.0] - 2021-03-23
+### New features
+* Added overloads of `PopEvent` and `PopEventForConnection` which return the pipeline used as an out parameter.
+
+### Changes
+
+### Fixes
+* Fixed some compatility issues with tiny.
+* Fixed a crash when sending messages slightly less than one MTU using the fragmentation pipeline.
+* Fixed a bug causing `NetworkDriver.RemoteEndPoint` to return an invalid value when using the default network interface.
+
+### Upgrade guide
+
+## [0.7.0] - 2021-02-05
+### New features
+* Added `DataStreamWriter.WriteRawbits` and `DataStreamWriter.ReadRawBits` for reading and writing raw bits from a data stream.
+
+### Changes
+* Optimized the `NetworkCompressionModel` to find buckets in constant time.
+* Changed the error behavior of `DataStreamReader` to be consistent between the editor and players.
+
+### Fixes
+* Fixed a crash when receiving a packet with an invalid pipeline identifier
+
+### Upgrade guide
+
## [0.6.0] - 2020-11-26
### New features
* An error handling pass has been made and `Error.StatusCode` have been added to indicate more specific errors.
diff --git a/DESIGN.md b/DESIGN.md
new file mode 100644
index 0000000..4fbe4cd
--- /dev/null
+++ b/DESIGN.md
@@ -0,0 +1,20 @@
+# Unity Transport Design Rules
+
+## All features are optional
+Unity transport is conceptually a thin layer on UDP adding a connection concept. All additional features on top of UDP + connection are optional, when not used they have zero performance or complexity overhead. If possible features are implemented as pipeline stages.
+
+Features that have a limited audience are implemented outside the package - either in game code or other packages.
+
+## Full control over processing time and when packets are sent/received
+UTP is optimized for making games. It can be used without creating any additional threads - only using the JobSystem. The layer on top has full control over when the transport schedules jobs. The layer on top also has full control over when packets are sent on the wire. There are no internal buffers delaying messages (except possibly in pipelines).
+
+There is generally no need to continuously poll for messages since incoming data needs to be read right before simulation starts, and we cannot start using new data in the middle of the simulation
+
+## Written in HPC#
+All code is jobified and burst compiled, there is no garbage collection. The transport does not spend any processing time outside setup on the main thread, and it allows the layer on top to not sync on the main thread.
+
+## Follows the DOTS principles, is usable in DOTS Runtime and always compatible with the latest versions of the DOTS packages
+There should always be a version compatible with the latest verions of the DOTS dependencies such as Unity Collections.
+
+## The protocol is well defined and documented
+Other implementations can communicate with games written with Unity Transport, without reverse engineering or reading the transport source code
\ No newline at end of file
diff --git a/DESIGN.md.meta b/DESIGN.md.meta
new file mode 100644
index 0000000..d32b361
--- /dev/null
+++ b/DESIGN.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 99b333ad37d614e42b1a4776de09e34e
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/BaselibNetworkInterface.cs b/Runtime/BaselibNetworkInterface.cs
index 1264ba6..8ecf7fe 100644
--- a/Runtime/BaselibNetworkInterface.cs
+++ b/Runtime/BaselibNetworkInterface.cs
@@ -170,7 +170,15 @@ public unsafe NetworkEndPoint GetGenericEndPoint(NetworkInterfaceEndPoint endpoi
{
// Set to a valid address so length is set correctly
var address = NetworkEndPoint.LoopbackIpv4;
- UnsafeUtility.MemCpy(&address.rawNetworkAddress, endpoint.data, endpoint.dataLength);
+ var error = default(ErrorState);
+ var slice = m_LocalAndTempEndpoint.AtIndexAsSlice(0, (uint)Binding.Baselib_RegisteredNetwork_Endpoint_MaxSize);
+ NetworkEndpoint local;
+ local.slice = slice;
+ local.slice.size = (uint)endpoint.dataLength;
+ UnsafeUtility.MemCpy((void*)local.slice.data, endpoint.data, endpoint.dataLength);
+ Binding.Baselib_RegisteredNetwork_Endpoint_GetNetworkAddress(local, &address.rawNetworkAddress, &error);
+ if (error.code != ErrorCode.Success)
+ return default;
return address;
}
@@ -333,7 +341,9 @@ public unsafe void Execute()
var remote = packet.remoteEndpoint.slice;
address.dataLength = (int)remote.size;
UnsafeUtility.MemCpy(address.data, (void*)remote.data, (int)remote.size);
- Receiver.ReceiveCount += Receiver.AppendPacket(address, *(UdpCHeader*)packet.payload.data, receivedBytes);
+ //FIXME: remove when burst 1.5 fix the problem
+ var temp = (UdpCHeader*)packet.payload.data;
+ Receiver.ReceiveCount += Receiver.AppendPacket(address, *temp,receivedBytes);
}
// Reuse the requests after they have been processed.
for (int i = 0; i < count; i++)
@@ -475,7 +485,7 @@ public unsafe NetworkSendInterface CreateSendInterface()
};
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[AOT.MonoPInvokeCallback(typeof(NetworkSendInterface.BeginSendMessageDelegate))]
private static unsafe int BeginSendMessage(out NetworkInterfaceSendHandle handle, IntPtr userData, int requiredPayloadSize)
{
@@ -499,7 +509,7 @@ private static unsafe int BeginSendMessage(out NetworkInterfaceSendHandle handle
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[AOT.MonoPInvokeCallback(typeof(NetworkSendInterface.EndSendMessageDelegate))]
private static unsafe int EndSendMessage(ref NetworkInterfaceSendHandle handle, ref NetworkInterfaceEndPoint address, IntPtr userData, ref NetworkSendQueueHandle sendQueueHandle)
{
@@ -523,12 +533,12 @@ private static unsafe int EndSendMessage(ref NetworkInterfaceSendHandle handle,
if (error.code != ErrorCode.Success)
{
baselib->m_PayloadsTx.ReleaseHandle(index);
- return -(int)error.code;
+ return (int) error.code == -1 ? -1 : -(int) error.code;
}
return handle.size;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[AOT.MonoPInvokeCallback(typeof(NetworkSendInterface.AbortSendMessageDelegate))]
private static unsafe void AbortSendMessage(ref NetworkInterfaceSendHandle handle, IntPtr userData)
{
diff --git a/Runtime/DataStream.cs b/Runtime/DataStream.cs
index 55e2ccd..b719a82 100644
--- a/Runtime/DataStream.cs
+++ b/Runtime/DataStream.cs
@@ -2,6 +2,7 @@
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using System;
+using System.Diagnostics;
namespace Unity.Networking.Transport
{
@@ -93,10 +94,7 @@ struct StreamData
/// The used to allocate the memory.
public DataStreamWriter(int length, Allocator allocator)
{
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- if (allocator != Allocator.Temp)
- throw new InvalidOperationException("DataStreamWriters can only be created with temp memory");
-#endif
+ CheckAllocator(allocator);
Initialize(out this, new NativeArray(length, allocator));
}
@@ -169,9 +167,7 @@ public int Capacity
{
get
{
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- AtomicSafetyHandle.CheckReadAndThrow(m_Safety);
-#endif
+ CheckRead();
return m_Data.capacity;
}
}
@@ -183,9 +179,7 @@ public int Length
{
get
{
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- AtomicSafetyHandle.CheckReadAndThrow(m_Safety);
-#endif
+ CheckRead();
SyncBitData();
return m_Data.length + ((m_Data.bitIndex + 7) >> 3);
}
@@ -197,9 +191,7 @@ public int LengthInBits
{
get
{
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- AtomicSafetyHandle.CheckReadAndThrow(m_Safety);
-#endif
+ CheckRead();
SyncBitData();
return m_Data.length*8 + m_Data.bitIndex;
}
@@ -210,9 +202,8 @@ private void SyncBitData()
var bitIndex = m_Data.bitIndex;
if (bitIndex <= 0)
return;
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- AtomicSafetyHandle.CheckWriteAndThrow(m_Safety);
-#endif
+ CheckWrite();
+
var bitBuffer = m_Data.bitBuffer;
int offset = 0;
while (bitIndex > 0)
@@ -237,9 +228,8 @@ public void Flush()
public bool WriteBytes(byte* data, int bytes)
{
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- AtomicSafetyHandle.CheckWriteAndThrow(m_Safety);
-#endif
+ CheckWrite();
+
if (m_Data.length + ((m_Data.bitIndex + 7) >> 3) + bytes > m_Data.capacity)
{
++m_Data.failedWrites;
@@ -329,26 +319,33 @@ private void FlushBits()
}
void WriteRawBitsInternal(uint value, int numbits)
{
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- if (numbits < 0 || numbits > 32)
- throw new ArgumentOutOfRangeException("Invalid number of bits");
- if (value >= (1UL << numbits))
- throw new ArgumentOutOfRangeException("Value does not fit in the specified number of bits");
-#endif
+ CheckBits(value, numbits);
m_Data.bitBuffer |= ((ulong)value << m_Data.bitIndex);
m_Data.bitIndex += numbits;
}
+ public bool WriteRawBits(uint value, int numbits)
+ {
+ CheckWrite();
+
+ if (m_Data.length + ((m_Data.bitIndex + numbits + 7) >> 3) > m_Data.capacity)
+ {
+ ++m_Data.failedWrites;
+ return false;
+ }
+ WriteRawBitsInternal(value, numbits);
+ FlushBits();
+ return true;
+ }
public bool WritePackedUInt(uint value, NetworkCompressionModel model)
{
+ CheckWrite();
int bucket = model.CalculateBucket(value);
uint offset = model.bucketOffsets[bucket];
int bits = model.bucketSizes[bucket];
ushort encodeEntry = model.encodeTable[bucket];
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- AtomicSafetyHandle.CheckWriteAndThrow(m_Safety);
-#endif
+
if (m_Data.length + ((m_Data.bitIndex + (encodeEntry&0xff) + bits + 7) >> 3) > m_Data.capacity)
{
++m_Data.failedWrites;
@@ -380,12 +377,10 @@ public bool WritePackedIntDelta(int value, int baseline, NetworkCompressionModel
}
public bool WritePackedFloatDelta(float value, float baseline, NetworkCompressionModel model)
{
+ CheckWrite();
var bits = 0;
if (value != baseline)
bits = 32;
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- AtomicSafetyHandle.CheckWriteAndThrow(m_Safety);
-#endif
if (m_Data.length + ((m_Data.bitIndex + 1 + bits + 7) >> 3) > m_Data.capacity)
{
++m_Data.failedWrites;
@@ -502,6 +497,38 @@ public void Clear()
m_Data.bitBuffer = 0;
m_Data.failedWrites = 0;
}
+
+ [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
+ void CheckRead()
+ {
+#if ENABLE_UNITY_COLLECTIONS_CHECKS
+ AtomicSafetyHandle.CheckReadAndThrow(m_Safety);
+#endif
+ }
+
+ [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
+ void CheckWrite()
+ {
+#if ENABLE_UNITY_COLLECTIONS_CHECKS
+ AtomicSafetyHandle.CheckWriteAndThrow(m_Safety);
+#endif
+ }
+
+ [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
+ static void CheckAllocator(Allocator allocator)
+ {
+ if (allocator != Allocator.Temp)
+ throw new InvalidOperationException("DataStreamWriters can only be created with temp memory");
+ }
+
+ [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
+ static void CheckBits(uint value, int numbits)
+ {
+ if (numbits < 0 || numbits > 32)
+ throw new ArgumentOutOfRangeException("Invalid number of bits");
+ if (value >= (1UL << numbits))
+ throw new ArgumentOutOfRangeException("Value does not fit in the specified number of bits");
+ }
}
///
@@ -586,9 +613,7 @@ public int Length
{
get
{
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- AtomicSafetyHandle.CheckReadAndThrow(m_Safety);
-#endif
+ CheckRead();
return m_Length;
}
}
@@ -613,18 +638,15 @@ public bool IsCreated
/// position.
public void ReadBytes(byte* data, int length)
{
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- AtomicSafetyHandle.CheckReadAndThrow(m_Safety);
-#endif
+ CheckRead();
if (GetBytesRead() + length > m_Length)
{
++m_Context.m_FailedReads;
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- throw new System.ArgumentOutOfRangeException();
-#else
+#if ENABLE_UNITY_COLLECTIONS_CHECKS && !UNITY_DOTSRUNTIME
+ UnityEngine.Debug.LogError($"Trying to read {length} bytes from a stream where only {m_Length - GetBytesRead()} are available");
+#endif
UnsafeUtility.MemClear(data, length);
return;
-#endif
}
// Restore the full bytes moved to the bit buffer but no consumed
m_Context.m_ReadByteIndex -= (m_Context.m_BitIndex >> 3);
@@ -652,6 +674,20 @@ public int GetBitsRead()
{
return (m_Context.m_ReadByteIndex<<3) - m_Context.m_BitIndex;
}
+ public void SeekSet(int pos)
+ {
+ if (pos > m_Length)
+ {
+ ++m_Context.m_FailedReads;
+#if ENABLE_UNITY_COLLECTIONS_CHECKS && !UNITY_DOTSRUNTIME
+ UnityEngine.Debug.LogError($"Trying to seek to {pos} in a stream of length {m_Length}");
+#endif
+ return;
+ }
+ m_Context.m_ReadByteIndex = pos;
+ m_Context.m_BitIndex = 0;
+ m_Context.m_BitBuffer = 0UL;
+ }
public byte ReadByte()
{
@@ -726,9 +762,7 @@ public float ReadFloat()
}
public uint ReadPackedUInt(NetworkCompressionModel model)
{
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- AtomicSafetyHandle.CheckReadAndThrow(m_Safety);
-#endif
+ CheckRead();
FillBitBuffer();
uint peekMask = (1u << NetworkCompressionModel.k_MaxHuffmanSymbolLength) - 1u;
uint peekBits = (uint)m_Context.m_BitBuffer & peekMask;
@@ -739,11 +773,10 @@ public uint ReadPackedUInt(NetworkCompressionModel model)
if (m_Context.m_BitIndex < length)
{
++m_Context.m_FailedReads;
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- throw new System.ArgumentOutOfRangeException();
-#else
- return 0;
+#if ENABLE_UNITY_COLLECTIONS_CHECKS && !UNITY_DOTSRUNTIME
+ UnityEngine.Debug.LogError($"Trying to read {length} bits from a stream where only {m_Context.m_BitIndex} are available");
#endif
+ return 0;
}
// Skip Huffman bits
@@ -764,24 +797,26 @@ void FillBitBuffer()
}
uint ReadRawBitsInternal(int numbits)
{
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- if (numbits < 0 || numbits > 32)
- throw new ArgumentOutOfRangeException("Invalid number of bits");
-#endif
+ CheckBits(numbits);
if (m_Context.m_BitIndex < numbits)
{
++m_Context.m_FailedReads;
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- throw new System.ArgumentOutOfRangeException("Not enough bits to read");
-#else
- return 0;
+#if ENABLE_UNITY_COLLECTIONS_CHECKS && !UNITY_DOTSRUNTIME
+ UnityEngine.Debug.LogError($"Trying to read {numbits} bits from a stream where only {m_Context.m_BitIndex} are available");
#endif
+ return 0;
}
uint res = (uint)(m_Context.m_BitBuffer & ((1UL << numbits) - 1UL));
m_Context.m_BitBuffer >>= numbits;
m_Context.m_BitIndex -= numbits;
return res;
}
+ public uint ReadRawBits(int numbits)
+ {
+ CheckRead();
+ FillBitBuffer();
+ return ReadRawBitsInternal(numbits);
+ }
public int ReadPackedInt(NetworkCompressionModel model)
{
@@ -805,9 +840,7 @@ public uint ReadPackedUIntDelta(uint baseline, NetworkCompressionModel model)
}
public float ReadPackedFloatDelta(float baseline, NetworkCompressionModel model)
{
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- AtomicSafetyHandle.CheckReadAndThrow(m_Safety);
-#endif
+ CheckRead();
FillBitBuffer();
if (ReadRawBitsInternal(1) == 0)
return baseline;
@@ -857,11 +890,12 @@ public unsafe ushort ReadFixedString(byte* data, int maxLength)
{
ushort length = ReadUShort();
if (length > maxLength)
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- throw new InvalidOperationException("Invalid string length");
-#else
- return 0;
+ {
+#if ENABLE_UNITY_COLLECTIONS_CHECKS && !UNITY_DOTSRUNTIME
+ UnityEngine.Debug.LogError($"Trying to read a string of length {length} but max length is {maxLength}");
#endif
+ return 0;
+ }
ReadBytes(data, length);
return length;
}
@@ -905,11 +939,12 @@ public unsafe ushort ReadPackedFixedStringDelta(byte* data, int maxLength, byte*
{
uint length = ReadPackedUIntDelta(baseLength, model);
if (length > (uint)maxLength)
-#if ENABLE_UNITY_COLLECTIONS_CHECKS
- throw new InvalidOperationException("Invalid string length");
-#else
- return 0;
+ {
+#if ENABLE_UNITY_COLLECTIONS_CHECKS && !UNITY_DOTSRUNTIME
+ UnityEngine.Debug.LogError($"Trying to read a string of length {length} but max length is {maxLength}");
#endif
+ return 0;
+ }
if (length <= baseLength)
{
for (int i = 0; i < length; ++i)
@@ -924,5 +959,19 @@ public unsafe ushort ReadPackedFixedStringDelta(byte* data, int maxLength, byte*
}
return (ushort)length;
}
+ [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
+ void CheckRead()
+ {
+#if ENABLE_UNITY_COLLECTIONS_CHECKS
+ AtomicSafetyHandle.CheckReadAndThrow(m_Safety);
+#endif
+ }
+
+ [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
+ static void CheckBits(int numbits)
+ {
+ if (numbits < 0 || numbits > 32)
+ throw new ArgumentOutOfRangeException("Invalid number of bits");
+ }
}
}
diff --git a/Runtime/IPCManager.cs b/Runtime/IPCManager.cs
index d11b5d8..da4275f 100644
--- a/Runtime/IPCManager.cs
+++ b/Runtime/IPCManager.cs
@@ -1,11 +1,12 @@
using System;
-using System.Collections.Generic;
+using System.Diagnostics;
using System.Runtime.InteropServices;
using Unity.Collections;
using Unity.Networking.Transport.Utilities;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using Unity.Networking.Transport.Protocols;
+using Random = Unity.Mathematics.Random;
namespace Unity.Networking.Transport
{
@@ -70,12 +71,10 @@ public unsafe NetworkInterfaceEndPoint CreateEndPoint(ushort port)
int id = 0;
if (port == 0)
{
- var rnd = new Random();
while (id == 0)
{
- port = (ushort)rnd.Next(1, 0xffff);
- int tmp;
- if (!m_IPCChannels.TryGetValue(port, out tmp))
+ port = RandomHelpers.GetRandomUShort();
+ if (!m_IPCChannels.TryGetValue(port, out _))
{
id = m_IPCChannels.Count() + 1;
m_IPCChannels.TryAdd(port, id);
diff --git a/Runtime/IPCNetworkInterface.cs b/Runtime/IPCNetworkInterface.cs
index aa73514..ac31de0 100644
--- a/Runtime/IPCNetworkInterface.cs
+++ b/Runtime/IPCNetworkInterface.cs
@@ -23,7 +23,6 @@ public int CreateInterfaceEndPoint(NetworkEndPoint address, out NetworkInterface
throw new ArgumentException("IPC network driver can only handle loopback addresses");
#else
endpoint = default(NetworkInterfaceEndPoint);
- endpoint.dataLength = 0;
return (int)Error.StatusCode.NetworkArgumentMismatch;
#endif
}
@@ -162,7 +161,7 @@ public NetworkSendInterface CreateSendInterface()
};
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[AOT.MonoPInvokeCallback(typeof(NetworkSendInterface.BeginSendMessageDelegate))]
private static unsafe int BeginSendMessage(out NetworkInterfaceSendHandle handle, IntPtr userData, int requiredPayloadSize)
{
@@ -174,7 +173,7 @@ private static unsafe int BeginSendMessage(out NetworkInterfaceSendHandle handle
return 0;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[AOT.MonoPInvokeCallback(typeof(NetworkSendInterface.EndSendMessageDelegate))]
private static unsafe int EndSendMessage(ref NetworkInterfaceSendHandle handle, ref NetworkInterfaceEndPoint address, IntPtr userData, ref NetworkSendQueueHandle sendQueueHandle)
{
@@ -186,7 +185,7 @@ private static unsafe int EndSendMessage(ref NetworkInterfaceSendHandle handle,
sendQueue.Enqueue(msg);
return handle.size;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[AOT.MonoPInvokeCallback(typeof(NetworkSendInterface.AbortSendMessageDelegate))]
private static void AbortSendMessage(ref NetworkInterfaceSendHandle handle, IntPtr userData)
{
diff --git a/Runtime/NetworkCompressionModel.cs b/Runtime/NetworkCompressionModel.cs
index 6ceb17a..2496891 100644
--- a/Runtime/NetworkCompressionModel.cs
+++ b/Runtime/NetworkCompressionModel.cs
@@ -1,5 +1,6 @@
using System;
using Unity.Collections;
+using Unity.Mathematics;
namespace Unity.Networking.Transport
{
@@ -14,6 +15,11 @@ public unsafe struct NetworkCompressionModel : IDisposable
{
0, 1, 2, 4, 8, 16, 32, 96, 352, 1376, 5472, 38240, 300384, 2397536, 19174752, 153392480
};
+ internal static readonly int[] k_FirstBucketCandidate =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
+ 15, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 8, 8, 7, 7, 6, 5, 4, 3, 2, 1, 1, 0
+ };
internal static readonly byte[] k_DefaultModelData = { 16, // 16 symbols
2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 6, 6,
0, 0 }; // no contexts
@@ -179,8 +185,8 @@ private static void GenerateHuffmanDecodeTable(ushort[] decodeTable, int decodeT
public fixed uint bucketOffsets[k_AlphabetSize];
public int CalculateBucket(uint value)
{
- int bucketIndex = 0;
- while (bucketIndex + 1 < k_AlphabetSize && value >= bucketOffsets[bucketIndex + 1]) // TODO: use CountLeadingZeros to do this in constant time
+ int bucketIndex = k_FirstBucketCandidate[math.lzcnt(value)];
+ if (bucketIndex + 1 < k_AlphabetSize && value >= bucketOffsets[bucketIndex + 1])
bucketIndex++;
return bucketIndex;
diff --git a/Runtime/NetworkConnection.cs b/Runtime/NetworkConnection.cs
index 415c2f6..bcd8299 100644
--- a/Runtime/NetworkConnection.cs
+++ b/Runtime/NetworkConnection.cs
@@ -10,13 +10,16 @@ namespace Error
public enum DisconnectReason : byte
{
/// Indicates a normal disconnection as a result of calling Disconnect on the connection.
- Default,
+ Default, // don't assign explicit values
/// Indicates the connection timed out.
Timeout,
/// Indicates the connection failed to establish a connection after .
MaxConnectionAttempts,
/// Indicates the connection was closed remotely.
- ClosedByRemote
+ ClosedByRemote,
+
+ /// Used only for count. Keep last and don't assign explicit values
+ Count
}
public enum StatusCode
@@ -79,6 +82,11 @@ public NetworkEvent.Type PopEvent(NetworkDriver driver, out DataStreamReader str
return driver.PopEventForConnection(this, out stream);
}
+ public NetworkEvent.Type PopEvent(NetworkDriver driver, out DataStreamReader stream, out NetworkPipeline pipeline)
+ {
+ return driver.PopEventForConnection(this, out stream, out pipeline);
+ }
+
///
/// Close an active NetworkConnection, similar to .
///
diff --git a/Runtime/NetworkDriver.cs b/Runtime/NetworkDriver.cs
index 2d551c2..196e35b 100644
--- a/Runtime/NetworkDriver.cs
+++ b/Runtime/NetworkDriver.cs
@@ -9,7 +9,7 @@
using Unity.Jobs.LowLevel.Unsafe;
using Unity.Mathematics;
using Unity.Networking.Transport.Error;
-using Random = System.Random;
+using Unity.Networking.Transport.Utilities;
namespace Unity.Networking.Transport
{
@@ -77,14 +77,22 @@ private Concurrent ToConcurrentSendOnly()
public struct Concurrent
{
public NetworkEvent.Type PopEventForConnection(NetworkConnection connectionId, out DataStreamReader reader)
+ {
+ return PopEventForConnection(connectionId, out reader, out var _);
+ }
+
+ public NetworkEvent.Type PopEventForConnection(NetworkConnection connectionId, out DataStreamReader reader, out NetworkPipeline pipeline)
{
int offset, size;
+ pipeline = default(NetworkPipeline);
+
reader = default(DataStreamReader);
if (connectionId.m_NetworkId < 0 || connectionId.m_NetworkId >= m_ConnectionList.Length ||
m_ConnectionList[connectionId.m_NetworkId].Version != connectionId.m_NetworkVersion)
return (int) NetworkEvent.Type.Empty;
- var type = m_EventQueue.PopEventForConnection(connectionId.m_NetworkId, out offset, out size);
+ var type = m_EventQueue.PopEventForConnection(connectionId.m_NetworkId, out offset, out size, out var pipelineId);
+ pipeline = new NetworkPipeline { Id = pipelineId };
if (type == NetworkEvent.Type.Disconnect && offset < 0)
reader = new DataStreamReader(((NativeArray)m_DisconnectReasons).GetSubArray(math.abs(offset), 1));
@@ -526,7 +534,8 @@ public NetworkDriver(INetworkInterface netIf, params INetworkParameter[] param)
#if ENABLE_UNITY_COLLECTIONS_CHECKS
m_PendingBeginSend = new NativeArray(JobsUtility.MaxJobThreadCount * JobsUtility.CacheLineSize/4, Allocator.Persistent);
#endif
- m_updateTime = m_NetworkParams.config.fixedFrameTimeMS > 0 ? 1 : Stopwatch.GetTimestamp() / TimeSpan.TicksPerMillisecond;
+ var time = Stopwatch.GetTimestamp() / TimeSpan.TicksPerMillisecond;
+ m_updateTime = m_NetworkParams.config.fixedFrameTimeMS > 0 ? 1 : time;
m_updateTimeAdjustment = 0;
int initialStreamSize = m_NetworkParams.dataStream.size;
if (initialStreamSize == 0)
@@ -545,20 +554,16 @@ public NetworkDriver(INetworkInterface netIf, params INetworkParameter[] param)
m_FreeList = new NativeQueue(Allocator.Persistent);
m_EventQueue = new NetworkEventQueue(NetworkParameterConstants.InitialEventQueueSize);
- var idx = 0;
- var reasons = Enum.GetValues(typeof(DisconnectReason));
- m_DisconnectReasons = new NativeArray(reasons.Length, Allocator.Persistent);
- foreach (var reason in reasons)
- {
- m_DisconnectReasons[idx++] = (byte) reason;
- }
+ const int reasons = (int)DisconnectReason.Count;
+ m_DisconnectReasons = new NativeArray(reasons, Allocator.Persistent);
+ for (var idx = 0; idx < reasons; ++idx)
+ m_DisconnectReasons[idx] = (byte)idx;
m_InternalState = new NativeArray(2, Allocator.Persistent);
m_PendingFree = new NativeQueue(Allocator.Persistent);
m_ReceiveCount = new NativeArray(1, Allocator.Persistent);
- m_SessionIdCounter = new NativeArray(1, Allocator.Persistent);
- m_SessionIdCounter[0] = (ushort)(new Random().Next() & 0xFFFF);
+ m_SessionIdCounter = new NativeArray(1, Allocator.Persistent) {[0] = RandomHelpers.GetRandomUShort()};
m_ErrorCodes = new NativeArray((int)ErrorCodeType.NumErrorCodes, Allocator.Persistent);
ReceiveCount = 0;
Listening = false;
@@ -702,7 +707,7 @@ void InternalUpdate()
if (updateCount > (m_ConnectionList.Length - m_FreeList.Count) * 64)
{
UnityEngine.Debug.LogWarning(
- $"A lot of pipeline updates have been queued, possibly too many being scheduled in pipeline logic, queue count: {updateCount}");
+ FixedString.Format("A lot of pipeline updates have been queued, possibly too many being scheduled in pipeline logic, queue count: {0}", updateCount));
}
m_DefaultHeaderFlags = UdpCHeader.HeaderFlags.HasPipeline;
@@ -710,7 +715,7 @@ void InternalUpdate()
if (updateCount > (m_ConnectionList.Length - m_FreeList.Count) * 64)
{
UnityEngine.Debug.LogWarning(
- $"A lot of pipeline updates have been queued, possibly too many being scheduled in pipeline logic, queue count: {updateCount}");
+ FixedString.Format("A lot of pipeline updates have been queued, possibly too many being scheduled in pipeline logic, queue count: {0}", updateCount));
}
m_DefaultHeaderFlags = 0;
@@ -985,11 +990,18 @@ public void AbortSend(DataStreamWriter writer)
/// Returns the type of event received, if the value is a event
/// then the DataStreamReader will contain the disconnect reason.
public NetworkEvent.Type PopEvent(out NetworkConnection con, out DataStreamReader reader)
+ {
+ return PopEvent(out con, out reader, out var _);
+ }
+
+ public NetworkEvent.Type PopEvent(out NetworkConnection con, out DataStreamReader reader, out NetworkPipeline pipeline)
{
int offset, size;
reader = default(DataStreamReader);
int id;
- var type = m_EventQueue.PopEvent(out id, out offset, out size);
+ var type = m_EventQueue.PopEvent(out id, out offset, out size, out var pipelineId);
+ pipeline = new NetworkPipeline { Id = pipelineId };
+
if (type == NetworkEvent.Type.Disconnect && offset < 0)
reader = new DataStreamReader(((NativeArray)m_DisconnectReasons).GetSubArray(math.abs(offset), 1));
else if (size > 0)
@@ -1009,13 +1021,21 @@ public NetworkEvent.Type PopEvent(out NetworkConnection con, out DataStreamReade
/// Returns the type of event received, if the value is a event
/// then the DataStreamReader will contain the disconnect reason.
public NetworkEvent.Type PopEventForConnection(NetworkConnection connectionId, out DataStreamReader reader)
+ {
+ return PopEventForConnection(connectionId, out reader, out var _);
+ }
+
+ public NetworkEvent.Type PopEventForConnection(NetworkConnection connectionId, out DataStreamReader reader, out NetworkPipeline pipeline)
{
int offset, size;
reader = default(DataStreamReader);
+ pipeline = default(NetworkPipeline);
+
if (connectionId.m_NetworkId < 0 || connectionId.m_NetworkId >= m_ConnectionList.Length ||
- m_ConnectionList[connectionId.m_NetworkId].Version != connectionId.m_NetworkVersion)
+ m_ConnectionList[connectionId.m_NetworkId].Version != connectionId.m_NetworkVersion)
return (int) NetworkEvent.Type.Empty;
- var type = m_EventQueue.PopEventForConnection(connectionId.m_NetworkId, out offset, out size);
+ var type = m_EventQueue.PopEventForConnection(connectionId.m_NetworkId, out offset, out size, out var pipelineId);
+ pipeline = new NetworkPipeline { Id = pipelineId };
if (type == NetworkEvent.Type.Disconnect && offset < 0)
reader = new DataStreamReader(((NativeArray)m_DisconnectReasons).GetSubArray(math.abs(offset), 1));
@@ -1200,7 +1220,7 @@ internal set
{
if (value != 0)
{
- UnityEngine.Debug.LogError($"Error on receive, errorCode = {value}");
+ UnityEngine.Debug.LogError(FixedString.Format("Error on receive, errorCode = {0}", value));
}
m_ErrorCodes[(int)ErrorCodeType.ReceiveError] = value;
}
@@ -1407,7 +1427,7 @@ internal int AppendPacket(NetworkInterfaceEndPoint address, UdpCHeader header, i
}
// Interface for receiving data from a pipeline
- internal unsafe void PushDataEvent(NetworkConnection con, byte* dataPtr, int dataLength)
+ internal unsafe void PushDataEvent(NetworkConnection con, int pipelineId, byte* dataPtr, int dataLength)
{
byte* streamBasePtr = (byte*)m_DataStream.GetUnsafePtr();
int sliceOffset = 0;
@@ -1434,6 +1454,7 @@ internal unsafe void PushDataEvent(NetworkConnection con, byte* dataPtr, int dat
m_EventQueue.PushEvent(new NetworkEvent
{
+ pipelineId = (short)pipelineId,
connectionId = con.m_NetworkId,
type = NetworkEvent.Type.Data,
offset = sliceOffset,
diff --git a/Runtime/NetworkEndPoint.cs b/Runtime/NetworkEndPoint.cs
index 1b5f865..f71107a 100644
--- a/Runtime/NetworkEndPoint.cs
+++ b/Runtime/NetworkEndPoint.cs
@@ -26,7 +26,7 @@ enum AddressType { Any = 0, Loopback = 1 }
private const int rawIpv4Length = 4;
private const int rawIpv6Length = 16;
private const int rawDataLength = 16; // Maximum space needed to hold a IPv6 Address
- private const int rawLength = rawDataLength + 3; // SizeOf
+ private const int rawLength = rawDataLength + 4; // SizeOf
private static readonly bool IsLittleEndian = true;
internal Binding.Baselib_NetworkAddress rawNetworkAddress;
@@ -131,8 +131,9 @@ public static bool TryParse(string address, ushort port, out NetworkEndPoint end
UnsafeUtility.SizeOf();
endpoint = default(NetworkEndPoint);
+ var nullTerminator = '\0';
var errorState = default(ErrorState);
- var ipBytes = System.Text.Encoding.UTF8.GetBytes(address + char.MinValue);
+ var ipBytes = System.Text.Encoding.UTF8.GetBytes(address + nullTerminator);
fixed (byte* ipBytesPtr = ipBytes)
fixed (Binding.Baselib_NetworkAddress* rawAddress = &endpoint.rawNetworkAddress)
@@ -244,6 +245,9 @@ private static uint ByteSwap(uint val)
static NetworkEndPoint CreateAddress(ushort port, AddressType type = AddressType.Any, NetworkFamily family = NetworkFamily.Ipv4)
{
+#if ENABLE_UNITY_COLLECTIONS_CHECKS
+ UnityEngine.Debug.Assert(UnsafeUtility.SizeOf() == rawLength);
+#endif
if (family == NetworkFamily.Invalid)
return default;
diff --git a/Runtime/NetworkEventQueue.cs b/Runtime/NetworkEventQueue.cs
index d28ba42..b984e65 100644
--- a/Runtime/NetworkEventQueue.cs
+++ b/Runtime/NetworkEventQueue.cs
@@ -12,19 +12,21 @@ public struct NetworkEvent
///
/// NetworkEvent.Type enumerates available network events for this driver.
///
- public enum Type : int
+ public enum Type : short
{
Empty = 0,
Data,
Connect,
Disconnect
}
+
[FieldOffset(0)] public Type type;
+ [FieldOffset(2)] public short pipelineId;
[FieldOffset(4)] public int connectionId;
- [FieldOffset(8)] public int status;
+ [FieldOffset(8)] public int status;
- [FieldOffset(8)] public int offset;
+ [FieldOffset(8)] public int offset;
[FieldOffset(12)] public int size;
}
@@ -53,10 +55,16 @@ public void Dispose()
// The returned stream is valid until PopEvent is called again or until the main driver updates
public NetworkEvent.Type PopEvent(out int id, out int offset, out int size)
+ {
+ return PopEvent(out id, out offset, out size, out var _);
+ }
+
+ public NetworkEvent.Type PopEvent(out int id, out int offset, out int size, out int pipelineId)
{
offset = 0;
size = 0;
id = -1;
+ pipelineId = 0;
while (true)
{
@@ -69,15 +77,21 @@ public NetworkEvent.Type PopEvent(out int id, out int offset, out int size)
if (m_ConnectionEventHeadTail[ev.connection * 2] == ev.idx)
{
id = ev.connection;
- return PopEventForConnection(ev.connection, out offset, out size);
+ return PopEventForConnection(ev.connection, out offset, out size, out pipelineId);
}
}
}
public NetworkEvent.Type PopEventForConnection(int connectionId, out int offset, out int size)
+ {
+ return PopEventForConnection(connectionId, out offset, out size, out var _);
+ }
+
+ public NetworkEvent.Type PopEventForConnection(int connectionId, out int offset, out int size, out int pipelineId)
{
offset = 0;
size = 0;
+ pipelineId = 0;
if (connectionId < 0 || connectionId >= m_ConnectionEventHeadTail.Length / 2)
return NetworkEvent.Type.Empty;
@@ -89,6 +103,8 @@ public NetworkEvent.Type PopEventForConnection(int connectionId, out int offset,
m_ConnectionEventHeadTail[connectionId * 2] = idx + 1;
NetworkEvent ev = m_ConnectionEventQ[connectionId * MaxEvents + idx];
+ pipelineId = ev.pipelineId;
+
if (ev.type == NetworkEvent.Type.Data)
{
offset = ev.offset;
@@ -222,14 +238,22 @@ private int MaxEvents {
}
public NetworkEvent.Type PopEventForConnection(int connectionId, out int offset, out int size)
+ {
+ return PopEventForConnection(connectionId, out offset, out size, out var _);
+ }
+
+ public NetworkEvent.Type PopEventForConnection(int connectionId, out int offset, out int size, out int pipelineId)
{
offset = 0;
size = 0;
+ pipelineId = 0;
int idx = m_ConnectionEventHeadTail.Dequeue(connectionId);
if (idx < 0)
return NetworkEvent.Type.Empty;
NetworkEvent ev = m_ConnectionEventQ[connectionId * MaxEvents + idx];
+ pipelineId = ev.pipelineId;
+
if (ev.type == NetworkEvent.Type.Data)
{
offset = ev.offset;
@@ -247,4 +271,4 @@ public NetworkEvent.Type PopEventForConnection(int connectionId, out int offset,
internal ConcurrentConnectionQueue m_ConnectionEventHeadTail;
}
}
-}
\ No newline at end of file
+}
diff --git a/Runtime/NetworkPipeline.cs b/Runtime/NetworkPipeline.cs
index 09d9a4e..4252018 100644
--- a/Runtime/NetworkPipeline.cs
+++ b/Runtime/NetworkPipeline.cs
@@ -448,7 +448,7 @@ internal unsafe int ProcessPipelineSend(NetworkDriver.Concurrent driver, int sta
sendHandle.size = sendSize;
if ((retval = driver.CompleteSend(connection, sendHandle)) < 0)
{
- UnityEngine.Debug.LogWarning($"CompleteSend failed with the following error code: {retval}");
+ UnityEngine.Debug.LogWarning(FixedString.Format("CompleteSend failed with the following error code: {0}", retval));
}
sendHandle = default;
}
@@ -466,7 +466,7 @@ internal unsafe int ProcessPipelineSend(NetworkDriver.Concurrent driver, int sta
{
if ((retval = driver.EndSend(writer)) <= 0)
{
- UnityEngine.Debug.Log($"An error occured during EndSend. ErrorCode: {retval}");
+ UnityEngine.Debug.Log(FixedString.Format("An error occurred during EndSend. ErrorCode: {0}", retval));
}
}
}
@@ -691,7 +691,7 @@ public NetworkPipeline CreatePipeline(params Type[] stages)
throw new InvalidOperationException("Trying to create pipeline with invalid stage " + stages[i]);
#endif
m_StageList.Add(stageId);
- m_AccumulatedHeaderCapacity.Add(0); // Allocate an entry. We will assign its value in the loop below.
+ m_AccumulatedHeaderCapacity.Add(headerCap); // For every stage, compute how much header space has already bee used by other stages when sending
// Make sure all data buffers are aligned
receiveCap += (m_StageCollection[stageId].ReceiveCapacity + AlignmentMinusOne) & (~AlignmentMinusOne);
sendCap += (m_StageCollection[stageId].SendCapacity + AlignmentMinusOne) & (~AlignmentMinusOne);
@@ -703,15 +703,6 @@ public NetworkPipeline CreatePipeline(params Type[] stages)
}
}
- // For every stage, compute how much header space is used by subsequent stages
- int accumulatedHeaderCap = 0;
- for (int i = stages.Length - 1; i >= 0; i--)
- {
- var stageId = NetworkPipelineStageCollection.GetStageId(stages[i]).Index;
- m_AccumulatedHeaderCapacity[pipeline.FirstStageIndex + i] = accumulatedHeaderCap;
- accumulatedHeaderCap += m_StageCollection[stageId].HeaderCapacity;
- }
-
pipeline.receiveBufferOffset = sizePerConnection[RecveiveSizeOffset];
sizePerConnection[RecveiveSizeOffset] = sizePerConnection[RecveiveSizeOffset] + receiveCap;
@@ -816,7 +807,7 @@ internal unsafe void UpdateSend(NetworkDriver.Concurrent driver, out int updateC
var result = ToConcurrent().ProcessPipelineSend(driver, updateItem.stage, updateItem.pipeline, updateItem.connection, default, 0, currentUpdates);
if (result < 0)
{
- UnityEngine.Debug.LogWarning($"ProcessPiplineSend failed with the following error code {result}.");
+ UnityEngine.Debug.LogWarning(FixedString.Format("ProcessPipelineSend failed with the following error code {0}.", result));
}
}
for (int i = 0; i < currentUpdates.Length; ++i)
@@ -863,6 +854,11 @@ public void UpdateReceive(NetworkDriver driver, out int updateCount)
public unsafe void Receive(NetworkDriver driver, NetworkConnection connection, NativeArray buffer)
{
byte pipelineId = buffer[0];
+ if (pipelineId == 0 || pipelineId > m_Pipelines.Length)
+ {
+ UnityEngine.Debug.LogError("Received a packet with an invalid pipeline.");
+ return;
+ }
var p = m_Pipelines[pipelineId-1];
int startStage = p.NumStages - 1;
@@ -938,7 +934,7 @@ private unsafe void ProcessReceiveStagesFrom(NetworkDriver driver, int startStag
}
if (inboundBuffer.bufferLength != 0)
- driver.PushDataEvent(connection, inboundBuffer.buffer, inboundBuffer.bufferLength);
+ driver.PushDataEvent(connection, pipeline.Id, inboundBuffer.buffer, inboundBuffer.bufferLength);
if (resumeQStart >= resumeQ.Length)
{
diff --git a/Runtime/Pipelines/FragmentationPipelineStage.cs b/Runtime/Pipelines/FragmentationPipelineStage.cs
index 76366a8..63e06a7 100644
--- a/Runtime/Pipelines/FragmentationPipelineStage.cs
+++ b/Runtime/Pipelines/FragmentationPipelineStage.cs
@@ -32,7 +32,7 @@ enum FragFlags
#else
const int FragHeaderCapacity = 2; // 2 bits for First/Last flags, 14 bits sequence number
#endif
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests)
{
@@ -44,7 +44,8 @@ private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer in
int headerCapacity = ctx.header.Capacity;
var systemHeaderCapacity = sizeof(UdpCHeader) + 1 + 2; // Extra byte is for pipeline id, two bytes for footer
- var maxBlockLength = NetworkParameterConstants.MTU - systemHeaderCapacity - headerCapacity - ctx.accumulatedHeaderCapacity;
+ var maxBlockLength = NetworkParameterConstants.MTU - systemHeaderCapacity - inboundBuffer.headerPadding;
+ var maxBlockLengthFirstPacket = maxBlockLength - ctx.accumulatedHeaderCapacity; // The first packet has the headers for all pipeline stages before this one
if (fragContext->endIndex > fragContext->startIndex)
{
@@ -66,11 +67,11 @@ private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer in
inboundBuffer.bufferWithHeadersLength = blockLength + inboundBuffer.headerPadding;
fragContext->startIndex += blockLength;
}
- else if (inboundBuffer.bufferWithHeadersLength > maxBlockLength)
+ else if (inboundBuffer.bufferLength > maxBlockLengthFirstPacket)
{
var payloadCapacity = param->PayloadCapacity;
- var excessLength = inboundBuffer.bufferLength - maxBlockLength;
- var excessStart = inboundBuffer.buffer + maxBlockLength;
+ var excessLength = inboundBuffer.bufferLength - maxBlockLengthFirstPacket;
+ var excessStart = inboundBuffer.buffer + maxBlockLengthFirstPacket;
if (excessLength + inboundBuffer.headerPadding > payloadCapacity)
{
throw new InvalidOperationException($"Fragmentation capacity exceeded. Capacity:{payloadCapacity} Payload:{excessLength + inboundBuffer.headerPadding}");
@@ -106,7 +107,7 @@ private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer in
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests)
{
@@ -177,7 +178,7 @@ private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffe
fragContext->sequence = (foundSequence + 1) & (int)FragFlags.SeqMask;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
diff --git a/Runtime/Pipelines/NullPipelineStage.cs b/Runtime/Pipelines/NullPipelineStage.cs
index c22fe7d..6e08d8a 100644
--- a/Runtime/Pipelines/NullPipelineStage.cs
+++ b/Runtime/Pipelines/NullPipelineStage.cs
@@ -6,20 +6,20 @@ namespace Unity.Networking.Transport
[BurstCompile]
public unsafe struct NullPipelineStage : INetworkPipelineStage
{
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests)
{
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests)
{
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
diff --git a/Runtime/Pipelines/ReliableSequencedPipelineStage.cs b/Runtime/Pipelines/ReliableSequencedPipelineStage.cs
index 56b4e30..310eb42 100644
--- a/Runtime/Pipelines/ReliableSequencedPipelineStage.cs
+++ b/Runtime/Pipelines/ReliableSequencedPipelineStage.cs
@@ -38,7 +38,7 @@ public NetworkPipelineStage StaticInitialize(byte* staticInstanceBuffer, int sta
}
public int StaticSize => UnsafeUtility.SizeOf();
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests)
{
@@ -105,7 +105,7 @@ private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffe
inboundBuffer = slice;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests)
{
@@ -169,7 +169,7 @@ private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer in
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
diff --git a/Runtime/Pipelines/ReliableUtility.cs b/Runtime/Pipelines/ReliableUtility.cs
index 8cc18c1..7aa20e6 100644
--- a/Runtime/Pipelines/ReliableUtility.cs
+++ b/Runtime/Pipelines/ReliableUtility.cs
@@ -2,7 +2,8 @@
using System.Runtime.InteropServices;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
-
+using Unity.Mathematics;
+
namespace Unity.Networking.Transport.Utilities
{
public struct SequenceBufferContext
@@ -587,7 +588,7 @@ public static unsafe void StoreReceiveTimestamp(byte* sharedBuffer, ushort seque
rttInfo.LastRtt = (int)Math.Max(timerData->ReceiveTime - timerData->SentTime - timerData->ProcessingTime, 1);
var delta = rttInfo.LastRtt - rttInfo.SmoothedRtt;
rttInfo.SmoothedRtt += delta / 8;
- rttInfo.SmoothedVariance += (Math.Abs(delta) - rttInfo.SmoothedVariance) / 4;
+ rttInfo.SmoothedVariance += (math.abs(delta) - rttInfo.SmoothedVariance) / 4;
rttInfo.ResendTimeout = (int)(rttInfo.SmoothedRtt + 4 * rttInfo.SmoothedVariance);
sharedCtx->RttInfo = rttInfo;
}
diff --git a/Runtime/Pipelines/SimulatorPipelineStage.cs b/Runtime/Pipelines/SimulatorPipelineStage.cs
index fbd3418..6d837ba 100644
--- a/Runtime/Pipelines/SimulatorPipelineStage.cs
+++ b/Runtime/Pipelines/SimulatorPipelineStage.cs
@@ -34,7 +34,7 @@ public NetworkPipelineStage StaticInitialize(byte* staticInstanceBuffer, int sta
);
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
@@ -49,14 +49,14 @@ private static void InitializeConnection(byte* staticInstanceBuffer, int staticI
}
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests)
{
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests)
{
@@ -139,7 +139,7 @@ public NetworkPipelineStage StaticInitialize(byte* staticInstanceBuffer, int sta
);
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
@@ -154,7 +154,7 @@ private static void InitializeConnection(byte* staticInstanceBuffer, int staticI
}
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests)
{
@@ -203,7 +203,7 @@ private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer in
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer,
ref NetworkPipelineStage.Requests requests)
diff --git a/Runtime/Pipelines/UnreliableSequencedPipelineStage.cs b/Runtime/Pipelines/UnreliableSequencedPipelineStage.cs
index 1ebad6a..ce55bde 100644
--- a/Runtime/Pipelines/UnreliableSequencedPipelineStage.cs
+++ b/Runtime/Pipelines/UnreliableSequencedPipelineStage.cs
@@ -26,7 +26,7 @@ public NetworkPipelineStage StaticInitialize(byte* staticInstanceBuffer, int sta
}
public int StaticSize => 0;
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests)
{
@@ -49,7 +49,7 @@ private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffe
inboundBuffer = default;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests)
{
@@ -59,7 +59,7 @@ private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer in
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
diff --git a/Runtime/Utilities.cs b/Runtime/Utilities.cs
index 06f2280..9861945 100644
--- a/Runtime/Utilities.cs
+++ b/Runtime/Utilities.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics;
using Unity.Collections;
namespace Unity.Networking.Transport.Utilities
@@ -8,7 +9,7 @@ namespace Unity.Networking.Transport.Utilities
/// Each bucket has its own first and last item and each bucket can have
/// items pushed and popped individually.
///
- public struct NativeMultiQueue : IDisposable where T : struct
+ public struct NativeMultiQueue : IDisposable where T : unmanaged
{
private NativeList m_Queue;
private NativeList m_QueueHeadTail;
@@ -182,16 +183,26 @@ public static string BitMaskToString(uint mask)
// |-------+-------+-------+--------|
// 00000000000000000000000000000000
- var bits = sizeof(uint) * 8;
- var sb = new System.Text.StringBuilder(new string('*', bits));
+ const int bits = 4 * 8;
+ var sb = new char[bits];
- for (int i = bits - 1; i >= 0; i--)
+ for (var i = bits - 1; i >= 0; i--)
{
sb[i] = (mask & 1) != 0 ? '1' : '0';
mask >>= 1;
}
- return sb.ToString();
+ return new string(sb);
+ }
+ }
+
+ public static class RandomHelpers
+ {
+ // returns ushort in [1..ushort.MaxValue - 1] range
+ public static ushort GetRandomUShort()
+ {
+ var rnd = new Unity.Mathematics.Random((uint) Stopwatch.GetTimestamp());
+ return (ushort)rnd.NextUInt(1, 0xffff);
}
}
}
\ No newline at end of file
diff --git a/Tests/Editor/DataStreamTests.cs b/Tests/Editor/DataStreamTests.cs
index 55c9bf5..cac094e 100644
--- a/Tests/Editor/DataStreamTests.cs
+++ b/Tests/Editor/DataStreamTests.cs
@@ -1,6 +1,8 @@
using System;
using NUnit.Framework;
using Unity.Collections;
+using UnityEngine.TestTools;
+using UnityEngine;
// using FsCheck;
@@ -27,7 +29,8 @@ public void CreateStreamWithPartOfSourceByteArray()
Assert.AreEqual(byteArray[i], reader.ReadByte());
}
- Assert.Throws(() => { reader.ReadByte(); });
+ LogAssert.Expect(LogType.Error, "Trying to read 1 bytes from a stream where only 0 are available");
+ Assert.AreEqual(0, reader.ReadByte());
}
[Test]
diff --git a/Tests/Editor/FragmentationPipelineTests.cs b/Tests/Editor/FragmentationPipelineTests.cs
index 01d51c2..dfd0030 100644
--- a/Tests/Editor/FragmentationPipelineTests.cs
+++ b/Tests/Editor/FragmentationPipelineTests.cs
@@ -30,7 +30,7 @@ public NetworkPipelineStage StaticInitialize(byte* staticInstanceBuffer, int sta
}
public int StaticSize => 2;
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -43,14 +43,14 @@ private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffe
*ctx.staticInstanceBuffer += 1;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
@@ -87,7 +87,7 @@ public void IPC_Setup()
new NetworkDataStreamParameter {size = 0},
timeoutParam,
new ReliableUtility.Parameters { WindowSize = 32 },
- new FragmentationUtility.Parameters { PayloadCapacity = 16 * 1024 });
+ new FragmentationUtility.Parameters { PayloadCapacity = 4 * 1024 });
m_ServerDriver.Bind(NetworkEndPoint.LoopbackIpv4);
m_ServerDriver.Listen();
m_ClientDriver =
@@ -96,7 +96,7 @@ public void IPC_Setup()
timeoutParam,
new ReliableUtility.Parameters { WindowSize = 32 },
new SimulatorUtility.Parameters { MaxPacketCount = 30, MaxPacketSize = 16, PacketDelayMs = 0, /*PacketDropInterval = 8,*/ PacketDropPercentage = 10},
- new FragmentationUtility.Parameters { PayloadCapacity = 16 * 1024 });
+ new FragmentationUtility.Parameters { PayloadCapacity = 4 * 1024 });
}
[TearDown]
@@ -181,6 +181,47 @@ public void NetworkPipeline_Fragmentation_SendRecvOversized()
Assert.AreEqual(i, readStrm.ReadInt());
}
}
+ [Test]
+ public void NetworkPipeline_Fragmentation_SendRecvMaxSize()
+ {
+ var clientPipe = m_ClientDriver.CreatePipeline(typeof(FragmentationPipelineStage));
+ var serverPipe = m_ServerDriver.CreatePipeline(typeof(FragmentationPipelineStage));
+
+ // Connect to server
+ var clientToServer = m_ClientDriver.Connect(m_ServerDriver.LocalEndPoint());
+ Assert.AreNotEqual(default(NetworkConnection), clientToServer);
+ m_ClientDriver.ScheduleUpdate().Complete();
+
+ // Handle incoming connection from client
+ m_ServerDriver.ScheduleUpdate().Complete();
+ var serverToClient = m_ServerDriver.Accept();
+ Assert.AreNotEqual(default(NetworkConnection), serverToClient);
+
+ int messageSize = 4*1024-m_ServerDriver.MaxHeaderSize(serverPipe);
+
+ // Send message to client
+ if (m_ServerDriver.BeginSend(serverPipe, serverToClient, out var strm, messageSize) == 0)
+ {
+ for (int i = 0; i < messageSize; ++i)
+ {
+ strm.WriteByte((byte)i);
+ }
+ m_ServerDriver.EndSend(strm);
+ }
+ m_ServerDriver.ScheduleUpdate().Complete();
+
+ // Receive incoming message from server
+ m_ClientDriver.ScheduleUpdate().Complete();
+ DataStreamReader readStrm;
+ Assert.AreEqual(NetworkEvent.Type.Connect, clientToServer.PopEvent(m_ClientDriver, out readStrm));
+ Assert.AreEqual(NetworkEvent.Type.Data, clientToServer.PopEvent(m_ClientDriver, out readStrm));
+
+ Assert.AreEqual(messageSize, readStrm.Length);
+ for (int i = 0; i < messageSize; ++i)
+ {
+ Assert.AreEqual((byte)i, readStrm.ReadByte());
+ }
+ }
[Test]
public unsafe void NetworkPipeline_Fragmentation_DroppedPacket()
@@ -254,5 +295,92 @@ public unsafe void NetworkPipeline_Fragmentation_DroppedPacket()
}
}
}
+ [Test]
+ public void NetworkPipeline_Fragmentation_Unreliable_SendRecv1380_Plus()
+ {
+ var clientPipe = m_ClientDriver.CreatePipeline(typeof(FragmentationPipelineStage), typeof(UnreliableSequencedPipelineStage));
+ var serverPipe = m_ServerDriver.CreatePipeline(typeof(FragmentationPipelineStage), typeof(UnreliableSequencedPipelineStage));
+
+ // Connect to server
+ var clientToServer = m_ClientDriver.Connect(m_ServerDriver.LocalEndPoint());
+ Assert.AreNotEqual(default(NetworkConnection), clientToServer);
+ m_ClientDriver.ScheduleUpdate().Complete();
+
+ // Handle incoming connection from client
+ m_ServerDriver.ScheduleUpdate().Complete();
+ var serverToClient = m_ServerDriver.Accept();
+ Assert.AreNotEqual(default(NetworkConnection), serverToClient);
+
+ m_ClientDriver.ScheduleUpdate().Complete();
+ DataStreamReader readStrm;
+ Assert.AreEqual(NetworkEvent.Type.Connect, clientToServer.PopEvent(m_ClientDriver, out readStrm));
+ for (int messageSize = 1380; messageSize <= 1400; ++messageSize)
+ {
+ // Send message to client
+ if (m_ServerDriver.BeginSend(serverPipe, serverToClient, out var strm, messageSize) == 0)
+ {
+ for (int i = 0; i < messageSize; ++i)
+ {
+ strm.WriteByte((byte)i);
+ }
+ m_ServerDriver.EndSend(strm);
+ }
+ m_ServerDriver.ScheduleUpdate().Complete();
+
+ // Receive incoming message from server
+ m_ClientDriver.ScheduleUpdate().Complete();
+ Assert.AreEqual(NetworkEvent.Type.Data, clientToServer.PopEvent(m_ClientDriver, out readStrm));
+
+ Assert.AreEqual(messageSize, readStrm.Length);
+ for (int i = 0; i < messageSize; ++i)
+ {
+ Assert.AreEqual((byte)i, readStrm.ReadByte());
+ }
+ }
+ }
+ [Test]
+ public void NetworkPipeline_Unreliable_Fragmentation_SendRecv1380_Plus()
+ {
+ var clientPipe = m_ClientDriver.CreatePipeline(typeof(UnreliableSequencedPipelineStage), typeof(FragmentationPipelineStage));
+ var serverPipe = m_ServerDriver.CreatePipeline(typeof(UnreliableSequencedPipelineStage), typeof(FragmentationPipelineStage));
+
+ // Connect to server
+ var clientToServer = m_ClientDriver.Connect(m_ServerDriver.LocalEndPoint());
+ Assert.AreNotEqual(default(NetworkConnection), clientToServer);
+ m_ClientDriver.ScheduleUpdate().Complete();
+
+ // Handle incoming connection from client
+ m_ServerDriver.ScheduleUpdate().Complete();
+ var serverToClient = m_ServerDriver.Accept();
+ Assert.AreNotEqual(default(NetworkConnection), serverToClient);
+
+ m_ClientDriver.ScheduleUpdate().Complete();
+ DataStreamReader readStrm;
+ Assert.AreEqual(NetworkEvent.Type.Connect, clientToServer.PopEvent(m_ClientDriver, out readStrm));
+
+ for (int messageSize = 1380; messageSize <= 1400; ++messageSize)
+ {
+ // Send message to client
+ if (m_ServerDriver.BeginSend(serverPipe, serverToClient, out var strm, messageSize) == 0)
+ {
+ for (int i = 0; i < messageSize; ++i)
+ {
+ strm.WriteByte((byte)i);
+ }
+ m_ServerDriver.EndSend(strm);
+ }
+ m_ServerDriver.ScheduleUpdate().Complete();
+
+ // Receive incoming message from server
+ m_ClientDriver.ScheduleUpdate().Complete();
+ Assert.AreEqual(NetworkEvent.Type.Data, clientToServer.PopEvent(m_ClientDriver, out readStrm));
+
+ Assert.AreEqual(messageSize, readStrm.Length);
+ for (int i = 0; i < messageSize; ++i)
+ {
+ Assert.AreEqual((byte)i, readStrm.ReadByte());
+ }
+ }
+ }
}
}
diff --git a/Tests/Editor/NetworkPipelineTest.cs b/Tests/Editor/NetworkPipelineTest.cs
index e34f5bb..9398173 100644
--- a/Tests/Editor/NetworkPipelineTest.cs
+++ b/Tests/Editor/NetworkPipelineTest.cs
@@ -27,7 +27,7 @@ public NetworkPipelineStage StaticInitialize(byte* staticInstanceBuffer, int sta
}
public int StaticSize => 0;
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -37,7 +37,7 @@ private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffe
inboundBuffer = inboundBuffer.Slice(4);
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -45,7 +45,7 @@ private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer in
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
@@ -74,7 +74,7 @@ public NetworkPipelineStage StaticInitialize(byte* staticInstanceBuffer, int sta
}
public int StaticSize => 0;
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -85,7 +85,7 @@ private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffe
inboundBuffer = inboundBuffer.Slice(4);
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -93,7 +93,7 @@ private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer in
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
@@ -123,7 +123,7 @@ public NetworkPipelineStage StaticInitialize(byte* staticInstanceBuffer, int sta
}
public int StaticSize => 0;
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -132,7 +132,7 @@ private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffe
inboundBuffer.buffer = ctx.internalProcessBuffer;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -147,7 +147,7 @@ private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer in
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
@@ -175,7 +175,7 @@ public NetworkPipelineStage StaticInitialize(byte* staticInstanceBuffer, int sta
}
public int StaticSize => 0;
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -183,7 +183,7 @@ private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffe
inboundBuffer.buffer[i] = (byte)(inboundBuffer.buffer[i] ^ 0xff);
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -198,7 +198,7 @@ private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer in
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
@@ -226,13 +226,13 @@ public NetworkPipelineStage StaticInitialize(byte* staticInstanceBuffer, int sta
}
public int StaticSize => 0;
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static unsafe int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -247,7 +247,7 @@ private static unsafe int Send(ref NetworkPipelineContext ctx, ref InboundSendBu
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
@@ -276,7 +276,7 @@ public NetworkPipelineStage StaticInitialize(byte* staticInstanceBuffer, int sta
}
public int StaticSize => 0;
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -294,7 +294,7 @@ private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffe
}
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -313,7 +313,7 @@ private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer in
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
@@ -360,7 +360,7 @@ public NetworkPipelineStage StaticInitialize(byte* staticInstanceBuffer, int sta
}
public int StaticSize => 0;
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -378,7 +378,7 @@ private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffe
}
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -397,7 +397,7 @@ private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer in
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
diff --git a/Tests/Editor/ReliablePipelineTests.cs b/Tests/Editor/ReliablePipelineTests.cs
index 02bb9de..abd5e8d 100644
--- a/Tests/Editor/ReliablePipelineTests.cs
+++ b/Tests/Editor/ReliablePipelineTests.cs
@@ -32,7 +32,7 @@ public NetworkPipelineStage StaticInitialize(byte* staticInstanceBuffer, int sta
}
public int StaticSize => 1;
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -42,14 +42,14 @@ private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffe
}
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
@@ -80,13 +80,13 @@ public NetworkPipelineStage StaticInitialize(byte* staticInstanceBuffer, int sta
}
public int StaticSize => 1;
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.ReceiveDelegate))]
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.SendDelegate))]
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests request)
{
@@ -97,7 +97,7 @@ private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer in
return (int)Error.StatusCode.Success;
}
- [BurstCompile]
+ [BurstCompile(DisableDirectCall = true)]
[MonoPInvokeCallback(typeof(NetworkPipelineStage.InitializeConnectionDelegate))]
private static void InitializeConnection(byte* staticInstanceBuffer, int staticInstanceBufferLength,
byte* sendProcessBuffer, int sendProcessBufferLength, byte* recvProcessBuffer, int recvProcessBufferLength,
diff --git a/Tests/Editor/Unity.Networking.Transport.EditorTests.asmdef b/Tests/Editor/Unity.Networking.Transport.EditorTests.asmdef
index bf2cf98..00da37b 100644
--- a/Tests/Editor/Unity.Networking.Transport.EditorTests.asmdef
+++ b/Tests/Editor/Unity.Networking.Transport.EditorTests.asmdef
@@ -14,4 +14,4 @@
],
"excludePlatforms": [],
"allowUnsafeCode": true
-}
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index 2e08ba5..af6ded7 100644
--- a/package.json
+++ b/package.json
@@ -1,21 +1,20 @@
{
"name": "com.unity.transport",
"displayName": "Unity Transport",
- "version": "0.6.0-preview.7",
- "unity": "2020.1",
- "unityRelease": "9f1",
+ "version": "0.8.0-preview.8",
+ "unity": "2020.3",
+ "unityRelease": "0f1",
"description": "Unity network transport layer - the low-level interface for sending UDP data",
"dependencies": {
- "com.unity.burst": "1.4.1",
- "com.unity.collections": "0.15.0-preview.21",
+ "com.unity.collections": "0.17.0-preview.18",
"com.unity.mathematics": "1.2.1"
},
"upmCi": {
- "footprint": "1619488fe883cf1780f26686c2e6392d18511acf"
+ "footprint": "f4ac6d1e17d1839c024a0985f5bcc5ca909710df"
},
"repository": {
"url": "https://github.com/Unity-Technologies/netcode.git",
"type": "git",
- "revision": "f5463f493744a4b8b62680e2ed23a5687b8aabfd"
+ "revision": "a2c8b3132fa8d626631512a2006ed68b024a6bf4"
}
}