private static void Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests) { var sequenceId = (int *)ctx.internalProcessBuffer; ctx.header.WriteUShort((ushort)*sequenceId); *sequenceId = (ushort)(*sequenceId + 1); }
private static void Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests) { // Request an update to see if a queued packet needs to be resent later or if an ack packet should be sent requests = NetworkPipelineStage.Requests.Update; bool needsResume = false; var header = new ReliableUtility.PacketHeader(); var reliable = (ReliableUtility.Context *)ctx.internalProcessBuffer; needsResume = ReliableUtility.ReleaseOrResumePackets(ctx); if (needsResume) { requests |= NetworkPipelineStage.Requests.Resume; } if (inboundBuffer.bufferLength > 0) { reliable->LastSentTime = ctx.timestamp; ReliableUtility.Write(ctx, inboundBuffer, ref header); ctx.header.WriteBytes((byte *)&header, UnsafeUtility.SizeOf <ReliableUtility.PacketHeader>()); if (reliable->Resume != ReliableUtility.NullEntry) { requests |= NetworkPipelineStage.Requests.Resume; } reliable->PreviousTimestamp = ctx.timestamp; return; } if (reliable->Resume != ReliableUtility.NullEntry) { reliable->LastSentTime = ctx.timestamp; inboundBuffer = ReliableUtility.ResumeSend(ctx, out header, ref needsResume); if (needsResume) { requests |= NetworkPipelineStage.Requests.Resume; } ctx.header.Clear(); ctx.header.WriteBytes((byte *)&header, UnsafeUtility.SizeOf <ReliableUtility.PacketHeader>()); reliable->PreviousTimestamp = ctx.timestamp; return; } if (ReliableUtility.ShouldSendAck(ctx)) { reliable->LastSentTime = ctx.timestamp; ReliableUtility.WriteAckPacket(ctx, ref header); ctx.header.WriteBytes((byte *)&header, UnsafeUtility.SizeOf <ReliableUtility.PacketHeader>()); reliable->PreviousTimestamp = ctx.timestamp; // TODO: Sending dummy byte over since the pipeline won't send an empty payload (ignored on receive) inboundBuffer.bufferWithHeadersLength = inboundBuffer.headerPadding + 1; inboundBuffer.bufferWithHeaders = (byte *)UnsafeUtility.Malloc(inboundBuffer.bufferWithHeadersLength, 8, Allocator.Temp); inboundBuffer.SetBufferFrombufferWithHeaders(); return; } reliable->PreviousTimestamp = ctx.timestamp; }
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests) { var sequenceId = (int *)ctx.internalProcessBuffer; ctx.header.WriteUShort((ushort)*sequenceId); *sequenceId = (ushort)(*sequenceId + 1); return((int)Error.StatusCode.Success); }
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 int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer 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.headerPadding + inboundBuffer.bufferLength > param.MaxPacketSize) { //UnityEngine.Debug.LogWarning("Incoming packet too large for internal storage buffer. Passing through. [buffer=" + (inboundBuffer.headerPadding+inboundBuffer.buffer.Length) + " packet=" + param.MaxPacketSize + "]"); return((int)Error.StatusCode.NetworkPacketOverflow); } var timestamp = ctx.timestamp; if (inboundBuffer.bufferLength > 0) { context->PacketCount++; if (simulator.ShouldDropPacket(context, param, timestamp)) { context->PacketDropCount++; inboundBuffer = default; return((int)Error.StatusCode.Success); } if (context->FuzzFactor > 0) { simulator.FuzzPacket(context, ref inboundBuffer); } if (context->PacketDelayMs == 0 || !simulator.DelayPacket(ref ctx, inboundBuffer, ref requests, timestamp)) { return((int)Error.StatusCode.Success); } } InboundSendBuffer returnPacket = default; if (simulator.GetDelayedPacket(ref ctx, ref returnPacket, ref requests, timestamp)) { inboundBuffer = returnPacket; return((int)Error.StatusCode.Success); } inboundBuffer = default; return((int)Error.StatusCode.Success); }
private static void Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests) { }
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests) { return((int)Error.StatusCode.Success); }
private unsafe void ProcessSendStage(int startStage, int internalBufferOffset, int internalSharedBufferOffset, PipelineImpl p, ref NativeList <int> resumeQ, ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref bool needsUpdate) { var pipelineStage = m_StageCollection[m_StageList[p.FirstStageIndex + startStage]]; ctx.staticInstanceBuffer = (byte *)m_StaticInstanceBuffer.GetUnsafeReadOnlyPtr() + pipelineStage.StaticStateStart; ctx.staticInstanceBufferLength = pipelineStage.StaticStateCapcity; ctx.internalProcessBuffer = (byte *)sendBuffer.GetUnsafeReadOnlyPtr() + internalBufferOffset; ctx.internalProcessBufferLength = pipelineStage.SendCapacity; ctx.internalSharedProcessBuffer = (byte *)sharedBuffer.GetUnsafeReadOnlyPtr() + internalSharedBufferOffset; ctx.internalSharedProcessBufferLength = pipelineStage.SharedStateCapacity; NetworkPipelineStage.Requests requests = NetworkPipelineStage.Requests.None; pipelineStage.Send.Ptr.Invoke(ref ctx, ref inboundBuffer, ref requests); if ((requests & NetworkPipelineStage.Requests.Resume) != 0) { resumeQ.Add(startStage); } needsUpdate = (requests & NetworkPipelineStage.Requests.Update) != 0; }
private static int Send(ref NetworkPipelineContext ctx, ref InboundSendBuffer inboundBuffer, ref NetworkPipelineStage.Requests requests) { var fragContext = (FragContext *)ctx.internalProcessBuffer; var dataBuffer = ctx.internalProcessBuffer + sizeof(FragContext); var param = (FragmentationUtility.Parameters *)ctx.staticInstanceBuffer; FragFlags flags = FragFlags.First; int headerCapacity = ctx.header.Capacity; var systemHeaderCapacity = sizeof(UdpCHeader) + 1 + 2; // Extra byte is for pipeline id, two bytes for footer var maxBlockLength = NetworkParameterConstants.MTU - systemHeaderCapacity - inboundBuffer.headerPadding; var maxBlockLengthFirstPacket = maxBlockLength - ctx.accumulatedHeaderCapacity; // The first packet has the headers for all pipeline stages before this one if (fragContext->endIndex > fragContext->startIndex) { var isResume = 0 == inboundBuffer.bufferLength; if (!isResume) { throw new InvalidOperationException("Internal error: we encountered data in the fragmentation buffer, but this is not a resume call."); } // We have data left over from a previous call flags &= ~FragFlags.First; var blockLength = fragContext->endIndex - fragContext->startIndex; if (blockLength > maxBlockLength) { blockLength = maxBlockLength; } var blockStart = dataBuffer + fragContext->startIndex; inboundBuffer.buffer = blockStart; inboundBuffer.bufferWithHeaders = blockStart - inboundBuffer.headerPadding; inboundBuffer.bufferLength = blockLength; inboundBuffer.bufferWithHeadersLength = blockLength + inboundBuffer.headerPadding; fragContext->startIndex += blockLength; } else if (inboundBuffer.bufferLength > maxBlockLengthFirstPacket) { var payloadCapacity = param->PayloadCapacity; var excessLength = inboundBuffer.bufferLength - maxBlockLengthFirstPacket; var excessStart = inboundBuffer.buffer + maxBlockLengthFirstPacket; if (excessLength + inboundBuffer.headerPadding > payloadCapacity) { throw new InvalidOperationException($"Fragmentation capacity exceeded. Capacity:{payloadCapacity} Payload:{excessLength + inboundBuffer.headerPadding}"); } UnsafeUtility.MemCpy(dataBuffer + inboundBuffer.headerPadding, excessStart, excessLength); fragContext->startIndex = inboundBuffer.headerPadding; // Leaving room for header fragContext->endIndex = excessLength + inboundBuffer.headerPadding; inboundBuffer.bufferWithHeadersLength -= excessLength; inboundBuffer.bufferLength -= excessLength; } if (fragContext->endIndex > fragContext->startIndex) { requests |= NetworkPipelineStage.Requests.Resume; } else { flags |= FragFlags.Last; } var sequence = fragContext->sequence++; var combined = (sequence & (int)FragFlags.SeqMask) | (int)flags; // lower 14 bits sequence, top 2 bits flags ctx.header.WriteShort((short)combined); #if FRAGMENTATION_DEBUG // For debugging - this allows WireShark to identify fragmentation packets ctx.header.WriteByte((byte)'@'); ctx.header.WriteByte((byte)'@'); ctx.header.WriteByte((byte)'@'); ctx.header.WriteByte((byte)'@'); #endif return((int)Error.StatusCode.Success); }