async Task WriteOnceAsync() { await reset.WaitAsync(); while (!token.IsCancellationRequested && queue.TryDequeue(out var packet)) { // quickly estimate the maximum required length for this message. our estimation is as follows: // // - [payload] // - take the message length, and add the chunk + message headers. // // - [chunk headers] // - all chunk headers begin with a 0-3 byte header, indicating chunk stream id + message header // format. // - the one byte variant can encode chunk stream ids up to and including #63. we don't expect to // encode that many streams right now (unless a user library wants it), so we can assume 1 byte // chunk headers for now. //~ // - [message headers] // - the first message header must be a type 0 (new) header, which is 11 bytes large. // - all further message headers can be a type 3 (continuation) header, which is 0 bytes large. // // - [total] // - message_length + chunk_count * 1 + 11 // var packetLength = packet.Span.Length; var chunkCount = packetLength / chunkLength + 1; var estimatedMaxLength = packetLength + chunkCount + 11; var writer = new AmfWriter(estimatedMaxLength, context); var previous = streams.TryGetValue(packet.StreamId, out var value) ? value : default(ChunkStream.Snapshot); var next = previous.Clone(); next.Ready = true; next.ContentType = packet.Type; next.ChunkStreamId = packet.StreamId; next.MessageStreamId = 0; next.MessageLength = packetLength; next.Timestamp = Ts.CurrentTime; streams[packet.StreamId] = next; ChunkStream.WriteTo(writer, previous, next, chunkLength, packet.Span); await stream.WriteAsync(writer.Span, token); writer.Return(); } }