public unsafe int Bind(NetworkInterfaceEndPoint endpoint) { var baselib = m_Baselib[0]; if (m_Baselib[0].m_Socket.handle != IntPtr.Zero) { #if ENABLE_UNITY_COLLECTIONS_CHECKS AllSockets.OpenSockets.Remove(new SocketList.SocketId { socket = m_Baselib[0].m_Socket }); #endif Binding.Baselib_RegisteredNetwork_Socket_UDP_Close(m_Baselib[0].m_Socket); baselib.m_Socket.handle = IntPtr.Zero; // Recreate the payloads to make sure we do not loose any items from the queue m_PayloadsRx.Dispose(); m_PayloadsRx = new Payloads(rxQueueSize, maximumPayloadSize); } var slice = m_LocalAndTempEndpoint.AtIndexAsSlice(0, (uint)Binding.Baselib_RegisteredNetwork_Endpoint_MaxSize); UnsafeUtility.MemCpy((void *)slice.data, endpoint.data, endpoint.dataLength); var error = default(ErrorState); NetworkEndpoint local; local.slice = slice; Binding.Baselib_NetworkAddress localAddress; Binding.Baselib_RegisteredNetwork_Endpoint_GetNetworkAddress(local, &localAddress, error.NativeErrorStatePtr); baselib.m_Socket = Binding.Baselib_RegisteredNetwork_Socket_UDP_Create( &localAddress, Binding.Baselib_NetworkAddress_AddressReuse.Allow, checked ((uint)txQueueSize), checked ((uint)rxQueueSize), error.NativeErrorStatePtr); if (error.ErrorCode != ErrorCode.Success) { m_Baselib[0] = baselib; return(-1); } // Schedule receive right away so we do not loose packets received before the first call to update int count = 0; var requests = stackalloc Binding.Baselib_RegisteredNetwork_Request[m_PayloadsRx.Capacity]; while (m_PayloadsRx.InUse < m_PayloadsRx.Capacity) { int handle = m_PayloadsRx.AcquireHandle(); requests[count] = m_PayloadsRx.GetRequestFromHandle(handle); requests[count].requestUserdata = (IntPtr)handle + 1; ++count; } if (count > 0) { Binding.Baselib_RegisteredNetwork_Socket_UDP_ScheduleRecv( baselib.m_Socket, requests, (uint)count, error.NativeErrorStatePtr); } #if ENABLE_UNITY_COLLECTIONS_CHECKS AllSockets.OpenSockets.Add(new SocketList.SocketId { socket = baselib.m_Socket }); #endif m_Baselib[0] = baselib; return(0); }
public unsafe void Execute() { var count = 0; var outstanding = Rx.InUse; var error = default(ErrorState); var requests = stackalloc Binding.Baselib_RegisteredNetwork_Request[Rx.Capacity]; if (outstanding > 0) { var pollCount = 0; while (Binding.Baselib_RegisteredNetwork_Socket_UDP_ProcessRecv(Baselib[0].m_Socket, error.NativeErrorStatePtr) == Binding.Baselib_RegisteredNetwork_ProcessStatus.Pending && pollCount++ < k_defaultRxQueueSize) { } var results = stackalloc Binding.Baselib_RegisteredNetwork_CompletionResult[outstanding]; // Pop Completed Requests off the CompletionQ count = (int)Binding.Baselib_RegisteredNetwork_Socket_UDP_DequeueRecv(Baselib[0].m_Socket, results, (uint)outstanding, error.NativeErrorStatePtr); if (error.ErrorCode != ErrorCode.Success) { Receiver.ReceiveErrorCode = (int)error.ErrorCode; return; } // Copy and run Append on each Packet. var stream = Receiver.GetDataStream(); var headerLength = UnsafeUtility.SizeOf <UdpCHeader>(); var address = default(NetworkInterfaceEndPoint); var indicies = stackalloc int[count]; for (int i = 0; i < count; i++) { if (results[i].status == Binding.Baselib_RegisteredNetwork_CompletionStatus.Failed) { // todo: report error? continue; } var receivedBytes = (int)results[i].bytesTransferred; var index = (int)results[i].requestUserdata - 1; var packet = Rx.GetRequestFromHandle(index); indicies[i] = index; outstanding--; // todo: make sure we avoid this copy var payloadLen = receivedBytes - headerLength; int dataStreamSize = Receiver.GetDataStreamSize(); if (Receiver.DynamicDataStreamSize()) { while (dataStreamSize + payloadLen >= stream.Length) { stream.ResizeUninitialized(stream.Length * 2); } } else if (dataStreamSize + payloadLen > stream.Length) { Receiver.ReceiveErrorCode = 10040;//(int)ErrorCode.OutOfMemory; continue; } UnsafeUtility.MemCpy( (byte *)stream.GetUnsafePtr() + dataStreamSize, (byte *)packet.payload.data + headerLength, payloadLen); var remote = packet.remoteEndpoint.slice; address.dataLength = (int)remote.size; UnsafeUtility.MemCpy(address.data, (void *)remote.data, (int)remote.size); Receiver.ReceiveCount += Receiver.AppendPacket(address, *(UdpCHeader *)packet.payload.data, receivedBytes); } // Reuse the requests after they have been processed. for (int i = 0; i < count; i++) { requests[i] = Rx.GetRequestFromHandle(indicies[i]); requests[i].requestUserdata = (IntPtr)indicies[i] + 1; } } while (Rx.InUse < Rx.Capacity) { int handle = Rx.AcquireHandle(); requests[count] = Rx.GetRequestFromHandle(handle); requests[count].requestUserdata = (IntPtr)handle + 1; ++count; } if (count > 0) { count = (int)Binding.Baselib_RegisteredNetwork_Socket_UDP_ScheduleRecv( Baselib[0].m_Socket, requests, (uint)count, error.NativeErrorStatePtr); if (error.ErrorCode != ErrorCode.Success) { Receiver.ReceiveErrorCode = (int)error.ErrorCode; } } }