Example #1
0
            [Obsolete] public unsafe int Send <T>(T driver, NetworkPipeline pipeline, NetworkConnection connection, NativeSlice <byte> payloadData) where T : struct, INetworkPipelineSender
            {
                var p = m_Pipelines[pipeline.Id - 1];

                var connectionId = connection.m_NetworkId;
                int startStage   = 0;

                // TODO: not really read-only, just hacking the safety system
                NativeArray <byte> tmpBuffer = sendBuffer;
                int *sendBufferLock          = (int *)tmpBuffer.GetUnsafeReadOnlyPtr();

                sendBufferLock += connectionId * sizePerConnection[SendSizeOffset] / 4;

                while (Interlocked.CompareExchange(ref *sendBufferLock, 1, 0) != 0)
                {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                    throw new InvalidOperationException("The parallel network driver needs to process a single unique connection per job, processing a single connection multiple times in a parallel for is not supported.");
#endif
                }

                NativeList <UpdatePipeline> currentUpdates = new NativeList <UpdatePipeline>(128, Allocator.Temp);
                ProcessPipelineSend(driver, startStage, pipeline, connection, payloadData, currentUpdates);
                // Move the updates requested in this iteration to the concurrent queue so it can be read/parsed in update routine
                for (int i = 0; i < currentUpdates.Length; ++i)
                {
                    m_SendStageNeedsUpdateWrite.Enqueue(currentUpdates[i]);
                }

                Interlocked.Exchange(ref *sendBufferLock, 0);
                return(payloadData.Length);
            }
Example #2
0
        public void GetPipelineBuffers(NetworkPipeline pipelineId, NetworkPipelineStageId stageId, NetworkConnection connection,
                                       out NativeArray <byte> readProcessingBuffer, out NativeArray <byte> writeProcessingBuffer,
                                       out NativeArray <byte> sharedBuffer)
        {
            if (pipelineId.Id < 1)
            {
                throw new InvalidOperationException("The specified pipeline is not valid");
            }
            if (stageId.IsValid == 0)
            {
                throw new InvalidOperationException("The specified pipeline stage is not valid");
            }
            var pipeline = m_Pipelines[pipelineId.Id - 1];

            int recvBufferOffset   = pipeline.receiveBufferOffset + sizePerConnection[RecveiveSizeOffset] * connection.InternalId;
            int sendBufferOffset   = pipeline.sendBufferOffset + sizePerConnection[SendSizeOffset] * connection.InternalId;
            int sharedBufferOffset = pipeline.sharedBufferOffset + sizePerConnection[SharedSizeOffset] * connection.InternalId;

            int  stageIndexInList;
            bool stageNotFound = true;

            for (stageIndexInList = pipeline.FirstStageIndex;
                 stageIndexInList < pipeline.FirstStageIndex + pipeline.NumStages;
                 stageIndexInList++)
            {
                if (m_StageList[stageIndexInList] == stageId.Index)
                {
                    stageNotFound = false;
                    break;
                }
                sendBufferOffset   += (m_StageCollection[m_StageList[stageIndexInList]].SendCapacity + AlignmentMinusOne) & (~AlignmentMinusOne);
                recvBufferOffset   += (m_StageCollection[m_StageList[stageIndexInList]].ReceiveCapacity + AlignmentMinusOne) & (~AlignmentMinusOne);
                sharedBufferOffset += (m_StageCollection[m_StageList[stageIndexInList]].SharedStateCapacity + AlignmentMinusOne) & (~AlignmentMinusOne);
            }

            if (stageNotFound)
            {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                throw new InvalidOperationException("Could not find stage ID " + stageId +
                                                    " make sure the type for this stage ID is added when the pipeline is created.");
#else
                writeProcessingBuffer = default;
                readProcessingBuffer  = default;
                sharedBuffer          = default;
                return;
#endif
            }

            writeProcessingBuffer = ((NativeArray <byte>)m_SendBuffer).GetSubArray(sendBufferOffset, m_StageCollection[m_StageList[stageIndexInList]].SendCapacity);
            readProcessingBuffer  = ((NativeArray <byte>)m_ReceiveBuffer).GetSubArray(recvBufferOffset, m_StageCollection[m_StageList[stageIndexInList]].ReceiveCapacity);
            sharedBuffer          = ((NativeArray <byte>)m_SharedBuffer).GetSubArray(sharedBufferOffset, m_StageCollection[m_StageList[stageIndexInList]].SharedStateCapacity);
        }
Example #3
0
        private void ProcessReceiveStage(int stage, NetworkPipeline pipeline, int internalBufferOffset, int internalSharedBufferOffset, ref NetworkPipelineContext ctx, ref NativeSlice <byte> inboundBuffer, ref NativeList <int> resumeQ, ref bool needsUpdate, ref bool needsSendUpdate)
        {
            bool needsResume = false;
            var  p           = m_Pipelines[pipeline.Id - 1];

            ctx.internalProcessBuffer =
                new NativeSlice <byte>(m_ReceiveBuffer, internalBufferOffset, m_StageCollection.GetReceiveCapacity(m_StageList[p.FirstStageIndex + stage]));
            ctx.internalSharedProcessBuffer =
                new NativeSlice <byte>(m_SharedBuffer, internalSharedBufferOffset, m_StageCollection.GetSharedStateCapacity(m_StageList[p.FirstStageIndex + stage]));
            var stageId = m_StageList[p.FirstStageIndex + stage];

            inboundBuffer = m_StageCollection.InvokeReceive(stageId, ctx, inboundBuffer, ref needsResume, ref needsUpdate, ref needsSendUpdate);

            if (needsResume)
            {
                resumeQ.Add(stage);
            }
        }
Example #4
0
        public void GetPipelineBuffers(NetworkPipeline pipelineId, int stageId, NetworkConnection connection,
                                       ref NativeSlice <byte> readProcessingBuffer, ref NativeSlice <byte> writeProcessingBuffer,
                                       ref NativeSlice <byte> sharedBuffer)
        {
            var pipeline = m_Pipelines[pipelineId.Id - 1];

            int recvBufferOffset   = pipeline.receiveBufferOffset + sizePerConnection[RecveiveSizeOffset] * connection.InternalId;
            int sendBufferOffset   = pipeline.sendBufferOffset + sizePerConnection[SendSizeOffset] * connection.InternalId;
            int sharedBufferOffset = pipeline.sharedBufferOffset + sizePerConnection[SharedSizeOffset] * connection.InternalId;

            int  stageIndexInList;
            bool stageNotFound = true;

            for (stageIndexInList = pipeline.FirstStageIndex;
                 stageIndexInList < pipeline.FirstStageIndex + pipeline.NumStages;
                 stageIndexInList++)
            {
                if (m_StageList[stageIndexInList] == stageId)
                {
                    stageNotFound = false;
                    break;
                }
                sendBufferOffset   += m_StageCollection.GetSendCapacity(m_StageList[stageIndexInList]);
                recvBufferOffset   += m_StageCollection.GetReceiveCapacity(m_StageList[stageIndexInList]);
                sharedBufferOffset += m_StageCollection.GetSharedStateCapacity(m_StageList[stageIndexInList]);
            }

            if (stageNotFound)
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            { throw new InvalidOperationException("Could not find stage ID " + stageId +
                                                  " make sure the type for this stage ID is added when the pipeline is created."); }
#else
            { return; }
#endif

            writeProcessingBuffer =
                new NativeSlice <byte>(m_SendBuffer, sendBufferOffset, m_StageCollection.GetSendCapacity(m_StageList[stageIndexInList]));
            readProcessingBuffer =
                new NativeSlice <byte>(m_ReceiveBuffer, recvBufferOffset, m_StageCollection.GetReceiveCapacity(m_StageList[stageIndexInList]));
            sharedBuffer =
                new NativeSlice <byte>(m_SharedBuffer, sharedBufferOffset, m_StageCollection.GetSharedStateCapacity(m_StageList[stageIndexInList]));
        }
Example #5
0
        private static void AddSendUpdate(NetworkConnection connection, int stageId, NetworkPipeline pipelineId, NativeList <UpdatePipeline> currentUpdates)
        {
            var newUpdate = new UpdatePipeline
            {
                connection = connection, stage = stageId, pipeline = pipelineId
            };
            bool uniqueItem = true;

            for (int j = 0; j < currentUpdates.Length; ++j)
            {
                if (currentUpdates[j].stage == newUpdate.stage &&
                    currentUpdates[j].pipeline.Id == newUpdate.pipeline.Id &&
                    currentUpdates[j].connection == newUpdate.connection)
                {
                    uniqueItem = false;
                }
            }
            if (uniqueItem)
            {
                currentUpdates.Add(newUpdate);
            }
        }
Example #6
0
 public NetworkEvent.Type PopEvent(NetworkDriver driver, out DataStreamReader stream, out NetworkPipeline pipeline)
 {
     return(driver.PopEventForConnection(this, out stream, out pipeline));
 }
Example #7
0
        private void ProcessReceiveStagesFrom <T>(T driver, int startStage, NetworkPipeline pipeline, NetworkConnection connection, NativeSlice <byte> buffer) where T : struct, INetworkPipelineReceiver
        {
            var p            = m_Pipelines[pipeline.Id - 1];
            var connectionId = connection.m_NetworkId;
            var resumeQ      = new NativeList <int>(16, Allocator.Temp);
            int resumeQStart = 0;

            NetworkPipelineContext ctx = default(NetworkPipelineContext);

            ctx.timestamp = Timestamp;
            var inboundBuffer = new NativeSlice <byte>(buffer, 0, buffer.Length);

            ctx.header = default(DataStreamWriter);
            NativeList <UpdatePipeline> sendUpdates = new NativeList <UpdatePipeline>(128, Allocator.Temp);

            while (true)
            {
                bool needsUpdate                = false;
                bool needsSendUpdate            = false;
                int  internalBufferOffset       = p.receiveBufferOffset + sizePerConnection[RecveiveSizeOffset] * connectionId;
                int  internalSharedBufferOffset = p.sharedBufferOffset + sizePerConnection[SharedSizeOffset] * connectionId;

                // Adjust offset accounting for stages in front of the starting stage, since we're parsing the stages in reverse order
                for (int st = 0; st < startStage; ++st)
                {
                    internalBufferOffset       += m_StageCollection.GetReceiveCapacity(m_StageList[p.FirstStageIndex + st]);
                    internalSharedBufferOffset += m_StageCollection.GetSharedStateCapacity(m_StageList[p.FirstStageIndex + st]);
                }

                for (int i = startStage; i >= 0; --i)
                {
                    ProcessReceiveStage(i, pipeline, internalBufferOffset, internalSharedBufferOffset, ref ctx, ref inboundBuffer, ref resumeQ, ref needsUpdate, ref needsSendUpdate);
                    if (needsUpdate)
                    {
                        var newUpdate = new UpdatePipeline
                        {
                            connection = connection, stage = i, pipeline = pipeline
                        };
                        bool uniqueItem = true;
                        for (int j = 0; j < m_ReceiveStageNeedsUpdate.Length; ++j)
                        {
                            if (m_ReceiveStageNeedsUpdate[j].stage == newUpdate.stage &&
                                m_ReceiveStageNeedsUpdate[j].pipeline.Id == newUpdate.pipeline.Id &&
                                m_ReceiveStageNeedsUpdate[j].connection == newUpdate.connection)
                            {
                                uniqueItem = false;
                            }
                        }
                        if (uniqueItem)
                        {
                            m_ReceiveStageNeedsUpdate.Add(newUpdate);
                        }
                    }

                    if (needsSendUpdate)
                    {
                        AddSendUpdate(connection, i, pipeline, m_SendStageNeedsUpdate);
                    }

                    if (inboundBuffer.Length == 0)
                    {
                        break;
                    }

                    // Offset needs to be adjusted for the next pipeline (the one in front of this one)
                    if (i > 0)
                    {
                        internalBufferOffset -=
                            m_StageCollection.GetReceiveCapacity(m_StageList[p.FirstStageIndex + i - 1]);
                        internalSharedBufferOffset -=
                            m_StageCollection.GetSharedStateCapacity(m_StageList[p.FirstStageIndex + i - 1]);
                    }

                    needsUpdate = false;
                }

                if (inboundBuffer.Length != 0)
                {
                    driver.PushDataEvent(connection, inboundBuffer);
                }

                if (resumeQStart >= resumeQ.Length)
                {
                    return;
                }

                startStage    = resumeQ[resumeQStart++];
                inboundBuffer = default(NativeSlice <byte>);
            }
        }
Example #8
0
            internal unsafe void ProcessPipelineSend <T>(T driver, int startStage, NetworkPipeline pipeline, NetworkConnection connection,
                                                         NativeSlice <byte> payloadBuffer, NativeList <UpdatePipeline> currentUpdates) where T : struct, INetworkPipelineSender
            {
                NetworkPipelineContext ctx = default(NetworkPipelineContext);

                ctx.timestamp = m_timestamp[0];
                var p            = m_Pipelines[pipeline.Id - 1];
                var connectionId = connection.m_NetworkId;

                var resumeQ      = new NativeList <int>(16, Allocator.Temp);
                int resumeQStart = 0;

                ctx.header = new DataStreamWriter(p.headerCapacity, Allocator.Temp);

                var inboundBuffer = default(InboundBufferVec);

                inboundBuffer.buffer1 = payloadBuffer;

                var prevHeader = new DataStreamWriter(p.headerCapacity, Allocator.Temp);

                while (true)
                {
                    int internalBufferOffset       = p.sendBufferOffset + sizePerConnection[SendSizeOffset] * connectionId;
                    int internalSharedBufferOffset = p.sharedBufferOffset + sizePerConnection[SharedSizeOffset] * connectionId;

                    bool needsUpdate = false;
                    // If this is not the first stage we need to fast forward the buffer offset to the correct place
                    if (startStage > 0)
                    {
                        for (int i = 0; i < startStage; ++i)
                        {
                            internalBufferOffset       += m_StageCollection.GetSendCapacity(m_StageList[p.FirstStageIndex + i]);
                            internalSharedBufferOffset += m_StageCollection.GetSharedStateCapacity(m_StageList[p.FirstStageIndex + i]);
                        }
                    }

                    for (int i = startStage; i < p.NumStages; ++i)
                    {
                        var prevInbound = inboundBuffer;
                        ProcessSendStage(i, internalBufferOffset, internalSharedBufferOffset, p, ref resumeQ, ref ctx, ref inboundBuffer, ref needsUpdate);
                        if (inboundBuffer.buffer1 == prevInbound.buffer1 &&
                            inboundBuffer.buffer2 == prevInbound.buffer2)
                        {
                            if (ctx.header.Length > 0)
                            {
                                if (prevHeader.Length > 0)
                                {
                                    ctx.header.WriteBytes(prevHeader.GetUnsafeReadOnlyPtr(), prevHeader.Length);
                                }
                                prevHeader.Clear();
                                var tempHeader = ctx.header;
                                ctx.header = prevHeader;
                                prevHeader = tempHeader;
                                if (inboundBuffer.buffer2.Length == 0)
                                {
                                    inboundBuffer.buffer2 = inboundBuffer.buffer1;
                                }
                                inboundBuffer.buffer1 = prevHeader.GetNativeSlice(0, prevHeader.Length);
                            }
                        }
                        else
                        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                            if (inboundBuffer.buffer2.Length > 0)
                            {
                                throw new InvalidOperationException("Pipeline send stages must return either the unmodified inbound buffers or a consolidated version with a single buffer");
                            }
#endif
                            // Prev header is now part of payload
                            prevHeader.Clear();
                            if (ctx.header.Length > 0)
                            {
                                var tempHeader = ctx.header;
                                ctx.header            = prevHeader;
                                prevHeader            = tempHeader;
                                inboundBuffer.buffer2 = inboundBuffer.buffer1;
                                inboundBuffer.buffer1 = prevHeader.GetNativeSlice(0, prevHeader.Length);
                            }
                        }
                        if (needsUpdate)
                        {
                            AddSendUpdate(connection, i, pipeline, currentUpdates);
                        }
                        if (inboundBuffer.buffer1.Length == 0)
                        {
                            break;
                        }

                        needsUpdate = false;

                        internalBufferOffset       += ctx.internalProcessBuffer.Length;
                        internalSharedBufferOffset += ctx.internalSharedProcessBuffer.Length;
                    }

                    if (inboundBuffer.buffer1.Length != 0)
                    {
                        var iov        = stackalloc network_iovec[4];
                        var pipelineId = pipeline.Id;
                        iov[0].buf = &pipelineId;
                        iov[0].len = 1;
                        iov[1].buf = ctx.header.GetUnsafePtr();
                        iov[1].len = ctx.header.Length;
                        iov[2].buf = inboundBuffer.buffer1.GetUnsafeReadOnlyPtr();
                        iov[2].len = inboundBuffer.buffer1.Length;
                        if (inboundBuffer.buffer2.Length > 0)
                        {
                            iov[3].buf = inboundBuffer.buffer2.GetUnsafeReadOnlyPtr();
                            iov[3].len = inboundBuffer.buffer2.Length;
                            // FIXME: handle send errors
                            driver.Send(connection, iov, 4);
                        }
                        else
                        {
                            driver.Send(connection, iov, 3);
                        }
                    }

                    if (resumeQStart >= resumeQ.Length)
                    {
                        break;
                    }

                    startStage = resumeQ[resumeQStart++];

                    prevHeader.Clear();
                    inboundBuffer = default(InboundBufferVec);
                }
            }
Example #9
0
 public bool Equals(NetworkPipeline connection)
 {
     return(connection.Id == Id);
 }
Example #10
0
 public int Send(NetworkPipeline pipe, NetworkConnection id, IntPtr data, int len)
 {
     return(m_genericConcurrent.Send(pipe, id, data, len));
 }
Example #11
0
 public int Send(NetworkPipeline pipe, NetworkConnection id, DataStreamWriter strm)
 {
     return(m_genericConcurrent.Send(pipe, id, strm));
 }
Example #12
0
 public int Send(NetworkPipeline pipe, NetworkConnection con, IntPtr data, int len)
 {
     return(m_genericDriver.Send(pipe, con, data, len));
 }
Example #13
0
 public int Send(NetworkPipeline pipe, NetworkConnection con, DataStreamWriter strm)
 {
     return(m_genericDriver.Send(pipe, con, strm));
 }
Example #14
0
 public void GetPipelineBuffers(NetworkPipeline pipeline, int stageId, NetworkConnection connection,
                                ref NativeSlice <byte> readProcessingBuffer, ref NativeSlice <byte> writeProcessingBuffer,
                                ref NativeSlice <byte> sharedBuffer)
 {
     m_genericDriver.GetPipelineBuffers(pipeline, stageId, connection, ref readProcessingBuffer, ref writeProcessingBuffer, ref sharedBuffer);
 }
Example #15
0
            internal unsafe int ProcessPipelineSend(NetworkDriver.Concurrent driver, int startStage, NetworkPipeline pipeline, NetworkConnection connection,
                                                    NetworkInterfaceSendHandle sendHandle, int headerSize, NativeList <UpdatePipeline> currentUpdates)
            {
                int retval = sendHandle.size;
                NetworkPipelineContext ctx = default(NetworkPipelineContext);

                ctx.timestamp = m_timestamp[0];
                var p            = m_Pipelines[pipeline.Id - 1];
                var connectionId = connection.m_NetworkId;

                var resumeQ      = new NativeList <int>(16, Allocator.Temp);
                int resumeQStart = 0;

#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (headerSize != p.headerCapacity + UnsafeUtility.SizeOf <UdpCHeader>() + 1 && sendHandle.data != IntPtr.Zero)
                {
                    throw new InvalidOperationException("Invalid header size.");
                }
#endif
                var inboundBuffer = default(InboundSendBuffer);
                if (sendHandle.data != IntPtr.Zero)
                {
                    inboundBuffer.bufferWithHeaders       = (byte *)sendHandle.data + UnsafeUtility.SizeOf <UdpCHeader>() + 1;
                    inboundBuffer.bufferWithHeadersLength = sendHandle.size - UnsafeUtility.SizeOf <UdpCHeader>() - 1;
                    inboundBuffer.buffer       = inboundBuffer.bufferWithHeaders + p.headerCapacity;
                    inboundBuffer.bufferLength = inboundBuffer.bufferWithHeadersLength - p.headerCapacity;
                }

                while (true)
                {
                    headerSize = p.headerCapacity;

                    int internalBufferOffset       = p.sendBufferOffset + sizePerConnection[SendSizeOffset] * connectionId;
                    int internalSharedBufferOffset = p.sharedBufferOffset + sizePerConnection[SharedSizeOffset] * connectionId;

                    bool needsUpdate = false;
                    // If this is not the first stage we need to fast forward the buffer offset to the correct place
                    if (startStage > 0)
                    {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                        if (inboundBuffer.bufferWithHeadersLength > 0)
                        {
                            throw new InvalidOperationException("Can't start from a stage with a buffer");
                        }
#endif
                        for (int i = 0; i < startStage; ++i)
                        {
                            internalBufferOffset       += (m_StageCollection[m_StageList[p.FirstStageIndex + i]].SendCapacity + AlignmentMinusOne) & (~AlignmentMinusOne);
                            internalSharedBufferOffset += (m_StageCollection[m_StageList[p.FirstStageIndex + i]].SharedStateCapacity + AlignmentMinusOne) & (~AlignmentMinusOne);
                            headerSize -= m_StageCollection[m_StageList[p.FirstStageIndex + i]].HeaderCapacity;
                        }
                    }

                    for (int i = startStage; i < p.NumStages; ++i)
                    {
                        int stageHeaderCapacity = m_StageCollection[m_StageList[p.FirstStageIndex + i]].HeaderCapacity;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                        if (stageHeaderCapacity > headerSize)
                        {
                            throw new InvalidOperationException("Not enough header space");
                        }
#endif
                        inboundBuffer.headerPadding = headerSize;
                        headerSize -= stageHeaderCapacity;
                        if (stageHeaderCapacity > 0 && inboundBuffer.bufferWithHeadersLength > 0)
                        {
                            var headerArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <byte>(inboundBuffer.bufferWithHeaders + headerSize, stageHeaderCapacity, Allocator.Invalid);
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                            NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref headerArray, AtomicSafetyHandle.GetTempMemoryHandle());
#endif
                            ctx.header = new DataStreamWriter(headerArray);
                        }
                        else
                        {
                            ctx.header = new DataStreamWriter(stageHeaderCapacity, Allocator.Temp);
                        }
                        var prevInbound = inboundBuffer;
                        ProcessSendStage(i, internalBufferOffset, internalSharedBufferOffset, p, ref resumeQ, ref ctx, ref inboundBuffer, ref needsUpdate);

                        if (needsUpdate)
                        {
                            AddSendUpdate(connection, i, pipeline, currentUpdates);
                        }
                        if (inboundBuffer.bufferWithHeadersLength == 0)
                        {
                            break;
                        }

#if ENABLE_UNITY_COLLECTIONS_CHECKS
                        if (inboundBuffer.headerPadding != prevInbound.headerPadding)
                        {
                            throw new InvalidOperationException("Changing the header padding in a pipeline is not supported");
                        }
#endif
                        if (inboundBuffer.buffer != prevInbound.buffer)
                        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                            if (inboundBuffer.buffer != inboundBuffer.bufferWithHeaders + inboundBuffer.headerPadding ||
                                inboundBuffer.bufferLength + inboundBuffer.headerPadding > inboundBuffer.bufferWithHeadersLength)
                            {
                                throw new InvalidOperationException("When creating an internal buffer in piplines the buffer must be a subset of the buffer width headers");
                            }
#endif

                            // Copy header to new buffer so it is part of the payload
                            UnsafeUtility.MemCpy(inboundBuffer.bufferWithHeaders + headerSize, ctx.header.AsNativeArray().GetUnsafeReadOnlyPtr(), ctx.header.Length);
                        }
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                        else
                        {
                            if (inboundBuffer.bufferWithHeaders != prevInbound.bufferWithHeaders)
                            {
                                throw new InvalidOperationException("Changing the send buffer with headers without changing the buffer is not supported");
                            }
                        }
#endif
                        if (ctx.header.Length < stageHeaderCapacity)
                        {
                            int wastedSpace = stageHeaderCapacity - ctx.header.Length;
                            // Remove wasted space in the header
                            UnsafeUtility.MemMove(inboundBuffer.buffer - wastedSpace, inboundBuffer.buffer, inboundBuffer.bufferLength);
                        }

                        // Update the inbound buffer for next iteration
                        inboundBuffer.buffer       = inboundBuffer.bufferWithHeaders + headerSize;
                        inboundBuffer.bufferLength = ctx.header.Length + inboundBuffer.bufferLength;


                        needsUpdate = false;

                        internalBufferOffset       += (ctx.internalProcessBufferLength + AlignmentMinusOne) & (~AlignmentMinusOne);
                        internalSharedBufferOffset += (ctx.internalSharedProcessBufferLength + AlignmentMinusOne) & (~AlignmentMinusOne);
                    }

                    if (inboundBuffer.bufferLength != 0)
                    {
                        if (sendHandle.data != IntPtr.Zero && inboundBuffer.bufferWithHeaders == (byte *)sendHandle.data + UnsafeUtility.SizeOf <UdpCHeader>() + 1)
                        {
                            // Actually send the data - after collapsing it again
                            if (inboundBuffer.buffer != inboundBuffer.bufferWithHeaders)
                            {
                                UnsafeUtility.MemMove(inboundBuffer.bufferWithHeaders, inboundBuffer.buffer, inboundBuffer.bufferLength);
                                inboundBuffer.buffer = inboundBuffer.bufferWithHeaders;
                            }
                            ((byte *)sendHandle.data)[UnsafeUtility.SizeOf <UdpCHeader>()] = (byte)pipeline.Id;
                            int sendSize = UnsafeUtility.SizeOf <UdpCHeader>() + 1 + inboundBuffer.bufferLength;
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                            if (sendSize > sendHandle.size)
                            {
                                throw new InvalidOperationException("Pipeline increased the data in the buffer, this is not allowed");
                            }
#endif
                            sendHandle.size = sendSize;
                            retval          = driver.CompleteSend(connection, sendHandle);
                            sendHandle      = default;
                        }
                        else
                        {
                            // Sending without pipeline, the correct pipeline will be added by the default flags when this is called
                            var writer = driver.BeginSend(connection);
                            writer.WriteByte((byte)pipeline.Id);
                            writer.WriteBytes(inboundBuffer.buffer, inboundBuffer.bufferLength);
                            if (writer.HasFailedWrites)
                            {
                                driver.AbortSend(writer);
                            }
                            else
                            {
                                driver.EndSend(writer);
                            }
                        }
                    }

                    if (resumeQStart >= resumeQ.Length)
                    {
                        break;
                    }

                    startStage = resumeQ[resumeQStart++];

                    inboundBuffer = default(InboundSendBuffer);
                }
                if (sendHandle.data != IntPtr.Zero)
                {
                    driver.AbortSend(sendHandle);
                }
                return(retval);
            }
Example #16
0
            public unsafe int SendHeaderCapacity(NetworkPipeline pipeline)
            {
                var p = m_Pipelines[pipeline.Id - 1];

                return(p.headerCapacity);
            }