private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests) { var context = (SimulatorUtility.Context *)ctx.internalSharedProcessBuffer; var param = *(SimulatorUtility.Parameters *)ctx.staticInstanceBuffer; var simulator = new SimulatorUtility(param.MaxPacketCount, param.MaxPacketSize, param.PacketDelayMs, param.PacketJitterMs); if (inboundBuffer.bufferLength > param.MaxPacketSize) { //UnityEngine.Debug.LogWarning("Incoming packet too large for internal storage buffer. Passing through. [buffer=" + inboundBuffer.Length + " packet=" + param->MaxPacketSize + "]"); // TODO: Add error code for this return; } var timestamp = ctx.timestamp; // Inbound buffer is empty if this is a resumed receive if (inboundBuffer.bufferLength > 0) { context->PacketCount++; if (simulator.ShouldDropPacket(context, param, timestamp)) { context->PacketDropCount++; inboundBuffer = default; return; } var bufferVec = default(InboundSendBuffer); bufferVec.bufferWithHeaders = inboundBuffer.buffer; bufferVec.bufferWithHeadersLength = inboundBuffer.bufferLength; bufferVec.buffer = inboundBuffer.buffer; bufferVec.bufferLength = inboundBuffer.bufferLength; bufferVec.headerPadding = 0; if (context->PacketDelayMs == 0 || !simulator.DelayPacket(ref ctx, bufferVec, ref requests, timestamp)) { return; } } InboundSendBuffer returnPacket = default; if (simulator.GetDelayedPacket(ref ctx, ref returnPacket, ref requests, timestamp)) { inboundBuffer.buffer = returnPacket.bufferWithHeaders; inboundBuffer.bufferLength = returnPacket.bufferWithHeadersLength; return; } inboundBuffer = default; }
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests) { var inboundArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <byte>(inboundBuffer.buffer, inboundBuffer.bufferLength, Allocator.Invalid); #if ENABLE_UNITY_COLLECTIONS_CHECKS var safetyHandle = AtomicSafetyHandle.GetTempMemoryHandle(); NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref inboundArray, safetyHandle); #endif var reader = new DataStreamReader(inboundArray); var oldSequenceId = (int *)ctx.internalProcessBuffer; ushort sequenceId = reader.ReadUShort(); if (SequenceHelpers.GreaterThan16(sequenceId, (ushort)*oldSequenceId)) { *oldSequenceId = sequenceId; // Skip over the part of the buffer which contains the header inboundBuffer = inboundBuffer.Slice(sizeof(ushort)); return; } inboundBuffer = default; }
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests) { }
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests) { // Request a send update to see if a queued packet needs to be resent later or if an ack packet should be sent requests = NetworkPipelineStage.Requests.SendUpdate; bool needsResume = false; var header = default(ReliableUtility.PacketHeader); var slice = default(InboundRecvBuffer); ReliableUtility.Context * reliable = (ReliableUtility.Context *)ctx.internalProcessBuffer; ReliableUtility.SharedContext *shared = (ReliableUtility.SharedContext *)ctx.internalSharedProcessBuffer; shared->errorCode = 0; if (reliable->Resume == ReliableUtility.NullEntry) { if (inboundBuffer.bufferLength <= 0) { inboundBuffer = slice; return; } var inboundArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <byte>(inboundBuffer.buffer, inboundBuffer.bufferLength, Allocator.Invalid); #if ENABLE_UNITY_COLLECTIONS_CHECKS var safetyHandle = AtomicSafetyHandle.GetTempMemoryHandle(); NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref inboundArray, safetyHandle); #endif var reader = new DataStreamReader(inboundArray); reader.ReadBytes((byte *)&header, UnsafeUtility.SizeOf <ReliableUtility.PacketHeader>()); if (header.Type == (ushort)ReliableUtility.PacketType.Ack) { ReliableUtility.ReadAckPacket(ctx, header); inboundBuffer = default; return; } var result = ReliableUtility.Read(ctx, header); if (result >= 0) { var nextExpectedSequenceId = (ushort)(reliable->Delivered + 1); if (result == nextExpectedSequenceId) { reliable->Delivered = result; slice = inboundBuffer.Slice(UnsafeUtility.SizeOf <ReliableUtility.PacketHeader>()); if (needsResume = SequenceHelpers.GreaterThan16((ushort)shared->ReceivedPackets.Sequence, (ushort)result)) { reliable->Resume = (ushort)(result + 1); } } else { ReliableUtility.SetPacket(ctx.internalProcessBuffer, result, inboundBuffer.Slice(UnsafeUtility.SizeOf <ReliableUtility.PacketHeader>())); slice = ReliableUtility.ResumeReceive(ctx, reliable->Delivered + 1, ref needsResume); } } } else { slice = ReliableUtility.ResumeReceive(ctx, reliable->Resume, ref needsResume); } if (needsResume) { requests |= NetworkPipelineStage.Requests.Resume; } inboundBuffer = slice; }
private static void Receive(ref NetworkPipelineContext ctx, ref InboundRecvBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests) { var fragContext = (FragContext *)ctx.internalProcessBuffer; var dataBuffer = ctx.internalProcessBuffer + sizeof(FragContext); var param = (FragmentationUtility.Parameters *)ctx.staticInstanceBuffer; var inboundArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <byte>(inboundBuffer.buffer, inboundBuffer.bufferLength, Allocator.Invalid); #if ENABLE_UNITY_COLLECTIONS_CHECKS var safetyHandle = AtomicSafetyHandle.GetTempMemoryHandle(); NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref inboundArray, safetyHandle); #endif var reader = new DataStreamReader(inboundArray); var combined = reader.ReadShort(); var foundSequence = combined & (int)FragFlags.SeqMask; var flags = (FragFlags)combined & ~FragFlags.SeqMask; inboundBuffer = inboundBuffer.Slice(FragHeaderCapacity); var expectedSequence = fragContext->sequence; var isFirst = 0 != (flags & FragFlags.First); var isLast = 0 != (flags & FragFlags.Last); if (isFirst) { expectedSequence = foundSequence; fragContext->packetError = false; fragContext->endIndex = 0; } if (foundSequence != expectedSequence) { // We've missed a packet. fragContext->packetError = true; fragContext->endIndex = 0; // Discard data we have already collected } if (!fragContext->packetError) { if (!isLast || fragContext->endIndex > 0) { if (fragContext->endIndex + inboundBuffer.bufferLength > param->PayloadCapacity) { throw new InvalidOperationException($"Fragmentation capacity exceeded"); } // Append the data to the end UnsafeUtility.MemCpy(dataBuffer + fragContext->endIndex, inboundBuffer.buffer, inboundBuffer.bufferLength); fragContext->endIndex += inboundBuffer.bufferLength; } if (isLast && fragContext->endIndex > 0) { // Data is complete inboundBuffer = new InboundRecvBuffer { buffer = dataBuffer, bufferLength = fragContext->endIndex }; } } if (!isLast || fragContext->packetError) { // No output if we expect more data, or if data is incomplete due to packet loss inboundBuffer = default; } fragContext->sequence = (foundSequence + 1) & (int)FragFlags.SeqMask; }