您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
164 行
5.0 KiB
164 行
5.0 KiB
using System;
|
|
using System.Diagnostics;
|
|
using System.Runtime.InteropServices;
|
|
using Unity.Collections;
|
|
using Unity.Networking.Transport.Utilities;
|
|
using Unity.Collections.LowLevel.Unsafe;
|
|
using Unity.Jobs;
|
|
using Unity.Networking.Transport.Protocols;
|
|
using Random = Unity.Mathematics.Random;
|
|
|
|
namespace Unity.Networking.Transport
|
|
{
|
|
internal struct IPCManager
|
|
{
|
|
public static IPCManager Instance = new IPCManager();
|
|
|
|
[StructLayout(LayoutKind.Explicit)]
|
|
internal unsafe struct IPCData
|
|
{
|
|
[FieldOffset(0)] public int from;
|
|
[FieldOffset(4)] public int length;
|
|
[FieldOffset(8)] public fixed byte data[NetworkParameterConstants.MTU];
|
|
}
|
|
|
|
private NativeMultiQueue<IPCData> m_IPCQueue;
|
|
private NativeHashMap<ushort, int> m_IPCChannels;
|
|
|
|
internal static JobHandle ManagerAccessHandle;
|
|
|
|
public bool IsCreated => m_IPCQueue.IsCreated;
|
|
|
|
private int m_RefCount;
|
|
|
|
public void AddRef()
|
|
{
|
|
if (m_RefCount == 0)
|
|
{
|
|
m_IPCQueue = new NativeMultiQueue<IPCData>(128);
|
|
m_IPCChannels = new NativeHashMap<ushort, int>(64, Allocator.Persistent);
|
|
}
|
|
++m_RefCount;
|
|
}
|
|
|
|
public void Release()
|
|
{
|
|
--m_RefCount;
|
|
if (m_RefCount == 0)
|
|
{
|
|
ManagerAccessHandle.Complete();
|
|
m_IPCQueue.Dispose();
|
|
m_IPCChannels.Dispose();
|
|
}
|
|
}
|
|
|
|
internal unsafe void Update(NetworkInterfaceEndPoint local, NativeQueue<QueuedSendMessage> queue)
|
|
{
|
|
QueuedSendMessage val;
|
|
while (queue.TryDequeue(out val))
|
|
{
|
|
var ipcData = new IPCData();
|
|
UnsafeUtility.MemCpy(ipcData.data, val.Data, val.DataLength);
|
|
ipcData.length = val.DataLength;
|
|
ipcData.from = *(int*)local.data;
|
|
m_IPCQueue.Enqueue(*(int*)val.Dest.data, ipcData);
|
|
}
|
|
}
|
|
|
|
public unsafe NetworkInterfaceEndPoint CreateEndPoint(ushort port)
|
|
{
|
|
ManagerAccessHandle.Complete();
|
|
int id = 0;
|
|
if (port == 0)
|
|
{
|
|
while (id == 0)
|
|
{
|
|
port = RandomHelpers.GetRandomUShort();
|
|
if (!m_IPCChannels.TryGetValue(port, out _))
|
|
{
|
|
id = m_IPCChannels.Count() + 1;
|
|
m_IPCChannels.TryAdd(port, id);
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if (!m_IPCChannels.TryGetValue(port, out id))
|
|
{
|
|
id = m_IPCChannels.Count() + 1;
|
|
m_IPCChannels.TryAdd(port, id);
|
|
}
|
|
}
|
|
|
|
var endpoint = default(NetworkInterfaceEndPoint);
|
|
endpoint.dataLength = 4;
|
|
*(int*) endpoint.data = id;
|
|
|
|
return endpoint;
|
|
}
|
|
public unsafe bool GetEndPointPort(NetworkInterfaceEndPoint ep, out ushort port)
|
|
{
|
|
ManagerAccessHandle.Complete();
|
|
int id = *(int*) ep.data;
|
|
var values = m_IPCChannels.GetValueArray(Allocator.Temp);
|
|
var keys = m_IPCChannels.GetKeyArray(Allocator.Temp);
|
|
port = 0;
|
|
for (var i = 0; i < m_IPCChannels.Count(); ++i)
|
|
{
|
|
if (values[i] == id)
|
|
{
|
|
port = keys[i];
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public unsafe int PeekNext(NetworkInterfaceEndPoint local, void* slice, out int length, out NetworkInterfaceEndPoint from)
|
|
{
|
|
ManagerAccessHandle.Complete();
|
|
IPCData data;
|
|
from = default(NetworkInterfaceEndPoint);
|
|
length = 0;
|
|
|
|
if (m_IPCQueue.Peek(*(int*)local.data, out data))
|
|
{
|
|
UnsafeUtility.MemCpy(slice, data.data, data.length);
|
|
|
|
length = data.length;
|
|
}
|
|
|
|
GetEndPointByHandle(data.from, out from);
|
|
|
|
return length;
|
|
}
|
|
|
|
public unsafe int ReceiveMessageEx(NetworkInterfaceEndPoint local, void* payloadData, int payloadLen, ref NetworkInterfaceEndPoint remote)
|
|
{
|
|
IPCData data;
|
|
if (!m_IPCQueue.Peek(*(int*)local.data, out data))
|
|
return 0;
|
|
GetEndPointByHandle(data.from, out remote);
|
|
|
|
var totalLength = Math.Min(payloadLen, data.length);
|
|
UnsafeUtility.MemCpy(payloadData, data.data, totalLength);
|
|
|
|
if (totalLength < data.length)
|
|
return -1;
|
|
m_IPCQueue.Dequeue(*(int*)local.data, out data);
|
|
|
|
return totalLength;
|
|
}
|
|
|
|
private unsafe void GetEndPointByHandle(int handle, out NetworkInterfaceEndPoint endpoint)
|
|
{
|
|
var temp = default(NetworkInterfaceEndPoint);
|
|
temp.dataLength = 4;
|
|
*(int*)temp.data = handle;
|
|
|
|
endpoint = temp;
|
|
}
|
|
}
|
|
}
|