浏览代码

Add LiteNetLib transport

/main
Luke Stampfli 4 年前
当前提交
447aac2f
共有 77 个文件被更改,包括 8248 次插入0 次删除
  1. 8
      Packages/packages-lock.json
  2. 5
      Packages/com.unity.multiplayer.transport.litenet/CHANGELOG.md
  3. 7
      Packages/com.unity.multiplayer.transport.litenet/CHANGELOG.md.meta
  4. 21
      Packages/com.unity.multiplayer.transport.litenet/LICENSE.md
  5. 7
      Packages/com.unity.multiplayer.transport.litenet/LICENSE.md.meta
  6. 1
      Packages/com.unity.multiplayer.transport.litenet/README.md
  7. 7
      Packages/com.unity.multiplayer.transport.litenet/README.md.meta
  8. 8
      Packages/com.unity.multiplayer.transport.litenet/Runtime.meta
  9. 8
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib.meta
  10. 31
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/BaseChannel.cs
  11. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/BaseChannel.cs.meta
  12. 137
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/ConnectionRequest.cs
  13. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/ConnectionRequest.cs.meta
  14. 224
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/INetEventListener.cs
  15. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/INetEventListener.cs.meta
  16. 8
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Layers.meta
  17. 36
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Layers/Crc32cLayer.cs
  18. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Layers/Crc32cLayer.cs.meta
  19. 15
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Layers/PacketLayerBase.cs
  20. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Layers/PacketLayerBase.cs.meta
  21. 59
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Layers/XorEncryptLayer.cs
  22. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Layers/XorEncryptLayer.cs.meta
  23. 7
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/LiteNetLib.csproj.meta
  24. 245
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NatPunchModule.cs
  25. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NatPunchModule.cs.meta
  26. 72
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetConstants.cs
  27. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetConstants.cs.meta
  28. 92
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetDebug.cs
  29. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetDebug.cs.meta
  30. 1001
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetManager.cs
  31. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetManager.cs.meta
  32. 276
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetPacket.cs
  33. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetPacket.cs.meta
  34. 74
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetPacketPool.cs
  35. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetPacketPool.cs.meta
  36. 1001
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetPeer.cs
  37. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetPeer.cs.meta
  38. 483
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetSocket.cs
  39. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetSocket.cs.meta
  40. 39
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetStatistics.cs
  41. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetStatistics.cs.meta
  42. 197
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetUtils.cs
  43. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetUtils.cs.meta
  44. 323
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/ReliableChannel.cs
  45. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/ReliableChannel.cs.meta
  46. 99
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/SequencedChannel.cs
  47. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/SequencedChannel.cs.meta
  48. 8
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils.meta
  49. 111
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/CRC32C.cs
  50. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/CRC32C.cs.meta
  51. 118
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/FastBitConverter.cs
  52. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/FastBitConverter.cs.meta
  53. 8
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/INetSerializable.cs
  54. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/INetSerializable.cs.meta
  55. 694
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetDataReader.cs
  56. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetDataReader.cs.meta
  57. 382
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetDataWriter.cs
  58. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetDataWriter.cs.meta
  59. 314
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetPacketProcessor.cs
  60. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetPacketProcessor.cs.meta
  61. 752
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetSerializer.cs
  62. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetSerializer.cs.meta
  63. 426
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NtpPacket.cs
  64. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NtpPacket.cs.meta
  65. 175
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NtpRequest.cs
  66. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NtpRequest.cs.meta
  67. 415
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLibTransport.cs
  68. 11
      Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLibTransport.cs.meta
  69. 16
      Packages/com.unity.multiplayer.transport.litenet/Runtime/com.unity.multiplayer.transport.litenet.asmdef
  70. 7
      Packages/com.unity.multiplayer.transport.litenet/Runtime/com.unity.multiplayer.transport.litenet.asmdef.meta
  71. 16
      Packages/com.unity.multiplayer.transport.litenet/package.json
  72. 7
      Packages/com.unity.multiplayer.transport.litenet/package.json.meta

8
Packages/packages-lock.json


"dependencies": {},
"hash": "c4a9ab0da78e366f6f7fdf2d337455cc1d94dbb0"
},
"com.unity.multiplayer.transport.litenet": {
"version": "file:com.unity.multiplayer.transport.litenet",
"depth": 0,
"source": "embedded",
"dependencies": {
"com.unity.multiplayer.mlapi": "0.0.1-preview.1"
}
},
"com.unity.test-framework": {
"version": "1.1.16",
"depth": 0,

5
Packages/com.unity.multiplayer.transport.litenet/CHANGELOG.md


Changelog
All notable changes to this package will be documented in this file. The format is based on Keep a Changelog
[0.0.1-preview.1] - 2020-10-05
This is the first release of Enet MLAPI Package

7
Packages/com.unity.multiplayer.transport.litenet/CHANGELOG.md.meta


fileFormatVersion: 2
guid: 28f71d7dc1ed3bc4ba12892aa139f9e6
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

21
Packages/com.unity.multiplayer.transport.litenet/LICENSE.md


MIT License
Copyright (c) 2018, 2019 Albin Corén
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

7
Packages/com.unity.multiplayer.transport.litenet/LICENSE.md.meta


fileFormatVersion: 2
guid: 0112cf41b55769347836bdb4bfc2f66e
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

1
Packages/com.unity.multiplayer.transport.litenet/README.md


Enet transport for MLAPI

7
Packages/com.unity.multiplayer.transport.litenet/README.md.meta


fileFormatVersion: 2
guid: 859976d97fd97dc48adc4bc7ff818f45
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.multiplayer.transport.litenet/Runtime.meta


fileFormatVersion: 2
guid: 76d634f7c88c1da4cb3ea69d7bae43bb
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib.meta


fileFormatVersion: 2
guid: 22e683408a542064b9a7e0670cba52a2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

31
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/BaseChannel.cs


using System.Collections.Generic;
namespace LiteNetLib
{
internal abstract class BaseChannel
{
public BaseChannel Next;
protected readonly NetPeer Peer;
protected readonly Queue<NetPacket> OutgoingQueue;
protected BaseChannel(NetPeer peer)
{
Peer = peer;
OutgoingQueue = new Queue<NetPacket>(64);
}
public int PacketsInQueue
{
get { return OutgoingQueue.Count; }
}
public void AddToQueue(NetPacket packet)
{
lock (OutgoingQueue)
OutgoingQueue.Enqueue(packet);
}
public abstract void SendNextPackets();
public abstract bool ProcessPacket(NetPacket packet);
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/BaseChannel.cs.meta


fileFormatVersion: 2
guid: a74c865f121743d479838192cd3b2e06
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

137
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/ConnectionRequest.cs


using System.Net;
using System.Threading;
using LiteNetLib.Utils;
namespace LiteNetLib
{
internal enum ConnectionRequestResult
{
None,
Accept,
Reject,
RejectForce
}
public class ConnectionRequest
{
private readonly NetManager _listener;
private int _used;
public readonly NetDataReader Data;
internal ConnectionRequestResult Result { get; private set; }
internal long ConnectionTime;
internal byte ConnectionNumber;
public readonly IPEndPoint RemoteEndPoint;
private bool TryActivate()
{
return Interlocked.CompareExchange(ref _used, 1, 0) == 0;
}
internal void UpdateRequest(NetConnectRequestPacket connRequest)
{
if (connRequest.ConnectionTime >= ConnectionTime)
{
ConnectionTime = connRequest.ConnectionTime;
ConnectionNumber = connRequest.ConnectionNumber;
}
}
internal ConnectionRequest(
long connectionId,
byte connectionNumber,
NetDataReader netDataReader,
IPEndPoint endPoint,
NetManager listener)
{
ConnectionTime = connectionId;
ConnectionNumber = connectionNumber;
RemoteEndPoint = endPoint;
Data = netDataReader;
_listener = listener;
}
public NetPeer AcceptIfKey(string key)
{
if (!TryActivate())
return null;
try
{
if (Data.GetString() == key)
Result = ConnectionRequestResult.Accept;
}
catch
{
NetDebug.WriteError("[AC] Invalid incoming data");
}
if (Result == ConnectionRequestResult.Accept)
return _listener.OnConnectionSolved(this, null, 0, 0);
Result = ConnectionRequestResult.Reject;
_listener.OnConnectionSolved(this, null, 0, 0);
return null;
}
/// <summary>
/// Accept connection and get new NetPeer as result
/// </summary>
/// <returns>Connected NetPeer</returns>
public NetPeer Accept()
{
if (!TryActivate())
return null;
Result = ConnectionRequestResult.Accept;
return _listener.OnConnectionSolved(this, null, 0, 0);
}
public void Reject(byte[] rejectData, int start, int length, bool force)
{
if (!TryActivate())
return;
Result = force ? ConnectionRequestResult.RejectForce : ConnectionRequestResult.Reject;
_listener.OnConnectionSolved(this, rejectData, start, length);
}
public void Reject(byte[] rejectData, int start, int length)
{
Reject(rejectData, start, length, false);
}
public void RejectForce(byte[] rejectData, int start, int length)
{
Reject(rejectData, start, length, true);
}
public void RejectForce()
{
Reject(null, 0, 0, true);
}
public void RejectForce(byte[] rejectData)
{
Reject(rejectData, 0, rejectData.Length, true);
}
public void RejectForce(NetDataWriter rejectData)
{
Reject(rejectData.Data, 0, rejectData.Length, true);
}
public void Reject()
{
Reject(null, 0, 0, false);
}
public void Reject(byte[] rejectData)
{
Reject(rejectData, 0, rejectData.Length, false);
}
public void Reject(NetDataWriter rejectData)
{
Reject(rejectData.Data, 0, rejectData.Length, false);
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/ConnectionRequest.cs.meta


fileFormatVersion: 2
guid: ab9cb220487967e4ba764971b6eb9fac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

224
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/INetEventListener.cs


using System.Net;
using System.Net.Sockets;
namespace LiteNetLib
{
/// <summary>
/// Type of message that you receive in OnNetworkReceiveUnconnected event
/// </summary>
public enum UnconnectedMessageType
{
BasicMessage,
Broadcast
}
/// <summary>
/// Disconnect reason that you receive in OnPeerDisconnected event
/// </summary>
public enum DisconnectReason
{
ConnectionFailed,
Timeout,
HostUnreachable,
NetworkUnreachable,
RemoteConnectionClose,
DisconnectPeerCalled,
ConnectionRejected,
InvalidProtocol,
UnknownHost,
Reconnect,
PeerToPeerConnection
}
/// <summary>
/// Additional information about disconnection
/// </summary>
public struct DisconnectInfo
{
/// <summary>
/// Additional info why peer disconnected
/// </summary>
public DisconnectReason Reason;
/// <summary>
/// Error code (if reason is SocketSendError or SocketReceiveError)
/// </summary>
public SocketError SocketErrorCode;
/// <summary>
/// Additional data that can be accessed (only if reason is RemoteConnectionClose)
/// </summary>
public NetPacketReader AdditionalData;
}
public interface INetEventListener
{
/// <summary>
/// New remote peer connected to host, or client connected to remote host
/// </summary>
/// <param name="peer">Connected peer object</param>
void OnPeerConnected(NetPeer peer);
/// <summary>
/// Peer disconnected
/// </summary>
/// <param name="peer">disconnected peer</param>
/// <param name="disconnectInfo">additional info about reason, errorCode or data received with disconnect message</param>
void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo);
/// <summary>
/// Network error (on send or receive)
/// </summary>
/// <param name="endPoint">From endPoint (can be null)</param>
/// <param name="socketError">Socket error</param>
void OnNetworkError(IPEndPoint endPoint, SocketError socketError);
/// <summary>
/// Received some data
/// </summary>
/// <param name="peer">From peer</param>
/// <param name="reader">DataReader containing all received data</param>
/// <param name="deliveryMethod">Type of received packet</param>
void OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod);
/// <summary>
/// Received unconnected message
/// </summary>
/// <param name="remoteEndPoint">From address (IP and Port)</param>
/// <param name="reader">Message data</param>
/// <param name="messageType">Message type (simple, discovery request or response)</param>
void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType);
/// <summary>
/// Latency information updated
/// </summary>
/// <param name="peer">Peer with updated latency</param>
/// <param name="latency">latency value in milliseconds</param>
void OnNetworkLatencyUpdate(NetPeer peer, int latency);
/// <summary>
/// On peer connection requested
/// </summary>
/// <param name="request">Request information (EndPoint, internal id, additional data)</param>
void OnConnectionRequest(ConnectionRequest request);
}
public interface IDeliveryEventListener
{
/// <summary>
/// On reliable message delivered
/// </summary>
/// <param name="peer"></param>
/// <param name="userData"></param>
void OnMessageDelivered(NetPeer peer, object userData);
}
public class EventBasedNetListener : INetEventListener, IDeliveryEventListener
{
public delegate void OnPeerConnected(NetPeer peer);
public delegate void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo);
public delegate void OnNetworkError(IPEndPoint endPoint, SocketError socketError);
public delegate void OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod);
public delegate void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType);
public delegate void OnNetworkLatencyUpdate(NetPeer peer, int latency);
public delegate void OnConnectionRequest(ConnectionRequest request);
public delegate void OnDeliveryEvent(NetPeer peer, object userData);
public event OnPeerConnected PeerConnectedEvent;
public event OnPeerDisconnected PeerDisconnectedEvent;
public event OnNetworkError NetworkErrorEvent;
public event OnNetworkReceive NetworkReceiveEvent;
public event OnNetworkReceiveUnconnected NetworkReceiveUnconnectedEvent;
public event OnNetworkLatencyUpdate NetworkLatencyUpdateEvent;
public event OnConnectionRequest ConnectionRequestEvent;
public event OnDeliveryEvent DeliveryEvent;
public void ClearPeerConnectedEvent()
{
PeerConnectedEvent = null;
}
public void ClearPeerDisconnectedEvent()
{
PeerDisconnectedEvent = null;
}
public void ClearNetworkErrorEvent()
{
NetworkErrorEvent = null;
}
public void ClearNetworkReceiveEvent()
{
NetworkReceiveEvent = null;
}
public void ClearNetworkReceiveUnconnectedEvent()
{
NetworkReceiveUnconnectedEvent = null;
}
public void ClearNetworkLatencyUpdateEvent()
{
NetworkLatencyUpdateEvent = null;
}
public void ClearConnectionRequestEvent()
{
ConnectionRequestEvent = null;
}
public void ClearDeliveryEvent()
{
DeliveryEvent = null;
}
void INetEventListener.OnPeerConnected(NetPeer peer)
{
if (PeerConnectedEvent != null)
PeerConnectedEvent(peer);
}
void INetEventListener.OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo)
{
if (PeerDisconnectedEvent != null)
PeerDisconnectedEvent(peer, disconnectInfo);
}
void INetEventListener.OnNetworkError(IPEndPoint endPoint, SocketError socketErrorCode)
{
if (NetworkErrorEvent != null)
NetworkErrorEvent(endPoint, socketErrorCode);
}
void INetEventListener.OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod)
{
if (NetworkReceiveEvent != null)
NetworkReceiveEvent(peer, reader, deliveryMethod);
}
void INetEventListener.OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType)
{
if (NetworkReceiveUnconnectedEvent != null)
NetworkReceiveUnconnectedEvent(remoteEndPoint, reader, messageType);
}
void INetEventListener.OnNetworkLatencyUpdate(NetPeer peer, int latency)
{
if (NetworkLatencyUpdateEvent != null)
NetworkLatencyUpdateEvent(peer, latency);
}
void INetEventListener.OnConnectionRequest(ConnectionRequest request)
{
if (ConnectionRequestEvent != null)
ConnectionRequestEvent(request);
}
void IDeliveryEventListener.OnMessageDelivered(NetPeer peer, object userData)
{
if (DeliveryEvent != null)
DeliveryEvent(peer, userData);
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/INetEventListener.cs.meta


fileFormatVersion: 2
guid: 28881074a6c781a439d38403a3182c2b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Layers.meta


fileFormatVersion: 2
guid: aebc2d698872c56429dc96aa2ddcd270
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

36
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Layers/Crc32cLayer.cs


using LiteNetLib.Utils;
using System;
namespace LiteNetLib.Layers
{
public sealed class Crc32cLayer : PacketLayerBase
{
public Crc32cLayer() : base(CRC32C.ChecksumSize)
{
}
public override void ProcessInboundPacket(ref byte[] data, ref int length)
{
if (length < NetConstants.HeaderSize + CRC32C.ChecksumSize)
{
NetDebug.WriteError("[NM] DataReceived size: bad!");
return;
}
int checksumPoint = length - CRC32C.ChecksumSize;
if (CRC32C.Compute(data, 0, checksumPoint) != BitConverter.ToUInt32(data, checksumPoint))
{
NetDebug.Write("[NM] DataReceived checksum: bad!");
return;
}
length -= CRC32C.ChecksumSize;
}
public override void ProcessOutBoundPacket(ref byte[] data, ref int offset, ref int length)
{
FastBitConverter.GetBytes(data, length, CRC32C.Compute(data, offset, length));
length += CRC32C.ChecksumSize;
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Layers/Crc32cLayer.cs.meta


fileFormatVersion: 2
guid: d658f1c6b66f5684780b95233d5fe00b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

15
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Layers/PacketLayerBase.cs


namespace LiteNetLib.Layers
{
public abstract class PacketLayerBase
{
public readonly int ExtraPacketSizeForLayer;
protected PacketLayerBase(int extraPacketSizeForLayer)
{
ExtraPacketSizeForLayer = extraPacketSizeForLayer;
}
public abstract void ProcessInboundPacket(ref byte[] data, ref int length);
public abstract void ProcessOutBoundPacket(ref byte[] data, ref int offset, ref int length);
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Layers/PacketLayerBase.cs.meta


fileFormatVersion: 2
guid: aba74192fa2edf74cac4992b18f7bc84
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

59
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Layers/XorEncryptLayer.cs


using System;
using System.Text;
namespace LiteNetLib.Layers
{
public class XorEncryptLayer : PacketLayerBase
{
private byte[] _byteKey;
public XorEncryptLayer() : base(0)
{
}
public XorEncryptLayer(byte[] key) : this()
{
SetKey(key);
}
public XorEncryptLayer(string key) : this()
{
SetKey(key);
}
public void SetKey(string key)
{
_byteKey = Encoding.UTF8.GetBytes(key);
}
public void SetKey(byte[] key)
{
if (_byteKey == null || _byteKey.Length != key.Length)
_byteKey = new byte[key.Length];
Buffer.BlockCopy(key, 0, _byteKey, 0, key.Length);
}
public override void ProcessInboundPacket(ref byte[] data, ref int length)
{
if (_byteKey == null)
return;
for (var i = 0; i < length; i++)
{
var offset = i % _byteKey.Length;
data[i] = (byte)(data[i] ^ _byteKey[offset]);
}
}
public override void ProcessOutBoundPacket(ref byte[] data, ref int offset, ref int length)
{
if (_byteKey == null)
return;
var cur = offset;
for (var i = 0; i < length; i++, cur++)
{
data[cur] = (byte)(data[cur] ^ _byteKey[i % _byteKey.Length]);
}
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Layers/XorEncryptLayer.cs.meta


fileFormatVersion: 2
guid: 0aca7a11bf01a5146a4e435b448bf342
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

7
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/LiteNetLib.csproj.meta


fileFormatVersion: 2
guid: 11c9a199da28e0144b82a7c9dbd440be
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

245
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NatPunchModule.cs


using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using LiteNetLib.Utils;
namespace LiteNetLib
{
public enum NatAddressType
{
Internal,
External
}
public interface INatPunchListener
{
void OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, string token);
void OnNatIntroductionSuccess(IPEndPoint targetEndPoint, NatAddressType type, string token);
}
public class EventBasedNatPunchListener : INatPunchListener
{
public delegate void OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, string token);
public delegate void OnNatIntroductionSuccess(IPEndPoint targetEndPoint, NatAddressType type, string token);
public event OnNatIntroductionRequest NatIntroductionRequest;
public event OnNatIntroductionSuccess NatIntroductionSuccess;
void INatPunchListener.OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, string token)
{
if(NatIntroductionRequest != null)
NatIntroductionRequest(localEndPoint, remoteEndPoint, token);
}
void INatPunchListener.OnNatIntroductionSuccess(IPEndPoint targetEndPoint, NatAddressType type, string token)
{
if (NatIntroductionSuccess != null)
NatIntroductionSuccess(targetEndPoint, type, token);
}
}
/// <summary>
/// Module for UDP NAT Hole punching operations. Can be accessed from NetManager
/// </summary>
public sealed class NatPunchModule
{
struct RequestEventData
{
public IPEndPoint LocalEndPoint;
public IPEndPoint RemoteEndPoint;
public string Token;
}
struct SuccessEventData
{
public IPEndPoint TargetEndPoint;
public NatAddressType Type;
public string Token;
}
class NatIntroduceRequestPacket
{
public IPEndPoint Internal { get; set; }
public string Token { get; set; }
}
class NatIntroduceResponsePacket
{
public IPEndPoint Internal { get; set; }
public IPEndPoint External { get; set; }
public string Token { get; set; }
}
class NatPunchPacket
{
public string Token { get; set; }
public bool IsExternal { get; set; }
}
private readonly NetSocket _socket;
private readonly Queue<RequestEventData> _requestEvents = new Queue<RequestEventData>();
private readonly Queue<SuccessEventData> _successEvents = new Queue<SuccessEventData>();
private readonly NetDataReader _cacheReader = new NetDataReader();
private readonly NetDataWriter _cacheWriter = new NetDataWriter();
private readonly NetPacketProcessor _netPacketProcessor = new NetPacketProcessor(MaxTokenLength);
private INatPunchListener _natPunchListener;
public const int MaxTokenLength = 256;
internal NatPunchModule(NetSocket socket)
{
_socket = socket;
_netPacketProcessor.SubscribeReusable<NatIntroduceResponsePacket>(OnNatIntroductionResponse);
_netPacketProcessor.SubscribeReusable<NatIntroduceRequestPacket, IPEndPoint>(OnNatIntroductionRequest);
_netPacketProcessor.SubscribeReusable<NatPunchPacket, IPEndPoint>(OnNatPunch);
}
internal void ProcessMessage(IPEndPoint senderEndPoint, NetPacket packet)
{
lock (_cacheReader)
{
_cacheReader.SetSource(packet.RawData, NetConstants.HeaderSize, packet.Size);
_netPacketProcessor.ReadAllPackets(_cacheReader, senderEndPoint);
}
}
public void Init(INatPunchListener listener)
{
_natPunchListener = listener;
}
private void Send<T>(T packet, IPEndPoint target) where T : class, new()
{
SocketError errorCode = 0;
_cacheWriter.Reset();
_cacheWriter.Put((byte)PacketProperty.NatMessage);
_netPacketProcessor.Write(_cacheWriter, packet);
_socket.SendTo(_cacheWriter.Data, 0, _cacheWriter.Length, target, ref errorCode);
}
public void NatIntroduce(
IPEndPoint hostInternal,
IPEndPoint hostExternal,
IPEndPoint clientInternal,
IPEndPoint clientExternal,
string additionalInfo)
{
var req = new NatIntroduceResponsePacket
{
Token = additionalInfo
};
//First packet (server) send to client
req.Internal = hostInternal;
req.External = hostExternal;
Send(req, clientExternal);
//Second packet (client) send to server
req.Internal = clientInternal;
req.External = clientExternal;
Send(req, hostExternal);
}
public void PollEvents()
{
if (_natPunchListener == null || (_successEvents.Count == 0 && _requestEvents.Count == 0))
return;
lock (_successEvents)
{
while (_successEvents.Count > 0)
{
var evt = _successEvents.Dequeue();
_natPunchListener.OnNatIntroductionSuccess(
evt.TargetEndPoint,
evt.Type,
evt.Token);
}
}
lock (_requestEvents)
{
while (_requestEvents.Count > 0)
{
var evt = _requestEvents.Dequeue();
_natPunchListener.OnNatIntroductionRequest(evt.LocalEndPoint, evt.RemoteEndPoint, evt.Token);
}
}
}
public void SendNatIntroduceRequest(string host, int port, string additionalInfo)
{
SendNatIntroduceRequest(NetUtils.MakeEndPoint(host, port), additionalInfo);
}
public void SendNatIntroduceRequest(IPEndPoint masterServerEndPoint, string additionalInfo)
{
//prepare outgoing data
string networkIp = NetUtils.GetLocalIp(LocalAddrType.IPv4);
if (string.IsNullOrEmpty(networkIp))
{
networkIp = NetUtils.GetLocalIp(LocalAddrType.IPv6);
}
Send(
new NatIntroduceRequestPacket
{
Internal = NetUtils.MakeEndPoint(networkIp, _socket.LocalPort),
Token = additionalInfo
},
masterServerEndPoint);
}
//We got request and must introduce
private void OnNatIntroductionRequest(NatIntroduceRequestPacket req, IPEndPoint senderEndPoint)
{
lock (_requestEvents)
{
_requestEvents.Enqueue(new RequestEventData
{
LocalEndPoint = req.Internal,
RemoteEndPoint = senderEndPoint,
Token = req.Token
});
}
}
//We got introduce and must punch
private void OnNatIntroductionResponse(NatIntroduceResponsePacket req)
{
NetDebug.Write(NetLogLevel.Trace, "[NAT] introduction received");
// send internal punch
var punchPacket = new NatPunchPacket {Token = req.Token};
Send(punchPacket, req.Internal);
NetDebug.Write(NetLogLevel.Trace, "[NAT] internal punch sent to " + req.Internal);
// hack for some routers
SocketError errorCode = 0;
_socket.Ttl = 2;
_socket.SendTo(new[] { (byte)PacketProperty.Empty }, 0, 1, req.External, ref errorCode);
// send external punch
_socket.Ttl = NetConstants.SocketTTL;
punchPacket.IsExternal = true;
Send(punchPacket, req.External);
NetDebug.Write(NetLogLevel.Trace, "[NAT] external punch sent to " + req.External);
}
//We got punch and can connect
private void OnNatPunch(NatPunchPacket req, IPEndPoint senderEndPoint)
{
//Read info
NetDebug.Write(NetLogLevel.Trace, "[NAT] punch received from {0} - additional info: {1}",
senderEndPoint, req.Token);
//Release punch success to client; enabling him to Connect() to Sender if token is ok
lock (_successEvents)
{
_successEvents.Enqueue(new SuccessEventData
{
TargetEndPoint = senderEndPoint,
Type = req.IsExternal ? NatAddressType.External : NatAddressType.Internal,
Token = req.Token
});
}
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NatPunchModule.cs.meta


fileFormatVersion: 2
guid: a7d2dee632c79624ea2b1909415f2755
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

72
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetConstants.cs


namespace LiteNetLib
{
/// <summary>
/// Sending method type
/// </summary>
public enum DeliveryMethod : byte
{
/// <summary>
/// Unreliable. Packets can be dropped, can be duplicated, can arrive without order.
/// </summary>
Unreliable = 4,
/// <summary>
/// Reliable. Packets won't be dropped, won't be duplicated, can arrive without order.
/// </summary>
ReliableUnordered = 0,
/// <summary>
/// Unreliable. Packets can be dropped, won't be duplicated, will arrive in order.
/// </summary>
Sequenced = 1,
/// <summary>
/// Reliable and ordered. Packets won't be dropped, won't be duplicated, will arrive in order.
/// </summary>
ReliableOrdered = 2,
/// <summary>
/// Reliable only last packet. Packets can be dropped (except the last one), won't be duplicated, will arrive in order.
/// </summary>
ReliableSequenced = 3
}
/// <summary>
/// Network constants. Can be tuned from sources for your purposes.
/// </summary>
public static class NetConstants
{
//can be tuned
public const int DefaultWindowSize = 64;
public const int SocketBufferSize = 1024 * 1024; //1mb
public const int SocketTTL = 255;
public const int HeaderSize = 1;
public const int ChanneledHeaderSize = 4;
public const int FragmentHeaderSize = 6;
public const int FragmentedHeaderTotalSize = ChanneledHeaderSize + FragmentHeaderSize;
public const ushort MaxSequence = 32768;
public const ushort HalfMaxSequence = MaxSequence / 2;
//protocol
internal const int ProtocolId = 11;
internal const int MaxUdpHeaderSize = 68;
internal static readonly int[] PossibleMtu =
{
576 - MaxUdpHeaderSize, //minimal
1232 - MaxUdpHeaderSize,
1460 - MaxUdpHeaderSize, //google cloud
1472 - MaxUdpHeaderSize, //VPN
1492 - MaxUdpHeaderSize, //Ethernet with LLC and SNAP, PPPoE (RFC 1042)
1500 - MaxUdpHeaderSize //Ethernet II (RFC 1191)
};
internal static readonly int MaxPacketSize = PossibleMtu[PossibleMtu.Length - 1];
//peer specific
public const byte MaxConnectionNumber = 4;
public const int PacketPoolSize = 1000;
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetConstants.cs.meta


fileFormatVersion: 2
guid: fff3c8002deb1964b8adfb05e6d70f9f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

92
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetDebug.cs


using System;
using System.Diagnostics;
namespace LiteNetLib
{
public class InvalidPacketException : ArgumentException
{
public InvalidPacketException(string message) : base(message)
{
}
}
public class TooBigPacketException : InvalidPacketException
{
public TooBigPacketException(string message) : base(message)
{
}
}
public enum NetLogLevel
{
Warning,
Error,
Trace,
Info
}
/// <summary>
/// Interface to implement for your own logger
/// </summary>
public interface INetLogger
{
void WriteNet(NetLogLevel level, string str, params object[] args);
}
/// <summary>
/// Static class for defining your own LiteNetLib logger instead of Console.WriteLine
/// or Debug.Log if compiled with UNITY flag
/// </summary>
public static class NetDebug
{
public static INetLogger Logger = null;
private static readonly object DebugLogLock = new object();
private static void WriteLogic(NetLogLevel logLevel, string str, params object[] args)
{
lock (DebugLogLock)
{
if (Logger == null)
{
#if UNITY_4 || UNITY_5 || UNITY_5_3_OR_NEWER
UnityEngine.Debug.Log(string.Format(str, args));
#else
Console.WriteLine(str, args);
#endif
}
else
{
Logger.WriteNet(logLevel, str, args);
}
}
}
[Conditional("DEBUG_MESSAGES")]
internal static void Write(string str, params object[] args)
{
WriteLogic(NetLogLevel.Trace, str, args);
}
[Conditional("DEBUG_MESSAGES")]
internal static void Write(NetLogLevel level, string str, params object[] args)
{
WriteLogic(level, str, args);
}
[Conditional("DEBUG_MESSAGES"), Conditional("DEBUG")]
internal static void WriteForce(string str, params object[] args)
{
WriteLogic(NetLogLevel.Trace, str, args);
}
[Conditional("DEBUG_MESSAGES"), Conditional("DEBUG")]
internal static void WriteForce(NetLogLevel level, string str, params object[] args)
{
WriteLogic(level, str, args);
}
internal static void WriteError(string str, params object[] args)
{
WriteLogic(NetLogLevel.Error, str, args);
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetDebug.cs.meta


fileFormatVersion: 2
guid: 164aa985149ec81468dbb9bed6d746f0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

1001
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetManager.cs
文件差异内容过多而无法显示
查看文件

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetManager.cs.meta


fileFormatVersion: 2
guid: 68a7d55eeb581134cb7700df070236f7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

276
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetPacket.cs


using System;
using System.Net;
using LiteNetLib.Utils;
namespace LiteNetLib
{
internal enum PacketProperty : byte
{
Unreliable,
Channeled,
Ack,
Ping,
Pong,
ConnectRequest,
ConnectAccept,
Disconnect,
UnconnectedMessage,
MtuCheck,
MtuOk,
Broadcast,
Merged,
ShutdownOk,
PeerNotFound,
InvalidProtocol,
NatMessage,
Empty
}
internal sealed class NetPacket
{
private static readonly int LastProperty = Enum.GetValues(typeof(PacketProperty)).Length;
private static readonly int[] HeaderSizes;
static NetPacket()
{
HeaderSizes = new int[LastProperty+1];
for (int i = 0; i < HeaderSizes.Length; i++)
{
switch ((PacketProperty)i)
{
case PacketProperty.Channeled:
case PacketProperty.Ack:
HeaderSizes[i] = NetConstants.ChanneledHeaderSize;
break;
case PacketProperty.Ping:
HeaderSizes[i] = NetConstants.HeaderSize + 2;
break;
case PacketProperty.ConnectRequest:
HeaderSizes[i] = NetConnectRequestPacket.HeaderSize;
break;
case PacketProperty.ConnectAccept:
HeaderSizes[i] = NetConnectAcceptPacket.Size;
break;
case PacketProperty.Disconnect:
HeaderSizes[i] = NetConstants.HeaderSize + 8;
break;
case PacketProperty.Pong:
HeaderSizes[i] = NetConstants.HeaderSize + 10;
break;
default:
HeaderSizes[i] = NetConstants.HeaderSize;
break;
}
}
}
//Header
public PacketProperty Property
{
get { return (PacketProperty)(RawData[0] & 0x1F); }
set { RawData[0] = (byte)((RawData[0] & 0xE0) | (byte)value); }
}
public byte ConnectionNumber
{
get { return (byte)((RawData[0] & 0x60) >> 5); }
set { RawData[0] = (byte) ((RawData[0] & 0x9F) | (value << 5)); }
}
public ushort Sequence
{
get { return BitConverter.ToUInt16(RawData, 1); }
set { FastBitConverter.GetBytes(RawData, 1, value); }
}
public bool IsFragmented
{
get { return (RawData[0] & 0x80) != 0; }
}
public void MarkFragmented()
{
RawData[0] |= 0x80; //set first bit
}
public byte ChannelId
{
get { return RawData[3]; }
set { RawData[3] = value; }
}
public ushort FragmentId
{
get { return BitConverter.ToUInt16(RawData, 4); }
set { FastBitConverter.GetBytes(RawData, 4, value); }
}
public ushort FragmentPart
{
get { return BitConverter.ToUInt16(RawData, 6); }
set { FastBitConverter.GetBytes(RawData, 6, value); }
}
public ushort FragmentsTotal
{
get { return BitConverter.ToUInt16(RawData, 8); }
set { FastBitConverter.GetBytes(RawData, 8, value); }
}
//Data
public byte[] RawData;
public int Size;
//Delivery
public object UserData;
//Pool node
public NetPacket Next;
public NetPacket(int size)
{
RawData = new byte[size];
Size = size;
}
public NetPacket(PacketProperty property, int size)
{
size += GetHeaderSize(property);
RawData = new byte[size];
Property = property;
Size = size;
}
public static int GetHeaderSize(PacketProperty property)
{
return HeaderSizes[(int)property];
}
public int GetHeaderSize()
{
return HeaderSizes[RawData[0] & 0x1F];
}
//Packet constructor from byte array
public bool FromBytes(byte[] data, int start, int packetSize)
{
//Reading property
byte property = (byte)(data[start] & 0x1F);
bool fragmented = (data[start] & 0x80) != 0;
int headerSize = HeaderSizes[property];
if (property > LastProperty || packetSize < headerSize ||
(fragmented && packetSize < headerSize + NetConstants.FragmentHeaderSize) ||
data.Length < start + packetSize)
{
return false;
}
Buffer.BlockCopy(data, start, RawData, 0, packetSize);
Size = (ushort)packetSize;
return true;
}
}
internal sealed class NetConnectRequestPacket
{
public const int HeaderSize = 14;
public readonly long ConnectionTime;
public readonly byte ConnectionNumber;
public readonly byte[] TargetAddress;
public readonly NetDataReader Data;
private NetConnectRequestPacket(long connectionTime, byte connectionNumber, byte[] targetAddress, NetDataReader data)
{
ConnectionTime = connectionTime;
ConnectionNumber = connectionNumber;
TargetAddress = targetAddress;
Data = data;
}
public static int GetProtocolId(NetPacket packet)
{
return BitConverter.ToInt32(packet.RawData, 1);
}
public static NetConnectRequestPacket FromData(NetPacket packet)
{
if (packet.ConnectionNumber >= NetConstants.MaxConnectionNumber)
return null;
//Getting new id for peer
long connectionId = BitConverter.ToInt64(packet.RawData, 5);
//Get target address
int addrSize = packet.RawData[13];
if (addrSize != 16 && addrSize != 28)
return null;
byte[] addressBytes = new byte[addrSize];
Buffer.BlockCopy(packet.RawData, 14, addressBytes, 0, addrSize);
// Read data and create request
var reader = new NetDataReader(null, 0, 0);
if (packet.Size > HeaderSize+addrSize)
reader.SetSource(packet.RawData, HeaderSize + addrSize, packet.Size);
return new NetConnectRequestPacket(connectionId, packet.ConnectionNumber, addressBytes, reader);
}
public static NetPacket Make(NetDataWriter connectData, SocketAddress addressBytes, long connectId)
{
//Make initial packet
var packet = new NetPacket(PacketProperty.ConnectRequest, connectData.Length+addressBytes.Size);
//Add data
FastBitConverter.GetBytes(packet.RawData, 1, NetConstants.ProtocolId);
FastBitConverter.GetBytes(packet.RawData, 5, connectId);
packet.RawData[13] = (byte)addressBytes.Size;
for (int i = 0; i < addressBytes.Size; i++)
packet.RawData[14+i] = addressBytes[i];
Buffer.BlockCopy(connectData.Data, 0, packet.RawData, 14+addressBytes.Size, connectData.Length);
return packet;
}
}
internal sealed class NetConnectAcceptPacket
{
public const int Size = 11;
public readonly long ConnectionId;
public readonly byte ConnectionNumber;
public readonly bool IsReusedPeer;
private NetConnectAcceptPacket(long connectionId, byte connectionNumber, bool isReusedPeer)
{
ConnectionId = connectionId;
ConnectionNumber = connectionNumber;
IsReusedPeer = isReusedPeer;
}
public static NetConnectAcceptPacket FromData(NetPacket packet)
{
if (packet.Size > Size)
return null;
long connectionId = BitConverter.ToInt64(packet.RawData, 1);
//check connect num
byte connectionNumber = packet.RawData[9];
if (connectionNumber >= NetConstants.MaxConnectionNumber)
return null;
//check reused flag
byte isReused = packet.RawData[10];
if (isReused > 1)
return null;
return new NetConnectAcceptPacket(connectionId, connectionNumber, isReused == 1);
}
public static NetPacket Make(long connectId, byte connectNum, bool reusedPeer)
{
var packet = new NetPacket(PacketProperty.ConnectAccept, 0);
FastBitConverter.GetBytes(packet.RawData, 1, connectId);
packet.RawData[9] = connectNum;
packet.RawData[10] = (byte)(reusedPeer ? 1 : 0);
return packet;
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetPacket.cs.meta


fileFormatVersion: 2
guid: 9bbfda42bbf0c64468c913e03e91b6f5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

74
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetPacketPool.cs


using System;
using System.Threading;
namespace LiteNetLib
{
internal sealed class NetPacketPool
{
private NetPacket _head;
private int _count;
public NetPacket GetWithData(PacketProperty property, byte[] data, int start, int length)
{
int headerSize = NetPacket.GetHeaderSize(property);
NetPacket packet = GetPacket(length + headerSize);
packet.Property = property;
Buffer.BlockCopy(data, start, packet.RawData, headerSize, length);
return packet;
}
//Get packet with size
public NetPacket GetWithProperty(PacketProperty property, int size)
{
NetPacket packet = GetPacket(size + NetPacket.GetHeaderSize(property));
packet.Property = property;
return packet;
}
public NetPacket GetWithProperty(PacketProperty property)
{
NetPacket packet = GetPacket(NetPacket.GetHeaderSize(property));
packet.Property = property;
return packet;
}
public NetPacket GetPacket(int size)
{
if (size > NetConstants.MaxPacketSize)
return new NetPacket(size);
NetPacket packet;
do
{
packet = _head;
if (packet == null)
return new NetPacket(size);
} while (packet != Interlocked.CompareExchange(ref _head, packet.Next, packet));
_count--;
packet.Size = size;
if (packet.RawData.Length < size)
packet.RawData = new byte[size];
return packet;
}
public void Recycle(NetPacket packet)
{
if (packet.RawData.Length > NetConstants.MaxPacketSize || _count >= NetConstants.PacketPoolSize)
{
//Don't pool big packets. Save memory
return;
}
_count++;
//Clean fragmented flag
packet.RawData[0] = 0;
do
{
packet.Next = _head;
} while (packet.Next != Interlocked.CompareExchange(ref _head, packet, packet.Next));
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetPacketPool.cs.meta


fileFormatVersion: 2
guid: c9de9278957067a47b6fb32e6edcf6a8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

1001
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetPeer.cs
文件差异内容过多而无法显示
查看文件

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetPeer.cs.meta


fileFormatVersion: 2
guid: 7d8b1e2f1951cd64fa5f3ddaf623f006
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

483
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetSocket.cs


#if UNITY_5_3_OR_NEWER
#define UNITY
#if UNITY_IOS && !UNITY_EDITOR
using UnityEngine;
#endif
#endif
#if NETSTANDARD || NETCOREAPP
using System.Runtime.InteropServices;
#endif
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace LiteNetLib
{
#if UNITY_IOS && !UNITY_EDITOR
public class UnitySocketFix : MonoBehaviour
{
internal IPAddress BindAddrIPv4;
internal IPAddress BindAddrIPv6;
internal bool Reuse;
internal IPv6Mode IPv6;
internal int Port;
internal bool Paused;
internal NetSocket Socket;
private void Update()
{
if (Socket == null)
Destroy(gameObject);
}
private void OnApplicationPause(bool pause)
{
if (Socket == null)
return;
if (pause)
{
Paused = true;
Socket.Close(true);
}
else if (Paused)
{
if (!Socket.Bind(BindAddrIPv4, BindAddrIPv6, Port, Reuse, IPv6))
{
NetDebug.WriteError("[S] Cannot restore connection \"{0}\",\"{1}\" port {2}", BindAddrIPv4, BindAddrIPv6, Port);
Socket.OnErrorRestore();
}
}
}
}
#endif
internal interface INetSocketListener
{
void OnMessageReceived(byte[] data, int length, SocketError errorCode, IPEndPoint remoteEndPoint);
}
internal sealed class NetSocket
{
public const int ReceivePollingTime = 500000; //0.5 second
private Socket _udpSocketv4;
private Socket _udpSocketv6;
private Thread _threadv4;
private Thread _threadv6;
private readonly INetSocketListener _listener;
private const int SioUdpConnreset = -1744830452; //SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12
private static readonly IPAddress MulticastAddressV6 = IPAddress.Parse("ff02::1");
internal static readonly bool IPv6Support;
#if UNITY_IOS && !UNITY_EDITOR
private UnitySocketFix _unitySocketFix;
public void OnErrorRestore()
{
Close(false);
_listener.OnMessageReceived(null, 0, SocketError.NotConnected, new IPEndPoint(0,0));
}
#endif
public int LocalPort { get; private set; }
public volatile bool IsRunning;
public short Ttl
{
get
{
#if UNITY_SWITCH
return 0;
#else
if (_udpSocketv4.AddressFamily == AddressFamily.InterNetworkV6)
return (short)_udpSocketv4.GetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.HopLimit);
return _udpSocketv4.Ttl;
#endif
}
set
{
#if !UNITY_SWITCH
if (_udpSocketv4.AddressFamily == AddressFamily.InterNetworkV6)
_udpSocketv4.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.HopLimit, value);
else
_udpSocketv4.Ttl = value;
#endif
}
}
static NetSocket()
{
#if DISABLE_IPV6 || (!UNITY_EDITOR && ENABLE_IL2CPP && !UNITY_2018_3_OR_NEWER)
IPv6Support = false;
#elif !UNITY_2019_1_OR_NEWER && !UNITY_2018_4_OR_NEWER && (!UNITY_EDITOR && ENABLE_IL2CPP && UNITY_2018_3_OR_NEWER)
string version = UnityEngine.Application.unityVersion;
IPv6Support = Socket.OSSupportsIPv6 && int.Parse(version.Remove(version.IndexOf('f')).Split('.')[2]) >= 6;
#elif UNITY_2018_2_OR_NEWER
IPv6Support = Socket.OSSupportsIPv6;
#elif UNITY
#pragma warning disable 618
IPv6Support = Socket.SupportsIPv6;
#pragma warning restore 618
#else
IPv6Support = Socket.OSSupportsIPv6;
#endif
}
public NetSocket(INetSocketListener listener)
{
_listener = listener;
}
private bool IsActive()
{
#if UNITY_IOS && !UNITY_EDITOR
var unitySocketFix = _unitySocketFix; //save for multithread
if (unitySocketFix != null && unitySocketFix.Paused)
return false;
#endif
return IsRunning;
}
private void ReceiveLogic(object state)
{
Socket socket = (Socket)state;
EndPoint bufferEndPoint = new IPEndPoint(socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0);
byte[] receiveBuffer = new byte[NetConstants.MaxPacketSize];
while (IsActive())
{
int result;
//Reading data
try
{
if (socket.Available == 0 && !socket.Poll(ReceivePollingTime, SelectMode.SelectRead))
continue;
result = socket.ReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None,
ref bufferEndPoint);
}
catch (SocketException ex)
{
switch (ex.SocketErrorCode)
{
#if UNITY_IOS && !UNITY_EDITOR
case SocketError.NotConnected:
#endif
case SocketError.Interrupted:
case SocketError.NotSocket:
return;
case SocketError.ConnectionReset:
case SocketError.MessageSize:
case SocketError.TimedOut:
NetDebug.Write(NetLogLevel.Trace, "[R]Ignored error: {0} - {1}",
(int)ex.SocketErrorCode, ex.ToString());
break;
default:
NetDebug.WriteError("[R]Error code: {0} - {1}", (int)ex.SocketErrorCode,
ex.ToString());
_listener.OnMessageReceived(null, 0, ex.SocketErrorCode, (IPEndPoint)bufferEndPoint);
break;
}
continue;
}
catch (ObjectDisposedException)
{
return;
}
//All ok!
NetDebug.Write(NetLogLevel.Trace, "[R]Received data from {0}, result: {1}", bufferEndPoint.ToString(), result);
_listener.OnMessageReceived(receiveBuffer, result, 0, (IPEndPoint)bufferEndPoint);
}
}
public bool Bind(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool reuseAddress, IPv6Mode ipv6Mode)
{
if (IsActive())
return false;
bool dualMode = ipv6Mode == IPv6Mode.DualMode && IPv6Support;
_udpSocketv4 = new Socket(
dualMode ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork,
SocketType.Dgram,
ProtocolType.Udp);
if (!BindSocket(_udpSocketv4, new IPEndPoint(dualMode ? addressIPv6 : addressIPv4, port), reuseAddress, ipv6Mode))
return false;
LocalPort = ((IPEndPoint) _udpSocketv4.LocalEndPoint).Port;
#if UNITY_IOS && !UNITY_EDITOR
if (_unitySocketFix == null)
{
var unityFixObj = new GameObject("LiteNetLib_UnitySocketFix");
GameObject.DontDestroyOnLoad(unityFixObj);
_unitySocketFix = unityFixObj.AddComponent<UnitySocketFix>();
_unitySocketFix.Socket = this;
_unitySocketFix.BindAddrIPv4 = addressIPv4;
_unitySocketFix.BindAddrIPv6 = addressIPv6;
_unitySocketFix.Reuse = reuseAddress;
_unitySocketFix.Port = LocalPort;
_unitySocketFix.IPv6 = ipv6Mode;
}
else
{
_unitySocketFix.Paused = false;
}
#endif
if (dualMode)
_udpSocketv6 = _udpSocketv4;
IsRunning = true;
_threadv4 = new Thread(ReceiveLogic)
{
Name = "SocketThreadv4(" + LocalPort + ")",
IsBackground = true
};
_threadv4.Start(_udpSocketv4);
//Check IPv6 support
if (!IPv6Support || ipv6Mode != IPv6Mode.SeparateSocket)
return true;
_udpSocketv6 = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
//Use one port for two sockets
if (BindSocket(_udpSocketv6, new IPEndPoint(addressIPv6, LocalPort), reuseAddress, ipv6Mode))
{
_threadv6 = new Thread(ReceiveLogic)
{
Name = "SocketThreadv6(" + LocalPort + ")",
IsBackground = true
};
_threadv6.Start(_udpSocketv6);
}
return true;
}
private bool BindSocket(Socket socket, IPEndPoint ep, bool reuseAddress, IPv6Mode ipv6Mode)
{
//Setup socket
socket.ReceiveTimeout = 500;
socket.SendTimeout = 500;
socket.ReceiveBufferSize = NetConstants.SocketBufferSize;
socket.SendBufferSize = NetConstants.SocketBufferSize;
#if !UNITY || UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
#if NETSTANDARD || NETCOREAPP
if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
#endif
try
{
socket.IOControl(SioUdpConnreset, new byte[] { 0 }, null);
}
catch
{
//ignored
}
#endif
try
{
socket.ExclusiveAddressUse = !reuseAddress;
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, reuseAddress);
}
catch
{
//Unity with IL2CPP throws an exception here, it doesn't matter in most cases so just ignore it
}
if (socket.AddressFamily == AddressFamily.InterNetwork)
{
Ttl = NetConstants.SocketTTL;
#if NETSTANDARD || NETCOREAPP
if(!RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
#endif
try { socket.DontFragment = true; }
catch (SocketException e)
{
NetDebug.WriteError("[B]DontFragment error: {0}", e.SocketErrorCode);
}
try { socket.EnableBroadcast = true; }
catch (SocketException e)
{
NetDebug.WriteError("[B]Broadcast error: {0}", e.SocketErrorCode);
}
}
else //IPv6 specific
{
if (ipv6Mode == IPv6Mode.DualMode)
{
try
{
//Disable IPv6 only mode
socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
}
catch(Exception e)
{
NetDebug.WriteError("[B]Bind exception (dualmode setting): {0}", e.ToString());
}
}
}
//Bind
try
{
socket.Bind(ep);
NetDebug.Write(NetLogLevel.Trace, "[B]Successfully binded to port: {0}", ((IPEndPoint)socket.LocalEndPoint).Port);
//join multicast
if (socket.AddressFamily == AddressFamily.InterNetworkV6)
{
try
{
#if !UNITY
socket.SetSocketOption(
SocketOptionLevel.IPv6,
SocketOptionName.AddMembership,
new IPv6MulticastOption(MulticastAddressV6));
#endif
}
catch (Exception)
{
// Unity3d throws exception - ignored
}
}
}
catch (SocketException bindException)
{
switch (bindException.SocketErrorCode)
{
//IPv6 bind fix
case SocketError.AddressAlreadyInUse:
if (socket.AddressFamily == AddressFamily.InterNetworkV6 && ipv6Mode != IPv6Mode.DualMode)
{
try
{
//Set IPv6Only
socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, true);
socket.Bind(ep);
}
#if UNITY_2018_3_OR_NEWER
catch (SocketException ex)
{
//because its fixed in 2018_3
NetDebug.WriteError("[B]Bind exception: {0}, errorCode: {1}", ex.ToString(), ex.SocketErrorCode);
#else
catch(SocketException)
{
#endif
return false;
}
return true;
}
break;
//hack for iOS (Unity3D)
case SocketError.AddressFamilyNotSupported:
return true;
}
NetDebug.WriteError("[B]Bind exception: {0}, errorCode: {1}", bindException.ToString(), bindException.SocketErrorCode);
return false;
}
return true;
}
public bool SendBroadcast(byte[] data, int offset, int size, int port)
{
if (!IsActive())
return false;
bool broadcastSuccess = false;
bool multicastSuccess = false;
try
{
broadcastSuccess = _udpSocketv4.SendTo(
data,
offset,
size,
SocketFlags.None,
new IPEndPoint(IPAddress.Broadcast, port)) > 0;
if (_udpSocketv6 != null)
{
multicastSuccess = _udpSocketv6.SendTo(
data,
offset,
size,
SocketFlags.None,
new IPEndPoint(MulticastAddressV6, port)) > 0;
}
}
catch (Exception ex)
{
NetDebug.WriteError("[S][MCAST]" + ex);
return broadcastSuccess;
}
return broadcastSuccess || multicastSuccess;
}
public int SendTo(byte[] data, int offset, int size, IPEndPoint remoteEndPoint, ref SocketError errorCode)
{
if (!IsActive())
return 0;
try
{
var socket = _udpSocketv4;
if (remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6 && IPv6Support)
socket = _udpSocketv6;
int result = socket.SendTo(data, offset, size, SocketFlags.None, remoteEndPoint);
NetDebug.Write(NetLogLevel.Trace, "[S]Send packet to {0}, result: {1}", remoteEndPoint, result);
return result;
}
catch (SocketException ex)
{
switch (ex.SocketErrorCode)
{
case SocketError.NoBufferSpaceAvailable:
case SocketError.Interrupted:
return 0;
case SocketError.MessageSize: //do nothing
break;
default:
NetDebug.WriteError("[S]" + ex);
break;
}
errorCode = ex.SocketErrorCode;
return -1;
}
catch (Exception ex)
{
NetDebug.WriteError("[S]" + ex);
return -1;
}
}
public void Close(bool suspend)
{
if (!suspend)
{
IsRunning = false;
#if UNITY_IOS && !UNITY_EDITOR
_unitySocketFix.Socket = null;
_unitySocketFix = null;
#endif
}
//cleanup dual mode
if (_udpSocketv4 == _udpSocketv6)
_udpSocketv6 = null;
if (_udpSocketv4 != null)
_udpSocketv4.Close();
if (_udpSocketv6 != null)
_udpSocketv6.Close();
_udpSocketv4 = null;
_udpSocketv6 = null;
if (_threadv4 != null && _threadv4 != Thread.CurrentThread)
_threadv4.Join();
if (_threadv6 != null && _threadv6 != Thread.CurrentThread)
_threadv6.Join();
_threadv4 = null;
_threadv6 = null;
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetSocket.cs.meta


fileFormatVersion: 2
guid: 1dbea90b528ba0448a61b7222dab0657
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

39
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetStatistics.cs


namespace LiteNetLib
{
public sealed class NetStatistics
{
public ulong PacketsSent;
public ulong PacketsReceived;
public ulong BytesSent;
public ulong BytesReceived;
public ulong PacketLoss;
public ulong PacketLossPercent
{
get { return PacketsSent == 0 ? 0 : PacketLoss * 100 / PacketsSent; }
}
public ulong SequencedPacketLoss;
public void Reset()
{
PacketsSent = 0;
PacketsReceived = 0;
BytesSent = 0;
BytesReceived = 0;
PacketLoss = 0;
}
public override string ToString()
{
return
string.Format(
"BytesReceived: {0}\nPacketsReceived: {1}\nBytesSent: {2}\nPacketsSent: {3}\nPacketLoss: {4}\nPacketLossPercent: {5}\n",
BytesReceived,
PacketsReceived,
BytesSent,
PacketsSent,
PacketLoss,
PacketLossPercent);
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetStatistics.cs.meta


fileFormatVersion: 2
guid: bdf18575c3cbb17488b16fe4463e64c4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

197
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetUtils.cs


using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
namespace LiteNetLib
{
/// <summary>
/// Address type that you want to receive from NetUtils.GetLocalIp method
/// </summary>
[Flags]
public enum LocalAddrType
{
IPv4 = 1,
IPv6 = 2,
All = IPv4 | IPv6
}
/// <summary>
/// Some specific network utilities
/// </summary>
public static class NetUtils
{
public static IPEndPoint MakeEndPoint(string hostStr, int port)
{
return new IPEndPoint(ResolveAddress(hostStr), port);
}
public static IPAddress ResolveAddress(string hostStr)
{
if(hostStr == "localhost")
return IPAddress.Loopback;
IPAddress ipAddress;
if (!IPAddress.TryParse(hostStr, out ipAddress))
{
if (NetSocket.IPv6Support)
ipAddress = ResolveAddress(hostStr, AddressFamily.InterNetworkV6);
if (ipAddress == null)
ipAddress = ResolveAddress(hostStr, AddressFamily.InterNetwork);
}
if (ipAddress == null)
throw new ArgumentException("Invalid address: " + hostStr);
return ipAddress;
}
private static IPAddress ResolveAddress(string hostStr, AddressFamily addressFamily)
{
IPAddress[] addresses = ResolveAddresses(hostStr);
foreach (IPAddress ip in addresses)
{
if (ip.AddressFamily == addressFamily)
{
return ip;
}
}
return null;
}
private static IPAddress[] ResolveAddresses(string hostStr)
{
#if NETSTANDARD || NETCOREAPP
var hostTask = Dns.GetHostEntryAsync(hostStr);
hostTask.GetAwaiter().GetResult();
var host = hostTask.Result;
#else
var host = Dns.GetHostEntry(hostStr);
#endif
return host.AddressList;
}
/// <summary>
/// Get all local ip addresses
/// </summary>
/// <param name="addrType">type of address (IPv4, IPv6 or both)</param>
/// <returns>List with all local ip addresses</returns>
public static List<string> GetLocalIpList(LocalAddrType addrType)
{
List<string> targetList = new List<string>();
GetLocalIpList(targetList, addrType);
return targetList;
}
/// <summary>
/// Get all local ip addresses (non alloc version)
/// </summary>
/// <param name="targetList">result list</param>
/// <param name="addrType">type of address (IPv4, IPv6 or both)</param>
public static void GetLocalIpList(IList<string> targetList, LocalAddrType addrType)
{
bool ipv4 = (addrType & LocalAddrType.IPv4) == LocalAddrType.IPv4;
bool ipv6 = (addrType & LocalAddrType.IPv6) == LocalAddrType.IPv6;
try
{
foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
//Skip loopback and disabled network interfaces
if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback ||
ni.OperationalStatus != OperationalStatus.Up)
continue;
var ipProps = ni.GetIPProperties();
//Skip address without gateway
if (ipProps.GatewayAddresses.Count == 0)
continue;
foreach (UnicastIPAddressInformation ip in ipProps.UnicastAddresses)
{
var address = ip.Address;
if ((ipv4 && address.AddressFamily == AddressFamily.InterNetwork) ||
(ipv6 && address.AddressFamily == AddressFamily.InterNetworkV6))
targetList.Add(address.ToString());
}
}
}
catch
{
//ignored
}
//Fallback mode (unity android)
if (targetList.Count == 0)
{
IPAddress[] addresses = ResolveAddresses(Dns.GetHostName());
foreach (IPAddress ip in addresses)
{
if((ipv4 && ip.AddressFamily == AddressFamily.InterNetwork) ||
(ipv6 && ip.AddressFamily == AddressFamily.InterNetworkV6))
targetList.Add(ip.ToString());
}
}
if (targetList.Count == 0)
{
if(ipv4)
targetList.Add("127.0.0.1");
if(ipv6)
targetList.Add("::1");
}
}
private static readonly List<string> IpList = new List<string>();
/// <summary>
/// Get first detected local ip address
/// </summary>
/// <param name="addrType">type of address (IPv4, IPv6 or both)</param>
/// <returns>IP address if available. Else - string.Empty</returns>
public static string GetLocalIp(LocalAddrType addrType)
{
lock (IpList)
{
IpList.Clear();
GetLocalIpList(IpList, addrType);
return IpList.Count == 0 ? string.Empty : IpList[0];
}
}
// ===========================================
// Internal and debug log related stuff
// ===========================================
internal static void PrintInterfaceInfos()
{
NetDebug.WriteForce(NetLogLevel.Info, "IPv6Support: {0}", NetSocket.IPv6Support);
try
{
foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
{
foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
{
if (ip.Address.AddressFamily == AddressFamily.InterNetwork ||
ip.Address.AddressFamily == AddressFamily.InterNetworkV6)
{
NetDebug.WriteForce(
NetLogLevel.Info,
"Interface: {0}, Type: {1}, Ip: {2}, OpStatus: {3}",
ni.Name,
ni.NetworkInterfaceType.ToString(),
ip.Address.ToString(),
ni.OperationalStatus.ToString());
}
}
}
}
catch (Exception e)
{
NetDebug.WriteForce(NetLogLevel.Info, "Error while getting interface infos: {0}", e.ToString());
}
}
internal static int RelativeSequenceNumber(int number, int expected)
{
return (number - expected + NetConstants.MaxSequence + NetConstants.HalfMaxSequence) % NetConstants.MaxSequence - NetConstants.HalfMaxSequence;
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/NetUtils.cs.meta


fileFormatVersion: 2
guid: 9ba71ed4d3dcdf747abc2f5fc7a2a6dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

323
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/ReliableChannel.cs


using System;
namespace LiteNetLib
{
internal sealed class ReliableChannel : BaseChannel
{
private struct PendingPacket
{
private NetPacket _packet;
private long _timeStamp;
private bool _isSent;
public override string ToString()
{
return _packet == null ? "Empty" : _packet.Sequence.ToString();
}
public void Init(NetPacket packet)
{
_packet = packet;
_isSent = false;
}
public void TrySend(long currentTime, NetPeer peer)
{
if (_packet == null)
return;
if (_isSent) //check send time
{
double resendDelay = peer.ResendDelay * TimeSpan.TicksPerMillisecond;
double packetHoldTime = currentTime - _timeStamp;
if (packetHoldTime < resendDelay)
return;
NetDebug.Write("[RC]Resend: {0} > {1}", (int)packetHoldTime, resendDelay);
}
_timeStamp = currentTime;
_isSent = true;
peer.SendUserData(_packet);
}
public bool Clear(NetPeer peer)
{
if (_packet != null)
{
peer.RecycleAndDeliver(_packet);
_packet = null;
return true;
}
return false;
}
}
private readonly NetPacket _outgoingAcks; //for send acks
private readonly PendingPacket[] _pendingPackets; //for unacked packets and duplicates
private readonly NetPacket[] _receivedPackets; //for order
private readonly bool[] _earlyReceived; //for unordered
private int _localSeqence;
private int _remoteSequence;
private int _localWindowStart;
private int _remoteWindowStart;
private bool _mustSendAcks;
private readonly DeliveryMethod _deliveryMethod;
private readonly bool _ordered;
private readonly int _windowSize;
private const int BitsInByte = 8;
private readonly byte _id;
public ReliableChannel(NetPeer peer, bool ordered, byte id) : base(peer)
{
_id = id;
_windowSize = NetConstants.DefaultWindowSize;
_ordered = ordered;
_pendingPackets = new PendingPacket[_windowSize];
for (int i = 0; i < _pendingPackets.Length; i++)
_pendingPackets[i] = new PendingPacket();
if (_ordered)
{
_deliveryMethod = DeliveryMethod.ReliableOrdered;
_receivedPackets = new NetPacket[_windowSize];
}
else
{
_deliveryMethod = DeliveryMethod.ReliableUnordered;
_earlyReceived = new bool[_windowSize];
}
_localWindowStart = 0;
_localSeqence = 0;
_remoteSequence = 0;
_remoteWindowStart = 0;
_outgoingAcks = new NetPacket(PacketProperty.Ack, (_windowSize - 1) / BitsInByte + 2) {ChannelId = id};
}
//ProcessAck in packet
private void ProcessAck(NetPacket packet)
{
if (packet.Size != _outgoingAcks.Size)
{
NetDebug.Write("[PA]Invalid acks packet size");
return;
}
ushort ackWindowStart = packet.Sequence;
int windowRel = NetUtils.RelativeSequenceNumber(_localWindowStart, ackWindowStart);
if (ackWindowStart >= NetConstants.MaxSequence || windowRel < 0)
{
NetDebug.Write("[PA]Bad window start");
return;
}
//check relevance
if (windowRel >= _windowSize)
{
NetDebug.Write("[PA]Old acks");
return;
}
byte[] acksData = packet.RawData;
lock (_pendingPackets)
{
for (int pendingSeq = _localWindowStart;
pendingSeq != _localSeqence;
pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence)
{
int rel = NetUtils.RelativeSequenceNumber(pendingSeq, ackWindowStart);
if (rel >= _windowSize)
{
NetDebug.Write("[PA]REL: " + rel);
break;
}
int pendingIdx = pendingSeq % _windowSize;
int currentByte = NetConstants.ChanneledHeaderSize + pendingIdx / BitsInByte;
int currentBit = pendingIdx % BitsInByte;
if ((acksData[currentByte] & (1 << currentBit)) == 0)
{
#if DEBUG
Peer.Statistics.PacketLoss++;
#else
if (Peer.NetManager.EnableStatistics)
{
Peer.Statistics.PacketLoss++;
}
#endif
//Skip false ack
NetDebug.Write("[PA]False ack: {0}", pendingSeq);
continue;
}
if (pendingSeq == _localWindowStart)
{
//Move window
_localWindowStart = (_localWindowStart + 1) % NetConstants.MaxSequence;
}
//clear packet
if (_pendingPackets[pendingIdx].Clear(Peer))
NetDebug.Write("[PA]Removing reliableInOrder ack: {0} - true", pendingSeq);
}
}
}
public override void SendNextPackets()
{
if (_mustSendAcks)
{
_mustSendAcks = false;
NetDebug.Write("[RR]SendAcks");
lock(_outgoingAcks)
Peer.SendUserData(_outgoingAcks);
}
long currentTime = DateTime.UtcNow.Ticks;
lock (_pendingPackets)
{
//get packets from queue
lock (OutgoingQueue)
{
while (OutgoingQueue.Count > 0)
{
int relate = NetUtils.RelativeSequenceNumber(_localSeqence, _localWindowStart);
if (relate >= _windowSize)
break;
var netPacket = OutgoingQueue.Dequeue();
netPacket.Sequence = (ushort) _localSeqence;
netPacket.ChannelId = _id;
_pendingPackets[_localSeqence % _windowSize].Init(netPacket);
_localSeqence = (_localSeqence + 1) % NetConstants.MaxSequence;
}
}
//send
for (int pendingSeq = _localWindowStart; pendingSeq != _localSeqence; pendingSeq = (pendingSeq + 1) % NetConstants.MaxSequence)
_pendingPackets[pendingSeq % _windowSize].TrySend(currentTime, Peer);
}
}
//Process incoming packet
public override bool ProcessPacket(NetPacket packet)
{
if (packet.Property == PacketProperty.Ack)
{
ProcessAck(packet);
return false;
}
int seq = packet.Sequence;
if (seq >= NetConstants.MaxSequence)
{
NetDebug.Write("[RR]Bad sequence");
return false;
}
int relate = NetUtils.RelativeSequenceNumber(seq, _remoteWindowStart);
int relateSeq = NetUtils.RelativeSequenceNumber(seq, _remoteSequence);
if (relateSeq > _windowSize)
{
NetDebug.Write("[RR]Bad sequence");
return false;
}
//Drop bad packets
if (relate < 0)
{
//Too old packet doesn't ack
NetDebug.Write("[RR]ReliableInOrder too old");
return false;
}
if (relate >= _windowSize * 2)
{
//Some very new packet
NetDebug.Write("[RR]ReliableInOrder too new");
return false;
}
//If very new - move window
int ackIdx;
int ackByte;
int ackBit;
lock (_outgoingAcks)
{
if (relate >= _windowSize)
{
//New window position
int newWindowStart = (_remoteWindowStart + relate - _windowSize + 1) % NetConstants.MaxSequence;
_outgoingAcks.Sequence = (ushort) newWindowStart;
//Clean old data
while (_remoteWindowStart != newWindowStart)
{
ackIdx = _remoteWindowStart % _windowSize;
ackByte = NetConstants.ChanneledHeaderSize + ackIdx / BitsInByte;
ackBit = ackIdx % BitsInByte;
_outgoingAcks.RawData[ackByte] &= (byte) ~(1 << ackBit);
_remoteWindowStart = (_remoteWindowStart + 1) % NetConstants.MaxSequence;
}
}
//Final stage - process valid packet
//trigger acks send
_mustSendAcks = true;
ackIdx = seq % _windowSize;
ackByte = NetConstants.ChanneledHeaderSize + ackIdx / BitsInByte;
ackBit = ackIdx % BitsInByte;
if ((_outgoingAcks.RawData[ackByte] & (1 << ackBit)) != 0)
{
NetDebug.Write("[RR]ReliableInOrder duplicate");
return false;
}
//save ack
_outgoingAcks.RawData[ackByte] |= (byte) (1 << ackBit);
}
//detailed check
if (seq == _remoteSequence)
{
NetDebug.Write("[RR]ReliableInOrder packet succes");
Peer.AddReliablePacket(_deliveryMethod, packet);
_remoteSequence = (_remoteSequence + 1) % NetConstants.MaxSequence;
if (_ordered)
{
NetPacket p;
while ((p = _receivedPackets[_remoteSequence % _windowSize]) != null)
{
//process holden packet
_receivedPackets[_remoteSequence % _windowSize] = null;
Peer.AddReliablePacket(_deliveryMethod, p);
_remoteSequence = (_remoteSequence + 1) % NetConstants.MaxSequence;
}
}
else
{
while (_earlyReceived[_remoteSequence % _windowSize])
{
//process early packet
_earlyReceived[_remoteSequence % _windowSize] = false;
_remoteSequence = (_remoteSequence + 1) % NetConstants.MaxSequence;
}
}
return true;
}
//holden packet
if (_ordered)
{
_receivedPackets[ackIdx] = packet;
}
else
{
_earlyReceived[ackIdx] = true;
Peer.AddReliablePacket(_deliveryMethod, packet);
}
return true;
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/ReliableChannel.cs.meta


fileFormatVersion: 2
guid: c27d3fcb06848ee46b913dc9029ce2cd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

99
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/SequencedChannel.cs


using System;
namespace LiteNetLib
{
internal sealed class SequencedChannel : BaseChannel
{
private int _localSequence;
private ushort _remoteSequence;
private readonly bool _reliable;
private NetPacket _lastPacket;
private readonly NetPacket _ackPacket;
private bool _mustSendAck;
private readonly byte _id;
private long _lastPacketSendTime;
public SequencedChannel(NetPeer peer, bool reliable, byte id) : base(peer)
{
_id = id;
_reliable = reliable;
if (_reliable)
_ackPacket = new NetPacket(PacketProperty.Ack, 0) {ChannelId = id};
}
public override void SendNextPackets()
{
if (_reliable && OutgoingQueue.Count == 0)
{
long currentTime = DateTime.UtcNow.Ticks;
long packetHoldTime = currentTime - _lastPacketSendTime;
if (packetHoldTime < Peer.ResendDelay * TimeSpan.TicksPerMillisecond)
return;
var packet = _lastPacket;
if (packet != null)
{
_lastPacketSendTime = currentTime;
Peer.SendUserData(packet);
}
}
else
{
lock (OutgoingQueue)
{
while (OutgoingQueue.Count > 0)
{
NetPacket packet = OutgoingQueue.Dequeue();
_localSequence = (_localSequence + 1) % NetConstants.MaxSequence;
packet.Sequence = (ushort)_localSequence;
packet.ChannelId = _id;
Peer.SendUserData(packet);
if (_reliable && OutgoingQueue.Count == 0)
{
_lastPacketSendTime = DateTime.UtcNow.Ticks;
_lastPacket = packet;
}
else
{
Peer.NetManager.NetPacketPool.Recycle(packet);
}
}
}
}
if (_reliable && _mustSendAck)
{
_mustSendAck = false;
_ackPacket.Sequence = _remoteSequence;
Peer.SendUserData(_ackPacket);
}
}
public override bool ProcessPacket(NetPacket packet)
{
if (packet.IsFragmented)
return false;
if (packet.Property == PacketProperty.Ack)
{
if (_reliable && _lastPacket != null && packet.Sequence == _lastPacket.Sequence)
_lastPacket = null;
return false;
}
int relative = NetUtils.RelativeSequenceNumber(packet.Sequence, _remoteSequence);
bool packetProcessed = false;
if (packet.Sequence < NetConstants.MaxSequence && relative > 0)
{
Peer.Statistics.PacketLoss += (ulong)(relative - 1);
_remoteSequence = packet.Sequence;
Peer.NetManager.CreateReceiveEvent(
packet,
_reliable ? DeliveryMethod.ReliableSequenced : DeliveryMethod.Sequenced,
NetConstants.ChanneledHeaderSize,
Peer);
packetProcessed = true;
}
_mustSendAck = true;
return packetProcessed;
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/SequencedChannel.cs.meta


fileFormatVersion: 2
guid: 80bbd04014ae8cb48ab6513dc3b32646
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils.meta


fileFormatVersion: 2
guid: b42820447c8a8454e9f0fa10fa865fa2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

111
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/CRC32C.cs


#if NETCOREAPP3_0
using System;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics.X86;
#endif
namespace LiteNetLib.Utils
{
//Implementation from Crc32.NET
public static class CRC32C
{
public const int ChecksumSize = 4;
private const uint Poly = 0x82F63B78u;
private static readonly uint[] Table;
static CRC32C()
{
#if NETCOREAPP3_0
if(Sse42.IsSupported)
return;
#endif
Table = new uint[16 * 256];
for (uint i = 0; i < 256; i++)
{
uint res = i;
for (int t = 0; t < 16; t++)
{
for (int k = 0; k < 8; k++)
res = (res & 1) == 1 ? Poly ^ (res >> 1) : (res >> 1);
Table[t * 256 + i] = res;
}
}
}
/// <summary>
/// Compute CRC32C for data
/// </summary>
/// <param name="input">input data</param>
/// <param name="offset">offset</param>
/// <param name="length">length</param>
/// <returns>CRC32C checksum</returns>
public static uint Compute(byte[] input, int offset, int length)
{
uint crcLocal = uint.MaxValue;
#if NETCOREAPP3_0
if (Sse42.IsSupported)
{
var data = new ReadOnlySpan<byte>(input, offset, length);
int processed = 0;
if (Sse42.X64.IsSupported && data.Length > sizeof(ulong))
{
processed = data.Length / sizeof(ulong) * sizeof(ulong);
var ulongs = MemoryMarshal.Cast<byte, ulong>(data.Slice(0, processed));
ulong crclong = crcLocal;
for (int i = 0; i < ulongs.Length; i++)
{
crclong = Sse42.X64.Crc32(crclong, ulongs[i]);
}
crcLocal = (uint)crclong;
}
else if (data.Length > sizeof(uint))
{
processed = data.Length / sizeof(uint) * sizeof(uint);
var uints = MemoryMarshal.Cast<byte, uint>(data.Slice(0, processed));
for (int i = 0; i < uints.Length; i++)
{
crcLocal = Sse42.Crc32(crcLocal, uints[i]);
}
}
for (int i = processed; i < data.Length; i++)
{
crcLocal = Sse42.Crc32(crcLocal, data[i]);
}
return crcLocal ^ uint.MaxValue;
}
#endif
while (length >= 16)
{
var a = Table[(3 * 256) + input[offset + 12]]
^ Table[(2 * 256) + input[offset + 13]]
^ Table[(1 * 256) + input[offset + 14]]
^ Table[(0 * 256) + input[offset + 15]];
var b = Table[(7 * 256) + input[offset + 8]]
^ Table[(6 * 256) + input[offset + 9]]
^ Table[(5 * 256) + input[offset + 10]]
^ Table[(4 * 256) + input[offset + 11]];
var c = Table[(11 * 256) + input[offset + 4]]
^ Table[(10 * 256) + input[offset + 5]]
^ Table[(9 * 256) + input[offset + 6]]
^ Table[(8 * 256) + input[offset + 7]];
var d = Table[(15 * 256) + ((byte)crcLocal ^ input[offset])]
^ Table[(14 * 256) + ((byte)(crcLocal >> 8) ^ input[offset + 1])]
^ Table[(13 * 256) + ((byte)(crcLocal >> 16) ^ input[offset + 2])]
^ Table[(12 * 256) + ((crcLocal >> 24) ^ input[offset + 3])];
crcLocal = d ^ c ^ b ^ a;
offset += 16;
length -= 16;
}
while (--length >= 0)
crcLocal = Table[(byte)(crcLocal ^ input[offset++])] ^ crcLocal >> 8;
return crcLocal ^ uint.MaxValue;
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/CRC32C.cs.meta


fileFormatVersion: 2
guid: b9bc296b45361e44fb4b61c5c7f8ca43
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

118
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/FastBitConverter.cs


using System.Runtime.InteropServices;
namespace LiteNetLib.Utils
{
public static class FastBitConverter
{
[StructLayout(LayoutKind.Explicit)]
private struct ConverterHelperDouble
{
[FieldOffset(0)]
public ulong Along;
[FieldOffset(0)]
public double Adouble;
}
[StructLayout(LayoutKind.Explicit)]
private struct ConverterHelperFloat
{
[FieldOffset(0)]
public int Aint;
[FieldOffset(0)]
public float Afloat;
}
private static void WriteLittleEndian(byte[] buffer, int offset, ulong data)
{
#if BIGENDIAN
buffer[offset + 7] = (byte)(data);
buffer[offset + 6] = (byte)(data >> 8);
buffer[offset + 5] = (byte)(data >> 16);
buffer[offset + 4] = (byte)(data >> 24);
buffer[offset + 3] = (byte)(data >> 32);
buffer[offset + 2] = (byte)(data >> 40);
buffer[offset + 1] = (byte)(data >> 48);
buffer[offset ] = (byte)(data >> 56);
#else
buffer[offset] = (byte)(data);
buffer[offset + 1] = (byte)(data >> 8);
buffer[offset + 2] = (byte)(data >> 16);
buffer[offset + 3] = (byte)(data >> 24);
buffer[offset + 4] = (byte)(data >> 32);
buffer[offset + 5] = (byte)(data >> 40);
buffer[offset + 6] = (byte)(data >> 48);
buffer[offset + 7] = (byte)(data >> 56);
#endif
}
private static void WriteLittleEndian(byte[] buffer, int offset, int data)
{
#if BIGENDIAN
buffer[offset + 3] = (byte)(data);
buffer[offset + 2] = (byte)(data >> 8);
buffer[offset + 1] = (byte)(data >> 16);
buffer[offset ] = (byte)(data >> 24);
#else
buffer[offset] = (byte)(data);
buffer[offset + 1] = (byte)(data >> 8);
buffer[offset + 2] = (byte)(data >> 16);
buffer[offset + 3] = (byte)(data >> 24);
#endif
}
public static void WriteLittleEndian(byte[] buffer, int offset, short data)
{
#if BIGENDIAN
buffer[offset + 1] = (byte)(data);
buffer[offset ] = (byte)(data >> 8);
#else
buffer[offset] = (byte)(data);
buffer[offset + 1] = (byte)(data >> 8);
#endif
}
public static void GetBytes(byte[] bytes, int startIndex, double value)
{
ConverterHelperDouble ch = new ConverterHelperDouble { Adouble = value };
WriteLittleEndian(bytes, startIndex, ch.Along);
}
public static void GetBytes(byte[] bytes, int startIndex, float value)
{
ConverterHelperFloat ch = new ConverterHelperFloat { Afloat = value };
WriteLittleEndian(bytes, startIndex, ch.Aint);
}
public static void GetBytes(byte[] bytes, int startIndex, short value)
{
WriteLittleEndian(bytes, startIndex, value);
}
public static void GetBytes(byte[] bytes, int startIndex, ushort value)
{
WriteLittleEndian(bytes, startIndex, (short)value);
}
public static void GetBytes(byte[] bytes, int startIndex, int value)
{
WriteLittleEndian(bytes, startIndex, value);
}
public static void GetBytes(byte[] bytes, int startIndex, uint value)
{
WriteLittleEndian(bytes, startIndex, (int)value);
}
public static void GetBytes(byte[] bytes, int startIndex, long value)
{
WriteLittleEndian(bytes, startIndex, (ulong)value);
}
public static void GetBytes(byte[] bytes, int startIndex, ulong value)
{
WriteLittleEndian(bytes, startIndex, value);
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/FastBitConverter.cs.meta


fileFormatVersion: 2
guid: db75e586fc1fe264e9bc12949520676c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/INetSerializable.cs


namespace LiteNetLib.Utils
{
public interface INetSerializable
{
void Serialize(NetDataWriter writer);
void Deserialize(NetDataReader reader);
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/INetSerializable.cs.meta


fileFormatVersion: 2
guid: 067110f4d769ffe43959f64f7a32a178
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

694
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetDataReader.cs


using System;
using System.Net;
using System.Text;
namespace LiteNetLib.Utils
{
public class NetDataReader
{
protected byte[] _data;
protected int _position;
protected int _dataSize;
private int _offset;
public byte[] RawData
{
get { return _data; }
}
public int RawDataSize
{
get { return _dataSize; }
}
public int UserDataOffset
{
get { return _offset; }
}
public int UserDataSize
{
get { return _dataSize - _offset; }
}
public bool IsNull
{
get { return _data == null; }
}
public int Position
{
get { return _position; }
}
public bool EndOfData
{
get { return _position == _dataSize; }
}
public int AvailableBytes
{
get { return _dataSize - _position; }
}
public void SkipBytes(int count)
{
_position += count;
}
public void SetSource(NetDataWriter dataWriter)
{
_data = dataWriter.Data;
_position = 0;
_offset = 0;
_dataSize = dataWriter.Length;
}
public void SetSource(byte[] source)
{
_data = source;
_position = 0;
_offset = 0;
_dataSize = source.Length;
}
public void SetSource(byte[] source, int offset)
{
_data = source;
_position = offset;
_offset = offset;
_dataSize = source.Length;
}
public void SetSource(byte[] source, int offset, int maxSize)
{
_data = source;
_position = offset;
_offset = offset;
_dataSize = maxSize;
}
public NetDataReader()
{
}
public NetDataReader(NetDataWriter writer)
{
SetSource(writer);
}
public NetDataReader(byte[] source)
{
SetSource(source);
}
public NetDataReader(byte[] source, int offset)
{
SetSource(source, offset);
}
public NetDataReader(byte[] source, int offset, int maxSize)
{
SetSource(source, offset, maxSize);
}
#region GetMethods
public IPEndPoint GetNetEndPoint()
{
string host = GetString(1000);
int port = GetInt();
return NetUtils.MakeEndPoint(host, port);
}
public byte GetByte()
{
byte res = _data[_position];
_position += 1;
return res;
}
public sbyte GetSByte()
{
var b = (sbyte)_data[_position];
_position++;
return b;
}
public bool[] GetBoolArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new bool[size];
Buffer.BlockCopy(_data, _position, arr, 0, size);
_position += size;
return arr;
}
public ushort[] GetUShortArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new ushort[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 2);
_position += size * 2;
return arr;
}
public short[] GetShortArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new short[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 2);
_position += size * 2;
return arr;
}
public long[] GetLongArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new long[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 8);
_position += size * 8;
return arr;
}
public ulong[] GetULongArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new ulong[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 8);
_position += size * 8;
return arr;
}
public int[] GetIntArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new int[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 4);
_position += size * 4;
return arr;
}
public uint[] GetUIntArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new uint[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 4);
_position += size * 4;
return arr;
}
public float[] GetFloatArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new float[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 4);
_position += size * 4;
return arr;
}
public double[] GetDoubleArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new double[size];
Buffer.BlockCopy(_data, _position, arr, 0, size * 8);
_position += size * 8;
return arr;
}
public string[] GetStringArray()
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new string[size];
for (int i = 0; i < size; i++)
{
arr[i] = GetString();
}
return arr;
}
public string[] GetStringArray(int maxStringLength)
{
ushort size = BitConverter.ToUInt16(_data, _position);
_position += 2;
var arr = new string[size];
for (int i = 0; i < size; i++)
{
arr[i] = GetString(maxStringLength);
}
return arr;
}
public bool GetBool()
{
bool res = _data[_position] > 0;
_position += 1;
return res;
}
public char GetChar()
{
char result = BitConverter.ToChar(_data, _position);
_position += 2;
return result;
}
public ushort GetUShort()
{
ushort result = BitConverter.ToUInt16(_data, _position);
_position += 2;
return result;
}
public short GetShort()
{
short result = BitConverter.ToInt16(_data, _position);
_position += 2;
return result;
}
public long GetLong()
{
long result = BitConverter.ToInt64(_data, _position);
_position += 8;
return result;
}
public ulong GetULong()
{
ulong result = BitConverter.ToUInt64(_data, _position);
_position += 8;
return result;
}
public int GetInt()
{
int result = BitConverter.ToInt32(_data, _position);
_position += 4;
return result;
}
public uint GetUInt()
{
uint result = BitConverter.ToUInt32(_data, _position);
_position += 4;
return result;
}
public float GetFloat()
{
float result = BitConverter.ToSingle(_data, _position);
_position += 4;
return result;
}
public double GetDouble()
{
double result = BitConverter.ToDouble(_data, _position);
_position += 8;
return result;
}
public string GetString(int maxLength)
{
int bytesCount = GetInt();
if (bytesCount <= 0 || bytesCount > maxLength*2)
{
return string.Empty;
}
int charCount = Encoding.UTF8.GetCharCount(_data, _position, bytesCount);
if (charCount > maxLength)
{
return string.Empty;
}
string result = Encoding.UTF8.GetString(_data, _position, bytesCount);
_position += bytesCount;
return result;
}
public string GetString()
{
int bytesCount = GetInt();
if (bytesCount <= 0)
{
return string.Empty;
}
string result = Encoding.UTF8.GetString(_data, _position, bytesCount);
_position += bytesCount;
return result;
}
public ArraySegment<byte> GetRemainingBytesSegment()
{
ArraySegment<byte> segment = new ArraySegment<byte>(_data, _position, AvailableBytes);
_position = _data.Length;
return segment;
}
public T Get<T>() where T : INetSerializable, new()
{
var obj = new T();
obj.Deserialize(this);
return obj;
}
public byte[] GetRemainingBytes()
{
byte[] outgoingData = new byte[AvailableBytes];
Buffer.BlockCopy(_data, _position, outgoingData, 0, AvailableBytes);
_position = _data.Length;
return outgoingData;
}
public void GetBytes(byte[] destination, int start, int count)
{
Buffer.BlockCopy(_data, _position, destination, start, count);
_position += count;
}
public void GetBytes(byte[] destination, int count)
{
Buffer.BlockCopy(_data, _position, destination, 0, count);
_position += count;
}
public sbyte[] GetSBytesWithLength()
{
int length = GetInt();
sbyte[] outgoingData = new sbyte[length];
Buffer.BlockCopy(_data, _position, outgoingData, 0, length);
_position += length;
return outgoingData;
}
public byte[] GetBytesWithLength()
{
int length = GetInt();
byte[] outgoingData = new byte[length];
Buffer.BlockCopy(_data, _position, outgoingData, 0, length);
_position += length;
return outgoingData;
}
#endregion
#region PeekMethods
public byte PeekByte()
{
return _data[_position];
}
public sbyte PeekSByte()
{
return (sbyte)_data[_position];
}
public bool PeekBool()
{
return _data[_position] > 0;
}
public char PeekChar()
{
return BitConverter.ToChar(_data, _position);
}
public ushort PeekUShort()
{
return BitConverter.ToUInt16(_data, _position);
}
public short PeekShort()
{
return BitConverter.ToInt16(_data, _position);
}
public long PeekLong()
{
return BitConverter.ToInt64(_data, _position);
}
public ulong PeekULong()
{
return BitConverter.ToUInt64(_data, _position);
}
public int PeekInt()
{
return BitConverter.ToInt32(_data, _position);
}
public uint PeekUInt()
{
return BitConverter.ToUInt32(_data, _position);
}
public float PeekFloat()
{
return BitConverter.ToSingle(_data, _position);
}
public double PeekDouble()
{
return BitConverter.ToDouble(_data, _position);
}
public string PeekString(int maxLength)
{
int bytesCount = BitConverter.ToInt32(_data, _position);
if (bytesCount <= 0 || bytesCount > maxLength * 2)
{
return string.Empty;
}
int charCount = Encoding.UTF8.GetCharCount(_data, _position + 4, bytesCount);
if (charCount > maxLength)
{
return string.Empty;
}
string result = Encoding.UTF8.GetString(_data, _position + 4, bytesCount);
return result;
}
public string PeekString()
{
int bytesCount = BitConverter.ToInt32(_data, _position);
if (bytesCount <= 0)
{
return string.Empty;
}
string result = Encoding.UTF8.GetString(_data, _position + 4, bytesCount);
return result;
}
#endregion
#region TryGetMethods
public bool TryGetByte(out byte result)
{
if (AvailableBytes >= 1)
{
result = GetByte();
return true;
}
result = 0;
return false;
}
public bool TryGetSByte(out sbyte result)
{
if (AvailableBytes >= 1)
{
result = GetSByte();
return true;
}
result = 0;
return false;
}
public bool TryGetBool(out bool result)
{
if (AvailableBytes >= 1)
{
result = GetBool();
return true;
}
result = false;
return false;
}
public bool TryGetChar(out char result)
{
if (AvailableBytes >= 2)
{
result = GetChar();
return true;
}
result = '\0';
return false;
}
public bool TryGetShort(out short result)
{
if (AvailableBytes >= 2)
{
result = GetShort();
return true;
}
result = 0;
return false;
}
public bool TryGetUShort(out ushort result)
{
if (AvailableBytes >= 2)
{
result = GetUShort();
return true;
}
result = 0;
return false;
}
public bool TryGetInt(out int result)
{
if (AvailableBytes >= 4)
{
result = GetInt();
return true;
}
result = 0;
return false;
}
public bool TryGetUInt(out uint result)
{
if (AvailableBytes >= 4)
{
result = GetUInt();
return true;
}
result = 0;
return false;
}
public bool TryGetLong(out long result)
{
if (AvailableBytes >= 8)
{
result = GetLong();
return true;
}
result = 0;
return false;
}
public bool TryGetULong(out ulong result)
{
if (AvailableBytes >= 8)
{
result = GetULong();
return true;
}
result = 0;
return false;
}
public bool TryGetFloat(out float result)
{
if (AvailableBytes >= 4)
{
result = GetFloat();
return true;
}
result = 0;
return false;
}
public bool TryGetDouble(out double result)
{
if (AvailableBytes >= 8)
{
result = GetDouble();
return true;
}
result = 0;
return false;
}
public bool TryGetString(out string result)
{
if (AvailableBytes >= 4)
{
var bytesCount = PeekInt();
if (AvailableBytes >= bytesCount + 4)
{
result = GetString();
return true;
}
}
result = null;
return false;
}
public bool TryGetStringArray(out string[] result)
{
ushort size;
if (!TryGetUShort(out size))
{
result = null;
return false;
}
result = new string[size];
for (int i = 0; i < size; i++)
{
if (!TryGetString(out result[i]))
{
result = null;
return false;
}
}
return true;
}
public bool TryGetBytesWithLength(out byte[] result)
{
if (AvailableBytes >= 4)
{
var length = PeekInt();
if (length >= 0 && AvailableBytes >= length + 4)
{
result = GetBytesWithLength();
return true;
}
}
result = null;
return false;
}
#endregion
public void Clear()
{
_position = 0;
_dataSize = 0;
_data = null;
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetDataReader.cs.meta


fileFormatVersion: 2
guid: d531661040bfd9942b93adcf122d67a2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

382
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetDataWriter.cs


using System;
using System.Net;
using System.Text;
namespace LiteNetLib.Utils
{
public class NetDataWriter
{
protected byte[] _data;
protected int _position;
private const int InitialSize = 64;
private readonly bool _autoResize;
public int Capacity
{
get { return _data.Length; }
}
public NetDataWriter() : this(true, InitialSize)
{
}
public NetDataWriter(bool autoResize) : this(autoResize, InitialSize)
{
}
public NetDataWriter(bool autoResize, int initialSize)
{
_data = new byte[initialSize];
_autoResize = autoResize;
}
/// <summary>
/// Creates NetDataWriter from existing ByteArray
/// </summary>
/// <param name="bytes">Source byte array</param>
/// <param name="copy">Copy array to new location or use existing</param>
public static NetDataWriter FromBytes(byte[] bytes, bool copy)
{
if (copy)
{
var netDataWriter = new NetDataWriter(true, bytes.Length);
netDataWriter.Put(bytes);
return netDataWriter;
}
return new NetDataWriter(true, 0) {_data = bytes};
}
/// <summary>
/// Creates NetDataWriter from existing ByteArray (always copied data)
/// </summary>
/// <param name="bytes">Source byte array</param>
/// <param name="offset">Offset of array</param>
/// <param name="length">Length of array</param>
public static NetDataWriter FromBytes(byte[] bytes, int offset, int length)
{
var netDataWriter = new NetDataWriter(true, bytes.Length);
netDataWriter.Put(bytes, offset, length);
return netDataWriter;
}
public static NetDataWriter FromString(string value)
{
var netDataWriter = new NetDataWriter();
netDataWriter.Put(value);
return netDataWriter;
}
public void ResizeIfNeed(int newSize)
{
int len = _data.Length;
if (len < newSize)
{
while (len < newSize)
len *= 2;
Array.Resize(ref _data, len);
}
}
public void Reset(int size)
{
ResizeIfNeed(size);
_position = 0;
}
public void Reset()
{
_position = 0;
}
public byte[] CopyData()
{
byte[] resultData = new byte[_position];
Buffer.BlockCopy(_data, 0, resultData, 0, _position);
return resultData;
}
public byte[] Data
{
get { return _data; }
}
public int Length
{
get { return _position; }
}
public void Put(float value)
{
if (_autoResize)
ResizeIfNeed(_position + 4);
FastBitConverter.GetBytes(_data, _position, value);
_position += 4;
}
public void Put(double value)
{
if (_autoResize)
ResizeIfNeed(_position + 8);
FastBitConverter.GetBytes(_data, _position, value);
_position += 8;
}
public void Put(long value)
{
if (_autoResize)
ResizeIfNeed(_position + 8);
FastBitConverter.GetBytes(_data, _position, value);
_position += 8;
}
public void Put(ulong value)
{
if (_autoResize)
ResizeIfNeed(_position + 8);
FastBitConverter.GetBytes(_data, _position, value);
_position += 8;
}
public void Put(int value)
{
if (_autoResize)
ResizeIfNeed(_position + 4);
FastBitConverter.GetBytes(_data, _position, value);
_position += 4;
}
public void Put(uint value)
{
if (_autoResize)
ResizeIfNeed(_position + 4);
FastBitConverter.GetBytes(_data, _position, value);
_position += 4;
}
public void Put(char value)
{
if (_autoResize)
ResizeIfNeed(_position + 2);
FastBitConverter.GetBytes(_data, _position, value);
_position += 2;
}
public void Put(ushort value)
{
if (_autoResize)
ResizeIfNeed(_position + 2);
FastBitConverter.GetBytes(_data, _position, value);
_position += 2;
}
public void Put(short value)
{
if (_autoResize)
ResizeIfNeed(_position + 2);
FastBitConverter.GetBytes(_data, _position, value);
_position += 2;
}
public void Put(sbyte value)
{
if (_autoResize)
ResizeIfNeed(_position + 1);
_data[_position] = (byte)value;
_position++;
}
public void Put(byte value)
{
if (_autoResize)
ResizeIfNeed(_position + 1);
_data[_position] = value;
_position++;
}
public void Put(byte[] data, int offset, int length)
{
if (_autoResize)
ResizeIfNeed(_position + length);
Buffer.BlockCopy(data, offset, _data, _position, length);
_position += length;
}
public void Put(byte[] data)
{
if (_autoResize)
ResizeIfNeed(_position + data.Length);
Buffer.BlockCopy(data, 0, _data, _position, data.Length);
_position += data.Length;
}
public void PutSBytesWithLength(sbyte[] data, int offset, int length)
{
if (_autoResize)
ResizeIfNeed(_position + length + 4);
FastBitConverter.GetBytes(_data, _position, length);
Buffer.BlockCopy(data, offset, _data, _position + 4, length);
_position += length + 4;
}
public void PutSBytesWithLength(sbyte[] data)
{
if (_autoResize)
ResizeIfNeed(_position + data.Length + 4);
FastBitConverter.GetBytes(_data, _position, data.Length);
Buffer.BlockCopy(data, 0, _data, _position + 4, data.Length);
_position += data.Length + 4;
}
public void PutBytesWithLength(byte[] data, int offset, int length)
{
if (_autoResize)
ResizeIfNeed(_position + length + 4);
FastBitConverter.GetBytes(_data, _position, length);
Buffer.BlockCopy(data, offset, _data, _position + 4, length);
_position += length + 4;
}
public void PutBytesWithLength(byte[] data)
{
if (_autoResize)
ResizeIfNeed(_position + data.Length + 4);
FastBitConverter.GetBytes(_data, _position, data.Length);
Buffer.BlockCopy(data, 0, _data, _position + 4, data.Length);
_position += data.Length + 4;
}
public void Put(bool value)
{
if (_autoResize)
ResizeIfNeed(_position + 1);
_data[_position] = (byte)(value ? 1 : 0);
_position++;
}
private void PutArray(Array arr, int sz)
{
ushort length = arr == null ? (ushort) 0 : (ushort)arr.Length;
sz *= length;
if (_autoResize)
ResizeIfNeed(_position + sz + 2);
FastBitConverter.GetBytes(_data, _position, length);
if (arr != null)
Buffer.BlockCopy(arr, 0, _data, _position + 2, sz);
_position += sz + 2;
}
public void PutArray(float[] value)
{
PutArray(value, 4);
}
public void PutArray(double[] value)
{
PutArray(value, 8);
}
public void PutArray(long[] value)
{
PutArray(value, 8);
}
public void PutArray(ulong[] value)
{
PutArray(value, 8);
}
public void PutArray(int[] value)
{
PutArray(value, 4);
}
public void PutArray(uint[] value)
{
PutArray(value, 4);
}
public void PutArray(ushort[] value)
{
PutArray(value, 2);
}
public void PutArray(short[] value)
{
PutArray(value, 2);
}
public void PutArray(bool[] value)
{
PutArray(value, 1);
}
public void PutArray(string[] value)
{
ushort len = value == null ? (ushort)0 : (ushort)value.Length;
Put(len);
for (int i = 0; i < len; i++)
Put(value[i]);
}
public void PutArray(string[] value, int maxLength)
{
ushort len = value == null ? (ushort)0 : (ushort)value.Length;
Put(len);
for (int i = 0; i < len; i++)
Put(value[i], maxLength);
}
public void Put(IPEndPoint endPoint)
{
Put(endPoint.Address.ToString());
Put(endPoint.Port);
}
public void Put(string value)
{
if (string.IsNullOrEmpty(value))
{
Put(0);
return;
}
//put bytes count
int bytesCount = Encoding.UTF8.GetByteCount(value);
if (_autoResize)
ResizeIfNeed(_position + bytesCount + 4);
Put(bytesCount);
//put string
Encoding.UTF8.GetBytes(value, 0, value.Length, _data, _position);
_position += bytesCount;
}
public void Put(string value, int maxLength)
{
if (string.IsNullOrEmpty(value))
{
Put(0);
return;
}
int length = value.Length > maxLength ? maxLength : value.Length;
//calculate max count
int bytesCount = Encoding.UTF8.GetByteCount(value);
if (_autoResize)
ResizeIfNeed(_position + bytesCount + 4);
//put bytes count
Put(bytesCount);
//put string
Encoding.UTF8.GetBytes(value, 0, length, _data, _position);
_position += bytesCount;
}
public void Put<T>(T obj) where T : INetSerializable
{
obj.Serialize(this);
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetDataWriter.cs.meta


fileFormatVersion: 2
guid: 69c77411d55e98941802ca35835dd3da
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

314
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetPacketProcessor.cs


using System;
using System.Collections.Generic;
namespace LiteNetLib.Utils
{
public class NetPacketProcessor
{
private static class HashCache<T>
{
public static bool Initialized;
public static ulong Id;
}
protected delegate void SubscribeDelegate(NetDataReader reader, object userData);
private readonly NetSerializer _netSerializer;
private readonly Dictionary<ulong, SubscribeDelegate> _callbacks = new Dictionary<ulong, SubscribeDelegate>();
private readonly NetDataWriter _netDataWriter = new NetDataWriter();
public NetPacketProcessor()
{
_netSerializer = new NetSerializer();
}
public NetPacketProcessor(int maxStringLength)
{
_netSerializer = new NetSerializer(maxStringLength);
}
//FNV-1 64 bit hash
protected virtual ulong GetHash<T>()
{
if(HashCache<T>.Initialized)
return HashCache<T>.Id;
ulong hash = 14695981039346656037UL; //offset
string typeName = typeof(T).FullName;
for (var i = 0; i < typeName.Length; i++)
{
hash = hash ^ typeName[i];
hash *= 1099511628211UL; //prime
}
HashCache<T>.Initialized = true;
HashCache<T>.Id = hash;
return hash;
}
protected virtual SubscribeDelegate GetCallbackFromData(NetDataReader reader)
{
var hash = reader.GetULong();
SubscribeDelegate action;
if (!_callbacks.TryGetValue(hash, out action))
{
throw new ParseException("Undefined packet in NetDataReader");
}
return action;
}
protected virtual void WriteHash<T>(NetDataWriter writer)
{
writer.Put(GetHash<T>());
}
/// <summary>
/// Register nested property type
/// </summary>
/// <typeparam name="T">INetSerializable structure</typeparam>
public void RegisterNestedType<T>() where T : struct, INetSerializable
{
_netSerializer.RegisterNestedType<T>();
}
/// <summary>
/// Register nested property type
/// </summary>
/// <param name="writeDelegate"></param>
/// <param name="readDelegate"></param>
public void RegisterNestedType<T>(Action<NetDataWriter, T> writeDelegate, Func<NetDataReader, T> readDelegate)
{
_netSerializer.RegisterNestedType<T>(writeDelegate, readDelegate);
}
/// <summary>
/// Register nested property type
/// </summary>
/// <typeparam name="T">INetSerializable class</typeparam>
public void RegisterNestedType<T>(Func<T> constructor) where T : class, INetSerializable
{
_netSerializer.RegisterNestedType(constructor);
}
/// <summary>
/// Reads all available data from NetDataReader and calls OnReceive delegates
/// </summary>
/// <param name="reader">NetDataReader with packets data</param>
public void ReadAllPackets(NetDataReader reader)
{
while (reader.AvailableBytes > 0)
ReadPacket(reader);
}
/// <summary>
/// Reads all available data from NetDataReader and calls OnReceive delegates
/// </summary>
/// <param name="reader">NetDataReader with packets data</param>
/// <param name="userData">Argument that passed to OnReceivedEvent</param>
/// <exception cref="ParseException">Malformed packet</exception>
public void ReadAllPackets(NetDataReader reader, object userData)
{
while (reader.AvailableBytes > 0)
ReadPacket(reader, userData);
}
/// <summary>
/// Reads one packet from NetDataReader and calls OnReceive delegate
/// </summary>
/// <param name="reader">NetDataReader with packet</param>
/// <exception cref="ParseException">Malformed packet</exception>
public void ReadPacket(NetDataReader reader)
{
ReadPacket(reader, null);
}
public void Send<T>(NetPeer peer, T packet, DeliveryMethod options) where T : class, new()
{
_netDataWriter.Reset();
Write(_netDataWriter, packet);
peer.Send(_netDataWriter, options);
}
public void SendNetSerializable<T>(NetPeer peer, T packet, DeliveryMethod options) where T : INetSerializable
{
_netDataWriter.Reset();
WriteNetSerializable(_netDataWriter, packet);
peer.Send(_netDataWriter, options);
}
public void Send<T>(NetManager manager, T packet, DeliveryMethod options) where T : class, new()
{
_netDataWriter.Reset();
Write(_netDataWriter, packet);
manager.SendToAll(_netDataWriter, options);
}
public void SendNetSerializable<T>(NetManager manager, T packet, DeliveryMethod options) where T : INetSerializable
{
_netDataWriter.Reset();
WriteNetSerializable(_netDataWriter, packet);
manager.SendToAll(_netDataWriter, options);
}
public void Write<T>(NetDataWriter writer, T packet) where T : class, new()
{
WriteHash<T>(writer);
_netSerializer.Serialize(writer, packet);
}
public void WriteNetSerializable<T>(NetDataWriter writer, T packet) where T : INetSerializable
{
WriteHash<T>(writer);
packet.Serialize(writer);
}
public byte[] Write<T>(T packet) where T : class, new()
{
_netDataWriter.Reset();
WriteHash<T>(_netDataWriter);
_netSerializer.Serialize(_netDataWriter, packet);
return _netDataWriter.CopyData();
}
public byte[] WriteNetSerializable<T>(T packet) where T : INetSerializable
{
_netDataWriter.Reset();
WriteHash<T>(_netDataWriter);
packet.Serialize(_netDataWriter);
return _netDataWriter.CopyData();
}
/// <summary>
/// Reads one packet from NetDataReader and calls OnReceive delegate
/// </summary>
/// <param name="reader">NetDataReader with packet</param>
/// <param name="userData">Argument that passed to OnReceivedEvent</param>
/// <exception cref="ParseException">Malformed packet</exception>
public void ReadPacket(NetDataReader reader, object userData)
{
GetCallbackFromData(reader)(reader, userData);
}
/// <summary>
/// Register and subscribe to packet receive event
/// </summary>
/// <param name="onReceive">event that will be called when packet deserialized with ReadPacket method</param>
/// <param name="packetConstructor">Method that constructs packet instead of slow Activator.CreateInstance</param>
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public void Subscribe<T>(Action<T> onReceive, Func<T> packetConstructor) where T : class, new()
{
_netSerializer.Register<T>();
_callbacks[GetHash<T>()] = (reader, userData) =>
{
var reference = packetConstructor();
_netSerializer.Deserialize(reader, reference);
onReceive(reference);
};
}
/// <summary>
/// Register and subscribe to packet receive event (with userData)
/// </summary>
/// <param name="onReceive">event that will be called when packet deserialized with ReadPacket method</param>
/// <param name="packetConstructor">Method that constructs packet instead of slow Activator.CreateInstance</param>
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public void Subscribe<T, TUserData>(Action<T, TUserData> onReceive, Func<T> packetConstructor) where T : class, new()
{
_netSerializer.Register<T>();
_callbacks[GetHash<T>()] = (reader, userData) =>
{
var reference = packetConstructor();
_netSerializer.Deserialize(reader, reference);
onReceive(reference, (TUserData)userData);
};
}
/// <summary>
/// Register and subscribe to packet receive event
/// This method will overwrite last received packet class on receive (less garbage)
/// </summary>
/// <param name="onReceive">event that will be called when packet deserialized with ReadPacket method</param>
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public void SubscribeReusable<T>(Action<T> onReceive) where T : class, new()
{
_netSerializer.Register<T>();
var reference = new T();
_callbacks[GetHash<T>()] = (reader, userData) =>
{
_netSerializer.Deserialize(reader, reference);
onReceive(reference);
};
}
/// <summary>
/// Register and subscribe to packet receive event
/// This method will overwrite last received packet class on receive (less garbage)
/// </summary>
/// <param name="onReceive">event that will be called when packet deserialized with ReadPacket method</param>
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public void SubscribeReusable<T, TUserData>(Action<T, TUserData> onReceive) where T : class, new()
{
_netSerializer.Register<T>();
var reference = new T();
_callbacks[GetHash<T>()] = (reader, userData) =>
{
_netSerializer.Deserialize(reader, reference);
onReceive(reference, (TUserData)userData);
};
}
public void SubscribeNetSerializable<T, TUserData>(
Action<T, TUserData> onReceive,
Func<T> packetConstructor) where T : INetSerializable
{
_callbacks[GetHash<T>()] = (reader, userData) =>
{
var pkt = packetConstructor();
pkt.Deserialize(reader);
onReceive(pkt, (TUserData)userData);
};
}
public void SubscribeNetSerializable<T>(
Action<T> onReceive,
Func<T> packetConstructor) where T : INetSerializable
{
_callbacks[GetHash<T>()] = (reader, userData) =>
{
var pkt = packetConstructor();
pkt.Deserialize(reader);
onReceive(pkt);
};
}
public void SubscribeNetSerializable<T, TUserData>(
Action<T, TUserData> onReceive) where T : INetSerializable, new()
{
var reference = new T();
_callbacks[GetHash<T>()] = (reader, userData) =>
{
reference.Deserialize(reader);
onReceive(reference, (TUserData)userData);
};
}
public void SubscribeNetSerializable<T>(
Action<T> onReceive) where T : INetSerializable, new()
{
var reference = new T();
_callbacks[GetHash<T>()] = (reader, userData) =>
{
reference.Deserialize(reader);
onReceive(reference);
};
}
/// <summary>
/// Remove any subscriptions by type
/// </summary>
/// <typeparam name="T">Packet type</typeparam>
/// <returns>true if remove is success</returns>
public bool RemoveSubscription<T>()
{
return _callbacks.Remove(GetHash<T>());
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetPacketProcessor.cs.meta


fileFormatVersion: 2
guid: 9b0c0e8aa2c23504fbc252cd239cddbc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

752
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetSerializer.cs


using System;
using System.Reflection;
using System.Collections.Generic;
using System.Net;
namespace LiteNetLib.Utils
{
public class InvalidTypeException : ArgumentException
{
public InvalidTypeException(string message) : base(message) { }
}
public class ParseException : Exception
{
public ParseException(string message) : base(message) { }
}
public class NetSerializer
{
private enum CallType
{
Basic,
Array,
List
}
private abstract class FastCall<T>
{
public CallType Type;
public virtual void Init(MethodInfo getMethod, MethodInfo setMethod, CallType type) { Type = type; }
public abstract void Read(T inf, NetDataReader r);
public abstract void Write(T inf, NetDataWriter w);
public abstract void ReadArray(T inf, NetDataReader r);
public abstract void WriteArray(T inf, NetDataWriter w);
public abstract void ReadList(T inf, NetDataReader r);
public abstract void WriteList(T inf, NetDataWriter w);
}
private abstract class FastCallSpecific<TClass, TProperty> : FastCall<TClass>
{
protected Func<TClass, TProperty> Getter;
protected Action<TClass, TProperty> Setter;
protected Func<TClass, TProperty[]> GetterArr;
protected Action<TClass, TProperty[]> SetterArr;
protected Func<TClass, List<TProperty>> GetterList;
protected Action<TClass, List<TProperty>> SetterList;
public override void ReadArray(TClass inf, NetDataReader r) { throw new InvalidTypeException("Unsupported type: " + typeof(TProperty) + "[]"); }
public override void WriteArray(TClass inf, NetDataWriter w) { throw new InvalidTypeException("Unsupported type: " + typeof(TProperty) + "[]"); }
public override void ReadList(TClass inf, NetDataReader r) { throw new InvalidTypeException("Unsupported type: List<" + typeof(TProperty) + ">"); }
public override void WriteList(TClass inf, NetDataWriter w) { throw new InvalidTypeException("Unsupported type: List<" + typeof(TProperty) + ">"); }
protected TProperty[] ReadArrayHelper(TClass inf, NetDataReader r)
{
ushort count = r.GetUShort();
var arr = GetterArr(inf);
arr = arr == null || arr.Length != count ? new TProperty[count] : arr;
SetterArr(inf, arr);
return arr;
}
protected TProperty[] WriteArrayHelper(TClass inf, NetDataWriter w)
{
var arr = GetterArr(inf);
w.Put((ushort)arr.Length);
return arr;
}
protected List<TProperty> ReadListHelper(TClass inf, NetDataReader r, out int len)
{
len = r.GetUShort();
var list = GetterList(inf);
if (list == null)
{
list = new List<TProperty>(len);
SetterList(inf, list);
}
return list;
}
protected List<TProperty> WriteListHelper(TClass inf, NetDataWriter w, out int len)
{
var list = GetterList(inf);
if (list == null)
{
len = 0;
w.Put(0);
return null;
}
len = list.Count;
w.Put((ushort)len);
return list;
}
public override void Init(MethodInfo getMethod, MethodInfo setMethod, CallType type)
{
base.Init(getMethod, setMethod, type);
switch (type)
{
case CallType.Array:
GetterArr = (Func<TClass, TProperty[]>)Delegate.CreateDelegate(typeof(Func<TClass, TProperty[]>), getMethod);
SetterArr = (Action<TClass, TProperty[]>)Delegate.CreateDelegate(typeof(Action<TClass, TProperty[]>), setMethod);
break;
case CallType.List:
GetterList = (Func<TClass, List<TProperty>>)Delegate.CreateDelegate(typeof(Func<TClass, List<TProperty>>), getMethod);
SetterList = (Action<TClass, List<TProperty>>)Delegate.CreateDelegate(typeof(Action<TClass, List<TProperty>>), setMethod);
break;
default:
Getter = (Func<TClass, TProperty>)Delegate.CreateDelegate(typeof(Func<TClass, TProperty>), getMethod);
Setter = (Action<TClass, TProperty>)Delegate.CreateDelegate(typeof(Action<TClass, TProperty>), setMethod);
break;
}
}
}
private abstract class FastCallSpecificAuto<TClass, TProperty> : FastCallSpecific<TClass, TProperty>
{
protected abstract void ElementRead(NetDataReader r, out TProperty prop);
protected abstract void ElementWrite(NetDataWriter w, ref TProperty prop);
public override void Read(TClass inf, NetDataReader r)
{
TProperty elem;
ElementRead(r, out elem);
Setter(inf, elem);
}
public override void Write(TClass inf, NetDataWriter w)
{
var elem = Getter(inf);
ElementWrite(w, ref elem);
}
public override void ReadArray(TClass inf, NetDataReader r)
{
var arr = ReadArrayHelper(inf, r);
for (int i = 0; i < arr.Length; i++)
ElementRead(r, out arr[i]);
}
public override void WriteArray(TClass inf, NetDataWriter w)
{
var arr = WriteArrayHelper(inf, w);
for (int i = 0; i < arr.Length; i++)
ElementWrite(w, ref arr[i]);
}
}
private sealed class FastCallStatic<TClass, TProperty> : FastCallSpecific<TClass, TProperty>
{
private readonly Action<NetDataWriter, TProperty> _writer;
private readonly Func<NetDataReader, TProperty> _reader;
public FastCallStatic(Action<NetDataWriter, TProperty> write, Func<NetDataReader, TProperty> read)
{
_writer = write;
_reader = read;
}
public override void Read(TClass inf, NetDataReader r) { Setter(inf, _reader(r)); }
public override void Write(TClass inf, NetDataWriter w) { _writer(w, Getter(inf)); }
public override void ReadList(TClass inf, NetDataReader r)
{
int len;
var list = ReadListHelper(inf, r, out len);
int listCount = list.Count;
if (len > listCount)
{
for (int i = 0; i < listCount; i++)
list[i] = _reader(r);
for (int i = listCount; i < len; i++)
list.Add(_reader(r));
return;
}
if (len < listCount)
list.RemoveRange(len, listCount - len);
for (int i = 0; i < len; i++)
list[i] = _reader(r);
}
public override void WriteList(TClass inf, NetDataWriter w)
{
int len;
var list = WriteListHelper(inf, w, out len);
for (int i = 0; i < len; i++)
_writer(w, list[i]);
}
public override void ReadArray(TClass inf, NetDataReader r)
{
var arr = ReadArrayHelper(inf, r);
int len = arr.Length;
for (int i = 0; i < len; i++)
arr[i] = _reader(r);
}
public override void WriteArray(TClass inf, NetDataWriter w)
{
var arr = WriteArrayHelper(inf, w);
int len = arr.Length;
for (int i = 0; i < len; i++)
_writer(w, arr[i]);
}
}
private sealed class FastCallStruct<TClass, TProperty> : FastCallSpecific<TClass, TProperty> where TProperty : struct, INetSerializable
{
private TProperty _p;
public override void Read(TClass inf, NetDataReader r)
{
_p.Deserialize(r);
Setter(inf, _p);
}
public override void Write(TClass inf, NetDataWriter w)
{
_p = Getter(inf);
_p.Serialize(w);
}
public override void ReadList(TClass inf, NetDataReader r)
{
int len;
var list = ReadListHelper(inf, r, out len);
int listCount = list.Count;
if (len > listCount)
{
for (int i = 0; i < listCount; i++)
list[i].Deserialize(r);
for (int i = listCount; i < len; i++)
{
var itm = default(TProperty);
itm.Deserialize(r);
list.Add(itm);
}
return;
}
if(len < listCount)
list.RemoveRange(len, listCount - len);
for (int i = 0; i < len; i++)
list[i].Deserialize(r);
}
public override void WriteList(TClass inf, NetDataWriter w)
{
int len;
var list = WriteListHelper(inf, w, out len);
for (int i = 0; i < len; i++)
list[i].Serialize(w);
}
public override void ReadArray(TClass inf, NetDataReader r)
{
var arr = ReadArrayHelper(inf, r);
int len = arr.Length;
for (int i = 0; i < len; i++)
arr[i].Deserialize(r);
}
public override void WriteArray(TClass inf, NetDataWriter w)
{
var arr = WriteArrayHelper(inf, w);
int len = arr.Length;
for (int i = 0; i < len; i++)
arr[i].Serialize(w);
}
}
private sealed class FastCallClass<TClass, TProperty> : FastCallSpecific<TClass, TProperty> where TProperty : class, INetSerializable
{
private readonly Func<TProperty> _constructor;
public FastCallClass(Func<TProperty> constructor) { _constructor = constructor; }
public override void Read(TClass inf, NetDataReader r)
{
var p = _constructor();
p.Deserialize(r);
Setter(inf, p);
}
public override void Write(TClass inf, NetDataWriter w)
{
var p = Getter(inf);
if(p != null)
p.Serialize(w);
}
public override void ReadList(TClass inf, NetDataReader r)
{
int len;
var list = ReadListHelper(inf, r, out len);
int listCount = list.Count;
if (len > listCount)
{
for (int i = 0; i < listCount; i++)
list[i].Deserialize(r);
for (int i = listCount; i < len; i++)
{
var itm = _constructor();
itm.Deserialize(r);
list.Add(itm);
}
return;
}
if (len < listCount)
list.RemoveRange(len, listCount - len);
for (int i = 0; i < len; i++)
list[i].Deserialize(r);
}
public override void WriteList(TClass inf, NetDataWriter w)
{
int len;
var list = WriteListHelper(inf, w, out len);
for (int i = 0; i < len; i++)
list[i].Serialize(w);
}
public override void ReadArray(TClass inf, NetDataReader r)
{
var arr = ReadArrayHelper(inf, r);
int len = arr.Length;
for (int i = 0; i < len; i++)
{
arr[i] = _constructor();
arr[i].Deserialize(r);
}
}
public override void WriteArray(TClass inf, NetDataWriter w)
{
var arr = WriteArrayHelper(inf, w);
int len = arr.Length;
for (int i = 0; i < len; i++)
arr[i].Serialize(w);
}
}
private class IntSerializer<T> : FastCallSpecific<T, int>
{
public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetInt()); }
public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetIntArray()); }
public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
}
private class UIntSerializer<T> : FastCallSpecific<T, uint>
{
public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetUInt()); }
public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetUIntArray()); }
public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
}
private class ShortSerializer<T> : FastCallSpecific<T, short>
{
public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetShort()); }
public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetShortArray()); }
public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
}
private class UShortSerializer<T> : FastCallSpecific<T, ushort>
{
public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetUShort()); }
public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetUShortArray()); }
public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
}
private class LongSerializer<T> : FastCallSpecific<T, long>
{
public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetLong()); }
public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetLongArray()); }
public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
}
private class ULongSerializer<T> : FastCallSpecific<T, ulong>
{
public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetULong()); }
public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetULongArray()); }
public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
}
private class ByteSerializer<T> : FastCallSpecific<T, byte>
{
public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetByte()); }
public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetBytesWithLength()); }
public override void WriteArray(T inf, NetDataWriter w) { w.PutBytesWithLength(GetterArr(inf)); }
}
private class SByteSerializer<T> : FastCallSpecific<T, sbyte>
{
public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetSByte()); }
public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetSBytesWithLength()); }
public override void WriteArray(T inf, NetDataWriter w) { w.PutSBytesWithLength(GetterArr(inf)); }
}
private class FloatSerializer<T> : FastCallSpecific<T, float>
{
public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetFloat()); }
public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetFloatArray()); }
public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
}
private class DoubleSerializer<T> : FastCallSpecific<T, double>
{
public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetDouble()); }
public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetDoubleArray()); }
public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
}
private class BoolSerializer<T> : FastCallSpecific<T, bool>
{
public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetBool()); }
public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf)); }
public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetBoolArray()); }
public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf)); }
}
private class CharSerializer<T> : FastCallSpecificAuto<T, char>
{
protected override void ElementWrite(NetDataWriter w, ref char prop) { w.Put(prop); }
protected override void ElementRead(NetDataReader r, out char prop) { prop = r.GetChar(); }
}
private class IPEndPointSerializer<T> : FastCallSpecificAuto<T, IPEndPoint>
{
protected override void ElementWrite(NetDataWriter w, ref IPEndPoint prop) { w.Put(prop); }
protected override void ElementRead(NetDataReader r, out IPEndPoint prop) { prop = r.GetNetEndPoint(); }
}
private class StringSerializer<T> : FastCallSpecific<T, string>
{
private readonly int _maxLength;
public StringSerializer(int maxLength) { _maxLength = maxLength > 0 ? maxLength : short.MaxValue; }
public override void Read(T inf, NetDataReader r) { Setter(inf, r.GetString(_maxLength)); }
public override void Write(T inf, NetDataWriter w) { w.Put(Getter(inf), _maxLength); }
public override void ReadArray(T inf, NetDataReader r) { SetterArr(inf, r.GetStringArray(_maxLength)); }
public override void WriteArray(T inf, NetDataWriter w) { w.PutArray(GetterArr(inf), _maxLength); }
}
private class EnumByteSerializer<T> : FastCall<T>
{
protected readonly PropertyInfo Property;
protected readonly Type PropertyType;
public EnumByteSerializer(PropertyInfo property, Type propertyType)
{
Property = property;
PropertyType = propertyType;
}
public override void Read(T inf, NetDataReader r) { Property.SetValue(inf, Enum.ToObject(PropertyType, r.GetByte()), null); }
public override void Write(T inf, NetDataWriter w) { w.Put((byte)Property.GetValue(inf, null)); }
public override void ReadArray(T inf, NetDataReader r) { throw new InvalidTypeException("Unsupported type: Enum[]"); }
public override void WriteArray(T inf, NetDataWriter w) { throw new InvalidTypeException("Unsupported type: Enum[]"); }
public override void ReadList(T inf, NetDataReader r) { throw new InvalidTypeException("Unsupported type: List<Enum>"); }
public override void WriteList(T inf, NetDataWriter w) { throw new InvalidTypeException("Unsupported type: List<Enum>"); }
}
private class EnumIntSerializer<T> : EnumByteSerializer<T>
{
public EnumIntSerializer(PropertyInfo property, Type propertyType) : base(property, propertyType) { }
public override void Read(T inf, NetDataReader r) { Property.SetValue(inf, Enum.ToObject(PropertyType, r.GetInt()), null); }
public override void Write(T inf, NetDataWriter w) { w.Put((int)Property.GetValue(inf, null)); }
}
private sealed class ClassInfo<T>
{
public static ClassInfo<T> Instance;
private readonly FastCall<T>[] _serializers;
private readonly int _membersCount;
public ClassInfo(List<FastCall<T>> serializers)
{
_membersCount = serializers.Count;
_serializers = serializers.ToArray();
}
public void Write(T obj, NetDataWriter writer)
{
for (int i = 0; i < _membersCount; i++)
{
var s = _serializers[i];
if (s.Type == CallType.Basic)
s.Write(obj, writer);
else if (s.Type == CallType.Array)
s.WriteArray(obj, writer);
else
s.WriteList(obj, writer);
}
}
public void Read(T obj, NetDataReader reader)
{
for (int i = 0; i < _membersCount; i++)
{
var s = _serializers[i];
if (s.Type == CallType.Basic)
s.Read(obj, reader);
else if(s.Type == CallType.Array)
s.ReadArray(obj, reader);
else
s.ReadList(obj, reader);
}
}
}
private abstract class CustomType
{
public abstract FastCall<T> Get<T>();
}
private sealed class CustomTypeStruct<TProperty> : CustomType where TProperty : struct, INetSerializable
{
public override FastCall<T> Get<T>() { return new FastCallStruct<T, TProperty>(); }
}
private sealed class CustomTypeClass<TProperty> : CustomType where TProperty : class, INetSerializable
{
private readonly Func<TProperty> _constructor;
public CustomTypeClass(Func<TProperty> constructor) { _constructor = constructor; }
public override FastCall<T> Get<T>() { return new FastCallClass<T, TProperty>(_constructor); }
}
private sealed class CustomTypeStatic<TProperty> : CustomType
{
private readonly Action<NetDataWriter, TProperty> _writer;
private readonly Func<NetDataReader, TProperty> _reader;
public CustomTypeStatic(Action<NetDataWriter, TProperty> writer, Func<NetDataReader, TProperty> reader)
{
_writer = writer;
_reader = reader;
}
public override FastCall<T> Get<T>() { return new FastCallStatic<T, TProperty>(_writer, _reader); }
}
/// <summary>
/// Register custom property type
/// </summary>
/// <typeparam name="T">INetSerializable structure</typeparam>
public void RegisterNestedType<T>() where T : struct, INetSerializable
{
_registeredTypes.Add(typeof(T), new CustomTypeStruct<T>());
}
/// <summary>
/// Register custom property type
/// </summary>
/// <typeparam name="T">INetSerializable class</typeparam>
public void RegisterNestedType<T>(Func<T> constructor) where T : class, INetSerializable
{
_registeredTypes.Add(typeof(T), new CustomTypeClass<T>(constructor));
}
/// <summary>
/// Register custom property type
/// </summary>
/// <typeparam name="T">Any packet</typeparam>
/// <param name="writer">custom type writer</param>
/// <param name="reader">custom type reader</param>
public void RegisterNestedType<T>(Action<NetDataWriter, T> writer, Func<NetDataReader, T> reader)
{
_registeredTypes.Add(typeof(T), new CustomTypeStatic<T>(writer, reader));
}
private NetDataWriter _writer;
private readonly int _maxStringLength;
private readonly Dictionary<Type, CustomType> _registeredTypes = new Dictionary<Type, CustomType>();
public NetSerializer() : this(0)
{
}
public NetSerializer(int maxStringLength)
{
_maxStringLength = maxStringLength;
}
private ClassInfo<T> RegisterInternal<T>()
{
if (ClassInfo<T>.Instance != null)
return ClassInfo<T>.Instance;
Type t = typeof(T);
var props = t.GetProperties(
BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.GetProperty |
BindingFlags.SetProperty);
var serializers = new List<FastCall<T>>();
for (int i = 0; i < props.Length; i++)
{
var property = props[i];
var propertyType = property.PropertyType;
var elementType = propertyType.IsArray ? propertyType.GetElementType() : propertyType;
var callType = propertyType.IsArray ? CallType.Array : CallType.Basic;
if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(List<>))
{
elementType = propertyType.GetGenericArguments()[0];
callType = CallType.List;
}
var getMethod = property.GetGetMethod();
var setMethod = property.GetSetMethod();
if (getMethod == null || setMethod == null)
continue;
FastCall<T> serialzer = null;
if (propertyType.IsEnum)
{
var underlyingType = Enum.GetUnderlyingType(propertyType);
if (underlyingType == typeof(byte))
serialzer = new EnumByteSerializer<T>(property, propertyType);
else if (underlyingType == typeof(int))
serialzer = new EnumIntSerializer<T>(property, propertyType);
else
throw new InvalidTypeException("Not supported enum underlying type: " + underlyingType.Name);
}
else if (elementType == typeof(string))
serialzer = new StringSerializer<T>(_maxStringLength);
else if (elementType == typeof(bool))
serialzer = new BoolSerializer<T>();
else if (elementType == typeof(byte))
serialzer = new ByteSerializer<T>();
else if (elementType == typeof(sbyte))
serialzer = new SByteSerializer<T>();
else if (elementType == typeof(short))
serialzer = new ShortSerializer<T>();
else if (elementType == typeof(ushort))
serialzer = new UShortSerializer<T>();
else if (elementType == typeof(int))
serialzer = new IntSerializer<T>();
else if (elementType == typeof(uint))
serialzer = new UIntSerializer<T>();
else if (elementType == typeof(long))
serialzer = new LongSerializer<T>();
else if (elementType == typeof(ulong))
serialzer = new ULongSerializer<T>();
else if (elementType == typeof(float))
serialzer = new FloatSerializer<T>();
else if (elementType == typeof(double))
serialzer = new DoubleSerializer<T>();
else if (elementType == typeof(char))
serialzer = new CharSerializer<T>();
else if (elementType == typeof(IPEndPoint))
serialzer = new IPEndPointSerializer<T>();
else
{
CustomType customType;
_registeredTypes.TryGetValue(elementType, out customType);
if (customType != null)
serialzer = customType.Get<T>();
}
if (serialzer != null)
{
serialzer.Init(getMethod, setMethod, callType);
serializers.Add(serialzer);
}
else
{
throw new InvalidTypeException("Unknown property type: " + propertyType.FullName);
}
}
ClassInfo<T>.Instance = new ClassInfo<T>(serializers);
return ClassInfo<T>.Instance;
}
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public void Register<T>()
{
RegisterInternal<T>();
}
/// <summary>
/// Reads packet with known type
/// </summary>
/// <param name="reader">NetDataReader with packet</param>
/// <returns>Returns packet if packet in reader is matched type</returns>
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public T Deserialize<T>(NetDataReader reader) where T : class, new()
{
var info = RegisterInternal<T>();
var result = new T();
try
{
info.Read(result, reader);
}
catch
{
return null;
}
return result;
}
/// <summary>
/// Reads packet with known type (non alloc variant)
/// </summary>
/// <param name="reader">NetDataReader with packet</param>
/// <param name="target">Deserialization target</param>
/// <returns>Returns true if packet in reader is matched type</returns>
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public bool Deserialize<T>(NetDataReader reader, T target) where T : class, new()
{
var info = RegisterInternal<T>();
try
{
info.Read(target, reader);
}
catch
{
return false;
}
return true;
}
/// <summary>
/// Serialize object to NetDataWriter (fast)
/// </summary>
/// <param name="writer">Serialization target NetDataWriter</param>
/// <param name="obj">Object to serialize</param>
/// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
public void Serialize<T>(NetDataWriter writer, T obj) where T : class, new()
{
RegisterInternal<T>().Write(obj, writer);
}
/// <summary>
/// Serialize object to byte array
/// </summary>
/// <param name="obj">Object to serialize</param>
/// <returns>byte array with serialized data</returns>
public byte[] Serialize<T>(T obj) where T : class, new()
{
if (_writer == null)
_writer = new NetDataWriter();
_writer.Reset();
Serialize(_writer, obj);
return _writer.CopyData();
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NetSerializer.cs.meta


fileFormatVersion: 2
guid: 15d07ef2204a4b04a9b6a94a1b7e61ae
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

426
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NtpPacket.cs


using System;
namespace LiteNetLib.Utils
{
/// <summary>
/// Represents RFC4330 SNTP packet used for communication to and from a network time server.
/// </summary>
/// <remarks>
/// <para>
/// Most applications should just use the <see cref="NtpPacket.CorrectionOffset" /> property.
/// </para>
/// <para>
/// The same data structure represents both request and reply packets.
/// Request and reply differ in which properties are set and to what values.
/// </para>
/// <para>
/// The only real property is <see cref="NtpPacket.Bytes" />.
/// All other properties read from and write to the underlying byte array
/// with the exception of <see cref="NtpPacket.DestinationTimestamp" />,
/// which is not part of the packet on network and it is instead set locally after receiving the packet.
/// </para>
/// <para>
/// Copied from <a href="https://guerrillantp.machinezoo.com/">GuerrillaNtp project</a>
/// with permission from Robert Vazan (@robertvazan) under MIT license, see https://github.com/RevenantX/LiteNetLib/pull/236
/// </para>
/// </remarks>
public class NtpPacket
{
private static readonly DateTime Epoch = new DateTime(1900, 1, 1);
/// <summary>
/// Gets RFC4330-encoded SNTP packet.
/// </summary>
/// <value>
/// Byte array containing RFC4330-encoded SNTP packet. It is at least 48 bytes long.
/// </value>
/// <remarks>
/// This is the only real property. All other properties except
/// <see cref="NtpPacket.DestinationTimestamp" /> read from or write to this byte array.
/// </remarks>
public byte[] Bytes { get; private set; }
/// <summary>
/// Gets the leap second indicator.
/// </summary>
/// <value>
/// Leap second warning, if any. Special value
/// <see cref="NtpLeapIndicator.AlarmCondition" /> indicates unsynchronized server clock.
/// Default is <see cref="NtpLeapIndicator.NoWarning" />.
/// </value>
/// <remarks>
/// Only servers fill in this property. Clients can consult this property for possible leap second warning.
/// </remarks>
public NtpLeapIndicator LeapIndicator
{
get { return (NtpLeapIndicator)((Bytes[0] & 0xC0) >> 6); }
}
/// <summary>
/// Gets or sets protocol version number.
/// </summary>
/// <value>
/// SNTP protocol version. Default is 4, which is the latest version at the time of this writing.
/// </value>
/// <remarks>
/// In request packets, clients should leave this property at default value 4.
/// Servers usually reply with the same protocol version.
/// </remarks>
public int VersionNumber
{
get { return (Bytes[0] & 0x38) >> 3; }
private set { Bytes[0] = (byte)((Bytes[0] & ~0x38) | value << 3); }
}
/// <summary>
/// Gets or sets SNTP packet mode, i.e. whether this is client or server packet.
/// </summary>
/// <value>
/// SNTP packet mode. Default is <see cref="NtpMode.Client" /> in newly created packets.
/// Server reply should have this property set to <see cref="NtpMode.Server" />.
/// </value>
public NtpMode Mode
{
get { return (NtpMode)(Bytes[0] & 0x07); }
private set { Bytes[0] = (byte)((Bytes[0] & ~0x07) | (int)value); }
}
/// <summary>
/// Gets server's distance from the reference clock.
/// </summary>
/// <value>
/// <para>
/// Distance from the reference clock. This property is set only in server reply packets.
/// Servers connected directly to reference clock hardware set this property to 1.
/// Statum number is incremented by 1 on every hop down the NTP server hierarchy.
/// </para>
/// <para>
/// Special value 0 indicates that this packet is a Kiss-o'-Death message
/// with kiss code stored in <see cref="NtpPacket.ReferenceId" />.
/// </para>
/// </value>
public int Stratum { get { return Bytes[1]; } }
/// <summary>
/// Gets server's preferred polling interval.
/// </summary>
/// <value>
/// Polling interval in log2 seconds, e.g. 4 stands for 16s and 17 means 131,072s.
/// </value>
public int Poll { get { return Bytes[2]; } }
/// <summary>
/// Gets the precision of server clock.
/// </summary>
/// <value>
/// Clock precision in log2 seconds, e.g. -20 for microsecond precision.
/// </value>
public int Precision { get { return (sbyte)Bytes[3]; } }
/// <summary>
/// Gets the total round-trip delay from the server to the reference clock.
/// </summary>
/// <value>
/// Round-trip delay to the reference clock. Normally a positive value smaller than one second.
/// </value>
public TimeSpan RootDelay { get { return GetTimeSpan32(4); } }
/// <summary>
/// Gets the estimated error in time reported by the server.
/// </summary>
/// <value>
/// Estimated error in time reported by the server. Normally a positive value smaller than one second.
/// </value>
public TimeSpan RootDispersion { get { return GetTimeSpan32(8); } }
/// <summary>
/// Gets the ID of the time source used by the server or Kiss-o'-Death code sent by the server.
/// </summary>
/// <value>
/// <para>
/// ID of server's time source or Kiss-o'-Death code.
/// Purpose of this property depends on value of <see cref="NtpPacket.Stratum" /> property.
/// </para>
/// <para>
/// Stratum 1 servers write here one of several special values that describe the kind of hardware clock they use.
/// </para>
/// <para>
/// Stratum 2 and lower servers set this property to IPv4 address of their upstream server.
/// If upstream server has IPv6 address, the address is hashed, because it doesn't fit in this property.
/// </para>
/// <para>
/// When server sets <see cref="NtpPacket.Stratum" /> to special value 0,
/// this property contains so called kiss code that instructs the client to stop querying the server.
/// </para>
/// </value>
public uint ReferenceId { get { return GetUInt32BE(12); } }
/// <summary>
/// Gets or sets the time when the server clock was last set or corrected.
/// </summary>
/// <value>
/// Time when the server clock was last set or corrected or <c>null</c> when not specified.
/// </value>
/// <remarks>
/// This Property is usually set only by servers. It usually lags server's current time by several minutes,
/// so don't use this property for time synchronization.
/// </remarks>
public DateTime? ReferenceTimestamp { get { return GetDateTime64(16); } }
/// <summary>
/// Gets or sets the time when the client sent its request.
/// </summary>
/// <value>
/// This property is <c>null</c> in request packets.
/// In reply packets, it is the time when the client sent its request.
/// Servers copy this value from <see cref="NtpPacket.TransmitTimestamp" />
/// that they find in received request packet.
/// </value>
/// <seealso cref="NtpPacket.CorrectionOffset" />
/// <seealso cref="NtpPacket.RoundTripTime" />
public DateTime? OriginTimestamp { get { return GetDateTime64(24); } }
/// <summary>
/// Gets or sets the time when the request was received by the server.
/// </summary>
/// <value>
/// This property is <c>null</c> in request packets.
/// In reply packets, it is the time when the server received client request.
/// </value>
/// <seealso cref="NtpPacket.CorrectionOffset" />
/// <seealso cref="NtpPacket.RoundTripTime" />
public DateTime? ReceiveTimestamp { get { return GetDateTime64(32); } }
/// <summary>
/// Gets or sets the time when the packet was sent.
/// </summary>
/// <value>
/// Time when the packet was sent. It should never be <c>null</c>.
/// Default value is <see cref="System.DateTime.UtcNow" />.
/// </value>
/// <remarks>
/// This property must be set by both clients and servers.
/// </remarks>
/// <seealso cref="NtpPacket.CorrectionOffset" />
/// <seealso cref="NtpPacket.RoundTripTime" />
public DateTime? TransmitTimestamp { get { return GetDateTime64(40); } private set { SetDateTime64(40, value); } }
/// <summary>
/// Gets or sets the time of reception of response SNTP packet on the client.
/// </summary>
/// <value>
/// Time of reception of response SNTP packet on the client. It is <c>null</c> in request packets.
/// </value>
/// <remarks>
/// This property is not part of the protocol and has to be set when reply packet is received.
/// </remarks>
/// <seealso cref="NtpPacket.CorrectionOffset" />
/// <seealso cref="NtpPacket.RoundTripTime" />
public DateTime? DestinationTimestamp { get; private set; }
/// <summary>
/// Gets the round-trip time to the server.
/// </summary>
/// <value>
/// Time the request spent traveling to the server plus the time the reply spent traveling back.
/// This is calculated from timestamps in the packet as <c>(t1 - t0) + (t3 - t2)</c>
/// where t0 is <see cref="NtpPacket.OriginTimestamp" />,
/// t1 is <see cref="NtpPacket.ReceiveTimestamp" />,
/// t2 is <see cref="NtpPacket.TransmitTimestamp" />,
/// and t3 is <see cref="NtpPacket.DestinationTimestamp" />.
/// This property throws an exception in request packets.
/// </value>
public TimeSpan RoundTripTime
{
get
{
CheckTimestamps();
return (ReceiveTimestamp.Value - OriginTimestamp.Value) + (DestinationTimestamp.Value - TransmitTimestamp.Value);
}
}
/// <summary>
/// Gets the offset that should be added to local time to synchronize it with server time.
/// </summary>
/// <value>
/// Time difference between server and client. It should be added to local time to get server time.
/// It is calculated from timestamps in the packet as <c>0.5 * ((t1 - t0) - (t3 - t2))</c>
/// where t0 is <see cref="NtpPacket.OriginTimestamp" />,
/// t1 is <see cref="NtpPacket.ReceiveTimestamp" />,
/// t2 is <see cref="NtpPacket.TransmitTimestamp" />,
/// and t3 is <see cref="NtpPacket.DestinationTimestamp" />.
/// This property throws an exception in request packets.
/// </value>
public TimeSpan CorrectionOffset
{
get
{
CheckTimestamps();
return TimeSpan.FromTicks(((ReceiveTimestamp.Value - OriginTimestamp.Value) - (DestinationTimestamp.Value - TransmitTimestamp.Value)).Ticks / 2);
}
}
/// <summary>
/// Initializes default request packet.
/// </summary>
/// <remarks>
/// Properties <see cref="NtpPacket.Mode" /> and <see cref="NtpPacket.VersionNumber" />
/// are set appropriately for request packet. Property <see cref="NtpPacket.TransmitTimestamp" />
/// is set to <see cref="System.DateTime.UtcNow" />.
/// </remarks>
public NtpPacket() : this(new byte[48])
{
Mode = NtpMode.Client;
VersionNumber = 4;
TransmitTimestamp = DateTime.UtcNow;
}
/// <summary>
/// Initializes packet from received data.
/// </summary>
internal NtpPacket(byte[] bytes)
{
if (bytes.Length < 48)
throw new ArgumentException("SNTP reply packet must be at least 48 bytes long.", "bytes");
Bytes = bytes;
}
/// <summary>
/// Initializes packet from data received from a server.
/// </summary>
/// <param name="bytes">Data received from the server.</param>
/// <param name="destinationTimestamp">Utc time of reception of response SNTP packet on the client.</param>
/// <returns></returns>
public static NtpPacket FromServerResponse(byte[] bytes, DateTime destinationTimestamp)
{
return new NtpPacket(bytes) { DestinationTimestamp = destinationTimestamp };
}
internal void ValidateRequest()
{
if (Mode != NtpMode.Client)
throw new InvalidOperationException("This is not a request SNTP packet.");
if (VersionNumber == 0)
throw new InvalidOperationException("Protocol version of the request is not specified.");
if (TransmitTimestamp == null)
throw new InvalidOperationException("TransmitTimestamp must be set in request packet.");
}
internal void ValidateReply()
{
if (Mode != NtpMode.Server)
throw new InvalidOperationException("This is not a reply SNTP packet.");
if (VersionNumber == 0)
throw new InvalidOperationException("Protocol version of the reply is not specified.");
if (Stratum == 0)
throw new InvalidOperationException(string.Format("Received Kiss-o'-Death SNTP packet with code 0x{0:x}.", ReferenceId));
if (LeapIndicator == NtpLeapIndicator.AlarmCondition)
throw new InvalidOperationException("SNTP server has unsynchronized clock.");
CheckTimestamps();
}
private void CheckTimestamps()
{
if (OriginTimestamp == null)
throw new InvalidOperationException("Origin timestamp is missing.");
if (ReceiveTimestamp == null)
throw new InvalidOperationException("Receive timestamp is missing.");
if (TransmitTimestamp == null)
throw new InvalidOperationException("Transmit timestamp is missing.");
if (DestinationTimestamp == null)
throw new InvalidOperationException("Destination timestamp is missing.");
}
private DateTime? GetDateTime64(int offset)
{
var field = GetUInt64BE(offset);
if (field == 0)
return null;
return new DateTime(Epoch.Ticks + Convert.ToInt64(field * (1.0 / (1L << 32) * 10000000.0)));
}
private void SetDateTime64(int offset, DateTime? value)
{
SetUInt64BE(offset, value == null ? 0 : Convert.ToUInt64((value.Value.Ticks - Epoch.Ticks) * (0.0000001 * (1L << 32))));
}
private TimeSpan GetTimeSpan32(int offset)
{
return TimeSpan.FromSeconds(GetInt32BE(offset) / (double)(1 << 16));
}
private ulong GetUInt64BE(int offset)
{
return SwapEndianness(BitConverter.ToUInt64(Bytes, offset));
}
private void SetUInt64BE(int offset, ulong value)
{
FastBitConverter.GetBytes(Bytes, offset, SwapEndianness(value));
}
private int GetInt32BE(int offset)
{
return (int)GetUInt32BE(offset);
}
private uint GetUInt32BE(int offset)
{
return SwapEndianness(BitConverter.ToUInt32(Bytes, offset));
}
private static uint SwapEndianness(uint x)
{
return ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24);
}
private static ulong SwapEndianness(ulong x)
{
return ((ulong)SwapEndianness((uint)x) << 32) | SwapEndianness((uint)(x >> 32));
}
}
/// <summary>
/// Represents leap second warning from the server that instructs the client to add or remove leap second.
/// </summary>
/// <seealso cref="NtpPacket.LeapIndicator" />
public enum NtpLeapIndicator
{
/// <summary>
/// No leap second warning. No action required.
/// </summary>
NoWarning,
/// <summary>
/// Warns the client that the last minute of the current day has 61 seconds.
/// </summary>
LastMinuteHas61Seconds,
/// <summary>
/// Warns the client that the last minute of the current day has 59 seconds.
/// </summary>
LastMinuteHas59Seconds,
/// <summary>
/// Special value indicating that the server clock is unsynchronized and the returned time is unreliable.
/// </summary>
AlarmCondition
}
/// <summary>
/// Describes SNTP packet mode, i.e. client or server.
/// </summary>
/// <seealso cref="NtpPacket.Mode" />
public enum NtpMode
{
/// <summary>
/// Identifies client-to-server SNTP packet.
/// </summary>
Client = 3,
/// <summary>
/// Identifies server-to-client SNTP packet.
/// </summary>
Server = 4,
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NtpPacket.cs.meta


fileFormatVersion: 2
guid: 17522d9782736174d811ad894ecf20be
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

175
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NtpRequest.cs


using System;
using System.Net;
using System.Net.Sockets;
#if NETSTANDARD || NETCOREAPP
using System.Threading.Tasks;
#endif
namespace LiteNetLib.Utils
{
/// <summary>
/// Make NTP request.
/// <para>
/// 1. Create the object by <see cref="Create(IPEndPoint,Action&lt;NtpPacket&gt;)"/> method.
/// </para>
/// <para>
/// 2. Use <see cref="Send"/> method to send requests.
/// </para>
/// <para>
/// 3. Call <see cref="Close"/> to release the socket AFTER you have received the response or some timeout.
/// If you close the socket too early, you may miss the response.
/// </para>
/// </summary>
public sealed class NtpRequest : INetSocketListener
{
public const int DefaultPort = 123;
private readonly NetSocket _socket;
private readonly Action<NtpPacket> _onRequestComplete;
private readonly IPEndPoint _ntpEndPoint;
/// <summary>
/// Initialize object, open socket.
/// </summary>
/// <param name="endPoint">NTP Server endpoint</param>
/// <param name="onRequestComplete">callback (called from other thread!)</param>
private NtpRequest(IPEndPoint endPoint, Action<NtpPacket> onRequestComplete)
{
_ntpEndPoint = endPoint;
_onRequestComplete = onRequestComplete;
// Create and start socket
_socket = new NetSocket(this);
_socket.Bind(
IPAddress.Any,
IPAddress.IPv6Any,
0,
false,
endPoint.AddressFamily == AddressFamily.InterNetworkV6 ? IPv6Mode.SeparateSocket : IPv6Mode.Disabled);
}
/// <summary>
/// Create the requests for NTP server, open socket.
/// </summary>
/// <param name="endPoint">NTP Server address.</param>
/// <param name="onRequestComplete">callback (called from other thread!)</param>
public static NtpRequest Create(IPEndPoint endPoint, Action<NtpPacket> onRequestComplete)
{
return new NtpRequest(endPoint, onRequestComplete);
}
/// <summary>
/// Create the requests for NTP server (default port), open socket.
/// </summary>
/// <param name="ipAddress">NTP Server address.</param>
/// <param name="onRequestComplete">callback (called from other thread!)</param>
public static NtpRequest Create(IPAddress ipAddress, Action<NtpPacket> onRequestComplete)
{
IPEndPoint endPoint = new IPEndPoint(ipAddress, DefaultPort);
return Create(endPoint, onRequestComplete);
}
/// <summary>
/// Create the requests for NTP server, open socket.
/// </summary>
/// <param name="ntpServerAddress">NTP Server address.</param>
/// <param name="port">port</param>
/// <param name="onRequestComplete">callback (called from other thread!)</param>
public static NtpRequest Create(string ntpServerAddress, int port, Action<NtpPacket> onRequestComplete)
{
IPEndPoint endPoint = NetUtils.MakeEndPoint(ntpServerAddress, port);
return Create(endPoint, onRequestComplete);
}
/// <summary>
/// Create the requests for NTP server (default port), open socket.
/// </summary>
/// <param name="ntpServerAddress">NTP Server address.</param>
/// <param name="onRequestComplete">callback (called from other thread!)</param>
public static NtpRequest Create(string ntpServerAddress, Action<NtpPacket> onRequestComplete)
{
IPEndPoint endPoint = NetUtils.MakeEndPoint(ntpServerAddress, DefaultPort);
return Create(endPoint, onRequestComplete);
}
#if NETSTANDARD || NETCOREAPP
/// <summary>
/// Requests asynchronously NTP server for time offset
/// </summary>
/// <param name="ntpServerAddress">NTP Server address.</param>
/// <returns>Scheduled task</returns>
public static async Task<NtpPacket> RequestAsync(string ntpServerAddress)
{
var t = new TaskCompletionSource<NtpPacket>();
await Task.Run(() =>
{
NtpRequest request = null;
request = Create(ntpServerAddress, (ntpPacket) =>
{
request.Close();
t.SetResult(ntpPacket);
});
request.Send();
});
return await t.Task;
}
#endif
/// <summary>
/// Send request to the NTP server calls callback (if success).
/// In case of error the callback is called with null param.
/// </summary>
public void Send()
{
SocketError errorCode = 0;
var packet = new NtpPacket();
packet.ValidateRequest(); // not necessary
byte[] sendData = packet.Bytes;
var sendCount = _socket.SendTo(sendData, 0, sendData.Length, _ntpEndPoint, ref errorCode);
if (errorCode != 0 || sendCount != sendData.Length)
{
_onRequestComplete(null);
}
}
/// <summary>
/// Close socket.
/// </summary>
public void Close()
{
_socket.Close(false);
}
/// <summary>
/// Handle received data: transform bytes to NtpPacket, close socket and call the callback.
/// </summary>
void INetSocketListener.OnMessageReceived(byte[] data, int length, SocketError errorCode, IPEndPoint remoteEndPoint)
{
DateTime destinationTimestamp = DateTime.UtcNow;
if (!remoteEndPoint.Equals(_ntpEndPoint))
return;
if (length < 48)
{
NetDebug.Write(NetLogLevel.Trace, "NTP response too short: {}", length);
_onRequestComplete(null);
return;
}
NtpPacket packet = NtpPacket.FromServerResponse(data, destinationTimestamp);
try
{
packet.ValidateReply();
}
catch (InvalidOperationException ex)
{
NetDebug.Write(NetLogLevel.Trace, "NTP response error: {}", ex.Message);
packet = null;
}
_onRequestComplete(packet);
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLib/Utils/NtpRequest.cs.meta


fileFormatVersion: 2
guid: ac0e7ca5f9a65c54b92bdfe59c6a5486
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

415
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLibTransport.cs


using LiteNetLib;
using MLAPI.Transports;
using MLAPI.Transports.Tasks;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
namespace LiteNetLibTransport
{
public class LiteNetLibTransport : Transport, INetEventListener
{
private enum HostType
{
None,
Server,
Client
}
public struct LiteChannel
{
public byte number;
public DeliveryMethod method;
}
public struct Event
{
public NetEventType type;
public ulong clientId;
public string channelName;
public NetPacketReader packetReader;
public DateTime dateTime;
}
[Tooltip("The port to listen on (if server) or connect to (if client)")]
public ushort Port = 7777;
[Tooltip("The address to connect to as client; ignored if server")]
public string Address = "127.0.0.1";
[Tooltip("Interval between ping packets used for detecting latency and checking connection, in seconds")]
public float PingInterval = 1f;
[Tooltip("Maximum duration for a connection to survive without receiving packets, in seconds")]
public float DisconnectTimeout = 5f;
[Tooltip("Delay between connection attempts, in seconds")]
public float ReconnectDelay = 0.5f;
[Tooltip("Maximum connection attempts before client stops and reports a disconnection")]
public int MaxConnectAttempts = 10;
public TransportChannel[] channels = new TransportChannel[0];
[Tooltip("Size of default buffer for decoding incoming packets, in bytes")]
public int MessageBufferSize = 1024 * 5;
[Tooltip("Simulated chance for a packet to be \"lost\", from 0 (no simulation) to 100 percent")]
public int SimulatePacketLossChance = 0;
[Tooltip("Simulated minimum additional latency for packets in milliseconds (0 for no simulation)")]
public int SimulateMinLatency = 0;
[Tooltip("Simulated maximum additional latency for packets in milliseconds (0 for no simulation")]
public int SimulateMaxLatency = 0;
private readonly Dictionary<ulong, NetPeer> peers = new Dictionary<ulong, NetPeer>();
private readonly Dictionary<string, LiteChannel> liteChannels = new Dictionary<string, LiteChannel>();
private NetManager netManager;
private Queue<Event> eventQueue = new Queue<Event>();
private byte[] messageBuffer;
private WeakReference temporaryBufferReference;
public override ulong ServerClientId => 0;
private HostType hostType;
private static readonly ArraySegment<byte> emptyArraySegment = new ArraySegment<byte>();
private SocketTask connectTask;
private void OnValidate()
{
PingInterval = Math.Max(0, PingInterval);
DisconnectTimeout = Math.Max(0, DisconnectTimeout);
ReconnectDelay = Math.Max(0, ReconnectDelay);
MaxConnectAttempts = Math.Max(0, MaxConnectAttempts);
MessageBufferSize = Math.Max(0, MessageBufferSize);
SimulatePacketLossChance = Math.Min(100, Math.Max(0, SimulatePacketLossChance));
SimulateMinLatency = Math.Max(0, SimulateMinLatency);
SimulateMaxLatency = Math.Max(SimulateMinLatency, SimulateMaxLatency);
}
private void Update()
{
netManager?.PollEvents();
}
public override bool IsSupported => Application.platform != RuntimePlatform.WebGLPlayer;
public override void Send(ulong clientId, ArraySegment<byte> data, string channelName)
{
LiteChannel channel = liteChannels[channelName];
if (peers.ContainsKey(clientId))
{
peers[clientId].Send(data.Array, data.Offset, data.Count, channel.method);
}
}
public override NetEventType PollEvent(out ulong clientId, out string channelName, out ArraySegment<byte> payload, out float receiveTime)
{
payload = emptyArraySegment;
clientId = 0;
channelName = null;
receiveTime = Time.realtimeSinceStartup;
if (eventQueue.Count > 0)
{
Event @event = eventQueue.Dequeue();
clientId = @event.clientId;
channelName = @event.channelName;
receiveTime = Time.realtimeSinceStartup - ((float)DateTime.UtcNow.Subtract(@event.dateTime).TotalSeconds);
if (@event.packetReader != null)
{
int size = @event.packetReader.UserDataSize;
byte[] data = messageBuffer;
if (size > messageBuffer.Length)
{
if (temporaryBufferReference != null && temporaryBufferReference.IsAlive && ((byte[])temporaryBufferReference.Target).Length >= size)
{
data = (byte[])temporaryBufferReference.Target;
}
else
{
data = new byte[size];
temporaryBufferReference = new WeakReference(data);
}
}
Buffer.BlockCopy(@event.packetReader.RawData, @event.packetReader.UserDataOffset, data, 0, size);
payload = new ArraySegment<byte>(data, 0, size);
@event.packetReader.Recycle();
}
return @event.type;
}
return NetEventType.Nothing;
}
public override SocketTasks StartClient()
{
SocketTask task = SocketTask.Working;
if (hostType != HostType.None)
{
throw new InvalidOperationException("Already started as " + hostType);
}
hostType = HostType.Client;
netManager.Start();
NetPeer peer = netManager.Connect(Address, Port, string.Empty);
if (peer.Id != 0)
{
throw new InvalidPacketException("Server peer did not have id 0: " + peer.Id);
}
peers[(ulong)peer.Id] = peer;
return task.AsTasks();
}
public override SocketTasks StartServer()
{
if (hostType != HostType.None)
{
throw new InvalidOperationException("Already started as " + hostType);
}
hostType = HostType.Server;
bool success = netManager.Start(Port);
return new SocketTask()
{
IsDone = true,
Message = null,
SocketError = SocketError.SocketError,
State = null,
Success = success,
TransportCode = -1,
TransportException = null
}.AsTasks();
}
public override void DisconnectRemoteClient(ulong clientId)
{
if (peers.ContainsKey(clientId))
{
peers[clientId].Disconnect();
}
}
public override void DisconnectLocalClient()
{
netManager.Flush();
netManager.DisconnectAll();
peers.Clear();
}
public override ulong GetCurrentRtt(ulong clientId)
{
if (!peers.ContainsKey(clientId))
{
return 0;
}
return (ulong)peers[clientId].Ping * 2;
}
public override void Shutdown()
{
netManager.Flush();
netManager.Stop();
peers.Clear();
hostType = HostType.None;
}
public override void Init()
{
liteChannels.Clear();
MapChannels(MLAPI_CHANNELS);
MapChannels(channels);
AddRpcResponseChannels();
if (liteChannels.Count > 64)
{
throw new InvalidOperationException("LiteNetLib supports up to 64 channels, got: " + liteChannels.Count);
}
messageBuffer = new byte[MessageBufferSize];
netManager = new NetManager(this)
{
PingInterval = SecondsToMilliseconds(PingInterval),
DisconnectTimeout = SecondsToMilliseconds(DisconnectTimeout),
ReconnectDelay = SecondsToMilliseconds(ReconnectDelay),
MaxConnectAttempts = MaxConnectAttempts,
SimulatePacketLoss = SimulatePacketLossChance > 0,
SimulationPacketLossChance = SimulatePacketLossChance,
SimulateLatency = SimulateMaxLatency > 0,
SimulationMinLatency = SimulateMinLatency,
SimulationMaxLatency = SimulateMaxLatency
};
}
private void MapChannels(TransportChannel[] channels)
{
byte id = (byte)liteChannels.Count;
for (int i = 0; i < channels.Length; i++)
{
liteChannels.Add(channels[i].Name, new LiteChannel()
{
number = id++,
method = ConvertChannelType(channels[i].Type)
});
}
}
private void AddRpcResponseChannels()
{
byte id = (byte)liteChannels.Count;
foreach (DeliveryMethod method in Enum.GetValues(typeof(DeliveryMethod)) as DeliveryMethod[])
{
liteChannels.Add("LITENETLIB_RESPONSE_" + method.ToString(), new LiteChannel()
{
number = id++,
method = method
});
}
}
private DeliveryMethod ConvertChannelType(ChannelType type)
{
switch (type)
{
case ChannelType.Unreliable:
{
return DeliveryMethod.Unreliable;
}
case ChannelType.UnreliableSequenced:
{
return DeliveryMethod.Sequenced;
}
case ChannelType.Reliable:
{
return DeliveryMethod.ReliableUnordered;
}
case ChannelType.ReliableSequenced:
{
return DeliveryMethod.ReliableOrdered;
}
case ChannelType.ReliableFragmentedSequenced:
{
return DeliveryMethod.ReliableOrdered;
}
default:
{
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
}
}
void INetEventListener.OnPeerConnected(NetPeer peer)
{
if (connectTask != null)
{
connectTask.Success = true;
connectTask.IsDone = true;
connectTask = null;
}
Event @event = new Event()
{
dateTime = DateTime.UtcNow,
type = NetEventType.Connect,
clientId = GetMLAPIClientId(peer)
};
peers[@event.clientId] = peer;
eventQueue.Enqueue(@event);
}
void INetEventListener.OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo)
{
if (connectTask != null)
{
connectTask.Success = false;
connectTask.IsDone = true;
connectTask = null;
}
Event @event = new Event()
{
dateTime = DateTime.UtcNow,
type = NetEventType.Disconnect,
clientId = GetMLAPIClientId(peer)
};
peers.Remove(@event.clientId);
eventQueue.Enqueue(@event);
}
void INetEventListener.OnNetworkError(IPEndPoint endPoint, SocketError socketError)
{
// Ignore
if (connectTask != null)
{
connectTask.SocketError = socketError;
connectTask.IsDone = true;
connectTask = null;
}
}
void INetEventListener.OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod)
{
Event @event = new Event()
{
dateTime = DateTime.UtcNow,
type = NetEventType.Data,
clientId = GetMLAPIClientId(peer),
packetReader = reader,
channelName = "LITENETLIB_RESPONSE_" + deliveryMethod.ToString()
};
eventQueue.Enqueue(@event);
}
void INetEventListener.OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType)
{
// Ignore
}
void INetEventListener.OnNetworkLatencyUpdate(NetPeer peer, int latency)
{
// Ignore
}
void INetEventListener.OnConnectionRequest(ConnectionRequest request)
{
request.Accept();
}
private ulong GetMLAPIClientId(NetPeer peer)
{
ulong clientId = (ulong)peer.Id;
if (hostType == HostType.Server)
{
clientId += 1;
}
return clientId;
}
private static int SecondsToMilliseconds(float seconds)
{
return (int)Mathf.Ceil(seconds * 1000);
}
}
}

11
Packages/com.unity.multiplayer.transport.litenet/Runtime/LiteNetLibTransport.cs.meta


fileFormatVersion: 2
guid: db28424c2ae12f64da25c9ecccded6b1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

16
Packages/com.unity.multiplayer.transport.litenet/Runtime/com.unity.multiplayer.transport.litenet.asmdef


{
"name": "LiteNEt MLAPI Transport",
"rootNamespace": "",
"references": [
"Unity.Multiplayer.MLAPI.Runtime"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": false,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

7
Packages/com.unity.multiplayer.transport.litenet/Runtime/com.unity.multiplayer.transport.litenet.asmdef.meta


fileFormatVersion: 2
guid: 255e067ad7348fc4682b169db21e7c05
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

16
Packages/com.unity.multiplayer.transport.litenet/package.json


{
"name": "com.unity.multiplayer.transport.litenet",
"displayName": "LiteNet Transport for MLAPI",
"version": "0.0.1-preview.1",
"unity": "2019.4",
"unityRelease": "8f1",
"description": "LiteNet Transport for MLAPI",
"keywords": [
"unity"
],
"dependencies": {
"com.unity.multiplayer.mlapi": "0.0.1-preview.1"
},
"type": "library",
"hideInEditor": false
}

7
Packages/com.unity.multiplayer.transport.litenet/package.json.meta


fileFormatVersion: 2
guid: 1dab2b0d4030b264683f7d356ef17655
PackageManifestImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存