protected async ValueTask ProcessOutgoingPacket(IOutputLogger?m, IOutgoingPacket outgoingPacket, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return; } using (m?.SendingMessage(ref outgoingPacket, OutputPump.PConfig.ProtocolLevel)) { if (outgoingPacket.Qos != QualityOfService.AtMostOnce) { // This must be done BEFORE writing the packet to avoid concurrency issues. _outgoingPacketStore.OnPacketSent(m, outgoingPacket.PacketId); // Explanation: // The receiver and input loop can run before the next line is executed. } await outgoingPacket.WriteAsync(OutputPump.PConfig.ProtocolLevel, _pipeWriter, cancellationToken); } }
protected override async ValueTask <IOutgoingPacket> DoStorePacket(IActivityMonitor?m, IOutgoingPacket packet) { int packetSize = packet.GetSize(_protocolConfig.ProtocolLevel); m?.Trace($"Renting {packetSize} bytes to persist {packet}."); IMemoryOwner <byte> memOwner = MemoryPool <byte> .Shared.Rent(packetSize); PipeWriter pipe = PipeWriter.Create(memOwner.Memory.AsStream()); // And write their content to this memory. using (m?.OpenTrace($"Serializing {packet} into memory...")) { if (await packet.WriteAsync(_protocolConfig.ProtocolLevel, pipe, default) != WriteResult.Written) { throw new InvalidOperationException("Didn't wrote packet correctly."); } } Memory <byte> slicedMem = memOwner.Memory.Slice(0, packetSize); base[packet.PacketId].Content.Storage = new StoredPacket(slicedMem, memOwner); return(new FromMemoryOutgoingPacket(slicedMem, packet.Qos, packet.PacketId)); }