public unsafe bool DelayPacket(ref NetworkPipelineContext ctx, InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests, long timestamp) { // Find empty slot in bookkeeping data space to track this packet int packetPayloadOffset = 0; int packetDataOffset = 0; var processBufferPtr = (byte *)ctx.internalProcessBuffer; 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); } UnsafeUtility.MemCpy(ctx.internalProcessBuffer + packetPayloadOffset + inboundBuffer.headerPadding, inboundBuffer.buffer, inboundBuffer.bufferLength); var param = (SimulatorUtility.Context *)ctx.internalSharedProcessBuffer; // Add tracking for this packet so we can resurrect later DelayedPacket packet; packet.delayUntil = timestamp + m_PacketDelayMs + param->Random.NextInt(m_PacketJitterMs * 2) - m_PacketJitterMs; packet.processBufferOffset = packetPayloadOffset; packet.packetSize = (ushort)(inboundBuffer.headerPadding + inboundBuffer.bufferLength); packet.packetHeaderPadding = (ushort)inboundBuffer.headerPadding; byte *packetPtr = (byte *)&packet; UnsafeUtility.MemCpy(processBufferPtr + packetDataOffset, packetPtr, UnsafeUtility.SizeOf <DelayedPacket>()); // Schedule an update call so packet can be resurrected later requests |= NetworkPipelineStage.Requests.Update; return(true); }
private static unsafe void Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests request) { var len = inboundBuffer.bufferLength; for (int i = 0; i < len; ++i) { ctx.internalProcessBuffer[inboundBuffer.headerPadding + i] = (byte)(inboundBuffer.buffer[i] ^ 0xff); } var nextInbound = default(InboundSendBuffer); nextInbound.bufferWithHeaders = ctx.internalProcessBuffer; nextInbound.bufferWithHeadersLength = len + inboundBuffer.headerPadding; nextInbound.SetBufferFrombufferWithHeaders(); inboundBuffer = nextInbound; }
private static void Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests request) { var sendData = (int *)ctx.internalProcessBuffer; for (int i = 1; i <= 3; ++i) { Assert.AreEqual(*sendData, i * 10); sendData++; } var sharedData = (int *)ctx.internalSharedProcessBuffer; for (int i = 7; i <= 8; ++i) { Assert.AreEqual(*sharedData, i * 10); sharedData++; } }
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests request) { var sendData = (int *)ctx.internalProcessBuffer; for (int i = 1; i <= 3; ++i) { Assert.AreEqual(*sendData, i); sendData++; } var sharedData = (int *)ctx.internalSharedProcessBuffer; for (int i = 7; i <= 8; ++i) { Assert.AreEqual(*sharedData, i); sharedData++; } return((int)Error.StatusCode.Success); }
public unsafe void FuzzPacket(Context *ctx, ref InboundSendBuffer inboundBuffer) { int fuzzFactor = ctx->FuzzFactor; int fuzzOffset = ctx->FuzzOffset; int rand = ctx->Random.NextInt(0, 100); if (rand > fuzzFactor) { return; } var length = inboundBuffer.bufferLength; for (int i = fuzzOffset; i < length; ++i) { for (int j = 0; j < 8; ++j) { if (fuzzFactor > ctx->Random.NextInt(0, 100)) { inboundBuffer.buffer[i] ^= (byte)(1 << j); } } } }
private static void Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests request) { ctx.header.WriteInt((int)2); }
public unsafe bool GetDelayedPacket(ref NetworkPipelineContext ctx, ref InboundSendBuffer delayedPacket, ref NetworkPipelineStage.Requests requests, long currentTimestamp) { requests = NetworkPipelineStage.Requests.None; var dataSize = UnsafeUtility.SizeOf <DelayedPacket>(); byte *processBufferPtr = (byte *)ctx.internalProcessBuffer; var simCtx = (Context *)ctx.internalSharedProcessBuffer; int oldestPacketIndex = -1; long oldestTime = long.MaxValue; int readyPackets = 0; int packetsInQueue = 0; for (int i = 0; i < m_PacketCount; i++) { DelayedPacket *packet = (DelayedPacket *)(processBufferPtr + dataSize * i); if ((int)packet->delayUntil == 0) { continue; } packetsInQueue++; if (packet->delayUntil > currentTimestamp) { continue; } readyPackets++; if (oldestTime <= packet->delayUntil) { continue; } oldestPacketIndex = i; oldestTime = packet->delayUntil; } simCtx->ReadyPackets = readyPackets; simCtx->WaitingPackets = packetsInQueue; simCtx->NextPacketTime = oldestTime; simCtx->StatsTime = currentTimestamp; // If more than one item has expired timer we need to resume this pipeline stage if (readyPackets > 1) { requests |= NetworkPipelineStage.Requests.Resume; } // If more than one item is present (but doesn't have expired timer) we need to re-run the pipeline // in a later update call else if (packetsInQueue > 0) { requests |= NetworkPipelineStage.Requests.Update; } if (oldestPacketIndex >= 0) { DelayedPacket *packet = (DelayedPacket *)(processBufferPtr + dataSize * oldestPacketIndex); packet->delayUntil = 0; delayedPacket.bufferWithHeaders = ctx.internalProcessBuffer + packet->processBufferOffset; delayedPacket.bufferWithHeadersLength = packet->packetSize; delayedPacket.headerPadding = packet->packetHeaderPadding; delayedPacket.SetBufferFrombufferWithHeaders(); return(true); } return(false); }
/// <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(byte *self, int sequence, PacketHeader header, InboundSendBuffer data, long timestamp) { Context *ctx = (Context *)self; int totalSize = data.bufferLength + data.headerPadding; if (totalSize + UnsafeUtility.SizeOf <PacketHeader>() > 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 = (ushort)totalSize; info->HeaderPadding = (ushort)data.headerPadding; info->SendTime = timestamp; Packet *packet = GetPacket(self, sequence); packet->Header = header; var offset = (ctx->DataPtrOffset + (index * ctx->DataStride)) + UnsafeUtility.SizeOf <PacketHeader>(); void *dataPtr = (self + offset); if (data.bufferLength > 0) { UnsafeUtility.MemCpy((byte *)dataPtr + data.headerPadding, data.buffer, data.bufferLength); } }
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests request) { return((int)Error.StatusCode.Success); }