Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
## [0.3.0-preview.6] - 2020-02-24
### New features
### Changes
* Pipelines are now registered by calling `NetworkPipelineStageCollection.RegisterPipelineStage` before creating a `NetworkDriver`. The built-in pipelines do not require explicit registration. The interface for implementing pipelines has been changed to support this.
* NetworkDriver is no longer a generic type. You pass it an interface when creating the `NetworkDriver`, which means you can switch between backends without modifying all usage of the driver. There is a new `NetworkDriver.Create` which creates a driver with the default `NetworkInterface`. It is also possible to create a `new NetworkDriver` by passing a `NetworkInterface` instance as the first argument.
* `NetworkDriver.Send` is replaced by `BeginSend` and `EndSend`. This allows us to do less data copying when sending messages. The interface for implementing new netowrk interfaces has been changed to support this.
* `DataStreamReader` and `DataStreamWriter` no longer owns any memory. They are just reading/writing the data of a `NativeArray<byte>`.
* `DataStreamWriter` has explicit types for all Write methods.
* `DataStreamReader.Context` has been removed.
* Error handling for `DataStreamWriter` has been improved, on failure it returns false and sets `DataStreamWriter.HasFailedWrites` to true. `DataStreamReader` returns a default value and sets `DataStreamReader.HasFailedReads` to true. `DataStreamReader` will throw an excpetion instead of returning a default value in the editor.
* IPCManager is no longer public, it is still possible to create a `NetworkDriver` with a `IPCNetworkInterface`.
* Added `NetworkDriver.ScheduleFlushSend` which must be called to guarantee that messages are send before next call to `NetworkDriver.ScheduleUpdate`.
* Added `NetworkDriver.LastUpdateTime` to get the update time the `NetworkDriver` used for the most recent update.
* Removed the IPC address family, use a IPv4 localhost address instead.

### Fixes
* Fixed a memory overflow in the reliability pipeline.
* Made the soaker report locale independent.

### Upgrade guide
Creation and type of `NetworkDriver` has changed, use `NetworkDriver.Create` or pass an instance of a `NetworkInterface` to the `NetworkDriver` constructor.

`NetworkDriver.Send` has been replaced by a pair of `NetworkDriver.BeginSend` and `NetworkDriver.EndSend`. Calling `BeginSend` will return a `DataStreamWriter` to which you write the data. The `DataStreamWriter` is then passed to `EndSend`.

All write calls in `DataStreamWriter` need an explicit type, for example `Write(0)` should be replaced by `WriteInt(0)`.

`DataStreamWriter` no longer shares current position between copies, if you call a method which writes you must pass it by ref for the modifications to apply.

`DataStreamWriter` no longer returns a DeferedWriter, you need to take a copy of the writer at the point you want to make modifications and use the copy to overwrite data later.

`DataStreamWriter` is no longer disposable. If you use the allocating constructor you need to use `Allocator.Temp`, if you pass a `NativeArray<byte>` to the constructor the `NativeArray` owns the memory.

`DataStreamReader.Context` no longer exists, you need to pass the `DataStreamReader` itself by ref if you read in a different function.

The interface for network pipelines has been changed.

The interface for network interfaces has been changed.
  • Loading branch information
Unity Technologies committed Feb 23, 2020
1 parent e98eb3f commit 64824ab
Show file tree
Hide file tree
Showing 67 changed files with 4,795 additions and 4,370 deletions.
38 changes: 38 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,43 @@
# Change log

## [0.3.0-preview.6] - 2020-02-24
### New features
### Changes
* Pipelines are now registered by calling `NetworkPipelineStageCollection.RegisterPipelineStage` before creating a `NetworkDriver`. The built-in pipelines do not require explicit registration. The interface for implementing pipelines has been changed to support this.
* NetworkDriver is no longer a generic type. You pass it an interface when creating the `NetworkDriver`, which means you can switch between backends without modifying all usage of the driver. There is a new `NetworkDriver.Create` which creates a driver with the default `NetworkInterface`. It is also possible to create a `new NetworkDriver` by passing a `NetworkInterface` instance as the first argument.
* `NetworkDriver.Send` is replaced by `BeginSend` and `EndSend`. This allows us to do less data copying when sending messages. The interface for implementing new netowrk interfaces has been changed to support this.
* `DataStreamReader` and `DataStreamWriter` no longer owns any memory. They are just reading/writing the data of a `NativeArray<byte>`.
* `DataStreamWriter` has explicit types for all Write methods.
* `DataStreamReader.Context` has been removed.
* Error handling for `DataStreamWriter` has been improved, on failure it returns false and sets `DataStreamWriter.HasFailedWrites` to true. `DataStreamReader` returns a default value and sets `DataStreamReader.HasFailedReads` to true. `DataStreamReader` will throw an excpetion instead of returning a default value in the editor.
* IPCManager is no longer public, it is still possible to create a `NetworkDriver` with a `IPCNetworkInterface`.
* Added `NetworkDriver.ScheduleFlushSend` which must be called to guarantee that messages are send before next call to `NetworkDriver.ScheduleUpdate`.
* Added `NetworkDriver.LastUpdateTime` to get the update time the `NetworkDriver` used for the most recent update.
* Removed the IPC address family, use a IPv4 localhost address instead.

### Fixes
* Fixed a memory overflow in the reliability pipeline.
* Made the soaker report locale independent.

### Upgrade guide
Creation and type of `NetworkDriver` has changed, use `NetworkDriver.Create` or pass an instance of a `NetworkInterface` to the `NetworkDriver` constructor.

`NetworkDriver.Send` has been replaced by a pair of `NetworkDriver.BeginSend` and `NetworkDriver.EndSend`. Calling `BeginSend` will return a `DataStreamWriter` to which you write the data. The `DataStreamWriter` is then passed to `EndSend`.

All write calls in `DataStreamWriter` need an explicit type, for example `Write(0)` should be replaced by `WriteInt(0)`.

`DataStreamWriter` no longer shares current position between copies, if you call a method which writes you must pass it by ref for the modifications to apply.

`DataStreamWriter` no longer returns a DeferedWriter, you need to take a copy of the writer at the point you want to make modifications and use the copy to overwrite data later.

`DataStreamWriter` is no longer disposable. If you use the allocating constructor you need to use `Allocator.Temp`, if you pass a `NativeArray<byte>` to the constructor the `NativeArray` owns the memory.

`DataStreamReader.Context` no longer exists, you need to pass the `DataStreamReader` itself by ref if you read in a different function.

The interface for network pipelines has been changed.

The interface for network interfaces has been changed.

## [0.2.3-preview.0] - 2019-12-12
### New features
### Changes
Expand Down
38 changes: 17 additions & 21 deletions Documentation~/pipelines-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Pipelines are a feature which offers layers of functionality on top of the defau

## 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.
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.

Expand All @@ -19,13 +19,12 @@ When sending packets the pipeline can then be specified as a parameter, so the p

```c#
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Networking.Transport;
using Unity.Networking.Transport.Utilities;

public class Client {

UdpNetworkDriver m_DriverHandle;
public class Client
{
NetworkDriver m_DriverHandle;
NetworkPipeline m_Pipeline;

const int k_PacketSize = 256;
Expand All @@ -36,17 +35,17 @@ public class Client {
public void Configure()
{
// Driver can be used as normal
m_DriverHandle = new UdpNetworkDriver(new SimulatorUtility.Parameters {MaxPacketSize = k_PacketSize, MaxPacketCount = 30, PacketDelayMs = 100});
m_DriverHandle = NetworkDriver.Create(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<byte> someData)
public void SendMessage(NativeArray<byte> 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);
var writer = m_DriverHandle.BeginSend(m_Pipeline, m_ConnectionToServer);
writer.WriteBytes(someData);
m_DriverHandle.EndSend(writer);
}
}
```
Expand All @@ -59,7 +58,7 @@ The simulator pipeline stage could be added on either the client or server to si

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_DriverHandle = NetworkDriver.Create(new SimulatorUtility.Parameters {MaxPacketSize = NetworkParameterConstants.MTU, MaxPacketCount = 30, PacketDelayMs = 25, PacketDropPercentage = 10});
m_Pipeline = m_DriverHandle.CreatePipeline(typeof(SimulatorPipelineStage));
```

Expand All @@ -72,10 +71,8 @@ To get information about internal state in the simulator you can check the Simul
```c#
public unsafe void DumpSimulatorStatistics()
{
NativeSlice<byte> receiveBuffer = default;
NativeSlice<byte> sendBuffer = default;
NativeSlice<byte> sharedBuffer = default;
driver.GetPipelineBuffers(pipeline, 0, connection[0], ref receiveBuffer, ref sendBuffer, ref sharedBuffer);
var simulatorStageId = NetworkPipelineStageCollection.GetStageId(typeof(SimulatorPipelineStage));
driver.GetPipelineBuffers(pipeline, simulatorStageId, connection[0], out var receiveBuffer, out var sendBuffer, out var sharedBuffer);
var simCtx = (SimulatorUtility.Context*)sharedBuffer.GetUnsafeReadOnlyPtr();
UnityEngine.Debug.Log("Simulator stats\n" +
"PacketCount: " + simCtx->PacketCount + "\n" +
Expand Down Expand Up @@ -109,7 +106,7 @@ The ack packet type is used when a certain amount of time has passed and nothing
### Using the reliability pipeline

```c#
m_ServerDriver = new UdpNetworkDriver(new ReliableUtility.Parameters { WindowSize = 32 });
m_ServerDriver = NetworkDriver.Create(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.
Expand All @@ -118,13 +115,12 @@ Because only 32 packets can be tracked at a time there can't be more than 32 pac

```c#
// Get a reference to the internal state or shared context of the reliability
NativeSlice<byte> tmpReceiveBuffer = default;
NativeSlice<byte> tmpSendBuffer = default;
NativeSlice<byte> serverReliableBuffer = default;
m_ServerDriver.GetPipelineBuffers(typeof(ReliableSequencedPipelineStage), serverToClient, ref tmpReceiveBuffer, ref tmpSendBuffer, ref serverReliableBuffer);
var reliableStageId = NetworkPipelineStageCollection.GetStageId(typeof(ReliableSequencedPipelineStage));
m_ServerDriver.GetPipelineBuffers(serverPipe, reliableStageId, serverToClient, out var tmpReceiveBuffer, out var tmpSendBuffer, out var serverReliableBuffer);
var serverReliableCtx = (ReliableUtility.SharedContext*) serverReliableBuffer.GetUnsafePtr();

m_ServerDriver.Send(serverPipe, serverToClient, strm);
var strm = m_ServerDriver.BeginSend(serverPipe, serverToClient);
m_ServerDriver.EndSend(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
Expand Down
23 changes: 9 additions & 14 deletions Documentation~/samples/clientbehaviour.cs.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
```c#
using UnityEngine;

using Unity.Collections;
using Unity.Networking.Transport;

public class ClientBehaviour : MonoBehaviour
{
public UdpNetworkDriver m_Driver;
public NetworkDriver m_Driver;
public NetworkConnection m_Connection;
public bool m_Done;

void Start ()
{
m_Driver = new UdpNetworkDriver(new INetworkParameter[0]);
{
m_Driver = NetworkDriver.Create();
m_Connection = default(NetworkConnection);

var endpoint = NetworkEndPoint.LoopbackIpv4;
Expand All @@ -39,24 +38,20 @@ public class ClientBehaviour : MonoBehaviour
DataStreamReader stream;
NetworkEvent.Type cmd;

while ((cmd = m_Connection.PopEvent(m_Driver, out stream)) !=
NetworkEvent.Type.Empty)
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);
}
uint value = 1;
var writer = m_Driver.BeginSend(m_Connection);
writer.WriteUInt(value);
m_Driver.EndSend(writer);
}
else if (cmd == NetworkEvent.Type.Data)
{
var readerCtx = default(DataStreamReader.Context);
uint value = stream.ReadUInt(ref readerCtx);
uint value = stream.ReadUInt();
Debug.Log("Got the value = " + value + " back from the server");
m_Done = true;
m_Connection.Disconnect(m_Driver);
Expand Down
88 changes: 42 additions & 46 deletions Documentation~/samples/jobifiedclientbehaviour.cs.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,66 +7,62 @@ using Unity.Networking.Transport;

struct ClientUpdateJob : IJob
{
public UdpNetworkDriver driver;
public NativeArray<NetworkConnection> connection;
public NativeArray<byte> done;
public NetworkDriver driver;
public NativeArray<NetworkConnection> connection;
public NativeArray<byte> done;

public void Execute()
{
if (!connection[0].IsCreated)
{
if (done[0] != 1)
Debug.Log("Something went wrong during connect");
return;
}
public void Execute()
{
if (!connection[0].IsCreated)
{
if (done[0] != 1)
Debug.Log("Something went wrong during connect");
return;
}

DataStreamReader stream;
NetworkEvent.Type cmd;
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");
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);
}
}
}
uint value = 1;
var writer = driver.BeginSend(connection[0]);
writer.WriteUInt(value);
driver.EndSend(writer);
}
else if (cmd == NetworkEvent.Type.Data)
{
uint value = stream.ReadUInt();
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 NetworkDriver m_Driver;
public NativeArray<NetworkConnection> m_Connection;
public NativeArray<byte> m_Done;

public JobHandle ClientJobHandle;

void Start ()
{
m_Driver = new UdpNetworkDriver(new INetworkParameter[0]);
{
m_Driver = NetworkDriver.Create();

m_Connection = new NativeArray<NetworkConnection>(1, Allocator.Persistent);
m_Done = new NativeArray<byte>(1, Allocator.Persistent);
Expand Down
29 changes: 12 additions & 17 deletions Documentation~/samples/jobifiedserverbehaviour.cs.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ using Unity.Networking.Transport;

struct ServerUpdateConnectionsJob : IJob
{
public UdpNetworkDriver driver;
public NetworkDriver driver;
public NativeList<NetworkConnection> connections;

public void Execute()
Expand All @@ -34,32 +34,27 @@ struct ServerUpdateConnectionsJob : IJob

struct ServerUpdateJob : IJobParallelForDefer
{
public UdpNetworkDriver.Concurrent driver;
public NetworkDriver.Concurrent driver;
public NativeArray<NetworkConnection> connections;

public void Execute(int index)
{
DataStreamReader stream;
if (!connections[index].IsCreated)
Assert.IsTrue(true);
Assert.IsTrue(connections[index].IsCreated);

NetworkEvent.Type cmd;
while ((cmd = driver.PopEventForConnection(connections[index], out stream)) !=
NetworkEvent.Type.Empty)
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);
uint number = stream.ReadUInt();

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);
}
var writer = driver.BeginSend(connections[index]);
writer.WriteUInt(number);
driver.EndSend(writer);
}
else if (cmd == NetworkEvent.Type.Disconnect)
{
Expand All @@ -72,14 +67,14 @@ struct ServerUpdateJob : IJobParallelForDefer

public class JobifiedServerBehaviour : MonoBehaviour
{
public UdpNetworkDriver m_Driver;
public NetworkDriver m_Driver;
public NativeList<NetworkConnection> m_Connections;
private JobHandle ServerJobHandle;

void Start ()
{
{
m_Connections = new NativeList<NetworkConnection>(16, Allocator.Persistent);
m_Driver = new UdpNetworkDriver(new INetworkParameter[0]);
m_Driver = NetworkDriver.Create();
var endpoint = NetworkEndPoint.AnyIpv4;
endpoint.Port = 9000;
if (m_Driver.Bind(endpoint) != 0)
Expand All @@ -97,7 +92,7 @@ public class JobifiedServerBehaviour : MonoBehaviour
}

void Update ()
{
{
ServerJobHandle.Complete();

var connectionJob = new ServerUpdateConnectionsJob
Expand Down
Loading

0 comments on commit 64824ab

Please sign in to comment.