示例#1
0
            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();
            }
示例#2
0
            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();
                }
            }
示例#3
0
            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);
            }