static async Task WriteC2Async(Stream stream, uint remoteTime, Space <byte> remoteRandom) { var time = Ts.CurrentTime; var writer = new AmfWriter(new byte[FrameLength], EmptyContext); writer.WriteUInt32(remoteTime); // "time": a copy of s1 time writer.WriteUInt32(time); // "time2": current local time writer.WriteBytes(remoteRandom); // "random echo": a copy of s1 random await stream.WriteAsync(writer.Span); writer.Return(); }
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(); } }
static async Task <(uint time, Space <byte> random)> WriteC1Async(Stream stream) { var writer = new AmfWriter(new byte[C1Length], EmptyContext); var random = RandomEx.GetBytes(RandomLength); var time = Ts.CurrentTime; writer.WriteByte(3); // rtmp version (constant 3) [c0] writer.WriteUInt32(time); // time [c1] writer.WriteUInt32(0); // zero [c1] writer.WriteBytes(random); // random bytes [c1] await stream.WriteAsync(writer.Span); writer.Return(); return(time, random); }