From 5a6718ebbe3b8bca0b0563cd99ff785f2ddd0ede Mon Sep 17 00:00:00 2001 From: Unity Technologies <@unity.com> Date: Tue, 26 Nov 2019 00:00:00 +0100 Subject: [PATCH] com.unity.transport@0.2.0-preview.4 # Change log ## [0.2.0-preview.4] - 2019-11-26 ### New features ### Changes * Added support for unquantized floats to `DataStream` class. * Added `NetworkConfigParameter.maxFrameTimeMS` so you to allow longer frame times when debugging to prevent disconnections due to timeout. * Allow "1.1.1.1:1234" strings when parsing the IP string in the NetworkEndPoint class, it will use the port part when it's present. * Reliable pipeline now doesn't require parameters passed in (uses default window size of 32) * Added Read/Write of ulong to `DataStream`. * Made it possible to get connection state from the parallel NetworkDriver. * Added `LengthInBits` to the `DataStreamWriter`. ### Fixes * Do not push data events to disconnected connections. Fixes an error about resetting the queue with pending messages * Made the endian checks in `DataStream` compatible with latest version of burst. ### Upgrade guide ## [0.1.2-preview.1] - 2019-07-17 ### New features * Added a new *Ping-Multiplay* sample based on the *Ping* sample * Created to be the main sample for demonstrating Multiplay compatibility and best practices (SQP usage, IP binding, etc.) * Contains both client and server code. Additional details in readme in `/Assets/Samples/Ping-Multiplay/`. * **DedicatedServerConfig**: added arguments for `-fps` and `-timeout` * **NetworkEndPoint**: Added a `TryParse()` method which returns false if parsing fails * Note: The `Parse()` method returns a default IP / Endpoint if parsing fails, but a method that could report failure was needed for the Multiplay sample * **CommandLine**: * Added a `HasArgument()` method which returns true if an argument is present * Added a `PrintArgsToLog()` method which is a simple way to print launch args to logs * Added a `TryUpdateVariableWithArgValue()` method which updates a ref var only if an arg was found and successfully parsed ### Changes * Deleted existing SQP code and added reference to SQP Package (now in staging) * Removed SQP server usage from basic *Ping* sample * Note: The SQP server was only needed for Multiplay compatibility, so the addition of *Ping-Multiplay* allowed us to remove SQP from *Ping* ### Fixes * **DedicatedServerConfig**: Vsync is now disabled programmatically if requesting an FPS different from the current screen refresh rate ### Upgrade guide ## [0.1.1-preview.1] - 2019-06-05 ### New features * Moved MatchMaking to a package and supporting code to a separate folder. ### Fixes * Fixed an issue with the reliable pipeline not resending when completely idle. ### Upgrade guide ## [0.1.0-preview.1] - 2019-04-16 ### New features * Added network pipelines to enable processing of outgoing and incomming packets. The available pipeline stages are `ReliableSequencedPipelineStage` for reliable UDP messages and `SimulatorPipelineStage` for emulating network conditions such as high latency and packet loss. See [the pipeline documentation](com.unity.transport/Documentation~/pipelines-usage.md) for more information. * Added reading and writing of packed signed and unsigned integers to `DataStream`. These new methods use huffman encoding to reduce the size of transfered data for small numbers. ### Changes * Enable Burst compilation for most jobs * Made it possible to get the remote endpoint for a connection * Replacing EndPoint parsing with custom code to avoid having a dependency on System.Net * Change the ping sample command-line parameters for server to -port and -query_port * For matchmaking - use an Assignment object containing the ConnectionString, the Roster, and an AssignmentError string instead of just the ConnectionString. ### Fixes * Fixed an issue with building iOS on Windows * Fixed inconsistent error handling between platforms when the network buffer is full ### Upgrade guide Unity 2019.1 is now required. `BasicNetworkDriver` has been renamed to `GenericNetworkDriver` and a new `UdpNetworkDriver` helper class is also available. System.Net EndPoints can no longer be used as addresses, use the new NetworkEndpoint struct instead. --- CHANGELOG.md | 72 + CHANGELOG.md.meta | 7 + Documentation~/TableOfContents.md | 20 + Documentation~/connection-state-machine.md | 17 + Documentation~/event-consumption.md | 60 + .../images/Pipeline-stages-diagram.png | Bin 0 -> 14518 bytes .../images/com.unity.transport.connection.png | Bin 0 -> 35421 bytes .../images/com.unity.transport.driver.png | Bin 0 -> 36120 bytes Documentation~/images/console-view.PNG | Bin 0 -> 25251 bytes Documentation~/images/game-object.PNG | Bin 0 -> 4973 bytes Documentation~/images/inspector.PNG | Bin 0 -> 24018 bytes Documentation~/images/layercake.png | Bin 0 -> 24612 bytes Documentation~/index.md | 50 + Documentation~/install.md | 13 + Documentation~/pipelines-usage.md | 140 ++ Documentation~/samples/clientbehaviour.cs.md | 73 + .../samples/jobifiedclientbehaviour.cs.md | 99 + .../samples/jobifiedserverbehaviour.cs.md | 120 ++ Documentation~/samples/serverbehaviour.cs.md | 86 + Documentation~/update-flow.md | 20 + Documentation~/workflow-client-server-jobs.md | 423 ++++ Documentation~/workflow-client-server.md | 418 ++++ Editor.meta | 8 + Editor/PipelineCollectionGeneratorWindow.cs | 200 ++ .../PipelineCollectionGeneratorWindow.cs.meta | 11 + .../Unity.Networking.Transport.Editor.asmdef | 9 + ...ty.Networking.Transport.Editor.asmdef.meta | 7 + LICENSE.md | 11 + LICENSE.md.meta | 7 + Runtime.meta | 8 + Runtime/Bindings.meta | 8 + Runtime/Bindings/ios.meta | 8 + Runtime/Bindings/ios/network.bindings.c | 258 +++ Runtime/Bindings/ios/network.bindings.c.meta | 103 + Runtime/Bindings/ios/network.bindings.h | 61 + Runtime/Bindings/ios/network.bindings.h.meta | 103 + Runtime/Bindings/ios/platform.h | 26 + Runtime/Bindings/ios/platform.h.meta | 103 + Runtime/Bindings/network.bindings.bundle | Bin 0 -> 11140 bytes Runtime/Bindings/network.bindings.bundle.meta | 39 + Runtime/Bindings/network.bindings.cs | 118 ++ Runtime/Bindings/network.bindings.cs.meta | 11 + Runtime/Bindings/network.bindings.dll | Bin 0 -> 111616 bytes Runtime/Bindings/network.bindings.dll.meta | 30 + Runtime/Bindings/network.bindings.pdb | Bin 0 -> 3903488 bytes Runtime/Bindings/network.bindings.pdb.meta | 7 + Runtime/DataStream.cs | 1154 +++++++++++ Runtime/DataStream.cs.meta | 11 + Runtime/INetworkDriver.cs | 125 ++ Runtime/INetworkDriver.cs.meta | 11 + Runtime/INetworkInterface.cs | 76 + Runtime/INetworkInterface.cs.meta | 11 + Runtime/IPCManager.cs | 212 ++ Runtime/IPCManager.cs.meta | 11 + Runtime/IPCNetworkDriver.cs | 142 ++ Runtime/IPCNetworkDriver.cs.meta | 11 + Runtime/IPCNetworkInterface.cs | 142 ++ Runtime/IPCNetworkInterface.cs.meta | 11 + Runtime/NetworkCompressionModel.cs | 192 ++ Runtime/NetworkCompressionModel.cs.meta | 11 + Runtime/NetworkConnection.cs | 115 ++ Runtime/NetworkConnection.cs.meta | 11 + Runtime/NetworkDriver.cs | 1180 +++++++++++ Runtime/NetworkDriver.cs.meta | 11 + Runtime/NetworkEndPoint.cs | 210 ++ Runtime/NetworkEndPoint.cs.meta | 11 + Runtime/NetworkEventQueue.cs | 243 +++ Runtime/NetworkEventQueue.cs.meta | 11 + Runtime/NetworkLogger.cs | 124 ++ Runtime/NetworkLogger.cs.meta | 11 + Runtime/NetworkParams.cs | 59 + Runtime/NetworkParams.cs.meta | 11 + Runtime/NetworkPipeline.cs | 718 +++++++ Runtime/NetworkPipeline.cs.meta | 11 + Runtime/NetworkProtocols.cs | 31 + Runtime/NetworkProtocols.cs.meta | 11 + Runtime/Pipelines.meta | 8 + .../DefaultPipelineStageCollection.cs | 237 +++ .../DefaultPipelineStageCollection.cs.meta | 11 + .../ReliableSequencedPipelineStage.cs | 155 ++ .../ReliableSequencedPipelineStage.cs.meta | 11 + Runtime/Pipelines/ReliableUtility.cs | 754 +++++++ Runtime/Pipelines/ReliableUtility.cs.meta | 11 + Runtime/Pipelines/SimulatorPipelineStage.cs | 144 ++ .../Pipelines/SimulatorPipelineStage.cs.meta | 11 + Runtime/Pipelines/SimulatorUtility.cs | 249 +++ Runtime/Pipelines/SimulatorUtility.cs.meta | 11 + .../UnreliableSequencedPipelineStage.cs | 60 + .../UnreliableSequencedPipelineStage.cs.meta | 11 + Runtime/UDPNetworkDriver.cs | 141 ++ Runtime/UDPNetworkDriver.cs.meta | 11 + Runtime/UDPNetworkInterface.cs | 213 ++ Runtime/UDPNetworkInterface.cs.meta | 11 + Runtime/Unity.Networking.Transport.asmdef | 11 + .../Unity.Networking.Transport.asmdef.meta | 7 + Runtime/Utilities.cs | 210 ++ Runtime/Utilities.cs.meta | 11 + Tests.meta | 8 + Tests/Editor.meta | 8 + Tests/Editor/DataStreamTests.cs | 218 +++ Tests/Editor/DataStreamTests.cs.meta | 11 + Tests/Editor/NetworkConnectionUnitTests.cs | 128 ++ .../Editor/NetworkConnectionUnitTests.cs.meta | 11 + Tests/Editor/NetworkDriverFlowTest.cs | 99 + Tests/Editor/NetworkDriverFlowTest.cs.meta | 11 + Tests/Editor/NetworkDriverLoadTest.cs | 0 Tests/Editor/NetworkDriverLoadTest.cs.meta | 11 + Tests/Editor/NetworkDriverUnitTests.cs | 705 +++++++ Tests/Editor/NetworkDriverUnitTests.cs.meta | 11 + Tests/Editor/NetworkEndPointUnitTests.cs | 53 + Tests/Editor/NetworkEndPointUnitTests.cs.meta | 11 + Tests/Editor/NetworkEventQueueTests.cs | 210 ++ Tests/Editor/NetworkEventQueueTests.cs.meta | 11 + Tests/Editor/NetworkHostUnitTests.cs | 68 + Tests/Editor/NetworkHostUnitTests.cs.meta | 11 + Tests/Editor/NetworkJobTests.cs | 333 ++++ Tests/Editor/NetworkJobTests.cs.meta | 11 + Tests/Editor/NetworkParamsTests.cs | 0 Tests/Editor/NetworkParamsTests.cs.meta | 11 + Tests/Editor/NetworkPipelineTest.cs | 971 +++++++++ Tests/Editor/NetworkPipelineTest.cs.meta | 11 + Tests/Editor/NetworkProtocolsTests.cs | 12 + Tests/Editor/NetworkProtocolsTests.cs.meta | 11 + Tests/Editor/ReliablePipelineTests.cs | 1727 +++++++++++++++++ Tests/Editor/ReliablePipelineTests.cs.meta | 11 + ...ty.Networking.Transport.EditorTests.asmdef | 17 + ...tworking.Transport.EditorTests.asmdef.meta | 7 + Tests/Editor/UtilitiesTests.cs | 51 + Tests/Editor/UtilitiesTests.cs.meta | 11 + Tests/Runtime.meta | 8 + Tests/Runtime/ServerAndClientTests.cs | 331 ++++ Tests/Runtime/ServerAndClientTests.cs.meta | 11 + .../Runtime/com.unity.transport.Tests.asmdef | 12 + .../com.unity.transport.Tests.asmdef.meta | 7 + package.json | 18 + package.json.meta | 7 + 136 files changed, 15093 insertions(+) create mode 100644 CHANGELOG.md create mode 100644 CHANGELOG.md.meta create mode 100644 Documentation~/TableOfContents.md create mode 100644 Documentation~/connection-state-machine.md create mode 100644 Documentation~/event-consumption.md create mode 100644 Documentation~/images/Pipeline-stages-diagram.png create mode 100644 Documentation~/images/com.unity.transport.connection.png create mode 100644 Documentation~/images/com.unity.transport.driver.png create mode 100644 Documentation~/images/console-view.PNG create mode 100644 Documentation~/images/game-object.PNG create mode 100644 Documentation~/images/inspector.PNG create mode 100644 Documentation~/images/layercake.png create mode 100644 Documentation~/index.md create mode 100644 Documentation~/install.md create mode 100644 Documentation~/pipelines-usage.md create mode 100644 Documentation~/samples/clientbehaviour.cs.md create mode 100644 Documentation~/samples/jobifiedclientbehaviour.cs.md create mode 100644 Documentation~/samples/jobifiedserverbehaviour.cs.md create mode 100644 Documentation~/samples/serverbehaviour.cs.md create mode 100644 Documentation~/update-flow.md create mode 100644 Documentation~/workflow-client-server-jobs.md create mode 100644 Documentation~/workflow-client-server.md create mode 100644 Editor.meta create mode 100644 Editor/PipelineCollectionGeneratorWindow.cs create mode 100644 Editor/PipelineCollectionGeneratorWindow.cs.meta create mode 100644 Editor/Unity.Networking.Transport.Editor.asmdef create mode 100644 Editor/Unity.Networking.Transport.Editor.asmdef.meta create mode 100644 LICENSE.md create mode 100644 LICENSE.md.meta create mode 100644 Runtime.meta create mode 100644 Runtime/Bindings.meta create mode 100644 Runtime/Bindings/ios.meta create mode 100644 Runtime/Bindings/ios/network.bindings.c create mode 100644 Runtime/Bindings/ios/network.bindings.c.meta create mode 100644 Runtime/Bindings/ios/network.bindings.h create mode 100644 Runtime/Bindings/ios/network.bindings.h.meta create mode 100644 Runtime/Bindings/ios/platform.h create mode 100644 Runtime/Bindings/ios/platform.h.meta create mode 100644 Runtime/Bindings/network.bindings.bundle create mode 100644 Runtime/Bindings/network.bindings.bundle.meta create mode 100644 Runtime/Bindings/network.bindings.cs create mode 100644 Runtime/Bindings/network.bindings.cs.meta create mode 100644 Runtime/Bindings/network.bindings.dll create mode 100644 Runtime/Bindings/network.bindings.dll.meta create mode 100644 Runtime/Bindings/network.bindings.pdb create mode 100644 Runtime/Bindings/network.bindings.pdb.meta create mode 100644 Runtime/DataStream.cs create mode 100644 Runtime/DataStream.cs.meta create mode 100644 Runtime/INetworkDriver.cs create mode 100644 Runtime/INetworkDriver.cs.meta create mode 100644 Runtime/INetworkInterface.cs create mode 100644 Runtime/INetworkInterface.cs.meta create mode 100644 Runtime/IPCManager.cs create mode 100644 Runtime/IPCManager.cs.meta create mode 100644 Runtime/IPCNetworkDriver.cs create mode 100644 Runtime/IPCNetworkDriver.cs.meta create mode 100644 Runtime/IPCNetworkInterface.cs create mode 100644 Runtime/IPCNetworkInterface.cs.meta create mode 100644 Runtime/NetworkCompressionModel.cs create mode 100644 Runtime/NetworkCompressionModel.cs.meta create mode 100644 Runtime/NetworkConnection.cs create mode 100644 Runtime/NetworkConnection.cs.meta create mode 100644 Runtime/NetworkDriver.cs create mode 100644 Runtime/NetworkDriver.cs.meta create mode 100644 Runtime/NetworkEndPoint.cs create mode 100644 Runtime/NetworkEndPoint.cs.meta create mode 100644 Runtime/NetworkEventQueue.cs create mode 100644 Runtime/NetworkEventQueue.cs.meta create mode 100644 Runtime/NetworkLogger.cs create mode 100644 Runtime/NetworkLogger.cs.meta create mode 100644 Runtime/NetworkParams.cs create mode 100644 Runtime/NetworkParams.cs.meta create mode 100644 Runtime/NetworkPipeline.cs create mode 100644 Runtime/NetworkPipeline.cs.meta create mode 100644 Runtime/NetworkProtocols.cs create mode 100644 Runtime/NetworkProtocols.cs.meta create mode 100644 Runtime/Pipelines.meta create mode 100644 Runtime/Pipelines/DefaultPipelineStageCollection.cs create mode 100644 Runtime/Pipelines/DefaultPipelineStageCollection.cs.meta create mode 100644 Runtime/Pipelines/ReliableSequencedPipelineStage.cs create mode 100644 Runtime/Pipelines/ReliableSequencedPipelineStage.cs.meta create mode 100644 Runtime/Pipelines/ReliableUtility.cs create mode 100644 Runtime/Pipelines/ReliableUtility.cs.meta create mode 100644 Runtime/Pipelines/SimulatorPipelineStage.cs create mode 100644 Runtime/Pipelines/SimulatorPipelineStage.cs.meta create mode 100644 Runtime/Pipelines/SimulatorUtility.cs create mode 100644 Runtime/Pipelines/SimulatorUtility.cs.meta create mode 100644 Runtime/Pipelines/UnreliableSequencedPipelineStage.cs create mode 100644 Runtime/Pipelines/UnreliableSequencedPipelineStage.cs.meta create mode 100644 Runtime/UDPNetworkDriver.cs create mode 100644 Runtime/UDPNetworkDriver.cs.meta create mode 100644 Runtime/UDPNetworkInterface.cs create mode 100644 Runtime/UDPNetworkInterface.cs.meta create mode 100644 Runtime/Unity.Networking.Transport.asmdef create mode 100644 Runtime/Unity.Networking.Transport.asmdef.meta create mode 100644 Runtime/Utilities.cs create mode 100644 Runtime/Utilities.cs.meta create mode 100644 Tests.meta create mode 100644 Tests/Editor.meta create mode 100644 Tests/Editor/DataStreamTests.cs create mode 100644 Tests/Editor/DataStreamTests.cs.meta create mode 100644 Tests/Editor/NetworkConnectionUnitTests.cs create mode 100644 Tests/Editor/NetworkConnectionUnitTests.cs.meta create mode 100644 Tests/Editor/NetworkDriverFlowTest.cs create mode 100644 Tests/Editor/NetworkDriverFlowTest.cs.meta create mode 100644 Tests/Editor/NetworkDriverLoadTest.cs create mode 100644 Tests/Editor/NetworkDriverLoadTest.cs.meta create mode 100644 Tests/Editor/NetworkDriverUnitTests.cs create mode 100644 Tests/Editor/NetworkDriverUnitTests.cs.meta create mode 100644 Tests/Editor/NetworkEndPointUnitTests.cs create mode 100644 Tests/Editor/NetworkEndPointUnitTests.cs.meta create mode 100644 Tests/Editor/NetworkEventQueueTests.cs create mode 100644 Tests/Editor/NetworkEventQueueTests.cs.meta create mode 100644 Tests/Editor/NetworkHostUnitTests.cs create mode 100644 Tests/Editor/NetworkHostUnitTests.cs.meta create mode 100644 Tests/Editor/NetworkJobTests.cs create mode 100644 Tests/Editor/NetworkJobTests.cs.meta create mode 100644 Tests/Editor/NetworkParamsTests.cs create mode 100644 Tests/Editor/NetworkParamsTests.cs.meta create mode 100644 Tests/Editor/NetworkPipelineTest.cs create mode 100644 Tests/Editor/NetworkPipelineTest.cs.meta create mode 100644 Tests/Editor/NetworkProtocolsTests.cs create mode 100644 Tests/Editor/NetworkProtocolsTests.cs.meta create mode 100644 Tests/Editor/ReliablePipelineTests.cs create mode 100644 Tests/Editor/ReliablePipelineTests.cs.meta create mode 100644 Tests/Editor/Unity.Networking.Transport.EditorTests.asmdef create mode 100644 Tests/Editor/Unity.Networking.Transport.EditorTests.asmdef.meta create mode 100644 Tests/Editor/UtilitiesTests.cs create mode 100644 Tests/Editor/UtilitiesTests.cs.meta create mode 100644 Tests/Runtime.meta create mode 100644 Tests/Runtime/ServerAndClientTests.cs create mode 100644 Tests/Runtime/ServerAndClientTests.cs.meta create mode 100644 Tests/Runtime/com.unity.transport.Tests.asmdef create mode 100644 Tests/Runtime/com.unity.transport.Tests.asmdef.meta create mode 100644 package.json create mode 100644 package.json.meta diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..ddcaaf0 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,72 @@ +# Change log + +## [0.2.0-preview.4] - 2019-11-26 +### New features +### Changes +* Added support for unquantized floats to `DataStream` class. +* Added `NetworkConfigParameter.maxFrameTimeMS` so you to allow longer frame times when debugging to prevent disconnections due to timeout. +* Allow "1.1.1.1:1234" strings when parsing the IP string in the NetworkEndPoint class, it will use the port part when it's present. +* Reliable pipeline now doesn't require parameters passed in (uses default window size of 32) +* Added Read/Write of ulong to `DataStream`. +* Made it possible to get connection state from the parallel NetworkDriver. +* Added `LengthInBits` to the `DataStreamWriter`. + +### Fixes +* Do not push data events to disconnected connections. Fixes an error about resetting the queue with pending messages +* Made the endian checks in `DataStream` compatible with latest version of burst. +### Upgrade guide + +## [0.1.2-preview.1] - 2019-07-17 +### New features +* Added a new *Ping-Multiplay* sample based on the *Ping* sample + * Created to be the main sample for demonstrating Multiplay compatibility and best practices (SQP usage, IP binding, etc.) + * Contains both client and server code. Additional details in readme in `/Assets/Samples/Ping-Multiplay/`. +* **DedicatedServerConfig**: added arguments for `-fps` and `-timeout` +* **NetworkEndPoint**: Added a `TryParse()` method which returns false if parsing fails + * Note: The `Parse()` method returns a default IP / Endpoint if parsing fails, but a method that could report failure was needed for the Multiplay sample +* **CommandLine**: + * Added a `HasArgument()` method which returns true if an argument is present + * Added a `PrintArgsToLog()` method which is a simple way to print launch args to logs + * Added a `TryUpdateVariableWithArgValue()` method which updates a ref var only if an arg was found and successfully parsed + +### Changes +* Deleted existing SQP code and added reference to SQP Package (now in staging) +* Removed SQP server usage from basic *Ping* sample + * Note: The SQP server was only needed for Multiplay compatibility, so the addition of *Ping-Multiplay* allowed us to remove SQP from *Ping* + +### Fixes +* **DedicatedServerConfig**: Vsync is now disabled programmatically if requesting an FPS different from the current screen refresh rate + +### Upgrade guide + +## [0.1.1-preview.1] - 2019-06-05 +### New features +* Moved MatchMaking to a package and supporting code to a separate folder. + +### Fixes +* Fixed an issue with the reliable pipeline not resending when completely idle. + +### Upgrade guide + +## [0.1.0-preview.1] - 2019-04-16 +### New features +* Added network pipelines to enable processing of outgoing and incomming packets. The available pipeline stages are `ReliableSequencedPipelineStage` for reliable UDP messages and `SimulatorPipelineStage` for emulating network conditions such as high latency and packet loss. See [the pipeline documentation](com.unity.transport/Documentation~/pipelines-usage.md) for more information. +* Added reading and writing of packed signed and unsigned integers to `DataStream`. These new methods use huffman encoding to reduce the size of transfered data for small numbers. + +### Changes +* Enable Burst compilation for most jobs +* Made it possible to get the remote endpoint for a connection +* Replacing EndPoint parsing with custom code to avoid having a dependency on System.Net +* Change the ping sample command-line parameters for server to -port and -query_port +* For matchmaking - use an Assignment object containing the ConnectionString, the Roster, and an AssignmentError string instead of just the ConnectionString. + +### Fixes +* Fixed an issue with building iOS on Windows +* Fixed inconsistent error handling between platforms when the network buffer is full + +### Upgrade guide +Unity 2019.1 is now required. + +`BasicNetworkDriver` has been renamed to `GenericNetworkDriver` and a new `UdpNetworkDriver` helper class is also available. + +System.Net EndPoints can no longer be used as addresses, use the new NetworkEndpoint struct instead. diff --git a/CHANGELOG.md.meta b/CHANGELOG.md.meta new file mode 100644 index 0000000..c3bd80e --- /dev/null +++ b/CHANGELOG.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2f10a9a833f64e641a5733d67911a362 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Documentation~/TableOfContents.md b/Documentation~/TableOfContents.md new file mode 100644 index 0000000..7cbf46f --- /dev/null +++ b/Documentation~/TableOfContents.md @@ -0,0 +1,20 @@ +# Unity Transport manual + +* **Introduction** + * [Unity Transport overview](index.md) + * [Installation guide](install.md) +* **Workflows** + * [Creating a minimal client and server](workflow-client-server.md) + * [Creating a jobified client and server](workflow-client-server-jobs.md) + * [Using pipelines](pipelines-usage.md) +* **Background information** + * [Understanding the Update flow](update-flow.md) + * [Understanding the Connection State Machine](connection-state-machine.md) + * [Event consumption](event-consumption.md) +* **Samples** + * [ClientBehaviour](samples/clientbehaviour.cs.md) + * [ServerBehaviour](samples/serverbehaviour.cs.md) + * [JobifiedClientBehaviour](samples/jobifiedclientbehaviour.cs.md) + * [JobifiedServerBehaviour](samples/jobifiedserverbehaviour.cs.md) + * [Source Project for Workflows](https://oc.unity3d.com/index.php/s/PHaNZP79Va2YOLT) + diff --git a/Documentation~/connection-state-machine.md b/Documentation~/connection-state-machine.md new file mode 100644 index 0000000..975e350 --- /dev/null +++ b/Documentation~/connection-state-machine.md @@ -0,0 +1,17 @@ +# Understanding the Connection State Machine + +It's important to at least understand how transitions occur in the connection state machine so you make decisions depending on what triggered each state. And to understand the subtle differences depending if you are `Connecting` to another host or if you simply want to Listen for incoming connections. As you can see below the state machine for the `NetworkConnection` is pretty simple. + +![ConnectionState](images/com.unity.transport.connection.png) + +All connections start in `Disconnected` state. + +- Depending what state the `NetworkDriver` is in, the `Listening (Passive)` state might be triggered. This is when the driver acts like a server listening for incoming connections and data requests. And secondly you could try to use the driver to connect to a remote endpoint and then we would invoke another flow of the state machine. + +So to give a overview we have two standard scenarios. Either you listen for incoming connections or you use and outgoing connection to connect to someone else. + +In our [client/server workflow](workflow-client-server.md) we use the ServerBehaviour to `Listen` and the ClientBehaviour to `Connect`. + + + +[Back to table of contents](TableOfContents.md) \ No newline at end of file diff --git a/Documentation~/event-consumption.md b/Documentation~/event-consumption.md new file mode 100644 index 0000000..b402ded --- /dev/null +++ b/Documentation~/event-consumption.md @@ -0,0 +1,60 @@ +# Event consumption + +There are currently 4 types of events supplied by the `NetworkDriver` + +```c# +public enum Type +{ + Empty = 0, + Data, + Connect, + Disconnect +} +``` + +As mentioned, there are a few subtle differences running the driver as a host or client. Mainly when it comes to consumption of events. + +Both your client and you server loop will want to consume the events that are produced by the `NetworkDriver`. And you do so by either calling `PopEvent` on each `NetworkConnection` similar to how we did before. + +```c# +DataStreamReader strm; +NetworkEvent.Type cmd; +while ((cmd = m_Connection.PopEvent(driver, out strm)) != NetworkEvent.Type.Empty) + ; // Handle Event +``` + +You can try calling the `PopEventForConnection` on the `NetworkDriver` as we did in the ServerBehaviour example: + +```c# +DataStreamReader strm; +NetworkEvent.Type cmd; +while ((cmd = m_Driver.PopEventForConnection(m_Connections[i], out strm)) != NetworkEvent.Type.Empty) + ; // Handle Event +``` + +There is no real difference between these calls, both calls will do the same thing. Its just how you want to phrase yourself when writing the code. + +And finally to receive a new `NetworkConnection` on the Driver while Listening you can call `Accept` + +```c# +NetworkConnection c; +while ((c = m_Driver.Accept()) != default(NetworkConnection)) + ; // Handle Connection Event. +``` + +| Event | Description | +| ---------- | ------------------------------------------------------------ | +| Empty | The `Empty` event signals that there are no more messages in our event queue to handle this frame. | +| Data | The `Data` event signals that we have received data from a connected endpoint. | +| Connect | The `Connect` event signals that a new connection has been established.
**Note**: this event is only available if the `NetworkDriver` is **not** in the `Listening` state. | +| Disconnect | The `Disconnect` event is received if;
1. `Disconnect` packet was received (calling `NetworkConnection::Disconnect` will trigger this.)
2. A *socket timeout* occurred.
3. Maximum connect attempts on the `NetworkConnection` exceeded.
**Note:** That if you call `Disconnect` on your `NetworkConnection` this will **NOT** trigger an `Disconnect` event on your local `NetworkDriver`. | + +Looking at this table we see that there are 2 things that stand out. + +- The first thing is that the `Connect` event is only available if the `NetworkDriver` is **NOT** `Listening` + - In order to receive any `Connect` events on a `NetworkDriver` that is in the `Listening` state we need to call the special function `Accept` just as we did in the *Creating a Server* section in the [Creating a minimal client and server](workflow-client-server.md) workflow page. +- The second thing to notice is that if you call `Disconnect` on a `NetworkConnection` this will not trigger an event inside your own driver. + + + +[Back to table of contents](TableOfContents.md) \ No newline at end of file diff --git a/Documentation~/images/Pipeline-stages-diagram.png b/Documentation~/images/Pipeline-stages-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..d6e32bd336aef1771a3f8eb40a552af482fe4b51 GIT binary patch literal 14518 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 literal 0 HcmV?d00001 diff --git a/Documentation~/images/com.unity.transport.driver.png b/Documentation~/images/com.unity.transport.driver.png new file mode 100644 index 0000000000000000000000000000000000000000..4a3b8ad87edc00717990434ec9bace867da53bff GIT binary patch literal 36120 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%0AonYE2H@ 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 literal 0 HcmV?d00001 diff --git a/Documentation~/images/game-object.PNG b/Documentation~/images/game-object.PNG new file mode 100644 index 0000000000000000000000000000000000000000..032b4d70b5bd6062daa62d575fb8b6abc1c44901 GIT binary patch literal 4973 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 Lrc_C@4q^0@4FfQBe_4kd^>Z5m7=2 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 BbsGQx literal 0 HcmV?d00001 diff --git a/Documentation~/index.md b/Documentation~/index.md new file mode 100644 index 0000000..2ff4344 --- /dev/null +++ b/Documentation~/index.md @@ -0,0 +1,50 @@ +# About Unity.Networking.Transport + +Use the `com.unity.transport` package to add multiplayer / network features to your project. + +## Overview + +![Transport Overview](images/layercake.png) + +# Installing Unity.Networking.Transport + +For installation instructions on the `com.unity.transport` package, follow the [installation guide](install.md). + +# Using Unity.Networking.Transport + +To learn how to use the `com.unity.transport` package in your own project, read the [manual](TableOfContents.md). + +> **Note**: Once you have installed the package, it is recommended that you read through the client and server workflows first. + +# Technical details + +## Requirements + +This version of `com.unity.transport` is compatible with the following versions of the Unity Editor: + +* 2019.1 and later + +## Known limitations + +Unity.Networking.Transport version 0.1.0 has the following limitations: + +* Currently only supports the platforms + * Windows, Linux, Mac OSX, iOS and Android + +## Package contents + +The following table shows the package folder contents. + +|Location|Description| +|---|---| +|`Documentation`|Contains manual part of the documentation (script reference is inline using xmldoc).| +|`Runtime`|Contains the implementation.| +|`Tests`|Contains all the tests.| + + +## Document revision history + +|Date|Reason| +|---|---| +|Oct 22, 2018|Documentation reorganised and proofread by Technical Writer.| +|Jul 18, 2018|Document created. Matches package version 0.1.0.| diff --git a/Documentation~/install.md b/Documentation~/install.md new file mode 100644 index 0000000..528f025 --- /dev/null +++ b/Documentation~/install.md @@ -0,0 +1,13 @@ +# Installing com.unity.transport + +1. Open the Unity Editor (`2019.1.0f1` or later) +2. Create a new Project. +3. Open the Package Manager (menu: **Window** > **Package Manager**). +4. Click the **Advanced** button at the top of the window and turn on the **Show preview packages** option. +5. Add the `Unity Transport` package to the project. + +> Note: If you encounter errors, please [report an issue](https://github.com/Unity-Technologies/multiplayer/issues) in the repository. + + +[Back to table of contents](TableOfContents.md) + diff --git a/Documentation~/pipelines-usage.md b/Documentation~/pipelines-usage.md new file mode 100644 index 0000000..da47c4a --- /dev/null +++ b/Documentation~/pipelines-usage.md @@ -0,0 +1,140 @@ +# Using pipelines +Pipelines are a feature which offers layers of functionality on top of the default socket implementation behaviour. In the case of the UDP socket this makes it possible to have additional functionality on top of the standard unreliable datagram, such as Quality of Service features like sequencing, reliability, fragmentation and so on. This could work with any type of socket interface which has been implemented for use in the driver. + +## How it works + +The way it works is that you can add any number of pipeline stages to your transport driver. So when you send a packet it will go to the first stage, then the next and so on until it's sent on the wire. On the receiving side the stages are then processed in reverse order, so the packet is correctly "unpacked" by the stages. + +For example the first stage might compress a packet and a second stage could add a sequence number (just the packets header). When receiving the packet is first passed through the sequence stage and then decompressed. The sequence stage could drop the packet if it's out of order in which case it leaves the pipeline and doesn't continue to the decompression. + +![PipelineStagesDiagram](images/Pipeline-stages-diagram.png) + +The pipeline stages are gathered together in a collection. This is the interface between the pipeline processor in the driver to the pipeline stages you might be using. Here the pipeline stages are initialized and so on. There is a default collection provided in the driver which has all the built in pipeline stages already configured. It's possible to just use that and use a custom collection if you have your own pipeline stage you need to add to the collection. + +## Example usage + +The example below shows how the driver can create a new pipeline with 2 pipeline stages present (sequencer and simulator). The driver is created with the default pipeline collection and the pipeline parameters can be passed to the collection there. Multiple pipeline parameters can be passed in this way and the collection itself takes care of assigning them to the right pipeline stage. + +When sending packets the pipeline can then be specified as a parameter, so the packet is passed through it, it's then automatically processed the right way on the receiving end. It's therefore important both the client and server set up their pipelines in exactly the same way. One exception is with pipeline stages which do not manipulate the packet payload or header, these do not need to be symmetric. For example the simulator stage here is only keeping packets on hold for a certain time and then releases them unmodified or drops them altogether, it can therefore be set up to only run on the client. + +```c# +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Networking.Transport; +using Unity.Networking.Transport.Utilities; + +public class Client { + + UdpNetworkDriver m_DriverHandle; + NetworkPipeline m_Pipeline; + + const int k_PacketSize = 256; + + // Connection establishment omitted + public NetworkConnection m_ConnectionToServer; + + public void Configure() + { + // Driver can be used as normal + m_DriverHandle = new UdpNetworkDriver(new SimulatorUtility.Parameters {MaxPacketSize = k_PacketSize, MaxPacketCount = 30, PacketDelayMs = 100}); + // Driver now knows about this pipeline and can explicitly be asked to send packets through it (by default it sends directly) + m_Pipeline = m_DriverHandle.CreatePipeline(typeof(UnreliableSequencedPipelineStage), typeof(SimulatorPipelineStage)); + } + + public unsafe void SendMessage(NativeArray someData) + { + var writer = new DataStreamWriter(k_PacketSize, Allocator.Persistent); + writer.WriteBytes((byte*)someData.GetUnsafeReadOnlyPtr(), someData.Length); + // Send using the pipeline created in Configure() + m_ConnectionToServer.Send(m_DriverHandle, m_Pipeline, writer); + } +} +``` + +## Simulator Pipeline + +The simulator pipeline stage could be added on either the client or server to simulate bad network conditions. It's best to add it as the last stage in the pipeline, then it will either drop the packet or add a delay right before it would go on the wire. + +### Using the simulator + +Nothing needs to be done after configuring the pipline, it can be set up like this when the driver is created: +```c# +m_DriverHandle = new UdpNetworkDriver(new SimulatorUtility.Parameters {MaxPacketSize = NetworkParameterConstants.MTU, MaxPacketCount = 30, PacketDelayMs = 25, PacketDropPercentage = 10}); +m_Pipeline = m_DriverHandle.CreatePipeline(typeof(SimulatorPipelineStage)); +``` + +This would create a simulator pipeline stage which can delay up to 30 packets of a size up to the MTU size constant. Each packets gets a 25 ms delay applied and 10% of packets received will be dropped. SimulatorPipelineStage processes packets on the Receive stage of the pipeline. + +### Debug information + +To get information about internal state in the simulator you can check the SimulatorUtility.Context structure, stored in the pipeline stage shared buffer. This tracks how many packets have been seet, PacketCount, and how many of those were dropped, PacketDropCount. ReadyPackets and WaitingPackets shows what packets are now ready to be sent (delay time expired) and how many are stored by the simulator. StatsTime and NextPacketTime show the last time the simulator ran and when the next packet is due to be released. + +```c# +public unsafe void DumpSimulatorStatistics() +{ + NativeSlice receiveBuffer = default; + NativeSlice sendBuffer = default; + NativeSlice sharedBuffer = default; + driver.GetPipelineBuffers(pipeline, 0, connection[0], ref receiveBuffer, ref sendBuffer, ref sharedBuffer); + var simCtx = (SimulatorUtility.Context*)sharedBuffer.GetUnsafeReadOnlyPtr(); + UnityEngine.Debug.Log("Simulator stats\n" + + "PacketCount: " + simCtx->PacketCount + "\n" + + "PacketDropCount: " + simCtx->PacketDropCount + "\n" + + "ReadyPackets: " + simCtx->ReadyPackets + "\n" + + "WaitingPackets: " + simCtx->WaitingPackets + "\n" + + "NextPacketTime: " + simCtx->NextPacketTime + "\n" + + "StatsTime: " + simCtx->StatsTime); +} +``` + +## Reliability pipeline + +The reliability pipeline makes sure all packets are delivered and in order. It adds header information to all packets sent and tracks their state internally to make this happen. Whenever a packet is sent, it is given a sequence ID and then stored in the send processing buffer along with timing information (send time). The packet is then sent with that sequence ID added to the packet header. All packet headers also include information about what remote sequence IDs have been seen, so the receiver of the packet can know the delivery state of the packets it sent. This way there is always information about delivery state flowing between the two endpoints who make up a connection. If a certain time interval expires without an acknowledgement for a particular sequence ID the packet is resent and the timers reset. + +Reliability packet header looks like this: +```c# +public struct PacketHeader +{ + public ushort Type; + public ushort ProcessingTime; + public ushort SequenceId; + public ushort AckedSequenceId; + public uint AckMask; +} +``` +Where the type could be either a payload or ack packet, which is an empty packet with only this header. Processing time is time which passed between receiving a particular sequence ID and sending an acknowledgement for it, this is used for Round Trip Time (RTT) calculations. Then there is the sequence ID of this packet (not used in ack packets) and what remote sequence ID is being acknowledged. The AckMask is the history of acknowledgements we know about (up to the window size) so you can acknowledge multiple packets in a single header. + +The ack packet type is used when a certain amount of time has passed and nothing has been sent to the remote endpoint. We then check if we need to send a pending acknowledgement to him, or else the last packet will be assumed lost and a resend will take place. If a message is sent on every update call these kinds of packets never need to be sent. + +### Using the reliability pipeline + +```c# +m_ServerDriver = new UdpNetworkDriver(new ReliableUtility.Parameters { WindowSize = 32 }); +m_Pipeline = m_ServerDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage)); +``` +This would create a pipeline with just the reliability pipeline stage present, and initialize it to a window size of 32 (so it can keep track of 32 reliable packets at a one time). The maximum value for this is 32. + +Because only 32 packets can be tracked at a time there can't be more than 32 packets in flight at any one time, trying to send a 33rd packet will result in an error and it will not be reliable (no guarantee of delivery). It's possible to check for such errors by checking the error code in the reliability internal state: + +```c# +// Get a reference to the internal state or shared context of the reliability +NativeSlice tmpReceiveBuffer = default; +NativeSlice tmpSendBuffer = default; +NativeSlice serverReliableBuffer = default; +m_ServerDriver.GetPipelineBuffers(typeof(ReliableSequencedPipelineStage), serverToClient, ref tmpReceiveBuffer, ref tmpSendBuffer, ref serverReliableBuffer); +var serverReliableCtx = (ReliableUtility.SharedContext*) serverReliableBuffer.GetUnsafePtr(); + +m_ServerDriver.Send(serverPipe, serverToClient, strm); +if (serverReliableCtx->errorCode != 0) +{ + // Failed to send with reliability, error code will be ReliableUtility.ErrorCodes.OutgoingQueueIsFull if no buffer space is left to store the packet +} +``` + +It's possible to run into the OutgoingQueueIsFull error when packets are being sent too frequently for the latency and quality of the connection. High packet loss means packets need to stay for multiple RTTs in the queue and if the RTT is high then that time can end up being longer than the send rate + window size permit. For example with 60 packets sent per second a packet will go out every 16 ms, if the RTT is 250 ms about 16 packets will be in the queue at any one time. With a packet drop the total time will go up to 500 ms and the packet will be in the last slot when it's finally freed. + +It best suited to use the reliabilty pipeline for event type messages (door opened), Remote Procedure Calls (RPCs) or slow frequency messages like chat. + +### Debug information + +More internal state information can be gathered using GetPipelineBuffers as shown above. The soaker test gathers a lot of statistics as seen in the SoakCommon.cs file, in the GatherReliabilityStats function. There it checks what the RTT used internally is determined to be and how many packets have been sent, received, dropped, duplicated and resent. \ No newline at end of file diff --git a/Documentation~/samples/clientbehaviour.cs.md b/Documentation~/samples/clientbehaviour.cs.md new file mode 100644 index 0000000..8047aad --- /dev/null +++ b/Documentation~/samples/clientbehaviour.cs.md @@ -0,0 +1,73 @@ +```c# +using UnityEngine; + +using Unity.Collections; +using Unity.Networking.Transport; + +public class ClientBehaviour : MonoBehaviour +{ + public UdpNetworkDriver m_Driver; + public NetworkConnection m_Connection; + public bool m_Done; + + void Start () + { + m_Driver = new UdpNetworkDriver(new INetworkParameter[0]); + m_Connection = default(NetworkConnection); + + var endpoint = NetworkEndPoint.LoopbackIpv4; + endpoint.Port = 9000; + m_Connection = m_Driver.Connect(endpoint); + } + + public void OnDestroy() + { + m_Driver.Dispose(); + } + + void Update() + { + m_Driver.ScheduleUpdate().Complete(); + + if (!m_Connection.IsCreated) + { + if (!m_Done) + Debug.Log("Something went wrong during connect"); + return; + } + + DataStreamReader stream; + NetworkEvent.Type cmd; + + while ((cmd = m_Connection.PopEvent(m_Driver, out stream)) != + NetworkEvent.Type.Empty) + { + if (cmd == NetworkEvent.Type.Connect) + { + Debug.Log("We are now connected to the server"); + + var value = 1; + using (var writer = new DataStreamWriter(4, Allocator.Temp)) + { + writer.Write(value); + m_Connection.Send(m_Driver, writer); + } + } + else if (cmd == NetworkEvent.Type.Data) + { + var readerCtx = default(DataStreamReader.Context); + uint value = stream.ReadUInt(ref readerCtx); + Debug.Log("Got the value = " + value + " back from the server"); + m_Done = true; + m_Connection.Disconnect(m_Driver); + m_Connection = default(NetworkConnection); + } + else if (cmd == NetworkEvent.Type.Disconnect) + { + Debug.Log("Client got disconnected from server"); + m_Connection = default(NetworkConnection); + } + } + } +} +``` \ No newline at end of file diff --git a/Documentation~/samples/jobifiedclientbehaviour.cs.md b/Documentation~/samples/jobifiedclientbehaviour.cs.md new file mode 100644 index 0000000..5f56775 --- /dev/null +++ b/Documentation~/samples/jobifiedclientbehaviour.cs.md @@ -0,0 +1,99 @@ +```c# +using UnityEngine; + +using Unity.Jobs; +using Unity.Collections; +using Unity.Networking.Transport; + +struct ClientUpdateJob : IJob +{ + public UdpNetworkDriver driver; + public NativeArray connection; + public NativeArray done; + + public void Execute() + { + if (!connection[0].IsCreated) + { + if (done[0] != 1) + Debug.Log("Something went wrong during connect"); + return; + } + + DataStreamReader stream; + NetworkEvent.Type cmd; + + while ((cmd = connection[0].PopEvent(driver, out stream)) != + NetworkEvent.Type.Empty) + { + if (cmd == NetworkEvent.Type.Connect) + { + Debug.Log("We are now connected to the server"); + + var value = 1; + using (var writer = new DataStreamWriter(4, Allocator.Temp)) + { + writer.Write(value); + connection[0].Send(driver, writer); + } + } + else if (cmd == NetworkEvent.Type.Data) + { + var readerCtx = default(DataStreamReader.Context); + uint value = stream.ReadUInt(ref readerCtx); + Debug.Log("Got the value = " + value + " back from the server"); + // And finally change the `done[0]` to `1` + done[0] = 1; + connection[0].Disconnect(driver); + connection[0] = default(NetworkConnection); + } + else if (cmd == NetworkEvent.Type.Disconnect) + { + Debug.Log("Client got disconnected from server"); + connection[0] = default(NetworkConnection); + } + } + } +} + +public class JobifiedClientBehaviour : MonoBehaviour +{ + public UdpNetworkDriver m_Driver; + public NativeArray m_Connection; + public NativeArray m_Done; + + public JobHandle ClientJobHandle; + + void Start () + { + m_Driver = new UdpNetworkDriver(new INetworkParameter[0]); + + m_Connection = new NativeArray(1, Allocator.Persistent); + m_Done = new NativeArray(1, Allocator.Persistent); + var endpoint = NetworkEndPoint.LoopbackIpv4; + endpoint.Port = 9000; + m_Connection[0] = m_Driver.Connect(endpoint); + } + + public void OnDestroy() + { + ClientJobHandle.Complete(); + m_Connection.Dispose(); + m_Driver.Dispose(); + m_Done.Dispose(); + } + + void Update() + { + ClientJobHandle.Complete(); + var job = new ClientUpdateJob + { + driver = m_Driver, + connection = m_Connection, + done = m_Done + }; + ClientJobHandle = m_Driver.ScheduleUpdate(); + ClientJobHandle = job.Schedule(ClientJobHandle); + } +} +``` \ No newline at end of file diff --git a/Documentation~/samples/jobifiedserverbehaviour.cs.md b/Documentation~/samples/jobifiedserverbehaviour.cs.md new file mode 100644 index 0000000..9d82c37 --- /dev/null +++ b/Documentation~/samples/jobifiedserverbehaviour.cs.md @@ -0,0 +1,120 @@ +```c# +using UnityEngine; +using UnityEngine.Assertions; + +using Unity.Jobs; +using Unity.Collections; +using Unity.Networking.Transport; + +struct ServerUpdateConnectionsJob : IJob +{ + public UdpNetworkDriver driver; + public NativeList connections; + + public void Execute() + { + // CleanUpConnections + for (int i = 0; i < connections.Length; i++) + { + if (!connections[i].IsCreated) + { + connections.RemoveAtSwapBack(i); + --i; + } + } + // AcceptNewConnections + NetworkConnection c; + while ((c = driver.Accept()) != default(NetworkConnection)) + { + connections.Add(c); + Debug.Log("Accepted a connection"); + } + } +} + +struct ServerUpdateJob : IJobParallelForDefer +{ + public UdpNetworkDriver.Concurrent driver; + public NativeArray connections; + + public void Execute(int index) + { + DataStreamReader stream; + if (!connections[index].IsCreated) + Assert.IsTrue(true); + + NetworkEvent.Type cmd; + while ((cmd = driver.PopEventForConnection(connections[index], out stream)) != + NetworkEvent.Type.Empty) + { + if (cmd == NetworkEvent.Type.Data) + { + var readerCtx = default(DataStreamReader.Context); + uint number = stream.ReadUInt(ref readerCtx); + + Debug.Log("Got " + number + " from the Client adding + 2 to it."); + number +=2; + + using (var writer = new DataStreamWriter(4, Allocator.Temp)) + { + writer.Write(number); + driver.Send(NetworkPipeline.Null, connections[index], writer); + } + } + else if (cmd == NetworkEvent.Type.Disconnect) + { + Debug.Log("Client disconnected from server"); + connections[index] = default(NetworkConnection); + } + } + } +} + +public class JobifiedServerBehaviour : MonoBehaviour +{ + public UdpNetworkDriver m_Driver; + public NativeList m_Connections; + private JobHandle ServerJobHandle; + + void Start () + { + m_Connections = new NativeList(16, Allocator.Persistent); + m_Driver = new UdpNetworkDriver(new INetworkParameter[0]); + var endpoint = NetworkEndPoint.AnyIpv4; + endpoint.Port = 9000; + if (m_Driver.Bind(endpoint) != 0) + Debug.Log("Failed to bind to port 9000"); + else + m_Driver.Listen(); + } + + public void OnDestroy() + { + // Make sure we run our jobs to completion before exiting. + ServerJobHandle.Complete(); + m_Connections.Dispose(); + m_Driver.Dispose(); + } + + void Update () + { + ServerJobHandle.Complete(); + + var connectionJob = new ServerUpdateConnectionsJob + { + driver = m_Driver, + connections = m_Connections + }; + + var serverUpdateJob = new ServerUpdateJob + { + driver = m_Driver.ToConcurrent(), + connections = m_Connections.AsDeferredJobArray() + }; + + ServerJobHandle = m_Driver.ScheduleUpdate(); + ServerJobHandle = connectionJob.Schedule(ServerJobHandle); + ServerJobHandle = serverUpdateJob.Schedule(m_Connections, 1, ServerJobHandle); + } +} +``` \ No newline at end of file diff --git a/Documentation~/samples/serverbehaviour.cs.md b/Documentation~/samples/serverbehaviour.cs.md new file mode 100644 index 0000000..32ce414 --- /dev/null +++ b/Documentation~/samples/serverbehaviour.cs.md @@ -0,0 +1,86 @@ +```c# +using UnityEngine; +using UnityEngine.Assertions; + +using Unity.Collections; +using Unity.Networking.Transport; + +public class ServerBehaviour : MonoBehaviour +{ + public UdpNetworkDriver m_Driver; + private NativeList m_Connections; + + void Start () + { + m_Driver = new UdpNetworkDriver(new INetworkParameter[0]); + var endpoint = NetworkEndPoint.AnyIpv4; + endpoint.Port = 9000; + if (m_Driver.Bind(endpoint) != 0) + Debug.Log("Failed to bind to port 9000"); + else + m_Driver.Listen(); + + m_Connections = new NativeList(16, Allocator.Persistent); + } + + public void OnDestroy() + { + m_Driver.Dispose(); + m_Connections.Dispose(); + } + + void Update () + { + m_Driver.ScheduleUpdate().Complete(); + + // CleanUpConnections + for (int i = 0; i < m_Connections.Length; i++) + { + if (!m_Connections[i].IsCreated) + { + m_Connections.RemoveAtSwapBack(i); + --i; + } + } + // AcceptNewConnections + NetworkConnection c; + while ((c = m_Driver.Accept()) != default(NetworkConnection)) + { + m_Connections.Add(c); + Debug.Log("Accepted a connection"); + } + + DataStreamReader stream; + for (int i = 0; i < m_Connections.Length; i++) + { + if (!m_Connections[i].IsCreated) + Assert.IsTrue(true); + + NetworkEvent.Type cmd; + while ((cmd = m_Driver.PopEventForConnection(m_Connections[i], out stream)) != + NetworkEvent.Type.Empty) + { + if (cmd == NetworkEvent.Type.Data) + { + var readerCtx = default(DataStreamReader.Context); + uint number = stream.ReadUInt(ref readerCtx); + + Debug.Log("Got " + number + " from the Client adding + 2 to it."); + number +=2; + + using (var writer = new DataStreamWriter(4, Allocator.Temp)) + { + writer.Write(number); + m_Driver.Send(NetworkPipeline.Null, m_Connections[i], writer); + } + } + else if (cmd == NetworkEvent.Type.Disconnect) + { + Debug.Log("Client disconnected from server"); + m_Connections[i] = default(NetworkConnection); + } + } + } + } +} +``` \ No newline at end of file diff --git a/Documentation~/update-flow.md b/Documentation~/update-flow.md new file mode 100644 index 0000000..2ee90d5 --- /dev/null +++ b/Documentation~/update-flow.md @@ -0,0 +1,20 @@ +# Understanding the Update flow + +We call the driver's `ScheduleUpdate` method on every frame. This is so we can update the state of each connection we have active to make sure we read all data that we have received and finally produce events that the user can react to using `PopEvent` and `PopEventForConnection`. + +The `Update` loop of the driver is really simple, it might look daunting at first glance but if you strip out all of the job system dependencies you will see we only do three things here: + +![FlowchartUpdate](images/com.unity.transport.driver.png) + +1. We start by calling our `InternalUpdate`, this call is where we clean up any stale connections, we clear our buffers and we finally check timeouts on our connections. +2. The second thing in the chain is running the `ReceiveJob` for reading and parsing the data from the socket. +3. Finally for each new message we receive on the socket we call a `AppendPacket` function that parses each packet received and either creates an event for it or discards it. + +That's it, we clean up, we populate our buffers and we push new events. + +You could almost view the `NetworkDriver` as a Control System for the State Machine handling +`NetworkConnection`. + + + +[Back to table of contents](TableOfContents.md) \ No newline at end of file diff --git a/Documentation~/workflow-client-server-jobs.md b/Documentation~/workflow-client-server-jobs.md new file mode 100644 index 0000000..1391e54 --- /dev/null +++ b/Documentation~/workflow-client-server-jobs.md @@ -0,0 +1,423 @@ +# Jobyfiying our Example + +In the workflow [Creating a minimal client and server](workflow-client-server.md), our client should look like this [code example](samples/clientbehaviour.cs.md). + +> **Note**: It is recommended, before reading this workflow, to refresh your memory on how the [C# Job System](https://docs.unity3d.com/Manual/JobSystem.html) works. + + +## Creating a Jobified Client + +Start by creating a client job to handle your inputs from the network. As you only handle one client at a time we will use the [IJob](https://docs.unity3d.com/ScriptReference/Unity.Jobs.IJob.html) as our job type. You need to pass the driver and the connection to the job so you can handle updates within the `Execute` method of the job. + +```c# +struct ClientUpdateJob: IJob +{ + public UdpNetworkDriver driver; + public NativeArray connection; + public NativeArray done; + + public void Execute() { ... } +} +``` + +> **Note**: The data inside the ClientUpdateJob is **copied**. If you want to use the data after the job is completed, you need to have your data in a shared container, such as a [NativeContainer](https://docs.unity3d.com/Manual/JobSystemNativeContainer.html). + +Since you might want to update the `NetworkConnection` and the `done` variables inside your job (we might receive a disconnect message), you need to make sure you can share the data between the job and the caller. In this case, you can use a [NativeArray](https://docs.unity3d.com/ScriptReference/Unity.Collections.NativeArray_1.html). + +> Note: You can only use [blittable types](https://docs.microsoft.com/en-us/dotnet/framework/interop/blittable-and-non-blittable-types) in a `NativeContainer`. In this case, instead of a `bool` you need to use a `byte`, as its a blittable type. + +In your `Execute` method, move over your code from the `Update` method that you have already in place from [_ClientBehaviour.cs_](samples/clientbehaviour.cs.md) and you are done. + +You need to change any call to `m_Connection` to `connection[0]` to refer to the first element inside your `NativeArray`. The same goes for your `done` variable, you need to call `done[0]` when you refer to the `done` variable. See the code below: + +```c# +public void Execute() +{ + if (!connection[0].IsCreated) + { + // Remember that its not a bool anymore. + if (done[0] != 1) + Debug.Log("Something went wrong during connect"); + return; + } + DataStreamReader stream; + NetworkEvent.Type cmd; + + while ((cmd = connection[0].PopEvent(driver, out stream)) != + NetworkEvent.Type.Empty) + { + if (cmd == NetworkEvent.Type.Connect) + { + Debug.Log("We are now connected to the server"); + + var value = 1; + using (var writer = new DataStreamWriter(4, Allocator.Temp)) + { + writer.Write(value); + connection[0].Send(driver, writer); + } + } + else if (cmd == NetworkEvent.Type.Data) + { + var readerCtx = default(DataStreamReader.Context); + uint value = stream.ReadUInt(ref readerCtx); + Debug.Log("Got the value = " + value + " back from the server"); + // And finally change the `done[0]` to `1` + done[0] = 1; + connection[0].Disconnect(driver); + connection[0] = default(NetworkConnection); + } + else if (cmd == NetworkEvent.Type.Disconnect) + { + Debug.Log("Client got disconnected from server"); + connection[0] = default(NetworkConnection); + } + } +} +``` + +### Updating the client MonoBehaviour + +When you have a job, you need to make sure that you can execute the job. To do this, you need to make some changes to your ClientBehaviour: + + +```c# +public class JobifiedClientBehaviour : MonoBehaviour { + public UdpCNetworkDriver m_Driver; + public NativeArray m_Connection; + public NativeArray m_Done; + public JobHandle ClientJobHandle; + + public void OnDestroy() { ... } + public void Start() { ... } + public void Update() { ... } +} +``` + +Both `m_Done` and `m_Connection` in the code above, have been changed to type `NativeArray`. We also added a [JobHandle](https://docs.unity3d.com/Manual/JobSystemJobDependencies.html) so you can track your ongoing jobs. + +#### Start method + +```c# +void Start () { + m_Driver = new UdpNetworkDriver(new INetworkParameter[0]); + m_Connection = new NativeArray(1, Allocator.Persistent); + m_Done = new NativeArray(1, Allocator.Persistent); + + var endpoint = NetworkEndPoint.LoopbackIpv4; + endpoint.Port = 9000; + + m_Connection[0] = m_Driver.Connect(endpoint); +} +``` + +The `Start` method looks pretty similar to before, the major update here is to make sure you create your `NativeArray`. + +#### OnDestroy method + +```c# +public void OnDestroy() +{ + ClientJobHandle.Complete(); + + m_Connection.Dispose(); + m_Driver.Dispose(); + m_Done.Dispose(); +} +``` + +Same goes for the `OnDestroy` method. Make sure you dispose all your `NativeArray` objects. A new addition is the `ClientJobHandle.Complete()` call. This makes sure your jobs complete before cleaning up and destroying the data they might be using. + +#### Client Update loop + +Finally you need to update your core game loop: + +```c# +void Update() +{ + ClientJobHandle.Complete(); + ... +} +``` + +You want to make sure (again) that before you start running your new frame, we check that the last frame is complete. Instead of calling `m_Driver.ScheduleUpdate().Complete()`, use the `JobHandle` and call `ClientJobHandle.Complete()`. + +To chain your job, start by creating a job struct: + +```c# +var job = new ClientUpdateJob +{ + driver = m_Driver, + connection = m_Connection, + done = m_Done +}; + +``` + + To schedule the job, you need to pass the `JobHandle` dependency that was returned from the `m_Driver.ScheduleUpdate` call in the `Schedule` function of your `IJob`. Start by invoking the `m_Driver.ScheduleUpdate` without a call to `Complete`, and pass the returning `JobHandle` to your saved `ClientJobHandle`. + +```c# +ClientJobHandle = m_Driver.ScheduleUpdate(); +ClientJobHandle = job.Schedule(ClientJobHandle); +``` + +As you can see in the code above, you pass the returned `ClientJobHandle` to your own job, returning a newly updated `ClientJobHandle`. + +You now have a *JobifiedClientBehaviour* that looks like [this](samples/jobifiedclientbehaviour.cs.md). + + + +## Creating a Jobified Server + +The server side is pretty similar to start with. You create the jobs you need and then you update the usage code. + +Consider this: you know that the `NetworkDriver` has a `ScheduleUpdate` method that returns a `JobHandle`. The job as you saw above populates the internal buffers of the `NetworkDriver` and lets us call `PopEvent`/`PopEventForConnection` method. What if you create a job that will fan out and run the processing code for all connected clients in parallel? If you look at the documentation for the C# Job System, you can see that there is a [IJobParallelFor](https://docs.unity3d.com/Manual/JobSystemParallelForJobs.html) job type that can handle this scenario + +> Note: Because we do not now how many requests we might receive or how many connections we might need to process at any one time, there is another `IJobPrarallelFor` job type that we can use namely: `IJobParallelForDefer` + +```c# +struct ServerUpdateJob : IJobParallelForDefer +{ + public void Execute(int index) + { + throw new System.NotImplementedException(); + } +} +``` + +However, we can’t run all of our code in parallel. + +In the client example above, we started off by cleaning up closed connections and accepting new ones, this can't be done in parallel. You need to create a connection job as well; + +Start by creating a `ServerUpdateConnectionJob` job. You know you need to pass both the `driver` and `connections` to our connection job. Then you want your job to "Clean up connections" and "Accept new connections": + +```c# +struct ServerUpdateConnectionsJob : IJob +{ + public UdpCNetworkDriver driver; + public NativeList connections; + + public void Execute() + { + // Clean up connections + for (int i = 0; i < connections.Length; i++) + { + if (!connections[i].IsCreated) + { + connections.RemoveAtSwapBack(i); + --i; + } + } + // Accept new connections + NetworkConnection c; + while ((c = driver.Accept()) != default(NetworkConnection)) + { + connections.Add(c); + Debug.Log("Accepted a connection"); + } + } +} +``` + +The code above should be almost identical to your old non-jobified code. + +With the `ServerUpdateConnectionsJob` done, lets look at how to implement the `ServerUpdateJob` using `IJobParallelFor`. + +```c# +struct ServerUpdateJob : IJobParallelForDefer +{ + public UdpCNetworkDriver.Concurrent driver; + public NativeArray connections; + + public void Execute(int index) + { + ... + } +} +``` + +There are **two** major differences here compared with our other `job`. First off we are using the `UdpNetworkDriver.Concurrent` type, this allows you to call the `NetworkDriver` from multiple threads, precisely what you need for the `IParallelForJobDefer`. Secondly, you are now passing a `NativeArray` of type `NetworkConnection` instead of a `NativeList`. The `IParallelForJobDefer` does not accept any other `Unity.Collections` type than a `NativeArray` (more on this later). + +### Execute method + +```c# +public void Execute(int index) +{ + DataStreamReader stream; + if (!connections[index].IsCreated) + Assert.IsTrue(true); + + NetworkEvent.Type cmd; + while ((cmd = driver.PopEventForConnection(connections[index], out stream)) != + NetworkEvent.Type.Empty) + { + if (cmd == NetworkEvent.Type.Data) + { + var readerCtx = default(DataStreamReader.Context); + uint number = stream.ReadUInt(ref readerCtx); + + Debug.Log("Got " + number + " from the Client adding + 2 to it."); + number +=2; + + using (var writer = new DataStreamWriter(4, Allocator.Temp)) + { + writer.Write(number); + driver.Send(connections[index], writer); + } + } + else if (cmd == NetworkEvent.Type.Disconnect) + { + Debug.Log("Client disconnected from server"); + connections[index] = default(NetworkConnection); + } + } +} +``` + +The only difference between our old code and our jobified example is that you remove the top level `for` loop that you had in your code: `for (int i = 0; i < m_Connections.Length; i++)`. This is removed because the `Execute` function on this job will be called for each connection, and the `index` to that a available connection will be passed in. You can see this `index` in use in the top level `while` loop: + +``` +while ((cmd = driver.PopEventForConnection(connections[index], out stream)) != NetworkEvent.Type.Empty` +``` + +> **Note**: You are using the `index` that was passed into your `Execute` method to iterate over all the `connections`. + +You now have 2 jobs: + +- The first job is to update your connection status. + - Add new connections + - Remove old / stale connections +- The second job is to parse `NetworkEvent` on each connected client. + + + +### Updating the server MonoBehaviour + +With this we can now go back to our [MonoBehaviour](https://docs.unity3d.com/ScriptReference/MonoBehaviour.html) and start updating the server. + +```c# +public class JobifiedServerBehaviour : MonoBehaviour +{ + public UdpNetworkDriver m_Driver; + public NativeList m_Connections; + private JobHandle ServerJobHandle; + + void Start () { ... } + + public void OnDestroy() { ... } + + void Update () { ... } +} +``` + +The only change made in your variable declaration is that you have once again added a `JobHandle` so you can keep track of your ongoing jobs. + +#### Start method + +You do not need to change your `Start` method as it should look the same: + +```c# +void Start () +{ + m_Connections = new NativeList(16, Allocator.Persistent); + m_Driver = new UdpCNetworkDriver(new INetworkParameter[0]); + + var endpoint = NetworkEndPoint.AnyIpv4; + endpoint.Port = 9000; + if (m_Driver.Bind(endpoint) != 0) + Debug.Log("Failed to bind to port 9000"); + else + m_Driver.Listen(); +} +``` + +#### OnDestroy method + +You need to remember to call `ServerJobHandle.Complete` in your `OnDestroy` method so you can properly clean up after yourself: + +```c# +public void OnDestroy() +{ + // Make sure we run our jobs to completion before exiting. + ServerJobHandle.Complete(); + m_Connections.Dispose(); + m_Driver.Dispose(); +} +``` + +#### Server update loop + +In your `Update` method, call `Complete`on the `JobHandle`. This will force the jobs to complete before we start a new frame: + +```c# +void Update () +{ + ServerJobHandle.Complete(); + + var connectionJob = new ServerUpdateConnectionsJob + { + driver = m_Driver, + connections = m_Connections + }; + + var serverUpdateJob = new ServerUpdateJob + { + driver = m_Driver.ToConcurrent(), + connections = m_Connections.ToDeferredJobArray() + }; + + ServerJobHandle = m_Driver.ScheduleUpdate(); + ServerJobHandle = connectionJob.Schedule(ServerJobHandle); + ServerJobHandle = serverUpdateJob.Schedule(m_Connections, 1, ServerJobHandle); +} +``` + +To chain the jobs, you want to following to happen: +`NetworkDriver.Update` -> `ServerUpdateConnectionsJob` -> `ServerUpdateJob`. + +Start by populating your `ServerUpdateConnectionsJob`: + +```c# +var connectionJob = new ServerUpdateConnectionsJob +{ + driver = m_Driver, + connections = m_Connections +}; +``` + +Then create your `ServerUpdateJob`. Remember to use the `ToConcurrent` call on your driver, to make sure you are using a concurrent driver for the `IParallelForJobDefer`: + +```c# +var serverUpdateJob = new ServerUpdateJob +{ + driver = m_Driver.ToConcurrent(), + connections = m_Connections.ToDeferredJobArray() +}; +``` + +The final step is to make sure the `NativeArray` is populated to the correct size. This +can be done using a `DeferredJobArray`. It makes sure that, when the job is executed, that the connections array is populated with the correct number of items that you have in your list. Since we will run the `ServerUpdateConnectionsJob` first, this might change the **size** of the list. + +Create your job chain and call `Scheduele` as follows: + +``` +ServerJobHandle = m_Driver.ScheduleUpdate(); +ServerJobHandle = connectionJob.Schedule(ServerJobHandle); +ServerJobHandle = serverUpdateJob.Schedule(m_Connections, 1, ServerJobHandle); +``` + +In the code above, you have: + +- Scheduled the `NetworkDriver` job. +- Add the `JobHandle` returned as a dependency on the `ServerUpdateConnectionJob`. +- The final link in the chain is the `ServerUpdateJob` that needs to run after the `ServerUpdateConnectionsJob`. In this line of code, there is a trick to invoke the `IJobParallelForDeferExtensions`. As you can see, `m_Connections` `NativeList` is passed to the `Schedule` method, this updates the count of connections before starting the job. It's here that it will fan out and run all the `ServerUpdateConnectionJobs` in parallel. + +> **Note**: If you are having trouble with the `serverUpdateJob.Schedule(m_Connections, 1, ServerJobHandle);` call, you might need to add `"com.unity.jobs": "0.0.7-preview.5"` to your `manifest.json` file, inside the _/Packages_ folder. + + + +You should now have a fully functional [jobified server](samples/jobifiedserverbehaviour.cs.md). + +You can download all examples from [here](https://oc.unity3d.com/index.php/s/PHaNZP79Va2YOLT). + +[Back to table of contents](TableOfContents.md) \ No newline at end of file diff --git a/Documentation~/workflow-client-server.md b/Documentation~/workflow-client-server.md new file mode 100644 index 0000000..9c40af8 --- /dev/null +++ b/Documentation~/workflow-client-server.md @@ -0,0 +1,418 @@ +# Workflow: Creating a minimal client and server + +## Table of contents + +* [Introduction](#introduction) +* [Creating a Server](#creating-a-server) +* [Creating a Client](#creating-a-client) + +## Introduction + +This workflow helps you create a sample project that highlights how to use the `com.unity.transport` API to: + +- Configure +- Connect +- Send data +- Receive data +- Close a connection +- Disconnect +- Timeout a connection + +> **Note**: This workflow covers all aspects of the Unity.Networking.Transport package. + +The goal is to make a remote `add` function. The flow will be: a client connects to the server, and sends a number, this number is then received by the server that adds another number to it and sends it back to the client. The client, upon receiving the number, disconnects and quits. + +Using the `INetworkDriver` to write client and server code is pretty similar between clients and servers, there are a few subtle differences that you can see demonstrated below. + +## Creating a Server + +A server is an endpoint that listens for incoming connection requests and sends and receives messages. + +Start by creating a C# script in the Unity Editor. + +Filename: [_Assets\Scripts\ServerBehaviour.cs_](samples/serverbehaviour.cs.md) +```c# +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class ServerBehaviour : MonoBehaviour { + + // Use this for initialization + void Start () { + + } + + // Update is called once per frame + void Update () { + + } +} +``` + +### Boilerplate code + +As the `com.unity.transport` package is a low level API, there is a bit of boiler plate code you might want to setup. This is an architecture design Unity chose to make sure that you always have full control. + +> **Note**: As development on the `com.unity.transport` package evolves, more abstractions may be created to reduce your workload on a day-to-day basis. + +The next step is to clean up the dependencies and add our boilerplate code: + +**Filename**: [_Assets\Scripts\ServerBehaviour.cs_](samples/serverbehaviour.cs.md) + +```c# +using UnityEngine; +using UnityEngine.Assertions; + +using Unity.Collections; +using Unity.Networking.Transport; + +... +``` + +#### Code walkthrough + +### ServerBehaviour.cs + +Adding the members we need the following code: + +**Filename**: [_Assets\Scripts\ServerBehaviour.cs_](samples/serverbehaviour.cs.md) + +```c# +using ... + +public class ServerBehaviour : MonoBehaviour { + + public UdpNetworkDriver m_Driver; + private NativeList m_Connections; + + void Start () { + } + + void OnDestroy() { + } + + void Update () { + } + +``` + +#### Code walkthrough + +``` +public UdpNetworkDriver m_Driver; +private NativeList m_Connections; +``` + +You need to declare a `INetworkDriver`, in this case you can use the UdpNetworkDriver. You also need to create a [NativeList](http://native-list-info) to hold our connections. + +### Start method + +**Filename**: [_Assets\Scripts\ServerBehaviour.cs_](samples/serverbehaviour.cs.md) + +```c# + void Start () + { + m_Driver = new UdpNetworkDriver(new INetworkParameter[0]); + var endpoint = NetworkEndPoint.AnyIpv4; + endpoint.Port = 9000; + if (m_Driver.Bind(endpoint) != 0) + Debug.Log("Failed to bind to port 9000"); + else + m_Driver.Listen(); + + m_Connections = new NativeList(16, Allocator.Persistent); + } +``` + +#### Code walkthrough + +The first line of code, `m_Driver = new UdpNetworkDriver(new INetworkParameter[0]);` , just makes sure you are creating your driver without any parameters. + +```c# + if (m_Driver.Bind(endpoint) != 0) + Debug.Log("Failed to bind to port 9000"); + else + m_Driver.Listen(); +``` + +Then we try to bind our driver to a specific network address and port, and if that does not fail, we call the `Listen` method. + +> **Important**: the call to the `Listen` method sets the `NetworkDriver` to the `Listen` state. This means that the `NetworkDriver` will now actively listen for incoming connections. + +` m_Connections = new NativeList(16, Allocator.Persistent);` + +Finally we create a `NativeList` to hold all the connections. + +### OnDestroy method + +Both `UdpNetworkDriver` and `NativeList` allocate unmanaged memory and need to be disposed. To make sure this happens we can simply call the `Dispose` method when we are done with both of them. + +Add the following code to the `OnDestroy` method on your [MonoBehaviour](https://docs.unity3d.com/ScriptReference/MonoBehaviour.html): + +**Filename**: [_Assets\Scripts\ServerBehaviour.cs_](samples/serverbehaviour.cs.md) + +```c# + public void OnDestroy() + { + m_Driver.Dispose(); + m_Connections.Dispose(); + } + +``` + +### Server Update loop + +As the `unity.networking.transport` package uses the [Unity C# Job System](https://docs.unity3d.com/Manual/JobSystem.html) internally, the the `m_Driver` has a `ScheduleUpdate` method call. Inside our `Update` loop you need to make sure to call the `Complete` method on the [JobHandle](https://docs.unity3d.com/Manual/JobSystemJobDependencies.html) that is returned, in order to know when you are ready to process any updates. + +```c# + void Update () { + + m_Driver.ScheduleUpdate().Complete(); +``` +> **Note**: In this example, we are forcing a synchronization on the main thread in order to update and handle our data later in the `MonoBehaviour::Update` call. The workflow [Creating a jobified client and server](workflow-client-server-jobs.md) shows you how to use the Transport package with the C# Job System. + + +The first thing we want to do, after you have updated your `m_Driver`, is to handle your connections. Start by cleaning up any old stale connections from the list before processing any new ones. This cleanup ensures that, when we iterate through the list to check what new events we have gotten, we dont have any old connections laying around. + +Inside the "Clean up connections" block below, we iterate through our connection list and just simply remove any stale connections. + +```c# + // Clean up connections + for (int i = 0; i < m_Connections.Length; i++) + { + if (!m_Connections[i].IsCreated) + { + m_Connections.RemoveAtSwapBack(i); + --i; + } + } +``` + +Under "Accept new connections" below, we add a connection while there are new connections to accept. +```c# + // Accept new connections + NetworkConnection c; + while ((c = m_Driver.Accept()) != default(NetworkConnection)) + { + m_Connections.Add(c); + Debug.Log("Accepted a connection"); + } +``` + +Now we have an up-to-date connection list. You can now start querying the driver for events that might have happened since the last update. + +```c# + DataStreamReader stream; + for (int i = 0; i < m_Connections.Length; i++) + { + if (!m_Connections[i].IsCreated) + continue; +``` +Begin by defining a `DataStreamReader`. This will be used in case any `Data` event was received. Then we just start looping through all our connections. + +For each connection we want to call `PopEventForConnection` while there are more events still needing to get processed. + +```c# + NetworkEvent.Type cmd; + while ((cmd = m_Driver.PopEventForConnection(m_Connections[i], out stream)) != + NetworkEvent.Type.Empty) + { +``` + +> **Note**: There is also the `NetworkEvent.Type PopEvent(out NetworkConnection con, out DataStreamReader slice)` method call, that returns the first available event, the `NetworkConnection` that its for and possibly a `DataStreamReader`. + +We are now ready to process events. Lets start with the `Data` event. + +```c# + if (cmd == NetworkEvent.Type.Data) + { + var readerCtx = default(DataStreamReader.Context); +``` + +Inside this block, you start by defining a `readerCtx`, this is a `DataStreamReader.Context` type. This type can be seen as a set of indices into a `DataStreamReader`, to help with knowing where in the stream you are, and how much you have read. + +Next, we use our context and try to read a `uint` from the stream and output what we have received: + +```c# + uint number = stream.ReadUInt(ref readerCtx); + Debug.Log("Got " + number + " from the Client adding + 2 to it."); +``` + +When this is done we simply add two to the number we received and send it back. To send anything with the `INetworkDriver` we need a instance of a `DataStreamWriter`. A `DataStreamWriter` is a new collection that comes with the `unity.networking.transport` package. It's also a type that needs to be disposed. In this workflow, the `using` statement makes sure that you clean up after yourself. + +After you have written your updated number to your stream, you call the `Send` method on the driver and off it goes: + +```c# + number +=2; + + using (var writer = new DataStreamWriter(4, Allocator.Temp)) + { + writer.Write(number); + m_Driver.Send(NetworkPipeline.Null, m_Connections[i], writer); + } + } +``` + +> One thing to note here is that we are `NetworkPipeline.Null`, to the `Send` function. This way we say to the driver to use the unreliable pipeline to send our data. + +Finally, you need to handle the disconnect case. This is pretty straight forward, if you receive a disconnect message you need to reset that connection to a `default(NetworkConnection)`. As you might remember, the next time the `Update` loop runs you will clean up after yourself. + +```c# + else if (cmd == NetworkEvent.Type.Disconnect) + { + Debug.Log("Client disconnected from server"); + m_Connections[i] = default(NetworkConnection); + } + } + } + } + +``` + +That's the whole server. Here is the full source code to [_ServerBehaviour.cs_](samples/serverbehaviour.cs.md). + +## Creating a Client + +The client code looks pretty similar to the server code at first glance, but there are a few subtle differences. This part of the workflow covers the differences between them, and not so much the similarities. + +### ClientBehaviour.cs + +You still define a `UdpNetworkDriver` but instead of having a list of connections we now only have one. There is a `Done` flag to indicate when we are done, or in case you have issues with a connection, you can exit quick. + +**Filename**: [_Assets\Scripts\ClientBehaviour.cs_](samples/clientbehaviour.cs.md) + +```c# +using ... + +public class ClientBehaviour : MonoBehaviour { + + public UdpNetworkDriver m_Driver; + public NetworkConnection m_Connection; + public bool Done; + + void Start () { ... } + public void OnDestroy() { ... } + void Update() { ... } +} +``` + +### Creating and Connecting a Client + +Start by creating a driver for the client and an address for the server. +```c# + void Start () { + m_Driver = new UdpNetworkDriver(new INetworkParameter[0]); + m_Connection = default(NetworkConnection); + + var endpoint = NetworkEndPoint.LoopbackIpv4; + endpoint.Port = 9000; + m_Connection = m_Driver.Connect(endpoint); + } +``` +Then call the `Connect` method on your driver. + +Cleaning up this time is a bit easier because you don’t need a `NativeList` to hold your connections, so it simply just becomes: + +```c# + public void OnDestroy() + { + m_Driver.Dispose(); + } +``` + +### Client Update loop + +You start the same way as you did in the server by calling `m_Driver.ScheduleUpdate().Complete();` and make sure that the connection worked. + +```c# + void Update() + { + m_Driver.ScheduleUpdate().Complete(); + + if (!m_Connection.IsCreated) + { + if (!Done) + Debug.Log("Something went wrong during connect"); + return; + } +``` + +You should recognize the code below, but if you look closely you can see that the call to `m_Driver.PopEventForConnection` was switched out with a call to `m_Connection.PopEvent`. This is technically the same method, it just makes it a bit clearer that you are handling a single connection. + +```c# + DataStreamReader stream; + NetworkEvent.Type cmd; + while ((cmd = m_Connection.PopEvent(m_Driver, out stream)) != + NetworkEvent.Type.Empty) + { +``` + +Now you encounter a new event you have not seen yet: a `NetworkEvent.Type.Connect` event. +This event tells you that you have received a `ConnectionAccept` message and you are now connected to the remote peer. + +> **Note**: In this case, the server that is listening on port `9000` on `IPAddress.Loopback` is more commonly known as `127.0.0.1`. + +``` + if (cmd == NetworkEvent.Type.Connect) + { + Debug.Log("We are now connected to the server"); + + var value = 1; + using (var writer = new DataStreamWriter(4, Allocator.Temp)) + { + writer.Write(value); + m_Connection.Send(m_Driver, writer); + } + } +``` +When you establish a connection between the client and the server, you send a number (that you want the server to increment by two). The use of the `using` pattern together with the `DataStreamWriter`, where we set `value` to one, write it into the stream, and finally send it out on the network. + +When the `NetworkEvent` type is `Data`, as below, you read the `value` back that you received from the server and then call the `Disconnect` method. + +> **Note**: A good pattern is to always set your `NetworkConnection` to `default(NetworkConnection)` to avoid stale references. + +```c# + else if (cmd == NetworkEvent.Type.Data) + { + var readerCtx = default(DataStreamReader.Context); + uint value = stream.ReadUInt(ref readerCtx); + Debug.Log("Got the value = " + value + " back from the server"); + Done = true; + m_Connection.Disconnect(m_Driver); + m_Connection = default(NetworkConnection); + } + +``` +Lastly we just want to make sure we handle the case that a server disconnects us for some reason. + +```c# + + else if (cmd == NetworkEvent.Type.Disconnect) + { + Debug.Log("Client got disconnected from server"); + m_Connection = default(NetworkConnection); + } + } + } +``` + +Here is the full source code for the [_ClientBehaviour.cs_](clientbehaviour.cs.md). + + +## Putting it all together. + +To take this for a test run, you can simply add a new empty [GameObject](https://docs.unity3d.com/ScriptReference/GameObject.html) to our **Scene**. + +![GameObject Added](images/game-object.PNG) + +Add add both of our behaviours to it. +![Inspector](images/inspector.PNG) + +Now when we press __Play__ we should see five log messages show up in your __Console__ window. Similar to this: + +![Console](images/console-view.PNG) + + + +[Back to table of contents](TableOfContents.md) diff --git a/Editor.meta b/Editor.meta new file mode 100644 index 0000000..a4b0631 --- /dev/null +++ b/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 234e7fea53ca344ec8293a8a3519d857 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/PipelineCollectionGeneratorWindow.cs b/Editor/PipelineCollectionGeneratorWindow.cs new file mode 100644 index 0000000..8faf5f3 --- /dev/null +++ b/Editor/PipelineCollectionGeneratorWindow.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Unity.Networking.Transport; +using UnityEditor; +using UnityEngine; + +public class PipelineCollectionGeneratorWindow : EditorWindow +{ + [MenuItem("Multiplayer/CodeGen/PipelineCollection Generator")] + public static void ShowWindow() + { + GetWindow(false, "PipelineCollection Generator", true); + } + + class PipelineStage + { + public Type type; + public bool generate; + } + private List m_PipelineTypes; + public PipelineCollectionGeneratorWindow() + { + m_PipelineTypes = new List(); + } + + private void OnGUI() + { + if (GUILayout.Button("Scan for Pipelines")) + { + FindAllPipelines(); + } + + for (int i = 0; i < m_PipelineTypes.Count; ++i) + { + m_PipelineTypes[i].generate = GUILayout.Toggle(m_PipelineTypes[i].generate, m_PipelineTypes[i].type.Name); + } + + if (GUILayout.Button("Generate Collection")) + { + var dstFile = EditorUtility.SaveFilePanel("Select file to save", "", "PipelineStageCollection", "cs"); + + var content = @"using System; +using Unity.Collections; +using Unity.Networking.Transport; +public struct PipelineStageCollection : INetworkPipelineStageCollection +{ +"; + for (int i = 0; i < m_PipelineTypes.Count; ++i) + { + if (m_PipelineTypes[i].generate) + content += " private " + m_PipelineTypes[i].type.Name + " m_" + m_PipelineTypes[i].type.Name + ";\n"; + } + + content += " public int GetStageId(Type type)\n {\n"; + int stageIdx = 0; + for (int i = 0; i < m_PipelineTypes.Count; ++i) + { + if (m_PipelineTypes[i].generate) + { + content += " if (type == typeof(" + m_PipelineTypes[i].type.Name + "))\n return " + + stageIdx + ";\n"; + ++stageIdx; + } + } + + content += " return -1;\n }\n"; + + content += @" public void Initialize(params INetworkParameter[] param) + { + for (int i = 0; i < param.Length; ++i) + { +"; + for (int i = 0; i < m_PipelineTypes.Count; ++i) + { + if (m_PipelineTypes[i].generate) + { + var inits = m_PipelineTypes[i].type.GetCustomAttributes(typeof(NetworkPipelineInitilizeAttribute), true); + foreach (var init in inits) + { + var pipelineInit = init as NetworkPipelineInitilizeAttribute; + content += " if (param[i] is " + pipelineInit.ParameterType.FullName.Replace("+", ".") + ")\n"; + content += " m_" + m_PipelineTypes[i].type.Name + ".Initialize((" + pipelineInit.ParameterType.FullName.Replace("+", ".") + ")param[i]);\n"; + } + } + } + content += " }\n }\n"; + + content += GenerateVoidInvoke( + "void InvokeInitialize(int pipelineStageId, NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, NativeSlice sharedStateBuffer)", + "InitializeConnection(sendProcessBuffer, recvProcessBuffer, sharedStateBuffer)"); + + content += GenerateInvoke( + "InboundBufferVec InvokeSend(int pipelineStageId, NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate)", + "Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate)", + "inboundBuffer"); + + content += GenerateInvoke( + "NativeSlice InvokeReceive(int pipelineStageId, NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate)", + "Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate)", + "inboundBuffer"); + + content += GenerateInvoke( + "int GetReceiveCapacity(int pipelineStageId)", + "ReceiveCapacity", + "0"); + + content += GenerateInvoke( + "int GetSendCapacity(int pipelineStageId)", + "SendCapacity", + "0"); + + content += GenerateInvoke( + "int GetHeaderCapacity(int pipelineStageId)", + "HeaderCapacity", + "0"); + + content += GenerateInvoke( + "int GetSharedStateCapacity(int pipelineStageId)", + "SharedStateCapacity", + "0"); + + content += "}\n"; + File.WriteAllText(dstFile, content); + AssetDatabase.Refresh(); + } + } + + string GenerateInvoke(string function, string perTypeInvoke, string fallback) + { + var content = " public " + function + "\n {\n"; + content += " switch (pipelineStageId)\n {\n"; + var stageIdx = 0; + for (int i = 0; i < m_PipelineTypes.Count(); ++i) + { + if (m_PipelineTypes[i].generate) + { + content += " case " + stageIdx + ":\n"; + ++stageIdx; + content += " return m_" + m_PipelineTypes[i].type.Name + "." + perTypeInvoke + ";\n"; + } + } + + content += " }\n return " + fallback + ";\n"; + content += " }\n"; + return content; + } + string GenerateVoidInvoke(string function, string perTypeInvoke) + { + var content = " public " + function + "\n {\n"; + content += " switch (pipelineStageId)\n {\n"; + var stageIdx = 0; + for (int i = 0; i < m_PipelineTypes.Count(); ++i) + { + if (m_PipelineTypes[i].generate) + { + content += " case " + stageIdx + ":\n"; + ++stageIdx; + content += " m_" + m_PipelineTypes[i].type.Name + "." + perTypeInvoke + ";\n break;\n"; + } + } + + content += " }\n }\n"; + return content; + } + + void FindAllPipelines() + { + m_PipelineTypes.Clear(); + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + IEnumerable allTypes; + + try + { + allTypes = assembly.GetTypes(); + + } + catch (ReflectionTypeLoadException e) + { + allTypes = e.Types.Where(t => t != null); + Debug.LogWarning( + $"PipelineCollectionGenerator failed loading assembly: {(assembly.IsDynamic ? assembly.ToString() : assembly.Location)}"); + } + + var pipelineTypes = allTypes.Where(t => + typeof(INetworkPipelineStage).IsAssignableFrom(t) && + !t.IsAbstract && + !t.ContainsGenericParameters); + + foreach (var pt in pipelineTypes) + { + m_PipelineTypes.Add(new PipelineStage {type = pt, generate = !pt.Name.StartsWith("Test")}); + } + } + } +} + diff --git a/Editor/PipelineCollectionGeneratorWindow.cs.meta b/Editor/PipelineCollectionGeneratorWindow.cs.meta new file mode 100644 index 0000000..a4dd316 --- /dev/null +++ b/Editor/PipelineCollectionGeneratorWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4bd04effab94b4a288837c0ae50a3f23 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Unity.Networking.Transport.Editor.asmdef b/Editor/Unity.Networking.Transport.Editor.asmdef new file mode 100644 index 0000000..fe00091 --- /dev/null +++ b/Editor/Unity.Networking.Transport.Editor.asmdef @@ -0,0 +1,9 @@ +{ + "name": "Unity.Networking.Transport.Editor", + "references": [ + "Unity.Networking.Transport" + ], + "includePlatforms": [ "Editor" ], + "excludePlatforms": [], + "allowUnsafeCode": true +} diff --git a/Editor/Unity.Networking.Transport.Editor.asmdef.meta b/Editor/Unity.Networking.Transport.Editor.asmdef.meta new file mode 100644 index 0000000..59be343 --- /dev/null +++ b/Editor/Unity.Networking.Transport.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 80733628b6e334c54b3e794956347a9b +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..75757a9 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,11 @@ +*Unity Transport copyright © 2018-2019 Unity Technologies ApS* + +Licensed under the Unity Companion License for Unity-dependent projects--see [Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License). + +Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the license for details on these and other terms and conditions. + +*Unity Transport platform bindings copyright © 2018-2019 Unity Technologies ApS* + +Licensed under the Unity Package Runtime Distribution License for Unity-dependent projects--see [Unity Package Runtime Distribution License](https://unity3d.com/legal/licenses/Unity_Package_Runtime_Distribution_License). + +Unless expressly provided otherwise, the Software under this license is made available strictly on an "AS IS" BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the license for details on these and other terms and conditions. diff --git a/LICENSE.md.meta b/LICENSE.md.meta new file mode 100644 index 0000000..9f1e39d --- /dev/null +++ b/LICENSE.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: dee4a72ac87dbbc43b3543eeca58fbe4 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime.meta b/Runtime.meta new file mode 100644 index 0000000..07718cc --- /dev/null +++ b/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d547784248f27e348aeac1860989bf5d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Bindings.meta b/Runtime/Bindings.meta new file mode 100644 index 0000000..591a917 --- /dev/null +++ b/Runtime/Bindings.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 143c9f4520011604995a64fc6de50a28 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Bindings/ios.meta b/Runtime/Bindings/ios.meta new file mode 100644 index 0000000..7c9af62 --- /dev/null +++ b/Runtime/Bindings/ios.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1be21c1ea98114a97b2db5b0bd708755 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Bindings/ios/network.bindings.c b/Runtime/Bindings/ios/network.bindings.c new file mode 100644 index 0000000..b335b57 --- /dev/null +++ b/Runtime/Bindings/ios/network.bindings.c @@ -0,0 +1,258 @@ +#include "network.bindings.h" + +#include +#include +#include + +#if PLATFORM_WIN +#include +#include +#include +#else +#include +#include +#include +#include +#define closesocket(x) \ + close(x) +#endif + +// TODO: fix this +static int g_initialized; + +#if PLATFORM_WIN +const unsigned int SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; +#endif + +static int32_t +native_get_last_error() +{ +#if PLATFORM_WIN + return WSAGetLastError(); +#else + return errno; +#endif +} + +EXPORT_API int32_t +network_initialize() +{ + int retval = 0; + if (g_initialized == 0) + { +#if PLATFORM_WIN + WSADATA wsaData = {0}; + WSAStartup(MAKEWORD(2, 2), &wsaData); +#endif + } + ++g_initialized; + return retval; +} + +EXPORT_API int32_t +network_terminate() +{ + if (g_initialized > 0) + --g_initialized; + + if (g_initialized == 0) + { +#if PLATFORM_WIN + WSACleanup(); +#endif + } + return SUCCESS; +} + +EXPORT_API int32_t +network_set_nonblocking(int64_t handle) +{ + int result = 0; +#if PLATFORM_WIN + DWORD arg = 1; + result = ioctlsocket(handle, FIONBIO, &arg); +#else + int flags = fcntl(handle, F_GETFL, 0); + fcntl(handle, F_SETFL, flags | O_NONBLOCK); +#endif + return result; +} + +EXPORT_API int32_t +network_set_send_buffer_size(int64_t handle, int size) +{ + char size_str[sizeof(int)]; + snprintf(size_str, sizeof(size_str), "%d", size); + int result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, size_str, sizeof(size_str)); + return result; +} + +EXPORT_API int32_t +network_set_receive_buffer_size(int64_t handle, int size) +{ + char size_str[sizeof(int)]; + snprintf(size_str, sizeof(size_str), "%d", size); + int result = setsockopt(handle, SOL_SOCKET, SO_RCVBUF, size_str, sizeof(size_str)); + return result; +} + +EXPORT_API int32_t +network_set_connection_reset(int64_t handle, int value) +{ + int result = 0; +#if PLATFORM_WIN + BOOL newValue = (BOOL)value; + DWORD bytesReturned = 0; + result = WSAIoctl(handle, SIO_UDP_CONNRESET, &newValue, sizeof(newValue), NULL, 0, &bytesReturned, NULL, NULL); +#else + // Avoid compiler warnings on non-windows + (void)handle; + (void)value; +#endif + return result; +} + +EXPORT_API int32_t network_get_socket_address(int64_t socket_handle, network_address* own_address, int32_t* errorcode) +{ + int retval = 0; +#if PLATFORM_WIN + if ((retval = getsockname(socket_handle, (struct sockaddr *)own_address, (int *)&own_address->length)) == 0) +#else + if ((retval = getsockname(socket_handle, (struct sockaddr *)own_address, (socklen_t*)&own_address->length)) < 0) +#endif + *errorcode = native_get_last_error(); + return retval; +} + +EXPORT_API int32_t +network_create_and_bind(int64_t *socket_handle, network_address *address, int32_t* errorcode) +{ + int64_t s = socket(address->addr.sa_family, SOCK_DGRAM, IPPROTO_UDP); + if (s < 0) + { + *errorcode = native_get_last_error(); + return -1; + } + if (address->addr.sa_family == AF_INET6) + { + int off = 0; + int result = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&off, sizeof(off)); + if (result != 0) + { + *errorcode = native_get_last_error(); + closesocket(s); + return -1; + } + } +#if PLATFORM_WIN + if (bind(s, (SOCKADDR*)address, (int)address->length) != 0) +#else + if (bind(s, (struct sockaddr*)address, (int)address->length) != 0) +#endif + { + *errorcode = native_get_last_error(); + closesocket(s); + return -1; + } + + *socket_handle = s; + return 0; +} + +EXPORT_API int32_t +network_sendmsg(int64_t socket_handle, network_iov_t *iov, int32_t iov_len, network_address *address, int32_t* errorcode) +{ + int ret = 0; +#if PLATFORM_WIN + WSABUF *iv = (WSABUF*)alloca(sizeof(WSABUF) * iov_len); + for (int32_t i = 0; i < iov_len; ++i) + { + iv[i].buf = iov[i].data; + iv[i].len = iov[i].length; + } + + uint32_t bytes_send; + ret = WSASendTo(socket_handle, iv, iov_len, + &bytes_send, 0, (SOCKADDR *)address, + (int)address->length, NULL, NULL); + if (ret != SOCKET_ERROR) + ret = bytes_send; +#else + struct iovec *iv = (struct iovec*)alloca(sizeof(struct iovec) * iov_len); + for (int32_t i = 0; i < iov_len; ++i) + { + iv[i].iov_base = iov[i].data; + iv[i].iov_len = iov[i].length; + } + + struct msghdr message; + memset(&message, 0, sizeof(struct msghdr)); + message.msg_name = (struct sockaddr *)address; + message.msg_namelen = (int)address->length; + message.msg_iov = iv; + message.msg_iovlen = iov_len; + + ret = sendmsg(socket_handle, &message, 0); +#endif + if (ret < 0) + *errorcode = native_get_last_error(); + return ret; +} + +EXPORT_API int32_t +network_recvmsg(int64_t socket_handle, network_iov_t *iov, int32_t iov_len, network_address *remote, int32_t* errorcode) +{ + int ret = 0; +#if PLATFORM_WIN + + WSABUF *iv = (WSABUF*)alloca(sizeof(WSABUF) * iov_len); + for (int32_t i = 0; i < iov_len; ++i) + { + iv[i].buf = iov[i].data; + iv[i].len = iov[i].length; + } + + uint32_t flags = 0; + uint32_t bytes_received = 0; + ret = WSARecvFrom(socket_handle, iv, iov_len, + &bytes_received, &flags, (SOCKADDR *)remote, + (int*)&remote->length, NULL, NULL); + if (ret != SOCKET_ERROR) + ret = bytes_received; +#else + struct iovec *iv = (struct iovec*)alloca(sizeof(struct iovec) * iov_len); + for (int32_t i = 0; i < iov_len; ++i) + { + iv[i].iov_base = iov[i].data; + iv[i].iov_len = iov[i].length; + } + + struct msghdr message; + memset(&message, 0, sizeof(struct msghdr)); + message.msg_name = (struct sockaddr *)remote; + message.msg_namelen = remote->length; + message.msg_iov = iv; + message.msg_iovlen = iov_len; + + ret = recvmsg(socket_handle, &message, 0); + remote->length = message.msg_namelen; + if (message.msg_flags & MSG_TRUNC) + { + *errorcode = 10040; // Match the error you would get on windows + return -1; + } +#endif + if (ret < 0) + *errorcode = native_get_last_error(); + return ret; +} + +EXPORT_API int32_t network_close(int64_t *socket_handle, int32_t* errorcode) +{ + int retval = closesocket(*socket_handle); + if (retval == SOCKET_ERROR) + *errorcode = native_get_last_error(); + + *socket_handle = 0; + return retval; +} diff --git a/Runtime/Bindings/ios/network.bindings.c.meta b/Runtime/Bindings/ios/network.bindings.c.meta new file mode 100644 index 0000000..bdf7caf --- /dev/null +++ b/Runtime/Bindings/ios/network.bindings.c.meta @@ -0,0 +1,103 @@ +fileFormatVersion: 2 +guid: db0202b1035774a33a0f1fdfd0146344 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 1 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude WebGL: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 0 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Bindings/ios/network.bindings.h b/Runtime/Bindings/ios/network.bindings.h new file mode 100644 index 0000000..473d4be --- /dev/null +++ b/Runtime/Bindings/ios/network.bindings.h @@ -0,0 +1,61 @@ +#pragma once + +#include "platform.h" + +#if PLATFORM_WIN +# include +# include +# pragma comment(lib, "ws2_32.lib") +#else +# include +# include +# define WSAEWOULDBLOCK EAGAIN +# define WSAECONNRESET ECONNRESET +# define SOCKET_ERROR -1 +#endif + +#if PLATFORM_ANDROID +#include +#endif + +#define SUCCESS 0 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + union + { + struct sockaddr addr; + struct sockaddr_in addr_in; + struct sockaddr_in6 addr_in6; + }; + int length; +} network_address; + +typedef struct +{ + int32_t length; + uint8_t *data; +} network_iov_t; + +// TODO: Should we name them ..._udp... +EXPORT_API int32_t network_initialize(); +EXPORT_API int32_t network_terminate(); + +EXPORT_API int32_t network_create_and_bind(int64_t *socket_handle, network_address *address, int32_t* errorcode); +EXPORT_API int32_t network_sendmsg(int64_t socket_handle, network_iov_t *iov, int32_t iov_len, network_address *address, int32_t* errorcode); +EXPORT_API int32_t network_recvmsg(int64_t socket_handle, network_iov_t *iov, int32_t iov_len, network_address *remote, int32_t* errorcode); +EXPORT_API int32_t network_close(int64_t *socket_handle, int32_t* errorcode); + +EXPORT_API int32_t network_set_nonblocking(int64_t socket_handle); +EXPORT_API int32_t network_set_send_buffer_size(int64_t handle, int size); +EXPORT_API int32_t network_set_receive_buffer_size(int64_t handle, int size); +EXPORT_API int32_t network_set_connection_reset(int64_t handle, int value); +EXPORT_API int32_t network_get_socket_address(int64_t socket_handle, network_address* own_address, int32_t* errorcode); + +#ifdef __cplusplus +} +#endif diff --git a/Runtime/Bindings/ios/network.bindings.h.meta b/Runtime/Bindings/ios/network.bindings.h.meta new file mode 100644 index 0000000..bd3a7b8 --- /dev/null +++ b/Runtime/Bindings/ios/network.bindings.h.meta @@ -0,0 +1,103 @@ +fileFormatVersion: 2 +guid: 5f839ca5ebe4e4b7cba2bdc4c6506c0b +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 1 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude WebGL: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 0 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Bindings/ios/platform.h b/Runtime/Bindings/ios/platform.h new file mode 100644 index 0000000..e9dc7e0 --- /dev/null +++ b/Runtime/Bindings/ios/platform.h @@ -0,0 +1,26 @@ +#pragma once + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) +#define PLATFORM_WIN 1 +#elif defined(__MACH__) || defined(__APPLE__) +#define PLATFORM_OSX 1 +#elif defined(__ANDROID__) +#define PLATFORM_ANDROID 1 +#elif defined(__linux__) +#define PLATFORM_LINUX 1 +#endif + +#include + +#if PLATFORM_WIN +#define WIN32_LEAN_AND_MEAN +#ifdef NETWORK_EXPORTS +#define EXPORT_API __declspec(dllexport) +#else +#define EXPORT_API __declspec(dllimport) +#endif +#elif PLATFORM_ANDROID +#define EXPORT_API __attribute__((visibility("default"))) +#else +#define EXPORT_API +#endif \ No newline at end of file diff --git a/Runtime/Bindings/ios/platform.h.meta b/Runtime/Bindings/ios/platform.h.meta new file mode 100644 index 0000000..cf660c4 --- /dev/null +++ b/Runtime/Bindings/ios/platform.h.meta @@ -0,0 +1,103 @@ +fileFormatVersion: 2 +guid: 6d2f995cc8e914dc68eff40e31bb9485 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 1 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude WebGL: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 0 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Bindings/network.bindings.bundle b/Runtime/Bindings/network.bindings.bundle new file mode 100644 index 0000000000000000000000000000000000000000..cb6a23487da5826ce22abf494558e787ece43035 GIT binary patch literal 11140 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 literal 0 HcmV?d00001 diff --git a/Runtime/Bindings/network.bindings.dll.meta b/Runtime/Bindings/network.bindings.dll.meta new file mode 100644 index 0000000..8661212 --- /dev/null +++ b/Runtime/Bindings/network.bindings.dll.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 69dcc7aac293f4eb48086f6d085ad3a5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Bindings/network.bindings.pdb b/Runtime/Bindings/network.bindings.pdb new file mode 100644 index 0000000000000000000000000000000000000000..b16833429e8fa4af2bcd7edbb8121153f93ba3cd GIT binary patch literal 3903488 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

    FurKW1^K&YDI)~yn}Uoq#`;xRudI$mA;&H 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�Hj&R@%Ixqs;Qe!ra0mo=+@XpeT}6ZstbX6rH5 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/x3JbLe)^Euj6Oajr-T?F8Kmx;=D1XlG~@ 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¥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

    &aH5Yf`i{jo?u^+W=lv+8RYs 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 D%eY=6 literal 0 HcmV?d00001 diff --git a/Runtime/Bindings/network.bindings.pdb.meta b/Runtime/Bindings/network.bindings.pdb.meta new file mode 100644 index 0000000..4699231 --- /dev/null +++ b/Runtime/Bindings/network.bindings.pdb.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 70549431d228545739524a2a46ef1d9f +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/DataStream.cs b/Runtime/DataStream.cs new file mode 100644 index 0000000..a53a57e --- /dev/null +++ b/Runtime/DataStream.cs @@ -0,0 +1,1154 @@ +using System.Runtime.InteropServices; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using System; +using Unity.Networking.Transport.LowLevel.Unsafe; + +namespace Unity.Networking.Transport +{ + [StructLayout(LayoutKind.Explicit)] + internal struct UIntFloat + { + [FieldOffset(0)] public float floatValue; + + [FieldOffset(0)] public uint intValue; + + [FieldOffset(0)] public double doubleValue; + + [FieldOffset(0)] public ulong longValue; + } + + /// + /// Data streams can be used to serialize data over the network. The + /// DataStreamWriter and DataStreamReader classes work together + /// to serialize data for sending and then to deserialize when receiving. + /// + /// + /// The reader can be used to deserialize the data from a writer, writing data + /// to a writer and reading it back can be done like this: + /// + /// using (var dataWriter = new DataStreamWriter(16, Allocator.Persistent)) + /// { + /// dataWriter.Write(42); + /// dataWriter.Write(1234); + /// // Length is the actual amount of data inside the writer, + /// // Capacity is the total amount. + /// var dataReader = new DataStreamReader(dataWriter, 0, dataWriter.Length); + /// var context = default(DataStreamReader.Context); + /// var myFirstInt = dataReader.ReadInt(ref context); + /// var mySecondInt = dataReader.ReadInt(ref context); + /// } + /// + /// + /// The writer needs to be Disposed (here done by wrapping usage in using statement) + /// because it uses native memory which needs to be freed. + /// + /// There are a number of functions for various data types. Each write call + /// returns a Deferred* variant for that particular type and this can be used + /// as a marker to overwrite the data later on, this is particularly useful when + /// the size of the data is written at the start and you want to write it at + /// the end when you know the value. + /// + /// + /// using (var data = new DataStreamWriter(16, Allocator.Persistent)) + /// { + /// // My header data + /// var headerSizeMark = data.Write((ushort)0); + /// var payloadSizeMark = data.Write((ushort)0); + /// data.Write(42); + /// data.Write(1234); + /// var headerSize = data.Length; + /// // Update header size to correct value + /// headerSizeMark.Update((ushort)headerSize); + /// // My payload data + /// byte[] someBytes = Encoding.ASCII.GetBytes("some string"); + /// data.Write(someBytes, someBytes.Length); + /// // Update payload size to correct value + /// payloadSizeMark.Update((ushort)(data.Length - headerSize)); + /// } + /// + /// + /// It's possible to get a more direct access to the buffer inside the + /// reader/writer, in an unsafe way. See + /// + [StructLayout(LayoutKind.Sequential)] + [NativeContainer] + public unsafe struct DataStreamWriter : IDisposable + { + public struct DeferredByte + { + public void Update(byte value) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (m_writer.m_Data->bitIndex != 0) + throw new InvalidOperationException("Cannot update a deferred writer without flushing packed writes"); +#endif + int oldOffset = m_writer.m_Data->length; + m_writer.m_Data->length = m_offset; + m_writer.Write(value); + m_writer.m_Data->length = oldOffset; + } + + internal DataStreamWriter m_writer; + internal int m_offset; + } + public struct DeferredShort + { + public void Update(short value) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (m_writer.m_Data->bitIndex != 0) + throw new InvalidOperationException("Cannot update a deferred writer without flushing packed writes"); +#endif + int oldOffset = m_writer.m_Data->length; + m_writer.m_Data->length = m_offset; + m_writer.Write(value); + m_writer.m_Data->length = oldOffset; + } + + internal DataStreamWriter m_writer; + internal int m_offset; + } + public struct DeferredUShort + { + public void Update(ushort value) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (m_writer.m_Data->bitIndex != 0) + throw new InvalidOperationException("Cannot update a deferred writer without flushing packed writes"); +#endif + int oldOffset = m_writer.m_Data->length; + m_writer.m_Data->length = m_offset; + m_writer.Write(value); + m_writer.m_Data->length = oldOffset; + } + + internal DataStreamWriter m_writer; + internal int m_offset; + } + public struct DeferredInt + { + public void Update(int value) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (m_writer.m_Data->bitIndex != 0) + throw new InvalidOperationException("Cannot update a deferred writer without flushing packed writes"); +#endif + int oldOffset = m_writer.m_Data->length; + m_writer.m_Data->length = m_offset; + m_writer.Write(value); + m_writer.m_Data->length = oldOffset; + } + + internal DataStreamWriter m_writer; + internal int m_offset; + } + public struct DeferredUInt + { + public void Update(uint value) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (m_writer.m_Data->bitIndex != 0) + throw new InvalidOperationException("Cannot update a deferred writer without flushing packed writes"); +#endif + int oldOffset = m_writer.m_Data->length; + m_writer.m_Data->length = m_offset; + m_writer.Write(value); + m_writer.m_Data->length = oldOffset; + } + + internal DataStreamWriter m_writer; + internal int m_offset; + } + public struct DeferredFloat + { + public void Update(float value) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (m_writer.m_Data->bitIndex != 0) + throw new InvalidOperationException("Cannot update a deferred writer without flushing packed writes"); +#endif + int oldOffset = m_writer.m_Data->length; + m_writer.m_Data->length = m_offset; + m_writer.Write(value); + m_writer.m_Data->length = oldOffset; + } + + internal DataStreamWriter m_writer; + internal int m_offset; + } + public struct DeferredShortNetworkByteOrder + { + public void Update(short value) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (m_writer.m_Data->bitIndex != 0) + throw new InvalidOperationException("Cannot update a deferred writer without flushing packed writes"); +#endif + int oldOffset = m_writer.m_Data->length; + m_writer.m_Data->length = m_offset; + m_writer.WriteNetworkByteOrder(value); + m_writer.m_Data->length = oldOffset; + } + + internal DataStreamWriter m_writer; + internal int m_offset; + } + public struct DeferredUShortNetworkByteOrder + { + public void Update(ushort value) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (m_writer.m_Data->bitIndex != 0) + throw new InvalidOperationException("Cannot update a deferred writer without flushing packed writes"); +#endif + int oldOffset = m_writer.m_Data->length; + m_writer.m_Data->length = m_offset; + m_writer.WriteNetworkByteOrder(value); + m_writer.m_Data->length = oldOffset; + } + + internal DataStreamWriter m_writer; + internal int m_offset; + } + public struct DeferredIntNetworkByteOrder + { + public void Update(int value) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (m_writer.m_Data->bitIndex != 0) + throw new InvalidOperationException("Cannot update a deferred writer without flushing packed writes"); +#endif + int oldOffset = m_writer.m_Data->length; + m_writer.m_Data->length = m_offset; + m_writer.WriteNetworkByteOrder(value); + m_writer.m_Data->length = oldOffset; + } + + internal DataStreamWriter m_writer; + internal int m_offset; + } + public struct DeferredUIntNetworkByteOrder + { + public void Update(uint value) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (m_writer.m_Data->bitIndex != 0) + throw new InvalidOperationException("Cannot update a deferred writer without flushing packed writes"); +#endif + int oldOffset = m_writer.m_Data->length; + m_writer.m_Data->length = m_offset; + m_writer.WriteNetworkByteOrder(value); + m_writer.m_Data->length = oldOffset; + } + + internal DataStreamWriter m_writer; + internal int m_offset; + } + + internal struct StreamData + { + public byte* buffer; + public int length; + public int capacity; + public ulong bitBuffer; + public int bitIndex; + } + + [NativeDisableUnsafePtrRestriction] internal StreamData* m_Data; + +#if ENABLE_UNITY_COLLECTIONS_CHECKS + internal AtomicSafetyHandle m_Safety; + [NativeSetClassTypeToNullOnSchedule] internal DisposeSentinel m_DisposeSentinel; +#endif + + Allocator m_Allocator; + + public DataStreamWriter(int capacity, Allocator allocator) + { + m_Allocator = allocator; + m_Data = (StreamData*)UnsafeUtility.Malloc(UnsafeUtility.SizeOf(), UnsafeUtility.AlignOf(), m_Allocator); + m_Data->capacity = capacity; + m_Data->length = 0; + m_Data->buffer = (byte*) UnsafeUtility.Malloc(capacity, UnsafeUtility.AlignOf(), m_Allocator); + m_Data->bitBuffer = 0; + m_Data->bitIndex = 0; + +#if ENABLE_UNITY_COLLECTIONS_CHECKS + DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 1, m_Allocator); +#endif + uint test = 1; + unsafe + { + byte* test_b = (byte*) &test; + m_IsLittleEndian = test_b[0] == 1 ? 1 : 0; + } + } + + private int m_IsLittleEndian; + private bool IsLittleEndian => m_IsLittleEndian != 0; + + private static short ByteSwap(short val) + { + return (short)(((val & 0xff) << 8) | ((val >> 8)&0xff)); + } + private static int ByteSwap(int val) + { + return (int)(((val & 0xff) << 24) |((val&0xff00)<<8) | ((val>>8)&0xff00) | ((val >> 24)&0xff)); + } + + /// + /// True if there is a valid data buffer present. This would be false + /// if the writer was created with no arguments. + /// + public bool IsCreated + { + get { return m_Data != null; } + } + + /// + /// The total size of the data buffer, see for + /// the size of space used in the buffer. Capacity can be + /// changed after the writer has been created. + /// + /// Thrown if the given + /// capacity is smaller than the current buffer usage. + public int Capacity + { + get + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckReadAndThrow(m_Safety); +#endif + return m_Data->capacity; + } + set + { + if (m_Data->capacity == value) + return; +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckWriteAndBumpSecondaryVersion(m_Safety); + if (m_Data->length + ((m_Data->bitIndex + 7) >> 3) > value) + throw new InvalidOperationException("Cannot shrink a data stream to be shorter than the current data in it"); +#endif + byte* newbuf = (byte*) UnsafeUtility.Malloc(value, UnsafeUtility.AlignOf(), m_Allocator); + UnsafeUtility.MemCpy(newbuf, m_Data->buffer, m_Data->length); + UnsafeUtility.Free(m_Data->buffer, m_Allocator); + m_Data->buffer = newbuf; + m_Data->capacity = value; + } + } + + /// + /// The size of the buffer used. See for the total size. + /// + public int Length + { + get + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckReadAndThrow(m_Safety); +#endif + return m_Data->length + ((m_Data->bitIndex + 7) >> 3); + } + } + /// + /// The size of the buffer used in bits. See for the length in bytes. + /// + public int LengthInBits + { + get + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckReadAndThrow(m_Safety); +#endif + return m_Data->length*8 + m_Data->bitIndex; + } + } + + /// + /// The writer uses unmanaged memory for its data buffer. Dispose + /// needs to be called to free this resource. + /// + public void Dispose() + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + DisposeSentinel.Dispose(ref m_Safety, ref m_DisposeSentinel); +#endif + UnsafeUtility.Free(m_Data->buffer, m_Allocator); + UnsafeUtility.Free(m_Data, m_Allocator); + m_Data = (StreamData*) 0; + } + + public void Flush() + { + while (m_Data->bitIndex > 0) + { + m_Data->buffer[m_Data->length++] = (byte)m_Data->bitBuffer; + m_Data->bitIndex -= 8; + m_Data->bitBuffer >>= 8; + } + + m_Data->bitIndex = 0; + } + + /// + /// Create a NativeSlice with access to the raw data in the writer, the data size + /// (start to length) must not exceed the total size of the array or + /// an exception will be thrown. + /// + /// + /// + public NativeSlice GetNativeSlice(int start, int length) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + ValidateSizeParameters(start, length, length); +#endif + + var slice = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice(m_Data->buffer + start, 1, + length); +#if ENABLE_UNITY_COLLECTIONS_CHECKS + NativeSliceUnsafeUtility.SetAtomicSafetyHandle(ref slice, m_Safety); +#endif + return slice; + } + + /// + /// Copy data from the writer to the given NativeArray, the data size + /// (start to length) must not exceed the total size of the array or + /// an exception will be thrown. + /// + /// + /// + /// + public void CopyTo(int start, int length, NativeArray dest) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + ValidateSizeParameters(start, length, dest.Length); +#endif + + void* dstPtr = dest.GetUnsafePtr(); + UnsafeUtility.MemCpy(dstPtr, m_Data->buffer + start, length); + } + + /// + /// Copy data from the writer to the given managed byte array, the + /// data size (start to length) must not exceed the total size of the + /// byte array or an exception will be thrown. + /// + /// + /// + /// + public void CopyTo(int start, int length, ref byte[] dest) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + ValidateSizeParameters(start, length, dest.Length); +#endif + + fixed (byte* ptr = dest) + { + UnsafeUtility.MemCpy(ptr, m_Data->buffer + start, length); + } + } + +#if ENABLE_UNITY_COLLECTIONS_CHECKS + void ValidateSizeParameters(int start, int length, int dstLength) + { + if (start < 0 || length + start > m_Data->length) + throw new ArgumentOutOfRangeException("start+length", + "The sum of start and length can not be larger than the data buffer Length"); + + if (length > dstLength) + throw new ArgumentOutOfRangeException("length", "Length must be <= than the length of the destination"); + + if (m_Data->bitIndex > 0) + throw new InvalidOperationException("Cannot read from a DataStreamWriter when there are pending packed writes, call Flush first"); + + AtomicSafetyHandle.CheckReadAndThrow(m_Safety); + } +#endif + + public void WriteBytes(byte* data, int bytes) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); + if (m_Data->length + ((m_Data->bitIndex + 7) >> 3) + bytes > m_Data->capacity) + throw new System.ArgumentOutOfRangeException(); +#endif + Flush(); + UnsafeUtility.MemCpy(m_Data->buffer + m_Data->length, data, bytes); + m_Data->length += bytes; + } + + public DeferredByte Write(byte value) + { + var ret = new DeferredByte {m_writer = this, m_offset = m_Data->length + ((m_Data->bitIndex + 7) >> 3)}; + WriteBytes((byte*) &value, sizeof(byte)); + return ret; + } + + /// + /// Copy byte array into the writers data buffer, up to the + /// given length or the complete size if no length (or -1) is given. + /// + /// Source byte array + /// Length to copy, omit this to copy all the byte array + public void Write(byte[] value, int length = -1) + { + if (length < 0) + length = value.Length; + + fixed (byte* p = value) + { + WriteBytes(p, length); + } + } + + public DeferredShort Write(short value) + { + var ret = new DeferredShort {m_writer = this, m_offset = m_Data->length + ((m_Data->bitIndex + 7) >> 3)}; + WriteBytes((byte*) &value, sizeof(short)); + return ret; + } + + public DeferredUShort Write(ushort value) + { + var ret = new DeferredUShort {m_writer = this, m_offset = m_Data->length + ((m_Data->bitIndex + 7) >> 3)}; + WriteBytes((byte*) &value, sizeof(ushort)); + return ret; + } + + public DeferredInt Write(int value) + { + var ret = new DeferredInt {m_writer = this, m_offset = m_Data->length + ((m_Data->bitIndex + 7) >> 3)}; + WriteBytes((byte*) &value, sizeof(int)); + return ret; + } + + public DeferredUInt Write(uint value) + { + var ret = new DeferredUInt {m_writer = this, m_offset = m_Data->length + ((m_Data->bitIndex + 7) >> 3)}; + WriteBytes((byte*) &value, sizeof(uint)); + return ret; + } + public void Write(ulong value) + { + WriteBytes((byte*) &value, sizeof(ulong)); + } + + public DeferredShortNetworkByteOrder WriteNetworkByteOrder(short value) + { + var ret = new DeferredShortNetworkByteOrder {m_writer = this, m_offset = m_Data->length + ((m_Data->bitIndex + 7) >> 3)}; + short netValue = IsLittleEndian ? ByteSwap(value) : value; + WriteBytes((byte*) &netValue, sizeof(short)); + return ret; + } + + public DeferredUShortNetworkByteOrder WriteNetworkByteOrder(ushort value) + { + var ret = new DeferredUShortNetworkByteOrder {m_writer = this, m_offset = m_Data->length + ((m_Data->bitIndex + 7) >> 3)}; + WriteNetworkByteOrder((short) value); + return ret; + } + + public DeferredIntNetworkByteOrder WriteNetworkByteOrder(int value) + { + var ret = new DeferredIntNetworkByteOrder {m_writer = this, m_offset = m_Data->length + ((m_Data->bitIndex + 7) >> 3)}; + int netValue = IsLittleEndian ? ByteSwap(value) : value; + WriteBytes((byte*) &netValue, sizeof(int)); + return ret; + } + + public DeferredUIntNetworkByteOrder WriteNetworkByteOrder(uint value) + { + var ret = new DeferredUIntNetworkByteOrder {m_writer = this, m_offset = m_Data->length + ((m_Data->bitIndex + 7) >> 3)}; + WriteNetworkByteOrder((int)value); + return ret; + } + + public DeferredFloat Write(float value) + { + var ret = new DeferredFloat {m_writer = this, m_offset = m_Data->length + ((m_Data->bitIndex + 7) >> 3)}; + UIntFloat uf = new UIntFloat(); + uf.floatValue = value; + Write((int) uf.intValue); + return ret; + } + + private void FlushBits() + { + while (m_Data->bitIndex >= 8) + { + m_Data->buffer[m_Data->length++] = (byte)m_Data->bitBuffer; + m_Data->bitIndex -= 8; + m_Data->bitBuffer >>= 8; + } + } + 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 + + m_Data->bitBuffer |= ((ulong)value << m_Data->bitIndex); + m_Data->bitIndex += numbits; + } + + public void WritePackedUInt(uint value, NetworkCompressionModel model) + { + 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); + if (m_Data->length + ((m_Data->bitIndex + encodeEntry&0xff + bits + 7) >> 3) > m_Data->capacity) + throw new System.ArgumentOutOfRangeException(); +#endif + WriteRawBitsInternal((uint)(encodeEntry >> 8), encodeEntry & 0xFF); + WriteRawBitsInternal(value - offset, bits); + FlushBits(); + } + public void WritePackedInt(int value, NetworkCompressionModel model) + { + uint interleaved = (uint)((value >> 31) ^ (value << 1)); // interleave negative values between positive values: 0, -1, 1, -2, 2 + WritePackedUInt(interleaved, model); + } + public void WritePackedFloat(float value, NetworkCompressionModel model) + { + WritePackedFloatDelta(value, 0, model); + } + public void WritePackedUIntDelta(uint value, uint baseline, NetworkCompressionModel model) + { + int diff = (int)(baseline - value); + WritePackedInt(diff, model); + } + public void WritePackedIntDelta(int value, int baseline, NetworkCompressionModel model) + { + int diff = (int)(baseline - value); + WritePackedInt(diff, model); + } + public void WritePackedFloatDelta(float value, float baseline, NetworkCompressionModel model) + { + var bits = 0; + if (value != baseline) + bits = 32; +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); + if (m_Data->length + ((m_Data->bitIndex + 1 + bits + 7) >> 3) > m_Data->capacity) + throw new System.ArgumentOutOfRangeException(); +#endif + if (bits == 0) + WriteRawBitsInternal(0, 1); + else + { + WriteRawBitsInternal(1, 1); + UIntFloat uf = new UIntFloat(); + uf.floatValue = value; + WriteRawBitsInternal(uf.intValue, bits); + } + FlushBits(); + } + /// + /// Moves the write position to the start of the data buffer used. + /// + public void Clear() + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckWriteAndBumpSecondaryVersion(m_Safety); +#endif + m_Data->length = 0; + m_Data->bitIndex = 0; + m_Data->bitBuffer = 0; + } + } + + /// + /// The DataStreamReader class is the counterpart of the + /// DataStreamWriter class and can be be used to deserialize + /// data which was prepared with it. + /// + /// + /// Simple usage example: + /// + /// using (var dataWriter = new DataStreamWriter(16, Allocator.Persistent)) + /// { + /// dataWriter.Write(42); + /// dataWriter.Write(1234); + /// // Length is the actual amount of data inside the writer, + /// // Capacity is the total amount. + /// var dataReader = new DataStreamReader(dataWriter, 0, dataWriter.Length); + /// var context = default(DataStreamReader.Context); + /// var myFirstInt = dataReader.ReadInt(ref context); + /// var mySecondInt = dataReader.ReadInt(ref context); + /// } + /// + /// + /// The DataStreamReader.Context passed to all the Read* functions + /// carries the position of the read pointer inside the buffer inside, this can be + /// used with the job system but normally you start by creating + /// a default context like the example above shows. + /// + /// See the class for more information + /// and examples. + /// + public unsafe struct DataStreamReader + { + /// + /// The context is the current index to the data buffer used by the + /// reader. This can be used when the reader is used with the job system but normally + /// the same context is passed in for each read invocation so the correct + /// read index is used: + /// + /// var dataReader = new DataStreamReader(someDataWriter, 0, someDataWriter.Length); + /// var ctx = default(DataStreamReader.Context); + /// var someInt = dataReader.ReadInt(ref ctx); + /// var someOtherInt = dataReader.ReadInt(ref ctx); + /// + /// + public struct Context + { + internal int m_ReadByteIndex; + internal int m_BitIndex; + internal ulong m_BitBuffer; + } + + internal byte* m_bufferPtr; + int m_Length; +#if ENABLE_UNITY_COLLECTIONS_CHECKS + internal AtomicSafetyHandle m_Safety; +#endif + + public DataStreamReader(NativeSlice slice) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + m_Safety = NativeSliceUnsafeUtility.GetAtomicSafetyHandle(slice); +#endif + m_bufferPtr = (byte*)slice.GetUnsafeReadOnlyPtr(); + m_Length = slice.Length; + + uint test = 1; + unsafe + { + byte* test_b = (byte*) &test; + m_IsLittleEndian = test_b[0] == 1 ? 1 : 0; + } + } + + public DataStreamReader(DataStreamWriter writer, int offset, int length) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (offset + length > writer.Length) + throw new System.ArgumentOutOfRangeException(); + m_Safety = writer.m_Safety; + AtomicSafetyHandle.UseSecondaryVersion(ref m_Safety); +#if !UNITY_2019_3_OR_NEWER + AtomicSafetyHandle.SetAllowSecondaryVersionWriting(m_Safety, false); +#endif +#endif + m_bufferPtr = writer.GetUnsafeReadOnlyPtr() + offset; + m_Length = length; + + uint test = 1; + unsafe + { + byte* test_b = (byte*) &test; + m_IsLittleEndian = test_b[0] == 1 ? 1 : 0; + } + } + + private int m_IsLittleEndian; + private bool IsLittleEndian => m_IsLittleEndian != 0; + + private static short ByteSwap(short val) + { + return (short)(((val & 0xff) << 8) | ((val >> 8)&0xff)); + } + private static int ByteSwap(int val) + { + return (int)(((val & 0xff) << 24) |((val&0xff00)<<8) | ((val>>8)&0xff00) | ((val >> 24)&0xff)); + } + + /// + /// The total size of the buffer space this reader is working with. + /// + public int Length + { + get + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckReadAndThrow(m_Safety); +#endif + return m_Length; + } + } + + /// + /// True if the reader has been pointed to a valid buffer space. This + /// would be false if the reader was created with no arguments. + /// + public bool IsCreated + { + get { return m_bufferPtr != null; } + } + + /// + /// Read and copy data to the memory location pointed to, an exception will + /// be thrown if it does not fit. + /// + /// + /// + /// + /// Thrown if the length + /// will put the reader out of bounds based on the current read pointer + /// position. + public void ReadBytes(ref Context ctx, byte* data, int length) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckReadAndThrow(m_Safety); + if (GetBytesRead(ref ctx) + length > m_Length) + { + throw new System.ArgumentOutOfRangeException(); + } +#endif + // Restore the full bytes moved to the bit buffer but no consumed + ctx.m_ReadByteIndex -= (ctx.m_BitIndex >> 3); + ctx.m_BitIndex = 0; + ctx.m_BitBuffer = 0; + UnsafeUtility.MemCpy(data, m_bufferPtr + ctx.m_ReadByteIndex, length); + ctx.m_ReadByteIndex += length; + } + + /// + /// Read and copy data into the given managed byte array, an exception will + /// be thrown if it does not fit. + /// + /// + /// + /// + public void ReadBytesIntoArray(ref Context ctx, ref byte[] dest, int length) + { + for (var i = 0; i < length; ++i) + dest[i] = ReadByte(ref ctx); + } + + /// + /// Create a new byte array and read the given length of bytes into it. + /// + /// Current reader context + /// Amount of bytes to read. + /// Newly created byte array with the contents. + public byte[] ReadBytesAsArray(ref Context ctx, int length) + { + var array = new byte[length]; + for (var i = 0; i < array.Length; ++i) + array[i] = ReadByte(ref ctx); + return array; + } + + public int GetBytesRead(ref Context ctx) + { + return ctx.m_ReadByteIndex - (ctx.m_BitIndex >> 3); + } + public int GetBitsRead(ref Context ctx) + { + return (ctx.m_ReadByteIndex<<3) - ctx.m_BitIndex; + } + + public byte ReadByte(ref Context ctx) + { + byte data; + ReadBytes(ref ctx, (byte*) &data, sizeof(byte)); + return data; + } + + public short ReadShort(ref Context ctx) + { + short data; + ReadBytes(ref ctx, (byte*) &data, sizeof(short)); + return data; + } + + public ushort ReadUShort(ref Context ctx) + { + ushort data; + ReadBytes(ref ctx, (byte*) &data, sizeof(ushort)); + return data; + } + + public int ReadInt(ref Context ctx) + { + int data; + ReadBytes(ref ctx, (byte*) &data, sizeof(int)); + return data; + } + + public uint ReadUInt(ref Context ctx) + { + uint data; + ReadBytes(ref ctx, (byte*) &data, sizeof(uint)); + return data; + } + public ulong ReadULong(ref Context ctx) + { + ulong data; + ReadBytes(ref ctx, (byte*) &data, sizeof(ulong)); + return data; + } + + public short ReadShortNetworkByteOrder(ref Context ctx) + { + short data; + ReadBytes(ref ctx, (byte*) &data, sizeof(short)); + return IsLittleEndian ? ByteSwap(data) : data; + } + + public ushort ReadUShortNetworkByteOrder(ref Context ctx) + { + return (ushort) ReadShortNetworkByteOrder(ref ctx); + } + + public int ReadIntNetworkByteOrder(ref Context ctx) + { + int data; + ReadBytes(ref ctx, (byte*) &data, sizeof(int)); + return IsLittleEndian ? ByteSwap(data) : data; + } + + public uint ReadUIntNetworkByteOrder(ref Context ctx) + { + return (uint) ReadIntNetworkByteOrder(ref ctx); + } + + public float ReadFloat(ref Context ctx) + { + UIntFloat uf = new UIntFloat(); + uf.intValue = (uint) ReadInt(ref ctx); + return uf.floatValue; + } + public uint ReadPackedUInt(ref Context ctx, NetworkCompressionModel model) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckReadAndThrow(m_Safety); +#endif + FillBitBuffer(ref ctx); + uint peekMask = (1u << NetworkCompressionModel.k_MaxHuffmanSymbolLength) - 1u; + uint peekBits = (uint)ctx.m_BitBuffer & peekMask; + ushort huffmanEntry = model.decodeTable[(int)peekBits]; + int symbol = huffmanEntry >> 8; + int length = huffmanEntry & 0xFF; + +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (ctx.m_BitIndex < length) + { + throw new System.ArgumentOutOfRangeException(); + } +#endif + + // Skip Huffman bits + ctx.m_BitBuffer >>= length; + ctx.m_BitIndex -= length; + + uint offset = model.bucketOffsets[symbol]; + int bits = model.bucketSizes[symbol]; + return ReadRawBitsInternal(ref ctx, bits) + offset; + } + void FillBitBuffer(ref Context ctx) + { + while (ctx.m_BitIndex <= 56 && ctx.m_ReadByteIndex < m_Length) + { + ctx.m_BitBuffer |= (ulong)m_bufferPtr[ctx.m_ReadByteIndex++] << ctx.m_BitIndex; + ctx.m_BitIndex += 8; + } + } + uint ReadRawBitsInternal(ref Context ctx, int numbits) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (numbits < 0 || numbits > 32) + throw new ArgumentOutOfRangeException("Invalid number of bits"); + if (ctx.m_BitIndex < numbits) + { + throw new System.ArgumentOutOfRangeException("Not enough bits to read"); + } +#endif + uint res = (uint)(ctx.m_BitBuffer & ((1UL << numbits) - 1UL)); + ctx.m_BitBuffer >>= numbits; + ctx.m_BitIndex -= numbits; + return res; + } + + public int ReadPackedInt(ref Context ctx, NetworkCompressionModel model) + { + uint folded = ReadPackedUInt(ref ctx, model); + return (int)(folded >> 1) ^ -(int)(folded & 1); // Deinterleave values from [0, -1, 1, -2, 2...] to [..., -2, -1, -0, 1, 2, ...] + } + public float ReadPackedFloat(ref Context ctx, NetworkCompressionModel model) + { + return ReadPackedFloatDelta(ref ctx, 0, model); + } + public int ReadPackedIntDelta(ref Context ctx, int baseline, NetworkCompressionModel model) + { + int delta = ReadPackedInt(ref ctx, model); + return baseline - delta; + } + + public uint ReadPackedUIntDelta(ref Context ctx, uint baseline, NetworkCompressionModel model) + { + uint delta = (uint)ReadPackedInt(ref ctx, model); + return baseline - delta; + } + public float ReadPackedFloatDelta(ref Context ctx, float baseline, NetworkCompressionModel model) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckReadAndThrow(m_Safety); +#endif + FillBitBuffer(ref ctx); + if (ReadRawBitsInternal(ref ctx, 1) == 0) + return baseline; + + var bits = 32; + UIntFloat uf = new UIntFloat(); + uf.intValue = ReadRawBitsInternal(ref ctx, bits); + return uf.floatValue; + } + } +} + +namespace Unity.Networking.Transport.LowLevel.Unsafe +{ + /// + public static class DataStreamUnsafeUtility + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + public static AtomicSafetyHandle GetAtomicSafetyHandle(DataStreamWriter strm) + { + return strm.m_Safety; + } + + public static void SetAtomicSafetyHandle(ref DataStreamWriter strm, AtomicSafetyHandle safety) + { + strm.m_Safety = safety; + } + +#endif + /// + /// Get the byte* pointer to the start of the buffer backing the DataStreamWriter. + /// A safety check is done to see if you have write access to the buffer. + /// + /// + /// Pointer to the data stream buffer. + public unsafe static byte* GetUnsafePtr(this DataStreamWriter strm) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckWriteAndThrow(strm.m_Safety); +#endif + return strm.m_Data->buffer; + } + + /// + /// Get the byte* pointer to the start of the buffer backing the DataStreamWriter. + /// A safety check is done to make sure you only have read access to the buffer. + /// + /// + /// Pointer to the data stream buffer. + public unsafe static byte* GetUnsafeReadOnlyPtr(this DataStreamWriter strm) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckReadAndThrow(strm.m_Safety); + if (strm.m_Data->bitIndex > 0) + throw new InvalidOperationException("Cannot read from a DataStreamWriter when there are pending packed writes, call Flush first"); +#endif + return strm.m_Data->buffer; + } + + /// + /// Get the byte* pointer to the buffer backing the DataStreamWriter. + /// Does not check the safety handle for read/write access. + /// + /// + /// Pointer to the data stream buffer. + unsafe public static byte* GetUnsafeBufferPointerWithoutChecks(this DataStreamWriter strm) + { + return strm.m_Data->buffer; + } + + /// + /// Get the byte* pointer to the start of the buffer backing the DataStreamReader. + /// A safety check is done to make sure you only have read access to the buffer. + /// + /// + /// Pointer to the data stream buffer. + public unsafe static byte* GetUnsafeReadOnlyPtr(this DataStreamReader strm) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckReadAndThrow(strm.m_Safety); +#endif + return strm.m_bufferPtr; + } + + /// + /// Signal how many bytes have been written to the buffer used by the data + /// stream using one of the unsafe pointer getters. + /// + /// + /// Amount of data written to the buffer. + /// If the length specified brings the total length to a value higher than the capacity of the buffer. + public unsafe static void WriteBytesWithUnsafePointer(this DataStreamWriter strm, int length) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckWriteAndThrow(strm.m_Safety); + if (strm.m_Data->length + length > strm.m_Data->capacity) + throw new ArgumentOutOfRangeException(); +#endif + strm.m_Data->length += length; + } + + public unsafe static DataStreamReader CreateReaderFromExistingData(byte* data, int length) + { + var slice = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice(data, 1, length); +#if ENABLE_UNITY_COLLECTIONS_CHECKS + NativeSliceUnsafeUtility.SetAtomicSafetyHandle(ref slice, AtomicSafetyHandle.GetTempUnsafePtrSliceHandle()); +#endif + return new DataStreamReader(slice); + } + } +} diff --git a/Runtime/DataStream.cs.meta b/Runtime/DataStream.cs.meta new file mode 100644 index 0000000..432702c --- /dev/null +++ b/Runtime/DataStream.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a006f31a7b465d946a601f1d26b9d13c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/INetworkDriver.cs b/Runtime/INetworkDriver.cs new file mode 100644 index 0000000..655368d --- /dev/null +++ b/Runtime/INetworkDriver.cs @@ -0,0 +1,125 @@ +using System; +using Unity.Jobs; + +namespace Unity.Networking.Transport +{ + /// + /// The NetworkDriver interface is the main entry point for the transport. + /// The Driver is similar to a UDP socket which can handle many connections. + /// + public interface INetworkDriver : IDisposable + { + // :: Driver Helpers + + bool IsCreated { get; } + + /// + /// Schedule a job to update the state of the NetworkDriver, read messages and events from the underlying + /// network interface and populate the event queues to allow reading from connections concurrently. + /// + /// + /// Used to chain dependencies for jobs. + /// + /// + /// A for the ScheduleUpdate Job. + /// + JobHandle ScheduleUpdate(JobHandle dep = default(JobHandle)); + + // :: Connection Helpers + /// + /// Bind the NetworkDriver to a port locally. This must be called before + /// the socket can listen for incoming connections. + /// + /// + /// A valid , can be implicitly cast using an System.Net.IPEndPoint + /// + /// + /// Returns 0 on Success. + /// + int Bind(NetworkEndPoint endpoint); + + /// + /// Enable listening for incoming connections on this driver. Before calling this + /// all connection attempts will be rejected. + /// + /// + /// Returns 0 on Success. + /// + int Listen(); + bool Listening { get; } + + + /// + /// Accept a pending connection attempt and get the established connection. + /// This should be called until it returns an invalid connection to make sure + /// all connections are accepted. + /// + /// + /// Returns a newly created NetworkConnection if it was Successful and a default(NetworkConnection) + /// if there where no more new NetworkConnections to accept. + /// + NetworkConnection Accept(); + + /// + /// Establish a new connection to a server with a specific address and port. + /// + /// + /// A valid NetworkEndPoint, can be implicitly cast using an System.Net.IPEndPoint + /// + NetworkConnection Connect(NetworkEndPoint endpoint); + + /// + /// Disconnect an existing connection. + /// + /// + /// Returns 0 on Success. + /// + int Disconnect(NetworkConnection con); + + /// + /// Get the state of an existing connection. If called with an invalid connection the call will return the Destroyed state. + /// + NetworkConnection.State GetConnectionState(NetworkConnection con); + + NetworkEndPoint RemoteEndPoint(NetworkConnection con); + NetworkEndPoint LocalEndPoint(); + + /// + /// Create a pipeline which can be used to process data packets sent and received by the transport package. + /// The pipelines must be created in the same order on the client and server since they are identified by + /// an index which is assigned on creation. + /// All pipelines must be created before the first connection is established. + /// + NetworkPipeline CreatePipeline(params Type[] stages); + + // :: Events + /// + /// Send a message to the specific connection. + /// + /// + /// A NetworkConnection to the endpoint you want to send to. + /// + /// + /// A valid DataStreamWriter. + /// + /// + /// Returns the size in bytes that was sent, -1 on failure. + /// + int Send(NetworkPipeline pipe, NetworkConnection con, DataStreamWriter strm); + + /// + /// Send a message to the specific connection. + /// + int Send(NetworkPipeline pipe, NetworkConnection con, IntPtr data, int len); + + /// + /// Receive an event for any connection. + /// + NetworkEvent.Type PopEvent(out NetworkConnection con, out DataStreamReader bs); + + /// + /// Receive an event for a specific connection. Should be called until it returns Empty, even if the socket is disconnected. + /// + NetworkEvent.Type PopEventForConnection(NetworkConnection con, out DataStreamReader bs); + } +} \ No newline at end of file diff --git a/Runtime/INetworkDriver.cs.meta b/Runtime/INetworkDriver.cs.meta new file mode 100644 index 0000000..0310c89 --- /dev/null +++ b/Runtime/INetworkDriver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6250d2765a8fe544b8c6b1ee0c5a580f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/INetworkInterface.cs b/Runtime/INetworkInterface.cs new file mode 100644 index 0000000..c6d94c3 --- /dev/null +++ b/Runtime/INetworkInterface.cs @@ -0,0 +1,76 @@ +using System; +using Unity.Jobs; +using Unity.Networking.Transport.Protocols; + +namespace Unity.Networking.Transport +{ + /// + /// The INetworkPacketReceiver is an interface for handling received packets, needed by the + /// + public interface INetworkPacketReceiver + { + int ReceiveCount { get; set; } + /// + /// AppendPacket is where we parse the data from the network into easy to handle events. + /// + /// The address of the endpoint we received data from. + /// The header data indicating what type of packet it is. for more information. + /// The size of the payload, if any. + /// + int AppendPacket(NetworkEndPoint address, UdpCHeader header, int dataLen); + + /// + /// Get the datastream associated with this Receiver. + /// + /// Returns a + DataStreamWriter GetDataStream(); + /// + /// Check if the the DataStreamWriter uses dynamic allocations to automatically resize the buffers or not. + /// + /// True if its dynamically resizing the DataStreamWriter + bool DynamicDataStreamSize(); + + int ReceiveErrorCode { set; } + } + + public interface INetworkInterface : IDisposable + { + /// + /// The Interface Family is used to indicate what type of medium we are trying to use. See + /// + NetworkFamily Family { get; } + + NetworkEndPoint LocalEndPoint { get; } + NetworkEndPoint RemoteEndPoint { get; } + + void Initialize(); + + /// + /// Schedule a ReceiveJob. This is used to read data from your supported medium and pass it to the AppendData function + /// supplied by the + /// + /// A used to parse the data received. + /// A to any dependency we might have. + /// Need to be of type + /// A to our newly created ScheduleReceive Job. + JobHandle ScheduleReceive(T receiver, JobHandle dep) where T : struct, INetworkPacketReceiver; + + /// + /// Binds the medium to a specific endpoint. + /// + /// + /// A valid , can be implicitly cast using an . + /// + /// 0 on Success + int Bind(NetworkEndPoint endpoint); + + /// + /// Sends a message using the underlying medium. + /// + /// An array of . + /// Lenght of the iov array passed in. + /// The address of the remote host we want to send data to. + /// + unsafe int SendMessage(network_iovec* iov, int iov_len, ref NetworkEndPoint address); + } +} \ No newline at end of file diff --git a/Runtime/INetworkInterface.cs.meta b/Runtime/INetworkInterface.cs.meta new file mode 100644 index 0000000..a922f97 --- /dev/null +++ b/Runtime/INetworkInterface.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7b096ed7046c56e419b59c93c44656ea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/IPCManager.cs b/Runtime/IPCManager.cs new file mode 100644 index 0000000..b1fec8f --- /dev/null +++ b/Runtime/IPCManager.cs @@ -0,0 +1,212 @@ +using System; +#if ENABLE_UNITY_COLLECTIONS_CHECKS +using System.IO; +#endif +using System.Runtime.InteropServices; +using Unity.Collections; +using Unity.Networking.Transport.Utilities; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Jobs; + +namespace Unity.Networking.Transport +{ + public struct IPCManager + { + public static IPCManager Instance = new IPCManager(); + + [StructLayout(LayoutKind.Explicit)] + internal unsafe struct IPCData + { + [FieldOffset(0)] public int from; + [FieldOffset(4)] public int length; + [FieldOffset(8)] public fixed byte data[NetworkParameterConstants.MTU]; + } + internal struct IPCQueuedMessage + { + public IPCManager.IPCData data; + public int dest; + } + + + private NativeQueue m_FreeList; + private NativeList m_IPCEndPoints; + private NativeMultiQueue m_IPCQueue; + + public int QueueSize { get; private set; } + internal static JobHandle ManagerAccessHandle; + + public bool IsCreated => m_IPCEndPoints.IsCreated; + + public void Initialize(int receiveQueueSize) + { + m_IPCQueue = new NativeMultiQueue(receiveQueueSize); + m_FreeList = new NativeQueue(Allocator.Persistent); + m_IPCEndPoints = new NativeList(1, Allocator.Persistent); + QueueSize = receiveQueueSize; + } + + public void Destroy() + { + ManagerAccessHandle.Complete(); + m_IPCQueue.Dispose(); + m_FreeList.Dispose(); + m_IPCEndPoints.Dispose(); + } + + internal void Update(NativeQueue queue) + { + IPCQueuedMessage val; + while (queue.TryDequeue(out val)) + { + m_IPCQueue.Enqueue(val.dest, val.data); + } + } + + /// + /// Create a NetworkEndPoint for IPC. If the EndPoint is passed to Bind the driver will assume ownership, + /// otherwise the EndPoint must be destroyed by calling ReleaseEndPoint. + /// + public unsafe NetworkEndPoint CreateEndPoint(string name = null) + { + ManagerAccessHandle.Complete(); + int id; + if (!m_FreeList.TryDequeue(out id)) + { + id = m_IPCEndPoints.Length; + m_IPCEndPoints.Add(1); + } + + var endpoint = new NetworkEndPoint + { + Family = NetworkFamily.IPC, + ipc_handle = id, + length = 6, + nbo_port = m_IPCEndPoints[id] + }; + + return endpoint; + } + + public unsafe void ReleaseEndPoint(NetworkEndPoint endpoint) + { + ManagerAccessHandle.Complete(); + if (endpoint.Family == NetworkFamily.IPC) + { + int handle = endpoint.ipc_handle; + m_IPCQueue.Clear(handle); + // Bump the version of the endpoint + ushort version = m_IPCEndPoints[handle]; + ++version; + if (version == 0) + version = 1; + m_IPCEndPoints[handle] = version; + + m_FreeList.Enqueue(handle); + } + } + + public unsafe int PeekNext(NetworkEndPoint local, void* slice, out int length, out NetworkEndPoint from) + { + ManagerAccessHandle.Complete(); + IPCData data; + from = default(NetworkEndPoint); + length = 0; + + if (m_IPCQueue.Peek(local.ipc_handle, out data)) + { + ushort version = m_IPCEndPoints[data.from]; + + UnsafeUtility.MemCpy(slice, data.data, data.length); + + length = data.length; + } + + NetworkEndPoint endpoint; + if (!TryGetEndPointByHandle(data.from, out endpoint)) + return -1; + from = endpoint; + + return length; + } + + static internal unsafe int SendMessageEx(NativeQueue.ParallelWriter queue, NetworkEndPoint local, + network_iovec* iov, int iov_len, ref NetworkEndPoint address) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (address.Family != NetworkFamily.IPC || local.Family != NetworkFamily.IPC || + address.nbo_port == 0 || local.nbo_port == 0) + throw new InvalidOperationException("Sending data over IPC requires both local and remote EndPoint to be valid IPC EndPoints"); +#endif + + var data = new IPCData(); + data.from = local.ipc_handle; + data.length = 0; + + for (int i = 0; i < iov_len; i++) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (data.length + iov[i].len >= NetworkParameterConstants.MTU) + throw new ArgumentOutOfRangeException("Cannot send more data than an MTU"); +#endif + UnsafeUtility.MemCpy(data.data+data.length, iov[i].buf, iov[i].len); + data.length += iov[i].len; + } + queue.Enqueue(new IPCQueuedMessage {dest = address.ipc_handle, data = data}); + return data.length; + } + + public unsafe int ReceiveMessageEx(NetworkEndPoint local, network_iovec* iov, int iov_len, ref NetworkEndPoint remote) + { + IPCData data; + if (!m_IPCQueue.Peek(local.ipc_handle, out data)) + return 0; + NetworkEndPoint endpoint; + if (!TryGetEndPointByHandle(data.from, out endpoint)) + return -1; +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (endpoint.Family != NetworkFamily.IPC) + throw new InvalidDataException("An incorrect message was pushed to the IPC message queue"); +#endif + +#if (UNITY_EDITOR_OSX || ((UNITY_STANDALONE_OSX || UNITY_IOS) && !UNITY_EDITOR)) + remote.family.sa_family = (byte) NetworkFamily.IPC; +#else + remote.family.sa_family = (ushort) NetworkFamily.IPC; +#endif + remote.ipc_handle = endpoint.ipc_handle; + remote.nbo_port = endpoint.nbo_port; + remote.length = 6; + + int totalLength = 0; + for (int i = 0; i < iov_len; i++) + { + var curLength = Math.Min(iov[i].len, data.length - totalLength); + UnsafeUtility.MemCpy(iov[i].buf, data.data + totalLength, curLength); + totalLength += curLength; + iov[i].len = curLength; + } + + if (totalLength < data.length) + return -1; + m_IPCQueue.Dequeue(local.ipc_handle, out data); + + return totalLength; + } + + public unsafe bool TryGetEndPointByHandle(int handle, out NetworkEndPoint endpoint) + { + endpoint = default(NetworkEndPoint); + if (handle >= m_IPCEndPoints.Length) + return false; + + var temp = new NetworkEndPoint(); + temp.Family = NetworkFamily.IPC; + temp.ipc_handle = handle; + + temp.nbo_port = m_IPCEndPoints[handle]; + endpoint = temp; + endpoint.length = 6; + return true; + } + } +} \ No newline at end of file diff --git a/Runtime/IPCManager.cs.meta b/Runtime/IPCManager.cs.meta new file mode 100644 index 0000000..5c7397d --- /dev/null +++ b/Runtime/IPCManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0b251b44841f75a46be8967c77f9e8f8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/IPCNetworkDriver.cs b/Runtime/IPCNetworkDriver.cs new file mode 100644 index 0000000..7a1abb5 --- /dev/null +++ b/Runtime/IPCNetworkDriver.cs @@ -0,0 +1,142 @@ +using System; +using Unity.Collections; +using Unity.Jobs; + +namespace Unity.Networking.Transport +{ + public struct LocalNetworkDriver : INetworkDriver + { + private GenericNetworkDriver m_genericDriver; + + public struct Concurrent + { + private GenericNetworkDriver.Concurrent m_genericConcurrent; + + internal Concurrent(GenericNetworkDriver.Concurrent genericConcurrent) + { + m_genericConcurrent = genericConcurrent; + } + public NetworkEvent.Type PopEventForConnection(NetworkConnection connectionId, out DataStreamReader slice) + { + return m_genericConcurrent.PopEventForConnection(connectionId, out slice); + } + + public int Send(NetworkPipeline pipe, NetworkConnection id, DataStreamWriter strm) + { + return m_genericConcurrent.Send(pipe, id, strm); + } + + public int Send(NetworkPipeline pipe, NetworkConnection id, IntPtr data, int len) + { + return m_genericConcurrent.Send(pipe, id, data, len); + } + + public NetworkConnection.State GetConnectionState(NetworkConnection id) + { + return m_genericConcurrent.GetConnectionState(id); + } + } + + public Concurrent ToConcurrent() + { + return new Concurrent(m_genericDriver.ToConcurrent()); + } + + public LocalNetworkDriver(params INetworkParameter[] param) + { + m_genericDriver = new GenericNetworkDriver(param); + } + public bool IsCreated => m_genericDriver.IsCreated; + public void Dispose() + { + m_genericDriver.Dispose(); + } + + public JobHandle ScheduleUpdate(JobHandle dep = default(JobHandle)) + { + return m_genericDriver.ScheduleUpdate(dep); + } + + public int ReceiveErrorCode => m_genericDriver.ReceiveErrorCode; + + public int Bind(NetworkEndPoint endpoint) + { + return m_genericDriver.Bind(endpoint); + } + + public int Listen() + { + return m_genericDriver.Listen(); + } + + public bool Listening => m_genericDriver.Listening; + + public NetworkConnection Accept() + { + return m_genericDriver.Accept(); + } + + public NetworkConnection Connect(NetworkEndPoint endpoint) + { + return m_genericDriver.Connect(endpoint); + } + + public int Disconnect(NetworkConnection con) + { + return m_genericDriver.Disconnect(con); + } + + public NetworkConnection.State GetConnectionState(NetworkConnection con) + { + return m_genericDriver.GetConnectionState(con); + } + + public void GetPipelineBuffers(Type pipelineType, NetworkConnection connection, + ref NativeSlice readProcessingBuffer, ref NativeSlice writeProcessingBuffer, + ref NativeSlice sharedBuffer) + { + m_genericDriver.GetPipelineBuffers(pipelineType, connection, ref readProcessingBuffer, + ref writeProcessingBuffer, ref sharedBuffer); + } + + public void GetPipelineBuffers(NetworkPipeline pipeline, int stageId, NetworkConnection connection, ref NativeSlice readProcessingBuffer, ref NativeSlice writeProcessingBuffer, ref NativeSlice sharedBuffer) + { + m_genericDriver.GetPipelineBuffers(pipeline, stageId, connection, ref readProcessingBuffer, ref writeProcessingBuffer, ref sharedBuffer); + } + + public NetworkEndPoint RemoteEndPoint(NetworkConnection con) + { + return m_genericDriver.RemoteEndPoint(con); + } + + public NetworkEndPoint LocalEndPoint() + { + return m_genericDriver.LocalEndPoint(); + } + + public NetworkPipeline CreatePipeline(params Type[] stages) + { + return m_genericDriver.CreatePipeline(stages); + } + + public int Send(NetworkPipeline pipe, NetworkConnection con, DataStreamWriter strm) + { + return m_genericDriver.Send(pipe, con, strm); + } + + public int Send(NetworkPipeline pipe, NetworkConnection con, IntPtr data, int len) + { + return m_genericDriver.Send(pipe, con, data, len); + } + + public NetworkEvent.Type PopEvent(out NetworkConnection con, out DataStreamReader bs) + { + return m_genericDriver.PopEvent(out con, out bs); + } + + public NetworkEvent.Type PopEventForConnection(NetworkConnection con, out DataStreamReader bs) + { + return m_genericDriver.PopEventForConnection(con, out bs); + } + } +} \ No newline at end of file diff --git a/Runtime/IPCNetworkDriver.cs.meta b/Runtime/IPCNetworkDriver.cs.meta new file mode 100644 index 0000000..4daeb48 --- /dev/null +++ b/Runtime/IPCNetworkDriver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3612fb161be744a4090a6c9f588ef0cf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/IPCNetworkInterface.cs b/Runtime/IPCNetworkInterface.cs new file mode 100644 index 0000000..1878ac0 --- /dev/null +++ b/Runtime/IPCNetworkInterface.cs @@ -0,0 +1,142 @@ +using System; +using Unity.Burst; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Jobs; +using Unity.Networking.Transport.LowLevel.Unsafe; +using Unity.Networking.Transport.Protocols; + +namespace Unity.Networking.Transport +{ + public struct IPCSocket : INetworkInterface + { + [NativeDisableContainerSafetyRestriction] private NativeQueue m_IPCQueue; + [ReadOnly] private NativeArray m_LocalEndPoint; + + public NetworkEndPoint LocalEndPoint => m_LocalEndPoint[0]; + public NetworkEndPoint RemoteEndPoint { get; } + + public NetworkFamily Family { get; } + + public void Initialize() + { + m_LocalEndPoint = new NativeArray(1, Allocator.Persistent); + m_LocalEndPoint[0] = IPCManager.Instance.CreateEndPoint(); + m_IPCQueue = new NativeQueue(Allocator.Persistent); + } + + public void Dispose() + { + IPCManager.Instance.ReleaseEndPoint(m_LocalEndPoint[0]); + m_LocalEndPoint.Dispose(); + m_IPCQueue.Dispose(); + } + + [BurstCompile] + struct SendUpdate : IJob + { + public IPCManager ipcManager; + public NativeQueue ipcQueue; + + public void Execute() + { + ipcManager.Update(ipcQueue); + } + } + + [BurstCompile] + struct ReceiveJob : IJob where T : struct, INetworkPacketReceiver + { + public T receiver; + public IPCManager ipcManager; + public NetworkEndPoint localEndPoint; + + public unsafe void Execute() + { + var address = new NetworkEndPoint {length = sizeof(NetworkEndPoint)}; + var header = new UdpCHeader(); + var stream = receiver.GetDataStream(); + receiver.ReceiveCount = 0; + receiver.ReceiveErrorCode = 0; + + while (true) + { + if (receiver.DynamicDataStreamSize()) + { + while (stream.Length+NetworkParameterConstants.MTU >= stream.Capacity) + stream.Capacity *= 2; + } + else if (stream.Length >= stream.Capacity) + return; + var sliceOffset = stream.Length; + var result = NativeReceive(ref header, stream.GetUnsafePtr() + sliceOffset, + Math.Min(NetworkParameterConstants.MTU, stream.Capacity - stream.Length), ref address); + if (result <= 0) + { + // FIXME: handle error + if (result < 0) + receiver.ReceiveErrorCode = 10040; + return; + } + + receiver.ReceiveCount += receiver.AppendPacket(address, header, result); + } + } + + unsafe int NativeReceive(ref UdpCHeader header, void* data, int length, ref NetworkEndPoint address) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (length <= 0) + throw new ArgumentException("Can't receive into 0 bytes or less of buffer memory"); +#endif + var iov = stackalloc network_iovec[2]; + + fixed (byte* ptr = header.Data) + { + iov[0].buf = ptr; + iov[0].len = UdpCHeader.Length; + + iov[1].buf = data; + iov[1].len = length; + } + +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (localEndPoint.Family != NetworkFamily.IPC || localEndPoint.nbo_port == 0) + throw new InvalidOperationException(); +#endif + return ipcManager.ReceiveMessageEx(localEndPoint, iov, 2, ref address); + } + } + + public JobHandle ScheduleReceive(T receiver, JobHandle dep) where T : struct, INetworkPacketReceiver + { + var sendJob = new SendUpdate {ipcManager = IPCManager.Instance, ipcQueue = m_IPCQueue}; + var job = new ReceiveJob + {receiver = receiver, ipcManager = IPCManager.Instance, localEndPoint = m_LocalEndPoint[0]}; + dep = job.Schedule(JobHandle.CombineDependencies(dep, IPCManager.ManagerAccessHandle)); + dep = sendJob.Schedule(dep); + IPCManager.ManagerAccessHandle = dep; + return dep; + } + + public int Bind(NetworkEndPoint endpoint) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (endpoint.Family != NetworkFamily.IPC || endpoint.nbo_port == 0) + throw new InvalidOperationException(); +#endif + IPCManager.Instance.ReleaseEndPoint(m_LocalEndPoint[0]); + m_LocalEndPoint[0] = endpoint; + return 0; + } + + public unsafe int SendMessage(network_iovec* iov, int iov_len, ref NetworkEndPoint address) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (m_LocalEndPoint[0].Family != NetworkFamily.IPC || m_LocalEndPoint[0].nbo_port == 0) + throw new InvalidOperationException(); +#endif + return IPCManager.SendMessageEx(m_IPCQueue.AsParallelWriter(), m_LocalEndPoint[0], iov, iov_len, ref address); + } + } +} \ No newline at end of file diff --git a/Runtime/IPCNetworkInterface.cs.meta b/Runtime/IPCNetworkInterface.cs.meta new file mode 100644 index 0000000..da51320 --- /dev/null +++ b/Runtime/IPCNetworkInterface.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 137e5edeb5e8eea4ca03b69eb129165c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/NetworkCompressionModel.cs b/Runtime/NetworkCompressionModel.cs new file mode 100644 index 0000000..c070fc8 --- /dev/null +++ b/Runtime/NetworkCompressionModel.cs @@ -0,0 +1,192 @@ +using System; +using Unity.Collections; + +namespace Unity.Networking.Transport +{ + public struct NetworkCompressionModel : IDisposable + { + internal static readonly byte[] k_BucketSizes = + { + 0, 0, 1, 2, 3, 4, 6, 8, 10, 12, 15, 18, 21, 24, 27, 32 + }; + + internal static readonly uint[] k_BucketOffsets = + { + 0, 1, 2, 4, 8, 16, 32, 96, 352, 1376, 5472, 38240, 300384, 2397536, 19174752, 153392480 + }; + 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 + internal const int k_AlphabetSize = 16; + internal const int k_MaxHuffmanSymbolLength = 6; + + public void Dispose() + { + encodeTable.Dispose(); + decodeTable.Dispose(); + bucketSizes.Dispose(); + bucketOffsets.Dispose(); + } + public NetworkCompressionModel(Allocator allocator) + { + bucketSizes = new NativeArray(k_BucketSizes, allocator); + bucketOffsets = new NativeArray(k_BucketOffsets, allocator); + byte[] modelData = k_DefaultModelData; + + //int numContexts = NetworkConfig.maxContexts; + int numContexts = 1; + byte[,] symbolLengths = new byte[numContexts, k_AlphabetSize]; + + int readOffset = 0; + { + // default model + int defaultModelAlphabetSize = modelData[readOffset++]; +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (defaultModelAlphabetSize != k_AlphabetSize) + throw new InvalidOperationException("The alphabet size of compression models must be " + k_AlphabetSize); +#endif + + for (int i = 0; i < k_AlphabetSize; i++) + { + byte length = modelData[readOffset++]; + for (int context = 0; context < numContexts; context++) + { + symbolLengths[context, i] = length; + } + } + + // other models + int numModels = modelData[readOffset] | (modelData[readOffset + 1] << 8); + readOffset += 2; + for (int model = 0; model < numModels; model++) + { + int context = modelData[readOffset] | (modelData[readOffset + 1] << 8); + readOffset += 2; + + int modelAlphabetSize = modelData[readOffset++]; +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (modelAlphabetSize != k_AlphabetSize) + throw new InvalidOperationException("The alphabet size of compression models must be " + k_AlphabetSize); +#endif + for (int i = 0; i < k_AlphabetSize; i++) + { + byte length = modelData[readOffset++]; + symbolLengths[context, i] = length; + } + } + } + + // generate tables + encodeTable = new NativeArray(numContexts * k_AlphabetSize, allocator); + decodeTable = new NativeArray(numContexts * (1 << k_MaxHuffmanSymbolLength), allocator); + + var tmpSymbolLengths = new byte[k_AlphabetSize]; + var tmpSymbolDecodeTable = new ushort[1 << k_MaxHuffmanSymbolLength]; + var symbolCodes = new byte[k_AlphabetSize]; + + for (int context = 0; context < numContexts; context++) + { + for (int i = 0; i < k_AlphabetSize; i++) + tmpSymbolLengths[i] = symbolLengths[context, i]; + + GenerateHuffmanCodes(symbolCodes, 0, tmpSymbolLengths, 0, k_AlphabetSize, k_MaxHuffmanSymbolLength); + GenerateHuffmanDecodeTable(tmpSymbolDecodeTable, 0, tmpSymbolLengths, symbolCodes, k_AlphabetSize, k_MaxHuffmanSymbolLength); + for (int i = 0; i < k_AlphabetSize; i++) + { + encodeTable[context * k_AlphabetSize + i] = (ushort)((symbolCodes[i] << 8) | symbolLengths[context, i]); + } + for (int i = 0; i < (1 << k_MaxHuffmanSymbolLength); i++) + { + decodeTable[context * (1 << k_MaxHuffmanSymbolLength) + i] = tmpSymbolDecodeTable[i]; + } + } + } + private static void GenerateHuffmanCodes(byte[] symboLCodes, int symbolCodesOffset, byte[] symbolLengths, int symbolLengthsOffset, int alphabetSize, int maxCodeLength) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (alphabetSize > 256 || maxCodeLength > 8) + throw new InvalidOperationException("Can only generate huffman codes up to alphabet size 256 and maximum code length 8"); +#endif + + var lengthCounts = new byte[maxCodeLength + 1]; + var symbolList = new byte[maxCodeLength + 1, alphabetSize]; + + //byte[] symbol_list[(MAX_HUFFMAN_CODE_LENGTH + 1u) * MAX_NUM_HUFFMAN_SYMBOLS]; + for (int symbol = 0; symbol < alphabetSize; symbol++) + { + int length = symbolLengths[symbol + symbolLengthsOffset]; +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (length > maxCodeLength) + throw new InvalidOperationException("Maximum code length exceeded"); +#endif + symbolList[length, lengthCounts[length]++] = (byte)symbol; + } + + uint nextCodeWord = 0; + for (int length = 1; length <= maxCodeLength; length++) + { + int length_count = lengthCounts[length]; + for (int i = 0; i < length_count; i++) + { + int symbol = symbolList[length, i]; +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (symbolLengths[symbol + symbolLengthsOffset] != length) + throw new InvalidOperationException("Incorrect symbol length"); +#endif + symboLCodes[symbol + symbolCodesOffset] = (byte)ReverseBits(nextCodeWord++, length); + } + nextCodeWord <<= 1; + } + } + private static uint ReverseBits(uint value, int num_bits) + { + value = ((value & 0x55555555u) << 1) | ((value & 0xAAAAAAAAu) >> 1); + value = ((value & 0x33333333u) << 2) | ((value & 0xCCCCCCCCu) >> 2); + value = ((value & 0x0F0F0F0Fu) << 4) | ((value & 0xF0F0F0F0u) >> 4); + value = ((value & 0x00FF00FFu) << 8) | ((value & 0xFF00FF00u) >> 8); + value = (value << 16) | (value >> 16); + return value >> (32 - num_bits); + } + + // decode table entries: (symbol << 8) | length + private static void GenerateHuffmanDecodeTable(ushort[] decodeTable, int decodeTableOffset, byte[] symbolLengths, byte[] symbolCodes, int alphabetSize, int maxCodeLength) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (alphabetSize > 256 || maxCodeLength > 8) + throw new InvalidOperationException("Can only generate huffman codes up to alphabet size 256 and maximum code length 8"); +#endif + + uint maxCode = 1u << maxCodeLength; + for (int symbol = 0; symbol < alphabetSize; symbol++) + { + int length = symbolLengths[symbol]; +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (length > maxCodeLength) + throw new InvalidOperationException("Maximum code length exceeded"); +#endif + if (length > 0) + { + uint code = symbolCodes[symbol]; + uint step = 1u << length; + do + { + decodeTable[decodeTableOffset + code] = (ushort)(symbol << 8 | length); + code += step; + } while (code < maxCode); + } + } + } + [ReadOnly] public NativeArray encodeTable; + [ReadOnly] public NativeArray decodeTable; + [ReadOnly] public NativeArray bucketSizes; + [ReadOnly] public NativeArray bucketOffsets; + public int CalculateBucket(uint value) + { + int bucketIndex = 0; + while (bucketIndex + 1 < bucketOffsets.Length && value >= bucketOffsets[bucketIndex + 1]) // TODO: use CountLeadingZeros to do this in constant time + bucketIndex++; + + return bucketIndex; + } + } +} \ No newline at end of file diff --git a/Runtime/NetworkCompressionModel.cs.meta b/Runtime/NetworkCompressionModel.cs.meta new file mode 100644 index 0000000..1977618 --- /dev/null +++ b/Runtime/NetworkCompressionModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8f1beb626cc4d46cea7be796acb882b8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/NetworkConnection.cs b/Runtime/NetworkConnection.cs new file mode 100644 index 0000000..f5d883e --- /dev/null +++ b/Runtime/NetworkConnection.cs @@ -0,0 +1,115 @@ +namespace Unity.Networking.Transport +{ + /// + /// The NetworkConnection is a struct that hold all information needed by the driver to link it with a virtual + /// connection. The NetworkConnection is a public representation of a connection. + /// + public struct NetworkConnection + { + internal int m_NetworkId; + internal int m_NetworkVersion; + + /// + /// ConnectionState enumerates available connection states a connection can have. + /// + public enum State + { + /// Indicates the connection is disconnected + Disconnected, + /// Indicates the connection is trying to connect. + Connecting, + /// Indicates the connection is waiting for a connection response. + AwaitingResponse, + /// Indicates the connection is connected.. + Connected + } + + /// + /// Disconnects a virtual connection and marks it for deletion. This connection will be removed on next the next frame. + /// + /// The driver that owns the virtual connection. + public int Disconnect(T driver) where T : struct, INetworkDriver + { + return driver.Disconnect(this); + } + + /// + /// Receive an event for this specific connection. Should be called until it returns , even if the socket is disconnected. + /// + /// The driver that owns the virtual connection. + /// A DataStreamReader, that will only be populated if a + /// event was received. + /// + public NetworkEvent.Type PopEvent(T driver, out DataStreamReader stream) where T : struct, INetworkDriver + { + return driver.PopEventForConnection(this, out stream); + } + + /// + /// Send data to the remote endpoint. + /// + /// The driver that owns the virtual connection. + /// A valid filled with the data you want to send. + public int Send(T driver, DataStreamWriter bs) where T : struct, INetworkDriver + { + return driver.Send(NetworkPipeline.Null, this, bs); + } + + public int Send(T driver, NetworkPipeline pipeline, DataStreamWriter bs) where T : struct, INetworkDriver + { + return driver.Send(pipeline, this, bs); + } + + /// + /// Close an active NetworkConnection, similar to . + /// + /// The driver that owns the virtual connection. + public int Close(T driver) where T : struct, INetworkDriver + { + if (m_NetworkId >= 0) + return driver.Disconnect(this); + return -1; + } + + /// + /// Check to see if a NetworkConnection is Created. + /// + /// `true` if the NetworkConnection has been correctly created by a call to + /// or + public bool IsCreated + { + get { return m_NetworkVersion != 0; } + } + + public State GetState(T driver) where T : struct, INetworkDriver + { + return driver.GetConnectionState(this); + } + + public static bool operator ==(NetworkConnection lhs, NetworkConnection rhs) + { + return lhs.m_NetworkId == rhs.m_NetworkId && lhs.m_NetworkVersion == rhs.m_NetworkVersion; + } + + public static bool operator !=(NetworkConnection lhs, NetworkConnection rhs) + { + return lhs.m_NetworkId != rhs.m_NetworkId || lhs.m_NetworkVersion != rhs.m_NetworkVersion; + } + + public override bool Equals(object o) + { + return this == (NetworkConnection)o; + } + public bool Equals(NetworkConnection o) + { + return this == o; + } + + public override int GetHashCode() + { + return (m_NetworkId << 8) ^ m_NetworkVersion; + } + + public int InternalId => m_NetworkId; + } +} \ No newline at end of file diff --git a/Runtime/NetworkConnection.cs.meta b/Runtime/NetworkConnection.cs.meta new file mode 100644 index 0000000..f34e10d --- /dev/null +++ b/Runtime/NetworkConnection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6823092a5f3f3ce4b858282568abac60 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/NetworkDriver.cs b/Runtime/NetworkDriver.cs new file mode 100644 index 0000000..4bf05f4 --- /dev/null +++ b/Runtime/NetworkDriver.cs @@ -0,0 +1,1180 @@ +using System; +using System.Diagnostics; +using Unity.Burst; +using Unity.Networking.Transport.LowLevel.Unsafe; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Networking.Transport.Protocols; +using Unity.Jobs; +using UnityEngine.Assertions; +using Random = System.Random; + +namespace Unity.Networking.Transport +{ + /// + /// The GenericNetworkDriver is an implementation of Virtual Connections over any transport. + /// + /// Basic usage: + /// + /// var driver = new GenericNetworkDriver<IPv4UDPSocket>(new INetworkParameter[0]); + /// + /// + /// Should be of type , the currently available NetworkInterfaces + /// are , or . + /// + public struct GenericNetworkDriver : INetworkDriver, INetworkPacketReceiver, INetworkPipelineReceiver where T : struct, INetworkInterface where TNetworkPipelineStageCollection : struct, INetworkPipelineStageCollection + { + /// + /// Create a Concurrent Copy of the NetworkDriver. + /// + public Concurrent ToConcurrent() + { + Concurrent concurrent; + concurrent.m_EventQueue = m_EventQueue.ToConcurrent(); + concurrent.m_ConnectionList = m_ConnectionList; + concurrent.m_DataStream = m_DataStream; + concurrent.m_NetworkInterface = m_NetworkInterface; + concurrent.m_PipelineProcessor = m_PipelineProcessor.ToConcurrent(); + concurrent.m_DefaultHeaderFlags = m_DefaultHeaderFlags; + concurrent.m_Logger = m_Logger.ToConcurrent(); + return concurrent; + } + + private Concurrent ToConcurrentSendOnly() + { + Concurrent concurrent; + concurrent.m_EventQueue = default(NetworkEventQueue.Concurrent); + concurrent.m_ConnectionList = m_ConnectionList; + concurrent.m_DataStream = default(DataStreamWriter); + concurrent.m_NetworkInterface = m_NetworkInterface; + concurrent.m_PipelineProcessor = m_PipelineProcessor.ToConcurrent(); + concurrent.m_DefaultHeaderFlags = m_DefaultHeaderFlags; + concurrent.m_Logger = m_Logger.ToConcurrent(); + return concurrent; + } + + /// + /// The Concurrent struct is used to create an Concurrent instance of the GenericNetworkDriver. + /// + public struct Concurrent : INetworkPipelineSender + { + public NetworkLogger.Concurrent m_Logger; + public NetworkEvent.Type PopEventForConnection(NetworkConnection connectionId, out DataStreamReader slice) + { + int offset, size; + slice = 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); + if (size > 0) + slice = new DataStreamReader(m_DataStream, offset, size); + return type; + } + + public unsafe int Send(NetworkPipeline pipe, NetworkConnection id, DataStreamWriter strm) + { + if (strm.IsCreated && strm.Length > 0) + { + return Send(pipe, id, (IntPtr) strm.GetUnsafeReadOnlyPtr(), strm.Length); + } + return 0; + } + + public unsafe int Send(NetworkPipeline pipe, NetworkConnection id, IntPtr data, int len) + { + if (pipe.Id > 0) + { + m_DefaultHeaderFlags = UdpCHeader.HeaderFlags.HasPipeline; + var slice = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice((void*) data, 1, len); +#if ENABLE_UNITY_COLLECTIONS_CHECKS + var safety = AtomicSafetyHandle.Create(); + AtomicSafetyHandle.SetAllowSecondaryVersionWriting(safety, false); + AtomicSafetyHandle.UseSecondaryVersion(ref safety); + NativeSliceUnsafeUtility.SetAtomicSafetyHandle(ref slice, safety); +#endif + var retval = m_PipelineProcessor.Send(this, pipe, id, slice); +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.Release(safety); +#endif + m_DefaultHeaderFlags = 0; + return retval; + } + if (id.m_NetworkId < 0 || id.m_NetworkId >= m_ConnectionList.Length) + return 0; + var connection = m_ConnectionList[id.m_NetworkId]; + if (connection.Version != id.m_NetworkVersion) + return 0; + +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (connection.State == NetworkConnection.State.Connecting) + throw new InvalidOperationException("Cannot send data while connecting"); +#endif + + // update last attempt; + var header = new UdpCHeader + { + Type = (int) UdpCProtocol.Data, + SessionToken = connection.SendToken, + Flags = m_DefaultHeaderFlags + }; + + + var iov = stackalloc network_iovec[3]; + iov[0].buf = header.Data; + iov[0].len = UdpCHeader.Length; + + iov[1].buf = (void*)data; + iov[1].len = len; + + iov[2].buf = &connection.ReceiveToken; + iov[2].len = 2; + + if (connection.DidReceiveData == 0) + { + header.Flags |= UdpCHeader.HeaderFlags.HasConnectToken; + return m_NetworkInterface.SendMessage(iov, 3, ref connection.Address); + } + return m_NetworkInterface.SendMessage(iov, 2, ref connection.Address); + } + public unsafe int Send(NetworkConnection id, network_iovec* dataIov, int dataIovLen) + { + if (id.m_NetworkId < 0 || id.m_NetworkId >= m_ConnectionList.Length) + return 0; + var connection = m_ConnectionList[id.m_NetworkId]; + if (connection.Version != id.m_NetworkVersion) + return 0; + +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (connection.State == NetworkConnection.State.Connecting) + throw new InvalidOperationException("Cannot send data while connecting"); +#endif + + // update last attempt; + var header = new UdpCHeader + { + Type = (int) UdpCProtocol.Data, + SessionToken = connection.SendToken, + Flags = m_DefaultHeaderFlags + }; + + var iov = stackalloc network_iovec[2+dataIovLen]; + iov[0].buf = header.Data; + iov[0].len = UdpCHeader.Length; + + for (int i = 0; i < dataIovLen; ++i) + iov[1 + i] = dataIov[i]; + + iov[1 + dataIovLen].buf = &connection.ReceiveToken; + iov[1 + dataIovLen].len = 2; + + if (connection.DidReceiveData == 0) + { + header.Flags |= UdpCHeader.HeaderFlags.HasConnectToken; + return m_NetworkInterface.SendMessage(iov, 2 + dataIovLen, ref connection.Address); + } + return m_NetworkInterface.SendMessage(iov, 1 + dataIovLen, ref connection.Address); + } + public NetworkConnection.State GetConnectionState(NetworkConnection id) + { + if (id.m_NetworkId < 0 || id.m_NetworkId >= m_ConnectionList.Length) + return NetworkConnection.State.Disconnected; + var connection = m_ConnectionList[id.m_NetworkId]; + if (connection.Version != id.m_NetworkVersion) + return NetworkConnection.State.Disconnected; + return connection.State; + } + + internal NetworkEventQueue.Concurrent m_EventQueue; + [ReadOnly] internal NativeList m_ConnectionList; + [ReadOnly] internal DataStreamWriter m_DataStream; + internal T m_NetworkInterface; + internal NetworkPipelineProcessor.Concurrent m_PipelineProcessor; + internal UdpCHeader.HeaderFlags m_DefaultHeaderFlags; + } + + internal struct Connection + { + public NetworkEndPoint Address; + public long LastAttempt; + public int Id; + public int Version; + public int Attempts; + public NetworkConnection.State State; + public ushort ReceiveToken; + public ushort SendToken; + public byte DidReceiveData; + + public static bool operator ==(Connection lhs, Connection rhs) + { + return lhs.Id == rhs.Id && lhs.Version == rhs.Version && lhs.Address == rhs.Address; + } + + public static bool operator !=(Connection lhs, Connection rhs) + { + return lhs.Id != rhs.Id || lhs.Version != rhs.Version || lhs.Address != rhs.Address; + } + + public override bool Equals(object compare) + { + return this == (Connection) compare; + } + + public static Connection Null => new Connection() {Id = 0, Version = 0}; + + public override int GetHashCode() + { + return Id; + } + + public bool Equals(Connection connection) + { + return connection.Id == Id && connection.Version == Version && connection.Address == Address; + } + } + + // internal variables ::::::::::::::::::::::::::::::::::::::::::::::::: + T m_NetworkInterface; + + NetworkEventQueue m_EventQueue; + + private NetworkLogger m_Logger; + + NativeQueue m_FreeList; + NativeQueue m_NetworkAcceptQueue; + NativeList m_ConnectionList; + NativeArray m_InternalState; + NativeQueue m_PendingFree; + NativeArray m_SessionIdCounter; + NativeArray m_ErrorCodes; + enum ErrorCodeType + { + ReceiveError = 0, + NumErrorCodes + } + +#pragma warning disable 649 + struct Parameters + { + public NetworkDataStreamParameter dataStream; + public NetworkConfigParameter config; + + public Parameters(params INetworkParameter[] param) + { + config = new NetworkConfigParameter { + maxConnectAttempts = NetworkParameterConstants.MaxConnectAttempts, + connectTimeoutMS = NetworkParameterConstants.ConnectTimeoutMS, + disconnectTimeoutMS = NetworkParameterConstants.DisconnectTimeoutMS, + maxFrameTimeMS = 0 + }; + dataStream = default(NetworkDataStreamParameter); + + for (int i = 0; i < param.Length; ++i) + { + if (param[i] is NetworkConfigParameter) + config = (NetworkConfigParameter)param[i]; + else if (param[i] is NetworkDataStreamParameter) + dataStream = (NetworkDataStreamParameter)param[i]; + } + } + } +#pragma warning restore 649 + + private Parameters m_NetworkParams; + private DataStreamWriter m_DataStream; + private NetworkPipelineProcessor m_PipelineProcessor; + private UdpCHeader.HeaderFlags m_DefaultHeaderFlags; + + private long m_updateTime; + private long m_updateTimeAdjustment; + + // properties ::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + private const int InternalStateListening = 0; + private const int InternalStateBound = 1; + + public bool Listening + { + get { return (m_InternalState[InternalStateListening] != 0); } + internal set { m_InternalState[InternalStateListening] = value ? 1 : 0; } + } + + enum StringType + { + ReceiveError, + ResetErrorCount, + ResetErrorConnection, + ResetErrorListening, + PipelineOverflow, + ConnectionRequestSendError, + ConnectionAcceptSendError, + DisconnectSendError, + ConnectionRequestWithPipeline, + ConnectionAcceptWithPipeline, + DisconnectWithPipeline, + AcceptWithoutToken, + ImplicitAcceptWithoutToken, + NumStrings + } + + private static readonly string[] StringValue = + { + "Error on receive ", + "Resetting event queue with pending events (Count=", + ", ConnectionID=", + ") Listening: ", + "A lot of pipeline updates have been queued, possibly too many being scheduled in pipeline logic, queue count: ", + "Failed to send a ConnectionRequest package", + "Failed to send a ConnectionAccept package", + "Failed to send a Disconnect package", + "Received an invalid ConnectionRequest with pipeline", + "Received an invalid ConnectionAccept with pipeline", + "Received an invalid Disconnect with pipeline", + "Received an invalid ConnectionAccept without a token", + "Received an invalid implicit connection accept without a token", + }; + + [ReadOnly] private NativeArray m_StringDB; + /// + /// Constructor for GenericNetworkDriver. + /// + /// + /// An array of INetworkParameter. There are currently only two , + /// the and the . + /// + public GenericNetworkDriver(params INetworkParameter[] param) + { + m_Logger = new NetworkLogger(NetworkLogger.LogLevel.Debug); + m_StringDB = new NativeArray((int)StringType.NumStrings, Allocator.Persistent); + if (StringValue.Length != (int)StringType.NumStrings) + throw new InvalidOperationException("Bad string database"); + for (int i = 0; i < (int) StringType.NumStrings; ++i) + { + m_StringDB[i] = new NativeString512(StringValue[i]); + } + m_updateTime = Stopwatch.GetTimestamp() / TimeSpan.TicksPerMillisecond; + m_updateTimeAdjustment = 0; + m_NetworkParams = new Parameters(param); + + int initialStreamSize = m_NetworkParams.dataStream.size; + if (initialStreamSize == 0) + initialStreamSize = NetworkParameterConstants.DriverDataStreamSize; + + m_DataStream = new DataStreamWriter(initialStreamSize, Allocator.Persistent); + m_PipelineProcessor = new NetworkPipelineProcessor(param); // Initial capacity might need to be bigger than 0 + m_DefaultHeaderFlags = 0; + + m_NetworkInterface = new T(); + m_NetworkInterface.Initialize(); + + m_NetworkAcceptQueue = new NativeQueue(Allocator.Persistent); + + m_ConnectionList = new NativeList(1, Allocator.Persistent); + + m_FreeList = new NativeQueue(Allocator.Persistent); + m_EventQueue = new NetworkEventQueue(NetworkParameterConstants.InitialEventQueueSize); + + 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_ErrorCodes = new NativeArray((int)ErrorCodeType.NumErrorCodes, Allocator.Persistent); + ReceiveCount = 0; + Listening = false; + } + + // interface implementation ::::::::::::::::::::::::::::::::::::::::::: + public void Dispose() + { + m_Logger.Dispose(); + m_StringDB.Dispose(); + m_NetworkInterface.Dispose(); + m_DataStream.Dispose(); + m_PipelineProcessor.Dispose(); + + m_EventQueue.Dispose(); + + m_NetworkAcceptQueue.Dispose(); + m_ConnectionList.Dispose(); + m_FreeList.Dispose(); + m_InternalState.Dispose(); + m_PendingFree.Dispose(); + m_ReceiveCount.Dispose(); + m_SessionIdCounter.Dispose(); + m_ErrorCodes.Dispose(); + } + + public bool IsCreated => m_InternalState.IsCreated; + + [BurstCompile] + struct UpdateJob : IJob + { + public GenericNetworkDriver driver; + + public void Execute() + { + driver.InternalUpdate(); + } + } + struct LogJob : IJob + { + public NetworkLogger logger; + + public void Execute() + { + logger.FlushPending(); +#if ENABLE_UNITY_COLLECTIONS_CHECKS + logger.DumpToConsole(); +#else + logger.Clear(); +#endif + } + } + +#if ENABLE_UNITY_COLLECTIONS_CHECKS + struct MissingClearMessage : INetworkLogMessage + { + public NativeArray stringDB; + public int count; + public int connection; + public int listening; + public void Print(ref NativeString512 msg) + { + var str = stringDB[(int) StringType.ResetErrorCount]; + msg.AppendFrom(str); + msg.Append(count); + str = stringDB[(int) StringType.ResetErrorConnection]; + msg.AppendFrom(str); + msg.Append(connection); + str = stringDB[(int) StringType.ResetErrorListening]; + msg.AppendFrom(str); + msg.Append(listening); + } + } +#endif + struct ClearEventQueue : IJob + { + public DataStreamWriter dataStream; + public NetworkEventQueue eventQueue; +#if ENABLE_UNITY_COLLECTIONS_CHECKS + public NetworkLogger logger; + public NativeArray stringDB; + [ReadOnly] public NativeList connectionList; + [ReadOnly] public NativeArray internalState; +#endif + public void Execute() + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + for (int i = 0; i < connectionList.Length; ++i) + { + int conCount = eventQueue.GetCountForConnection(i); + if (conCount != 0 && connectionList[i].State != NetworkConnection.State.Disconnected) + { + var msg = new MissingClearMessage { stringDB = stringDB, count = conCount, connection = i, listening = internalState[InternalStateListening]}; + logger.Log(NetworkLogger.LogLevel.Error, msg); + } + } +#endif + eventQueue.Clear(); + dataStream.Clear(); + } + } + + public JobHandle ScheduleUpdate(JobHandle dep = default(JobHandle)) + { + long timeNow = Stopwatch.GetTimestamp() / TimeSpan.TicksPerMillisecond - m_updateTimeAdjustment; + if (m_NetworkParams.config.maxFrameTimeMS > 0 && (timeNow - m_updateTime) > m_NetworkParams.config.maxFrameTimeMS) + { + m_updateTimeAdjustment += (timeNow - m_updateTime) - m_NetworkParams.config.maxFrameTimeMS; + timeNow = m_updateTime + m_NetworkParams.config.maxFrameTimeMS; + } + m_updateTime = timeNow; + var job = new UpdateJob {driver = this}; + JobHandle handle; + var clearJob = new ClearEventQueue + { + dataStream = m_DataStream, + eventQueue = m_EventQueue, +#if ENABLE_UNITY_COLLECTIONS_CHECKS + logger = m_Logger, + stringDB = m_StringDB, + connectionList = m_ConnectionList, + internalState = m_InternalState +#endif + }; + handle = clearJob.Schedule(dep); + handle = job.Schedule(handle); + handle = m_NetworkInterface.ScheduleReceive(this, handle); + var logJob = new LogJob {logger = m_Logger}; + handle = logJob.Schedule(handle); + return handle; + } + + struct PipelineOverflowMessage : INetworkLogMessage + { + public NativeArray stringDB; + public int count; + public void Print(ref NativeString512 msg) + { + var str = stringDB[(int)StringType.PipelineOverflow]; + msg.AppendFrom(str); + msg.Append(count); + } + } + void InternalUpdate() + { + m_PipelineProcessor.Timestamp = m_updateTime; + int free; + while (m_PendingFree.TryDequeue(out free)) + { + int ver = m_ConnectionList[free].Version + 1; + if (ver == 0) + ver = 1; + m_ConnectionList[free] = new Connection {Id = free, Version = ver}; + m_FreeList.Enqueue(free); + } + + CheckTimeouts(); + + int updateCount; + m_PipelineProcessor.UpdateReceive(this, out updateCount); + + // TODO: Find a good way to establish a good limit (connections*pipelines/2?) + if (updateCount > 64) + { + var msg = new PipelineOverflowMessage { stringDB = m_StringDB, count = updateCount }; + m_Logger.Log(NetworkLogger.LogLevel.Warning, msg); + } + + m_DefaultHeaderFlags = UdpCHeader.HeaderFlags.HasPipeline; + m_PipelineProcessor.UpdateSend(ToConcurrentSendOnly(), out updateCount); + if (updateCount > 64) + { + var msg = new PipelineOverflowMessage { stringDB = m_StringDB, count = updateCount }; + m_Logger.Log(NetworkLogger.LogLevel.Warning, msg); + } + + m_DefaultHeaderFlags = 0; + } + + public NetworkPipeline CreatePipeline(params Type[] stages) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (!m_InternalState.IsCreated) + throw new InvalidOperationException( + "Driver must be constructed with a populated or empty INetworkParameter params list"); + if (m_ConnectionList.Length > 0) + throw new InvalidOperationException( + "Pipelines cannot be created after establishing connections"); +#endif + return m_PipelineProcessor.CreatePipeline(stages); + } + + public int Bind(NetworkEndPoint endpoint) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (!m_InternalState.IsCreated) + throw new InvalidOperationException( + "Driver must be constructed with a populated or empty INetworkParameter params list"); + if (m_InternalState[InternalStateBound] != 0) + throw new InvalidOperationException( + "Bind can only be called once per NetworkDriver"); + if (m_ConnectionList.Length > 0) + throw new InvalidOperationException( + "Bind cannot be called after establishing connections"); +#endif + var ret = m_NetworkInterface.Bind(endpoint); + if (ret == 0) + m_InternalState[InternalStateBound] = 1; + return ret; + } + + public int Listen() + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (!m_InternalState.IsCreated) + throw new InvalidOperationException( + "Driver must be constructed with a populated or empty INetworkParameter params list"); + if (Listening) + throw new InvalidOperationException( + "Listen can only be called once per NetworkDriver"); + if (m_InternalState[InternalStateBound] == 0) + throw new InvalidOperationException( + "Listen can only be called after a successful call to Bind"); +#endif + if (m_InternalState[InternalStateBound] == 0) + return -1; + Listening = true; + return 0; + } + + public NetworkConnection Accept() + { + if (!Listening) + return default(NetworkConnection); + + int id; + if (!m_NetworkAcceptQueue.TryDequeue(out id)) + return default(NetworkConnection); + return new NetworkConnection {m_NetworkId = id, m_NetworkVersion = m_ConnectionList[id].Version}; + } + + public NetworkConnection Connect(NetworkEndPoint endpoint) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (!m_InternalState.IsCreated) + throw new InvalidOperationException( + "Driver must be constructed with a populated or empty INetworkParameter params list"); +#endif + int id; + if (!m_FreeList.TryDequeue(out id)) + { + id = m_ConnectionList.Length; + m_ConnectionList.Add(new Connection{Id = id, Version = 1}); + } + + int ver = m_ConnectionList[id].Version; + var c = new Connection + { + Id = id, + Version = ver, + State = NetworkConnection.State.Connecting, + Address = endpoint, + Attempts = 1, + LastAttempt = m_updateTime, + SendToken = 0, + ReceiveToken = m_SessionIdCounter[0] + }; + m_SessionIdCounter[0] = (ushort)(m_SessionIdCounter[0] + 1); + + m_ConnectionList[id] = c; + var netcon = new NetworkConnection {m_NetworkId = id, m_NetworkVersion = ver}; + SendConnectionRequest(c); + m_PipelineProcessor.initializeConnection(netcon); + + return netcon; + } + + void SendConnectionRequest(Connection c) + { + var header = new UdpCHeader + { + Type = (int) UdpCProtocol.ConnectionRequest, + SessionToken = c.ReceiveToken, + Flags = m_DefaultHeaderFlags + }; + + unsafe + { + network_iovec iov; + iov.buf = header.Data; + iov.len = UdpCHeader.Length; + if (m_NetworkInterface.SendMessage(&iov, 1, ref c.Address) <= 0) + { + m_Logger.Log(NetworkLogger.LogLevel.Error, m_StringDB[(int)StringType.ConnectionRequestSendError]); + } + } + } + + public int Disconnect(NetworkConnection id) + { + Connection connection; + if ((connection = GetConnection(id)) == Connection.Null) + return 0; + + if (connection.State == NetworkConnection.State.Connected) + { + if (SendPacket(UdpCProtocol.Disconnect, id) <= 0) + { + m_Logger.Log(NetworkLogger.LogLevel.Error, m_StringDB[(int)StringType.DisconnectSendError]); + } + } + RemoveConnection(connection); + + return 0; + } + + public void GetPipelineBuffers(Type pipelineType, NetworkConnection connection, ref NativeSlice readProcessingBuffer, ref NativeSlice writeProcessingBuffer, ref NativeSlice sharedBuffer) + { + m_PipelineProcessor.GetPipelineBuffers(pipelineType, connection, ref readProcessingBuffer, ref writeProcessingBuffer, ref sharedBuffer); + } + + public void GetPipelineBuffers(NetworkPipeline pipeline, int stageId, NetworkConnection connection, ref NativeSlice readProcessingBuffer, ref NativeSlice writeProcessingBuffer, ref NativeSlice sharedBuffer) + { + m_PipelineProcessor.GetPipelineBuffers(pipeline, stageId, connection, ref readProcessingBuffer, ref writeProcessingBuffer, ref sharedBuffer); + } + + public NetworkConnection.State GetConnectionState(NetworkConnection con) + { + Connection connection; + if ((connection = GetConnection(con)) == Connection.Null) + return NetworkConnection.State.Disconnected; + return connection.State; + } + + public NetworkEndPoint RemoteEndPoint(NetworkConnection id) + { + if (id == default(NetworkConnection)) + return m_NetworkInterface.RemoteEndPoint; + + Connection connection; + if ((connection = GetConnection(id)) == Connection.Null) + return default(NetworkEndPoint); + return connection.Address; + } + + public NetworkEndPoint LocalEndPoint() + { + return m_NetworkInterface.LocalEndPoint; + } + + public int Send(NetworkPipeline pipe, NetworkConnection id, DataStreamWriter strm) + { + unsafe + { + return Send(pipe, id, (IntPtr) strm.GetUnsafeReadOnlyPtr(), strm.Length); + } + } + + public unsafe int Send(NetworkPipeline pipe, NetworkConnection id, IntPtr data, int len) + { + return ToConcurrentSendOnly().Send(pipe, id, data, len); + } + + public NetworkEvent.Type PopEvent(out NetworkConnection con, out DataStreamReader slice) + { + int offset, size; + slice = default(DataStreamReader); + int id; + var type = m_EventQueue.PopEvent(out id, out offset, out size); + if (size > 0) + slice = new DataStreamReader(m_DataStream, offset, size); + con = id < 0 + ? default(NetworkConnection) + : new NetworkConnection {m_NetworkId = id, m_NetworkVersion = m_ConnectionList[id].Version}; + return type; + } + + public NetworkEvent.Type PopEventForConnection(NetworkConnection connectionId, out DataStreamReader slice) + { + int offset, size; + slice = 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); + if (size > 0) + slice = new DataStreamReader(m_DataStream, offset, size); + return type; + } + + // internal helper functions :::::::::::::::::::::::::::::::::::::::::: + void AddConnection(int id) + { + m_EventQueue.PushEvent(new NetworkEvent {connectionId = id, type = NetworkEvent.Type.Connect}); + } + + void AddDisconnection(int id) + { + m_EventQueue.PushEvent(new NetworkEvent {connectionId = id, type = NetworkEvent.Type.Disconnect}); + } + + Connection GetConnection(NetworkConnection id) + { + var con = m_ConnectionList[id.m_NetworkId]; + if (con.Version != id.m_NetworkVersion) + return Connection.Null; + return con; + } + + Connection GetConnection(NetworkEndPoint address, ushort sessionId) + { + for (int i = 0; i < m_ConnectionList.Length; i++) + { + if (address == m_ConnectionList[i].Address && m_ConnectionList[i].ReceiveToken == sessionId ) + return m_ConnectionList[i]; + } + + return Connection.Null; + } + + Connection GetNewConnection(NetworkEndPoint address, ushort sessionId) + { + for (int i = 0; i < m_ConnectionList.Length; i++) + { + if (address == m_ConnectionList[i].Address && m_ConnectionList[i].SendToken == sessionId ) + return m_ConnectionList[i]; + } + + return Connection.Null; + } + + void SetConnection(Connection connection) + { + m_ConnectionList[connection.Id] = connection; + } + + bool RemoveConnection(Connection connection) + { + if (connection.State != NetworkConnection.State.Disconnected && connection == m_ConnectionList[connection.Id]) + { + connection.State = NetworkConnection.State.Disconnected; + m_ConnectionList[connection.Id] = connection; + m_PendingFree.Enqueue(connection.Id); + + return true; + } + + return false; + } + + bool UpdateConnection(Connection connection) + { + if (connection == m_ConnectionList[connection.Id]) + { + SetConnection(connection); + return true; + } + + return false; + } + + unsafe int SendPacket(UdpCProtocol type, Connection connection) + { + var header = new UdpCHeader + { + Type = (byte) type, + SessionToken = connection.SendToken, + Flags = m_DefaultHeaderFlags + }; + + var iov = stackalloc network_iovec[2]; + iov[0].buf = header.Data; + iov[0].len = UdpCHeader.Length; + iov[1].buf = &connection.ReceiveToken; + iov[1].len = 2; + if (connection.DidReceiveData == 0) + { + header.Flags |= UdpCHeader.HeaderFlags.HasConnectToken; + return m_NetworkInterface.SendMessage(iov, 2, ref connection.Address); + } + return m_NetworkInterface.SendMessage(iov, 1, ref connection.Address); + } + + int SendPacket(UdpCProtocol type, NetworkConnection id) + { + Connection connection; + if ((connection = GetConnection(id)) == Connection.Null) + return 0; + + return SendPacket(type, connection); + } + + void CheckTimeouts() + { + for (int i = 0; i < m_ConnectionList.Length; ++i) + { + var connection = m_ConnectionList[i]; + if (connection == Connection.Null) + continue; + + long now = m_updateTime; + + var netcon = new NetworkConnection {m_NetworkId = connection.Id, m_NetworkVersion = connection.Version}; + if ((connection.State == NetworkConnection.State.Connecting || + connection.State == NetworkConnection.State.AwaitingResponse) && + now - connection.LastAttempt > m_NetworkParams.config.connectTimeoutMS) + { + if (connection.Attempts >= m_NetworkParams.config.maxConnectAttempts) + { + RemoveConnection(connection); + AddDisconnection(connection.Id); + continue; + } + + connection.Attempts = ++connection.Attempts; + connection.LastAttempt = now; + SetConnection(connection); + + if (connection.State == NetworkConnection.State.Connecting) + SendConnectionRequest(connection); + else + { + if (SendPacket(UdpCProtocol.ConnectionAccept, netcon) <= 0) + { + m_Logger.Log(NetworkLogger.LogLevel.Error, m_StringDB[(int)StringType.ConnectionAcceptSendError]); + } + } + } + + if (connection.State == NetworkConnection.State.Connected && + now - connection.LastAttempt > m_NetworkParams.config.disconnectTimeoutMS) + { + Disconnect(netcon); + AddDisconnection(connection.Id); + } + } + } + + public DataStreamWriter GetDataStream() + { + return m_DataStream; + } + + struct ReceiveErrorMessage : INetworkLogMessage + { + public NativeArray stringDB; + public int errorCode; + public void Print(ref NativeString512 msg) + { + var str = stringDB[(int) StringType.ReceiveError]; + msg.AppendFrom(str); + msg.Append(errorCode); + } + } + public int ReceiveErrorCode + { + get { return m_ErrorCodes[(int)ErrorCodeType.ReceiveError]; } + set + { + if (value != 0) + { + var msg = new ReceiveErrorMessage {stringDB = m_StringDB, errorCode = value}; + m_Logger.Log(NetworkLogger.LogLevel.Error, msg); + } + + m_ErrorCodes[(int)ErrorCodeType.ReceiveError] = value; + } + } + + private NativeArray m_ReceiveCount; + public int ReceiveCount { + get { return m_ReceiveCount[0]; } + set { m_ReceiveCount[0] = value; } + } + + public bool DynamicDataStreamSize() + { + return m_NetworkParams.dataStream.size == 0; + } + + public unsafe int AppendPacket(NetworkEndPoint address, UdpCHeader header, int dataLen) + { + int count = 0; + switch ((UdpCProtocol) header.Type) + { + case UdpCProtocol.ConnectionRequest: + { + if (!Listening) + return 0; + if ((header.Flags&UdpCHeader.HeaderFlags.HasPipeline) != 0) + { + m_Logger.Log(NetworkLogger.LogLevel.Error, m_StringDB[(int)StringType.ConnectionRequestWithPipeline]); + return 0; + } + + Connection c; + if ((c = GetNewConnection(address, header.SessionToken)) == Connection.Null || c.State == NetworkConnection.State.Disconnected) + { + int id; + var sessionId = m_SessionIdCounter[0]; + m_SessionIdCounter[0] = (ushort) (m_SessionIdCounter[0] + 1); + if (!m_FreeList.TryDequeue(out id)) + { + id = m_ConnectionList.Length; + m_ConnectionList.Add(new Connection{Id = id, Version = 1}); + } + + int ver = m_ConnectionList[id].Version; + c = new Connection + { + Id = id, + Version = ver, + ReceiveToken = sessionId, + SendToken = header.SessionToken, + State = NetworkConnection.State.Connected, + Address = address, + Attempts = 1, + LastAttempt = m_updateTime + }; + SetConnection(c); + m_PipelineProcessor.initializeConnection(new NetworkConnection{m_NetworkId = id, m_NetworkVersion = c.Version}); + m_NetworkAcceptQueue.Enqueue(id); + count++; + } + else + { + c.Attempts++; + c.LastAttempt = m_updateTime; + SetConnection(c); + } + + if (SendPacket(UdpCProtocol.ConnectionAccept, + new NetworkConnection {m_NetworkId = c.Id, m_NetworkVersion = c.Version}) <= 0) + { + m_Logger.Log(NetworkLogger.LogLevel.Error, m_StringDB[(int)StringType.ConnectionAcceptSendError]); + } + } + break; + case UdpCProtocol.ConnectionReject: + { + // m_EventQ.Enqueue(Id, (int)NetworkEvent.Connect); + } + break; + case UdpCProtocol.ConnectionAccept: + { + if ((header.Flags&UdpCHeader.HeaderFlags.HasConnectToken) == 0) + { + m_Logger.Log(NetworkLogger.LogLevel.Error, m_StringDB[(int)StringType.AcceptWithoutToken]); + return 0; + } + if ((header.Flags&UdpCHeader.HeaderFlags.HasPipeline) != 0) + { + m_Logger.Log(NetworkLogger.LogLevel.Error, m_StringDB[(int)StringType.ConnectionAcceptWithPipeline]); + return 0; + } + + Connection c = GetConnection(address, header.SessionToken); + if (c != Connection.Null) + { + c.DidReceiveData = 1; + + if (c.State == NetworkConnection.State.Connected) + { + //DebugLog("Dropping connect request for an already connected endpoint [" + address + "]"); + return 0; + } + + if (c.State == NetworkConnection.State.Connecting) + { + var sliceOffset = m_DataStream.Length; + m_DataStream.WriteBytesWithUnsafePointer(2); + var dataStreamReader = new DataStreamReader(m_DataStream, sliceOffset, 2); + var context = default(DataStreamReader.Context); + c.SendToken = dataStreamReader.ReadUShort(ref context); + m_DataStream.WriteBytesWithUnsafePointer(-2); + + c.State = NetworkConnection.State.Connected; + UpdateConnection(c); + AddConnection(c.Id); + count++; + } + } + } + break; + case UdpCProtocol.Disconnect: + { + if ((header.Flags&UdpCHeader.HeaderFlags.HasPipeline) != 0) + { + m_Logger.Log(NetworkLogger.LogLevel.Error, m_StringDB[(int)StringType.DisconnectWithPipeline]); + return 0; + } + Connection c = GetConnection(address, header.SessionToken); + if (c != Connection.Null) + { + if (RemoveConnection(c)) + AddDisconnection(c.Id); + count++; + } + } + break; + case UdpCProtocol.Data: + { + Connection c = GetConnection(address, header.SessionToken); + if (c == Connection.Null) + return 0; + + c.DidReceiveData = 1; + c.LastAttempt = m_updateTime; + UpdateConnection(c); + + var length = dataLen - UdpCHeader.Length; + + if (c.State == NetworkConnection.State.Connecting) + { + if ((header.Flags&UdpCHeader.HeaderFlags.HasConnectToken) == 0) + { + m_Logger.Log(NetworkLogger.LogLevel.Error, m_StringDB[(int)StringType.ImplicitAcceptWithoutToken]); + return 0; + } + + var tokenOffset = m_DataStream.Length + length - 2; + m_DataStream.WriteBytesWithUnsafePointer(length); + var dataStreamReader = new DataStreamReader(m_DataStream, tokenOffset, 2); + var context = default(DataStreamReader.Context); + c.SendToken = dataStreamReader.ReadUShort(ref context); + m_DataStream.WriteBytesWithUnsafePointer(-length); + + c.State = NetworkConnection.State.Connected; + UpdateConnection(c); + Assert.IsTrue(!Listening); + AddConnection(c.Id); + count++; + } + + if (c.State == NetworkConnection.State.Connected) + { + if ((header.Flags & UdpCHeader.HeaderFlags.HasConnectToken) != 0) + length -= 2; + + var sliceOffset = m_DataStream.Length; + m_DataStream.WriteBytesWithUnsafePointer(length); + + if ((header.Flags & UdpCHeader.HeaderFlags.HasPipeline) != 0) + { + var netCon = new NetworkConnection {m_NetworkId = c.Id, m_NetworkVersion = c.Version}; + m_PipelineProcessor.Receive(this, netCon, m_DataStream.GetNativeSlice(sliceOffset, length)); + return 0; + } + + m_EventQueue.PushEvent(new NetworkEvent + { + connectionId = c.Id, + type = NetworkEvent.Type.Data, + offset = sliceOffset, + size = length + }); + count++; + } + } break; + } + + return count; + } + + public unsafe void PushDataEvent(NetworkConnection con, NativeSlice data) + { + byte* dataPtr = (byte*)data.GetUnsafeReadOnlyPtr(); + byte* streamBasePtr = m_DataStream.GetUnsafePtr(); + int sliceOffset = 0; + if (dataPtr >= streamBasePtr && dataPtr + data.Length <= streamBasePtr + m_DataStream.Length) + { + // Pointer is a subset of our receive buffer, no need to copy + sliceOffset = (int)(dataPtr - streamBasePtr); + } + else + { + if (DynamicDataStreamSize()) + { + while (m_DataStream.Length + data.Length >= m_DataStream.Capacity) + m_DataStream.Capacity *= 2; + } + else if (m_DataStream.Length + data.Length >= m_DataStream.Capacity) + return; // FIXME: how do we signal this error? + + sliceOffset = m_DataStream.Length; + UnsafeUtility.MemCpy(streamBasePtr + sliceOffset, dataPtr, data.Length); + m_DataStream.WriteBytesWithUnsafePointer(data.Length); + } + + m_EventQueue.PushEvent(new NetworkEvent + { + connectionId = con.m_NetworkId, + type = NetworkEvent.Type.Data, + offset = sliceOffset, + size = data.Length + }); + } + } +} diff --git a/Runtime/NetworkDriver.cs.meta b/Runtime/NetworkDriver.cs.meta new file mode 100644 index 0000000..36dcdc1 --- /dev/null +++ b/Runtime/NetworkDriver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 38c540f496ff7824c96d4ba0d3bac37e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/NetworkEndPoint.cs b/Runtime/NetworkEndPoint.cs new file mode 100644 index 0000000..684e26d --- /dev/null +++ b/Runtime/NetworkEndPoint.cs @@ -0,0 +1,210 @@ +using System; +using System.Runtime.InteropServices; +using Unity.Collections.LowLevel.Unsafe; + +namespace Unity.Networking.Transport +{ + /// + /// NetworkFamily indicates what type of underlying medium we are using. + /// Currently supported are and + /// + public enum NetworkFamily + { + UdpIpv4 = 2,//AddressFamily.InterNetwork, + IPC = 0//AddressFamily.Unspecified + } + + /// + /// The NetworkEndPoint is our representation of the type. + /// + [StructLayout(LayoutKind.Explicit)] + public unsafe struct NetworkEndPoint + { + internal const int Length = 28; + [FieldOffset(0)] internal fixed byte data[Length]; + [FieldOffset(0)] internal sa_family_t family; + [FieldOffset(2)] internal ushort nbo_port; + [FieldOffset(4)] internal int ipc_handle; + [FieldOffset(28)] internal int length; + + private static bool IsLittleEndian = true; + static NetworkEndPoint() + { + uint test = 1; + unsafe + { + byte* test_b = (byte*) &test; + IsLittleEndian = test_b[0] == 1; + } + } + + private static ushort ByteSwap(ushort val) + { + return (ushort)(((val & 0xff) << 8) | (val >> 8)); + } + private static uint ByteSwap(uint val) + { + return (uint)(((val & 0xff) << 24) |((val&0xff00)<<8) | ((val>>8)&0xff00) | (val >> 24)); + } + public ushort Port + { + get { return IsLittleEndian ? ByteSwap(nbo_port) : nbo_port; } + set { nbo_port = IsLittleEndian ? ByteSwap(value) : value; } + } + + public NetworkFamily Family + { + get => (NetworkFamily) family.sa_family; +#if (UNITY_EDITOR_OSX || ((UNITY_STANDALONE_OSX || UNITY_IOS) && !UNITY_EDITOR)) + set => family.sa_family = (byte) value; +#else + set => family.sa_family = (ushort)value; +#endif + } + + public bool IsValid => Family != 0; + + public static NetworkEndPoint CreateIpv4(uint ip, ushort port) + { + if (IsLittleEndian) + { + port = ByteSwap(port); + ip = ByteSwap(ip); + } + + var sai = new sockaddr_in(); + +#if (UNITY_EDITOR_OSX || ((UNITY_STANDALONE_OSX || UNITY_IOS) && !UNITY_EDITOR)) + sai.sin_family.sa_family = (byte) NetworkFamily.UdpIpv4; + sai.sin_family.sa_len = (byte) sizeof(sockaddr_in); +#else + sai.sin_family.sa_family = (ushort) NetworkFamily.UdpIpv4; +#endif + sai.sin_port = port; + sai.sin_addr.s_addr = ip; + + var len = sizeof(sockaddr_in); + var address = new NetworkEndPoint + { + length = len + }; + + UnsafeUtility.MemCpy(address.data, sai.data, len); + return address; + } + + public static NetworkEndPoint AnyIpv4 => CreateIpv4(0, 0); + public static NetworkEndPoint LoopbackIpv4 => CreateIpv4((127<<24) | 1, 0); + + // Returns true if we can fully parse the input and return a valid endpoint + public static bool TryParse(string ip, ushort port, out NetworkEndPoint endpoint) + { + endpoint = default(NetworkEndPoint); + + // Parse failure check + if (ip == null || ip.Length < 7) + return false; + + uint ipaddr = 0; + var pos = 0; + + // Parse characters + for (var part = 0; part < 4; ++part) + { + // Parse failure check + if (pos >= ip.Length || ip[pos] < '0' || ip[pos] > '9') + return false; + + uint byteVal = 0; + + while (pos < ip.Length && ip[pos] >= '0' && ip[pos] <= '9') + { + byteVal = byteVal * 10 + (uint)(ip[pos] - '0'); + ++pos; + } + + // Parse failure check + if (byteVal > 255) + return false; + + ipaddr = (ipaddr << 8) | byteVal; + + if (pos < ip.Length && ip[pos] == '.') + ++pos; + } + + if (pos + 1 < ip.Length && ip[pos] == ':') + { + ++pos; + uint customPort = 0; + while (pos < ip.Length && ip[pos] >= '0' && ip[pos] <= '9') + { + customPort = customPort * 10 + (uint)(ip[pos] - '0'); + ++pos; + } + + if (customPort > ushort.MaxValue) + return false; + + port = (ushort)customPort; + } + + endpoint = CreateIpv4(ipaddr, port); + return endpoint.IsValid; + } + + // Returns a default address if parsing fails + public static NetworkEndPoint Parse(string ip, ushort port) + { + if (TryParse(ip, port, out var endpoint)) + return endpoint; + + return CreateIpv4(0, port); + } + + public static bool operator ==(NetworkEndPoint lhs, NetworkEndPoint rhs) + { + return lhs.Compare(rhs); + } + + public static bool operator !=(NetworkEndPoint lhs, NetworkEndPoint rhs) + { + return !lhs.Compare(rhs); + } + + public override bool Equals(object other) + { + return this == (NetworkEndPoint) other; + } + + public override int GetHashCode() + { + fixed (byte* p = data) + unchecked + { + var result = 0; + + for (int i = 0; i < Length; i++) + { + result = (result * 31) ^ (int)(IntPtr) (p + 1); + } + + return result; + } + } + + bool Compare(NetworkEndPoint other) + { + if (length != other.length) + return false; + + fixed (void* p = this.data) + { + if (UnsafeUtility.MemCmp(p, other.data, length) == 0) + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/Runtime/NetworkEndPoint.cs.meta b/Runtime/NetworkEndPoint.cs.meta new file mode 100644 index 0000000..d89d8ec --- /dev/null +++ b/Runtime/NetworkEndPoint.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f4fec373e8214414a96bbb300a2dcaac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/NetworkEventQueue.cs b/Runtime/NetworkEventQueue.cs new file mode 100644 index 0000000..c3abdbc --- /dev/null +++ b/Runtime/NetworkEventQueue.cs @@ -0,0 +1,243 @@ +using System; +using System.Threading; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; + +namespace Unity.Networking.Transport +{ + public struct NetworkEvent + { + /// + /// NetworkEvent.Type enumerates available network events for this driver. + /// + public enum Type + { + Empty = 0, + Data, + Connect, + Disconnect + } + + public Type type; + + public int connectionId; + public int offset; + public int size; + } + + public struct NetworkEventQueue : IDisposable + { + private int MaxEvents { + get { return m_ConnectionEventQ.Length / (m_ConnectionEventHeadTail.Length/2); } + } + public NetworkEventQueue(int queueSizePerConnection) + { + m_MasterEventQ = new NativeQueue(Allocator.Persistent); + m_ConnectionEventQ = new NativeList(queueSizePerConnection, Allocator.Persistent); + m_ConnectionEventHeadTail = new NativeList(2, Allocator.Persistent); + m_ConnectionEventQ.ResizeUninitialized(queueSizePerConnection); + m_ConnectionEventHeadTail.Add(0); + m_ConnectionEventHeadTail.Add(0); + } + + public void Dispose() + { + m_MasterEventQ.Dispose(); + m_ConnectionEventQ.Dispose(); + m_ConnectionEventHeadTail.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) + { + offset = 0; + size = 0; + id = -1; + + while (true) + { + SubQueueItem ev; + if (!m_MasterEventQ.TryDequeue(out ev)) + { + return NetworkEvent.Type.Empty; + } + + if (m_ConnectionEventHeadTail[ev.connection * 2] == ev.idx) + { + id = ev.connection; + return PopEventForConnection(ev.connection, out offset, out size); + } + } + } + + public NetworkEvent.Type PopEventForConnection(int connectionId, out int offset, out int size) + { + offset = 0; + size = 0; + + if (connectionId < 0 || connectionId >= m_ConnectionEventHeadTail.Length / 2) + return NetworkEvent.Type.Empty; + int idx = m_ConnectionEventHeadTail[connectionId * 2]; + if (idx >= m_ConnectionEventHeadTail[connectionId * 2 + 1]) + return NetworkEvent.Type.Empty; + m_ConnectionEventHeadTail[connectionId * 2] = idx + 1; + NetworkEvent ev = m_ConnectionEventQ[connectionId * MaxEvents + idx]; + if (ev.type == NetworkEvent.Type.Data) + { + offset = ev.offset; + size = ev.size; + } + + return ev.type; + } + + public int GetCountForConnection(int connectionId) + { + if (connectionId < 0 || connectionId >= m_ConnectionEventHeadTail.Length / 2) + return 0; + return m_ConnectionEventHeadTail[connectionId * 2 + 1] - m_ConnectionEventHeadTail[connectionId * 2]; + } + + /// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + /// internal helper functions :::::::::::::::::::::::::::::::::::::::::: + public void PushEvent(NetworkEvent ev) + { + int curMaxEvents = MaxEvents; + if (ev.connectionId >= m_ConnectionEventHeadTail.Length / 2) + { + // Connection id out of range, grow the number of connections in the queue + int oldSize = m_ConnectionEventHeadTail.Length; + m_ConnectionEventHeadTail.ResizeUninitialized((ev.connectionId + 1)*2); + for (;oldSize < m_ConnectionEventHeadTail.Length; ++oldSize) + m_ConnectionEventHeadTail[oldSize] = 0; + m_ConnectionEventQ.ResizeUninitialized((m_ConnectionEventHeadTail.Length / 2) * curMaxEvents); + } + int idx = m_ConnectionEventHeadTail[ev.connectionId * 2 + 1]; + if (idx >= curMaxEvents) + { + // Grow the max items per queue and remap the queues + int oldMax = curMaxEvents; + while (idx >= curMaxEvents) + curMaxEvents *= 2; + int maxConnections = m_ConnectionEventHeadTail.Length / 2; + m_ConnectionEventQ.ResizeUninitialized(maxConnections * curMaxEvents); + for (int con = maxConnections-1; con >= 0; --con) + { + for (int i = m_ConnectionEventHeadTail[con*2+1]-1; i >= m_ConnectionEventHeadTail[con * 2]; --i) + { + m_ConnectionEventQ[con * curMaxEvents + i] = m_ConnectionEventQ[con * oldMax + i]; + } + } + } + + m_ConnectionEventQ[ev.connectionId * curMaxEvents + idx] = ev; + m_ConnectionEventHeadTail[ev.connectionId * 2 + 1] = idx + 1; + + m_MasterEventQ.Enqueue(new SubQueueItem {connection = ev.connectionId, idx = idx}); + } + + internal void Clear() + { + m_MasterEventQ.Clear(); + for (int i = 0; i < m_ConnectionEventHeadTail.Length; ++i) + { + m_ConnectionEventHeadTail[i] = 0; + } + } + + struct SubQueueItem + { + public int connection; + public int idx; + } + + private NativeQueue m_MasterEventQ; + private NativeList m_ConnectionEventQ; + private NativeList m_ConnectionEventHeadTail; + + public Concurrent ToConcurrent() + { + Concurrent concurrent; + concurrent.m_ConnectionEventQ = m_ConnectionEventQ; + concurrent.m_ConnectionEventHeadTail = new Concurrent.ConcurrentConnectionQueue(m_ConnectionEventHeadTail); + return concurrent; + } + public struct Concurrent + { + [NativeContainer] + [NativeContainerIsAtomicWriteOnly] + internal unsafe struct ConcurrentConnectionQueue + { +#pragma warning disable 649 + struct ListData + { + public int* value; + public int length; + } +#pragma warning restore 649 + [NativeDisableUnsafePtrRestriction] private ListData* m_ConnectionEventHeadTail; +#if ENABLE_UNITY_COLLECTIONS_CHECKS + private AtomicSafetyHandle m_Safety; +#endif + public ConcurrentConnectionQueue(NativeList queue) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + m_Safety = NativeListUnsafeUtility.GetAtomicSafetyHandle(ref queue); + AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); +#endif + m_ConnectionEventHeadTail = (ListData*) NativeListUnsafeUtility.GetInternalListDataPtrUnchecked(ref queue); + } + + public int Length + { + get { return m_ConnectionEventHeadTail->length; } + } + + public int Dequeue(int connectionId) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); +#endif + int idx = -1; + if (connectionId < 0 || connectionId >= m_ConnectionEventHeadTail->length / 2) + return -1; + while (idx < 0) + { + idx = m_ConnectionEventHeadTail->value[connectionId * 2]; + if (idx >= m_ConnectionEventHeadTail->value[connectionId * 2 + 1]) + return -1; + if (Interlocked.CompareExchange(ref m_ConnectionEventHeadTail->value[connectionId * 2], idx + 1, + idx) != idx) + idx = -1; + } + + return idx; + } + } + private int MaxEvents { + get { return m_ConnectionEventQ.Length / (m_ConnectionEventHeadTail.Length/2); } + } + + public NetworkEvent.Type PopEventForConnection(int connectionId, out int offset, out int size) + { + offset = 0; + size = 0; + + int idx = m_ConnectionEventHeadTail.Dequeue(connectionId); + if (idx < 0) + return NetworkEvent.Type.Empty; + NetworkEvent ev = m_ConnectionEventQ[connectionId * MaxEvents + idx]; + if (ev.type == NetworkEvent.Type.Data) + { + offset = ev.offset; + size = ev.size; + } + + return ev.type; + } + + [ReadOnly] internal NativeList m_ConnectionEventQ; + internal ConcurrentConnectionQueue m_ConnectionEventHeadTail; + } + } +} \ No newline at end of file diff --git a/Runtime/NetworkEventQueue.cs.meta b/Runtime/NetworkEventQueue.cs.meta new file mode 100644 index 0000000..4802475 --- /dev/null +++ b/Runtime/NetworkEventQueue.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 24080868f8aea4078b8027bb059f03a2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/NetworkLogger.cs b/Runtime/NetworkLogger.cs new file mode 100644 index 0000000..4edca9c --- /dev/null +++ b/Runtime/NetworkLogger.cs @@ -0,0 +1,124 @@ +using System; +using Unity.Collections; + +namespace Unity.Networking.Transport +{ + public interface INetworkLogMessage + { + void Print(ref NativeString512 container); + } + + public struct NetworkLogger : IDisposable + { + internal struct LogMessage + { + public NativeString512 msg; + public LogLevel level; + } + public enum LogLevel + { + None = 0, + Error, + Warning, + Info, + Debug + } + + public NetworkLogger(LogLevel level) + { + m_Level = level; + m_PendingLog = new NativeQueue(Allocator.Persistent); + m_LogFile = new NativeList(Allocator.Persistent); + } + + public void Dispose() + { + m_PendingLog.Dispose(); + m_LogFile.Dispose(); + } + + public void FlushPending() + { + LogMessage msg; + while (m_PendingLog.TryDequeue(out msg)) + m_LogFile.Add(msg); + } + + public void DumpToConsole() + { + for (int i = 0; i < m_LogFile.Length; ++i) + { + var msg = m_LogFile[i]; + switch (msg.level) + { + case LogLevel.Error: + UnityEngine.Debug.LogError(msg.msg.ToString()); + break; + case LogLevel.Warning: + UnityEngine.Debug.LogWarning(msg.msg.ToString()); + break; + default: + UnityEngine.Debug.Log(msg.msg.ToString()); + break; + } + } + m_LogFile.Clear(); + } + public void Clear() + { + m_LogFile.Clear(); + } + + public void Log(LogLevel level, T message) where T : struct, INetworkLogMessage + { + if ((int) level > (int) m_Level) + return; + var msg = default(LogMessage); + msg.level = level; + message.Print(ref msg.msg); + m_PendingLog.Enqueue(msg); + } + public void Log(LogLevel level, NativeString512 str) + { + if ((int) level > (int) m_Level) + return; + var msg = new LogMessage {level = level, msg = str}; + m_PendingLog.Enqueue(msg); + } + + private LogLevel m_Level; + private NativeList m_LogFile; + private NativeQueue m_PendingLog; + + public Concurrent ToConcurrent() + { + var concurrent = default(Concurrent); + concurrent.m_PendingLog = m_PendingLog.AsParallelWriter(); + concurrent.m_Level = m_Level; + return concurrent; + } + + public struct Concurrent + { + public void Log(LogLevel level, T message) where T : struct, INetworkLogMessage + { + if ((int) level > (int) m_Level) + return; + var msg = default(LogMessage); + msg.level = level; + message.Print(ref msg.msg); + m_PendingLog.Enqueue(msg); + } + public void Log(LogLevel level, NativeString512 str) + { + if ((int) level > (int) m_Level) + return; + var msg = new LogMessage {level = level, msg = str}; + m_PendingLog.Enqueue(msg); + } + + internal NativeQueue.ParallelWriter m_PendingLog; + internal LogLevel m_Level; + } + } +} \ No newline at end of file diff --git a/Runtime/NetworkLogger.cs.meta b/Runtime/NetworkLogger.cs.meta new file mode 100644 index 0000000..10dc841 --- /dev/null +++ b/Runtime/NetworkLogger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 15b64cdc328dc422d9a5f3d1f8cc7137 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/NetworkParams.cs b/Runtime/NetworkParams.cs new file mode 100644 index 0000000..d007a96 --- /dev/null +++ b/Runtime/NetworkParams.cs @@ -0,0 +1,59 @@ +namespace Unity.Networking.Transport +{ + /// + /// The interface for NetworkParameters + /// + public interface INetworkParameter + { + } + + /// + /// Default NetworkParameter Constants. + /// + public struct NetworkParameterConstants + { + /// The default size of the event queue. + public const int InitialEventQueueSize = 100; + public const int InvalidConnectionId = -1; + + /// + /// The default size of the DataStreamWriter. This value can be overridden using the . + /// + public const int DriverDataStreamSize = 64 * 1024; + /// The default connection timeout value. This value can be overridden using the + public const int ConnectTimeoutMS = 1000; + /// The default max connection attempts value. This value can be overridden using the + public const int MaxConnectAttempts = 60; + /// The default disconnect timeout attempts value. This value can be overridden using the + public const int DisconnectTimeoutMS = 30 * 1000; + + public const int MTU = 1400; + } + + /// + /// The NetworkDataStreamParameter is used to set the initial data stream size. + /// + /// The can grow on demand so its not necessary to set this value. + public struct NetworkDataStreamParameter : INetworkParameter + { + /// Size of the default + public int size; + } + + /// + /// The NetworkConfigParameter is used to set specific parameters that the driver uses. + /// + public struct NetworkConfigParameter : INetworkParameter + { + /// A timeout in milliseconds indicating how long we will wait until we send a new connection attempt. + public int connectTimeoutMS; + /// The maximum amount of connection attempts we will try before disconnecting. + public int maxConnectAttempts; + /// A timeout in milliseconds indicating how long we will wait for a socket event, before we disconnect the socket. + /// The connection needs to receive data from the connected endpoint within this timeout. + public int disconnectTimeoutMS; + /// The maximum amount of time a single frame can advance timeout values. + /// The main use for this parameter is to not get disconnects at frame spikes when both endpoints lives in the same process. + public int maxFrameTimeMS; + } +} \ No newline at end of file diff --git a/Runtime/NetworkParams.cs.meta b/Runtime/NetworkParams.cs.meta new file mode 100644 index 0000000..2410ea0 --- /dev/null +++ b/Runtime/NetworkParams.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 727aa4ae963216b4aa40606d66cb2df1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/NetworkPipeline.cs b/Runtime/NetworkPipeline.cs new file mode 100644 index 0000000..adcc3bf --- /dev/null +++ b/Runtime/NetworkPipeline.cs @@ -0,0 +1,718 @@ +using System; +using System.Threading; +using Unity.Networking.Transport.LowLevel.Unsafe; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using UnityEngine; + +namespace Unity.Networking.Transport +{ + public interface INetworkPipelineSender + { + unsafe int Send(NetworkConnection con, network_iovec* iov, int iovLen); + } + public interface INetworkPipelineReceiver + { + void PushDataEvent(NetworkConnection con, NativeSlice data); + } + + public struct InboundBufferVec + { + public NativeSlice buffer1; + public NativeSlice buffer2; + } + public struct NetworkPipelineContext + { + public NativeSlice internalSharedProcessBuffer; + public NativeSlice internalProcessBuffer; + public DataStreamWriter header; + public long timestamp; + } + + public class NetworkPipelineInitilizeAttribute : Attribute + { + public NetworkPipelineInitilizeAttribute(Type t) + { + m_ParameterType = t; + } + + public Type ParameterType => m_ParameterType; + private Type m_ParameterType; + } + public interface INetworkPipelineStage + { + NativeSlice Receive(NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate); + InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate); + + void InitializeConnection(NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, NativeSlice sharedProcessBuffer); + + int ReceiveCapacity { get; } + int SendCapacity { get; } + int HeaderCapacity { get; } + int SharedStateCapacity { get; } + } + + public interface INetworkPipelineStageCollection + { + int GetStageId(Type type); + + void Initialize(params INetworkParameter[] param); + void InvokeInitialize(int pipelineStageId, NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, NativeSlice sharedStateBuffer); + InboundBufferVec InvokeSend(int pipelineStageId, NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate); + NativeSlice InvokeReceive(int pipelineStageId, NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate); + + int GetReceiveCapacity(int pipelineStageId); + int GetSendCapacity(int pipelineStageId); + int GetHeaderCapacity(int pipelineStageId); + int GetSharedStateCapacity(int pipelineStageId); + } + + public struct NetworkPipeline + { + internal int Id; + public static NetworkPipeline Null => default(NetworkPipeline); + + public static bool operator ==(NetworkPipeline lhs, NetworkPipeline rhs) + { + return lhs.Id == rhs.Id; + } + + public static bool operator !=(NetworkPipeline lhs, NetworkPipeline rhs) + { + return lhs.Id != rhs.Id; + } + + public override bool Equals(object compare) + { + return this == (NetworkPipeline) compare; + } + + public override int GetHashCode() + { + return Id; + } + + public bool Equals(NetworkPipeline connection) + { + return connection.Id == Id; + } + } + + public struct NetworkPipelineParams : INetworkParameter + { + public int initialCapacity; + } + + internal struct NetworkPipelineProcessor : IDisposable where TNetworkPipelineStageCollection: struct, INetworkPipelineStageCollection + { + public Concurrent ToConcurrent() + { + var concurrent = new Concurrent + { + m_StageCollection = m_StageCollection, + m_Pipelines = m_Pipelines, + m_StageList = m_StageList, + m_SendStageNeedsUpdateWrite = m_SendStageNeedsUpdateRead.AsParallelWriter(), + sizePerConnection = sizePerConnection, + sendBuffer = m_SendBuffer, + sharedBuffer = m_SharedBuffer, + m_timestamp = m_timestamp + }; + return concurrent; + } + public struct Concurrent + { + // FIXME: read-only? + internal TNetworkPipelineStageCollection m_StageCollection; + [ReadOnly] internal NativeList m_Pipelines; + [ReadOnly] internal NativeList m_StageList; + internal NativeQueue.ParallelWriter m_SendStageNeedsUpdateWrite; + [ReadOnly] internal NativeArray sizePerConnection; + // TODO: not really read-only, just hacking the safety system + [ReadOnly] internal NativeList sharedBuffer; + [ReadOnly] internal NativeList sendBuffer; + [ReadOnly] internal NativeArray m_timestamp; + + public unsafe int Send(T driver, NetworkPipeline pipeline, NetworkConnection connection, NativeSlice payloadData) where T : struct, INetworkPipelineSender + { + var p = m_Pipelines[pipeline.Id-1]; + + var connectionId = connection.m_NetworkId; + int startStage = 0; + + // TODO: not really read-only, just hacking the safety system + NativeArray tmpBuffer = sendBuffer; + int* sendBufferLock = (int*) tmpBuffer.GetUnsafeReadOnlyPtr(); + sendBufferLock += connectionId * sizePerConnection[SendSizeOffset] / 4; + + while (Interlocked.CompareExchange(ref *sendBufferLock, 1, 0) != 0) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + throw new InvalidOperationException("The parallel network driver needs to process a single unique connection per job, processing a single connection multiple times in a parallel for is not supported."); +#endif + } + + NativeList currentUpdates = new NativeList(128, Allocator.Temp); + ProcessPipelineSend(driver, startStage, pipeline, connection, payloadData, currentUpdates); + // Move the updates requested in this iteration to the concurrent queue so it can be read/parsed in update routine + for (int i = 0; i < currentUpdates.Length; ++i) + m_SendStageNeedsUpdateWrite.Enqueue(currentUpdates[i]); + + Interlocked.Exchange(ref *sendBufferLock, 0); + return payloadData.Length; + } + + internal unsafe void ProcessPipelineSend(T driver, int startStage, NetworkPipeline pipeline, NetworkConnection connection, + NativeSlice payloadBuffer, NativeList currentUpdates) where T : struct, INetworkPipelineSender + { + NetworkPipelineContext ctx = default(NetworkPipelineContext); + ctx.timestamp = m_timestamp[0]; + var p = m_Pipelines[pipeline.Id-1]; + var connectionId = connection.m_NetworkId; + + var resumeQ = new NativeList(16, Allocator.Temp); + int resumeQStart = 0; + ctx.header = new DataStreamWriter(p.headerCapacity, Allocator.Temp); + + var inboundBuffer = default(InboundBufferVec); + inboundBuffer.buffer1 = payloadBuffer; + + var prevHeader = new DataStreamWriter(p.headerCapacity, Allocator.Temp); + + while (true) + { + int internalBufferOffset = p.sendBufferOffset + sizePerConnection[SendSizeOffset] * connectionId; + int internalSharedBufferOffset = p.sharedBufferOffset + sizePerConnection[SharedSizeOffset] * connectionId; + + bool needsUpdate = false; + // If this is not the first stage we need to fast forward the buffer offset to the correct place + if (startStage > 0) + { + for (int i = 0; i < startStage; ++i) + { + internalBufferOffset += m_StageCollection.GetSendCapacity(m_StageList[p.FirstStageIndex + i]); + internalSharedBufferOffset += m_StageCollection.GetSharedStateCapacity(m_StageList[p.FirstStageIndex + i]); + } + } + + for (int i = startStage; i < p.NumStages; ++i) + { + var prevInbound = inboundBuffer; + ProcessSendStage(i, internalBufferOffset, internalSharedBufferOffset, p, ref resumeQ, ref ctx, ref inboundBuffer, ref needsUpdate); + if (inboundBuffer.buffer1 == prevInbound.buffer1 && + inboundBuffer.buffer2 == prevInbound.buffer2) + { + if (ctx.header.Length > 0) + { + if (prevHeader.Length > 0) + ctx.header.WriteBytes(prevHeader.GetUnsafeReadOnlyPtr(), prevHeader.Length); + prevHeader.Clear(); + var tempHeader = ctx.header; + ctx.header = prevHeader; + prevHeader = tempHeader; + if (inboundBuffer.buffer2.Length == 0) + inboundBuffer.buffer2 = inboundBuffer.buffer1; + inboundBuffer.buffer1 = prevHeader.GetNativeSlice(0, prevHeader.Length); + } + + } + else + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (inboundBuffer.buffer2.Length > 0) + throw new InvalidOperationException("Pipeline send stages must return either the unmodified inbound buffers or a consolidated version with a single buffer"); +#endif + // Prev header is now part of payload + prevHeader.Clear(); + if (ctx.header.Length > 0) + { + var tempHeader = ctx.header; + ctx.header = prevHeader; + prevHeader = tempHeader; + inboundBuffer.buffer2 = inboundBuffer.buffer1; + inboundBuffer.buffer1 = prevHeader.GetNativeSlice(0, prevHeader.Length); + } + } + if (needsUpdate) + AddSendUpdate(connection, i, pipeline, currentUpdates); + if (inboundBuffer.buffer1.Length == 0) + break; + + needsUpdate = false; + + internalBufferOffset += ctx.internalProcessBuffer.Length; + internalSharedBufferOffset += ctx.internalSharedProcessBuffer.Length; + } + + if (inboundBuffer.buffer1.Length != 0) + { + var iov = stackalloc network_iovec[4]; + var pipelineId = pipeline.Id; + iov[0].buf = &pipelineId; + iov[0].len = 1; + iov[1].buf = ctx.header.GetUnsafePtr(); + iov[1].len = ctx.header.Length; + iov[2].buf = inboundBuffer.buffer1.GetUnsafeReadOnlyPtr(); + iov[2].len = inboundBuffer.buffer1.Length; + if (inboundBuffer.buffer2.Length > 0) + { + iov[3].buf = inboundBuffer.buffer2.GetUnsafeReadOnlyPtr(); + iov[3].len = inboundBuffer.buffer2.Length; + // FIXME: handle send errors + driver.Send(connection, iov, 4); + } + else + driver.Send(connection, iov, 3); + } + + if (resumeQStart >= resumeQ.Length) + { + break; + } + + startStage = resumeQ[resumeQStart++]; + + prevHeader.Clear(); + inboundBuffer = default(InboundBufferVec); + } + } + + internal static unsafe NativeSlice Unsafe_GetSliceFromReadOnlyArray(NativeArray array, int offset, int length) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + var handle = AtomicSafetyHandle.Create(); +#endif + var ptr = (void*)((byte*) array.GetUnsafeReadOnlyPtr() + offset); + var buffer = + NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(ptr, length, Allocator.None); +#if ENABLE_UNITY_COLLECTIONS_CHECKS + NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref buffer, handle); +#endif + return buffer.Slice(); + } + + private void ProcessSendStage(int startStage, int internalBufferOffset, int internalSharedBufferOffset, + PipelineImpl p, ref NativeList resumeQ, ref NetworkPipelineContext ctx, ref InboundBufferVec inboundBuffer, ref bool needsUpdate) + { + bool needsResume = false; + ctx.internalProcessBuffer = Unsafe_GetSliceFromReadOnlyArray(sendBuffer, internalBufferOffset, + m_StageCollection.GetSendCapacity(m_StageList[p.FirstStageIndex + startStage])); + + ctx.internalSharedProcessBuffer = + Unsafe_GetSliceFromReadOnlyArray(sharedBuffer, internalSharedBufferOffset, + m_StageCollection.GetSharedStateCapacity(m_StageList[p.FirstStageIndex + startStage])); + + inboundBuffer = m_StageCollection.InvokeSend(m_StageList[p.FirstStageIndex + startStage], ctx, + inboundBuffer, ref needsResume, ref needsUpdate); + if (needsResume) + resumeQ.Add(startStage); + } + } + private TNetworkPipelineStageCollection m_StageCollection; + private NativeList m_StageList; + private NativeList m_Pipelines; + private NativeList m_ReceiveBuffer; + private NativeList m_SendBuffer; + private NativeList m_SharedBuffer; + private NativeList m_ReceiveStageNeedsUpdate; + private NativeList m_SendStageNeedsUpdate; + private NativeQueue m_SendStageNeedsUpdateRead; + + private NativeArray sizePerConnection; + + private NativeArray m_timestamp; + + private const int SendSizeOffset = 0; + private const int RecveiveSizeOffset = 1; + private const int SharedSizeOffset = 2; + + internal struct PipelineImpl + { + public int FirstStageIndex; + public int NumStages; + + public int receiveBufferOffset; + public int sendBufferOffset; + public int sharedBufferOffset; + public int headerCapacity; + } + + public NetworkPipelineProcessor(params INetworkParameter[] param) + { + NetworkPipelineParams config = default(NetworkPipelineParams); + for (int i = 0; i < param.Length; ++i) + { + if (param[i] is NetworkPipelineParams) + config = (NetworkPipelineParams)param[i]; + } + m_StageCollection = new TNetworkPipelineStageCollection(); + m_StageCollection.Initialize(param); + m_StageList = new NativeList(16, Allocator.Persistent); + m_Pipelines = new NativeList(16, Allocator.Persistent); + m_ReceiveBuffer = new NativeList(config.initialCapacity, Allocator.Persistent); + m_SendBuffer = new NativeList(config.initialCapacity, Allocator.Persistent); + m_SharedBuffer = new NativeList(config.initialCapacity, Allocator.Persistent); + sizePerConnection = new NativeArray(3, Allocator.Persistent); + // Store an int for the spinlock first in each connections send buffer + sizePerConnection[SendSizeOffset] = 4; + m_ReceiveStageNeedsUpdate = new NativeList(128, Allocator.Persistent); + m_SendStageNeedsUpdate = new NativeList(128, Allocator.Persistent); + m_SendStageNeedsUpdateRead = new NativeQueue(Allocator.Persistent); + m_timestamp = new NativeArray(1, Allocator.Persistent); + } + + public void Dispose() + { + m_StageList.Dispose(); + m_ReceiveBuffer.Dispose(); + m_SendBuffer.Dispose(); + m_SharedBuffer.Dispose(); + m_Pipelines.Dispose(); + sizePerConnection.Dispose(); + m_ReceiveStageNeedsUpdate.Dispose(); + m_SendStageNeedsUpdate.Dispose(); + m_SendStageNeedsUpdateRead.Dispose(); + m_timestamp.Dispose(); + } + + public long Timestamp + { + get { return m_timestamp[0]; } + internal set { m_timestamp[0] = value; } + } + + public unsafe void initializeConnection(NetworkConnection con) + { + var requiredReceiveSize = (con.m_NetworkId + 1) * sizePerConnection[RecveiveSizeOffset]; + var requiredSendSize = (con.m_NetworkId + 1) * sizePerConnection[SendSizeOffset]; + var requiredSharedSize = (con.m_NetworkId + 1) * sizePerConnection[SharedSizeOffset]; + if (m_ReceiveBuffer.Length < requiredReceiveSize) + m_ReceiveBuffer.ResizeUninitialized(requiredReceiveSize); + if (m_SendBuffer.Length < requiredSendSize) + m_SendBuffer.ResizeUninitialized(requiredSendSize); + if (m_SharedBuffer.Length < requiredSharedSize) + m_SharedBuffer.ResizeUninitialized(requiredSharedSize); + + UnsafeUtility.MemClear((byte*)m_ReceiveBuffer.GetUnsafePtr() + con.m_NetworkId * sizePerConnection[RecveiveSizeOffset], sizePerConnection[RecveiveSizeOffset]); + UnsafeUtility.MemClear((byte*)m_SendBuffer.GetUnsafePtr() + con.m_NetworkId * sizePerConnection[SendSizeOffset], sizePerConnection[SendSizeOffset]); + UnsafeUtility.MemClear((byte*)m_SharedBuffer.GetUnsafePtr() + con.m_NetworkId * sizePerConnection[SharedSizeOffset], sizePerConnection[SharedSizeOffset]); + + InitializeStages(con.m_NetworkId); + } + + void InitializeStages(int networkId) + { + var connectionId = networkId; + + for (int i = 0; i < m_Pipelines.Length; i++) + { + var pipeline = m_Pipelines[i]; + + int recvBufferOffset = pipeline.receiveBufferOffset + sizePerConnection[RecveiveSizeOffset] * connectionId; + int sendBufferOffset = pipeline.sendBufferOffset + sizePerConnection[SendSizeOffset] * connectionId; + int sharedBufferOffset = pipeline.sharedBufferOffset + sizePerConnection[SharedSizeOffset] * connectionId; + + for (int stage = pipeline.FirstStageIndex; + stage < pipeline.FirstStageIndex + pipeline.NumStages; + stage++) + { + var sendProcessBuffer = + new NativeSlice(m_SendBuffer, sendBufferOffset, m_StageCollection.GetSendCapacity(m_StageList[stage])); + var recvProcessBuffer = + new NativeSlice(m_ReceiveBuffer, recvBufferOffset, m_StageCollection.GetReceiveCapacity(m_StageList[stage])); + var sharedProcessBuffer = + new NativeSlice(m_SharedBuffer, sharedBufferOffset, m_StageCollection.GetSharedStateCapacity(m_StageList[stage])); + + m_StageCollection.InvokeInitialize(m_StageList[stage], sendProcessBuffer, recvProcessBuffer, sharedProcessBuffer); + + sendBufferOffset += sendProcessBuffer.Length; + recvBufferOffset += recvProcessBuffer.Length; + sharedBufferOffset += sharedProcessBuffer.Length; + } + } + } + + public NetworkPipeline CreatePipeline(params Type[] stages) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (m_Pipelines.Length > 255) + throw new InvalidOperationException("Cannot create more than 255 pipelines on a single driver"); +#endif + var receiveCap = 0; + var sharedCap = 0; + var sendCap = 0; + var headerCap = 0; + var pipeline = new PipelineImpl(); + pipeline.FirstStageIndex = m_StageList.Length; + pipeline.NumStages = stages.Length; + for (int i = 0; i < stages.Length; i++) + { + var stageId = m_StageCollection.GetStageId(stages[i]); +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (stageId < 0) + throw new InvalidOperationException("Trying to create pipeline with invalid stage " + stages[i]); +#endif + m_StageList.Add(stageId); + receiveCap += m_StageCollection.GetReceiveCapacity(stageId); + sendCap += m_StageCollection.GetSendCapacity(stageId); + headerCap += m_StageCollection.GetHeaderCapacity(stageId); + sharedCap += m_StageCollection.GetSharedStateCapacity(stageId); + } + + // Make sure all data buffers are 4-byte aligned + receiveCap = (receiveCap + 3) & (~3); + sendCap = (sendCap + 3) & (~3); + sharedCap = (sharedCap + 3) & (~3); + + pipeline.receiveBufferOffset = sizePerConnection[RecveiveSizeOffset]; + sizePerConnection[RecveiveSizeOffset] = sizePerConnection[RecveiveSizeOffset] + receiveCap; + + pipeline.sendBufferOffset = sizePerConnection[SendSizeOffset]; + sizePerConnection[SendSizeOffset] = sizePerConnection[SendSizeOffset] + sendCap; + + pipeline.sharedBufferOffset = sizePerConnection[SharedSizeOffset]; + sizePerConnection[SharedSizeOffset] = sizePerConnection[SharedSizeOffset] + sharedCap; + + pipeline.headerCapacity = headerCap; + + m_Pipelines.Add(pipeline); + return new NetworkPipeline {Id = m_Pipelines.Length}; + } + + public void GetPipelineBuffers(Type pipelineType, NetworkConnection connection, ref NativeSlice readProcessingBuffer, ref NativeSlice writeProcessingBuffer, ref NativeSlice sharedBuffer) + { + var stageId = m_StageCollection.GetStageId(pipelineType); + + int pipelineId = 0; + int stageIndexInList = 0; + for (pipelineId = 0; pipelineId < m_Pipelines.Length; pipelineId++) + { + var pipelineImpl = m_Pipelines[pipelineId]; + for (stageIndexInList = pipelineImpl.FirstStageIndex; + stageIndexInList < pipelineImpl.FirstStageIndex + pipelineImpl.NumStages; + stageIndexInList++) + { + if (m_StageList[stageIndexInList] == stageId) + break; + } + } + + GetPipelineBuffers(new NetworkPipeline{Id = pipelineId}, stageId, connection, ref readProcessingBuffer, ref writeProcessingBuffer, ref sharedBuffer); + } + + public void GetPipelineBuffers(NetworkPipeline pipelineId, int stageId, NetworkConnection connection, + ref NativeSlice readProcessingBuffer, ref NativeSlice writeProcessingBuffer, + ref NativeSlice sharedBuffer) + { + var pipeline = m_Pipelines[pipelineId.Id-1]; + + int recvBufferOffset = pipeline.receiveBufferOffset + sizePerConnection[RecveiveSizeOffset] * connection.InternalId; + int sendBufferOffset = pipeline.sendBufferOffset + sizePerConnection[SendSizeOffset] * connection.InternalId; + int sharedBufferOffset = pipeline.sharedBufferOffset + sizePerConnection[SharedSizeOffset] * connection.InternalId; + + int stageIndexInList; + bool stageNotFound = true; + for (stageIndexInList = pipeline.FirstStageIndex; + stageIndexInList < pipeline.FirstStageIndex + pipeline.NumStages; + stageIndexInList++) + { + if (m_StageList[stageIndexInList] == stageId) + { + stageNotFound = false; + break; + } + sendBufferOffset += m_StageCollection.GetSendCapacity(m_StageList[stageIndexInList]); + recvBufferOffset += m_StageCollection.GetReceiveCapacity(m_StageList[stageIndexInList]); + sharedBufferOffset += m_StageCollection.GetSharedStateCapacity(m_StageList[stageIndexInList]); + } + + if (stageNotFound) +#if ENABLE_UNITY_COLLECTIONS_CHECKS + throw new InvalidOperationException("Could not find stage ID " + stageId + + " make sure the type for this stage ID is added when the pipeline is created."); +#else + return; +#endif + + writeProcessingBuffer = + new NativeSlice(m_SendBuffer, sendBufferOffset, m_StageCollection.GetSendCapacity(m_StageList[stageIndexInList])); + readProcessingBuffer = + new NativeSlice(m_ReceiveBuffer, recvBufferOffset, m_StageCollection.GetReceiveCapacity(m_StageList[stageIndexInList])); + sharedBuffer = + new NativeSlice(m_SharedBuffer, sharedBufferOffset, m_StageCollection.GetSharedStateCapacity(m_StageList[stageIndexInList])); + } + + internal struct UpdatePipeline + { + public NetworkPipeline pipeline; + public int stage; + public NetworkConnection connection; + } + + internal void UpdateSend(T driver, out int updateCount) where T : struct, INetworkPipelineSender + { + NativeArray sendUpdates = new NativeArray(m_SendStageNeedsUpdateRead.Count + m_SendStageNeedsUpdate.Length, Allocator.Temp); + + UpdatePipeline updateItem; + updateCount = 0; + while (m_SendStageNeedsUpdateRead.TryDequeue(out updateItem)) + { + sendUpdates[updateCount++] = updateItem; + } + + int startLength = updateCount; + for (int i = 0; i < m_SendStageNeedsUpdate.Length; i++) + { + sendUpdates[startLength + i] = m_SendStageNeedsUpdate[i]; + updateCount++; + } + + NativeList currentUpdates = new NativeList(128, Allocator.Temp); + // Move the updates requested in this iteration to the concurrent queue so it can be read/parsed in update routine + for (int i = 0; i < updateCount; ++i) + { + updateItem = sendUpdates[i]; + var inboundBuffer = default(NativeSlice); + ToConcurrent().ProcessPipelineSend(driver, updateItem.stage, updateItem.pipeline, updateItem.connection, inboundBuffer, currentUpdates); + } + for (int i = 0; i < currentUpdates.Length; ++i) + m_SendStageNeedsUpdateRead.Enqueue(currentUpdates[i]); + } + + private static void AddSendUpdate(NetworkConnection connection, int stageId, NetworkPipeline pipelineId, NativeList currentUpdates) + { + var newUpdate = new UpdatePipeline + {connection = connection, stage = stageId, pipeline = pipelineId}; + bool uniqueItem = true; + for (int j = 0; j < currentUpdates.Length; ++j) + { + if (currentUpdates[j].stage == newUpdate.stage && + currentUpdates[j].pipeline.Id == newUpdate.pipeline.Id && + currentUpdates[j].connection == newUpdate.connection) + uniqueItem = false; + } + if (uniqueItem) + currentUpdates.Add(newUpdate); + } + + public void UpdateReceive(T driver, out int updateCount) where T: struct, INetworkPipelineReceiver + { + updateCount = m_ReceiveStageNeedsUpdate.Length; + NativeArray receiveUpdates = new NativeArray(updateCount, Allocator.Temp); + + // Move current update requests to a new queue + for (int i = 0; i < updateCount; ++i) + receiveUpdates[i] = m_ReceiveStageNeedsUpdate[i]; + m_ReceiveStageNeedsUpdate.Clear(); + + // Process all current requested updates, new update requests will (possibly) be generated from the pipeline stages + for (int i = 0; i < receiveUpdates.Length; ++i) + { + UpdatePipeline updateItem = receiveUpdates[i]; + ProcessReceiveStagesFrom(driver, updateItem.stage, updateItem.pipeline, updateItem.connection, default(NativeSlice)); + } + } + + public void Receive(T driver, NetworkConnection connection, NativeSlice buffer) where T: struct, INetworkPipelineReceiver + { + byte pipelineId = buffer[0]; + var p = m_Pipelines[pipelineId-1]; + int startStage = p.NumStages - 1; + + ProcessReceiveStagesFrom(driver, startStage, new NetworkPipeline{Id = pipelineId}, connection, new NativeSlice(buffer, 1, buffer.Length -1)); + } + + private void ProcessReceiveStagesFrom(T driver, int startStage, NetworkPipeline pipeline, NetworkConnection connection, NativeSlice buffer) where T: struct, INetworkPipelineReceiver + { + var p = m_Pipelines[pipeline.Id-1]; + var connectionId = connection.m_NetworkId; + var resumeQ = new NativeList(16, Allocator.Temp); + int resumeQStart = 0; + + NetworkPipelineContext ctx = default(NetworkPipelineContext); + ctx.timestamp = Timestamp; + var inboundBuffer = new NativeSlice(buffer, 0, buffer.Length); + ctx.header = default(DataStreamWriter); + NativeList sendUpdates = new NativeList(128, Allocator.Temp); + + while (true) + { + bool needsUpdate = false; + bool needsSendUpdate = false; + int internalBufferOffset = p.receiveBufferOffset + sizePerConnection[RecveiveSizeOffset] * connectionId; + int internalSharedBufferOffset = p.sharedBufferOffset + sizePerConnection[SharedSizeOffset] * connectionId; + + // Adjust offset accounting for stages in front of the starting stage, since we're parsing the stages in reverse order + for (int st = 0; st < startStage; ++st) + { + internalBufferOffset += m_StageCollection.GetReceiveCapacity(m_StageList[p.FirstStageIndex+st]); + internalSharedBufferOffset += m_StageCollection.GetSharedStateCapacity(m_StageList[p.FirstStageIndex+st]); + } + + for (int i = startStage; i >= 0; --i) + { + ProcessReceiveStage(i, pipeline, internalBufferOffset, internalSharedBufferOffset, ref ctx, ref inboundBuffer, ref resumeQ, ref needsUpdate, ref needsSendUpdate); + if (needsUpdate) + { + var newUpdate = new UpdatePipeline + {connection = connection, stage = i, pipeline = pipeline}; + bool uniqueItem = true; + for (int j = 0; j < m_ReceiveStageNeedsUpdate.Length; ++j) + { + if (m_ReceiveStageNeedsUpdate[j].stage == newUpdate.stage && + m_ReceiveStageNeedsUpdate[j].pipeline.Id == newUpdate.pipeline.Id && + m_ReceiveStageNeedsUpdate[j].connection == newUpdate.connection) + uniqueItem = false; + } + if (uniqueItem) + m_ReceiveStageNeedsUpdate.Add(newUpdate); + } + + if (needsSendUpdate) + AddSendUpdate(connection, i, pipeline, m_SendStageNeedsUpdate); + + if (inboundBuffer.Length == 0) + break; + + // Offset needs to be adjusted for the next pipeline (the one in front of this one) + if (i > 0) + { + internalBufferOffset -= + m_StageCollection.GetReceiveCapacity(m_StageList[p.FirstStageIndex + i - 1]); + internalSharedBufferOffset -= + m_StageCollection.GetSharedStateCapacity(m_StageList[p.FirstStageIndex + i - 1]); + } + + needsUpdate = false; + } + + if (inboundBuffer.Length != 0) + driver.PushDataEvent(connection, inboundBuffer); + + if (resumeQStart >= resumeQ.Length) + { + return; + } + + startStage = resumeQ[resumeQStart++]; + inboundBuffer = default(NativeSlice); + } + } + + private void ProcessReceiveStage(int stage, NetworkPipeline pipeline, int internalBufferOffset, int internalSharedBufferOffset, ref NetworkPipelineContext ctx, ref NativeSlice inboundBuffer, ref NativeList resumeQ, ref bool needsUpdate, ref bool needsSendUpdate) + { + bool needsResume = false; + var p = m_Pipelines[pipeline.Id-1]; + + ctx.internalProcessBuffer = + new NativeSlice(m_ReceiveBuffer, internalBufferOffset, m_StageCollection.GetReceiveCapacity(m_StageList[p.FirstStageIndex+stage])); + ctx.internalSharedProcessBuffer = + new NativeSlice(m_SharedBuffer, internalSharedBufferOffset, m_StageCollection.GetSharedStateCapacity(m_StageList[p.FirstStageIndex+stage])); + var stageId = m_StageList[p.FirstStageIndex + stage]; + inboundBuffer = m_StageCollection.InvokeReceive(stageId, ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + + if (needsResume) + resumeQ.Add(stage); + } + } +} diff --git a/Runtime/NetworkPipeline.cs.meta b/Runtime/NetworkPipeline.cs.meta new file mode 100644 index 0000000..fa2b44a --- /dev/null +++ b/Runtime/NetworkPipeline.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 261474cc1fff8d34e9e95e2f2dfdd7f5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/NetworkProtocols.cs b/Runtime/NetworkProtocols.cs new file mode 100644 index 0000000..0807cfc --- /dev/null +++ b/Runtime/NetworkProtocols.cs @@ -0,0 +1,31 @@ +using System; +using System.Runtime.InteropServices; + +namespace Unity.Networking.Transport.Protocols +{ + public enum UdpCProtocol + { + ConnectionRequest, + ConnectionReject, + ConnectionAccept, + Disconnect, + Data + } + + [StructLayout(LayoutKind.Explicit)] + public unsafe struct UdpCHeader + { + [Flags] + public enum HeaderFlags : byte + { + HasConnectToken = 0x1, + HasPipeline = 0x2 + } + + public const int Length = 4; + [FieldOffset(0)] public fixed byte Data[Length]; + [FieldOffset(0)] public byte Type; + [FieldOffset(1)] public HeaderFlags Flags; + [FieldOffset(2)] public ushort SessionToken; + } +} \ No newline at end of file diff --git a/Runtime/NetworkProtocols.cs.meta b/Runtime/NetworkProtocols.cs.meta new file mode 100644 index 0000000..3a6bcda --- /dev/null +++ b/Runtime/NetworkProtocols.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: baae74db3a3900e47bdd9e2a930406c6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Pipelines.meta b/Runtime/Pipelines.meta new file mode 100644 index 0000000..1869653 --- /dev/null +++ b/Runtime/Pipelines.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2c439af55be04483ba9d0917fdc6eb98 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Pipelines/DefaultPipelineStageCollection.cs b/Runtime/Pipelines/DefaultPipelineStageCollection.cs new file mode 100644 index 0000000..e7d841c --- /dev/null +++ b/Runtime/Pipelines/DefaultPipelineStageCollection.cs @@ -0,0 +1,237 @@ +using System; +using Unity.Collections; +using Unity.Networking.Transport.Utilities; + +namespace Unity.Networking.Transport +{ + public struct NullPipelineStageCollection : INetworkPipelineStageCollection + { + public int GetStageId(Type type) + { + return -1; + } + + public void Initialize(params INetworkParameter[] param) + { + } + + public void InvokeInitialize(int pipelineStageId, NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, + NativeSlice sharedStateBuffer) + { + throw new NotImplementedException(); + } + + public InboundBufferVec InvokeSend(int pipelineStageId, NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate) + { + return inboundBuffer; + } + + public NativeSlice InvokeReceive(int pipelineStageId, NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate) + { + return inboundBuffer; + } + + public int GetReceiveCapacity(int pipelineStageId) + { + return 0; + } + + public int GetSendCapacity(int pipelineStageId) + { + return 0; + } + + public int GetHeaderCapacity(int pipelineStageId) + { + return 0; + } + + public int GetSharedStateCapacity(int pipelineStageId) + { + return 0; + } + } + + public struct DefaultPipelineStageCollection : INetworkPipelineStageCollection + { + private SimulatorPipelineStage m_SimulatorPipelineStage; + private SimulatorPipelineStageInSend m_SimulatorPipelineStageInSend; + private NullPipelineStage m_NullPipelineStage; + private UnreliableSequencedPipelineStage m_UnreliableSequencedPipelineStage; + private ReliableSequencedPipelineStage m_ReliableSequencedPipelineStage; + public int GetStageId(Type type) + { + if (type == typeof(SimulatorPipelineStage)) + return 0; + if (type == typeof(SimulatorPipelineStageInSend)) + return 1; + if (type == typeof(NullPipelineStage)) + return 2; + if (type == typeof(UnreliableSequencedPipelineStage)) + return 3; + if (type == typeof(ReliableSequencedPipelineStage)) + return 4; + return -1; + } + public void Initialize(params INetworkParameter[] param) + { + for (int i = 0; i < param.Length; ++i) + { + if (param[i] is SimulatorUtility.Parameters) + m_SimulatorPipelineStage.Initialize((SimulatorUtility.Parameters)param[i]); + if (param[i] is SimulatorUtility.Parameters) + m_SimulatorPipelineStageInSend.Initialize((SimulatorUtility.Parameters)param[i]); + if (param[i] is ReliableUtility.Parameters) + m_ReliableSequencedPipelineStage.Initialize((ReliableUtility.Parameters)param[i]); + } + } + public void InvokeInitialize(int pipelineStageId, NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, NativeSlice sharedStateBuffer) + { + switch (pipelineStageId) + { + case 0: + m_SimulatorPipelineStage.InitializeConnection(sendProcessBuffer, recvProcessBuffer, sharedStateBuffer); + break; + case 1: + m_SimulatorPipelineStageInSend.InitializeConnection(sendProcessBuffer, recvProcessBuffer, sharedStateBuffer); + break; + case 2: + m_NullPipelineStage.InitializeConnection(sendProcessBuffer, recvProcessBuffer, sharedStateBuffer); + break; + case 3: + m_UnreliableSequencedPipelineStage.InitializeConnection(sendProcessBuffer, recvProcessBuffer, sharedStateBuffer); + break; + case 4: + m_ReliableSequencedPipelineStage.InitializeConnection(sendProcessBuffer, recvProcessBuffer, sharedStateBuffer); + break; + } + } + public InboundBufferVec InvokeSend(int pipelineStageId, NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate) + { + switch (pipelineStageId) + { + case 0: + return m_SimulatorPipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate); + case 1: + return m_SimulatorPipelineStageInSend.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate); + case 2: + return m_NullPipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate); + case 3: + return m_UnreliableSequencedPipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate); + case 4: + return m_ReliableSequencedPipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate); + } + return inboundBuffer; + } + public NativeSlice InvokeReceive(int pipelineStageId, NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate) + { + switch (pipelineStageId) + { + case 0: + return m_SimulatorPipelineStage.Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + case 1: + return m_SimulatorPipelineStageInSend.Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + case 2: + return m_NullPipelineStage.Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + case 3: + return m_UnreliableSequencedPipelineStage.Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + case 4: + return m_ReliableSequencedPipelineStage.Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + } + return inboundBuffer; + } + public int GetReceiveCapacity(int pipelineStageId) + { + switch (pipelineStageId) + { + case 0: + return m_SimulatorPipelineStage.ReceiveCapacity; + case 1: + return m_SimulatorPipelineStageInSend.ReceiveCapacity; + case 2: + return m_NullPipelineStage.ReceiveCapacity; + case 3: + return m_UnreliableSequencedPipelineStage.ReceiveCapacity; + case 4: + return m_ReliableSequencedPipelineStage.ReceiveCapacity; + } + return 0; + } + public int GetSendCapacity(int pipelineStageId) + { + switch (pipelineStageId) + { + case 0: + return m_SimulatorPipelineStage.SendCapacity; + case 1: + return m_SimulatorPipelineStageInSend.SendCapacity; + case 2: + return m_NullPipelineStage.SendCapacity; + case 3: + return m_UnreliableSequencedPipelineStage.SendCapacity; + case 4: + return m_ReliableSequencedPipelineStage.SendCapacity; + } + return 0; + } + public int GetHeaderCapacity(int pipelineStageId) + { + switch (pipelineStageId) + { + case 0: + return m_SimulatorPipelineStage.HeaderCapacity; + case 1: + return m_SimulatorPipelineStageInSend.HeaderCapacity; + case 2: + return m_NullPipelineStage.HeaderCapacity; + case 3: + return m_UnreliableSequencedPipelineStage.HeaderCapacity; + case 4: + return m_ReliableSequencedPipelineStage.HeaderCapacity; + } + return 0; + } + public int GetSharedStateCapacity(int pipelineStageId) + { + switch (pipelineStageId) + { + case 0: + return m_SimulatorPipelineStage.SharedStateCapacity; + case 1: + return m_SimulatorPipelineStageInSend.SharedStateCapacity; + case 2: + return m_NullPipelineStage.SharedStateCapacity; + case 3: + return m_UnreliableSequencedPipelineStage.SharedStateCapacity; + case 4: + return m_ReliableSequencedPipelineStage.SharedStateCapacity; + } + return 0; + } + } + + public struct NullPipelineStage : INetworkPipelineStage + { + public NativeSlice Receive(NetworkPipelineContext ctx, NativeSlice inboundBuffer, + ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate) + { + return inboundBuffer; + } + + public InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, + ref bool needsUpdate) + { + return inboundBuffer; + } + + public void InitializeConnection(NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, + NativeSlice sharedProcessBuffer) + { + } + + public int ReceiveCapacity => 0; + public int SendCapacity => 0; + public int HeaderCapacity => 0; + public int SharedStateCapacity => 0; + } +} diff --git a/Runtime/Pipelines/DefaultPipelineStageCollection.cs.meta b/Runtime/Pipelines/DefaultPipelineStageCollection.cs.meta new file mode 100644 index 0000000..937269f --- /dev/null +++ b/Runtime/Pipelines/DefaultPipelineStageCollection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 299f00a4e7d7d1344a8e410a7b3e807c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Pipelines/ReliableSequencedPipelineStage.cs b/Runtime/Pipelines/ReliableSequencedPipelineStage.cs new file mode 100644 index 0000000..c65d83a --- /dev/null +++ b/Runtime/Pipelines/ReliableSequencedPipelineStage.cs @@ -0,0 +1,155 @@ +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Networking.Transport.Utilities; + +namespace Unity.Networking.Transport +{ + [NetworkPipelineInitilize(typeof(ReliableUtility.Parameters))] + public struct ReliableSequencedPipelineStage : INetworkPipelineStage + { + private ReliableUtility.Parameters m_ReliableParams; + + public NativeSlice Receive(NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate) + { + needsResume = false; + // Request a send update to see if a queued packet needs to be resent later or if an ack packet should be sent + needsSendUpdate = true; + + var context = default(DataStreamReader.Context); + var header = default(ReliableUtility.PacketHeader); + var slice = default(NativeSlice); + unsafe + { + ReliableUtility.Context* reliable = (ReliableUtility.Context*) ctx.internalProcessBuffer.GetUnsafePtr(); + ReliableUtility.SharedContext* shared = (ReliableUtility.SharedContext*) ctx.internalSharedProcessBuffer.GetUnsafePtr(); + shared->errorCode = 0; + if (reliable->Resume == ReliableUtility.NullEntry) + { + if (inboundBuffer.Length <= 0) + return slice; + var reader = new DataStreamReader(inboundBuffer); + reader.ReadBytes(ref context, (byte*)&header, UnsafeUtility.SizeOf()); + + if (header.Type == (ushort)ReliableUtility.PacketType.Ack) + { + ReliableUtility.ReadAckPacket(ctx, header); + inboundBuffer = new NativeSlice(); + return inboundBuffer; + } + + var result = ReliableUtility.Read(ctx, header); + + if (result >= 0) + { + var nextExpectedSequenceId = (ushort) (reliable->Delivered + 1); + if (result == nextExpectedSequenceId) + { + reliable->Delivered = result; + slice = inboundBuffer.Slice(UnsafeUtility.SizeOf()); + + if (needsResume = SequenceHelpers.GreaterThan16((ushort) shared->ReceivedPackets.Sequence, + (ushort) result)) + { + reliable->Resume = (ushort)(result + 1); + } + } + else + { + ReliableUtility.SetPacket(ctx.internalProcessBuffer, result, inboundBuffer.Slice(UnsafeUtility.SizeOf())); + slice = ReliableUtility.ResumeReceive(ctx, reliable->Delivered + 1, ref needsResume); + } + } + } + else + { + slice = ReliableUtility.ResumeReceive(ctx, reliable->Resume, ref needsResume); + } + } + return slice; + } + + public InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate) + { + // Request an update to see if a queued packet needs to be resent later or if an ack packet should be sent + needsUpdate = true; + + var header = new ReliableUtility.PacketHeader(); + unsafe + { + var reliable = (ReliableUtility.Context*) ctx.internalProcessBuffer.GetUnsafePtr(); + + needsResume = ReliableUtility.ReleaseOrResumePackets(ctx); + + if (inboundBuffer.buffer1.Length > 0) + { + reliable->LastSentTime = ctx.timestamp; + + ReliableUtility.Write(ctx, inboundBuffer, ref header); + ctx.header.WriteBytes((byte*)&header, UnsafeUtility.SizeOf()); + if (reliable->Resume != ReliableUtility.NullEntry) + needsResume = true; + + reliable->PreviousTimestamp = ctx.timestamp; + return inboundBuffer; + } + + if (reliable->Resume != ReliableUtility.NullEntry) + { + reliable->LastSentTime = ctx.timestamp; + var slice = ReliableUtility.ResumeSend(ctx, out header, ref needsResume); + ctx.header.Clear(); + ctx.header.WriteBytes((byte*)&header, UnsafeUtility.SizeOf()); + inboundBuffer.buffer1 = slice; + inboundBuffer.buffer2 = default(NativeSlice); + reliable->PreviousTimestamp = ctx.timestamp; + return inboundBuffer; + } + + if (ReliableUtility.ShouldSendAck(ctx)) + { + reliable->LastSentTime = ctx.timestamp; + + ReliableUtility.WriteAckPacket(ctx, ref header); + ctx.header.WriteBytes((byte*)&header, UnsafeUtility.SizeOf()); + reliable->PreviousTimestamp = ctx.timestamp; + + // TODO: Sending dummy byte over since the pipeline won't send an empty payload (ignored on receive) + inboundBuffer.buffer1 = new NativeSlice(ctx.internalProcessBuffer, 0, 1); + return inboundBuffer; + } + reliable->PreviousTimestamp = ctx.timestamp; + return inboundBuffer; + } + } + + public void InitializeConnection(NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, + NativeSlice sharedProcessBuffer) + { + if (sharedProcessBuffer.Length >= ReliableUtility.SharedCapacityNeeded(m_ReliableParams) && + (sendProcessBuffer.Length + recvProcessBuffer.Length) >= ReliableUtility.ProcessCapacityNeeded(m_ReliableParams) * 2) + { + ReliableUtility.InitializeContext(sharedProcessBuffer, sendProcessBuffer, recvProcessBuffer, m_ReliableParams); + } + } + + public void Initialize(ReliableUtility.Parameters param) + { + m_ReliableParams = param; + } + + public int HeaderCapacity => UnsafeUtility.SizeOf(); + + public int SharedStateCapacity + { + get { if (m_ReliableParams.WindowSize == 0) m_ReliableParams = new ReliableUtility.Parameters{WindowSize = ReliableUtility.ParameterConstants.WindowSize}; return ReliableUtility.SharedCapacityNeeded(m_ReliableParams);} + } + public int ReceiveCapacity + { + get { if (m_ReliableParams.WindowSize == 0) m_ReliableParams = new ReliableUtility.Parameters{WindowSize = ReliableUtility.ParameterConstants.WindowSize}; return ReliableUtility.ProcessCapacityNeeded(m_ReliableParams);} + } + public int SendCapacity + { + get { if (m_ReliableParams.WindowSize == 0) m_ReliableParams = new ReliableUtility.Parameters{WindowSize = ReliableUtility.ParameterConstants.WindowSize}; return ReliableUtility.ProcessCapacityNeeded(m_ReliableParams);} + } + } +} diff --git a/Runtime/Pipelines/ReliableSequencedPipelineStage.cs.meta b/Runtime/Pipelines/ReliableSequencedPipelineStage.cs.meta new file mode 100644 index 0000000..26072e0 --- /dev/null +++ b/Runtime/Pipelines/ReliableSequencedPipelineStage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d4a883e653375453c8a2dcaec90940a2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Pipelines/ReliableUtility.cs b/Runtime/Pipelines/ReliableUtility.cs new file mode 100644 index 0000000..3f19cee --- /dev/null +++ b/Runtime/Pipelines/ReliableUtility.cs @@ -0,0 +1,754 @@ +using System; +using System.Runtime.InteropServices; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; + +namespace Unity.Networking.Transport.Utilities +{ + public struct SequenceBufferContext + { + public int Sequence; + public int Acked; + public uint AckMask; + } + + public struct ReliableUtility + { + public struct Statistics + { + public int PacketsReceived; + public int PacketsSent; + public int PacketsDropped; + public int PacketsOutOfOrder; + public int PacketsDuplicated; + public int PacketsStale; + public int PacketsResent; + } + + public struct RTTInfo + { + public int LastRtt; + public float SmoothedRtt; + public float SmoothedVariance; + public int ResendTimeout; + } + + public const int NullEntry = -1; + // The least amount of time we'll wait until a packet resend is performed + // This is 4x16ms (assumes a 60hz update rate) + public const int DefaultMinimumResendTime = 64; + public const int MaximumResendTime = 200; + + public enum ErrorCodes + { + Stale_Packet = -1, + Duplicated_Packet = -2, + + OutgoingQueueIsFull = -7, + InsufficientMemory = -8 + } + + public enum PacketType : ushort + { + Payload = 0, + Ack = 1 + } + + public struct SharedContext + { + public int WindowSize; + public int MinimumResendTime; + + /// + /// Context of sent packets, last sequence ID sent (-1), last ID of our sent packet acknowledged by + /// remote peer, ackmask of acknowledged packets. This is used when determining if a resend + /// is needed. + /// + public SequenceBufferContext SentPackets; + /// + /// Context of received packets, last sequence ID received, and ackmask of received packets. Acked is not used. + /// This is sent back to the remote peer in the header when sending. + /// + public SequenceBufferContext ReceivedPackets; + public Statistics stats; + public ErrorCodes errorCode; + + // Timing information for calculating resend times for packets + public RTTInfo RttInfo; + public int TimerDataOffset; + public int TimerDataStride; + public int RemoteTimerDataOffset; + public int RemoteTimerDataStride; + } + + public struct Context + { + public int Capacity; + public int Resume; + public int Delivered; + public int IndexStride; + public int IndexPtrOffset; + public int DataStride; + public int DataPtrOffset; + public long LastSentTime; + public long PreviousTimestamp; + } + + public struct Parameters : INetworkParameter + { + public int WindowSize; + } + + public struct ParameterConstants + { + public const int WindowSize = 32; + } + + [StructLayout(LayoutKind.Sequential)] + public struct PacketHeader + { + public ushort Type; + public ushort ProcessingTime; + public ushort SequenceId; + public ushort AckedSequenceId; + public uint AckMask; + } + + [StructLayout(LayoutKind.Sequential)] + public struct PacketInformation + { + public int SequenceId; + public int Size; + public long SendTime; + } + + // Header is inside the total packet length (Buffer size) + [StructLayout(LayoutKind.Explicit)] + public unsafe struct Packet + { + internal const int Length = NetworkParameterConstants.MTU; + [FieldOffset(0)] public PacketHeader Header; + [FieldOffset(0)] public fixed byte Buffer[Length]; + } + + [StructLayout(LayoutKind.Sequential)] + public struct PacketTimers + { + public ushort ProcessingTime; + public ushort Padding; + public int SequenceId; + public long SentTime; + public long ReceiveTime; + } + + public static int SharedCapacityNeeded(Parameters param) + { + int capacityNeeded; + unsafe + { + // Timers are stored for both remote packets (processing time) and local packets (round trip time) + // The amount of timestamps needed in the queues is the same as the window size capacity + var timerDataSize = sizeof(PacketTimers) * param.WindowSize * 2; + capacityNeeded = sizeof(SharedContext) + timerDataSize; + } + return capacityNeeded; + } + + public static int ProcessCapacityNeeded(Parameters param) + { + int capacityNeeded; + unsafe + { + var infoSize = param.WindowSize * UnsafeUtility.SizeOf(); + var dataSize = param.WindowSize * Packet.Length; + + capacityNeeded = sizeof(Context)+ infoSize + dataSize; + } + return capacityNeeded; + } + + public static unsafe SharedContext InitializeContext(NativeSlice sharedBuffer, NativeSlice sendBuffer, NativeSlice recvBuffer, Parameters param) + { + InitializeProcessContext(sendBuffer, param); + InitializeProcessContext(recvBuffer, param); + + SharedContext* notifier = (SharedContext*) sharedBuffer.GetUnsafePtr(); + *notifier = new SharedContext + { + WindowSize = param.WindowSize, + SentPackets = new SequenceBufferContext { Acked = NullEntry }, + MinimumResendTime = DefaultMinimumResendTime, + ReceivedPackets = new SequenceBufferContext { Sequence = NullEntry }, + RttInfo = new RTTInfo { SmoothedVariance = 5, SmoothedRtt = 50, ResendTimeout = 50, LastRtt = 50}, + TimerDataOffset = UnsafeUtility.SizeOf(), + TimerDataStride = UnsafeUtility.SizeOf(), + RemoteTimerDataOffset = UnsafeUtility.SizeOf() + UnsafeUtility.SizeOf() * param.WindowSize, + RemoteTimerDataStride = UnsafeUtility.SizeOf() + }; + return *notifier; + } + + public static unsafe int InitializeProcessContext(NativeSlice self, Parameters param) + { + int totalCapacity = ProcessCapacityNeeded(param); + if (self.Length != totalCapacity) + { + return (int) ErrorCodes.InsufficientMemory; + } + Context* ctx = (Context*) self.GetUnsafePtr(); + + ctx->Capacity = param.WindowSize; + ctx->IndexStride = (UnsafeUtility.SizeOf() + 3) & ~3; + ctx->IndexPtrOffset = sizeof(Context); + ctx->DataStride = (Packet.Length + 3) & ~3; + ctx->DataPtrOffset = ctx->IndexPtrOffset + (ctx->IndexStride * ctx->Capacity); + ctx->Resume = NullEntry; + ctx->Delivered = NullEntry; + + Release(self, 0, param.WindowSize); + return 0; + } + + public static unsafe void SetPacket(NativeSlice self, int sequence, NativeSlice data) + { + SetPacket(self, sequence, data.GetUnsafeReadOnlyPtr(), data.Length); + } + + public static unsafe void SetPacket(NativeSlice self, int sequence, void* data, int length) + { + byte *ptr = (byte*)self.GetUnsafePtr(); + Context* ctx = (Context*) ptr; + + if (length > ctx->DataStride) +#if ENABLE_UNITY_COLLECTIONS_CHECKS + throw new OverflowException(); +#else + return; +#endif + + var index = sequence % ctx->Capacity; + + PacketInformation* info = GetPacketInformation(self, sequence); + info->SequenceId = sequence; + info->Size = length; + info->SendTime = -1; // Not used for packets queued for resume receive + + var offset = ctx->DataPtrOffset + (index * ctx->DataStride); + void* dataPtr = (ptr + offset); + + UnsafeUtility.MemCpy(dataPtr, data, length); + } + + /// + /// Write packet, packet header and tracking information to the given buffer space. This buffer + /// should contain the reliability Context at the front, that contains the capacity of the buffer + /// and pointer offsets needed to find the slots we can copy the packet to. + /// + /// Buffer space where we can store packets. + /// The sequence ID of the packet, this is used to find a slot inside the buffer. + /// The packet header which we'll store with the packet payload. + /// The packet data which we're storing. + /// + public static unsafe void SetHeaderAndPacket(NativeSlice self, int sequence, PacketHeader header, InboundBufferVec data, long timestamp) + { + byte *ptr = (byte*)self.GetUnsafePtr(); + Context* ctx = (Context*) ptr; + int totalSize = data.buffer1.Length + data.buffer2.Length; + + if (totalSize > ctx->DataStride) +#if ENABLE_UNITY_COLLECTIONS_CHECKS + throw new OverflowException(); +#else + return; +#endif + var index = sequence % ctx->Capacity; + + PacketInformation* info = GetPacketInformation(self, sequence); + info->SequenceId = sequence; + info->Size = totalSize; + info->SendTime = timestamp; + + Packet* packet = GetPacket(self, sequence); + packet->Header = header; + var offset = (ctx->DataPtrOffset + (index * ctx->DataStride)) + UnsafeUtility.SizeOf(); + void* dataPtr = (ptr + offset); + + if (data.buffer1.Length > 0) + UnsafeUtility.MemCpy(dataPtr, data.buffer1.GetUnsafeReadOnlyPtr(), data.buffer1.Length); + if (data.buffer2.Length > 0) + UnsafeUtility.MemCpy(&dataPtr + data.buffer1.Length, data.buffer2.GetUnsafeReadOnlyPtr(), data.buffer2.Length); + } + + public static unsafe PacketInformation* GetPacketInformation(NativeSlice self, int sequence) + { + byte *ptr = (byte*)self.GetUnsafePtr(); + Context* ctx = (Context*) ptr; + var index = sequence % ctx->Capacity; + + return (PacketInformation*) ((ptr + ctx->IndexPtrOffset) + (index * ctx->IndexStride)); + } + + public static unsafe Packet* GetPacket(NativeSlice self, int sequence) + { + byte *ptr = (byte*)self.GetUnsafePtr(); + Context* ctx = (Context*) ptr; + var index = sequence % ctx->Capacity; + + var offset = ctx->DataPtrOffset + (index * ctx->DataStride); + return (Packet*) (ptr + offset); + } + + public static unsafe bool TryAquire(NativeSlice self, int sequence) + { + Context* ctx = (Context*) self.GetUnsafePtr(); + + var index = sequence % ctx->Capacity; + + var currentSequenceId = GetIndex(self, index); + if (currentSequenceId == NullEntry) + { + SetIndex(self, index, sequence); + return true; + } + return false; + } + + public static unsafe void Release(NativeSlice self, int sequence) + { + Release(self, sequence, 1); + } + + public static unsafe void Release(NativeSlice self, int start_sequence, int count) + { + Context* ctx = (Context*) self.GetUnsafePtr(); + var index = start_sequence % ctx->Capacity; + for (int i = 0; i < count; i++) + { + SetIndex(self, index + i, NullEntry); + } + } + + static unsafe void SetIndex(NativeSlice self, int index, int sequence) + { + byte *ptr = (byte*)self.GetUnsafePtr(); + Context* ctx = (Context*) ptr; + + int* value = (int*) ((ptr + ctx->IndexPtrOffset) + (index * ctx->IndexStride)); + *value = sequence; + } + + static unsafe int GetIndex(NativeSlice self, int index) + { + byte *ptr = (byte*)self.GetUnsafePtr(); + Context* ctx = (Context*) ptr; + + int* value = (int*) ((ptr + ctx->IndexPtrOffset) + (index * ctx->IndexStride)); + return *value; + } + + /// + /// Acknowledge the reception of packets which have been sent. The reliability + /// shared context/state is updated when packets are received from the other end + /// of the connection. The other side will update it's ackmask with which packets + /// have been received (starting from last received sequence ID) each time it sends + /// a packet back. This checks the resend timers on each non-acknowledged packet + /// and notifies if it's time to resend yet. + /// + /// Pipeline context, contains the buffer slices this pipeline connection owns. + /// + public static unsafe bool ReleaseOrResumePackets(NetworkPipelineContext context) + { + SharedContext* reliable = (SharedContext*) context.internalSharedProcessBuffer.GetUnsafePtr(); + Context* ctx = (Context*) context.internalProcessBuffer.GetUnsafePtr(); + + // Last sequence ID and ackmask we received from the remote peer, these are confirmed delivered packets + var lastReceivedAckMask = reliable->SentPackets.AckMask; + var lastOwnSequenceIdAckedByRemote = (ushort)reliable->SentPackets.Acked; + + // To deal with wrapping, chop off the upper half of the sequence ID and multiply by window size, it + // will then never wrap but will map to the correct index in the packet storage, wrapping happens when + // sending low sequence IDs (since it checks sequence IDs backwards in time). + var sequence = (ushort)(reliable->WindowSize * ((1 - lastOwnSequenceIdAckedByRemote)>>15)); + + // Check each slot in the window, starting from the sequence ID calculated above (this isn't the + // latest sequence ID though as it was adjusted to avoid wrapping) + for (int i = 0; i < reliable->WindowSize; i++) + { + var info = GetPacketInformation(context.internalProcessBuffer, sequence); + if (info->SequenceId >= 0) + { + // Check the bit for this sequence ID against the ackmask. Bit 0 in the ackmask is the latest + // ackedSeqId, bit 1 latest ackedSeqId - 1 (one older) and so on. If bit X is 1 then ackedSeqId-X is acknowledged + var ackBits = 1 << (lastOwnSequenceIdAckedByRemote - info->SequenceId); + + // Release if this seqId has been flipped on in the ackmask (so it's acknowledged) + // Ignore if sequence ID is out of window range of the last acknowledged id + if (SequenceHelpers.AbsDistance((ushort)lastOwnSequenceIdAckedByRemote, (ushort)info->SequenceId) < reliable->WindowSize && (ackBits & lastReceivedAckMask) != 0) + { + Release(context.internalProcessBuffer, info->SequenceId); + info->SendTime = -1; + sequence = (ushort) (sequence - 1); + continue; + } + var timeToResend = CurrentResendTime(context.internalSharedProcessBuffer); + if (context.timestamp > info->SendTime + timeToResend) + { + ctx->Resume = info->SequenceId; + } + } + sequence = (ushort) (sequence - 1); + } + return ctx->Resume != NullEntry; + } + + /// + /// Resume or play back a packet we had received earlier out of order. When an out of order packet is received + /// it is stored since we need to first return the packet with the next sequence ID. When that packet finally + /// arrives it is returned but a pipeline resume is requested since we already have the next packet stored + /// and it can be processed immediately after. + /// + /// Pipeline context, we'll use both the shared reliability context and receive context. + /// The first packet which we need to retrieve now, there could be more after that. + /// Indicates if we need the pipeline to resume again. + /// + public static unsafe NativeSlice ResumeReceive(NetworkPipelineContext context, int startSequence, ref bool needsResume) + { + if (startSequence == NullEntry) return default(NativeSlice); + + SharedContext* shared = (SharedContext*) context.internalSharedProcessBuffer.GetUnsafePtr(); + Context* reliable = (Context*)context.internalProcessBuffer.GetUnsafePtr(); + + reliable->Resume = NullEntry; + + PacketInformation* info = GetPacketInformation(context.internalProcessBuffer, startSequence); + var latestReceivedPacket = shared->ReceivedPackets.Sequence; + if (info->SequenceId == startSequence) + { + var offset = reliable->DataPtrOffset + ((startSequence % reliable->Capacity) * reliable->DataStride); + NativeSlice slice = new NativeSlice(context.internalProcessBuffer, offset, info->Size); + reliable->Delivered = startSequence; + + if ((ushort)(startSequence + 1) <= latestReceivedPacket) + { + reliable->Resume = (ushort)(startSequence + 1); + needsResume = true; + } + return slice; + } + return default(NativeSlice); + } + + /// + /// Resend a packet which we have not received an acknowledgement for in time. Pipeline resume + /// will be enabled if there are more packets which we need to resend. The send reliability context + /// will then also be updated to track the next packet we need to resume. + /// + /// Pipeline context, we'll use both the shared reliability context and send context. + /// Packet header for the packet payload we're resending. + /// Indicates if a pipeline resume is needed again. + /// Buffer slice to packet payload. + /// + public static unsafe NativeSlice ResumeSend(NetworkPipelineContext context, out PacketHeader header, ref bool needsResume) + { + SharedContext* reliable = (SharedContext*) context.internalSharedProcessBuffer.GetUnsafePtr(); + Context* ctx = (Context*)context.internalProcessBuffer.GetUnsafePtr(); + +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (ctx->Resume == NullEntry) + throw new ApplicationException("This function should not be called unless there is data in resume"); +#endif + + var sequence = (ushort) ctx->Resume; + + PacketInformation* information; + information = GetPacketInformation(context.internalProcessBuffer, sequence); + // Reset the resend timer + information->SendTime = context.timestamp; + + Packet *packet = GetPacket(context.internalProcessBuffer, sequence); + header = packet->Header; + + // Update acked/ackmask to latest values + header.AckedSequenceId = (ushort) reliable->ReceivedPackets.Sequence; + header.AckMask = reliable->ReceivedPackets.AckMask; + + var offset = (ctx->DataPtrOffset + ((sequence % ctx->Capacity) * ctx->DataStride)) + UnsafeUtility.SizeOf(); + + NativeSlice slice = new NativeSlice(context.internalProcessBuffer, offset, information->Size); + reliable->stats.PacketsResent++; + + needsResume = false; + ctx->Resume = -1; + + // Check if another packet needs to be resent right after this one + for (int i = sequence + 1; i < reliable->ReceivedPackets.Sequence + 1; i++) + { + var timeToResend = CurrentResendTime(context.internalSharedProcessBuffer); + information = GetPacketInformation(context.internalProcessBuffer, i); + if (information->SequenceId >= 0 && information->SendTime + timeToResend > context.timestamp) + { + needsResume = true; + ctx->Resume = i; + } + } + return slice; + } + + /// + /// Store the packet for possible later resends, and fill in the header we'll use to send it (populate with + /// sequence ID, last acknowledged ID from remote with ackmask. + /// + /// Pipeline context, the reliability shared state is used here. + /// Buffer with packet data. + /// Packet header which will be populated. + /// Sequence ID assigned to this packet. + public static unsafe int Write(NetworkPipelineContext context, InboundBufferVec inboundBuffer, ref PacketHeader header) + { + SharedContext* reliable = (SharedContext*) context.internalSharedProcessBuffer.GetUnsafePtr(); + + var sequence = (ushort) reliable->SentPackets.Sequence; + + if (!TryAquire(context.internalProcessBuffer, sequence)) + { + reliable->errorCode = ErrorCodes.OutgoingQueueIsFull; + return (int)ErrorCodes.OutgoingQueueIsFull; + } + reliable->stats.PacketsSent++; + + header.SequenceId = sequence; + header.AckedSequenceId = (ushort) reliable->ReceivedPackets.Sequence; + header.AckMask = reliable->ReceivedPackets.AckMask; + + reliable->ReceivedPackets.Acked = reliable->ReceivedPackets.Sequence; + + // Attach our processing time of the packet we're acknowledging (time between receiving it and sending this ack) + header.ProcessingTime = + CalculateProcessingTime(context.internalSharedProcessBuffer, header.AckedSequenceId, context.timestamp); + + reliable->SentPackets.Sequence = (ushort) (reliable->SentPackets.Sequence + 1); + SetHeaderAndPacket(context.internalProcessBuffer, sequence, header, inboundBuffer, context.timestamp); + + StoreTimestamp(context.internalSharedProcessBuffer, sequence, context.timestamp); + + return sequence; + } + + /// + /// Write an ack packet, only the packet header is used and this doesn't advance the sequence ID. + /// The packet is not stored away for resend routine. + /// + /// Pipeline context, the reliability shared state is used here. + /// Packet header which will be populated. + /// + public static unsafe void WriteAckPacket(NetworkPipelineContext context, ref PacketHeader header) + { + SharedContext* reliable = (SharedContext*) context.internalSharedProcessBuffer.GetUnsafePtr(); + + header.Type = (ushort)PacketType.Ack; + header.AckedSequenceId = (ushort) reliable->ReceivedPackets.Sequence; + header.AckMask = reliable->ReceivedPackets.AckMask; + header.ProcessingTime = + CalculateProcessingTime(context.internalSharedProcessBuffer, header.AckedSequenceId, context.timestamp); + reliable->ReceivedPackets.Acked = reliable->ReceivedPackets.Sequence; + } + + public static unsafe void StoreTimestamp(NativeSlice sharedBuffer, ushort sequenceId, long timestamp) + { + var timerData = GetLocalPacketTimer(sharedBuffer, sequenceId); + timerData->SequenceId = sequenceId; + timerData->SentTime = timestamp; + timerData->ProcessingTime = 0; + timerData->ReceiveTime = 0; + } + + public static unsafe void StoreReceiveTimestamp(NativeSlice sharedBuffer, ushort sequenceId, long timestamp, ushort processingTime) + { + var sharedCtx = (SharedContext*) sharedBuffer.GetUnsafePtr(); + var rttInfo = sharedCtx->RttInfo; + var timerData = GetLocalPacketTimer(sharedBuffer, sequenceId); + if (timerData != null && timerData->SequenceId == sequenceId) + { + // Ignore the receive time if we've already received it (remote doesn't have new acks) + if (timerData->ReceiveTime > 0) + return; + timerData->ReceiveTime = timestamp; + timerData->ProcessingTime = processingTime; + + 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.ResendTimeout = (int)(rttInfo.SmoothedRtt + 4 * rttInfo.SmoothedVariance); + sharedCtx->RttInfo = rttInfo; + } + } + + public static unsafe void StoreRemoteReceiveTimestamp(NativeSlice sharedBuffer, ushort sequenceId, long timestamp) + { + var timerData = GetRemotePacketTimer(sharedBuffer, sequenceId); + timerData->SequenceId = sequenceId; + timerData->ReceiveTime = timestamp; + } + + static unsafe int CurrentResendTime(NativeSlice sharedBuffer) + { + var sharedCtx = (SharedContext*) sharedBuffer.GetUnsafePtr(); + if (sharedCtx->RttInfo.ResendTimeout > MaximumResendTime) + return MaximumResendTime; + return Math.Max(sharedCtx->RttInfo.ResendTimeout, sharedCtx->MinimumResendTime); + } + + public static unsafe ushort CalculateProcessingTime(NativeSlice sharedBuffer, ushort sequenceId, long timestamp) + { + // Look up previously recorded receive timestamp, subtract that from current timestamp and return as processing time + var timerData = GetRemotePacketTimer(sharedBuffer, sequenceId); + if (timerData != null && timerData->SequenceId == sequenceId) + return Math.Min((ushort) (timestamp - timerData->ReceiveTime), ushort.MaxValue); + return 0; + } + + public static unsafe PacketTimers* GetLocalPacketTimer(NativeSlice sharedBuffer, ushort sequenceId) + { + var sharedCtx = (SharedContext*) sharedBuffer.GetUnsafePtr(); + var index = sequenceId % sharedCtx->WindowSize; + var timerPtr = (long)sharedBuffer.GetUnsafePtr() + sharedCtx->TimerDataOffset + sharedCtx->TimerDataStride * index; + return (PacketTimers*) timerPtr; + } + + public static unsafe PacketTimers* GetRemotePacketTimer(NativeSlice sharedBuffer, ushort sequenceId) + { + var sharedCtx = (SharedContext*) sharedBuffer.GetUnsafePtr(); + var index = sequenceId % sharedCtx->WindowSize; + var timerPtr = (long)sharedBuffer.GetUnsafePtr() + sharedCtx->RemoteTimerDataOffset + sharedCtx->RemoteTimerDataStride * index; + return (PacketTimers*) timerPtr; + } + + /// + /// Read header data and update reliability tracking information in the shared context. + /// - If the packets sequence ID is lower than the last received ID+1, then it's stale + /// - If the packets sequence ID is higher, then we'll process it and update tracking info in the shared context + /// + /// Pipeline context, the reliability shared state is used here. + /// Packet header of a new received packet. + /// Sequence ID of the received packet. + public static unsafe int Read(NetworkPipelineContext context, PacketHeader header) + { + SharedContext* reliable = (SharedContext*) context.internalSharedProcessBuffer.GetUnsafePtr(); + + reliable->stats.PacketsReceived++; + if (SequenceHelpers.StalePacket( + header.SequenceId, + (ushort) (reliable->ReceivedPackets.Sequence + 1), + (ushort) reliable->WindowSize)) + { + reliable->stats.PacketsStale++; + return (int) ErrorCodes.Stale_Packet; + } + + var window = reliable->WindowSize - 1; + if (SequenceHelpers.GreaterThan16((ushort) (header.SequenceId + 1), (ushort) reliable->ReceivedPackets.Sequence)) + { + int distance = SequenceHelpers.AbsDistance(header.SequenceId, (ushort)reliable->ReceivedPackets.Sequence); + + for (var i = 0; i < Math.Min(distance, window); ++i) + { + if ((reliable->ReceivedPackets.AckMask & 1 << (window - i)) == 0) + { + reliable->stats.PacketsDropped++; + } + } + + if (distance > window) + { + reliable->stats.PacketsDropped += distance - window; + reliable->ReceivedPackets.AckMask = 1; + } + else + { + reliable->ReceivedPackets.AckMask <<= distance; + reliable->ReceivedPackets.AckMask |= 1; + } + + reliable->ReceivedPackets.Sequence = header.SequenceId; + } + else if (SequenceHelpers.LessThan16(header.SequenceId, (ushort) reliable->ReceivedPackets.Sequence)) + { + 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 + if (distance >= ushort.MaxValue - reliable->WindowSize) + distance = reliable->ReceivedPackets.Sequence - header.SequenceId; + + var ackBit = 1 << distance; + if ((ackBit & reliable->ReceivedPackets.AckMask) != 0) + { + reliable->stats.PacketsDuplicated++; + return (int) ErrorCodes.Duplicated_Packet; + } + + reliable->stats.PacketsOutOfOrder++; + reliable->ReceivedPackets.AckMask |= (uint) ackBit; + } + + // Store receive timestamp for remote sequence ID we just received + StoreRemoteReceiveTimestamp(context.internalSharedProcessBuffer, header.SequenceId, context.timestamp); + + ReadAckPacket(context, header); + + return header.SequenceId; + } + + public static unsafe void ReadAckPacket(NetworkPipelineContext context, PacketHeader header) + { + SharedContext* reliable = (SharedContext*) context.internalSharedProcessBuffer.GetUnsafePtr(); + + // Store receive timestamp for our acked sequence ID with remote processing time + StoreReceiveTimestamp(context.internalSharedProcessBuffer, header.AckedSequenceId, context.timestamp, header.ProcessingTime); + + // Check the distance of the acked seqId in the header, if it's too far away from last acked packet we + // can't process it and add it to the ack mask + if (!SequenceHelpers.GreaterThan16(header.AckedSequenceId, (ushort) reliable->SentPackets.Acked)) + { + // No new acks; + return; + } + + reliable->SentPackets.Acked = header.AckedSequenceId; + reliable->SentPackets.AckMask = header.AckMask; + } + + public static unsafe bool ShouldSendAck(NetworkPipelineContext ctx) + { + var reliable = (Context*) ctx.internalProcessBuffer.GetUnsafePtr(); + var shared = (SharedContext*) ctx.internalSharedProcessBuffer.GetUnsafePtr(); + + // If more than one full frame (timestamp - prevTimestamp = one frame) has elapsed then send ack packet + // and if the last received sequence ID has not been acked yet + if (reliable->LastSentTime < reliable->PreviousTimestamp && + shared->ReceivedPackets.Acked < shared->ReceivedPackets.Sequence) + return true; + return false; + } + + public static unsafe void SetMinimumResendTime(int value, UdpNetworkDriver driver, + NetworkPipeline pipeline, int stageId, NetworkConnection con) + { + NativeSlice receiveBuffer = default(NativeSlice); + NativeSlice sendBuffer = default(NativeSlice); + NativeSlice sharedBuffer = default(NativeSlice); + driver.GetPipelineBuffers(pipeline, stageId, con, ref receiveBuffer, ref sendBuffer, ref sharedBuffer); + var sharedCtx = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedCtx->MinimumResendTime = value; + } + + public static unsafe void SetMinimumResendTime(int value, LocalNetworkDriver driver, + NetworkPipeline pipeline, int stageId, NetworkConnection con) + { + NativeSlice receiveBuffer = default(NativeSlice); + NativeSlice sendBuffer = default(NativeSlice); + NativeSlice sharedBuffer = default(NativeSlice); + driver.GetPipelineBuffers(pipeline, stageId, con, ref receiveBuffer, ref sendBuffer, ref sharedBuffer); + var sharedCtx = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedCtx->MinimumResendTime = value; + } + } + } diff --git a/Runtime/Pipelines/ReliableUtility.cs.meta b/Runtime/Pipelines/ReliableUtility.cs.meta new file mode 100644 index 0000000..bcb530c --- /dev/null +++ b/Runtime/Pipelines/ReliableUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d04421de89975435aa55643e2d609958 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Pipelines/SimulatorPipelineStage.cs b/Runtime/Pipelines/SimulatorPipelineStage.cs new file mode 100644 index 0000000..7954e9b --- /dev/null +++ b/Runtime/Pipelines/SimulatorPipelineStage.cs @@ -0,0 +1,144 @@ +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Networking.Transport.Utilities; + +namespace Unity.Networking.Transport +{ + [NetworkPipelineInitilize(typeof(SimulatorUtility.Parameters))] + public struct SimulatorPipelineStage : INetworkPipelineStage + { + private SimulatorUtility.Parameters m_SimulatorParams; + + // Setup simulation parameters which get capacity function depends on, so buffer size can be correctly allocated + public void Initialize(SimulatorUtility.Parameters param) + { + m_SimulatorParams = param; + } + + public unsafe NativeSlice Receive(NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate) + { + var param = (SimulatorUtility.Context*) ctx.internalSharedProcessBuffer.GetUnsafePtr(); + var simulator = new SimulatorUtility(m_SimulatorParams.MaxPacketCount, m_SimulatorParams.MaxPacketSize, m_SimulatorParams.PacketDelayMs, m_SimulatorParams.PacketJitterMs); + if (inboundBuffer.Length > m_SimulatorParams.MaxPacketSize) + { + //UnityEngine.Debug.LogWarning("Incoming packet too large for internal storage buffer. Passing through. [buffer=" + inboundBuffer.Length + " packet=" + param->MaxPacketSize + "]"); + // TODO: Add error code for this + return inboundBuffer; + } + + var timestamp = ctx.timestamp; + + // Inbound buffer is empty if this is a resumed receive + if (inboundBuffer.Length > 0) + { + param->PacketCount++; + + if (simulator.ShouldDropPacket(param, m_SimulatorParams, timestamp)) + { + param->PacketDropCount++; + return default; + } + + var bufferVec = default(InboundBufferVec); + bufferVec.buffer1 = inboundBuffer; + if (param->PacketDelayMs == 0 || + !simulator.DelayPacket(ref ctx, bufferVec, ref needsUpdate, timestamp)) + { + return inboundBuffer; + } + } + + NativeSlice returnPacket = default(NativeSlice); + if (simulator.GetDelayedPacket(ref ctx, ref returnPacket, ref needsResume, ref needsUpdate, timestamp)) + return returnPacket; + + return default; + } + + public InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate) + { + return inboundBuffer; + } + + public unsafe void InitializeConnection(NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, + NativeSlice sharedProcessBuffer) + { + if (sharedProcessBuffer.Length >= UnsafeUtility.SizeOf()) + SimulatorUtility.InitializeContext(m_SimulatorParams, sharedProcessBuffer); + } + + public int ReceiveCapacity => m_SimulatorParams.MaxPacketCount * (m_SimulatorParams.MaxPacketSize+UnsafeUtility.SizeOf()); + public int SendCapacity => 0; + public int HeaderCapacity => 0; + public int SharedStateCapacity => UnsafeUtility.SizeOf(); + } + + [NetworkPipelineInitilize(typeof(SimulatorUtility.Parameters))] + public struct SimulatorPipelineStageInSend : INetworkPipelineStage + { + private SimulatorUtility.Parameters m_SimulatorParams; + + // Setup simulation parameters which get capacity function depends on, so buffer size can be correctly allocated + public void Initialize(SimulatorUtility.Parameters param) + { + m_SimulatorParams = param; + } + + public NativeSlice Receive(NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate) + { + return new NativeSlice(inboundBuffer, 0, inboundBuffer.Length); + } + + public unsafe InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate) + { + var param = (SimulatorUtility.Context*) ctx.internalSharedProcessBuffer.GetUnsafePtr(); + var simulator = new SimulatorUtility(m_SimulatorParams.MaxPacketCount, m_SimulatorParams.MaxPacketSize, m_SimulatorParams.PacketDelayMs, m_SimulatorParams.PacketJitterMs); + if (inboundBuffer.buffer1.Length+inboundBuffer.buffer2.Length > m_SimulatorParams.MaxPacketSize) + { + //UnityEngine.Debug.LogWarning("Incoming packet too large for internal storage buffer. Passing through. [buffer=" + (inboundBuffer.buffer1.Length+inboundBuffer.buffer2.Length) + " packet=" + param->MaxPacketSize + "]"); + return inboundBuffer; + } + + var timestamp = ctx.timestamp; + + if (inboundBuffer.buffer1.Length > 0) + { + param->PacketCount++; + + if (simulator.ShouldDropPacket(param, m_SimulatorParams, timestamp)) + { + param->PacketDropCount++; + return default; + } + + if (param->PacketDelayMs == 0 || + !simulator.DelayPacket(ref ctx, inboundBuffer, ref needsUpdate, timestamp)) + { + return inboundBuffer; + } + } + + NativeSlice returnPacket = default; + if (simulator.GetDelayedPacket(ref ctx, ref returnPacket, ref needsResume, ref needsUpdate, timestamp)) + { + inboundBuffer.buffer1 = returnPacket; + inboundBuffer.buffer2 = default; + return inboundBuffer; + } + + return default; + } + + public void InitializeConnection(NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, + NativeSlice sharedProcessBuffer) + { + if (sharedProcessBuffer.Length >= UnsafeUtility.SizeOf()) + SimulatorUtility.InitializeContext(m_SimulatorParams, sharedProcessBuffer); + } + + public int ReceiveCapacity => 0; + public int SendCapacity => m_SimulatorParams.MaxPacketCount * (m_SimulatorParams.MaxPacketSize+UnsafeUtility.SizeOf()); + public int HeaderCapacity => 0; + public int SharedStateCapacity => UnsafeUtility.SizeOf(); + } +} diff --git a/Runtime/Pipelines/SimulatorPipelineStage.cs.meta b/Runtime/Pipelines/SimulatorPipelineStage.cs.meta new file mode 100644 index 0000000..fb3bed3 --- /dev/null +++ b/Runtime/Pipelines/SimulatorPipelineStage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6c94271ce32ea46fa9d8019f313443eb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Pipelines/SimulatorUtility.cs b/Runtime/Pipelines/SimulatorUtility.cs new file mode 100644 index 0000000..8b39899 --- /dev/null +++ b/Runtime/Pipelines/SimulatorUtility.cs @@ -0,0 +1,249 @@ +using System.Runtime.InteropServices; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Random = Unity.Mathematics.Random; + +namespace Unity.Networking.Transport.Utilities +{ + public struct SimulatorUtility + { + private int m_PacketCount; + private int m_MaxPacketSize; + private int m_PacketDelayMs; + private int m_PacketJitterMs; + + /// + /// Configuration parameters for the simulator pipeline stage. + /// + [StructLayout(LayoutKind.Sequential)] + public struct Parameters : INetworkParameter + { + /// + /// The maximum amount of packets the pipeline can keep track of. This used when a + /// packet is delayed, the packet is stored in the pipeline processing buffer and can + /// be later brought back. + /// + public int MaxPacketCount; + /// + /// The maximum size of a packet which the simulator stores. If a packet exceeds this size it will + /// bypass the simulator. + /// + public int MaxPacketSize; + /// + /// Fixed delay to apply to all packets which pass through. + /// + public int PacketDelayMs; + /// + /// Variable delay to apply to all packets which pass through, adds or subtracts amount from fixed delay. + /// + public int PacketJitterMs; + /// + /// Fixed interval to drop packets on. This is most suitable for tests where predictable + /// behaviour is desired, every Xth packet will be dropped. If PacketDropInterval is 5 + /// every 5th packet is dropped. + /// + public int PacketDropInterval; + /// + /// Use a drop percentage when deciding when to drop packet. For every packet + /// a random number generator is used to determine if the packet should be dropped or not. + /// A percentage of 5 means approximately every 20th packet will be dropped. + /// + public int PacketDropPercentage; + } + + [StructLayout(LayoutKind.Sequential)] + public struct Context + { + public int MaxPacketCount; + public int MaxPacketSize; + public int PacketDelayMs; + public int PacketJitterMs; + public int PacketDrop; + + public Random Random; + + // Statistics + public int PacketCount; + public int PacketDropCount; + public int ReadyPackets; + public int WaitingPackets; + public long NextPacketTime; + public long StatsTime; + } + + [StructLayout(LayoutKind.Sequential)] + public struct DelayedPacket + { + public int processBufferOffset; + public int packetSize; + public long delayUntil; + } + + public SimulatorUtility(int packetCount, int maxPacketSize, int packetDelayMs, int packetJitterMs) + { + m_PacketCount = packetCount; + m_MaxPacketSize = maxPacketSize; + m_PacketDelayMs = packetDelayMs; + m_PacketJitterMs = packetJitterMs; + } + + public static unsafe void InitializeContext(Parameters param, NativeSlice sharedProcessBuffer) + { + // Store parameters in the shared buffer space + Context* ctx = (Context*) sharedProcessBuffer.GetUnsafePtr(); + ctx->MaxPacketCount = param.MaxPacketCount; + ctx->MaxPacketSize = param.MaxPacketSize; + ctx->PacketDelayMs = param.PacketDelayMs; + ctx->PacketJitterMs = param.PacketJitterMs; + ctx->PacketDrop = param.PacketDropInterval; + ctx->PacketCount = 0; + ctx->PacketDropCount = 0; + ctx->Random = new Random(); + ctx->Random.InitState(); + } + + public unsafe bool GetEmptyDataSlot(byte* processBufferPtr, ref int packetPayloadOffset, + ref int packetDataOffset) + { + var dataSize = UnsafeUtility.SizeOf(); + var packetPayloadStartOffset = m_PacketCount * dataSize; + + bool foundSlot = false; + for (int i = 0; i < m_PacketCount; i++) + { + packetDataOffset = dataSize * i; + DelayedPacket* packetData = (DelayedPacket*) (processBufferPtr + packetDataOffset); + + // Check if this slot is empty + if (packetData->delayUntil == 0) + { + foundSlot = true; + packetPayloadOffset = packetPayloadStartOffset + m_MaxPacketSize * i; + break; + } + } + + return foundSlot; + } + + public void StorePacketPayload(NativeSlice destinationSlice, NativeSlice sourceSlice1, + NativeSlice sourceSlice2) + { + int position; + for (position = 0; position < sourceSlice1.Length; ++position) + destinationSlice[position] = sourceSlice1[position]; + for (int i = 0; i < sourceSlice2.Length; ++i) + destinationSlice[position++] = sourceSlice2[i]; + } + + public unsafe bool GetDelayedPacket(ref NetworkPipelineContext ctx, ref NativeSlice delayedPacket, + ref bool needsResume, ref bool needsUpdate, long currentTimestamp) + { + needsUpdate = needsResume = false; + + var dataSize = UnsafeUtility.SizeOf(); + byte* processBufferPtr = (byte*) ctx.internalProcessBuffer.GetUnsafePtr(); + var simCtx = (Context*) ctx.internalSharedProcessBuffer.GetUnsafePtr(); + int oldestPacketIndex = -1; + long oldestTime = long.MaxValue; + int readyPackets = 0; + int packetsInQueue = 0; + for (int i = 0; i < m_PacketCount; i++) + { + DelayedPacket* packet = (DelayedPacket*) (processBufferPtr + dataSize * i); + if ((int) packet->delayUntil == 0) continue; + packetsInQueue++; + + if (packet->delayUntil > currentTimestamp) continue; + readyPackets++; + + if (oldestTime <= packet->delayUntil) continue; + oldestPacketIndex = i; + oldestTime = packet->delayUntil; + } + + simCtx->ReadyPackets = readyPackets; + simCtx->WaitingPackets = packetsInQueue; + simCtx->NextPacketTime = oldestTime; + simCtx->StatsTime = currentTimestamp; + + // If more than one item has expired timer we need to resume this pipeline stage + if (readyPackets > 1) + { + needsUpdate = false; + needsResume = true; + } + // If more than one item is present (but doesn't have expired timer) we need to re-run the pipeline + // in a later update call + else if (packetsInQueue > 0) + { + needsUpdate = true; + needsResume = false; + } + + if (oldestPacketIndex >= 0) + { + DelayedPacket* packet = (DelayedPacket*) (processBufferPtr + dataSize * oldestPacketIndex); + packet->delayUntil = 0; + + delayedPacket = new NativeSlice(ctx.internalProcessBuffer, packet->processBufferOffset, + packet->packetSize); + return true; + } + + return false; + } + + public unsafe bool DelayPacket(ref NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, + ref bool needsUpdate, + long timestamp) + { + // Find empty slot in bookkeeping data space to track this packet + int packetPayloadOffset = 0; + int packetDataOffset = 0; + var processBufferPtr = (byte*) ctx.internalProcessBuffer.GetUnsafePtr(); + bool foundSlot = GetEmptyDataSlot(processBufferPtr, ref packetPayloadOffset, ref packetDataOffset); + + if (!foundSlot) + { + //UnityEngine.Debug.LogWarning("No space left for delaying packet (" + m_PacketCount + " packets in queue)"); + return false; + } + + NativeSlice packetPayload = + new NativeSlice(ctx.internalProcessBuffer, packetPayloadOffset, + inboundBuffer.buffer1.Length + inboundBuffer.buffer2.Length); + + StorePacketPayload(packetPayload, inboundBuffer.buffer1, inboundBuffer.buffer2); + + var param = (SimulatorUtility.Context*) ctx.internalSharedProcessBuffer.GetUnsafePtr(); + // Add tracking for this packet so we can resurrect later + DelayedPacket packet; + packet.delayUntil = timestamp + m_PacketDelayMs + param->Random.NextInt(m_PacketJitterMs*2) - m_PacketJitterMs; + packet.processBufferOffset = packetPayloadOffset; + packet.packetSize = inboundBuffer.buffer1.Length + inboundBuffer.buffer2.Length; + byte* packetPtr = (byte*) &packet; + UnsafeUtility.MemCpy(processBufferPtr + packetDataOffset, packetPtr, UnsafeUtility.SizeOf()); + + // Schedule an update call so packet can be resurrected later + needsUpdate = true; + + return true; + } + + public unsafe bool ShouldDropPacket(Context* ctx, Parameters param, long timestamp) + { + if (param.PacketDropInterval > 0 && (ctx->PacketCount - 1) % param.PacketDropInterval == 0) + return true; + if (param.PacketDropPercentage > 0) + { + //var packetLoss = new System.Random().NextDouble() * 100; + var packetLoss = ctx->Random.NextDouble() * 100; + if (packetLoss < param.PacketDropPercentage) + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/Runtime/Pipelines/SimulatorUtility.cs.meta b/Runtime/Pipelines/SimulatorUtility.cs.meta new file mode 100644 index 0000000..51ba87e --- /dev/null +++ b/Runtime/Pipelines/SimulatorUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b8e5e0ea1828b4b52bd56c023866f6a6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Pipelines/UnreliableSequencedPipelineStage.cs b/Runtime/Pipelines/UnreliableSequencedPipelineStage.cs new file mode 100644 index 0000000..790bbb5 --- /dev/null +++ b/Runtime/Pipelines/UnreliableSequencedPipelineStage.cs @@ -0,0 +1,60 @@ +using System; +using Unity.Burst; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Networking.Transport.Utilities; + +namespace Unity.Networking.Transport +{ + public struct UnreliableSequencedPipelineStage : INetworkPipelineStage + { + public NativeSlice Receive(NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate) + { + needsResume = false; + var reader = new DataStreamReader(inboundBuffer); + var context = default(DataStreamReader.Context); + unsafe + { + var oldSequenceId = (int*) ctx.internalProcessBuffer.GetUnsafePtr(); + ushort sequenceId = reader.ReadUShort(ref context); + + if (SequenceHelpers.GreaterThan16(sequenceId, (ushort)*oldSequenceId)) + { + *oldSequenceId = sequenceId; + // Skip over the part of the buffer which contains the header + return inboundBuffer.Slice(sizeof(ushort)); + } + } + return default(NativeSlice); + } + + public InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate) + { + needsResume = false; + unsafe + { + var sequenceId = (int*) ctx.internalProcessBuffer.GetUnsafePtr(); + ctx.header.Write((ushort)*sequenceId); + *sequenceId = (ushort)(*sequenceId + 1); + } + return inboundBuffer; + } + + public void InitializeConnection(NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, NativeSlice sharedProcessBuffer) + { + unsafe + { + if (recvProcessBuffer.Length > 0) + { + // The receive processing buffer contains the current sequence ID, initialize it to -1 as it will be incremented when used. + *(int*) recvProcessBuffer.GetUnsafePtr() = -1; + } + } + } + + public int ReceiveCapacity => sizeof(int); + public int SendCapacity => sizeof(int); + public int HeaderCapacity => sizeof(ushort); + public int SharedStateCapacity { get; } + } +} \ No newline at end of file diff --git a/Runtime/Pipelines/UnreliableSequencedPipelineStage.cs.meta b/Runtime/Pipelines/UnreliableSequencedPipelineStage.cs.meta new file mode 100644 index 0000000..e613e54 --- /dev/null +++ b/Runtime/Pipelines/UnreliableSequencedPipelineStage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7e08c23b1aba74c94b04b54b8ea39e80 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/UDPNetworkDriver.cs b/Runtime/UDPNetworkDriver.cs new file mode 100644 index 0000000..f18442e --- /dev/null +++ b/Runtime/UDPNetworkDriver.cs @@ -0,0 +1,141 @@ +using System; +using Unity.Collections; +using Unity.Jobs; + +namespace Unity.Networking.Transport +{ + public struct UdpNetworkDriver : INetworkDriver + { + private GenericNetworkDriver m_genericDriver; + + public struct Concurrent + { + private GenericNetworkDriver.Concurrent m_genericConcurrent; + + internal Concurrent(GenericNetworkDriver.Concurrent genericConcurrent) + { + m_genericConcurrent = genericConcurrent; + } + public NetworkEvent.Type PopEventForConnection(NetworkConnection connectionId, out DataStreamReader slice) + { + return m_genericConcurrent.PopEventForConnection(connectionId, out slice); + } + + public int Send(NetworkPipeline pipe, NetworkConnection id, DataStreamWriter strm) + { + return m_genericConcurrent.Send(pipe, id, strm); + } + + public int Send(NetworkPipeline pipe, NetworkConnection id, IntPtr data, int len) + { + return m_genericConcurrent.Send(pipe, id, data, len); + } + + public NetworkConnection.State GetConnectionState(NetworkConnection id) + { + return m_genericConcurrent.GetConnectionState(id); + } + } + + public Concurrent ToConcurrent() + { + return new Concurrent(m_genericDriver.ToConcurrent()); + } + + public UdpNetworkDriver(params INetworkParameter[] param) + { + m_genericDriver = new GenericNetworkDriver(param); + } + public bool IsCreated => m_genericDriver.IsCreated; + public void Dispose() + { + m_genericDriver.Dispose(); + } + + public JobHandle ScheduleUpdate(JobHandle dep = default(JobHandle)) + { + return m_genericDriver.ScheduleUpdate(dep); + } + + public int ReceiveErrorCode => m_genericDriver.ReceiveErrorCode; + + public int Bind(NetworkEndPoint endpoint) + { + return m_genericDriver.Bind(endpoint); + } + + public int Listen() + { + return m_genericDriver.Listen(); + } + + public bool Listening => m_genericDriver.Listening; + + public NetworkConnection Accept() + { + return m_genericDriver.Accept(); + } + + public NetworkConnection Connect(NetworkEndPoint endpoint) + { + return m_genericDriver.Connect(endpoint); + } + + public int Disconnect(NetworkConnection con) + { + return m_genericDriver.Disconnect(con); + } + + public NetworkConnection.State GetConnectionState(NetworkConnection con) + { + return m_genericDriver.GetConnectionState(con); + } + + public void GetPipelineBuffers(Type pipelineType, NetworkConnection connection, ref NativeSlice readProcessingBuffer, ref NativeSlice writeProcessingBuffer, ref NativeSlice sharedBuffer) + { + m_genericDriver.GetPipelineBuffers(pipelineType, connection, ref readProcessingBuffer, ref writeProcessingBuffer, ref sharedBuffer); + } + + public void GetPipelineBuffers(NetworkPipeline pipeline, int stageId, NetworkConnection connection, + ref NativeSlice readProcessingBuffer, ref NativeSlice writeProcessingBuffer, + ref NativeSlice sharedBuffer) + { + m_genericDriver.GetPipelineBuffers(pipeline, stageId, connection, ref readProcessingBuffer, ref writeProcessingBuffer, ref sharedBuffer); + } + + public NetworkEndPoint RemoteEndPoint(NetworkConnection con) + { + return m_genericDriver.RemoteEndPoint(con); + } + + public NetworkEndPoint LocalEndPoint() + { + return m_genericDriver.LocalEndPoint(); + } + + public NetworkPipeline CreatePipeline(params Type[] stages) + { + return m_genericDriver.CreatePipeline(stages); + } + + public int Send(NetworkPipeline pipe, NetworkConnection con, DataStreamWriter strm) + { + return m_genericDriver.Send(pipe, con, strm); + } + + public int Send(NetworkPipeline pipe, NetworkConnection con, IntPtr data, int len) + { + return m_genericDriver.Send(pipe, con, data, len); + } + + public NetworkEvent.Type PopEvent(out NetworkConnection con, out DataStreamReader bs) + { + return m_genericDriver.PopEvent(out con, out bs); + } + + public NetworkEvent.Type PopEventForConnection(NetworkConnection con, out DataStreamReader bs) + { + return m_genericDriver.PopEventForConnection(con, out bs); + } + } +} \ No newline at end of file diff --git a/Runtime/UDPNetworkDriver.cs.meta b/Runtime/UDPNetworkDriver.cs.meta new file mode 100644 index 0000000..8b49cfb --- /dev/null +++ b/Runtime/UDPNetworkDriver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f1d3e8318e4ee8b468111a082325c13b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/UDPNetworkInterface.cs b/Runtime/UDPNetworkInterface.cs new file mode 100644 index 0000000..feecab9 --- /dev/null +++ b/Runtime/UDPNetworkInterface.cs @@ -0,0 +1,213 @@ +using System; +using System.Collections.Generic; +using Unity.Burst; +using Unity.Jobs; +using Unity.Networking.Transport.LowLevel.Unsafe; +using Unity.Networking.Transport.Protocols; + +namespace Unity.Networking.Transport +{ +#if NET_DOTS + public class NetworkInterfaceException : Exception + { + public NetworkInterfaceException(int err) + : base("Socket error: " + err) + { + } + } +#else + public class NetworkInterfaceException : System.Net.Sockets.SocketException + { + public NetworkInterfaceException(int err) + : base(err) + { + } + } +#endif + + public struct IPv4UDPSocket : INetworkInterface + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + private class SocketList + { + public HashSet OpenSockets = new HashSet(); + + ~SocketList() + { + foreach (var socket in OpenSockets) + { + long sockHand = socket; + int errorcode = 0; + NativeBindings.network_close(ref sockHand, ref errorcode); + } + } + } + private static SocketList AllSockets = new SocketList(); +#endif + + private long m_SocketHandle; + private NetworkEndPoint m_RemoteEndPoint; + + public NetworkFamily Family => NetworkFamily.UdpIpv4; + + public unsafe NetworkEndPoint LocalEndPoint + { + get + { + var localEndPoint = new NetworkEndPoint {length = sizeof(NetworkEndPoint)}; + int errorcode = 0; + var result = NativeBindings.network_get_socket_address(m_SocketHandle, ref localEndPoint, ref errorcode); + if (result != 0) + { + throw new NetworkInterfaceException(errorcode); + } + return localEndPoint; + } + } + + public NetworkEndPoint RemoteEndPoint { + get { return m_RemoteEndPoint; } + } + + public void Initialize() + { + NativeBindings.network_initialize(); + int ret = CreateAndBindSocket(out m_SocketHandle, NetworkEndPoint.AnyIpv4); + if (ret != 0) + throw new NetworkInterfaceException(ret); + } + + public void Dispose() + { + Close(); + NativeBindings.network_terminate(); + } + + [BurstCompile] + struct ReceiveJob : IJob where T : struct, INetworkPacketReceiver + { + public T receiver; + public long socket; + + public unsafe void Execute() + { + var address = new NetworkEndPoint {length = sizeof(NetworkEndPoint)}; + var header = new UdpCHeader(); + var stream = receiver.GetDataStream(); + receiver.ReceiveCount = 0; + receiver.ReceiveErrorCode = 0; + + while (true) + { + if (receiver.DynamicDataStreamSize()) + { + while (stream.Length+NetworkParameterConstants.MTU >= stream.Capacity) + stream.Capacity *= 2; + } + else if (stream.Length >= stream.Capacity) + return; + var sliceOffset = stream.Length; + var result = NativeReceive(ref header, stream.GetUnsafePtr() + sliceOffset, + Math.Min(NetworkParameterConstants.MTU, stream.Capacity - stream.Length), ref address); + if (result <= 0) + return; + receiver.ReceiveCount += receiver.AppendPacket(address, header, result); + } + + } + + unsafe int NativeReceive(ref UdpCHeader header, void* data, int length, ref NetworkEndPoint address) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (length <= 0) + throw new ArgumentException("Can't receive into 0 bytes or less of buffer memory"); +#endif + var iov = stackalloc network_iovec[2]; + + fixed (byte* ptr = header.Data) + { + iov[0].buf = ptr; + iov[0].len = UdpCHeader.Length; + + iov[1].buf = data; + iov[1].len = length; + } + + int errorcode = 0; + var result = NativeBindings.network_recvmsg(socket, iov, 2, ref address, ref errorcode); + if (result == -1) + { + if (errorcode == 10035 || errorcode == 35 || errorcode == 11) + return 0; + + receiver.ReceiveErrorCode = errorcode; + } + return result; + } + } + + public JobHandle ScheduleReceive(T receiver, JobHandle dep) where T : struct, INetworkPacketReceiver + { + var job = new ReceiveJob {receiver = receiver, socket = m_SocketHandle}; + return job.Schedule(dep); + } + + public int Bind(NetworkEndPoint endpoint) + { +#if ENABLE_UNITY_COLLECTIONS_CHECKS + if (endpoint.Family != NetworkFamily.UdpIpv4) + throw new InvalidOperationException(); +#endif + + long newSocket; + int ret = CreateAndBindSocket(out newSocket, endpoint); + if (ret != 0) + return ret; + Close(); + + m_RemoteEndPoint = endpoint; + m_SocketHandle = newSocket; + + return 0; + } + + private void Close() + { + if (m_SocketHandle < 0) + return; +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AllSockets.OpenSockets.Remove(m_SocketHandle); +#endif + int errorcode = 0; + NativeBindings.network_close(ref m_SocketHandle, ref errorcode); + m_RemoteEndPoint = default(NetworkEndPoint); + m_SocketHandle = -1; + } + + public unsafe int SendMessage(network_iovec* iov, int iov_len, ref NetworkEndPoint address) + { + int errorcode = 0; + return NativeBindings.network_sendmsg(m_SocketHandle, iov, iov_len, ref address, ref errorcode); + } + + int CreateAndBindSocket(out long socket, NetworkEndPoint address) + { + socket = -1; + int errorcode = 0; + int ret = NativeBindings.network_create_and_bind(ref socket, ref address, ref errorcode); + if (ret != 0) + return errorcode; +#if ENABLE_UNITY_COLLECTIONS_CHECKS + AllSockets.OpenSockets.Add(socket); +#endif + NativeBindings.network_set_nonblocking(socket); + NativeBindings.network_set_send_buffer_size(socket, ushort.MaxValue); + NativeBindings.network_set_receive_buffer_size(socket, ushort.MaxValue); +#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN) + // Avoid WSAECONNRESET errors when sending to an endpoint which isn't open yet (unclean connect/disconnects) + NativeBindings.network_set_connection_reset(socket, 0); +#endif + return 0; + } + } +} \ No newline at end of file diff --git a/Runtime/UDPNetworkInterface.cs.meta b/Runtime/UDPNetworkInterface.cs.meta new file mode 100644 index 0000000..0d6b142 --- /dev/null +++ b/Runtime/UDPNetworkInterface.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 26ef3682e760f414591d4cef054aba2e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Unity.Networking.Transport.asmdef b/Runtime/Unity.Networking.Transport.asmdef new file mode 100644 index 0000000..944daf0 --- /dev/null +++ b/Runtime/Unity.Networking.Transport.asmdef @@ -0,0 +1,11 @@ +{ + "name": "Unity.Networking.Transport", + "references": [ + "Unity.Burst", + "Unity.Collections", + "Unity.Mathematics" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true +} diff --git a/Runtime/Unity.Networking.Transport.asmdef.meta b/Runtime/Unity.Networking.Transport.asmdef.meta new file mode 100644 index 0000000..dfc7fe6 --- /dev/null +++ b/Runtime/Unity.Networking.Transport.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f2d49d9fa7e7eb3418e39723a7d3b92f +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Utilities.cs b/Runtime/Utilities.cs new file mode 100644 index 0000000..ce79808 --- /dev/null +++ b/Runtime/Utilities.cs @@ -0,0 +1,210 @@ +using System; +using Unity.Collections; + +namespace Unity.Networking.Transport.Utilities +{ + /// + /// A NativeMultiQueue is a set of several FIFO queues split into buckets. + /// 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 + { + private NativeList m_Queue; + private NativeList m_QueueHeadTail; + private NativeArray m_MaxItems; + + /// + /// New NativeMultiQueue has a single bucket and the specified number + /// of items for that bucket. Accessing buckets out of range will grow + /// the number of buckets and pushing more items than the initial capacity + /// will increase the number of items for each bucket. + /// + public NativeMultiQueue(int initialMessageCapacity) + { + m_MaxItems = new NativeArray(1, Allocator.Persistent); + m_MaxItems[0] = initialMessageCapacity; + m_Queue = new NativeList(initialMessageCapacity, Allocator.Persistent); + m_QueueHeadTail = new NativeList(2, Allocator.Persistent); + } + + public void Dispose() + { + m_MaxItems.Dispose(); + m_Queue.Dispose(); + m_QueueHeadTail.Dispose(); + } + + /// + /// Enqueue a new item to a specific bucket. If the bucket does not yet exist + /// the number of buckets will be increased and if the queue is full the number + /// of items for each bucket will be increased. + /// + public void Enqueue(int bucket, T value) + { + // Grow number of buckets to fit specified index + if (bucket >= m_QueueHeadTail.Length / 2) + { + int oldSize = m_QueueHeadTail.Length; + m_QueueHeadTail.ResizeUninitialized((bucket+1)*2); + for (;oldSize < m_QueueHeadTail.Length; ++oldSize) + m_QueueHeadTail[oldSize] = 0; + m_Queue.ResizeUninitialized((m_QueueHeadTail.Length / 2) * m_MaxItems[0]); + } + int idx = m_QueueHeadTail[bucket * 2 + 1]; + if (idx >= m_MaxItems[0]) + { + // Grow number of items per bucket + int oldMax = m_MaxItems[0]; + while (idx >= m_MaxItems[0]) + m_MaxItems[0] = m_MaxItems[0]*2; + int maxBuckets = m_QueueHeadTail.Length / 2; + m_Queue.ResizeUninitialized(maxBuckets * m_MaxItems[0]); + for (int b = maxBuckets-1; b >= 0; --b) + { + for (int i = m_QueueHeadTail[b*2+1]-1; i >= m_QueueHeadTail[b * 2]; --i) + { + m_Queue[b * m_MaxItems[0] + i] = m_Queue[b * oldMax + i]; + } + } + } + m_Queue[m_MaxItems[0] * bucket + idx] = value; + m_QueueHeadTail[bucket * 2 + 1] = idx + 1; + } + + /// + /// Dequeue an item from a specific bucket. If the bucket does not exist or if the + /// bucket is empty the call will fail and return false. + /// + public bool Dequeue(int bucket, out T value) + { + if (bucket < 0 || bucket >= m_QueueHeadTail.Length / 2) + { + value = default(T); + return false; + } + int idx = m_QueueHeadTail[bucket * 2]; + if (idx >= m_QueueHeadTail[bucket * 2 + 1]) + { + m_QueueHeadTail[bucket * 2] = m_QueueHeadTail[bucket * 2 + 1] = 0; + value = default(T); + return false; + } + else if (idx + 1 == m_QueueHeadTail[bucket * 2 + 1]) + { + m_QueueHeadTail[bucket * 2] = m_QueueHeadTail[bucket * 2 + 1] = 0; + } + else + { + m_QueueHeadTail[bucket * 2] = idx + 1; + } + + value = m_Queue[m_MaxItems[0] * bucket + idx]; + return true; + } + + /// + /// Peek the next item in a specific bucket. If the bucket does not exist or if the + /// bucket is empty the call will fail and return false. + /// + public bool Peek(int bucket, out T value) + { + if (bucket < 0 || bucket >= m_QueueHeadTail.Length / 2) + { + value = default(T); + return false; + } + int idx = m_QueueHeadTail[bucket * 2]; + if (idx >= m_QueueHeadTail[bucket * 2 + 1]) + { + value = default(T); + return false; + } + + value = m_Queue[m_MaxItems[0] * bucket + idx]; + return true; + } + + /// + /// Remove all items from a specific bucket. If the bucket does not exist + /// the call will not do anything. + /// + public void Clear(int bucket) + { + if (bucket < 0 || bucket >= m_QueueHeadTail.Length / 2) + return; + m_QueueHeadTail[bucket * 2] = 0; + m_QueueHeadTail[bucket * 2 + 1] = 0; + } + } + + /// + /// A simple timer used to measure the number of milliseconds since it was created. + /// + public class Timer + { + private System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); + + public Timer() + { + stopwatch.Start(); + } + + public long ElapsedMilliseconds => stopwatch.ElapsedMilliseconds; + } + + public struct SequenceHelpers + { + // Calculate difference between the sequence IDs taking into account wrapping, so when you go from 65535 to 0 the distance is 1 + public static int AbsDistance(ushort lhs, ushort rhs) + { + int distance; + if (lhs < rhs) + distance = lhs + ushort.MaxValue + 1 - rhs; + else + distance = lhs - rhs; + return distance; + } + + public static bool IsNewer(uint current, uint old) + { + // Invert the check so same does not count as newer + return !(old - current < (1u << 31)); + } + + public static bool GreaterThan16(ushort lhs, ushort rhs) + { + const uint max_sequence_divide_2 = 0x7FFF; + return lhs > rhs && lhs - rhs <= (ushort) max_sequence_divide_2 || + lhs < rhs && rhs - lhs > (ushort) max_sequence_divide_2; + } + + public static bool LessThan16(ushort lhs, ushort rhs) + { + return GreaterThan16(rhs, lhs); + } + + public static bool StalePacket(ushort sequence, ushort oldSequence, ushort windowSize) + { + return LessThan16(sequence, (ushort) (oldSequence - windowSize)); + } + + public static string BitMaskToString(uint mask) + { + // 31 24 16 8 0 + // |-------+-------+-------+--------| + // 00000000000000000000000000000000 + + var bits = sizeof(uint) * 8; + var sb = new System.Text.StringBuilder(new string('*', bits)); + + for (int i = bits - 1; i >= 0; i--) + { + sb[i] = (mask & 1) != 0 ? '1' : '0'; + mask >>= 1; + } + + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/Runtime/Utilities.cs.meta b/Runtime/Utilities.cs.meta new file mode 100644 index 0000000..e33706f --- /dev/null +++ b/Runtime/Utilities.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 35ee5e9bd3cd5d445880fd82472e1919 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests.meta b/Tests.meta new file mode 100644 index 0000000..750266c --- /dev/null +++ b/Tests.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2ec122f21a0281042850d4e10c829506 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor.meta b/Tests/Editor.meta new file mode 100644 index 0000000..e4da256 --- /dev/null +++ b/Tests/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e77bee39967e3f24fb25f974b39b44e2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/DataStreamTests.cs b/Tests/Editor/DataStreamTests.cs new file mode 100644 index 0000000..48336da --- /dev/null +++ b/Tests/Editor/DataStreamTests.cs @@ -0,0 +1,218 @@ +using System; +using Unity.Networking.Transport.Utilities; +using NUnit.Framework; +using UnityEngine; +using Unity.Collections; + +// using FsCheck; + +namespace Unity.Networking.Transport.Tests +{ + public class DataStreamTests + { + [Test] + public void CreateStreamWithPartOfSourceByteArray() + { + byte[] byteArray = + { + (byte) 's', (byte) 'o', (byte) 'm', (byte) 'e', + (byte) ' ', (byte) 'd', (byte) 'a', (byte) 't', (byte) 'a' + }; + + DataStreamWriter dataStream; + using (dataStream = new DataStreamWriter(4, Allocator.Persistent)) + { + dataStream.Write(byteArray, 4); + Assert.AreEqual(dataStream.Length, 4); + var reader = new DataStreamReader(dataStream, 0, dataStream.Length); + var readerCtx = default(DataStreamReader.Context); + for (int i = 0; i < reader.Length; ++i) + { + Assert.AreEqual(byteArray[i], reader.ReadByte(ref readerCtx)); + } + + Assert.Throws(() => { reader.ReadByte(ref readerCtx); }); + } + } + + [Test] + public void CreateStreamWithSourceByteArray() + { + byte[] byteArray = new byte[100]; + byteArray[0] = (byte) 'a'; + byteArray[1] = (byte) 'b'; + byteArray[2] = (byte) 'c'; + + DataStreamWriter dataStream; + using (dataStream = new DataStreamWriter(byteArray.Length, Allocator.Persistent)) + { + dataStream.Write(byteArray, byteArray.Length); + var reader = new DataStreamReader(dataStream, 0, byteArray.Length); + var readerCtx = default(DataStreamReader.Context); + for (int i = 0; i < reader.Length; ++i) + { + Assert.AreEqual(byteArray[i], reader.ReadByte(ref readerCtx)); + } + } + } + + [Test] + public void ReadIntoExistingByteArray() + { + byte[] byteArray = new byte[100]; + + DataStreamWriter dataStream; + using (dataStream = new DataStreamWriter(3, Allocator.Persistent)) + { + dataStream.Write((byte) 'a'); + dataStream.Write((byte) 'b'); + dataStream.Write((byte) 'c'); + var reader = new DataStreamReader(dataStream, 0, dataStream.Length); + var readerCtx = default(DataStreamReader.Context); + reader.ReadBytesIntoArray(ref readerCtx, ref byteArray, dataStream.Length); + readerCtx = default(DataStreamReader.Context); + for (int i = 0; i < reader.Length; ++i) + { + Assert.AreEqual(byteArray[i], reader.ReadByte(ref readerCtx)); + } + } + } + + [Test] + public void ReadingDataFromStreamWithSliceOffset() + { + using (var dataStream = new DataStreamWriter(100, Allocator.Persistent)) + { + dataStream.Write((byte) 'a'); + dataStream.Write((byte) 'b'); + dataStream.Write((byte) 'c'); + dataStream.Write((byte) 'd'); + dataStream.Write((byte) 'e'); + dataStream.Write((byte) 'f'); + var reader = new DataStreamReader(dataStream, 3, 3); + var readerCtx = default(DataStreamReader.Context); + Assert.AreEqual('d', reader.ReadByte(ref readerCtx)); + Assert.AreEqual('e', reader.ReadByte(ref readerCtx)); + Assert.AreEqual('f', reader.ReadByte(ref readerCtx)); + } + } + + [Test] + public void CopyToByteArrayWithOffset() + { + byte[] byteArray = new byte[100]; + + using (var dataStream = new DataStreamWriter(100, Allocator.Persistent)) + { + dataStream.Write((byte) 'a'); + dataStream.Write((byte) 'b'); + dataStream.Write((byte) 'c'); + dataStream.Write((byte) 'd'); + dataStream.Write((byte) 'e'); + dataStream.Write((byte) 'f'); + + dataStream.CopyTo(2, 3, ref byteArray); + Assert.AreEqual(byteArray[0], (byte) 'c'); + Assert.AreEqual(byteArray[1], (byte) 'd'); + Assert.AreEqual(byteArray[2], (byte) 'e'); + Assert.AreNotEqual(byteArray[3], (byte) 'f'); + } + } + + [Test] + public void CopyToNativeArrayWithOffset() + { + using (var dataStream = new DataStreamWriter(100, Allocator.Persistent)) + using (var nativeArray = new NativeArray(100, Allocator.Persistent)) + { + dataStream.Write((byte) 'a'); + dataStream.Write((byte) 'b'); + dataStream.Write((byte) 'c'); + dataStream.Write((byte) 'd'); + dataStream.Write((byte) 'e'); + dataStream.Write((byte) 'f'); + + dataStream.CopyTo(2, 3, nativeArray); + Assert.AreEqual(nativeArray[0], (byte) 'c'); + Assert.AreEqual(nativeArray[1], (byte) 'd'); + Assert.AreEqual(nativeArray[2], (byte) 'e'); + Assert.AreNotEqual(nativeArray[3], (byte) 'f'); + } + } + + [Test] + public void ReadWritePackedUInt() + { + using (var dataStream = new DataStreamWriter(300 * 4, Allocator.Persistent)) + using (var compressionModel = new NetworkCompressionModel(Allocator.Persistent)) + { + uint base_val = 2000; + uint count = 277; + for (uint i = 0; i < count; ++i) + dataStream.WritePackedUInt(base_val + i, compressionModel); + + dataStream.Write((int) 1979); + dataStream.Flush(); + var reader = new DataStreamReader(dataStream, 0, dataStream.Length); + var ctx = default(DataStreamReader.Context); + for (uint i = 0; i < count; ++i) + { + var val = reader.ReadPackedUInt(ref ctx, compressionModel); + Assert.AreEqual(base_val + i, val); + } + Assert.AreEqual(1979, reader.ReadInt(ref ctx)); + } + } + [Test] + public void ReadWritePackedInt() + { + using (var dataStream = new DataStreamWriter(300 * 4, Allocator.Persistent)) + using (var compressionModel = new NetworkCompressionModel(Allocator.Persistent)) + { + int base_val = -10; + int count = 20; + for (int i = 0; i < count; ++i) + dataStream.WritePackedInt(base_val + i, compressionModel); + + dataStream.Write((int) 1979); + dataStream.Flush(); + var reader = new DataStreamReader(dataStream, 0, dataStream.Length); + var ctx = default(DataStreamReader.Context); + for (int i = 0; i < count; ++i) + { + var val = reader.ReadPackedInt(ref ctx, compressionModel); + Assert.AreEqual(base_val + i, val); + } + Assert.AreEqual(1979, reader.ReadInt(ref ctx)); + } + } + [Test] + public void ReadWritePackedUIntWithDeferred() + { + using (var dataStream = new DataStreamWriter(300 * 4, Allocator.Persistent)) + using (var compressionModel = new NetworkCompressionModel(Allocator.Persistent)) + { + uint base_val = 2000; + uint count = 277; + var def = dataStream.Write((int) 0); + for (uint i = 0; i < count; ++i) + dataStream.WritePackedUInt(base_val + i, compressionModel); + + dataStream.Flush(); + def.Update(1979); + def = dataStream.Write((int) 0); + def.Update(1979); + dataStream.Flush(); + var reader = new DataStreamReader(dataStream, 0, dataStream.Length); + var ctx = default(DataStreamReader.Context); + Assert.AreEqual(1979, reader.ReadInt(ref ctx)); + for (uint i = 0; i < count; ++i) + { + var val = reader.ReadPackedUInt(ref ctx, compressionModel); + Assert.AreEqual(base_val + i, val); + } + Assert.AreEqual(1979, reader.ReadInt(ref ctx)); + } + } + } +} \ No newline at end of file diff --git a/Tests/Editor/DataStreamTests.cs.meta b/Tests/Editor/DataStreamTests.cs.meta new file mode 100644 index 0000000..44493a0 --- /dev/null +++ b/Tests/Editor/DataStreamTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2a2377a965b74cf43b04ec42c9c776b4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/NetworkConnectionUnitTests.cs b/Tests/Editor/NetworkConnectionUnitTests.cs new file mode 100644 index 0000000..b9e258a --- /dev/null +++ b/Tests/Editor/NetworkConnectionUnitTests.cs @@ -0,0 +1,128 @@ +using NUnit.Framework; +using Unity.Collections; + +namespace Unity.Networking.Transport.Tests +{ + public static class SharedConstants + { + public static byte[] ping = + { + (byte) 'p', + (byte) 'i', + (byte) 'n', + (byte) 'g' + }; + + public static byte[] pong = + { + (byte) 'p', + (byte) 'o', + (byte) 'n', + (byte) 'g' + }; + } + + public class NetworkConnectionUnitTests + { + private LocalNetworkDriver Driver; + private LocalNetworkDriver RemoteDriver; + private DataStreamWriter Stream; + + [SetUp] + public void IPC_Setup() + { + IPCManager.Instance.Initialize(100); + + Stream = new DataStreamWriter(64, Allocator.Persistent); + Driver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + RemoteDriver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + + RemoteDriver.Bind(IPCManager.Instance.CreateEndPoint("remote_host")); + RemoteDriver.Listen(); + } + + [TearDown] + public void IPC_TearDown() + { + Driver.Dispose(); + RemoteDriver.Dispose(); + Stream.Dispose(); + + IPCManager.Instance.Destroy(); + } + + [Test] + public void CreateAndConnect_NetworkConnection_ToRemoteEndPoint() + { + var connection = Driver.Connect(RemoteDriver.LocalEndPoint()); + Assert.That(connection.IsCreated); + Driver.ScheduleUpdate().Complete(); + + RemoteDriver.ScheduleUpdate().Complete(); + Assert.That(RemoteDriver.Accept().IsCreated); + + Driver.ScheduleUpdate().Complete(); + DataStreamReader reader; + Assert.That(connection.PopEvent(Driver, out reader) == NetworkEvent.Type.Connect); + } + + + [Test] + public void CreateConnectPopAndClose_NetworkConnection_ToRemoteEndPoint() + { + var connection = Driver.Connect(RemoteDriver.LocalEndPoint()); + Assert.That(connection.IsCreated); + Driver.ScheduleUpdate().Complete(); + + RemoteDriver.ScheduleUpdate().Complete(); + var remoteId = default(NetworkConnection); + Assert.That((remoteId = RemoteDriver.Accept()) != default(NetworkConnection)); + + DataStreamReader reader; + + Driver.ScheduleUpdate().Complete(); + Assert.That(connection.PopEvent(Driver, out reader) == NetworkEvent.Type.Connect); + + connection.Close(Driver); + Driver.ScheduleUpdate().Complete(); + + RemoteDriver.ScheduleUpdate().Complete(); + Assert.That( + RemoteDriver.PopEventForConnection(remoteId, out reader) == NetworkEvent.Type.Disconnect); + } + + [Test] + public void Connection_SetupSendAndReceive() + { + var connection = Driver.Connect(RemoteDriver.LocalEndPoint()); + Assert.That(connection.IsCreated); + Driver.ScheduleUpdate().Complete(); + + RemoteDriver.ScheduleUpdate().Complete(); + var remoteId = default(NetworkConnection); + Assert.That((remoteId = RemoteDriver.Accept()) != default(NetworkConnection)); + + DataStreamReader reader; + + Driver.ScheduleUpdate().Complete(); + Assert.That(connection.PopEvent(Driver, out reader) == NetworkEvent.Type.Connect); + + // Send to endpoint + Stream.Write(SharedConstants.ping); + connection.Send(Driver, Stream); + Driver.ScheduleUpdate().Complete(); + + RemoteDriver.ScheduleUpdate().Complete(); + var ev = RemoteDriver.PopEventForConnection(remoteId, out reader); + Assert.That(ev == NetworkEvent.Type.Data); + Assert.That(reader.Length == SharedConstants.ping.Length); + + connection.Close(Driver); + Driver.ScheduleUpdate().Complete(); + RemoteDriver.ScheduleUpdate().Complete(); + + Assert.That( + RemoteDriver.PopEventForConnection(remoteId, out reader) == NetworkEvent.Type.Disconnect); + } + } +} \ No newline at end of file diff --git a/Tests/Editor/NetworkConnectionUnitTests.cs.meta b/Tests/Editor/NetworkConnectionUnitTests.cs.meta new file mode 100644 index 0000000..a2a0d9e --- /dev/null +++ b/Tests/Editor/NetworkConnectionUnitTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: affed4d906927cb40a80f84fd8c662c3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/NetworkDriverFlowTest.cs b/Tests/Editor/NetworkDriverFlowTest.cs new file mode 100644 index 0000000..28052bf --- /dev/null +++ b/Tests/Editor/NetworkDriverFlowTest.cs @@ -0,0 +1,99 @@ +using System; +using NUnit.Framework; + +namespace Unity.Networking.Transport.Tests +{ + namespace Helpers + { + class SharedConstants + { + public const float TickRate = 60.0f; + public const float TickInterval = 1.0f / TickRate; + } + + public class UnreliableClient : IDisposable + { + public void Dispose() + { + } + + public void Tick() + { + } + } + + public class UnreliableServer : IDisposable + { + private LocalNetworkDriver m_Driver; + + //private List m_Connections; + + public UnreliableServer() + { + m_Driver = new LocalNetworkDriver(new NetworkDataStreamParameter + {size = NetworkParameterConstants.MTU}); + } + + public void Host(NetworkEndPoint endpoint) + { + m_Driver.Bind(endpoint); + m_Driver.Listen(); + } + + public void Tick() + { + //NetworkConnection connection; + while ((/*connection =*/ m_Driver.Accept()) != default(NetworkConnection)) + { + //m_Connections.Add(connection); + } + } + + public void OnConnection() + { + } + + public void OnDisconnection() + { + } + + public void OnData() + { + } + + public void Dispose() + { + m_Driver.Dispose(); + } + } + } + + public class NetworkDriverFlowTests + { + [Test] + public void NetworkDriver_Simple_Flow([Values(100)] int iterations) + { + /* + Stopwatch stopwatch = new Stopwatch(); + var frequency = Stopwatch.Frequency; + + stopwatch.Start(); + var frametime = (double) stopwatch.ElapsedTicks / frequency; + double nexttick = 0.0f; + + UnreliableServer server = new UnreliableServer(); + server.Host(new IPCEndPoint("server")); + UnreliableClient[] clients = new UnreliableClient[NetworkParams.Constants.MaximumConnectionsSupported]; + + for (int i = 0; i < iterations; ++i) + { + server.Tick(); + foreach (var client in clients) + { + client.Tick(); + } + } + */ + } + } +} \ No newline at end of file diff --git a/Tests/Editor/NetworkDriverFlowTest.cs.meta b/Tests/Editor/NetworkDriverFlowTest.cs.meta new file mode 100644 index 0000000..8c0948f --- /dev/null +++ b/Tests/Editor/NetworkDriverFlowTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5fff067607dd3654ca461a006a9cc680 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/NetworkDriverLoadTest.cs b/Tests/Editor/NetworkDriverLoadTest.cs new file mode 100644 index 0000000..e69de29 diff --git a/Tests/Editor/NetworkDriverLoadTest.cs.meta b/Tests/Editor/NetworkDriverLoadTest.cs.meta new file mode 100644 index 0000000..92ec3c5 --- /dev/null +++ b/Tests/Editor/NetworkDriverLoadTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 46aed37f60b217d46b4c804ca2bcf12b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/NetworkDriverUnitTests.cs b/Tests/Editor/NetworkDriverUnitTests.cs new file mode 100644 index 0000000..13f1660 --- /dev/null +++ b/Tests/Editor/NetworkDriverUnitTests.cs @@ -0,0 +1,705 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Unity.Networking.Transport.LowLevel.Unsafe; +using NUnit.Framework; +using Unity.Collections; +using UnityEngine; +using Unity.Networking.Transport.Protocols; +using Unity.Networking.Transport.Utilities; +using Random = UnityEngine.Random; + +namespace Unity.Networking.Transport.Tests.Utilities +{ + using System.Linq; + public static class Random + { + private static System.Random random = new System.Random(); + + public static string String(int length) + { + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + return new string(Enumerable.Repeat(chars, length) + .Select(s => s[random.Next(s.Length)]).ToArray()); + } + } +} + +namespace Unity.Networking.Transport.Tests +{ + public struct LocalDriverHelper : IDisposable + { + public NetworkEndPoint Address { get; } + public LocalNetworkDriver m_LocalDriver; + private DataStreamWriter m_LocalDataStream; + public NetworkConnection Connection { get; internal set; } + public List ClientConnections; + + public LocalDriverHelper(NetworkEndPoint endpoint, params INetworkParameter[] networkParams) + { + if (networkParams.Length == 0) + m_LocalDriver = new LocalNetworkDriver(new NetworkDataStreamParameter + {size = NetworkParameterConstants.MTU}); + else + m_LocalDriver = new LocalNetworkDriver(networkParams); + m_LocalDataStream = new DataStreamWriter(NetworkParameterConstants.MTU, Allocator.Persistent); + + if (endpoint.Family == NetworkFamily.IPC && endpoint.Port != 0) + { + Address = endpoint; + } + else + { + Address = IPCManager.Instance.CreateEndPoint(Utilities.Random.String(32)); + } + + Connection = default(NetworkConnection); + ClientConnections = new List(); + } + + public void Dispose() + { + m_LocalDriver.Dispose(); + m_LocalDataStream.Dispose(); + } + + public void Update() + { + m_LocalDriver.ScheduleUpdate().Complete(); + } + + public NetworkConnection Accept() + { + return m_LocalDriver.Accept(); + } + + public void Host() + { + m_LocalDriver.Bind(Address); + m_LocalDriver.Listen(); + } + + public void Connect(NetworkEndPoint endpoint) + { + Assert.True(endpoint.Family == NetworkFamily.IPC); + Connection = m_LocalDriver.Connect(endpoint); + m_LocalDriver.ScheduleUpdate().Complete(); + } + + public unsafe void Assert_GotConnectionRequest(NetworkEndPoint from, bool accept = false) + { + int length; + NetworkEndPoint remote; + m_LocalDataStream.Clear(); + Assert.True( + IPCManager.Instance.PeekNext(Address, m_LocalDataStream.GetUnsafePtr(), out length, out remote) >= + sizeof(UdpCHeader)); + m_LocalDataStream.WriteBytesWithUnsafePointer(length); + + UdpCHeader header = new UdpCHeader(); + var reader = new DataStreamReader(m_LocalDataStream, 0, sizeof(UdpCHeader)); + var readerCtx = default(DataStreamReader.Context); + Assert.True(reader.IsCreated); + reader.ReadBytes(ref readerCtx, header.Data, sizeof(UdpCHeader)); + Assert.True(header.Type == (int) UdpCProtocol.ConnectionRequest); + + Assert.True(remote.Family == NetworkFamily.IPC); + //Assert.True(remote.ipc_handle == from.ipc_handle); + Assert.True(remote.Port == from.Port); + + if (accept) + { + m_LocalDriver.ScheduleUpdate().Complete(); + var con = m_LocalDriver.Accept(); + ClientConnections.Add(con); + Assert.True(con != default(NetworkConnection)); + } + } + + public unsafe void Assert_GotDisconnectionRequest(NetworkEndPoint from) + { + int length; + NetworkEndPoint remote; + m_LocalDataStream.Clear(); + Assert.True( + IPCManager.Instance.PeekNext(Address, m_LocalDataStream.GetUnsafePtr(), out length, out remote) >= + sizeof(UdpCHeader)); + m_LocalDataStream.WriteBytesWithUnsafePointer(length); + + UdpCHeader header = new UdpCHeader(); + var reader = new DataStreamReader(m_LocalDataStream, 0, sizeof(UdpCHeader)); + var readerCtx = default(DataStreamReader.Context); + Assert.True(reader.IsCreated); + reader.ReadBytes(ref readerCtx, header.Data, sizeof(UdpCHeader)); + Assert.True(header.Type == (int) UdpCProtocol.Disconnect); + + Assert.True(remote.Family == NetworkFamily.IPC); + //Assert.True(remote.ipc_handle == from.ipc_handle); + Assert.True(remote.Port == from.Port); + } + + public unsafe void Assert_GotDataRequest(NetworkEndPoint from, byte[] dataToCompare) + { + NetworkEndPoint remote = default(NetworkEndPoint); + m_LocalDataStream.Clear(); + network_iovec[] iovecs = new network_iovec[2]; + iovecs[0].buf = m_LocalDataStream.GetUnsafePtr(); + iovecs[0].len = sizeof(UdpCHeader); + iovecs[1].buf = m_LocalDataStream.GetUnsafePtr() + sizeof(UdpCHeader); + iovecs[1].len = NetworkParameterConstants.MTU; + int dataLen = 0; + fixed (network_iovec* iovptr = &iovecs[0]) + { + dataLen = IPCManager.Instance.ReceiveMessageEx(Address, iovptr, 2, ref remote); + } + + if (dataLen <= 0) + { + iovecs[0].len = iovecs[1].len = 0; + } + + Assert.True(iovecs[0].len+iovecs[1].len == dataLen); + Assert.True(iovecs[0].len == sizeof(UdpCHeader)); + m_LocalDataStream.WriteBytesWithUnsafePointer(iovecs[0].len); + + UdpCHeader header = new UdpCHeader(); + var reader = new DataStreamReader(m_LocalDataStream, 0, sizeof(UdpCHeader)); + var readerCtx = default(DataStreamReader.Context); + Assert.True(reader.IsCreated); + reader.ReadBytes(ref readerCtx, header.Data, sizeof(UdpCHeader)); + Assert.True(header.Type == (int) UdpCProtocol.Data); + + Assert.True(remote.Family == NetworkFamily.IPC); + //Assert.True(remote.ipc_handle == from.ipc_handle); + Assert.True(remote.Port == from.Port); + + Assert.True(iovecs[1].len == dataToCompare.Length); + m_LocalDataStream.WriteBytesWithUnsafePointer(iovecs[1].len); + + reader = new DataStreamReader(m_LocalDataStream, iovecs[0].len, dataToCompare.Length); + readerCtx = default(DataStreamReader.Context); + var received = reader.ReadBytesAsArray(ref readerCtx, dataToCompare.Length); + + for (int i = 0, n = dataToCompare.Length; i < n; ++i) + Assert.True(received[i] == dataToCompare[i]); + } + + public unsafe void Assert_PopEventForConnection(NetworkConnection connection, NetworkEvent.Type evnt) + { + DataStreamReader reader; + var retval = m_LocalDriver.PopEventForConnection(connection, out reader); + Assert.True(retval == evnt); + } + + public unsafe void Assert_PopEvent(out NetworkConnection connection, NetworkEvent.Type evnt) + { + DataStreamReader reader; + + var retval = m_LocalDriver.PopEvent(out connection, out reader); + Assert.True(retval == evnt); + } + } + + public class NetworkDriverUnitTests + { + private Timer m_timer; + [SetUp] + public void IPC_Setup() + { + m_timer = new Timer(); + IPCManager.Instance.Initialize(100); + } + + [TearDown] + public void IPC_TearDown() + { + IPCManager.Instance.Destroy(); + } + + [Test] + public void InitializeAndDestroyDriver() + { + var driver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + driver.Dispose(); + } + + [Test] + public void BindDriverToAEndPoint() + { + var driver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + + driver.Bind(IPCManager.Instance.CreateEndPoint("host")); + driver.Dispose(); + } + + [Test] + public void ListenOnDriver() + { + var driver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + + // Make sure we Bind before we Listen. + driver.Bind(IPCManager.Instance.CreateEndPoint("host")); + driver.Listen(); + + Assert.True(driver.Listening); + driver.Dispose(); + } + + [Test] + public void AcceptNewConnectionsOnDriver() + { + var driver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + + // Make sure we Bind before we Listen. + driver.Bind(IPCManager.Instance.CreateEndPoint("host")); + driver.Listen(); + + Assert.True(driver.Listening); + + //NetworkConnection connection; + while ((/*connection =*/ driver.Accept()) != default(NetworkConnection)) + { + //Assert.True(connectionId != NetworkParameterConstants.InvalidConnectionId); + } + + driver.Dispose(); + } + + [Test] + public void ConnectToARemoteEndPoint() + { + using (var host = new LocalDriverHelper(default(NetworkEndPoint))) + { + host.Host(); + var driver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + + NetworkConnection connectionId = driver.Connect(host.Address); + Assert.True(connectionId != default(NetworkConnection)); + driver.ScheduleUpdate().Complete(); + + var local = driver.LocalEndPoint(); + host.Assert_GotConnectionRequest(local); + + driver.Dispose(); + } + } + + // TODO: Add tests where connection attempts are exceeded (connect fails) + // TODO: Test dropped connection accept messages (accept retries happen) + // TODO: Needs a way to explicitly assert on connect attempt stats + // In this test multiple connect requests are received on the server, from client, might be this is expected + // because of how the IPC driver works, but this situation is handled properly at least by basic driver logic. + [Test] + public void ConnectAttemptWithRetriesToARemoteEndPoint() + { + NetworkConnection connection; + NetworkEvent.Type eventType = 0; + DataStreamReader reader; + var hostAddress = IPCManager.Instance.CreateEndPoint(Utilities.Random.String(32)); + + // Tiny connect timeout for this test to be quicker + using (var client = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}, + new NetworkConfigParameter {connectTimeoutMS = 1, maxConnectAttempts = 10})) + { + client.Connect(hostAddress); + + // Wait past the connect timeout so there will be unanswered connect requests + long timeout = m_timer.ElapsedMilliseconds + 2; + while (m_timer.ElapsedMilliseconds < timeout) + client.ScheduleUpdate().Complete(); + + using (var host = new LocalDriverHelper(hostAddress)) + { + host.Host(); + + // Now give the next connect attempt time to happen + // TODO: Would be better to be able to see internal state here and explicitly wait until next connect attempt happens + timeout = m_timer.ElapsedMilliseconds + 10; + while (m_timer.ElapsedMilliseconds < timeout) + client.ScheduleUpdate().Complete(); + + host.Assert_GotConnectionRequest(client.LocalEndPoint(), true); + + // Wait for the client to get the connect event back + timeout = m_timer.ElapsedMilliseconds + 2; + while (m_timer.ElapsedMilliseconds < timeout) + { + client.ScheduleUpdate().Complete(); + eventType = client.PopEvent(out connection, out reader); + if (eventType != NetworkEvent.Type.Empty) + break; + } + + Assert.AreEqual(NetworkEvent.Type.Connect, eventType); + } + } + } + + [Test] + public void DisconnectFromARemoteEndPoint() + { + using (var host = new LocalDriverHelper(default(NetworkEndPoint))) + { + host.Host(); + var driver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + + // Need to be connected in order to be able to send a disconnect packet. + NetworkConnection connectionId = driver.Connect(host.Address); + Assert.True(connectionId != default(NetworkConnection)); + driver.ScheduleUpdate().Complete(); + + var local = driver.LocalEndPoint(); + host.Assert_GotConnectionRequest(local, true); + + NetworkConnection con; + DataStreamReader slice; + // Pump so we get the accept message back. + driver.ScheduleUpdate().Complete(); + Assert.AreEqual(NetworkEvent.Type.Connect, driver.PopEvent(out con, out slice)); + driver.Disconnect(connectionId); + driver.ScheduleUpdate().Complete(); + + host.Assert_GotDisconnectionRequest(local); + + driver.Dispose(); + } + } + + [Test] + public void DisconnectTimeoutOnServer() + { + using (var host = new LocalDriverHelper(default(NetworkEndPoint), + new NetworkConfigParameter {disconnectTimeoutMS = 40})) + using (var client = new LocalNetworkDriver(new NetworkConfigParameter {disconnectTimeoutMS = 40})) + { + NetworkConnection id; + NetworkEvent.Type popEvent = NetworkEvent.Type.Empty; + DataStreamReader reader; + + host.Host(); + + client.Connect(host.Address); + client.ScheduleUpdate().Complete(); + host.Assert_GotConnectionRequest(client.LocalEndPoint(), true); + + var stream = new DataStreamWriter(100, Allocator.Persistent); + for (int i = 0; i < 100; i++) + stream.Write((byte) i); + + // Host sends stuff but gets nothing back, until disconnect timeout happens + var timeout = m_timer.ElapsedMilliseconds + 100; + while (m_timer.ElapsedMilliseconds < timeout) + { + host.m_LocalDriver.Send(NetworkPipeline.Null, host.ClientConnections[0], stream); + popEvent = host.m_LocalDriver.PopEvent(out id, out reader); + if (popEvent != NetworkEvent.Type.Empty) + break; + host.Update(); + } + + stream.Dispose(); + Assert.AreEqual(NetworkEvent.Type.Disconnect, popEvent); + } + } + + [Test] + public void SendDataToRemoteEndPoint() + { + using (var host = new LocalDriverHelper(default(NetworkEndPoint))) + using (var stream = new DataStreamWriter(64, Allocator.Persistent)) + { + host.Host(); + var driver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + + // Need to be connected in order to be able to send a disconnect packet. + NetworkConnection connectionId = driver.Connect(host.Address); + Assert.True(connectionId != default(NetworkConnection)); + driver.ScheduleUpdate().Complete(); + var local = driver.LocalEndPoint(); + host.Assert_GotConnectionRequest(local, true); + + NetworkConnection con; + DataStreamReader slice; + // Pump so we get the accept message back. + driver.ScheduleUpdate().Complete(); + Assert.AreEqual(NetworkEvent.Type.Connect, driver.PopEvent(out con, out slice)); + + stream.Clear(); + var data = Encoding.ASCII.GetBytes("data to send"); + stream.Write(data); + driver.Send(NetworkPipeline.Null, connectionId, stream); + driver.ScheduleUpdate().Complete(); + + host.Assert_GotDataRequest(local, data); + + driver.Dispose(); + } + } + + [Test] + public void HandleEventsFromSpecificEndPoint() + { + using (var host = new LocalDriverHelper(default(NetworkEndPoint))) + using (var client0 = new LocalDriverHelper(default(NetworkEndPoint))) + using (var client1 = new LocalDriverHelper(default(NetworkEndPoint))) + { + host.Host(); + client0.Connect(host.Address); + client1.Connect(host.Address); + + host.Assert_PopEventForConnection(client0.Connection, NetworkEvent.Type.Empty); + host.Assert_PopEventForConnection(client1.Connection, NetworkEvent.Type.Empty); + + host.Update(); + + var clientConnectionId0 = host.Accept(); + Assert.True(clientConnectionId0 != default(NetworkConnection)); + var clientConnectionId1 = host.Accept(); + Assert.True(clientConnectionId1 != default(NetworkConnection)); + + client1.Update(); + client1.Assert_PopEventForConnection(client1.Connection, NetworkEvent.Type.Connect); + + client0.Update(); + client0.Assert_PopEventForConnection(client0.Connection, NetworkEvent.Type.Connect); + } + } + + [Test] + public void HandleEventsFromAnyEndPoint() + { + using (var host = new LocalDriverHelper(default(NetworkEndPoint))) + using (var client0 = new LocalDriverHelper(default(NetworkEndPoint))) + using (var client1 = new LocalDriverHelper(default(NetworkEndPoint))) + { + host.Host(); + client0.Connect(host.Address); + client1.Connect(host.Address); + + host.Assert_PopEventForConnection(client0.Connection, NetworkEvent.Type.Empty); + host.Assert_PopEventForConnection(client1.Connection, NetworkEvent.Type.Empty); + + host.Update(); + + var clientConnectionId0 = host.Accept(); + Assert.True(clientConnectionId0 != default(NetworkConnection)); + var clientConnectionId1 = host.Accept(); + Assert.True(clientConnectionId1 != default(NetworkConnection)); + + NetworkConnection id; + + client1.Update(); + client1.Assert_PopEvent(out id, NetworkEvent.Type.Connect); + Assert.True(id == client1.Connection); + + client0.Update(); + client0.Assert_PopEvent(out id, NetworkEvent.Type.Connect); + Assert.True(id == client0.Connection); + } + } + + [Test] + public void FillInternalBitStreamBuffer() + { + const int k_InternalBufferSize = 1000; + const int k_PacketCount = 21; // Exactly enough to fill the receive buffer + 1 too much + const int k_PacketSize = 50; + + using (var host = new LocalNetworkDriver(new NetworkDataStreamParameter {size = k_InternalBufferSize})) + using (var client = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64})) + using (var stream = new DataStreamWriter(64, Allocator.Persistent)) + { + host.Bind(IPCManager.Instance.CreateEndPoint(Utilities.Random.String(32))); + host.Listen(); + + NetworkConnection connectionId = client.Connect(host.LocalEndPoint()); + + client.ScheduleUpdate().Complete(); + host.ScheduleUpdate().Complete(); + + NetworkConnection poppedId; + DataStreamReader reader; + host.Accept(); + + client.ScheduleUpdate().Complete(); + + var retval = client.PopEvent(out poppedId, out reader); + Assert.AreEqual(retval, NetworkEvent.Type.Connect); + + var dataBlob = new Dictionary(); + for (int i = 0; i < k_PacketCount; ++i) + { + // Scramble each packet contents so you can't match reading the same data twice as success + dataBlob.Add(i, Encoding.ASCII.GetBytes(Utilities.Random.String(k_PacketSize))); + } + + for (int i = 0; i < k_PacketCount; ++i) + { + stream.Clear(); + stream.Write(dataBlob[i]); + client.Send(NetworkPipeline.Null, connectionId, stream); + } + + // Process the pending events + client.ScheduleUpdate().Complete(); + host.ScheduleUpdate().Complete(); + + for (int i = 0; i < k_PacketCount; ++i) + { + retval = host.PopEvent(out poppedId, out reader); + + if (i == k_PacketCount - 1) + { + Assert.AreEqual(retval, NetworkEvent.Type.Empty); + Assert.IsFalse(reader.IsCreated); + host.ScheduleUpdate().Complete(); + retval = host.PopEvent(out poppedId, out reader); + } + + Assert.AreEqual(retval, NetworkEvent.Type.Data); + Assert.AreEqual(k_PacketSize, reader.Length); + + var readerCtx = default(DataStreamReader.Context); + for (int j = 0; j < k_PacketSize; ++j) + { + Assert.AreEqual(dataBlob[i][j], reader.ReadByte(ref readerCtx)); + } + } + } + } + + [Test] + public void SendAndReceiveMessage_RealNetwork() + { + using (var clientSendData = new DataStreamWriter(64, Allocator.Persistent)) + { + DataStreamReader stream; + var serverEndpoint = NetworkEndPoint.LoopbackIpv4; + serverEndpoint.Port = (ushort)Random.Range(2000, 65000); + + var serverDriver = new UdpNetworkDriver(new NetworkDataStreamParameter {size = 64}); + serverDriver.Bind(serverEndpoint); + + serverDriver.Listen(); + + var clientDriver = new UdpNetworkDriver(new NetworkDataStreamParameter {size = 64}); + clientDriver.Bind(NetworkEndPoint.LoopbackIpv4); + + var clientToServerId = clientDriver.Connect(serverEndpoint); + + NetworkConnection serverToClientId = default(NetworkConnection); + // Retry a few times since the network might need some time to process + for (int i = 0; i < 10 && serverToClientId == default(NetworkConnection); ++i) + { + serverDriver.ScheduleUpdate().Complete(); + + serverToClientId = serverDriver.Accept(); + } + + Assert.That(serverToClientId != default(NetworkConnection)); + + clientDriver.ScheduleUpdate().Complete(); + + var eventId = clientDriver.PopEventForConnection(clientToServerId, out stream); + Assert.That(eventId == NetworkEvent.Type.Connect); + + + int testInt = 100; + float testFloat = 555.5f; + byte[] testByteArray = Encoding.ASCII.GetBytes("Some bytes blablabla 1111111111111111111"); + clientSendData.Write(testInt); + clientSendData.Write(testFloat); + clientSendData.Write(testByteArray.Length); + clientSendData.Write(testByteArray); + var sentBytes = clientDriver.Send(NetworkPipeline.Null, clientToServerId, clientSendData); + + // Header size is included in the sent bytes count (4 bytes overhead) + Assert.AreEqual(clientSendData.Length + 4, sentBytes); + + clientDriver.ScheduleUpdate().Complete(); + serverDriver.ScheduleUpdate().Complete(); + + DataStreamReader serverReceiveStream; + eventId = serverDriver.PopEventForConnection(serverToClientId, out serverReceiveStream); + var readerCtx = default(DataStreamReader.Context); + + Assert.True(eventId == NetworkEvent.Type.Data); + var receivedInt = serverReceiveStream.ReadInt(ref readerCtx); + var receivedFloat = serverReceiveStream.ReadFloat(ref readerCtx); + var byteArrayLength = serverReceiveStream.ReadInt(ref readerCtx); + var receivedBytes = serverReceiveStream.ReadBytesAsArray(ref readerCtx, byteArrayLength); + + Assert.True(testInt == receivedInt); + Assert.That(Mathf.Approximately(testFloat, receivedFloat)); + Assert.AreEqual(testByteArray, receivedBytes); + + clientDriver.Dispose(); + serverDriver.Dispose(); + } + } + + [Test] + public void SendAndReceiveMessage() + { + using (var clientSendData = new DataStreamWriter(64, Allocator.Persistent)) + { + DataStreamReader stream; + var serverEndpoint = IPCManager.Instance.CreateEndPoint("server"); + + var serverDriver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + serverDriver.Bind(serverEndpoint); + + serverDriver.Listen(); + + var clientDriver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + clientDriver.Bind(IPCManager.Instance.CreateEndPoint("client")); + + var clientToServerId = clientDriver.Connect(serverEndpoint); + clientDriver.ScheduleUpdate().Complete(); + + serverDriver.ScheduleUpdate().Complete(); + + NetworkConnection serverToClientId = serverDriver.Accept(); + Assert.That(serverToClientId != default(NetworkConnection)); + + clientDriver.ScheduleUpdate().Complete(); + + var eventId = clientDriver.PopEventForConnection(clientToServerId, out stream); + Assert.That(eventId == NetworkEvent.Type.Connect); + + + int testInt = 100; + float testFloat = 555.5f; + byte[] testByteArray = Encoding.ASCII.GetBytes("Some bytes blablabla 1111111111111111111"); + clientSendData.Write(testInt); + clientSendData.Write(testFloat); + clientSendData.Write(testByteArray.Length); + clientSendData.Write(testByteArray); + var sentBytes = clientDriver.Send(NetworkPipeline.Null, clientToServerId, clientSendData); + + // Header size is included in the sent bytes count (4 bytes overhead) + Assert.AreEqual(clientSendData.Length + 4, sentBytes); + + clientDriver.ScheduleUpdate().Complete(); + serverDriver.ScheduleUpdate().Complete(); + + DataStreamReader serverReceiveStream; + eventId = serverDriver.PopEventForConnection(serverToClientId, out serverReceiveStream); + var readerCtx = default(DataStreamReader.Context); + + Assert.True(eventId == NetworkEvent.Type.Data); + var receivedInt = serverReceiveStream.ReadInt(ref readerCtx); + var receivedFloat = serverReceiveStream.ReadFloat(ref readerCtx); + var byteArrayLength = serverReceiveStream.ReadInt(ref readerCtx); + var receivedBytes = serverReceiveStream.ReadBytesAsArray(ref readerCtx, byteArrayLength); + + Assert.True(testInt == receivedInt); + Assert.That(Mathf.Approximately(testFloat, receivedFloat)); + Assert.AreEqual(testByteArray, receivedBytes); + + clientDriver.Dispose(); + serverDriver.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/Tests/Editor/NetworkDriverUnitTests.cs.meta b/Tests/Editor/NetworkDriverUnitTests.cs.meta new file mode 100644 index 0000000..38d18e6 --- /dev/null +++ b/Tests/Editor/NetworkDriverUnitTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6ba3f82bf87aec445a34b94ba9edbca6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/NetworkEndPointUnitTests.cs b/Tests/Editor/NetworkEndPointUnitTests.cs new file mode 100644 index 0000000..f6cb251 --- /dev/null +++ b/Tests/Editor/NetworkEndPointUnitTests.cs @@ -0,0 +1,53 @@ +using NUnit.Framework; + +namespace Unity.Networking.Transport.Tests +{ + public class NetworkEndPointUnitTests + { + [Test] + public void NetworkEndPoint_Parse_WorksAsExpected() + { + ushort port = 12345; + NetworkEndPoint nep = NetworkEndPoint.LoopbackIpv4; + nep.Port = port; + + Assert.That(nep.Family == NetworkFamily.UdpIpv4); + Assert.That(nep.Port == port); + + NetworkEndPoint iep = NetworkEndPoint.Parse("127.0.0.1", port); + + Assert.That(nep == iep); + } + + [Test] + public void NetworkEndPoint_Parse_ExtractsPortIfPresent() + { + ushort defaultPort = 12345; + ushort customPort = 6789; + NetworkEndPoint nep = NetworkEndPoint.LoopbackIpv4; + nep.Port = customPort; + + Assert.That(nep.Family == NetworkFamily.UdpIpv4); + Assert.That(nep.Port == customPort); + + NetworkEndPoint iep = NetworkEndPoint.Parse("127.0.0.1:6789", defaultPort); + + Assert.That(nep == iep); + } + + [Test] + public void NetworkEndPoint_Parse_WhenEmptyPort_UsesDefaultPort() + { + ushort defaultPort = 12345; + NetworkEndPoint nep = NetworkEndPoint.LoopbackIpv4; + nep.Port = defaultPort; + + Assert.That(nep.Family == NetworkFamily.UdpIpv4); + Assert.That(nep.Port == defaultPort); + + NetworkEndPoint iep = NetworkEndPoint.Parse("127.0.0.1:", defaultPort); + + Assert.That(nep == iep); + } + } +} \ No newline at end of file diff --git a/Tests/Editor/NetworkEndPointUnitTests.cs.meta b/Tests/Editor/NetworkEndPointUnitTests.cs.meta new file mode 100644 index 0000000..abe30fe --- /dev/null +++ b/Tests/Editor/NetworkEndPointUnitTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7c312b56290b9d14e9149e1d16a253eb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/NetworkEventQueueTests.cs b/Tests/Editor/NetworkEventQueueTests.cs new file mode 100644 index 0000000..f3afe0b --- /dev/null +++ b/Tests/Editor/NetworkEventQueueTests.cs @@ -0,0 +1,210 @@ +using NUnit.Framework; +namespace Unity.Networking.Transport.Tests +{ + public class NetworkEventQueueTests + { + [Test] + public void PopFromEmptyQueueReturnsEmpty() + { + var queue = new NetworkEventQueue(1); + int offset, size; + Assert.AreEqual(NetworkEvent.Type.Empty, queue.PopEventForConnection(0, out offset, out size)); + queue.Dispose(); + } + + [Test] + public void PushToSingleConnectionCanBePoppedPerConnection() + { + var queue = new NetworkEventQueue(1); + int offset, size; + queue.PushEvent(new NetworkEvent{connectionId = 0, offset = 0, size = 0, type = NetworkEvent.Type.Data}); + Assert.AreEqual(NetworkEvent.Type.Data, queue.PopEventForConnection(0, out offset, out size)); + Assert.AreEqual(NetworkEvent.Type.Empty, queue.PopEventForConnection(0, out offset, out size)); + queue.Dispose(); + } + + [Test] + public void PushToSingleConnectionCanBePoppedGlobally() + { + var queue = new NetworkEventQueue(1); + int offset, size; + int id; + queue.PushEvent(new NetworkEvent{connectionId = 0, offset = 0, size = 0, type = NetworkEvent.Type.Data}); + Assert.AreEqual(NetworkEvent.Type.Data, queue.PopEvent(out id, out offset, out size)); + Assert.AreEqual(0, id); + Assert.AreEqual(NetworkEvent.Type.Empty, queue.PopEvent(out id, out offset, out size)); + queue.Dispose(); + } + + [Test] + public void PushToSingleConnectionCanGrowMaxEvents() + { + var queue = new NetworkEventQueue(1); + int offset, size; + for (int i = 0; i < 16; ++i) + queue.PushEvent(new NetworkEvent{connectionId = 0, offset = 0, size = 0, type = NetworkEvent.Type.Data}); + for (int i = 0; i < 16; ++i) + Assert.AreEqual(NetworkEvent.Type.Data, queue.PopEventForConnection(0, out offset, out size)); + Assert.AreEqual(NetworkEvent.Type.Empty, queue.PopEventForConnection(0, out offset, out size)); + queue.Dispose(); + } + + [Test] + public void PushToMultipleConnectionsCanGrowMaxEvents() + { + var queue = new NetworkEventQueue(1); + int offset, size; + for (int con = 0; con < 16; ++con) + { + for (int i = 0; i < con; ++i) + { + queue.PushEvent(new NetworkEvent + {connectionId = con, offset = con, size = i, type = NetworkEvent.Type.Data}); + } + } + + for (int con = 0; con < 16; ++con) + { + for (int i = 0; i < con; ++i) + { + Assert.AreEqual(NetworkEvent.Type.Data, queue.PopEventForConnection(con, out offset, out size)); + Assert.AreEqual(con, offset); + Assert.AreEqual(i, size); + } + + Assert.AreEqual(NetworkEvent.Type.Empty, queue.PopEventForConnection(con, out offset, out size)); + } + queue.Dispose(); + } + + [Test] + public void PopMixingMethodsOnSingleConnectionWorks() + { + var queue = new NetworkEventQueue(16); + int offset, size; + for (int i = 0; i < 16; ++i) + queue.PushEvent(new NetworkEvent{connectionId = 0, offset = i, size = 0, type = NetworkEvent.Type.Data}); + int id; + for (int i = 0; i < 16/2; ++i) + { + Assert.AreEqual(NetworkEvent.Type.Data, queue.PopEvent(out id, out offset, out size)); + Assert.AreEqual(0, id); + Assert.AreEqual(i*2, offset); + Assert.AreEqual(NetworkEvent.Type.Data, queue.PopEventForConnection(0, out offset, out size)); + Assert.AreEqual(i*2+1, offset); + } + + Assert.AreEqual(NetworkEvent.Type.Empty, queue.PopEvent(out id, out offset, out size)); + Assert.AreEqual(NetworkEvent.Type.Empty, queue.PopEventForConnection(0, out offset, out size)); + queue.Dispose(); + } + + [Test] + public void PopMixingMethodsOnMultipleConnectionsWorks() + { + var queue = new NetworkEventQueue(16); + int offset, size; + for (int i = 0; i < 16; ++i) + { + for (int con = 0; con < 16; ++con) + queue.PushEvent(new NetworkEvent + {connectionId = con, offset = con, size = i, type = NetworkEvent.Type.Data}); + } + + // Pop half the events from connection 10, make sure everything else is still in sync + + int id; + for (int i = 0; i < 8; ++i) + { + Assert.AreEqual(NetworkEvent.Type.Data, queue.PopEventForConnection(10, out offset, out size)); + Assert.AreEqual(10, offset); + Assert.AreEqual(i, size); + } + for (int i = 0; i < 16; ++i) + { + for (int con = 0; con < 16; ++con) + { + if (con == 10 && i < 8) + continue; + Assert.AreEqual(NetworkEvent.Type.Data, queue.PopEvent(out id, out offset, out size)); + Assert.AreEqual(con, id); + Assert.AreEqual(con, offset); + Assert.AreEqual(i, size); + } + } + + Assert.AreEqual(NetworkEvent.Type.Empty, queue.PopEventForConnection(10, out offset, out size)); + Assert.AreEqual(NetworkEvent.Type.Empty, queue.PopEvent(out id, out offset, out size)); + queue.Dispose(); + } + } + + public class NetworkEventQueueConcurrentTests + { + [Test] + public void PopFromEmptyQueueReturnsEmpty() + { + var queue = new NetworkEventQueue(1); + var cq = queue.ToConcurrent(); + int offset, size; + Assert.AreEqual(NetworkEvent.Type.Empty, cq.PopEventForConnection(0, out offset, out size)); + queue.Dispose(); + } + [Test] + public void PopFromSingleConnectionWorks() + { + var queue = new NetworkEventQueue(1); + var cq = queue.ToConcurrent(); + int offset, size; + queue.PushEvent(new NetworkEvent{connectionId = 0, offset = 0, size = 0, type = NetworkEvent.Type.Data}); + Assert.AreEqual(NetworkEvent.Type.Data, cq.PopEventForConnection(0, out offset, out size)); + Assert.AreEqual(NetworkEvent.Type.Empty, cq.PopEventForConnection(0, out offset, out size)); + queue.Dispose(); + } + [Test] + public void PopFromMultipleConnectionsWorks() + { + var queue = new NetworkEventQueue(1); + var cq = queue.ToConcurrent(); + int offset, size; + for (int i = 0; i < 16; ++i) + queue.PushEvent(new NetworkEvent{connectionId = i, offset = i, size = 0, type = NetworkEvent.Type.Data}); + for (int i = 0; i < 16; ++i) + { + Assert.AreEqual(NetworkEvent.Type.Data, cq.PopEventForConnection(i, out offset, out size)); + Assert.AreEqual(i, offset); + Assert.AreEqual(NetworkEvent.Type.Empty, cq.PopEventForConnection(i, out offset, out size)); + } + + queue.Dispose(); + } + [Test] + public void PopFromMultipleConnectionsWithGrowingEventsWorks() + { + var queue = new NetworkEventQueue(1); + var cq = queue.ToConcurrent(); + int offset, size; + for (int con = 0; con < 16; ++con) + { + for (int i = 0; i < con; ++i) + { + queue.PushEvent(new NetworkEvent + {connectionId = con, offset = con, size = i, type = NetworkEvent.Type.Data}); + } + } + + for (int con = 0; con < 16; ++con) + { + for (int i = 0; i < con; ++i) + { + Assert.AreEqual(NetworkEvent.Type.Data, cq.PopEventForConnection(con, out offset, out size)); + Assert.AreEqual(con, offset); + Assert.AreEqual(i, size); + } + + Assert.AreEqual(NetworkEvent.Type.Empty, cq.PopEventForConnection(con, out offset, out size)); + } + queue.Dispose(); + } + } +} \ No newline at end of file diff --git a/Tests/Editor/NetworkEventQueueTests.cs.meta b/Tests/Editor/NetworkEventQueueTests.cs.meta new file mode 100644 index 0000000..36806b0 --- /dev/null +++ b/Tests/Editor/NetworkEventQueueTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3cf7054b45ae6495a9f1ebcf1ac90cdb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/NetworkHostUnitTests.cs b/Tests/Editor/NetworkHostUnitTests.cs new file mode 100644 index 0000000..ebd3c38 --- /dev/null +++ b/Tests/Editor/NetworkHostUnitTests.cs @@ -0,0 +1,68 @@ +using NUnit.Framework; + +namespace Unity.Networking.Transport.Tests +{ + public class NetworkHostUnitTests + { + private LocalNetworkDriver Driver; + private LocalNetworkDriver RemoteDriver; + + [SetUp] + public void IPC_Setup() + { + IPCManager.Instance.Initialize(100); + + Driver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + RemoteDriver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + } + + [TearDown] + public void IPC_TearDown() + { + Driver.Dispose(); + RemoteDriver.Dispose(); + IPCManager.Instance.Destroy(); + } + + [Test] + public void Listen() + { + Driver.Bind(IPCManager.Instance.CreateEndPoint("network_host")); + Driver.Listen(); + Assert.That(Driver.Listening); + } + + [Test] + public void Accept() + { + Driver.Bind(IPCManager.Instance.CreateEndPoint("network_host")); + Driver.Listen(); + Assert.That(Driver.Listening); + + // create connection to test to connect. + /*var remote =*/ RemoteDriver.Connect(Driver.LocalEndPoint()); + + NetworkConnection id; + DataStreamReader reader; + const int maximumIterations = 10; + int count = 0; + bool connected = false; + while (count++ < maximumIterations) + { + // Clear pending events + Driver.PopEvent(out id, out reader); + RemoteDriver.PopEvent(out id, out reader); + + Driver.ScheduleUpdate().Complete(); + RemoteDriver.ScheduleUpdate().Complete(); + var connection = Driver.Accept(); + if (connection != default(NetworkConnection)) + { + connected = true; + } + } + + Assert.That(connected); + } + } +} \ No newline at end of file diff --git a/Tests/Editor/NetworkHostUnitTests.cs.meta b/Tests/Editor/NetworkHostUnitTests.cs.meta new file mode 100644 index 0000000..a1ea160 --- /dev/null +++ b/Tests/Editor/NetworkHostUnitTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 18b1968e3d0921d4cbc2fca61d48dffa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/NetworkJobTests.cs b/Tests/Editor/NetworkJobTests.cs new file mode 100644 index 0000000..1f5d1c8 --- /dev/null +++ b/Tests/Editor/NetworkJobTests.cs @@ -0,0 +1,333 @@ +using System; +using NUnit.Framework; +using Unity.Burst; +using Unity.Collections; +using Unity.Jobs; + +namespace Unity.Networking.Transport.Tests +{ + public class NetworkJobTests + { + [SetUp] + public void IPC_Setup() + { + IPCManager.Instance.Initialize(100); + } + + [TearDown] + public void IPC_TearDown() + { + IPCManager.Instance.Destroy(); + } + + void WaitForConnected(LocalNetworkDriver clientDriver, LocalNetworkDriver serverDriver, + NetworkConnection clientToServer) + { + // Make sure connect message is sent + clientDriver.ScheduleUpdate().Complete(); + // Make sure connection accept message is sent back + serverDriver.ScheduleUpdate().Complete(); + // Handle the connection accept message + clientDriver.ScheduleUpdate().Complete(); + DataStreamReader strmReader; + // Make sure the connected message was received + Assert.AreEqual(NetworkEvent.Type.Connect, clientToServer.PopEvent(clientDriver, out strmReader)); + } + + [Test] + public void ScheduleUpdateWorks() + { + var driver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + var updateHandle = driver.ScheduleUpdate(); + updateHandle.Complete(); + driver.Dispose(); + } + [Test] + public void ScheduleUpdateWithMissingDependencyThrowsException() + { + var driver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + var updateHandle = driver.ScheduleUpdate(); + Assert.Throws(() => { driver.ScheduleUpdate().Complete(); }); + updateHandle.Complete(); + driver.Dispose(); + } + +#if UNITY_2019_3_OR_NEWER + [Ignore("Safety check temporarily disabled in 2019.3+")] +#endif + [Test] + public void DataStremReaderIsOnlyUsableUntilUpdate() + { + var serverDriver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + serverDriver.Bind(IPCManager.Instance.CreateEndPoint()); + serverDriver.Listen(); + var clientDriver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + var clientToServer = clientDriver.Connect(serverDriver.LocalEndPoint()); + WaitForConnected(clientDriver, serverDriver, clientToServer); + var strmWriter = new DataStreamWriter(4, Allocator.Temp); + strmWriter.Write(42); + clientToServer.Send(clientDriver, strmWriter); + clientDriver.ScheduleUpdate().Complete(); + var serverToClient = serverDriver.Accept(); + serverDriver.ScheduleUpdate().Complete(); + DataStreamReader strmReader; + Assert.AreEqual(NetworkEvent.Type.Data, serverToClient.PopEvent(serverDriver, out strmReader)); + var ctx = default(DataStreamReader.Context); + Assert.AreEqual(42, strmReader.ReadInt(ref ctx)); + ctx = default(DataStreamReader.Context); + Assert.AreEqual(42, strmReader.ReadInt(ref ctx)); + serverDriver.ScheduleUpdate().Complete(); + ctx = default(DataStreamReader.Context); + Assert.Throws(() => { strmReader.ReadInt(ref ctx); }); + clientDriver.Dispose(); + serverDriver.Dispose(); + } + + struct AcceptJob : IJob + { + public LocalNetworkDriver driver; + public NativeArray connections; + public void Execute() + { + for (int i = 0; i < connections.Length; ++i) + connections[i] = driver.Accept(); + } + } + [Test] + public void AcceptInJobWorks() + { + var serverDriver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + serverDriver.Bind(IPCManager.Instance.CreateEndPoint()); + serverDriver.Listen(); + var clientDriver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + /*var clientToServer =*/ clientDriver.Connect(serverDriver.LocalEndPoint()); + clientDriver.ScheduleUpdate().Complete(); + + var serverToClient = new NativeArray(1, Allocator.TempJob); + var acceptJob = new AcceptJob {driver = serverDriver, connections = serverToClient}; + Assert.IsFalse(serverToClient[0].IsCreated); + acceptJob.Schedule(serverDriver.ScheduleUpdate()).Complete(); + Assert.IsTrue(serverToClient[0].IsCreated); + + serverToClient.Dispose(); + clientDriver.Dispose(); + serverDriver.Dispose(); + } + struct ReceiveJob : IJob + { + public LocalNetworkDriver driver; + public NativeArray connections; + public NativeArray result; + public void Execute() + { + DataStreamReader strmReader; + // Data + connections[0].PopEvent(driver, out strmReader); + var ctx = default(DataStreamReader.Context); + result[0] = strmReader.ReadInt(ref ctx); + } + } + [Test] + public void ReceiveInJobWorks() + { + var serverDriver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + serverDriver.Bind(IPCManager.Instance.CreateEndPoint()); + serverDriver.Listen(); + var clientDriver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + var clientToServer = clientDriver.Connect(serverDriver.LocalEndPoint()); + WaitForConnected(clientDriver, serverDriver, clientToServer); + var strmWriter = new DataStreamWriter(4, Allocator.Temp); + strmWriter.Write(42); + clientToServer.Send(clientDriver, strmWriter); + clientDriver.ScheduleUpdate().Complete(); + + var serverToClient = new NativeArray(1, Allocator.TempJob); + var result = new NativeArray(1, Allocator.TempJob); + var recvJob = new ReceiveJob {driver = serverDriver, connections = serverToClient, result = result}; + Assert.AreNotEqual(42, result[0]); + var acceptJob = new AcceptJob {driver = serverDriver, connections = serverToClient}; + recvJob.Schedule(serverDriver.ScheduleUpdate(acceptJob.Schedule())).Complete(); + Assert.AreEqual(42, result[0]); + + result.Dispose(); + serverToClient.Dispose(); + clientDriver.Dispose(); + serverDriver.Dispose(); + } + + struct SendJob : IJob + { + public LocalNetworkDriver driver; + public NetworkConnection connection; + public void Execute() + { + var strmWriter = new DataStreamWriter(4, Allocator.Temp); + strmWriter.Write(42); + connection.Send(driver, strmWriter); + } + } + [Test] + public void SendInJobWorks() + { + var serverDriver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + serverDriver.Bind(IPCManager.Instance.CreateEndPoint()); + serverDriver.Listen(); + var clientDriver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}); + var clientToServer = clientDriver.Connect(serverDriver.LocalEndPoint()); + WaitForConnected(clientDriver, serverDriver, clientToServer); + var sendJob = new SendJob {driver = clientDriver, connection = clientToServer}; + clientDriver.ScheduleUpdate(sendJob.Schedule()).Complete(); + var serverToClient = serverDriver.Accept(); + serverDriver.ScheduleUpdate().Complete(); + DataStreamReader strmReader; + Assert.AreEqual(NetworkEvent.Type.Data, serverToClient.PopEvent(serverDriver, out strmReader)); + var ctx = default(DataStreamReader.Context); + Assert.AreEqual(42, strmReader.ReadInt(ref ctx)); + clientDriver.Dispose(); + serverDriver.Dispose(); + } + struct SendReceiveParallelJob : IJobParallelFor + { + public LocalNetworkDriver.Concurrent driver; + public NativeArray connections; + public void Execute(int i) + { + DataStreamReader strmReader; + // Data + if (driver.PopEventForConnection(connections[i], out strmReader) != NetworkEvent.Type.Data) + throw new InvalidOperationException("Expected data: " + i); + var ctx = default(DataStreamReader.Context); + int result = strmReader.ReadInt(ref ctx); + var strmWriter = new DataStreamWriter(4, Allocator.Temp); + strmWriter.Write(result + 1); + driver.Send(NetworkPipeline.Null, connections[i], strmWriter); + } + } + [Test] + public void SendReceiveInParallelJobWorks() + { + NativeArray serverToClient; + using (var serverDriver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64})) + using (var clientDriver0 = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64})) + using (var clientDriver1 = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64})) + using (serverToClient = new NativeArray(2, Allocator.Persistent)) + { + serverDriver.Bind(IPCManager.Instance.CreateEndPoint()); + serverDriver.Listen(); + var strmWriter = new DataStreamWriter(4, Allocator.Temp); + strmWriter.Write(42); + var clientToServer0 = clientDriver0.Connect(serverDriver.LocalEndPoint()); + var clientToServer1 = clientDriver1.Connect(serverDriver.LocalEndPoint()); + WaitForConnected(clientDriver0, serverDriver, clientToServer0); + serverToClient[0] = serverDriver.Accept(); + Assert.IsTrue(serverToClient[0].IsCreated); + WaitForConnected(clientDriver1, serverDriver, clientToServer1); + serverToClient[1] = serverDriver.Accept(); + Assert.IsTrue(serverToClient[1].IsCreated); + clientToServer0.Send(clientDriver0, strmWriter); + clientToServer1.Send(clientDriver1, strmWriter); + clientDriver0.ScheduleUpdate().Complete(); + clientDriver1.ScheduleUpdate().Complete(); + + var sendRecvJob = new SendReceiveParallelJob {driver = serverDriver.ToConcurrent(), connections = serverToClient}; + var jobHandle = serverDriver.ScheduleUpdate(); + jobHandle = sendRecvJob.Schedule(serverToClient.Length, 1, jobHandle); + serverDriver.ScheduleUpdate(jobHandle).Complete(); + + AssertDataReceived(serverDriver, serverToClient, clientDriver0, clientToServer0, 43, true); + AssertDataReceived(serverDriver, serverToClient, clientDriver1, clientToServer1, 43, true); + } + } + [BurstCompile/*(CompileSynchronously = true)*/] // FIXME: sync compilation makes tests timeout + struct SendReceiveWithPipelineParallelJob : IJobParallelFor + { + public LocalNetworkDriver.Concurrent driver; + public NativeArray connections; + public NetworkPipeline pipeline; + public void Execute(int i) + { + DataStreamReader strmReader; + // Data + if (driver.PopEventForConnection(connections[i], out strmReader) != NetworkEvent.Type.Data) + throw new InvalidOperationException("Expected data: " + i); + var ctx = default(DataStreamReader.Context); + int result = strmReader.ReadInt(ref ctx); + var strmWriter = new DataStreamWriter(4, Allocator.Temp); + strmWriter.Write(result + 1); + driver.Send(pipeline, connections[i], strmWriter); + } + } + [Test] + public void SendReceiveWithPipelineInParallelJobWorks() + { + var timeoutParam = new NetworkConfigParameter + { + connectTimeoutMS = NetworkParameterConstants.ConnectTimeoutMS, + maxConnectAttempts = NetworkParameterConstants.MaxConnectAttempts, + disconnectTimeoutMS = 90 * 1000 + }; + NativeArray serverToClient; + using (var serverDriver = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}, timeoutParam)) + using (var clientDriver0 = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}, timeoutParam)) + using (var clientDriver1 = new LocalNetworkDriver(new NetworkDataStreamParameter {size = 64}, timeoutParam)) + using (serverToClient = new NativeArray(2, Allocator.Persistent)) + { + var serverPipeline = serverDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage)); + serverDriver.Bind(IPCManager.Instance.CreateEndPoint()); + serverDriver.Listen(); + var client0Pipeline = clientDriver0.CreatePipeline(typeof(ReliableSequencedPipelineStage)); + var client1Pipeline = clientDriver1.CreatePipeline(typeof(ReliableSequencedPipelineStage)); + var strmWriter = new DataStreamWriter(4, Allocator.Temp); + strmWriter.Write(42); + var clientToServer0 = clientDriver0.Connect(serverDriver.LocalEndPoint()); + var clientToServer1 = clientDriver1.Connect(serverDriver.LocalEndPoint()); + WaitForConnected(clientDriver0, serverDriver, clientToServer0); + serverToClient[0] = serverDriver.Accept(); + Assert.IsTrue(serverToClient[0].IsCreated); + WaitForConnected(clientDriver1, serverDriver, clientToServer1); + serverToClient[1] = serverDriver.Accept(); + Assert.IsTrue(serverToClient[1].IsCreated); + clientToServer0.Send(clientDriver0, client0Pipeline, strmWriter); + clientToServer1.Send(clientDriver1, client1Pipeline, strmWriter); + clientDriver0.ScheduleUpdate().Complete(); + clientDriver1.ScheduleUpdate().Complete(); + + var sendRecvJob = new SendReceiveWithPipelineParallelJob + {driver = serverDriver.ToConcurrent(), connections = serverToClient, pipeline = serverPipeline}; + var jobHandle = serverDriver.ScheduleUpdate(); + jobHandle = sendRecvJob.Schedule(serverToClient.Length, 1, jobHandle); + serverDriver.ScheduleUpdate(jobHandle).Complete(); + + AssertDataReceived(serverDriver, serverToClient, clientDriver0, clientToServer0, 43, false); + AssertDataReceived(serverDriver, serverToClient, clientDriver1, clientToServer1, 43, false); + } + } + + void AssertDataReceived(LocalNetworkDriver serverDriver, NativeArray serverConnections, LocalNetworkDriver clientDriver, NetworkConnection clientToServerConnection, int assertValue, bool serverResend) + { + DataStreamReader strmReader; + clientDriver.ScheduleUpdate().Complete(); + var evnt = clientToServerConnection.PopEvent(clientDriver, out strmReader); + int counter = 0; + while (evnt == NetworkEvent.Type.Empty) + { + serverDriver.ScheduleUpdate().Complete(); + clientDriver.ScheduleUpdate().Complete(); + evnt = clientToServerConnection.PopEvent(clientDriver, out strmReader); + if (counter++ > 1000) + { + if (!serverResend) + break; + counter = 0; + var strmWriter = new DataStreamWriter(4, Allocator.Temp); + strmWriter.Write(assertValue); + for (int i = 0; i < serverConnections.Length; ++i) + serverDriver.Send(NetworkPipeline.Null, serverConnections[i], strmWriter); + } + } + Assert.AreEqual(NetworkEvent.Type.Data, evnt); + var ctx = default(DataStreamReader.Context); + Assert.AreEqual(assertValue, strmReader.ReadInt(ref ctx)); + } + } +} diff --git a/Tests/Editor/NetworkJobTests.cs.meta b/Tests/Editor/NetworkJobTests.cs.meta new file mode 100644 index 0000000..9bf1e48 --- /dev/null +++ b/Tests/Editor/NetworkJobTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6c3ab283e669f4aa5b81fd8477f0f48a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/NetworkParamsTests.cs b/Tests/Editor/NetworkParamsTests.cs new file mode 100644 index 0000000..e69de29 diff --git a/Tests/Editor/NetworkParamsTests.cs.meta b/Tests/Editor/NetworkParamsTests.cs.meta new file mode 100644 index 0000000..9f07997 --- /dev/null +++ b/Tests/Editor/NetworkParamsTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 47fafc55cd4a7b74c87066d6f440f4ef +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/NetworkPipelineTest.cs b/Tests/Editor/NetworkPipelineTest.cs new file mode 100644 index 0000000..25a614f --- /dev/null +++ b/Tests/Editor/NetworkPipelineTest.cs @@ -0,0 +1,971 @@ +using System; +using System.Diagnostics; +using NUnit.Framework; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Networking.Transport.Utilities; + +namespace Unity.Networking.Transport.Tests +{ + public struct TestPipelineStageWithHeader : INetworkPipelineStage + { + public NativeSlice Receive(NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate) + { + unsafe + { + var headerData = (int*)inboundBuffer.GetUnsafeReadOnlyPtr(); + if (*headerData != 1) + throw new InvalidOperationException("Header data invalid, got " + *headerData); + } + return new NativeSlice(inboundBuffer, 4, inboundBuffer.Length - 4); + } + + public InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate) + { + ctx.header.Write((int) 1); + return inboundBuffer; + } + + public void InitializeConnection(NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, NativeSlice sharedProcessBuffer) + { + } + + public int ReceiveCapacity => 0; + public int SendCapacity => 0; + public int HeaderCapacity => 4; + public int SharedStateCapacity { get; } + } + + public struct TestPipelineStageWithHeaderTwo : INetworkPipelineStage + { + public unsafe NativeSlice Receive(NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate) + { + var headerData = (int*)inboundBuffer.GetUnsafeReadOnlyPtr(); + if (*headerData != 2) + throw new InvalidOperationException("Header data invalid, got " + *headerData); + + return new NativeSlice(inboundBuffer, 4, inboundBuffer.Length - 4); + } + + public InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate) + { + ctx.header.Write((int) 2); + return inboundBuffer; + } + + public void InitializeConnection(NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, NativeSlice sharedProcessBuffer) + { + } + + public int ReceiveCapacity => 0; + public int SendCapacity => 0; + public int HeaderCapacity => 4; + public int SharedStateCapacity { get; } + } + + public struct TestEncryptPipelineStage : INetworkPipelineStage + { + private const int k_MaxPacketSize = 64; + + public NativeSlice Receive(NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate) + { + for (int i = 0; i < inboundBuffer.Length; ++i) + ctx.internalProcessBuffer[i] = (byte)(inboundBuffer[i] ^ 0xff); + return new NativeSlice(ctx.internalProcessBuffer, 0, inboundBuffer.Length); + } + + public InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate) + { + var len1 = inboundBuffer.buffer1.Length; + var len2 = inboundBuffer.buffer2.Length; + for (int i = 0; i < len1; ++i) + ctx.internalProcessBuffer[i] = (byte)(inboundBuffer.buffer1[i] ^ 0xff); + for (int i = 0; i < len2; ++i) + ctx.internalProcessBuffer[len1+i] = (byte)(inboundBuffer.buffer2[i] ^ 0xff); + var nextInbound = default(InboundBufferVec); + nextInbound.buffer1 = new NativeSlice(ctx.internalProcessBuffer, 0, len1+len2); + return nextInbound; + } + + public void InitializeConnection(NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, NativeSlice sharedProcessBuffer) + { + } + + public int ReceiveCapacity => k_MaxPacketSize; + public int SendCapacity => k_MaxPacketSize; + public int HeaderCapacity => 0; + public int SharedStateCapacity { get; } + } + public struct TestEncryptInPlacePipelineStage : INetworkPipelineStage + { + public NativeSlice Receive(NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate) + { + for (int i = 0; i < inboundBuffer.Length; ++i) + inboundBuffer[i] = (byte)(inboundBuffer[i] ^ 0xff); + return inboundBuffer; + } + + public InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate) + { + var len1 = inboundBuffer.buffer1.Length; + var len2 = inboundBuffer.buffer2.Length; + for (int i = 0; i < len1; ++i) + ctx.internalProcessBuffer[i] = (byte)(inboundBuffer.buffer1[i] ^ 0xff); + for (int i = 0; i < len2; ++i) + ctx.internalProcessBuffer[len1+i] = (byte)(inboundBuffer.buffer2[i] ^ 0xff); + var nextInbound = default(InboundBufferVec); + nextInbound.buffer1 = new NativeSlice(ctx.internalProcessBuffer, 0, len1+len2); + return nextInbound; + } + + public void InitializeConnection(NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, NativeSlice sharedProcessBuffer) + { + } + + public int ReceiveCapacity => 0; + public int SendCapacity => NetworkParameterConstants.MTU; + public int HeaderCapacity => 0; + public int SharedStateCapacity { get; } + } + public struct TestInvertPipelineStage : INetworkPipelineStage + { + public NativeSlice Receive(NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate) + { + return inboundBuffer; + } + + public unsafe InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate) + { + var len1 = inboundBuffer.buffer1.Length; + var len2 = inboundBuffer.buffer2.Length; + for (int i = 0; i < len1; ++i) + ctx.internalProcessBuffer[i] = (byte)(inboundBuffer.buffer1[i] ^ 0xff); + for (int i = 0; i < len2; ++i) + ctx.internalProcessBuffer[len1+i] = (byte)(inboundBuffer.buffer2[i] ^ 0xff); + var nextInbound = default(InboundBufferVec); + nextInbound.buffer1 = new NativeSlice(ctx.internalProcessBuffer, 0, len1+len2); + return nextInbound; + } + + public void InitializeConnection(NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, NativeSlice sharedProcessBuffer) + { + } + + public int ReceiveCapacity => 0; + public int SendCapacity => NetworkParameterConstants.MTU; + public int HeaderCapacity => 0; + public int SharedStateCapacity { get; } + } + + public unsafe struct TestPipelineWithInitializers : INetworkPipelineStage + { + public NativeSlice Receive(NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate) + { + var receiveData = (int*)ctx.internalProcessBuffer.GetUnsafePtr(); + for (int i = 4; i <= 6; ++i) + { + Assert.AreEqual(*receiveData, i); + receiveData++; + } + var sharedData = (int*)ctx.internalSharedProcessBuffer.GetUnsafePtr(); + for (int i = 7; i <= 8; ++i) + { + Assert.AreEqual(*sharedData, i); + sharedData++; + } + return inboundBuffer; + } + + public unsafe InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate) + { + var sendData = (int*)ctx.internalProcessBuffer.GetUnsafePtr(); + for (int i = 1; i <= 3; ++i) + { + Assert.AreEqual(*sendData, i); + sendData++; + } + var sharedData = (int*)ctx.internalSharedProcessBuffer.GetUnsafePtr(); + for (int i = 7; i <= 8; ++i) + { + Assert.AreEqual(*sharedData, i); + sharedData++; + } + return inboundBuffer; + } + + public unsafe void InitializeConnection(NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, NativeSlice sharedProcessBuffer) + { + var sendData = (int*)sendProcessBuffer.GetUnsafePtr(); + *sendData = 1; + sendData++; + *sendData = 2; + sendData++; + *sendData = 3; + var receiveData = (int*)recvProcessBuffer.GetUnsafePtr(); + *receiveData = 4; + receiveData++; + *receiveData = 5; + receiveData++; + *receiveData = 6; + var sharedData = (int*) sharedProcessBuffer.GetUnsafePtr(); + *sharedData = 7; + sharedData++; + *sharedData = 8; + sharedData++; + *sharedData = 9; + } + + public int ReceiveCapacity => 3*sizeof(int); + public int SendCapacity => 3*sizeof(int); + public int HeaderCapacity => 0; + public int SharedStateCapacity => 3*sizeof(int); + } + + public unsafe struct TestPipelineWithInitializersTwo : INetworkPipelineStage + { + public NativeSlice Receive(NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate) + { + var receiveData = (int*)ctx.internalProcessBuffer.GetUnsafePtr(); + for (int i = 4; i <= 6; ++i) + { + Assert.AreEqual(*receiveData, i*10); + receiveData++; + } + var sharedData = (int*)ctx.internalSharedProcessBuffer.GetUnsafePtr(); + for (int i = 7; i <= 8; ++i) + { + Assert.AreEqual(*sharedData, i*10); + sharedData++; + } + return inboundBuffer; + } + + public unsafe InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate) + { + var sendData = (int*)ctx.internalProcessBuffer.GetUnsafePtr(); + for (int i = 1; i <= 3; ++i) + { + Assert.AreEqual(*sendData, i*10); + sendData++; + } + var sharedData = (int*)ctx.internalSharedProcessBuffer.GetUnsafePtr(); + for (int i = 7; i <= 8; ++i) + { + Assert.AreEqual(*sharedData, i*10); + sharedData++; + } + return inboundBuffer; + } + + public unsafe void InitializeConnection(NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, NativeSlice sharedProcessBuffer) + { + var sendData = (int*)sendProcessBuffer.GetUnsafePtr(); + *sendData = 10; + sendData++; + *sendData = 20; + sendData++; + *sendData = 30; + var receiveData = (int*)recvProcessBuffer.GetUnsafePtr(); + *receiveData = 40; + receiveData++; + *receiveData = 50; + receiveData++; + *receiveData = 60; + var sharedData = (int*) sharedProcessBuffer.GetUnsafePtr(); + *sharedData = 70; + sharedData++; + *sharedData = 80; + sharedData++; + *sharedData = 90; + } + + public int ReceiveCapacity => 3*sizeof(int); + public int SendCapacity => 3*sizeof(int); + public int HeaderCapacity => 0; + public int SharedStateCapacity => 3*sizeof(int); + } + + public struct TestNetworkPipelineStageCollection : INetworkPipelineStageCollection + { + private TestPipelineStageWithHeader testPipelineStageWithHeader; + private TestPipelineStageWithHeaderTwo testPipelineStageWithHeaderTwo; + private TestEncryptPipelineStage testEncryptPipelineStage; + private TestEncryptInPlacePipelineStage testEncryptInPlacePipelineStage; + private TestInvertPipelineStage testInvertPipelineStage; + private TestPipelineWithInitializers testPipelineWithInitializers; + private TestPipelineWithInitializersTwo testPipelineWithInitializersTwo; + private SimulatorPipelineStage testDelayedReadPipelineStage; + private SimulatorPipelineStageInSend testDelayedSendPipelineStage; + private UnreliableSequencedPipelineStage testUnreliableSequencedPipelineStage; + + public int GetStageId(Type type) + { + if (type == typeof(TestPipelineStageWithHeader)) + return 0; + if (type == typeof(TestEncryptPipelineStage)) + return 1; + if (type == typeof(TestEncryptInPlacePipelineStage)) + return 2; + if (type == typeof(TestInvertPipelineStage)) + return 3; + if (type == typeof(SimulatorPipelineStage)) + return 4; + if (type == typeof(SimulatorPipelineStageInSend)) + return 5; + if (type == typeof(UnreliableSequencedPipelineStage)) + return 6; + if (type == typeof(TestPipelineStageWithHeaderTwo)) + return 7; + if (type == typeof(TestPipelineWithInitializers)) + return 8; + if (type == typeof(TestPipelineWithInitializersTwo)) + return 9; + + return -1; + } + + public void Initialize(params INetworkParameter[] param) + { + for (int i = 0; i < param.Length; ++i) + { + if (param[i] is SimulatorUtility.Parameters) + { + testDelayedReadPipelineStage.Initialize((SimulatorUtility.Parameters)param[i]); + testDelayedSendPipelineStage.Initialize((SimulatorUtility.Parameters)param[i]); + } + } + } + + public void InvokeInitialize(int pipelineStageId, NativeSlice sendProcessBuffer, NativeSlice recvProcessBuffer, + NativeSlice sharedStateBuffer) + { + switch (pipelineStageId) + { + case 4: + testDelayedReadPipelineStage.InitializeConnection(sendProcessBuffer, recvProcessBuffer, sharedStateBuffer); + break; + case 5: + testDelayedSendPipelineStage.InitializeConnection(sendProcessBuffer, recvProcessBuffer, sharedStateBuffer); + break; + case 6: + testUnreliableSequencedPipelineStage.InitializeConnection(sendProcessBuffer, recvProcessBuffer, sharedStateBuffer); + break; + case 8: + testPipelineWithInitializers.InitializeConnection(sendProcessBuffer, recvProcessBuffer, sharedStateBuffer); + break; + case 9: + testPipelineWithInitializersTwo.InitializeConnection(sendProcessBuffer, recvProcessBuffer, sharedStateBuffer); + break; + } + } + + public InboundBufferVec InvokeSend(int pipelineStageId, NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate) + { + switch (pipelineStageId) + { + case 0: + return testPipelineStageWithHeader.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate); + case 1: + return testEncryptPipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate); + case 2: + return testEncryptInPlacePipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate); + case 3: + return testInvertPipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate); + case 4: + return testDelayedReadPipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate); + case 5: + return testDelayedSendPipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate); + case 6: + return testUnreliableSequencedPipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate); + case 7: + return testPipelineStageWithHeaderTwo.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate); + case 8: + return testPipelineWithInitializers.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate); + case 9: + return testPipelineWithInitializersTwo.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate); + } + return inboundBuffer; + } + + public NativeSlice InvokeReceive(int pipelineStageId, NetworkPipelineContext ctx, NativeSlice inboundBuffer, ref bool needsResume, ref bool needsUpdate, ref bool needsSendUpdate) + { + switch (pipelineStageId) + { + case 0: + return testPipelineStageWithHeader.Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + case 1: + return testEncryptPipelineStage.Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + case 2: + return testEncryptInPlacePipelineStage.Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + case 3: + return testInvertPipelineStage.Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + case 4: + return testDelayedReadPipelineStage.Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + case 5: + return testDelayedSendPipelineStage.Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + case 6: + return testUnreliableSequencedPipelineStage.Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + case 7: + return testPipelineStageWithHeaderTwo.Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + case 8: + return testPipelineWithInitializers.Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + case 9: + return testPipelineWithInitializersTwo.Receive(ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate); + } + return inboundBuffer; + } + + public int GetReceiveCapacity(int pipelineStageId) + { + switch (pipelineStageId) + { + case 0: + return testPipelineStageWithHeader.ReceiveCapacity; + case 1: + return testEncryptPipelineStage.ReceiveCapacity; + case 2: + return testEncryptInPlacePipelineStage.ReceiveCapacity; + case 3: + return testInvertPipelineStage.ReceiveCapacity; + case 4: + return testDelayedReadPipelineStage.ReceiveCapacity; + case 5: + return testDelayedSendPipelineStage.ReceiveCapacity; + case 6: + return testUnreliableSequencedPipelineStage.ReceiveCapacity; + case 7: + return testPipelineStageWithHeaderTwo.ReceiveCapacity; + case 8: + return testPipelineWithInitializers.ReceiveCapacity; + case 9: + return testPipelineWithInitializersTwo.ReceiveCapacity; + } + return 0; + } + + public int GetSendCapacity(int pipelineStageId) + { + switch (pipelineStageId) + { + case 0: + return testPipelineStageWithHeader.SendCapacity; + case 1: + return testEncryptPipelineStage.SendCapacity; + case 2: + return testEncryptInPlacePipelineStage.SendCapacity; + case 3: + return testInvertPipelineStage.SendCapacity; + case 4: + return testDelayedReadPipelineStage.SendCapacity; + case 5: + return testDelayedSendPipelineStage.SendCapacity; + case 6: + return testUnreliableSequencedPipelineStage.SendCapacity; + case 7: + return testPipelineStageWithHeaderTwo.SendCapacity; + case 8: + return testPipelineWithInitializers.SendCapacity; + case 9: + return testPipelineWithInitializersTwo.SendCapacity; + } + return 0; + } + + public int GetHeaderCapacity(int pipelineStageId) + { + switch (pipelineStageId) + { + case 0: + return testPipelineStageWithHeader.HeaderCapacity; + case 1: + return testEncryptPipelineStage.HeaderCapacity; + case 2: + return testEncryptInPlacePipelineStage.HeaderCapacity; + case 3: + return testInvertPipelineStage.HeaderCapacity; + case 4: + return testDelayedReadPipelineStage.HeaderCapacity; + case 5: + return testDelayedSendPipelineStage.HeaderCapacity; + case 6: + return testUnreliableSequencedPipelineStage.HeaderCapacity; + case 7: + return testPipelineStageWithHeaderTwo.HeaderCapacity; + case 8: + return testPipelineWithInitializers.HeaderCapacity; + case 9: + return testPipelineWithInitializersTwo.HeaderCapacity; + } + return 0; + } + + public int GetSharedStateCapacity(int pipelineStageId) + { + switch (pipelineStageId) + { + case 0: + return testPipelineStageWithHeader.SharedStateCapacity; + case 1: + return testEncryptPipelineStage.SharedStateCapacity; + case 2: + return testEncryptInPlacePipelineStage.SharedStateCapacity; + case 3: + return testInvertPipelineStage.SharedStateCapacity; + case 4: + return testDelayedReadPipelineStage.SharedStateCapacity; + case 5: + return testDelayedSendPipelineStage.SharedStateCapacity; + case 6: + return testUnreliableSequencedPipelineStage.SharedStateCapacity; + case 7: + return testPipelineStageWithHeaderTwo.SharedStateCapacity; + case 8: + return testPipelineWithInitializers.SharedStateCapacity; + case 9: + return testPipelineWithInitializersTwo.SharedStateCapacity; + } + return 0; + } + } + + public class NetworkPipelineTest + { + private GenericNetworkDriver m_ServerDriver; + private GenericNetworkDriver m_ClientDriver; + private GenericNetworkDriver m_ClientDriver2; + + [SetUp] + public void IPC_Setup() + { + IPCManager.Instance.Initialize(100); + // NOTE: MaxPacketSize should be 64 for all the tests using simulator except needs to account for header size as well (one test has 2x2B headers) + var simulatorParams = new SimulatorUtility.Parameters() + {MaxPacketSize = 68, MaxPacketCount = 30, PacketDelayMs = 100}; + m_ServerDriver = new GenericNetworkDriver(simulatorParams); + m_ServerDriver.Bind(IPCManager.Instance.CreateEndPoint()); + m_ServerDriver.Listen(); + m_ClientDriver = new GenericNetworkDriver(simulatorParams); + m_ClientDriver2 = new GenericNetworkDriver(simulatorParams); + } + + [TearDown] + public void IPC_TearDown() + { + m_ClientDriver.Dispose(); + m_ClientDriver2.Dispose(); + m_ServerDriver.Dispose(); + IPCManager.Instance.Destroy(); + } + [Test] + public void NetworkPipeline_CreatePipelineIsSymetrical() + { + var clientPipe = m_ClientDriver.CreatePipeline(typeof(TestPipelineStageWithHeader)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(TestPipelineStageWithHeader)); + Assert.AreEqual(clientPipe, serverPipe); + } + [Test] + public void NetworkPipeline_CreatePipelineAfterConnectFails() + { + m_ClientDriver.Connect(m_ServerDriver.LocalEndPoint()); + Assert.Throws(() => { m_ClientDriver.CreatePipeline(typeof(TestPipelineStageWithHeader)); }); + } + [Test] + public void NetworkPipeline_CreatePipelineWithInvalidStageFails() + { + Assert.Throws(() => { m_ClientDriver.CreatePipeline(typeof(NetworkPipelineTest)); }); + } + + [Test] + public void NetworkPipeline_CanExtendHeader() + { + // Create pipeline + var clientPipe = m_ClientDriver.CreatePipeline(typeof(TestPipelineStageWithHeader)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(TestPipelineStageWithHeader)); + Assert.AreEqual(clientPipe, serverPipe); + + // 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); + + // Send message to client + var strm = new DataStreamWriter(4, Allocator.Temp); + strm.Write((int) 42); + m_ServerDriver.Send(serverPipe, serverToClient, 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(4, readStrm.Length); + var readCtx = default(DataStreamReader.Context); + Assert.AreEqual(42, readStrm.ReadInt(ref readCtx)); + } + [Test] + public void NetworkPipeline_CanModifyAndRestoreData() + { + // Create pipeline + var clientPipe = m_ClientDriver.CreatePipeline(typeof(TestEncryptPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(TestEncryptPipelineStage)); + Assert.AreEqual(clientPipe, serverPipe); + + // 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); + + // Send message to client + var strm = new DataStreamWriter(4, Allocator.Temp); + strm.Write((int) 42); + m_ServerDriver.Send(serverPipe, serverToClient, 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(4, readStrm.Length); + var readCtx = default(DataStreamReader.Context); + Assert.AreEqual(42, readStrm.ReadInt(ref readCtx)); + } + [Test] + public void NetworkPipeline_CanModifyAndRestoreDataInPlace() + { + // Create pipeline + var clientPipe = m_ClientDriver.CreatePipeline(typeof(TestEncryptInPlacePipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(TestEncryptInPlacePipelineStage)); + Assert.AreEqual(clientPipe, serverPipe); + + // 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); + + // Send message to client + var strm = new DataStreamWriter(4, Allocator.Temp); + strm.Write((int) 42); + m_ServerDriver.Send(serverPipe, serverToClient, 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(4, readStrm.Length); + var readCtx = default(DataStreamReader.Context); + Assert.AreEqual(42, readStrm.ReadInt(ref readCtx)); + } + [Test] + public void NetworkPipeline_CanModifyData() + { + // Create pipeline + var clientPipe = m_ClientDriver.CreatePipeline(typeof(TestInvertPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(TestInvertPipelineStage)); + Assert.AreEqual(clientPipe, serverPipe); + + // 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); + + // Send message to client + var strm = new DataStreamWriter(4, Allocator.Temp); + strm.Write((int) 42); + m_ServerDriver.Send(serverPipe, serverToClient, 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(4, readStrm.Length); + var readCtx = default(DataStreamReader.Context); + Assert.AreEqual(-1^42, readStrm.ReadInt(ref readCtx)); + } + + [Test] + public void NetworkPipeline_MultiplePipelinesWork() + { + var clientPipe = m_ClientDriver.CreatePipeline(typeof(TestPipelineStageWithHeaderTwo), typeof(TestEncryptPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(TestPipelineStageWithHeaderTwo), typeof(TestEncryptPipelineStage)); + Assert.AreEqual(clientPipe, serverPipe); + + // 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); + + // Send message to client + var strm = new DataStreamWriter(4, Allocator.Temp); + strm.Write((int) 42); + m_ServerDriver.Send(serverPipe, serverToClient, 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(4, readStrm.Length); + var readCtx = default(DataStreamReader.Context); + Assert.AreEqual(42, readStrm.ReadInt(ref readCtx)); + } + + [Test] + public void NetworkPipeline_CanStorePacketsForLaterDeliveryInReceiveLastStage() + { + var clientPipe1 = m_ClientDriver.CreatePipeline(typeof(TestEncryptPipelineStage), typeof(SimulatorPipelineStage)); + var clientPipe2 = m_ClientDriver2.CreatePipeline(typeof(TestEncryptPipelineStage), typeof(SimulatorPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(TestEncryptPipelineStage), typeof(SimulatorPipelineStage)); + Assert.AreEqual(clientPipe1, serverPipe); + Assert.AreEqual(clientPipe2, serverPipe); + + TestPipeline(30, serverPipe); + } + + [Test] + public void NetworkPipeline_CanStorePacketsForLaterDeliveryInReceiveFirstStage() + { + var clientPipe1 = m_ClientDriver.CreatePipeline(typeof(SimulatorPipelineStage), typeof(TestEncryptPipelineStage)); + var clientPipe2 = m_ClientDriver2.CreatePipeline(typeof(SimulatorPipelineStage), typeof(TestEncryptPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(SimulatorPipelineStage), typeof(TestEncryptPipelineStage)); + Assert.AreEqual(clientPipe1, serverPipe); + Assert.AreEqual(clientPipe2, serverPipe); + + TestPipeline(30, serverPipe); + } + + [Test] + public void NetworkPipeline_CanStorePacketsForLaterDeliveryInSendLastStage() + { + var clientPipe1 = m_ClientDriver.CreatePipeline(typeof(TestEncryptPipelineStage), typeof(SimulatorPipelineStageInSend)); + var clientPipe2 = m_ClientDriver2.CreatePipeline(typeof(TestEncryptPipelineStage), typeof(SimulatorPipelineStageInSend)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(TestEncryptPipelineStage), typeof(SimulatorPipelineStageInSend)); + Assert.AreEqual(clientPipe1, serverPipe); + Assert.AreEqual(clientPipe2, serverPipe); + + TestPipeline(30, serverPipe); + } + + [Test] + public void NetworkPipeline_CanStorePacketsForLaterDeliveryInSendFirstStage() + { + var clientPipe1 = m_ClientDriver.CreatePipeline(typeof(SimulatorPipelineStageInSend), typeof(TestEncryptPipelineStage)); + var clientPipe2 = m_ClientDriver2.CreatePipeline(typeof(SimulatorPipelineStageInSend), typeof(TestEncryptPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(SimulatorPipelineStageInSend), typeof(TestEncryptPipelineStage)); + Assert.AreEqual(clientPipe1, serverPipe); + Assert.AreEqual(clientPipe2, serverPipe); + + TestPipeline(30, serverPipe); + } + + [Test] + public void NetworkPipeline_CanStoreSequencedPacketsForLaterDeliveryInSendLastStage() + { + // Server needs the simulator as it's the only one sending + var clientPipe1 = m_ClientDriver.CreatePipeline(typeof(UnreliableSequencedPipelineStage)); + var clientPipe2 = m_ClientDriver2.CreatePipeline(typeof(UnreliableSequencedPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(UnreliableSequencedPipelineStage), typeof(SimulatorPipelineStageInSend)); + Assert.AreEqual(clientPipe1, serverPipe); + Assert.AreEqual(clientPipe2, serverPipe); + + TestPipeline(30, serverPipe); + } + + [Test] + public void NetworkPipeline_CanStoreSequencedPacketsForLaterDeliveryInSendFirstStage() + { + // Server needs the simulator as it's the only one sending + var clientPipe1 = m_ClientDriver.CreatePipeline(typeof(UnreliableSequencedPipelineStage)); + var clientPipe2 = m_ClientDriver2.CreatePipeline(typeof(UnreliableSequencedPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(SimulatorPipelineStageInSend), typeof(UnreliableSequencedPipelineStage)); + Assert.AreEqual(clientPipe1, serverPipe); + Assert.AreEqual(clientPipe2, serverPipe); + + TestPipeline(30, serverPipe); + } + + [Test] + public void NetworkPipeline_CanStoreSequencedPacketsForLaterDeliveryInReceiveLastStage() + { + var clientPipe1 = m_ClientDriver.CreatePipeline(typeof(UnreliableSequencedPipelineStage), typeof(SimulatorPipelineStage)); + var clientPipe2 = m_ClientDriver2.CreatePipeline(typeof(UnreliableSequencedPipelineStage), typeof(SimulatorPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(UnreliableSequencedPipelineStage)); + Assert.AreEqual(clientPipe1, serverPipe); + Assert.AreEqual(clientPipe2, serverPipe); + + TestPipeline(30, serverPipe); + } + + [Test] + public void NetworkPipeline_CanStoreSequencedPacketsForLaterDeliveryInReceiveFirstStage() + { + var clientPipe1 = m_ClientDriver.CreatePipeline(typeof(SimulatorPipelineStage), typeof(UnreliableSequencedPipelineStage)); + var clientPipe2 = m_ClientDriver2.CreatePipeline(typeof(SimulatorPipelineStage), typeof(UnreliableSequencedPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(UnreliableSequencedPipelineStage)); + Assert.AreEqual(clientPipe1, serverPipe); + Assert.AreEqual(clientPipe2, serverPipe); + + TestPipeline(30, serverPipe); + } + + [Test] + public void NetworkPipeline_MultiplePipelinesWithHeadersWork() + { + m_ClientDriver.CreatePipeline(typeof(TestPipelineStageWithHeader), typeof(TestPipelineStageWithHeaderTwo)); + m_ClientDriver2.CreatePipeline(typeof(TestPipelineStageWithHeader), typeof(TestPipelineStageWithHeaderTwo)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(TestPipelineStageWithHeader), typeof(TestPipelineStageWithHeaderTwo)); + TestPipeline(30, serverPipe, 0); + } + + [Test] + public void NetworkPipeline_MultiplePipelinesWithHeadersWorkWithSimulator() + { + //m_ClientDriver.CreatePipeline(typeof(TestPipelineStageWithHeader), typeof(SimulatorPipelineStage), typeof(TestPipelineStageWithHeaderTwo)); + //m_ClientDriver2.CreatePipeline(typeof(SimulatorPipelineStage), typeof(TestPipelineStageWithHeader), typeof(TestPipelineStageWithHeaderTwo)); + m_ClientDriver.CreatePipeline(typeof(TestPipelineStageWithHeader), typeof(TestPipelineStageWithHeaderTwo)); + m_ClientDriver2.CreatePipeline(typeof(TestPipelineStageWithHeader), typeof(TestPipelineStageWithHeaderTwo)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(SimulatorPipelineStageInSend), typeof(TestPipelineStageWithHeader), typeof(TestPipelineStageWithHeaderTwo)); + TestPipeline(30, serverPipe); + } + + [Test] + public void NetworkPipeline_MuliplePipelinesWithInitializers() + { + m_ClientDriver.CreatePipeline(typeof(TestPipelineWithInitializers), typeof(TestPipelineWithInitializersTwo)); + m_ClientDriver2.CreatePipeline(typeof(TestPipelineWithInitializers), typeof(TestPipelineWithInitializersTwo)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(TestPipelineWithInitializers), typeof(TestPipelineWithInitializersTwo)); + TestPipeline(30, serverPipe, 0); + } + + [Test] + public void NetworkPipeline_MuliplePipelinesWithInitializersAndSimulator() + { + m_ClientDriver.CreatePipeline(typeof(TestPipelineWithInitializers), typeof(SimulatorPipelineStage), typeof(TestPipelineWithInitializersTwo)); + m_ClientDriver2.CreatePipeline(typeof(TestPipelineWithInitializers), typeof(TestPipelineWithInitializersTwo), typeof(SimulatorPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(SimulatorPipelineStageInSend), typeof(TestPipelineWithInitializers), typeof(TestPipelineWithInitializersTwo)); + TestPipeline(30, serverPipe); + } + + private void TestPipeline(int packetCount, NetworkPipeline serverPipe, int packetDelay = 100) + { + // Connect to server + var clientToServer = m_ClientDriver.Connect(m_ServerDriver.LocalEndPoint()); + var clientToServer2 = m_ClientDriver2.Connect(m_ServerDriver.LocalEndPoint()); + Assert.AreNotEqual(default(NetworkConnection), clientToServer); + Assert.AreNotEqual(default(NetworkConnection), clientToServer2); + m_ClientDriver.ScheduleUpdate().Complete(); + m_ClientDriver2.ScheduleUpdate().Complete(); + + // Driver only updates time in update, so must read start time before update + var startTime = Stopwatch.GetTimestamp() / TimeSpan.TicksPerMillisecond; + // Handle incoming connection from client + m_ServerDriver.ScheduleUpdate().Complete(); + var serverToClient = m_ServerDriver.Accept(); + Assert.AreNotEqual(default(NetworkConnection), serverToClient); + var serverToClient2 = m_ServerDriver.Accept(); + Assert.AreNotEqual(default(NetworkConnection), serverToClient2); + + // Send given packetCount number of packets in a row in one update + // Write 1's for packet 1, 2's for packet 2 and so on and verify they're received in same order + var strm = new DataStreamWriter(64, Allocator.Temp); + for (int i = 0; i < packetCount; i++) + { + strm.Clear(); + for (int j = 0; j < 16; j++) + strm.Write((int) i + 1); + m_ServerDriver.Send(serverPipe, serverToClient, strm); + m_ServerDriver.Send(serverPipe, serverToClient2, strm); + } + + m_ServerDriver.ScheduleUpdate().Complete(); + + // Receive incoming message from server + m_ClientDriver.ScheduleUpdate().Complete(); + m_ClientDriver2.ScheduleUpdate().Complete(); + DataStreamReader readStrm; + Assert.AreEqual(NetworkEvent.Type.Connect, clientToServer.PopEvent(m_ClientDriver, out readStrm)); + Assert.AreEqual(NetworkEvent.Type.Connect, clientToServer.PopEvent(m_ClientDriver2, out readStrm)); + + ClientReceivePackets(m_ClientDriver, packetCount, clientToServer, startTime, packetDelay); + ClientReceivePackets(m_ClientDriver2, packetCount, clientToServer2, startTime, packetDelay); + } + + private void ClientReceivePackets(GenericNetworkDriver clientDriver, int packetCount, NetworkConnection clientToServer, long startTime, int minDelay) + { + DataStreamReader readStrm; + NetworkEvent.Type netEvent; + var abortTimer = new Timer(); + while (true) + { + if (abortTimer.ElapsedMilliseconds > 2000) + Assert.Fail("Did not receive first delayed packet"); + netEvent = clientToServer.PopEvent(clientDriver, out readStrm); + if (netEvent == NetworkEvent.Type.Data) + break; + m_ServerDriver.ScheduleUpdate().Complete(); + clientDriver.ScheduleUpdate().Complete(); + } + + // All delayed packets (from first patch) should be poppable now + for (int i = 0; i < packetCount; i++) + { + var delay = Stopwatch.GetTimestamp() / TimeSpan.TicksPerMillisecond - startTime; + Assert.AreEqual(NetworkEvent.Type.Data, netEvent); + Assert.That(delay >= minDelay, "Delay too low on packet " + i + ": " + delay); + Assert.AreEqual(64, readStrm.Length); + var readCtx = default(DataStreamReader.Context); + for (int j = 0; j < 16; j++) + { + var read = readStrm.ReadInt(ref readCtx); + Assert.AreEqual(i + 1, read); + Assert.True(read > 0 && read <= packetCount, "read incorrect value: " + read); + } + + // Test done when all packets have been verified + if (i == packetCount - 1) + break; + + // It could be not all patch of packets were processed in one update (depending on how the timers land) + abortTimer = new Timer(); + while ((netEvent = clientToServer.PopEvent(clientDriver, out readStrm)) == NetworkEvent.Type.Empty) + { + if (abortTimer.ElapsedMilliseconds > 1000) + Assert.Fail("Didn't receive all delayed packets"); + clientDriver.ScheduleUpdate().Complete(); + m_ServerDriver.ScheduleUpdate().Complete(); + } + } + } + } +} diff --git a/Tests/Editor/NetworkPipelineTest.cs.meta b/Tests/Editor/NetworkPipelineTest.cs.meta new file mode 100644 index 0000000..def93b1 --- /dev/null +++ b/Tests/Editor/NetworkPipelineTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f2413d56d3b014d468eb09e594d227ee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/NetworkProtocolsTests.cs b/Tests/Editor/NetworkProtocolsTests.cs new file mode 100644 index 0000000..780ecdd --- /dev/null +++ b/Tests/Editor/NetworkProtocolsTests.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Unity.Networking.Transport.Tests +{ + class Protocols + { + } +} \ No newline at end of file diff --git a/Tests/Editor/NetworkProtocolsTests.cs.meta b/Tests/Editor/NetworkProtocolsTests.cs.meta new file mode 100644 index 0000000..3dd6ec4 --- /dev/null +++ b/Tests/Editor/NetworkProtocolsTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 194e452ea4df2c6478ae34de7f8893ce +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/ReliablePipelineTests.cs b/Tests/Editor/ReliablePipelineTests.cs new file mode 100644 index 0000000..bd41b60 --- /dev/null +++ b/Tests/Editor/ReliablePipelineTests.cs @@ -0,0 +1,1727 @@ +using System; +using NUnit.Framework; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Networking.Transport.Utilities; +using UnityEngine; + +namespace Unity.Networking.Transport.Tests +{ + public class ReliablePipelineTests + { + [Test] + public unsafe void ReliableUtility_ValidationScenarios() + { + // Receive a Packet Newer still gapped. [0, 1, Lost, 3, 4] + // Massage the resend flow using the Received Mask. [0, 1, Resend, 3, 4] + // Receive the missing packet '2' and massage the receive flow + + ReliableUtility.Parameters parameters = new ReliableUtility.Parameters + { + WindowSize = 32 + }; + + var processCapacity = ReliableUtility.ProcessCapacityNeeded(parameters); + var sharedCapacity = ReliableUtility.SharedCapacityNeeded(parameters); + + + // ep1 + var ep1SharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + var ep1SendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + var ep1RecvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + + // ep2 + var ep2SharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + var ep2SendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + var ep2RecvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + + // packet + var packet = new NativeArray(UnsafeUtility.SizeOf(), Allocator.Persistent); + packet[0] = 100; + + var header = new DataStreamWriter(UnsafeUtility.SizeOf(), Allocator.Persistent); + + ReliableSequencedPipelineStage ep1 = new ReliableSequencedPipelineStage(); + ReliableSequencedPipelineStage ep2 = new ReliableSequencedPipelineStage(); + + ep1.Initialize(parameters); + ep2.Initialize(parameters); + ep1.InitializeConnection(ep1SendBuffer, ep1RecvBuffer, ep1SharedBuffer); + ep2.InitializeConnection(ep2SendBuffer, ep2RecvBuffer, ep2SharedBuffer); + + var ep1sendContext = (ReliableUtility.Context*) ep1SendBuffer.GetUnsafePtr(); + //var ep1recvContext = (ReliableUtility.Context*) ep1RecvBuffer.GetUnsafePtr(); + //var ep1sharedContext = (ReliableUtility.SharedContext*) ep1SharedBuffer.GetUnsafePtr(); + + var ep2recvContext = (ReliableUtility.Context*) ep2RecvBuffer.GetUnsafePtr(); + //var ep2sendContext = (ReliableUtility.Context*) ep2SendBuffer.GetUnsafePtr(); + //var ep2sharedContext = (ReliableUtility.SharedContext*) ep2SharedBuffer.GetUnsafePtr(); + + // Send a Packet - Receive a Packet + var currentId = 0; + + var inboundSend = default(InboundBufferVec); + inboundSend.buffer1 = packet; + + bool needsUpdate = false; + bool needsResume = false; + bool needsSendUpdate = false; + var slice = default(NativeSlice); + var output = default(InboundBufferVec); + { + output = ep1.Send(new NetworkPipelineContext + { + header = header, + internalProcessBuffer = ep1SendBuffer, + internalSharedProcessBuffer = ep1SharedBuffer + }, inboundSend, ref needsResume, ref needsUpdate); + Assert.True(output.buffer1[0] == packet[0]); + Assert.True(!needsResume); + } + { + var info = ReliableUtility.GetPacketInformation(ep1SendBuffer, currentId); + var offset = ep1sendContext->DataPtrOffset; // + (index * ctx->DataStride); + NativeSlice data = new NativeSlice(ep1SendBuffer, offset, info->Size); + + + slice = ep2.Receive(new NetworkPipelineContext + { + internalProcessBuffer = ep2RecvBuffer, + internalSharedProcessBuffer = ep2SharedBuffer + }, data, ref needsResume, ref needsUpdate, ref needsSendUpdate); + + if (slice.Length > 0) + Assert.True(slice[0] == packet[0]); + } + Assert.True(!needsResume); + Assert.True(ep2recvContext->Delivered == currentId); + + // Scenario: Receive a Packet Newer then expected [0, 1, Lost, 3] + + // Start by "sending" 1, 2, 3; + for (int seq = currentId + 1; seq < 4; seq++) + { + packet[0] = (byte) (100 + seq); + + header.Clear(); + output = ep1.Send(new NetworkPipelineContext + { + header = header, + internalProcessBuffer = ep1SendBuffer, + internalSharedProcessBuffer = ep1SharedBuffer + }, inboundSend, ref needsResume, ref needsUpdate); + + Assert.True(!needsResume); + Assert.True(output.buffer1[0] == packet[0]); + } + + for (int seq = currentId + 1; seq < 4; seq++) + { + if (seq == 2) + continue; + + var info = ReliableUtility.GetPacketInformation(ep1SendBuffer, seq); + var offset = ep1sendContext->DataPtrOffset + ((seq % ep1sendContext->Capacity) * ep1sendContext->DataStride); + var inspectPacket = ReliableUtility.GetPacket(ep1SendBuffer, seq); + + NativeSlice data = new NativeSlice(ep1SendBuffer, offset, info->Size); + Assert.True(inspectPacket->Header.SequenceId == info->SequenceId); + + header.Clear(); + slice = ep2.Receive(new NetworkPipelineContext + { + header = header, + internalProcessBuffer = ep2RecvBuffer, + internalSharedProcessBuffer = ep2SharedBuffer + }, data, ref needsResume, ref needsUpdate, ref needsSendUpdate); + + if (slice.Length > 0) + { + Assert.True(slice[0] == seq + 100); + } + } + + // Receive packet number 2 and resume received packets. + bool first = true; + do + { + var data = default(NativeSlice); + if (first) + { + var seq = 2; + var info = ReliableUtility.GetPacketInformation(ep1SendBuffer, seq); + var offset = ep1sendContext->DataPtrOffset + + ((seq % ep1sendContext->Capacity) * ep1sendContext->DataStride); + var inspectPacket = ReliableUtility.GetPacket(ep1SendBuffer, seq); + + data = new NativeSlice(ep1SendBuffer, offset, info->Size); + Assert.True(inspectPacket->Header.SequenceId == info->SequenceId); + + first = false; + } + + slice = ep2.Receive(new NetworkPipelineContext + { + internalProcessBuffer = ep2RecvBuffer, + internalSharedProcessBuffer = ep2SharedBuffer + }, data, ref needsResume, ref needsUpdate, ref needsSendUpdate); + + if (slice.Length > 0) + { + Assert.True(slice[0] == ep2recvContext->Delivered + 100); + } + } while (needsResume); + + + packet.Dispose(); + header.Dispose(); + ep1SharedBuffer.Dispose(); + ep1SendBuffer.Dispose(); + ep1RecvBuffer.Dispose(); + ep2SharedBuffer.Dispose(); + ep2SendBuffer.Dispose(); + ep2RecvBuffer.Dispose(); + } + + + [Test] + public unsafe void ReliableUtility_Validation() + { + int capacity = 5; + NativeArray buffer = new NativeArray(1, Allocator.Persistent); + ReliableUtility.Parameters parameters = new ReliableUtility.Parameters + { + WindowSize = capacity + }; + + int result = ReliableUtility.ProcessCapacityNeeded(parameters); + NativeArray processBuffer = new NativeArray(result, Allocator.Persistent); + + ReliableUtility.InitializeProcessContext(processBuffer, parameters); + + Assert.IsTrue(ReliableUtility.TryAquire(processBuffer, 0)); + Assert.IsTrue(ReliableUtility.TryAquire(processBuffer, 1)); + Assert.IsTrue(ReliableUtility.TryAquire(processBuffer, 2)); + Assert.IsTrue(ReliableUtility.TryAquire(processBuffer, 3)); + Assert.IsTrue(ReliableUtility.TryAquire(processBuffer, 4)); + Assert.IsFalse(ReliableUtility.TryAquire(processBuffer, 5)); + + ReliableUtility.Release(processBuffer, 0, 5); + + Assert.IsTrue(ReliableUtility.TryAquire(processBuffer, 0)); + Assert.IsTrue(ReliableUtility.TryAquire(processBuffer, 1)); + Assert.IsTrue(ReliableUtility.TryAquire(processBuffer, 2)); + Assert.IsTrue(ReliableUtility.TryAquire(processBuffer, 3)); + Assert.IsTrue(ReliableUtility.TryAquire(processBuffer, 4)); + + buffer[0] = (byte)(1); + + ReliableUtility.SetPacket(processBuffer, 0, buffer); + + + var slice = ReliableUtility.GetPacket(processBuffer, 0); + Assert.IsTrue(slice->Buffer[0] == buffer[0]); + + for (int i = 0; i < capacity * 5; i++) + { + ReliableUtility.SetPacket(processBuffer, i, buffer); + slice = ReliableUtility.GetPacket(processBuffer, i); + Assert.IsTrue(slice->Buffer[0] == buffer[0]); + } + ReliableUtility.Release(processBuffer, 0, 5); + + processBuffer.Dispose(); + buffer.Dispose(); + } + + [Test] + public unsafe void ReliableUtility_AckPackets_SeqIdBeginAt0() + { + ReliableUtility.Parameters parameters = new ReliableUtility.Parameters + { + WindowSize = 10 + }; + + int processCapacity = ReliableUtility.ProcessCapacityNeeded(parameters); + int sharedCapacity = ReliableUtility.SharedCapacityNeeded(parameters); + NativeArray recvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + + ReliableUtility.InitializeContext(sharedBuffer, sendBuffer, recvBuffer, parameters); + + var pipelineContext = new NetworkPipelineContext + {internalProcessBuffer = sendBuffer, internalSharedProcessBuffer = sharedBuffer, timestamp = 1000}; + + // Sending seqId 3, last received ID 0 (1 is not yet acked, 2 was dropped) + var sharedContext = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedContext->SentPackets.Sequence = 0; // Last sent is initialized to what you are sending next + sharedContext->SentPackets.Acked = -1; + sharedContext->SentPackets.AckMask = 0x1; + sharedContext->ReceivedPackets.Sequence = sharedContext->SentPackets.Acked; + sharedContext->ReceivedPackets.AckMask = sharedContext->SentPackets.AckMask; + var receiveContext = (ReliableUtility.Context*) recvBuffer.GetUnsafePtr(); + receiveContext->Delivered = sharedContext->SentPackets.Acked; + + using (var stream = new DataStreamWriter(4, Allocator.Temp)) + { + // Add buffers in resend queue + stream.Write((int) 10); + ReliableUtility.SetPacket(sendBuffer, 65535, stream.GetNativeSlice(0, stream.Length)); + ReliableUtility.GetPacketInformation(sendBuffer, 65535)->SendTime = 980; + ReliableUtility.StoreTimestamp(pipelineContext.internalSharedProcessBuffer, 65535, 980); + ReliableUtility.StoreReceiveTimestamp(pipelineContext.internalSharedProcessBuffer, 65535, 990, 16); + stream.Clear(); + stream.Write((int) 11); + ReliableUtility.SetPacket(sendBuffer, 0, stream.GetNativeSlice(0, stream.Length)); + ReliableUtility.GetPacketInformation(sendBuffer, 0)->SendTime = 990; + ReliableUtility.StoreTimestamp(pipelineContext.internalSharedProcessBuffer, 0, 990); + + ReliableUtility.ReleaseOrResumePackets(pipelineContext); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + + // Validate that packet tracking state is correct, 65535 should be released, 0 should still be there + Assert.AreEqual(-1, ReliableUtility.GetPacketInformation(sendBuffer, 65535)->SequenceId); + Assert.AreEqual(0, ReliableUtility.GetPacketInformation(sendBuffer, 0)->SequenceId); + } + recvBuffer.Dispose(); + sendBuffer.Dispose(); + sharedBuffer.Dispose(); + } + + [Test] + public unsafe void ReliableUtility_AckPackets_SeqIdWrap1() + { + ReliableUtility.Parameters parameters = new ReliableUtility.Parameters + { + WindowSize = 10 + }; + + int processCapacity = ReliableUtility.ProcessCapacityNeeded(parameters); + int sharedCapacity = ReliableUtility.SharedCapacityNeeded(parameters); + NativeArray recvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + + ReliableUtility.InitializeContext(sharedBuffer, sendBuffer, recvBuffer, parameters); + + var pipelineContext = new NetworkPipelineContext + {internalProcessBuffer = sendBuffer, internalSharedProcessBuffer = sharedBuffer, timestamp = 1000}; + + // Sending seqId 3, last received ID 2 (same as last sent packet) + var sharedContext = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedContext->SentPackets.Sequence = 3; + sharedContext->SentPackets.Acked = 2; + sharedContext->SentPackets.AckMask = 0xFFFFFFFF; + sharedContext->ReceivedPackets.Sequence = sharedContext->SentPackets.Acked; + sharedContext->ReceivedPackets.AckMask = sharedContext->SentPackets.AckMask; + var receiveContext = (ReliableUtility.Context*) recvBuffer.GetUnsafePtr(); + receiveContext->Delivered = sharedContext->SentPackets.Acked; + + using (var stream = new DataStreamWriter(4, Allocator.Temp)) + { + // Add buffers in resend queue + stream.Write((int) 10); + ReliableUtility.SetPacket(sendBuffer, 1, stream.GetNativeSlice(0, stream.Length)); + ReliableUtility.GetPacketInformation(sendBuffer, 1)->SendTime = 980; + ReliableUtility.StoreTimestamp(pipelineContext.internalSharedProcessBuffer, 1, 980); + ReliableUtility.StoreReceiveTimestamp(pipelineContext.internalSharedProcessBuffer, 1, 990, 16); + stream.Clear(); + stream.Write((int) 11); + ReliableUtility.SetPacket(sendBuffer, 2, stream.GetNativeSlice(0, stream.Length)); + ReliableUtility.GetPacketInformation(sendBuffer, 2)->SendTime = 990; + ReliableUtility.StoreTimestamp(pipelineContext.internalSharedProcessBuffer, 2, 990); + ReliableUtility.StoreReceiveTimestamp(pipelineContext.internalSharedProcessBuffer, 2, 1000, 16); + + ReliableUtility.ReleaseOrResumePackets(pipelineContext); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + + // Validate that packet tracking state is correct, both packets should be released + Assert.AreEqual(-1, ReliableUtility.GetPacketInformation(sendBuffer, 1)->SequenceId); + Assert.AreEqual(-1, ReliableUtility.GetPacketInformation(sendBuffer, 2)->SequenceId); + } + recvBuffer.Dispose(); + sendBuffer.Dispose(); + sharedBuffer.Dispose(); + } + + [Test] + public unsafe void ReliableUtility_AckPackets_SeqIdWrap2() + { + ReliableUtility.Parameters parameters = new ReliableUtility.Parameters + { + WindowSize = 10 + }; + + int processCapacity = ReliableUtility.ProcessCapacityNeeded(parameters); + int sharedCapacity = ReliableUtility.SharedCapacityNeeded(parameters); + NativeArray recvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + + ReliableUtility.InitializeContext(sharedBuffer, sendBuffer, recvBuffer, parameters); + + var pipelineContext = new NetworkPipelineContext + {internalProcessBuffer = sendBuffer, internalSharedProcessBuffer = sharedBuffer}; + + // Sending seqId 3, last received ID 65535 (same as last sent) + var sharedContext = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedContext->SentPackets.Sequence = 0; + sharedContext->SentPackets.Acked = 65535; + sharedContext->SentPackets.AckMask = 0xFFFFFFFF; + sharedContext->ReceivedPackets.Sequence = sharedContext->SentPackets.Acked; + sharedContext->ReceivedPackets.AckMask = sharedContext->SentPackets.AckMask; + var receiveContext = (ReliableUtility.Context*) recvBuffer.GetUnsafePtr(); + receiveContext->Delivered = sharedContext->SentPackets.Acked; + + using (var stream = new DataStreamWriter(4, Allocator.Temp)) + { + // Add buffers in resend queue + stream.Write((int) 10); + ReliableUtility.SetPacket(sendBuffer, 65535, stream.GetNativeSlice(0, stream.Length)); + ReliableUtility.GetPacketInformation(sendBuffer, 65535)->SendTime = 980; + ReliableUtility.StoreTimestamp(pipelineContext.internalSharedProcessBuffer, 65535, 980); + ReliableUtility.StoreReceiveTimestamp(pipelineContext.internalSharedProcessBuffer, 65535, 990, 16); + + ReliableUtility.ReleaseOrResumePackets(pipelineContext); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + + // Validate that packet tracking state is correct, 65535 should be released + Assert.AreEqual(-1, ReliableUtility.GetPacketInformation(sendBuffer, 65535)->SequenceId); + } + recvBuffer.Dispose(); + sendBuffer.Dispose(); + sharedBuffer.Dispose(); + } + + [Test] + public unsafe void ReliableUtility_AckPackets_SeqIdWrap3() + { + ReliableUtility.Parameters parameters = new ReliableUtility.Parameters + { + WindowSize = 10 + }; + + int processCapacity = ReliableUtility.ProcessCapacityNeeded(parameters); + int sharedCapacity = ReliableUtility.SharedCapacityNeeded(parameters); + NativeArray recvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + + ReliableUtility.InitializeContext(sharedBuffer, sendBuffer, recvBuffer, parameters); + + var pipelineContext = new NetworkPipelineContext + {internalProcessBuffer = sendBuffer, internalSharedProcessBuffer = sharedBuffer}; + + // Sending seqId 3, last received ID 0 (1 is not yet acked, 2 was dropped) + var sharedContext = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedContext->SentPackets.Sequence = 17; + sharedContext->SentPackets.Acked = 16; + sharedContext->SentPackets.AckMask = 0xFFFFDBB7; + sharedContext->ReceivedPackets.Sequence = sharedContext->SentPackets.Acked; + sharedContext->ReceivedPackets.AckMask = sharedContext->SentPackets.AckMask; + var receiveContext = (ReliableUtility.Context*) recvBuffer.GetUnsafePtr(); + receiveContext->Delivered = sharedContext->SentPackets.Acked; + + using (var stream = new DataStreamWriter(4, Allocator.Temp)) + { + // Add buffers in resend queue + stream.Write((int) 10); + ReliableUtility.SetPacket(sendBuffer, 16, stream.GetNativeSlice(0, stream.Length)); + + ReliableUtility.ReleaseOrResumePackets(pipelineContext); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + + // Validate that packet tracking state is correct, packet 16 should be released + Assert.AreEqual(-1, ReliableUtility.GetPacketInformation(sendBuffer, 16)->SequenceId); + } + recvBuffer.Dispose(); + sendBuffer.Dispose(); + sharedBuffer.Dispose(); + } + + [Test] + public unsafe void ReliableUtility_AckPackets_ReleaseSlotWithWrappedSeqId() + { + ReliableUtility.Parameters parameters = new ReliableUtility.Parameters + { + WindowSize = 10 + }; + + int processCapacity = ReliableUtility.ProcessCapacityNeeded(parameters); + int sharedCapacity = ReliableUtility.SharedCapacityNeeded(parameters); + NativeArray recvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + + ReliableUtility.InitializeContext(sharedBuffer, sendBuffer, recvBuffer, parameters); + + var pipelineContext = new NetworkPipelineContext + {internalProcessBuffer = sendBuffer, internalSharedProcessBuffer = sharedBuffer}; + + // Sending seqId 3, last received ID 0 (1 is not yet acked, 2 was dropped) + var sharedContext = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedContext->SentPackets.Sequence = 1; + sharedContext->SentPackets.Acked = 0; + sharedContext->SentPackets.AckMask = 0xFFFFFFFF; + sharedContext->ReceivedPackets.Sequence = sharedContext->SentPackets.Acked; + sharedContext->ReceivedPackets.AckMask = sharedContext->SentPackets.AckMask; + var receiveContext = (ReliableUtility.Context*) recvBuffer.GetUnsafePtr(); + receiveContext->Delivered = sharedContext->SentPackets.Acked; + + using (var stream = new DataStreamWriter(4, Allocator.Temp)) + { + // Add buffers in resend queue + stream.Write((int) 10); + ReliableUtility.SetPacket(sendBuffer, 0, stream.GetNativeSlice(0, stream.Length)); + stream.Clear(); + stream.Write((int) 11); + ReliableUtility.SetPacket(sendBuffer, 65535, stream.GetNativeSlice(0, stream.Length)); + + ReliableUtility.ReleaseOrResumePackets(pipelineContext); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + + // Validate that packet tracking state is correct, slot with seqId 0 and 65535 should have been released + Assert.AreEqual(-1, ReliableUtility.GetPacketInformation(sendBuffer, 0)->SequenceId); + Assert.AreEqual(-1, ReliableUtility.GetPacketInformation(sendBuffer, 65535)->SequenceId); + } + recvBuffer.Dispose(); + sendBuffer.Dispose(); + sharedBuffer.Dispose(); + } + + [Test] + public unsafe void ReliableUtility_AckPackets_AckMaskShiftsProperly1() + { + ReliableUtility.Parameters parameters = new ReliableUtility.Parameters + { + WindowSize = 10 + }; + + int processCapacity = ReliableUtility.ProcessCapacityNeeded(parameters); + int sharedCapacity = ReliableUtility.SharedCapacityNeeded(parameters); + NativeArray recvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + + ReliableUtility.InitializeContext(sharedBuffer, sendBuffer, recvBuffer, parameters); + + var pipelineContext = new NetworkPipelineContext + {internalProcessBuffer = sendBuffer, internalSharedProcessBuffer = sharedBuffer, timestamp = 1000}; + + // Sending seqId 3, last received ID 0 (1 is not yet acked, 2 was dropped) + var sharedContext = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedContext->SentPackets.Sequence = 4; + sharedContext->SentPackets.Acked = 3; + sharedContext->SentPackets.AckMask = 0xFFFFFFFD; // bit 0 = seqId 3 (1), bit 1 = seqId 2 (0) + sharedContext->ReceivedPackets.Sequence = sharedContext->SentPackets.Acked; + sharedContext->ReceivedPackets.AckMask = sharedContext->SentPackets.AckMask; + var receiveContext = (ReliableUtility.Context*) recvBuffer.GetUnsafePtr(); + receiveContext->Delivered = sharedContext->SentPackets.Acked; + + using (var stream = new DataStreamWriter(4, Allocator.Temp)) + { + // Add buffers in resend queue + // SeqId 3 is received and ready to be released + stream.Write((int) 10); + ReliableUtility.SetPacket(sendBuffer, 3, stream.GetNativeSlice(0, stream.Length)); + ReliableUtility.GetPacketInformation(sendBuffer, 3)->SendTime = 990; + ReliableUtility.StoreTimestamp(pipelineContext.internalSharedProcessBuffer, 3, 980); + ReliableUtility.StoreReceiveTimestamp(pipelineContext.internalSharedProcessBuffer, 3, 990, 16); + stream.Clear(); + // SeqId 2 is not yet received so it should stick around + stream.Write((int) 11); + ReliableUtility.SetPacket(sendBuffer, 2, stream.GetNativeSlice(0, stream.Length)); + ReliableUtility.GetPacketInformation(sendBuffer, 2)->SendTime = 1000; + ReliableUtility.StoreTimestamp(pipelineContext.internalSharedProcessBuffer, 2, 1000); + + ReliableUtility.ReleaseOrResumePackets(pipelineContext); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + + // Validate that packet tracking state is correct, packet 3 should be released (has been acked), 2 should stick around + Assert.AreEqual(-1, ReliableUtility.GetPacketInformation(sendBuffer, 3)->SequenceId); + Assert.AreEqual(2, ReliableUtility.GetPacketInformation(sendBuffer, 2)->SequenceId); + } + recvBuffer.Dispose(); + sendBuffer.Dispose(); + sharedBuffer.Dispose(); + } + + [Test] + public unsafe void ReliableUtility_AckPackets_AckMaskShiftsProperly2() + { + ReliableUtility.Parameters parameters = new ReliableUtility.Parameters + { + WindowSize = 10 + }; + + int processCapacity = ReliableUtility.ProcessCapacityNeeded(parameters); + int sharedCapacity = ReliableUtility.SharedCapacityNeeded(parameters); + NativeArray recvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + + ReliableUtility.InitializeContext(sharedBuffer, sendBuffer, recvBuffer, parameters); + + var pipelineContext = new NetworkPipelineContext + {internalProcessBuffer = sendBuffer, internalSharedProcessBuffer = sharedBuffer, timestamp = 1000}; + + // Sending seqId 3, last received ID 0 (1 is not yet acked, 2 was dropped) + var sharedContext = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedContext->SentPackets.Sequence = 5; + sharedContext->SentPackets.Acked = 4; + sharedContext->SentPackets.AckMask = 0xFFFFFFFD; // bit 0 = seqId 4 (1), bit 1 = seqId 3 (0) + sharedContext->ReceivedPackets.Sequence = sharedContext->SentPackets.Acked; + sharedContext->ReceivedPackets.AckMask = sharedContext->SentPackets.AckMask; + var receiveContext = (ReliableUtility.Context*) recvBuffer.GetUnsafePtr(); + receiveContext->Delivered = sharedContext->SentPackets.Acked; + + using (var stream = new DataStreamWriter(4, Allocator.Temp)) + { + // Add buffers in resend queue + // SeqId 4 is received and ready to be released + stream.Write((int) 10); + ReliableUtility.SetPacket(sendBuffer, 4, stream.GetNativeSlice(0, stream.Length)); + ReliableUtility.GetPacketInformation(sendBuffer, 4)->SendTime = 980; + ReliableUtility.StoreTimestamp(pipelineContext.internalSharedProcessBuffer, 4, 980); + ReliableUtility.StoreReceiveTimestamp(pipelineContext.internalSharedProcessBuffer, 4, 990, 16); + stream.Clear(); + stream.Write((int) 11); + ReliableUtility.SetPacket(sendBuffer, 3, stream.GetNativeSlice(0, stream.Length)); + ReliableUtility.GetPacketInformation(sendBuffer, 3)->SendTime = 1000; + ReliableUtility.StoreTimestamp(pipelineContext.internalSharedProcessBuffer, 3, 1000); + + ReliableUtility.ReleaseOrResumePackets(pipelineContext); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + + // Validate that packet tracking state is correct, packet 3 should be released (has been acked), 2 should stick around + Assert.AreEqual(-1, ReliableUtility.GetPacketInformation(sendBuffer, 4)->SequenceId); + Assert.AreEqual(3, ReliableUtility.GetPacketInformation(sendBuffer, 3)->SequenceId); + } + recvBuffer.Dispose(); + sendBuffer.Dispose(); + sharedBuffer.Dispose(); + } + + [Test] + public unsafe void ReliableUtility_TimestampHandling() + { + ReliableUtility.Parameters parameters = new ReliableUtility.Parameters + { + WindowSize = 3 + }; + + int processCapacity = ReliableUtility.ProcessCapacityNeeded(parameters); + int sharedCapacity = ReliableUtility.SharedCapacityNeeded(parameters); + NativeArray ep1RecvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray ep1SendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray ep1SharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + NativeArray ep2RecvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray ep2SendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray ep2SharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + + ReliableUtility.InitializeContext(ep1SharedBuffer, ep1SendBuffer, ep1RecvBuffer, parameters); + ReliableUtility.InitializeContext(ep2SharedBuffer, ep2SendBuffer, ep2RecvBuffer, parameters); + + // When sending we store the send timestamp of the sequence ID (EP1 -> EP2) + ushort ep1SeqId = 10; + ReliableUtility.StoreTimestamp(ep1SharedBuffer, ep1SeqId, 900); + + // EP2 also sends something to EP1 + ushort ep2SeqId = 100; + ReliableUtility.StoreTimestamp(ep2SharedBuffer, ep2SeqId, 910); + + // When EP2 receives the packet the receive time is stored + ReliableUtility.StoreRemoteReceiveTimestamp(ep2SharedBuffer, ep1SeqId, 920); + + // EP2 also stores the timing information in the EP1 packet (processing time for the packet it sent earlier) + ReliableUtility.StoreReceiveTimestamp(ep2SharedBuffer, ep2SeqId, 920, 10); + + // When EP2 sends another packet to EP1 it calculates ep1SeqId processing time + int processTime = ReliableUtility.CalculateProcessingTime(ep2SharedBuffer, ep1SeqId, 930); + + // ep1SeqId processing time should be 10 ms (930 - 920) + Assert.AreEqual(10, processTime); + + // Verify information written so far (send/receive times + processing time) + var timerData = ReliableUtility.GetLocalPacketTimer(ep2SharedBuffer, ep2SeqId); + Assert.IsTrue(timerData != null, "Packet timing data not found"); + Assert.AreEqual(ep2SeqId, timerData->SequenceId); + Assert.AreEqual(10, timerData->ProcessingTime); + Assert.AreEqual(910, timerData->SentTime); + Assert.AreEqual(920, timerData->ReceiveTime); + + var ep2SharedCtx = (ReliableUtility.SharedContext*) ep2SharedBuffer.GetUnsafePtr(); + Debug.Log("LastRtt=" + ep2SharedCtx->RttInfo.LastRtt); + Debug.Log("SmoothedRTT=" + ep2SharedCtx->RttInfo.SmoothedRtt); + Debug.Log("ResendTimeout=" + ep2SharedCtx->RttInfo.ResendTimeout); + Debug.Log("SmoothedVariance=" + ep2SharedCtx->RttInfo.SmoothedVariance); + + ep1RecvBuffer.Dispose(); + ep1SendBuffer.Dispose(); + ep1SharedBuffer.Dispose(); + ep2RecvBuffer.Dispose(); + ep2SendBuffer.Dispose(); + ep2SharedBuffer.Dispose(); + } + + [Test] + public unsafe void Receive_ResumesMultipleStoredPacketsAroundWrapPoint1() + { + ReliableUtility.Parameters parameters = new ReliableUtility.Parameters + { + WindowSize = 10 + }; + + int processCapacity = ReliableUtility.ProcessCapacityNeeded(parameters); + int sharedCapacity = ReliableUtility.SharedCapacityNeeded(parameters); + NativeArray recvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + + ReliableUtility.InitializeContext(new NativeSlice(sharedBuffer), new NativeSlice(sendBuffer), new NativeSlice(recvBuffer), parameters); + + var pipelineContext = new NetworkPipelineContext + {internalProcessBuffer = recvBuffer, internalSharedProcessBuffer = sharedBuffer}; + + var sharedContext = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedContext->SentPackets.Sequence = 3; // what was last sent doesn't matter here + sharedContext->SentPackets.Acked = 2; + sharedContext->SentPackets.AckMask = 0xFFFFFFF7; // bit 0,1,2 maps to seqId 2,1,0 all delivered, bit 3 is seqId 65535 which is not yet delivered + sharedContext->ReceivedPackets.Sequence = sharedContext->SentPackets.Acked; + sharedContext->ReceivedPackets.AckMask = sharedContext->SentPackets.AckMask; + var receiveContext = (ReliableUtility.Context*) recvBuffer.GetUnsafePtr(); + receiveContext->Delivered = 65534; // latest in sequence delivered packet, one less than what unclogs the packet jam + + var reliablePipeline = new ReliableSequencedPipelineStage(); + + using (var stream = new DataStreamWriter(4, Allocator.Temp)) + using (var inboundStream = new DataStreamWriter(4, Allocator.Temp)) + { + // Add buffers to receive queue, packets which should be resume received after packet jam is unclogged + stream.Clear(); + stream.Write((int) 100); + ReliableUtility.SetPacket(recvBuffer, 0, stream.GetNativeSlice(0, stream.Length)); + stream.Clear(); + stream.Write((int) 200); + ReliableUtility.SetPacket(recvBuffer, 1, stream.GetNativeSlice(0, stream.Length)); + stream.Clear(); + stream.Write((int) 300); + ReliableUtility.SetPacket(recvBuffer, 2, stream.GetNativeSlice(0, stream.Length)); + + // Generate the packet which will be handled in receive + NativeSlice packet = default; + GeneratePacket(9000, 2, 0xFFFFFFFF, 65535, ref sendBuffer, out packet); + + bool needsResume = false; + bool needsUpdate = false; + bool needsSendUpdate = false; + // Process 65535, 0 should then be next in line on the resume field + reliablePipeline.Receive(pipelineContext, packet, ref needsResume, ref needsUpdate, ref needsSendUpdate); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + Assert.AreEqual(0, receiveContext->Resume); + Assert.IsTrue(needsResume); + // Process 0, after that 1 is up + reliablePipeline.Receive(pipelineContext, packet, ref needsResume, ref needsUpdate, ref needsSendUpdate); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + Assert.AreEqual(1, receiveContext->Resume); + Assert.IsTrue(needsResume); + // Process 1, after that 2 is up + reliablePipeline.Receive(pipelineContext, packet, ref needsResume, ref needsUpdate, ref needsSendUpdate); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + Assert.AreEqual(2, receiveContext->Resume); + Assert.IsTrue(needsResume); + // Process 2, and we are done + reliablePipeline.Receive(pipelineContext, packet, ref needsResume, ref needsUpdate, ref needsSendUpdate); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + Assert.AreEqual(-1, receiveContext->Resume); + Assert.IsFalse(needsResume); + } + recvBuffer.Dispose(); + sendBuffer.Dispose(); + sharedBuffer.Dispose(); + } + + [Test] + public unsafe void Receive_ResumesMultipleStoredPacketsAroundWrapPoint2() + { + ReliableUtility.Parameters parameters = new ReliableUtility.Parameters + { + WindowSize = 10 + }; + + int processCapacity = ReliableUtility.ProcessCapacityNeeded(parameters); + int sharedCapacity = ReliableUtility.SharedCapacityNeeded(parameters); + NativeArray recvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + + ReliableUtility.InitializeContext(new NativeSlice(sharedBuffer), new NativeSlice(sendBuffer), new NativeSlice(recvBuffer), parameters); + + var pipelineContext = new NetworkPipelineContext + {internalProcessBuffer = recvBuffer, internalSharedProcessBuffer = sharedBuffer}; + + var sharedContext = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedContext->SentPackets.Sequence = 2; // what was last sent doesn't matter here + sharedContext->SentPackets.Acked = 1; + sharedContext->SentPackets.AckMask = 0xFFFFFFF7; // bit 0,1,2 maps to seqId 1,0,65535 all delivered, bit 3 is seqId 65534 which is not yet delivered + sharedContext->ReceivedPackets.Sequence = 1; + sharedContext->ReceivedPackets.AckMask = 0xFFFFFFF7; + var receiveContext = (ReliableUtility.Context*) recvBuffer.GetUnsafePtr(); + receiveContext->Delivered = 65533; // latest in sequence delivered packet, one less than what unclogs the packet jam + + var reliablePipeline = new ReliableSequencedPipelineStage(); + + using (var stream = new DataStreamWriter(4, Allocator.Temp)) + { + // Add buffers to receive queue, packets which should be resume received after packet jam is unclogged + stream.Clear(); + stream.Write((int) 100); + ReliableUtility.SetPacket(recvBuffer, 65535, stream.GetNativeSlice(0, stream.Length)); + stream.Clear(); + stream.Write((int) 200); + ReliableUtility.SetPacket(recvBuffer, 0, stream.GetNativeSlice(0, stream.Length)); + stream.Clear(); + stream.Write((int) 300); + ReliableUtility.SetPacket(recvBuffer, 1, stream.GetNativeSlice(0, stream.Length)); + + // Generate the packet which will be handled in receive + NativeSlice packet = default; + GeneratePacket(9000, 65533, 0xFFFFFFFF, 65534, ref sendBuffer, out packet); + + bool needsResume = false; + bool needsUpdate = false; + bool needsSendUpdate = false; + // Process 65534, 65535 should then be next in line on the resume field + reliablePipeline.Receive(pipelineContext, packet, ref needsResume, ref needsUpdate, ref needsSendUpdate); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + Assert.AreEqual(65535, receiveContext->Resume); + Assert.IsTrue(needsResume); + // Process 65535, after that 0 is up + reliablePipeline.Receive(pipelineContext, packet, ref needsResume, ref needsUpdate, ref needsSendUpdate); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + Assert.AreEqual(0, receiveContext->Resume); + Assert.IsTrue(needsResume); + // Process 0, after that 1 is up + reliablePipeline.Receive(pipelineContext, packet, ref needsResume, ref needsUpdate, ref needsSendUpdate); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + Assert.AreEqual(1, receiveContext->Resume); + Assert.IsTrue(needsResume); + // Process 1, and we are done + reliablePipeline.Receive(pipelineContext, packet, ref needsResume, ref needsUpdate, ref needsSendUpdate); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + Assert.AreEqual(-1, receiveContext->Resume); + Assert.IsFalse(needsResume); + } + recvBuffer.Dispose(); + sendBuffer.Dispose(); + sharedBuffer.Dispose(); + } + + [Test] + public unsafe void Receive_ResumesMultipleStoredPacketsAndSetsAckedAckMaskProperly() + { + ReliableUtility.Parameters parameters = new ReliableUtility.Parameters + { + WindowSize = 10 + }; + + int processCapacity = ReliableUtility.ProcessCapacityNeeded(parameters); + int sharedCapacity = ReliableUtility.SharedCapacityNeeded(parameters); + NativeArray recvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + + ReliableUtility.InitializeContext(new NativeSlice(sharedBuffer), new NativeSlice(sendBuffer), new NativeSlice(recvBuffer), parameters); + + var pipelineContext = new NetworkPipelineContext + {internalProcessBuffer = recvBuffer, internalSharedProcessBuffer = sharedBuffer}; + + var sharedContext = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedContext->SentPackets.Sequence = 99; // what was last sent doesn't matter here + sharedContext->SentPackets.Acked = 97; + sharedContext->SentPackets.AckMask = 0xFFFFFFFF; + sharedContext->ReceivedPackets.Sequence = 98; + sharedContext->ReceivedPackets.AckMask = 0xFFFFFFF7; + var receiveContext = (ReliableUtility.Context*) recvBuffer.GetUnsafePtr(); + receiveContext->Delivered = 94; // latest in sequence delivered packet, one less than what unclogs the packet jam + + var reliablePipeline = new ReliableSequencedPipelineStage(); + + using (var stream = new DataStreamWriter(4, Allocator.Temp)) + { + // Add buffers to receive queue, packets which should be resume received after packet jam is unclogged + stream.Clear(); + stream.Write((int) 200); + ReliableUtility.SetPacket(recvBuffer, 96, stream.GetNativeSlice(0, stream.Length)); + stream.Clear(); + stream.Write((int) 300); + ReliableUtility.SetPacket(recvBuffer, 97, stream.GetNativeSlice(0, stream.Length)); + stream.Clear(); + stream.Write((int) 300); + ReliableUtility.SetPacket(recvBuffer, 98, stream.GetNativeSlice(0, stream.Length)); + + bool needsResume = false; + bool needsUpdate = false; + bool needsSendUpdate = false; + NativeSlice packet = default; + GeneratePacket(9000, 98, 0xFFFFFFFF, 99, ref sendBuffer, out packet); + + // Receive 99, it's out of order so should be queued for later (waiting for 95) + reliablePipeline.Receive(pipelineContext, packet, ref needsResume, ref needsUpdate, ref needsSendUpdate); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + Assert.AreEqual(-1, receiveContext->Resume); + Assert.IsFalse(needsResume); + + GeneratePacket(10000, 98, 0xFFFFFFFF, 95, ref sendBuffer, out packet); + + // First 95 is received and then receive resume runs up to 99 + reliablePipeline.Receive(pipelineContext, packet, ref needsResume, ref needsUpdate, ref needsSendUpdate); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + Assert.AreEqual(96, receiveContext->Resume); + Assert.IsTrue(needsResume); + reliablePipeline.Receive(pipelineContext, packet, ref needsResume, ref needsUpdate, ref needsSendUpdate); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + Assert.AreEqual(97, receiveContext->Resume); + Assert.IsTrue(needsResume); + reliablePipeline.Receive(pipelineContext, packet, ref needsResume, ref needsUpdate, ref needsSendUpdate); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + Assert.AreEqual(98, receiveContext->Resume); + Assert.IsTrue(needsResume); + reliablePipeline.Receive(pipelineContext, packet, ref needsResume, ref needsUpdate, ref needsSendUpdate); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + Assert.AreEqual(99, receiveContext->Resume); + Assert.IsTrue(needsResume); + reliablePipeline.Receive(pipelineContext, packet, ref needsResume, ref needsUpdate, ref needsSendUpdate); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, sharedContext->errorCode); + Assert.AreEqual(-1, receiveContext->Resume); + Assert.IsFalse(needsResume); + + // Verify that the ReceivePackets state is correct, 99 should be latest received and ackmask 0xFFFFF + Assert.AreEqual(99, sharedContext->ReceivedPackets.Sequence); + Assert.AreEqual(0xFFFFFFFF, sharedContext->ReceivedPackets.AckMask); + } + recvBuffer.Dispose(); + sendBuffer.Dispose(); + sharedBuffer.Dispose(); + } + + [Test] + public unsafe void Send_PacketsAreAcked_SendingPacket() + { + ReliableUtility.Parameters parameters = new ReliableUtility.Parameters + { + WindowSize = 3 + }; + + int processCapacity = ReliableUtility.ProcessCapacityNeeded(parameters); + int sharedCapacity = ReliableUtility.SharedCapacityNeeded(parameters); + NativeArray recvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + + ReliableUtility.InitializeContext(new NativeSlice(sharedBuffer), new NativeSlice(sendBuffer), new NativeSlice(recvBuffer), parameters); + + var pipelineContext = new NetworkPipelineContext + {internalProcessBuffer = sendBuffer, internalSharedProcessBuffer = sharedBuffer}; + + var sharedContext = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedContext->SentPackets.Sequence = 3; + sharedContext->SentPackets.Acked = 2; + sharedContext->SentPackets.AckMask = 0xFFFFFFFF; + sharedContext->ReceivedPackets.Sequence = 2; + sharedContext->ReceivedPackets.AckMask = 0xFFFFFFFF; + var receiveContext = (ReliableUtility.Context*) recvBuffer.GetUnsafePtr(); + receiveContext->Delivered = 1; + + var reliablePipeline = new ReliableSequencedPipelineStage(); + + using (var stream = new DataStreamWriter(4, Allocator.Temp)) + using (pipelineContext.header = new DataStreamWriter(UnsafeUtility.SizeOf(), Allocator.Persistent)) + { + // Fill window capacity, next send should then clear everything + stream.Clear(); + stream.Write((int) 100); + ReliableUtility.SetPacket(sendBuffer, 0, stream.GetNativeSlice(0, stream.Length)); + stream.Clear(); + stream.Write((int) 200); + ReliableUtility.SetPacket(sendBuffer, 1, stream.GetNativeSlice(0, stream.Length)); + stream.Clear(); + stream.Write((int) 300); + ReliableUtility.SetPacket(sendBuffer, 2, stream.GetNativeSlice(0, stream.Length)); + + // Set input buffer and send, this will be seqId 3 + stream.Clear(); + stream.Write((int) 9000); + var inboundBuffer = new InboundBufferVec(); + inboundBuffer.buffer1 = stream.GetNativeSlice(0, stream.Length); + inboundBuffer.buffer2 = default; + + bool needsResume = false; + bool needsUpdate = false; + reliablePipeline.Send(pipelineContext, inboundBuffer, ref needsResume, ref needsUpdate); + + // seqId 3 should now be stored in slot 0 + Assert.AreEqual(3, ReliableUtility.GetPacketInformation(sendBuffer, 3)->SequenceId); + + // slots 1 and 2 should be cleared + Assert.AreEqual(-1, ReliableUtility.GetPacketInformation(sendBuffer, 1)->SequenceId); + Assert.AreEqual(-1, ReliableUtility.GetPacketInformation(sendBuffer, 2)->SequenceId); + + Assert.IsFalse(needsResume); + Assert.IsTrue(needsUpdate); + + // Verify ack packet is written correctly + ReliableUtility.PacketHeader header = default; + ReliableUtility.WriteAckPacket(pipelineContext, ref header); + Assert.AreEqual(header.AckedSequenceId, 2); + Assert.AreEqual(header.AckMask, 0xFFFFFFFF); + } + recvBuffer.Dispose(); + sendBuffer.Dispose(); + sharedBuffer.Dispose(); + } + + [Test] + public unsafe void Send_PacketsAreAcked_UpdateAckState() + { + ReliableUtility.Parameters parameters = new ReliableUtility.Parameters + { + WindowSize = 3 + }; + + int processCapacity = ReliableUtility.ProcessCapacityNeeded(parameters); + int sharedCapacity = ReliableUtility.SharedCapacityNeeded(parameters); + NativeArray recvBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sendBuffer = new NativeArray(processCapacity, Allocator.Persistent); + NativeArray sharedBuffer = new NativeArray(sharedCapacity, Allocator.Persistent); + + ReliableUtility.InitializeContext(new NativeSlice(sharedBuffer), new NativeSlice(sendBuffer), new NativeSlice(recvBuffer), parameters); + + var pipelineContext = new NetworkPipelineContext + {internalProcessBuffer = sendBuffer, internalSharedProcessBuffer = sharedBuffer, timestamp = 1000}; + + var sharedContext = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedContext->SentPackets.Sequence = 3; + sharedContext->SentPackets.Acked = 2; + sharedContext->SentPackets.AckMask = 0xFFFFFFFF; + sharedContext->ReceivedPackets.Sequence = 2; + sharedContext->ReceivedPackets.AckMask = 0xFFFFFFFF; + var receiveContext = (ReliableUtility.Context*) recvBuffer.GetUnsafePtr(); + receiveContext->Delivered = 1; + + // Set last send time to something a long time ago so the ack state is sent in Send + var sendContext = (ReliableUtility.Context*) sendBuffer.GetUnsafePtr(); + sendContext->LastSentTime = 500; + sendContext->PreviousTimestamp = 980; // 20 ms ago + + var reliablePipeline = new ReliableSequencedPipelineStage(); + + using (var stream = new DataStreamWriter(4, Allocator.Temp)) + using (pipelineContext.header = new DataStreamWriter(UnsafeUtility.SizeOf(), Allocator.Persistent)) + { + // Fill window capacity, next send should then clear everything + stream.Clear(); + stream.Write((int) 100); + ReliableUtility.SetPacket(sendBuffer, 0, stream.GetNativeSlice(0, stream.Length)); + stream.Clear(); + stream.Write((int) 200); + ReliableUtility.SetPacket(sendBuffer, 1, stream.GetNativeSlice(0, stream.Length)); + stream.Clear(); + stream.Write((int) 300); + ReliableUtility.SetPacket(sendBuffer, 2, stream.GetNativeSlice(0, stream.Length)); + + var inboundBuffer = new InboundBufferVec(); + inboundBuffer.buffer1 = default; + inboundBuffer.buffer2 = default; + + bool needsResume = false; + bool needsUpdate = false; + reliablePipeline.Send(pipelineContext, inboundBuffer, ref needsResume, ref needsUpdate); + + Assert.AreEqual(-1, ReliableUtility.GetPacketInformation(sendBuffer, 0)->SequenceId); + Assert.AreEqual(-1, ReliableUtility.GetPacketInformation(sendBuffer, 1)->SequenceId); + Assert.AreEqual(-1, ReliableUtility.GetPacketInformation(sendBuffer, 2)->SequenceId); + + Assert.IsFalse(needsResume); + Assert.IsTrue(needsUpdate); + } + recvBuffer.Dispose(); + sendBuffer.Dispose(); + sharedBuffer.Dispose(); + } + + unsafe void GeneratePacket(int payload, ushort headerAckedId, uint headerAckMask, ushort headerSeqId, ref NativeArray sendBuffer, out NativeSlice packet) + { + DataStreamWriter inboundStream = new DataStreamWriter(4, Allocator.Temp); + + inboundStream.Write((int) payload); + InboundBufferVec data = default; + data.buffer1 = inboundStream.GetNativeSlice(0, inboundStream.Length); + ReliableUtility.PacketHeader header = new ReliableUtility.PacketHeader() + { + AckedSequenceId = headerAckedId, + AckMask = headerAckMask, + SequenceId = headerSeqId + }; + ReliableUtility.SetHeaderAndPacket(sendBuffer, headerSeqId, header, data, 1000); + + // Extract raw packet from the send buffer so it can be passed directly to receive + var sendCtx = (ReliableUtility.Context*) sendBuffer.GetUnsafePtr(); + var index = headerSeqId % sendCtx->Capacity; + var offset = sendCtx->DataPtrOffset + (index * sendCtx->DataStride); + packet = new NativeSlice(sendBuffer, offset, sendCtx->DataStride); + inboundStream.Dispose(); + } + } + + public class QoSNetworkPipelineTest + { + private LocalNetworkDriver m_ServerDriver; + private LocalNetworkDriver m_ClientDriver; + + [SetUp] + public void IPC_Setup() + { + IPCManager.Instance.Initialize(100); + m_ServerDriver = + new LocalNetworkDriver(new NetworkDataStreamParameter + {size = 0}, + new ReliableUtility.Parameters { WindowSize = 32}); + m_ServerDriver.Bind(IPCManager.Instance.CreateEndPoint()); + m_ServerDriver.Listen(); + m_ClientDriver = + new LocalNetworkDriver(new NetworkDataStreamParameter + {size = 0}, + new ReliableUtility.Parameters { WindowSize = 32}, + new SimulatorUtility.Parameters { MaxPacketCount = 30, MaxPacketSize = 16, PacketDelayMs = 0, /*PacketDropInterval = 8,*/ PacketDropPercentage = 10}); + } + + [TearDown] + public void IPC_TearDown() + { + m_ClientDriver.Dispose(); + m_ServerDriver.Dispose(); + IPCManager.Instance.Destroy(); + } + + [Test] + public void NetworkPipeline_ReliableSequenced_SendRecvOnce() + { + var clientPipe = m_ClientDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage)); + Assert.AreEqual(clientPipe, serverPipe); + + // 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); + + // Send message to client + var strm = new DataStreamWriter(4, Allocator.Temp); + strm.Write((int) 42); + m_ServerDriver.Send(serverPipe, serverToClient, 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(4, readStrm.Length); + var readCtx = default(DataStreamReader.Context); + Assert.AreEqual(42, readStrm.ReadInt(ref readCtx)); + } + + [Test] + public unsafe void NetworkPipeline_ReliableSequenced_SendRecvWithRTTCalculation() + { + var clientPipe = m_ClientDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage)); + var clientToServer = m_ClientDriver.Connect(m_ServerDriver.LocalEndPoint()); + m_ClientDriver.ScheduleUpdate().Complete(); + m_ServerDriver.ScheduleUpdate().Complete(); + var serverToClient = m_ServerDriver.Accept(); + + NativeSlice serverReceiveBuffer = default; + NativeSlice serverSendBuffer = default; + NativeSlice serverSharedBuffer = default; + m_ServerDriver.GetPipelineBuffers(serverPipe, 4, serverToClient, ref serverReceiveBuffer, ref serverSendBuffer, ref serverSharedBuffer); + var sharedContext = (ReliableUtility.SharedContext*) serverSharedBuffer.GetUnsafePtr(); + + NativeSlice clientReceiveBuffer = default; + NativeSlice clientSendBuffer = default; + NativeSlice clientSharedBuffer = default; + m_ClientDriver.GetPipelineBuffers(clientPipe, 4, clientToServer, ref clientReceiveBuffer, ref clientSendBuffer, ref clientSharedBuffer); + + // First the server sends a packet to the client + var strm = new DataStreamWriter(4, Allocator.Temp); + strm.Write((int) 42); + m_ServerDriver.Send(serverPipe, serverToClient, strm); + m_ServerDriver.ScheduleUpdate().Complete(); + + // Server sent time for the packet with seqId=0 is set + m_ServerDriver.GetPipelineBuffers(serverPipe, 4, serverToClient, ref serverReceiveBuffer, ref serverSendBuffer, ref serverSharedBuffer); + var serverPacketTimer = ReliableUtility.GetLocalPacketTimer(serverSharedBuffer, 0); + Assert.IsTrue(serverPacketTimer->SentTime > 0); + + m_ClientDriver.ScheduleUpdate().Complete(); + + // Client received seqId=0 from server and sets the receive time + m_ClientDriver.GetPipelineBuffers(clientPipe, 4, clientToServer, ref clientReceiveBuffer, ref clientSendBuffer, ref clientSharedBuffer); + var clientPacketTimer = ReliableUtility.GetRemotePacketTimer(clientSharedBuffer, 0); + Assert.IsTrue(clientPacketTimer->ReceiveTime >= serverPacketTimer->SentTime); + + DataStreamReader readStrm; + Assert.AreEqual(NetworkEvent.Type.Connect, clientToServer.PopEvent(m_ClientDriver, out readStrm)); + Assert.AreEqual(NetworkEvent.Type.Data, clientToServer.PopEvent(m_ClientDriver, out readStrm)); + + // Force processing time to be at least 20 ms, + var timer = new Timer(); + while (timer.ElapsedMilliseconds < 20) { } + // Now update client, if it's updated in the while loop it will automatically send ack packets to the server + // so processing time will actually be recorded as almost 0 + m_ClientDriver.ScheduleUpdate().Complete(); + + // Now client sends packet to the server, this should contain the ackedSeqId=0 for the servers initial packet + strm.Clear(); + strm.Write((int) 9000); + m_ClientDriver.Send(clientPipe, clientToServer, strm); + m_ClientDriver.ScheduleUpdate().Complete(); + + // Receive time for the server packet is 0 at this point + Assert.AreEqual(serverPacketTimer->ReceiveTime, 0); + + // Packet is now processed, receive+processing time recorded + m_ServerDriver.ScheduleUpdate().Complete(); + + // Server has now received a packet from the client with ackedSeqId=0 in the header and timing info for that + Assert.IsTrue(serverPacketTimer->ReceiveTime >= clientPacketTimer->ReceiveTime); + Assert.IsTrue(serverPacketTimer->ProcessingTime >= 20); + } + + [Test] + public void NetworkPipeline_ReliableSequenced_SendRecvMany() + { + var clientPipe = m_ClientDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage)); + Assert.AreEqual(clientPipe, serverPipe); + + // 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 i = 0; i < 30; ++i) + { + // Send message to client + var strm = new DataStreamWriter(4, Allocator.Temp); + strm.Write((int) i); + m_ServerDriver.Send(serverPipe, serverToClient, strm); + m_ServerDriver.ScheduleUpdate().Complete(); + + // Receive incoming message from server + m_ClientDriver.ScheduleUpdate().Complete(); + + var readCtx = default(DataStreamReader.Context); + var result = clientToServer.PopEvent(m_ClientDriver, out readStrm); + + Assert.AreEqual(NetworkEvent.Type.Data, result); + Assert.AreEqual(4, readStrm.Length); + Assert.AreEqual(i, readStrm.ReadInt(ref readCtx)); + + // Send back a message to server + strm.Clear(); + strm.Write((int) i*100); + m_ClientDriver.Send(clientPipe, clientToServer, strm); + m_ClientDriver.ScheduleUpdate().Complete(); + + // Receive incoming message from client + var timer = new Timer(); + while (true) + { + m_ServerDriver.ScheduleUpdate().Complete(); + readCtx = default(DataStreamReader.Context); + result = serverToClient.PopEvent(m_ServerDriver, out readStrm); + if (result != NetworkEvent.Type.Empty) + break; + if (timer.ElapsedMilliseconds > 1000) + break; + } + Assert.AreEqual(NetworkEvent.Type.Data, result); + Assert.AreEqual(4, readStrm.Length); + Assert.AreEqual(i*100, readStrm.ReadInt(ref readCtx)); + strm.Dispose(); + } + } + + [Test] + public unsafe void NetworkPipeline_ReliableSequenced_SendRecvManyWithPacketDropHighSeqId() + { + var clientPipe = m_ClientDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage), typeof(SimulatorPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage)); + Assert.AreEqual(clientPipe, serverPipe); + + // Connect to server + var clientToServer = m_ClientDriver.Connect(m_ServerDriver.LocalEndPoint()); + Assert.AreNotEqual(default(NetworkConnection), clientToServer); + m_ClientDriver.ScheduleUpdate().Complete(); + + // Set sequence ID to a value just below wrapping over 0, also need to set last received seqId value to one + // less or the first packet will be considered out of order and stored for later use + NativeSlice receiveBuffer = default; + NativeSlice sendBuffer = default; + NativeSlice sharedBuffer = default; + m_ClientDriver.GetPipelineBuffers(typeof(ReliableSequencedPipelineStage), clientToServer, ref receiveBuffer, ref sendBuffer, ref sharedBuffer); + var sharedContext = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedContext->SentPackets.Sequence = ushort.MaxValue - 1; + sharedContext->SentPackets.Acked = ushort.MaxValue - 2; + sharedContext->SentPackets.AckMask = 0xFFFFFFFF; + sharedContext->ReceivedPackets.Sequence = sharedContext->SentPackets.Acked; + sharedContext->ReceivedPackets.AckMask = sharedContext->SentPackets.AckMask; + var receiveContext = (ReliableUtility.Context*) receiveBuffer.GetUnsafePtr(); + receiveContext->Delivered = sharedContext->SentPackets.Acked; + + // Handle incoming connection from client + m_ServerDriver.ScheduleUpdate().Complete(); + var serverToClient = m_ServerDriver.Accept(); + Assert.AreNotEqual(default(NetworkConnection), serverToClient); + + // This test runs fast so the minimum resend times needs to be lower (assumes 1 ms update rate) + ReliableUtility.SetMinimumResendTime(4, m_ClientDriver, clientPipe, 4, clientToServer); + ReliableUtility.SetMinimumResendTime(4, m_ServerDriver, serverPipe, 4, serverToClient); + + m_ServerDriver.GetPipelineBuffers(typeof(ReliableSequencedPipelineStage), serverToClient, ref receiveBuffer, ref sendBuffer, ref sharedBuffer); + sharedContext = (ReliableUtility.SharedContext*) sharedBuffer.GetUnsafePtr(); + sharedContext->SentPackets.Sequence = ushort.MaxValue - 1; + sharedContext->SentPackets.Acked = ushort.MaxValue - 2; + sharedContext->SentPackets.AckMask = 0xFFFFFFFF; + sharedContext->ReceivedPackets.Sequence = sharedContext->SentPackets.Acked; + sharedContext->ReceivedPackets.AckMask = sharedContext->SentPackets.AckMask; + receiveContext = (ReliableUtility.Context*) receiveBuffer.GetUnsafePtr(); + receiveContext->Delivered = sharedContext->SentPackets.Acked; + + // Receive incoming message from server + m_ClientDriver.ScheduleUpdate().Complete(); + + SendAndReceiveMessages(clientToServer, serverToClient, clientPipe, serverPipe); + } + + [Test] + public void NetworkPipeline_ReliableSequenced_SendRecvManyWithPacketDrop() + { + var clientPipe = m_ClientDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage), typeof(SimulatorPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage)); + Assert.AreEqual(clientPipe, serverPipe); + + // 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); + + // This test runs fast so the minimum resend times needs to be lower (assumes 1 ms update rate) + ReliableUtility.SetMinimumResendTime(4, m_ClientDriver, clientPipe, 4, clientToServer); + ReliableUtility.SetMinimumResendTime(4, m_ServerDriver, serverPipe, 4, serverToClient); + + // Receive incoming message from server + m_ClientDriver.ScheduleUpdate().Complete(); + + SendAndReceiveMessages(clientToServer, serverToClient, clientPipe, serverPipe); + } + + unsafe void SendAndReceiveMessages(NetworkConnection clientToServer, NetworkConnection serverToClient, NetworkPipeline clientPipe, NetworkPipeline serverPipe) + { + DataStreamReader readStrm; + + Assert.AreEqual(NetworkEvent.Type.Connect, clientToServer.PopEvent(m_ClientDriver, out readStrm)); + // Next packet should be Empty and not Data as the packet was dropped + Assert.AreEqual(NetworkEvent.Type.Empty, clientToServer.PopEvent(m_ClientDriver, out readStrm)); + + var totalMessageCount = 100; + var sendMessageCount = 0; + var lastClientReceivedNumber = 0; + var lastServerReceivedNumber = 0; + var timer = new Timer(); + NativeSlice tmpReceiveBuffer = default; + NativeSlice tmpSendBuffer = default; + NativeSlice serverReliableBuffer = default; + NativeSlice clientReliableBuffer = default; + NativeSlice clientSimulatorBuffer = default; + m_ServerDriver.GetPipelineBuffers(typeof(ReliableSequencedPipelineStage), serverToClient, ref tmpReceiveBuffer, ref tmpSendBuffer, ref serverReliableBuffer); + var serverReliableCtx = (ReliableUtility.SharedContext*) serverReliableBuffer.GetUnsafePtr(); + m_ClientDriver.GetPipelineBuffers(typeof(ReliableSequencedPipelineStage), clientToServer, ref tmpReceiveBuffer, ref tmpSendBuffer, ref clientReliableBuffer); + var clientReliableCtx = (ReliableUtility.SharedContext*) clientReliableBuffer.GetUnsafePtr(); + m_ClientDriver.GetPipelineBuffers(typeof(SimulatorPipelineStage), clientToServer, ref tmpReceiveBuffer, ref tmpSendBuffer, ref clientSimulatorBuffer); + var clientSimulatorCtx = (SimulatorUtility.Context*) clientSimulatorBuffer.GetUnsafePtr(); + // Client is the one dropping packets, so wait for that count to reach total, server receive count will be higher + while (lastClientReceivedNumber < totalMessageCount) + { + // Send message to client + sendMessageCount++; + var strm = new DataStreamWriter(4, Allocator.Temp); + strm.Write((int) sendMessageCount); + m_ServerDriver.Send(serverPipe, serverToClient, strm); + if (serverReliableCtx->errorCode != 0) + { + UnityEngine.Debug.Log("Reliability stats\nPacketsDropped: " + serverReliableCtx->stats.PacketsDropped + "\n" + + "PacketsDuplicated: " + serverReliableCtx->stats.PacketsDuplicated + "\n" + + "PacketsOutOfOrder: " + serverReliableCtx->stats.PacketsOutOfOrder + "\n" + + "PacketsReceived: " + serverReliableCtx->stats.PacketsReceived + "\n" + + "PacketsResent: " + serverReliableCtx->stats.PacketsResent + "\n" + + "PacketsSent: " + serverReliableCtx->stats.PacketsSent + "\n" + + "PacketsStale: " + serverReliableCtx->stats.PacketsStale + "\n"); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, serverReliableCtx->errorCode); + } + m_ServerDriver.ScheduleUpdate().Complete(); + + var readCtx = default(DataStreamReader.Context); + NetworkEvent.Type result; + // Receive incoming message from server, might be empty but we still need to keep + // sending or else a resend for a dropped packet will not happen + m_ClientDriver.ScheduleUpdate().Complete(); + readCtx = default(DataStreamReader.Context); + result = clientToServer.PopEvent(m_ClientDriver, out readStrm); + Assert.AreEqual(m_ClientDriver.ReceiveErrorCode, 0); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, clientReliableCtx->errorCode); + while (result != NetworkEvent.Type.Empty) + { + Assert.AreEqual(4, readStrm.Length); + var read = readStrm.ReadInt(ref readCtx); + // We should be receiving in order, so last payload should be one more than the current receive count + Assert.AreEqual(lastClientReceivedNumber + 1, read); + lastClientReceivedNumber = read; + // Pop all events which might be pending (in case of dropped packet it should contain all the other packets already up to latest) + readCtx = default(DataStreamReader.Context); + result = clientToServer.PopEvent(m_ClientDriver, out readStrm); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, clientReliableCtx->errorCode); + } + + // Send back a message to server + strm.Clear(); + strm.Write((int) sendMessageCount * 100); + m_ClientDriver.Send(clientPipe, clientToServer, strm); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, clientReliableCtx->errorCode); + m_ClientDriver.ScheduleUpdate().Complete(); + + // Receive incoming message from client + m_ServerDriver.ScheduleUpdate().Complete(); + readCtx = default(DataStreamReader.Context); + result = serverToClient.PopEvent(m_ServerDriver, out readStrm); + Assert.AreEqual(m_ServerDriver.ReceiveErrorCode, 0); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, serverReliableCtx->errorCode); + while (result != NetworkEvent.Type.Empty) + { + Assert.AreEqual(4, readStrm.Length); + var read = readStrm.ReadInt(ref readCtx); + Assert.AreEqual(lastServerReceivedNumber + 100, read); + lastServerReceivedNumber = read; + readCtx = default(DataStreamReader.Context); + result = clientToServer.PopEvent(m_ClientDriver, out readStrm); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, serverReliableCtx->errorCode); + } + + //Assert.AreEqual(0, serverReliableCtx->stats.PacketsDuplicated); + Assert.AreEqual(0, serverReliableCtx->stats.PacketsStale); + //Assert.AreEqual(0, clientReliableCtx->stats.PacketsDuplicated); + Assert.AreEqual(0, clientReliableCtx->stats.PacketsStale); + + if (timer.ElapsedMilliseconds > 1000) + Assert.Fail("Test timeout, didn't receive all messages (" + totalMessageCount + ")"); + + strm.Dispose(); + } + + var stats = serverReliableCtx->stats; + // You can get legtimate duplicated packets in the test, if the ack was just not received in time for the resend timer expired + //Assert.AreEqual(stats.PacketsResent, clientSimulatorCtx->PacketDropCount); + //Assert.AreEqual(stats.PacketsDuplicated, 0); + Assert.AreEqual(stats.PacketsStale, 0); + UnityEngine.Debug.Log("Server Reliability stats\nPacketsDropped: " + serverReliableCtx->stats.PacketsDropped + "\n" + + "PacketsDuplicated: " + serverReliableCtx->stats.PacketsDuplicated + "\n" + + "PacketsOutOfOrder: " + serverReliableCtx->stats.PacketsOutOfOrder + "\n" + + "PacketsReceived: " + serverReliableCtx->stats.PacketsReceived + "\n" + + "PacketsResent: " + serverReliableCtx->stats.PacketsResent + "\n" + + "PacketsSent: " + serverReliableCtx->stats.PacketsSent + "\n" + + "PacketsStale: " + serverReliableCtx->stats.PacketsStale + "\n"); + UnityEngine.Debug.Log("Client Reliability stats\nPacketsDropped: " + clientReliableCtx->stats.PacketsDropped + "\n" + + "PacketsDuplicated: " + clientReliableCtx->stats.PacketsDuplicated + "\n" + + "PacketsOutOfOrder: " + clientReliableCtx->stats.PacketsOutOfOrder + "\n" + + "PacketsReceived: " + clientReliableCtx->stats.PacketsReceived + "\n" + + "PacketsResent: " + clientReliableCtx->stats.PacketsResent + "\n" + + "PacketsSent: " + clientReliableCtx->stats.PacketsSent + "\n" + + "PacketsStale: " + clientReliableCtx->stats.PacketsStale + "\n"); + UnityEngine.Debug.Log("Client Simulator stats\n" + + "PacketDropCount: " + clientSimulatorCtx->PacketDropCount + "\n" + + "PacketCount: " + clientSimulatorCtx->PacketCount); + } + + [Test] + public void NetworkPipeline_UnreliableSequenced_SendRecvOnce() + { + var clientPipe = m_ClientDriver.CreatePipeline(typeof(UnreliableSequencedPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(UnreliableSequencedPipelineStage)); + Assert.AreEqual(clientPipe, serverPipe); + + // 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); + + // Send message to client + var strm = new DataStreamWriter(4, Allocator.Temp); + strm.Write((int) 42); + m_ServerDriver.Send(serverPipe, serverToClient, 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(4, readStrm.Length); + var readCtx = default(DataStreamReader.Context); + Assert.AreEqual(42, readStrm.ReadInt(ref readCtx)); + } + + [Test] + public unsafe void NetworkPipeline_ReliableSequenced_ClientSendsNothing() + { + var clientPipe = m_ClientDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage)); + Assert.AreEqual(clientPipe, serverPipe); + + // 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); + + // Receive incoming message from server + m_ClientDriver.ScheduleUpdate().Complete(); + DataStreamReader readStrm; + Assert.AreEqual(NetworkEvent.Type.Connect, clientToServer.PopEvent(m_ClientDriver, out readStrm)); + + // Do a loop where server sends to client but client sends nothing back, it should send empty ack packets back + // so the servers queue will not get full + var totalMessageCount = 100; + var sendMessageCount = 0; + var lastClientReceivedNumber = 0; + var timer = new Timer(); + NativeSlice tmpReceiveBuffer = default; + NativeSlice tmpSendBuffer = default; + NativeSlice serverReliableBuffer = default; + NativeSlice clientReliableBuffer = default; + + m_ServerDriver.GetPipelineBuffers(typeof(ReliableSequencedPipelineStage), serverToClient, ref tmpReceiveBuffer, ref tmpSendBuffer, ref serverReliableBuffer); + var serverReliableCtx = (ReliableUtility.SharedContext*) serverReliableBuffer.GetUnsafePtr(); + m_ClientDriver.GetPipelineBuffers(typeof(ReliableSequencedPipelineStage), clientToServer, ref tmpReceiveBuffer, ref tmpSendBuffer, ref clientReliableBuffer); + var clientReliableCtx = (ReliableUtility.SharedContext*) clientReliableBuffer.GetUnsafePtr(); + + // Finish when client has received all messages from server without errors + while (lastClientReceivedNumber < totalMessageCount) + { + // Send message to client + sendMessageCount++; + var strm = new DataStreamWriter(4, Allocator.Temp); + strm.Write((int) sendMessageCount); + m_ServerDriver.Send(serverPipe, serverToClient, strm); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, serverReliableCtx->errorCode); + m_ServerDriver.ScheduleUpdate().Complete(); + + var readCtx = default(DataStreamReader.Context); + NetworkEvent.Type result; + // Receive incoming message from server, might be empty or might be more than one message + m_ClientDriver.ScheduleUpdate().Complete(); + readCtx = default(DataStreamReader.Context); + result = clientToServer.PopEvent(m_ClientDriver, out readStrm); + Assert.AreEqual(m_ClientDriver.ReceiveErrorCode, 0); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, clientReliableCtx->errorCode); + while (result != NetworkEvent.Type.Empty) + { + Assert.AreEqual(4, readStrm.Length); + var read = readStrm.ReadInt(ref readCtx); + // We should be receiving in order, so last payload should be one more than the current receive count + Assert.AreEqual(lastClientReceivedNumber + 1, read); + lastClientReceivedNumber = read; + // Pop all events which might be pending (in case of dropped packet it should contain all the other packets already up to latest) + readCtx = default(DataStreamReader.Context); + result = clientToServer.PopEvent(m_ClientDriver, out readStrm); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, clientReliableCtx->errorCode); + } + + // no-op + m_ClientDriver.ScheduleUpdate().Complete(); + + // Make sure no event has arrived on server and no errors seen + m_ServerDriver.ScheduleUpdate().Complete(); + readCtx = default(DataStreamReader.Context); + Assert.AreEqual(serverToClient.PopEvent(m_ServerDriver, out readStrm), NetworkEvent.Type.Empty); + Assert.AreEqual(m_ServerDriver.ReceiveErrorCode, 0); + Assert.AreEqual((ReliableUtility.ErrorCodes)0, serverReliableCtx->errorCode); + + if (timer.ElapsedMilliseconds > 1000) + Assert.Fail("Test timeout, didn't receive all messages (" + totalMessageCount + ")"); + + strm.Dispose(); + } + + // The empty ack packets will bump the PacketsSent count, also in this test it can happen that a duplicate + // packet is sent because the timers are tight + //Assert.AreEqual(totalMessageCount, serverReliableCtx->stats.PacketsSent); + } + + [Test] + public unsafe void NetworkPipeline_ReliableSequenced_NothingIsSentAfterPingPong() + { + // Use simulator pipeline here just to count packets, need to reset the drivers for this setup + m_ServerDriver.Dispose(); + m_ClientDriver.Dispose(); + m_ServerDriver = + new LocalNetworkDriver(new NetworkDataStreamParameter + {size = 0}, + new ReliableUtility.Parameters { WindowSize = 32}, + new SimulatorUtility.Parameters { MaxPacketCount = 30, MaxPacketSize = 16, PacketDelayMs = 0, PacketDropPercentage = 0}); + m_ServerDriver.Bind(IPCManager.Instance.CreateEndPoint()); + m_ServerDriver.Listen(); + m_ClientDriver = + new LocalNetworkDriver(new NetworkDataStreamParameter + {size = 0}, + new ReliableUtility.Parameters { WindowSize = 32}, + new SimulatorUtility.Parameters { MaxPacketCount = 30, MaxPacketSize = 16, PacketDelayMs = 0, PacketDropPercentage = 0}); + + var clientPipe = m_ClientDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage), typeof(SimulatorPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage), typeof(SimulatorPipelineStage)); + var clientToServer = m_ClientDriver.Connect(m_ServerDriver.LocalEndPoint()); + m_ClientDriver.ScheduleUpdate().Complete(); + m_ServerDriver.ScheduleUpdate().Complete(); + var serverToClient = m_ServerDriver.Accept(); + + m_ClientDriver.ScheduleUpdate().Complete(); + DataStreamReader readStrm; + Assert.AreEqual(NetworkEvent.Type.Connect, clientToServer.PopEvent(m_ClientDriver, out readStrm)); + + // Perform ping pong transmision + var strm = new DataStreamWriter(4, Allocator.Temp); + strm.Write((int) 100); + Console.WriteLine("Server send"); + m_ServerDriver.Send(serverPipe, serverToClient, strm); + m_ServerDriver.ScheduleUpdate().Complete(); + Console.WriteLine("Client update"); + m_ClientDriver.ScheduleUpdate().Complete(); + Assert.AreEqual(NetworkEvent.Type.Data, clientToServer.PopEvent(m_ClientDriver, out readStrm)); + strm.Clear(); + strm.Write((int) 200); + Console.WriteLine("Client send"); + m_ClientDriver.Send(clientPipe, clientToServer, strm); + m_ClientDriver.ScheduleUpdate().Complete(); + Console.WriteLine("Server update"); + m_ServerDriver.ScheduleUpdate().Complete(); + Assert.AreEqual(NetworkEvent.Type.Data, serverToClient.PopEvent(m_ServerDriver, out readStrm)); + + // Check how many packets have been sent so far + NativeSlice tmpReceiveBuffer = default; + NativeSlice tmpSendBuffer = default; + NativeSlice simulatorBuffer = default; + m_ClientDriver.GetPipelineBuffers(typeof(SimulatorPipelineStage), clientToServer, ref tmpReceiveBuffer, ref tmpSendBuffer, ref simulatorBuffer); + var simulatorCtx = (SimulatorUtility.Context*) simulatorBuffer.GetUnsafePtr(); + + // Do a loop and make sure nothing is being sent between client and server + var timer = new Timer(); + while (timer.ElapsedMilliseconds < 1000) + { + m_ServerDriver.ScheduleUpdate().Complete(); + m_ClientDriver.ScheduleUpdate().Complete(); + } + + // The client simulator counts all packets which pass through the pipeline so will catch anything the + // reliability pipeline might send, only 2 packets (data + ack packet) should have been received on client + Assert.AreEqual(2, simulatorCtx->PacketCount); + + // Check server side as well, server only has one packet as the client included it's ack in the pong packet it sent + m_ServerDriver.GetPipelineBuffers(typeof(SimulatorPipelineStage), clientToServer, ref tmpReceiveBuffer, ref tmpSendBuffer, ref simulatorBuffer); + simulatorCtx = (SimulatorUtility.Context*) simulatorBuffer.GetUnsafePtr(); + Assert.AreEqual(1, simulatorCtx->PacketCount); + } + + [Test] + public unsafe void NetworkPipeline_ReliableSequenced_IdleAfterPacketDrop() + { + // Use simulator drop interval, then first packet will be dropped + m_ClientDriver.Dispose(); + m_ClientDriver = + new LocalNetworkDriver(new NetworkDataStreamParameter + {size = 0}, + new ReliableUtility.Parameters { WindowSize = 32}, + new SimulatorUtility.Parameters { MaxPacketCount = 30, MaxPacketSize = 16, PacketDelayMs = 0, PacketDropInterval = 10}); + + m_ClientDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage), typeof(SimulatorPipelineStage)); + var serverPipe = m_ServerDriver.CreatePipeline(typeof(ReliableSequencedPipelineStage), typeof(SimulatorPipelineStage)); + var clientToServer = m_ClientDriver.Connect(m_ServerDriver.LocalEndPoint()); + m_ClientDriver.ScheduleUpdate().Complete(); + m_ServerDriver.ScheduleUpdate().Complete(); + var serverToClient = m_ServerDriver.Accept(); + + m_ClientDriver.ScheduleUpdate().Complete(); + DataStreamReader readStrm; + Assert.AreEqual(NetworkEvent.Type.Connect, clientToServer.PopEvent(m_ClientDriver, out readStrm)); + + // Server sends one packet, this will be dropped, client has empty event + var strm = new DataStreamWriter(4, Allocator.Temp); + strm.Write((int) 100); + m_ServerDriver.Send(serverPipe, serverToClient, strm); + m_ServerDriver.ScheduleUpdate().Complete(); + m_ClientDriver.ScheduleUpdate().Complete(); + Assert.AreEqual(NetworkEvent.Type.Empty, clientToServer.PopEvent(m_ClientDriver, out readStrm)); + + // Wait until client receives the server packet resend + var timer = new Timer(); + var clientEvent = NetworkEvent.Type.Empty; + while (timer.ElapsedMilliseconds < 1000) + { + m_ClientDriver.ScheduleUpdate().Complete(); + m_ServerDriver.ScheduleUpdate().Complete(); + clientEvent = clientToServer.PopEvent(m_ClientDriver, out readStrm); + if (clientEvent != NetworkEvent.Type.Empty) + break; + } + Assert.AreEqual(NetworkEvent.Type.Data, clientEvent); + + // Verify exactly one packet has been dropped + NativeSlice tmpReceiveBuffer = default; + NativeSlice tmpSendBuffer = default; + NativeSlice simulatorBuffer = default; + m_ClientDriver.GetPipelineBuffers(typeof(SimulatorPipelineStage), clientToServer, ref tmpReceiveBuffer, ref tmpSendBuffer, ref simulatorBuffer); + var simulatorCtx = (SimulatorUtility.Context*) simulatorBuffer.GetUnsafePtr(); + Assert.AreEqual(simulatorCtx->PacketDropCount, 1); + } + + } +} diff --git a/Tests/Editor/ReliablePipelineTests.cs.meta b/Tests/Editor/ReliablePipelineTests.cs.meta new file mode 100644 index 0000000..b02e033 --- /dev/null +++ b/Tests/Editor/ReliablePipelineTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a957151bc97f94967b3f7ed66cdc7b71 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/Unity.Networking.Transport.EditorTests.asmdef b/Tests/Editor/Unity.Networking.Transport.EditorTests.asmdef new file mode 100644 index 0000000..bf2cf98 --- /dev/null +++ b/Tests/Editor/Unity.Networking.Transport.EditorTests.asmdef @@ -0,0 +1,17 @@ +{ + "name": "Unity.Networking.Transport.EditorTests", + "references": [ + "Unity.Burst", + "Unity.Collections", + "Unity.Mathematics", + "Unity.Networking.Transport" + ], + "optionalUnityReferences": [ + "TestAssemblies" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": true +} diff --git a/Tests/Editor/Unity.Networking.Transport.EditorTests.asmdef.meta b/Tests/Editor/Unity.Networking.Transport.EditorTests.asmdef.meta new file mode 100644 index 0000000..6a1adac --- /dev/null +++ b/Tests/Editor/Unity.Networking.Transport.EditorTests.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 28209ba5cfb3c804291cf373a2a4d034 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Editor/UtilitiesTests.cs b/Tests/Editor/UtilitiesTests.cs new file mode 100644 index 0000000..848e05d --- /dev/null +++ b/Tests/Editor/UtilitiesTests.cs @@ -0,0 +1,51 @@ +using System; +using NUnit.Framework; +using Unity.Networking.Transport.Utilities; + +namespace Unity.Networking.Transport.Tests +{ + public class NativeMultiQueue_Tests + { + [SetUp] + public void Setup() + { + } + + [TearDown] + public void TearDown() + { + } + + [Test] + public void NativeMultiQueue_SimpleScenarios() + { + using (NativeMultiQueue eventQ = new NativeMultiQueue(5)) + { + for (int connection = 0; connection < 5; connection++) + { + // Test Add + int item = 0; + + eventQ.Enqueue(connection, 1); + eventQ.Enqueue(connection, 1); + eventQ.Enqueue(connection, 1); + eventQ.Enqueue(connection, 1); + eventQ.Enqueue(connection, 1); + + // Add grows capacity + eventQ.Enqueue(connection, 1); + + // Test Rem + Assert.True(eventQ.Dequeue(connection, out item)); + Assert.True(eventQ.Dequeue(connection, out item)); + Assert.True(eventQ.Dequeue(connection, out item)); + Assert.True(eventQ.Dequeue(connection, out item)); + Assert.True(eventQ.Dequeue(connection, out item)); + + // Remove with grown capacity + Assert.True(eventQ.Dequeue(connection, out item)); + } + } + } + } +} \ No newline at end of file diff --git a/Tests/Editor/UtilitiesTests.cs.meta b/Tests/Editor/UtilitiesTests.cs.meta new file mode 100644 index 0000000..334b698 --- /dev/null +++ b/Tests/Editor/UtilitiesTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 22ba6cf875ab6cf4f974a7acd99ef2a1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Runtime.meta b/Tests/Runtime.meta new file mode 100644 index 0000000..295cacf --- /dev/null +++ b/Tests/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7c2097333eb179342b536f3596f09f60 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Runtime/ServerAndClientTests.cs b/Tests/Runtime/ServerAndClientTests.cs new file mode 100644 index 0000000..f429a6f --- /dev/null +++ b/Tests/Runtime/ServerAndClientTests.cs @@ -0,0 +1,331 @@ +using System.Collections; +using Unity.Collections; +using NUnit.Framework; +using System; +using UnityEngine.TestTools; +using UnityEngine; +using Unity.Networking.Transport; + +namespace Tests +{ + public class ServerAndClientTests + { + UdpNetworkDriver server_driver; + NetworkConnection connectionToClient; + + UdpNetworkDriver client_driver; + NetworkConnection clientToServerConnection; + + NetworkEvent.Type ev; + DataStreamReader stream; + + public void SetupServerAndClientAndConnectThem(int bufferSize) + { + //setup server + server_driver = new UdpNetworkDriver(new NetworkDataStreamParameter { size = bufferSize }); + NetworkEndPoint server_endpoint = NetworkEndPoint.LoopbackIpv4; + server_endpoint.Port = 1337; + server_driver.Bind(server_endpoint); + server_driver.Listen(); + + //setup client + client_driver = new UdpNetworkDriver(new NetworkDataStreamParameter { size = bufferSize }); + clientToServerConnection = client_driver.Connect(server_endpoint); + + //update drivers + client_driver.ScheduleUpdate().Complete(); + server_driver.ScheduleUpdate().Complete(); + + //accept connection + connectionToClient = server_driver.Accept(); + + server_driver.ScheduleUpdate().Complete(); + ev = server_driver.PopEventForConnection(connectionToClient, out stream); + Assert.IsTrue(ev == NetworkEvent.Type.Empty, "Not empty NetworkEvent on the server appeared"); + + client_driver.ScheduleUpdate().Complete(); + ev = clientToServerConnection.PopEvent(client_driver, out stream); + Assert.IsTrue(ev == NetworkEvent.Type.Connect, "NetworkEvent should have Type.Connect on the client"); + } + + public void DisconnectAndCleanup() + { + clientToServerConnection.Close(client_driver); + + //update drivers + client_driver.ScheduleUpdate().Complete(); + server_driver.ScheduleUpdate().Complete(); + + ev = server_driver.PopEventForConnection(connectionToClient, out stream); + Assert.IsTrue(ev == NetworkEvent.Type.Disconnect, "NetworkEvent.Type.Disconnect was expected to appear, but " + ev + "appeared"); + + server_driver.Dispose(); + client_driver.Dispose(); + } + + [UnityTest] + public IEnumerator ServerAndClient_Connect_Successfully() + { + SetupServerAndClientAndConnectThem(0); + DisconnectAndCleanup(); + yield return null; + } + + [UnityTest] + public IEnumerator ServerAnd5Clients_Connect_Successfully() + { + int numberOfClients = 5; + NativeArray connectionToClientArray; + UdpNetworkDriver[] client_driversArray = new UdpNetworkDriver[numberOfClients]; + NativeArray clientToServerConnectionsArray; + + //setup server + connectionToClientArray = new NativeArray(numberOfClients, Allocator.Persistent); + server_driver = new UdpNetworkDriver(new NetworkDataStreamParameter { size = 0 }); + NetworkEndPoint server_endpoint = NetworkEndPoint.LoopbackIpv4; + server_endpoint.Port = 1337; + server_driver.Bind(server_endpoint); + server_driver.Listen(); + + //setup clients + clientToServerConnectionsArray = new NativeArray(numberOfClients, Allocator.Persistent); + + for (int i = 0; i < numberOfClients; i++) + { + client_driversArray[i] = new UdpNetworkDriver(new NetworkDataStreamParameter { size = 0 }); + clientToServerConnectionsArray[i] = client_driversArray[i].Connect(server_endpoint); + } + + //update drivers + for (int i = 0; i < numberOfClients; i++) + client_driversArray[i].ScheduleUpdate().Complete(); + server_driver.ScheduleUpdate().Complete(); + + //accept connections + for (int i = 0; i < numberOfClients; i++) + { + connectionToClientArray[i] = server_driver.Accept(); + + server_driver.ScheduleUpdate().Complete(); + ev = server_driver.PopEventForConnection(connectionToClientArray[i], out stream); + Assert.IsTrue(ev == NetworkEvent.Type.Empty, "Not empty NetworkEvent on the server appeared"); + + client_driversArray[i].ScheduleUpdate().Complete(); + ev = clientToServerConnectionsArray[i].PopEvent(client_driversArray[i], out stream); + Assert.IsTrue(ev == NetworkEvent.Type.Connect, "NetworkEvent should have Type.Connect on the client"); + } + //close connections + for (int i = 0; i < numberOfClients; i++) + { + clientToServerConnectionsArray[i].Close(client_driversArray[i]); + + //update drivers + client_driversArray[i].ScheduleUpdate().Complete(); + server_driver.ScheduleUpdate().Complete(); + + ev = server_driver.PopEventForConnection(connectionToClientArray[i], out stream); + Assert.IsTrue(ev == NetworkEvent.Type.Disconnect, "NetworkEvent.Type.Disconnect was expected to appear, but " + ev + "appeared"); + } + + server_driver.Dispose(); + for (int i = 0; i < numberOfClients; i++) + { + client_driversArray[i].Dispose(); + } + connectionToClientArray.Dispose(); + clientToServerConnectionsArray.Dispose(); + + yield return null; + } + + [UnityTest] + public IEnumerator ServerAndClient_PingPong_Successfully() + { + SetupServerAndClientAndConnectThem(0); + + //send data from client + DataStreamWriter m_OutStream = new DataStreamWriter(16, Allocator.Persistent); + m_OutStream.Clear(); + m_OutStream.Write(SharedConstants.ping); + clientToServerConnection.Send(client_driver, m_OutStream); + + //handle sent data + server_driver.ScheduleUpdate().Complete(); + ev = server_driver.PopEventForConnection(connectionToClient, out stream); + Assert.IsTrue(ev == NetworkEvent.Type.Data, "Expected to get Type.Data"); + var readerCtx = default(DataStreamReader.Context); + var msg = stream.ReadBytesAsArray(ref readerCtx, stream.Length); + if (msg.Length == SharedConstants.ping.Length) + { + for (var i = 0; i < msg.Length; i++) + { + if (SharedConstants.ping[i] != msg[i]) + { + Assert.Fail("Data reading error"); + } + } + } + + client_driver.ScheduleUpdate().Complete(); + + //send data from server + m_OutStream.Clear(); + m_OutStream.Write(SharedConstants.pong); + connectionToClient.Send(server_driver, m_OutStream); + m_OutStream.Dispose(); + + //handle sent data + server_driver.ScheduleUpdate().Complete(); + client_driver.ScheduleUpdate().Complete(); + ev = clientToServerConnection.PopEvent(client_driver, out stream); + Assert.IsTrue(ev == NetworkEvent.Type.Data, "Expected to get Type.Data"); + readerCtx = default(DataStreamReader.Context); + msg = stream.ReadBytesAsArray(ref readerCtx, stream.Length); + if (msg.Length == SharedConstants.pong.Length) + { + for (var i = 0; i < msg.Length; i++) + { + if (SharedConstants.pong[i] != msg[i]) + { + Assert.Fail("Data reading error"); + } + } + } + + DisconnectAndCleanup(); + yield return null; + } + + //test for buffer overflow + [UnityTest, UnityPlatform (RuntimePlatform.LinuxEditor, RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor)] + public IEnumerator ServerAndClient_SendBigMessage_OverflowsIncomingDriverBuffer() + { + SetupServerAndClientAndConnectThem(8); + + //send data from client + DataStreamWriter m_OutStream = new DataStreamWriter(16, Allocator.Persistent); + m_OutStream.Clear(); + m_OutStream.Write(SharedConstants.ping); + clientToServerConnection.Send(client_driver, m_OutStream); + + LogAssert.Expect(LogType.Error, "Error on receive 10040"); + m_OutStream.Dispose(); + + //handle sent data + server_driver.ScheduleUpdate().Complete(); + client_driver.ScheduleUpdate().Complete(); + + Assert.AreEqual(10040, server_driver.ReceiveErrorCode); + + DisconnectAndCleanup(); + yield return null; + } + + [UnityTest] + public IEnumerator ServerAndClient_SendMessageWithMaxLength_SentAndReceivedWithoutErrors() + { + SetupServerAndClientAndConnectThem(0); + + //send data from client + DataStreamWriter m_OutStream = new DataStreamWriter(1500, Allocator.Persistent); + m_OutStream.Clear(); + int messageLength = 1400; + byte[] messageToSend = new byte[messageLength]; + for (int i = 0; i < messageLength; i++) + { + messageToSend[i] = (byte)(33 + (i % 93)); + } + + m_OutStream.Write(messageToSend); + clientToServerConnection.Send(client_driver, m_OutStream); + m_OutStream.Dispose(); + + server_driver.ScheduleUpdate().Complete(); + ev = server_driver.PopEventForConnection(connectionToClient, out stream); + Assert.IsTrue(ev == NetworkEvent.Type.Data, "Expected to get Type.Data"); + var readerCtx = default(DataStreamReader.Context); + var msg = stream.ReadBytesAsArray(ref readerCtx, stream.Length); + Assert.IsTrue(msg.Length == messageLength, "Lenghts of sent and received messages are different"); + + DisconnectAndCleanup(); + yield return null; + } + + [UnityTest, UnityPlatform (RuntimePlatform.LinuxEditor, RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor)] + public IEnumerator ServerAndClient_SendMessageWithMoreThenMaxLength_OverflowsIncomingDriverBuffer() + { + SetupServerAndClientAndConnectThem(0); + + //send data from client + DataStreamWriter m_OutStream = new DataStreamWriter(1500, Allocator.Persistent); + m_OutStream.Clear(); + int messageLength = 1401; + byte[] messageToSend = new byte[messageLength]; + for (int i = 0; i < messageLength; i++) + { + messageToSend[i] = (byte)(33 + (i % 93)); + } + + m_OutStream.Write(messageToSend); + clientToServerConnection.Send(client_driver, m_OutStream); + LogAssert.Expect(LogType.Error, "Error on receive 10040"); + m_OutStream.Dispose(); + + //handle sent data + server_driver.ScheduleUpdate().Complete(); + client_driver.ScheduleUpdate().Complete(); + + Assert.AreEqual(10040, server_driver.ReceiveErrorCode); + + DisconnectAndCleanup(); + yield return null; + } + + [UnityTest, UnityPlatform (RuntimePlatform.LinuxEditor, RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor)] + public IEnumerator ServerAndClient_SendMessageWithoutReadingIt_GivesErrorOnDriverUpdate() + { + SetupServerAndClientAndConnectThem(0); + + //send data from client + DataStreamWriter m_OutStream = new DataStreamWriter(16, Allocator.Persistent); + m_OutStream.Clear(); + m_OutStream.Write(SharedConstants.ping); + clientToServerConnection.Send(client_driver, m_OutStream); + m_OutStream.Dispose(); + + server_driver.ScheduleUpdate().Complete(); + client_driver.ScheduleUpdate().Complete(); + + LogAssert.Expect(LogType.Error, "Resetting event queue with pending events (Count=1, ConnectionID=0) Listening: 1"); + server_driver.ScheduleUpdate().Complete(); + + DisconnectAndCleanup(); + yield return null; + } + } +} + +public class SharedConstants +{ + public static byte[] ping = { + (byte)'f', + (byte)'r', + (byte)'o', + (byte)'m', + (byte)'s', + (byte)'e', + (byte)'r', + (byte)'v', + (byte)'e', + (byte)'r' + }; + + public static byte[] pong = { + (byte)'c', + (byte)'l', + (byte)'i', + (byte)'e', + (byte)'n', + (byte)'t' + }; +} diff --git a/Tests/Runtime/ServerAndClientTests.cs.meta b/Tests/Runtime/ServerAndClientTests.cs.meta new file mode 100644 index 0000000..0886a2d --- /dev/null +++ b/Tests/Runtime/ServerAndClientTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 52ad2adda6b37d345871856ed4a57e3d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Runtime/com.unity.transport.Tests.asmdef b/Tests/Runtime/com.unity.transport.Tests.asmdef new file mode 100644 index 0000000..a323318 --- /dev/null +++ b/Tests/Runtime/com.unity.transport.Tests.asmdef @@ -0,0 +1,12 @@ +{ + "name": "Unity.Networking.Transport.PlayTests", + "references": [ + "Unity.Networking.Transport" + ], + "optionalUnityReferences": [ + "TestAssemblies" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true +} \ No newline at end of file diff --git a/Tests/Runtime/com.unity.transport.Tests.asmdef.meta b/Tests/Runtime/com.unity.transport.Tests.asmdef.meta new file mode 100644 index 0000000..4f000ba --- /dev/null +++ b/Tests/Runtime/com.unity.transport.Tests.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ae57ca33756974c419d9f739035d8ccc +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package.json b/package.json new file mode 100644 index 0000000..ca13e87 --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "com.unity.transport", + "displayName": "Unity Transport", + "version": "0.2.0-preview.4", + "unity": "2019.3", + "unityRelease": "0b11", + "description": "Unity network transport layer - the low-level interface for sending UDP data", + "dependencies": { + "com.unity.burst": "1.2.0-preview.9", + "com.unity.collections": "0.2.0-preview.13", + "com.unity.mathematics": "1.1.0" + }, + "repository": { + "type": "git", + "url": "git@github.com:Unity-Technologies/netcode.git", + "revision": "2a580c3ed0739a86c9e66aea2eca8b80cb8f118a" + } +} diff --git a/package.json.meta b/package.json.meta new file mode 100644 index 0000000..894e526 --- /dev/null +++ b/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 391ba20ad5cd61544945bad267a318cf +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: + /// DataStream (Reader/Writer) unsafe utilities used to do pointer operations on streams. + /// + /// These are added to the DataStreamWriter/DataStreamReader classes as extensions, so + /// you need to add using Unity.Collections.LowLevel.Unsafe at the top + /// of file where you need to access these functions. + /// + /// Since these are unsafe C# operations care must be taken when using them, it can + /// easily crash the editor/player. + /// + /// Every time data is written directly to the data stream buffer you must call + /// WriteBytesWithUnsafePointer afterwards with the length of the data written so + /// that the stream class can internally keep track of how much of the internal + /// buffer has been written to. + /// + /// The functions have read/write access check variants which utilize the job + /// system atomic safety handle. The ENABLE_UNITY_COLLECTIONS_CHECKS define needs + /// to be used for this to work. For more information see + /// Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle. + /// + /// Example of typical usage: + /// + /// // Manually write some numbers into a data stream from a source buffer. + /// var data = new DataStreamWriter(4, Allocator.Temp); + /// unsafe + /// { + /// var ptr = data.GetUnsafePtr(); + /// var sourceData = new NativeArray<byte>(4, Allocator.Temp); + /// sourceData[0] = 42; + /// sourceData[1] = 42; + /// sourceData[2] = 42; + /// sourceData[3] = 42; + /// UnsafeUtility.MemCpy(ptr, sourceData.GetUnsafePtr(), sourceData.Length); + /// data.WriteBytesWithUnsafePointer(sourceData.Length); + /// } + /// + ///

    3awO8ZO65#PzlQj-0{_GQ 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 z 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 z zPK8lc2xGYk(>}M4c>rJ2BAgnm-@zx3Rn7)oe8%%-smU7xOw$eF`8c?oK0#P`9C3y>E_s_ijriJoEl@(OSKvTpLyfYaW<@djyVv-ac+!ufp)-y)-|XQZsWUjSUw)L-(C|BR<&DZ|q< zysYG-vTyXjF7Oy@$09RYM*U@3!~EUiEm~SHwRwP5SSz>Vp}IVi-p#<*JV?(j;82c8 z6Kw}dZ&3GJydvVLjEJv@Bhu}mqERn;*`Pw8Pi zw%9|+U)wC_Y1*c40W>Uoo4hw5ZPiaId!&tNDNQ2hNGFi5X75dir}7fbBfx9&-XgRc z-jg@{58z4fR{&SuQGbyqEF*D@Z)D1Q8*r$PNK+E}D2R{SjqSY5)V10F9!-xrk#P)8 z%6kXW`_*`VC~H6GLKOc9F^A^Ns9OC_!#Sdm-5K%%>6NwwVX;9c?pz!F1PYGoJyD+h!;)Y%_l;;e?Uac(od* z!=IkKB&1H%p7>XwfjUZM|F7}Qc45X%3GZ|GrY>h6rg8oz66bGi9PP*dPQFdw$-aD_{JL~b9yw3yA?Gu?!IIWcT1>jK5-io$Kd3?vyY>T0_Q!d1|UAab= zI22iIH4D>?8?0%sUj)tCUiq%=^k z{~P~&R6ZI1cBifU$l?hN4xYA^9|F#{@;~_1w!%E)X#5Gn`Dh;6RuUH*TB3Qdt&kRN zEAO>!<$Fk{QCkVu2y4-d5xIY6t}fG`Zy39` z_ol9FXGdrIo*bGS>wP=Qe22(@nG2qe@3^+R1L1tgSH@Ak?!>#*X)>3jzR>u@yFlWh zPn6#<%%m8=$iG`9(1ek`iYlrski6j zn`vH!Uq3(KUX5=)75JQSoN*z(RS)idF6YW;co!i|MF?ks;*4V4Y)7LC&Pu1B$Fm$b z_swK;c^}R+FLlyvJ60-WeXC3x%raPVTV1HNnL$8ULA70Z#dAeJpW*Ft@=zMEI}2xU zz>N@ukdDh89Hqm>AuZ2|qa{Gv2tnfO`aCDE^&6q-V_x9o&2z`u{?GJ|rP>j$5ALaU z)aC!b?VtTC^&Gk}qkk*E+mqA}i5A`w#kNk|F2#lJm=+!FMee&Ym0Zm&nFH*3 zbs}o-8p?!dsyV%+FpAQ91e$*>dmy-W%W5u-(~-;A^jEpY_9)o@ca_PMhwD{%{Z+n_ z;|4(7*l<#3I|d_?M6Vuph%|cnL6_FJRM3s~O8eV~^6U7G@2Ug$qHB8_#Obqf^gNSm@J&5(o&D{PiwC$n z1|)qf6KNX4yI&53X*uFxN-uR7*806+o998BC;QeQtsu|3vLhcY2l+)Ft4?Kq%`|Sn zKOd!=X=wUU7}FqZt1Z(6;x?oM{e1un_OHGkI+Q;01Be?dQX7>@*t)2z29b`vdoLoJ z8%@ZZPdb8hRHy5G2crnf=5SrulCg(gkM9hw4%2VuUBNMp^rI&&WBA5l2N(|H%63a1 z!!+Htd0ts==pIKnEUFT3(!8hbRe=7zBn-Fd;|`OoSYTZocMq@4FF~3b-4i$^u<(9e z>WlNdeDcMB>4Wj8G~}nqP&34iP2$Pv3!@)TVJPfACgG^^+o*n|49}pfYzJ>Ob6z%U z=doH5PRvJz>(su{A!U0e*SRmVC$qo1GuzXi@9dh-<+BU(x!m6U9s7Is7)5*>k$T2KLop0~z z%J$6f&vl1M>sb#wM4DX>SpscOPhK;bz3ph`on1Mw50^{q>FmkoySnyMbUXL$i^%J` z*dZc~yxwg2r}Dap?*jgh;y+GaiwNgK*(2{&j#lvQ$}3?di|fiOd7^P{iNqnS5{aX8 zevX%D$K|}wD9)r;Lm25`88ppfcz5X_>^T1UC>>8-o->)AeYri|`#LiFI@&Xx9rJs$ z3;TK&+UK+ReVw_Ej z>=21Yo`2TzPv!Yme7_w3x8Xldo?n4*K9nQ!UghZL@b1bHVXw5fDo2b%o@ks`MdA?l z3o&s>qsIBgNF2g$kHmTE@|y3=b?)Eay{A3bwSRv$w?Dr>)6u;**WI39$nMF`?+wfA zy4W%Nehp}CEU# z>B(I7-S}31vMs+0|D4yqhrf6jhi%X0A-{h!29GppKJ1rFKFJoAhwn=3`|@aF?h_|#pCw_7B8UD@SE)-pb7V> z0*`Hg_9ATqpS9_!EdLe0wT>=<&F@mXj`7#b0}s=?Ox_aS3~YeBlZ5+QF+-=FY}MS5 zlFpRN=FSJ~@nbj#7bP6P<%cIt_~L58gmvP~A*3RAhWrikl32j@kLx+y6$*msO?(ai z*3v~iM1F6@H~GVNS-Z0DvUY{{?k1(TuaXC|wR}H~a-f*$n$BSMW$?W58V%RXvk3k-r7>0vZ4)L^p zCww!*acNRCd<#!ykrNbhhj9%NE_Y9?$Du8PAv5VIDd=M2JzRx&sNGz zC#%@W70`DkamF%LoBmX(yjmudyf{l>Qc&KS7fO38VN;dTLatghL@@&%P7u&`HgOEQ zW^r=hR0T(FR&#w-vYr8&&pE_nKuj6VB@CC=;mXE*1{b6ozVnEhpbRaFGdX`VmIp{H zc>!V$6G`?KjdgI`JW--@aI??BZ zU*Lob2Q2hTCg6s__)6h@Q zdvY($=b>X7?2L0Fauxb;mlGh{Blqm@SjhKuEg1ckI-hs(QJ>z8wG*zTsE=3+)?Gg3 z>(=Aai^Re`HO1*5Z!-dh5f*~bu7o08iI44&YmO^wESQP$mb7{vI#<_E5+(DXbZ@K9H9zzJ{JkI>3qee^Q6|kv7#(9{KiY)BS`-A zwYIK|-*J9)WhsZ25S&fbbxyQChn$IT_w#%GG->aRMy-0Iabi*qwW z)06$z4-L!?kM$j#5eC%Vz9;XFfqt-op0|CYsLU1JS7dT(OGy4E?f`e8HeHk1KLc&BaJkK43g z=J&b&xTn#eWP-gLbsH=ZI!0=Q%ka5T@bV>S%SmL+vV8}6t{2m^<@K<@O0-w<^1HSi zZkfM_FqYZ)yC=QxLj^^o23 z!u`Iae3MOMv&BKo+F%+5KVaw*qd@I7pQ9O}n^w{N~zd@`>O@@=y`g?YSSCri=5a!n3bMVdj+ih|A-i`gGZ2MZ5+6L=+-Q+#b z#=pwO*Lq>Qxh$kxlHS!8_XQSL)Bif!AnTiLnKTA<+2nQDIGr|*>Ky74;_;U{r_18) zwRpO>TxpN$%OH=<-aZ?*$Hr}>dzcn=P$S)Qz^3y;n@&JqpkH2OVLT&@a^ci)!%4kJ zrya*S^4SnSutPvDre{4@Ph5xmeVJ;MLPWY6p{bnp`sEGwZS^6HKm=Fo zhq#mhjva<9?y$vu4S1zvFnBr~pBS4tWCoBlN6GQYGNxvHoKfSz&3KOC%?O8?tFV&G z+PDF1D_}$UJS|eka-(Lvcfod^3kfr7c3>4Z(=BTxj%m?LCPzSEaJ2a>cqWtk+^+&xP-Ru=?c|_)IS_hr9m^Ra(L~tBNn->o!w~36Hb)(yX&w6AZ!g~BAe8=xu z;f3nfC}U6kt>TE{^hyZ^vZGNSzJ2@mE_BalJ9^-p0spBVLL_pYk4i`)cMFAc&Ds$EsNzK>~;7j2IrG}tY0}hH|Mdwl0zt3WSOU~ zK>PM(J36{M_I7mb&G+obZk)aI`@6ckvz_pJ%;o08EBO1?!wwaQ<@sf&Ja;_^FgkCWzg2h!KE z6xYSyhO`3Nfo{b2Q};2M&$hSE@6BX7JA3A{`*Qnod*?gh7d5{(pY7Za7o;$U*ToKT znDgaC%iBSp%FM6fU1f$sLD)O+&xg8-56jK)DBj(~bJqNydYQX(dvjeq`T1;TSAKuK zC*RXC&wW|*d$K+I_I39}{2JHAjw$myL93SeU6Ha7_HLF1k6UJjyJhD0dx__i`K$g| zab_recqZL9HFYFCGkS2MZ+32aC_OnndT?|iJux|(KGZihI@mWmG-&6QYvIpL+%PeD zc*5G^lipgm$Z=+Na(c+vXj5zA!dx^sd3eUA+q5R`(8TP}^wjj|%n;|Zw8wI6MZIzl zc(4XVW`w#10)|_sf9&&Zs(LtcG&c?J`_c**JWV+go*O=N0@iR^sHbzctQIP;`*D1p z4B^}$wrSF8=5%iSQE{{8**Rk8_RH_$V3}5IiaLom>1+z+A&b#4%1=X!S8^*0#um0Y zgmbu5IXb!0pIgclah^VD*#h`@=0s3T+{M)me$w7ce!d_4Oi#_E5BJ?Ll%5{yo0*(2 zJd6aAZ^u$PH<_yT)vydQ4_ot82E_Pg3p-bK;DfpO)kU*Nto$MG{P?rj=C-2pWh~BeiP)q`{)Azi8w9-ZVdJvz)7o|oyxEOA zRVkFXCL+^#13$xs4^=9q3athPcBTuPsbxp7`J#wh9yIT>T(|*_6{04)ADFvhrbIk$pr zm&>)uN@20Ef_g9DE=QJsr;FRaQX0h?quaJGaN*Y8baYxq;$PGN!3P9HpE34FZ1~!~2 z6em~cE5hPyU9!Epa8xJtp$W3(!EDjNfzC93B~n*xyFvVM?0v#?dmMM@**ij6Znoh7 z2l1r|o4R8gHn5r11v7-0moK+j>w-16}P;UcJZQvEwreu^^j zkh}_PFH_YC2y#Vf1Y4>zM&;l)Llo{K3sk z%6wsfCl?w{5-1bFADG!hVho0oT2^V0B;6&eC4ueaA*!PCU{l=8-V{y z1|xzB2Kz$CB>`--)Ihu_JI@aAW(vj9bg5Ju!~~6pRh(45T;br*YokI;Y0dTYJ|_;B z(?UZ%Jbp7m`|dcrU~xroo*RcVy}AP5mPIr4GCaC6z=LkFlPYK=rT=*W-0&Lntr~{q zrImX6uL^K|p3Y)#`EssSISJ;HXU`9C$O&U{Bj>EFTphrNP$i2eXDbkYpJ=I{7X&zV z31}JaqnJX=Ah@0`r~TUbRkp*$B3(}VRh-T!j?-opXHOKzX}5~g6~%Gdtm5pA;yCS8 zak`^8PTN$ReNh~zT`Epb6vt_winBk81cP6tUhwurjHk5w#9SWrjHk5xW#kY zsgD<8y2W$atdAFByv1t^WM?8*YtXnY?xhay8hxDa%eO1QZ`jYNkLhIruAN$-HP|+A zc>s&m77^X!mp3FtwhWH`@$o`}Wbqu`KS>$Hxl^l*M!OkB=7;DvRgnAI0m8 zlPgCL`FL@1<>(+EFHWu;J>=uX$(5sze7rcha&(f97grzc9%f_y@RJS57<4%28MSkU z`#2xFezM=V>y1tfPY#Ur&4|k$cE!{KFseR%EzTsNTwu0Y#h8~Skz95L7d+-FvP@4H z=h+ch-)e0M9d%)W#v9^r9vQ(I0PLV^Ba6WM=;xZj+_Pfmshn>|aK@?`)3XogWDgZ226h&ssqA&V#W%KOJ-~ms)G=YDFf&9el)^a z0<g)4AzU_w8~W*wM1Kb38!@C;kFx%KUsK#XqT$Bn6!|jFLs&0q z4q)bj8nwlM*oPaHPU~+npRW?@_isD{j%eqSB^RcVOSrKGsNjvkwiZC zJNe*jnImG!Ne{!SgQX6WOE?U9a4no^U50<2@w(0C`3Xr&hI6p38Q+UP3#Wg0V%Qjq z(i45^{~QiO`kx4u!BhwN#ymm)QXy~dMB;a|H_JU?QYgiNowsldBQO1K@dgXW3RReq zu}jL<9pi3i{S0A-Rmk~w=`tMkhMiKdP@e2xT{xPn(JrQGU1Z{{Vv3Q$c-W6eS!hE( zI!wME<%d6I^3R>}@AlHuvt#MO8&USr0hpv_M$)r={=HD~u-;y89%*^rsU%2qo(5^9 zhhVrIn(o8$k*U7;WF0i*V0>;r4O;1kM%p)=-&&aEUT#PFRq&@oav7Y4hv1a`aiL0~qv=6>wO-X@f)3u4U~H>ZOhLAqz5Z3WOv&7xe$Ehv zB909(Kpd!r17{EF@@l`bKlb z`J5Yo6pTFmolRp`sC>hi$shIk+~oDkH}hec9&*am>;=hUX9-oF8zA}cKF%0fMK3o# zIy-vMh*aO);OK06QWPiv%Aj?S{BnHWmZQPBt-|-dvA&4`^r#b)gH~JR!GsQ=zSA&hP3ix!u*U+N$u%Vq=ZFuN72n{I|PXR{|EvsdTiEo1yI;3!kR93jFl2|B%}bWv!6+WOJ?fUqFvO&}WTg+elO+ zC^&JYEzcsIP`$xYbt;3+I&Qye7Vp@1QFfEa`w=H^w84S7>A_K}9iJkJ};p*s=%&hKV#TE;7k^EK=XZ}FzZKEv;E_<^-}{h4Bh ztHg#@laE=fmA%dgr<|}4|B9r~JlLn0_PJ3xQQdW^#2(A7EQa?oB{|;a+KdH}KHjC{ z>Iw3Vy6fK^I=KHRuFc=P$scEjnvQ8S>4_sKmmO=z!Dog>CZ}|qig8{X&hX^)0N29D zCI`4?G&arY$bU z<#D(pqX$PsflW@`XwV^NEFZ?{arorfz^tw!4U7y8+%O~a3XI$1@ZprPr}GB8)g(R8 zH->J1bVmAmlMlx7aq-ac4Pg^M#(7hdqZ7C{(nb>6FvgFIgF*YqC=|Uvuo$2YvgN^g zd0ZTJveT1e>EW@-!|8)_eHc+1y0Cs8hu@D%y8+5=0%~<&dU9rRcou!lMBnr%s*rrc zm@6*cF!J#WK|HLn$Ki=Eq{k-vs6ink$2xAD@L7>+2sHGxG?n!>{&AX-`AuM2+s$NMBXDlkTKAps6GNR#~u(`fca1_$i-e*z!Uyb z*cMCG?fd*CKnv|br$LX5N@Al}0c@BghyV`{gz8b2HiZvuNIz-qAIfWnr7)hd+kC~= z!STtr9lqdhCEGYBr|E*zZ_HD3b)m?fy)tcM>s>0)da*W95T;%6+*ght9TZ|j2X z7Q2p$u#(C}+Cf{MhTn);1LJw~U&mzQ8Z4b*7Lk2^4NdU*BRJ(GS2@z%b*~n{V0tL(t8!q;MIdH1v360jBLv2&kfNB0Vj_YxCaTVssY6o1E}#n&^{i^ws|e zUj}n!40}ockL6ouDn?iQ1YsDj`|?CQC`5#@?xd~bo_Ol0=41ll`b6l)Z4`}|z$s@V zU~jaj@c)dRi{4;1Ag6;J|89uzDAAGveY|&)zT9Lv->;F}uN_L)#4&VJ_S#5i(#V^b*feW>u5d636jBj23IvJTj{5Z-3%0KZZP z!|`%w?Y0o4@$IJc|(xiUT-t}m$XmB>C1(MqtY9W@hqb<44ZIBk@K1q z2RBbE&Nz;=4b3#|w)^s6gH@e-DFH-VQg z_30!pQP}0Oq)mEmN>0@JSK~1vk-QF(os$gX#QlfAC4VC{a=H9 zcMl|uq(Np1SQ$W_@F2TD1|Ce#tfKg`0-=2U`{WJKmT=?8Ew1)xJE4s{e<&F^iHpOv zvqnKX)I-UMBQvYzG92uDe{80^6=irR33E&!93lAG0v}k#sbn~Y?pOgVoH<%3A z77rGSy4G=y;Ay>@a-2k6|AWuRZl8}2CyhN4qiCKACH6wnLLPrHIS7Yj4yw(_TI>Ch zB!qsdxC*Q9l0-ZKpszmcTF zIqS;oA5gx3Ga2>{GnP>!lPu%6{4#ck4}{YESTb-}a^u_p1^rlZaDGwtD$wUq_MQ0i zh%q0IMk=zQwQce|7krZVBuhcI9keKn+g)(m0S^ykD^fJlcAnyl9bI(8w`us`NxIyd z)}jbD{bwkSt-SsUuSZfOL*I7AG5Zb3P(_e-e7?e^7nnh#g!s=KUDZ0>5rWh4t2(;k zps@_CiUUs1T=!vr}+nZiVF$Q_mM5>^n)WIZBO8W#H>ZT;Yjs%3pKJwB-TtTk#pb)d@#N?F!?#z9kG38I(RP z6-X}AzZklrEeLz@DhOuyGf|GVl(siN&LlkRin!2OXk%Hg3gY@@C2j2~W6M{Xh}&hu zh{!xx<{pGeE4BPbtIruHOe-O1y~HK|dXd+1Zmyg~jc_`xX%jY*g0o)^9a_%tikRT0 zA9u=!hsFRz@$2UZ`5#0dU0JBeUFdE;HxVb4M1V#*+d#`wgLKSFv5{fo6&j~yP;Hx# z{wp=N0vSA-(>*e!O2}?-A^2NN4XrE`Gskka2NLD(^j|Me`CftpB~&Do(=^>(wR{&L zjZ-PM2kIx&r;nA`8w9d=cS^=S+&bcKnA1%|EI;f1-6;(J7vajnHEGDWYr|k&-Q&wu zm(&ks@ZMC2sWRYVdW79aK1qn-9rL(9Wpuo+M@%MCmlvZPpR{nX064HV#Qk$W|NW9b z`THs6A+7=@52hhu{U^(rYBi)^n8v52j%Ddz@{~ST0-J`e z@w3caUv}5{JAgynPK&E{iG;O3w4p!=$6k@J_6G@v{lT@%(1yUYz6#^fR_tYGTDuVc z0@x;q$9MJxk40V2T~8URsx+Bp&}FG87gZ~nEmd=2arZ~+|}?;pDn zi&2x)SQ8G+opBJ$-(H($0~_%07#4T1Ue!+@B6^w{U0oM!=}oruJ9R)_U5q*)-&k+t z8ycJNcLh34&!yn|9VjKrEB7ZHL>hW71!2SZ=D7kR{KZ4QFkJa^J;JYY;@{99{+Nv~ z_ogO1Zxr7t{Ep+7b{yy8uNIRwK`T> zS)}_*A6<^5>@OQw~f*=v+6qDyhe~z!h;OdWa7}jF=#({ar7c~d@*y)XBE4J(l z_-@m6GPtg&bE>Aj+nZUPH{)^{p=o%##=&v`*Dx5)^|&5y81wb1+`LQ@O!$7#-Rt$$ zinB|&OJRoNhN+qz*OJx|Z*+KQ@`l_=n-1ID6xP;CRaPyhszLw9`Sq0MJ-PxfbHfMD ztDSHx339_1_+-=MyxND);Z*3wLqj7L#(8xFhQ&%lJLl73*zl~vIH&eu>QY!diEgY^ ztKn_}t$)s|eLR?3c$kBWM&2C|9G&xVN^9(Atn*o|^Nyg-k9g)h49-jExim`8S4%T_ zdc>m)8yf|kipg;1L*CwGZLXS|(n(mhuAa;}&RXwFUSGL@?UY=(()7ySY!Np`lrt-w z?8|`PxBZg-n$nMRrZt@tjDun>+jQtJd@2a@=kzSg?V?jASBfW1dCWMIq8+4nC&qke zFt2p$77%R! zq(}t>amma3?3yQRQfhJWeS``B7;MsJrbqcUW#Js<{^*)Ehjyh^zkRb0dVuS2<(b?f zSM_W~YCRJEpbNKq0?B*A9v0Xj_vT`&;A{!DB<}g-@T4*_>zuvrr<*Ur{a+Q%> z5qsneA4yMh0`Uh2bjP2Wu-LLuF1IGEF5P3|P=B=~ILpaZTpI_|+L@S~X=Izeh_D#j z^reW`23XX-&hT9bAD9_bOShDX`CN|hDV%h{z2Pvw_~E+~(u+YESLM8Tts};{DgtXn zXL}SchGz1mOZn1e@~0g1Btmn3JuJnyVZRXZddY87Q`RxWw3Q!X9NM0o!nGH+zBmbl z^#i-${WTxfcTdvQBUU-s`nrbc$G}BVSRC@={-iZ#S=$xM^U0*G=e?#p7j37FKD5^2 zw@bnvjKHW#mEWZE;ba*$qGf69s?Qz?;!xd+Zlq7fqe-WhEuGharYDS@+}dcw-`r2H z4{$GKd4-+yx#fANKI|}nc2d2|G}Ja}uaJ=ns!P!3$u!k28Iz>Q8S8mx$}U-xan zHWS-429QQu3U~Qvr(^pY&h2+IoIN|*u#T&wP8sg#dD_Z)gD_vuv+kxC&UHKE;^VjT zBdNo=3f&c8xs~z>rvg2E6XB?lG7AQSyF0d6N|onUR?WU@t*dgXERBhzLThBIxHpQri=S}`3O2i>t9q~hM5nk|=kbXBfWW;MC`jrDhD z1g`QvguL%g9nKVLlPh*0Nro9sY|GDjzI#iZebcbl$_ROT&z6B=X*J7vf#ELVp9_oE z1oEIIhI#UP8sB;sH}CkSt>G5$isTH!^|^P8#1Io0qV{sGNgp(DC8;>(S68^#-^VnE z^vPEbN9eorWK3#KUtw)&0*7r%E}!yO8%-S&hW%j%c1X^DKuPV@R1P0n?7l0Nx$WX} zhO-?aGPm91)M*)eK(aHiEQ?N|tPvk~dC3}viXziG1p49IuNnGsvNLJ1utb()spJ;e9Ko=i==;2lSif9!BMKnD8t|@im*-zBMm8(ZNVwqRxj;( zKAEz(A)uXhz?k;z8~#ir{}VC7_N}FeeG6TC$c}R=^8J|oE`xs759Ihs*u!LxnjtC1 zASO^yNWLDmd~KkwLJqPf!BCK2PSVK#$Dp5F`_#x5^R4hlZMkl-_-9)E)@Hw&GSU){jfxtsj@XTR$#&haVU1tn$9qc|Y5EKgW4Lm+#4z zcIXDRA@cnWlm_J$8{%tFezhSI_DgI(upz#dzj(+OhO16{9m212;=jH@{9m^5)rNQn zzG*|e6TeCm(_!9kM3|p9!ZhzVSTx-?*>vBG-*=vEY>3YRy&mShvxRxl6*5LdpLwiM zDT#;bRH;BmF&%&85VzO!52}-P#LDXW7FT&5&=1 zvgs3c!h;Lvo=y`kvj$U!Jj#4Z>^FNlqc)mFz#bKt5Ak{8B@Ry>cB1I`qB&uWPQs92 zpZnItaCxSbuhGq;~$<(WNCey(@ zNaiqRyqt%f;l3mXz!=->@vU^Nz?OK@$3E-+q`&W<79R-@%^$7JwTOH$f5iC9c<{)M zffF^!&6P9i-v^TsW(`<_-HfrH5$EAXIBHXz3VbOZSr6ByOBsDMIeTKbYN@mQYeV=q z8l?gEEE(5Y+}C4c$~SfHY;BLrDEnhc%=2e+^ZoX0N%D{F^x-X-h7{}D>Z4nLKfqn6 zYBIM?)@e_V367jcJB1ZKkr|fZJ3;uYhO_NF!EmRUOY^bmt$-G@vT$Z9zEqh_TEJ-;Hp4R;NGjXLx%M9_TrQMeVe` z2(ztoTKCp4{s_Y(`_QMhi7%YARHKj#9hA}8ZFYWWZLG9C9NETJU0ASI${D#-(b9ek z;w**XA)8GF@XGeEeT;OS*gl9lE<&@?yTmjw^5U0}->L1e-^>(CaK{qaJXBsFdwl& zw6_k`j&tT7u^;!eLJntOF?H}M*S)QfUui(bL5B3#KE3L4^3BbzpM_R{miXJQ6g&G+l4<99O z9VWu_Q)oO68o$vh>x}5ljPZqOo{(^{#VOFYQ<7ibf_yFK{3w#vNyK4z9?K|L=4soiXBQn3Aejk~XY|WUVRrm~9NHV(&$zFiTjHfy4J>FD2h`Fw$JvYW#QaJbV|@O^^0sEm zYMbNP;w<;C3C%RCLmqLgs>6#_xZg8KXR1Q|G8VncA%OU z>e_@m>jK1=vv_2G<>*QoZULGOe0A);%gNOm0nT`~-G|ATS>pT#%Gl%C@n&#bnaCRF z4^tjC0nr)Bjs+NYlkqEJsQ4^1Z-&FpVa^LcGgTWmX+7oIcAW9f?W6~%?5->x5n9Nf zJN&R4{jfWYo#lv@g?Mi^VK=&AcbPCKk4ly2(HD^ z78{la>D&YVlG5>d7|VXIjWb(-*N?-i`%&L=5vgO_A^w9%D_1P~^F@X|;$hz&7JJO} z!Q}fc)X!tl`muYOD4UOA&w+0@lZ6=*kFY0Pn0gsF^58Yu%~sg)$P*t{7Ea0_METa- zWCs!A#2?I!M2?&6LZ;j~P!;`%aZ&Q!j=pJW68$J{^44gap6cTPZtyZTH*>Fr(93?N zf&HKDy5ZSov|qj#bg*w~V1s7-nW?e98*wba1di_UI{_z9@@HE2*tE2ddY_aL3m|a2 zQTbyS&L_j!QF5k~$P&YFUKG|qY#?|~dQ#xi`y~xj5+2(}IaxQRr`z@y=Bz3?P+H`i zev({wT)0hr z|5E$<4(o$$UldV6o|<3TX>$@KOfc}ee0d)w!G_IGvlc&Kx(4X}J>ZNRK2d<5mA-Ja$B zeV>;J?+@%dVH~fzu$NlC-3r;`IT4I&?-$`I5gx;sPo`X6hWHirvJL@4=Fh`w@O?>Oc*1MB$VBP{=S-wN>eI|}t;wqYC+p