Exemplo n.º 1
0
        /// <summary>
        /// Store the packet for possible later resends, and fill in the header we'll use to send it (populate with
        /// sequence ID, last acknowledged ID from remote with ackmask.
        /// </summary>
        /// <param name="context">Pipeline context, the reliability shared state is used here.</param>
        /// <param name="inboundBuffer">Buffer with packet data.</param>
        /// <param name="header">Packet header which will be populated.</param>
        /// <returns>Sequence ID assigned to this packet.</returns>
        public static unsafe int Write(NetworkPipelineContext context, InboundBufferVec inboundBuffer, ref PacketHeader header)
        {
            SharedContext *reliable = (SharedContext *)context.internalSharedProcessBuffer.GetUnsafePtr();

            var sequence = (ushort)reliable->SentPackets.Sequence;

            if (!TryAquire(context.internalProcessBuffer, sequence))
            {
                reliable->errorCode = ErrorCodes.OutgoingQueueIsFull;
                return((int)ErrorCodes.OutgoingQueueIsFull);
            }
            reliable->stats.PacketsSent++;

            header.SequenceId      = sequence;
            header.AckedSequenceId = (ushort)reliable->ReceivedPackets.Sequence;
            header.AckMask         = reliable->ReceivedPackets.AckMask;

            reliable->ReceivedPackets.Acked = reliable->ReceivedPackets.Sequence;

            // Attach our processing time of the packet we're acknowledging (time between receiving it and sending this ack)
            header.ProcessingTime =
                CalculateProcessingTime(context.internalSharedProcessBuffer, header.AckedSequenceId, context.timestamp);

            reliable->SentPackets.Sequence = (ushort)(reliable->SentPackets.Sequence + 1);
            SetHeaderAndPacket(context.internalProcessBuffer, sequence, header, inboundBuffer, context.timestamp);

            StoreTimestamp(context.internalSharedProcessBuffer, sequence, context.timestamp);

            return(sequence);
        }
Exemplo n.º 2
0
        public unsafe bool DelayPacket(ref NetworkPipelineContext ctx, InboundBufferVec inboundBuffer,
            ref bool needsUpdate,
            long timestamp)
        {
            // Find empty slot in bookkeeping data space to track this packet
            int packetPayloadOffset = 0;
            int packetDataOffset = 0;
            var processBufferPtr = (byte*) ctx.internalProcessBuffer.GetUnsafePtr();
            bool foundSlot = GetEmptyDataSlot(processBufferPtr, ref packetPayloadOffset, ref packetDataOffset);

            if (!foundSlot)
            {
                //UnityEngine.Debug.LogWarning("No space left for delaying packet (" + m_PacketCount + " packets in queue)");
                return false;
            }

            NativeSlice<byte> packetPayload =
                new NativeSlice<byte>(ctx.internalProcessBuffer, packetPayloadOffset,
                    inboundBuffer.buffer1.Length + inboundBuffer.buffer2.Length);

            StorePacketPayload(packetPayload, inboundBuffer.buffer1, inboundBuffer.buffer2);

            // Add tracking for this packet so we can resurrect later
            DelayedPacket packet;
            packet.delayUntil = timestamp + m_PacketDelayMs;
            packet.processBufferOffset = packetPayloadOffset;
            packet.packetSize = inboundBuffer.buffer1.Length + inboundBuffer.buffer2.Length;
            byte* packetPtr = (byte*) &packet;
            UnsafeUtility.MemCpy(processBufferPtr + packetDataOffset, packetPtr, UnsafeUtility.SizeOf<DelayedPacket>());

            // Schedule an update call so packet can be resurrected later
            needsUpdate = true;

            return true;
        }
Exemplo n.º 3
0
        public InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate)
        {
            var len1 = inboundBuffer.buffer1.Length;
            var len2 = inboundBuffer.buffer2.Length;

            for (int i = 0; i < len1; ++i)
            {
                ctx.internalProcessBuffer[i] = (byte)(inboundBuffer.buffer1[i] ^ 0xff);
            }
            for (int i = 0; i < len2; ++i)
            {
                ctx.internalProcessBuffer[len1 + i] = (byte)(inboundBuffer.buffer2[i] ^ 0xff);
            }
            var nextInbound = default(InboundBufferVec);

            nextInbound.buffer1 = new NativeSlice <byte>(ctx.internalProcessBuffer, 0, len1 + len2);
            return(nextInbound);
        }
Exemplo n.º 4
0
        public unsafe InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate)
        {
            var sendData = (int *)ctx.internalProcessBuffer.GetUnsafePtr();

            for (int i = 1; i <= 3; ++i)
            {
                Assert.AreEqual(*sendData, i * 10);
                sendData++;
            }
            var sharedData = (int *)ctx.internalSharedProcessBuffer.GetUnsafePtr();

            for (int i = 7; i <= 8; ++i)
            {
                Assert.AreEqual(*sharedData, i * 10);
                sharedData++;
            }
            return(inboundBuffer);
        }
Exemplo n.º 5
0
 public InboundBufferVec Send(NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate)
 {
     ctx.header.Write((int)2);
     return(inboundBuffer);
 }
Exemplo n.º 6
0
        public InboundBufferVec InvokeSend(int pipelineStageId, NetworkPipelineContext ctx, InboundBufferVec inboundBuffer, ref bool needsResume, ref bool needsUpdate)
        {
            switch (pipelineStageId)
            {
            case 0:
                return(testPipelineStageWithHeader.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate));

            case 1:
                return(testEncryptPipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate));

            case 2:
                return(testEncryptInPlacePipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate));

            case 3:
                return(testInvertPipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate));

            case 4:
                return(testDelayedReadPipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate));

            case 5:
                return(testDelayedSendPipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate));

            case 6:
                return(testUnreliableSequencedPipelineStage.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate));

            case 7:
                return(testPipelineStageWithHeaderTwo.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate));

            case 8:
                return(testPipelineWithInitializers.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate));

            case 9:
                return(testPipelineWithInitializersTwo.Send(ctx, inboundBuffer, ref needsResume, ref needsUpdate));
            }
            return(inboundBuffer);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Write packet, packet header and tracking information to the given buffer space. This buffer
        /// should contain the reliability Context at the front, that contains the capacity of the buffer
        /// and pointer offsets needed to find the slots we can copy the packet to.
        /// </summary>
        /// <param name="self">Buffer space where we can store packets.</param>
        /// <param name="sequence">The sequence ID of the packet, this is used to find a slot inside the buffer.</param>
        /// <param name="header">The packet header which we'll store with the packet payload.</param>
        /// <param name="data">The packet data which we're storing.</param>
        /// <exception cref="OverflowException"></exception>
        public static unsafe void SetHeaderAndPacket(NativeSlice <byte> self, int sequence, PacketHeader header, InboundBufferVec data, long timestamp)
        {
            byte *   ptr       = (byte *)self.GetUnsafePtr();
            Context *ctx       = (Context *)ptr;
            int      totalSize = data.buffer1.Length + data.buffer2.Length;

            if (totalSize > ctx->DataStride)
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            { throw new OverflowException(); }
#else
            { return; }
#endif
            var index = sequence % ctx->Capacity;

            PacketInformation *info = GetPacketInformation(self, sequence);
            info->SequenceId = sequence;
            info->Size       = totalSize;
            info->SendTime   = timestamp;

            Packet *packet = GetPacket(self, sequence);
            packet->Header = header;
            var   offset  = (ctx->DataPtrOffset + (index * ctx->DataStride)) + UnsafeUtility.SizeOf <PacketHeader>();
            void *dataPtr = (ptr + offset);

            if (data.buffer1.Length > 0)
            {
                UnsafeUtility.MemCpy(dataPtr, data.buffer1.GetUnsafeReadOnlyPtr(), data.buffer1.Length);
            }
            if (data.buffer2.Length > 0)
            {
                UnsafeUtility.MemCpy(&dataPtr + data.buffer1.Length, data.buffer2.GetUnsafeReadOnlyPtr(), data.buffer2.Length);
            }
        }