Пример #1
0
        public override void Serialize(SerializationContext context)
        {
            int bytesNeed = (int)(Messages.Count * 11 + Messages.Sum(m => m.DataLength));
            var buffer    = _arrayPool.Rent(bytesNeed);

            try
            {
                var span     = buffer.AsSpan(0, bytesNeed);
                int consumed = 0;
                foreach (var message in Messages)
                {
                    span[0] = (byte)message.Header.MessageType;
                    span    = span.Slice(sizeof(byte));
                    NetworkBitConverter.TryGetUInt24Bytes((uint)message.Header.MessageLength, span);
                    span = span.Slice(3);
                    NetworkBitConverter.TryGetBytes(message.Header.Timestamp, span);
                    span = span.Slice(4);
                    NetworkBitConverter.TryGetUInt24Bytes((uint)MessageHeader.MessageStreamId, span);
                    span = span.Slice(3);
                    MessageBuffer.AsSpan(consumed, (int)message.Header.MessageLength).CopyTo(span);
                    consumed += (int)message.Header.MessageLength;
                    span      = span.Slice((int)message.Header.MessageLength);
                }
                context.WriteBuffer.WriteToBuffer(span);
            }
            finally
            {
                _arrayPool.Return(buffer);
            }
        }
Пример #2
0
        public void WriteBytes(DateTime dateTime, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.Date);

            var  refIndex = context.ObjectReferenceTable.IndexOf(dateTime);
            uint header   = 0;

            if (refIndex >= 0)
            {
                header = (uint)refIndex << 1;

                WriteU29BytesImpl(header, context);
                return;
            }
            context.ObjectReferenceTable.Add(dateTime);

            var timeOffset = new DateTimeOffset(dateTime);
            var timestamp  = timeOffset.ToUnixTimeMilliseconds();

            header = 0x01;
            WriteU29BytesImpl(header, context);
            var backend = _arrayPool.Rent(sizeof(double));

            try
            {
                var contractRet = NetworkBitConverter.TryGetBytes(timestamp, backend);
                Contract.Assert(contractRet);
                context.Buffer.WriteToBuffer(backend.AsSpan(0, sizeof(double)));
            }
            finally
            {
                _arrayPool.Return(backend);
            }
        }
Пример #3
0
        public byte[] MultiplexFlvHeader(bool hasAudio, bool hasVideo)
        {
            var header = new byte[13];

            header[0] = 0x46;
            header[1] = 0x4C;
            header[2] = 0x56;
            header[3] = 0x01;

            byte audioFlag = 0x01 << 2;
            byte videoFlag = 0x01;
            byte typeFlag  = 0x00;

            if (hasAudio)
            {
                typeFlag |= audioFlag;
            }
            if (hasVideo)
            {
                typeFlag |= videoFlag;
            }
            header[4] = typeFlag;

            NetworkBitConverter.TryGetBytes(9, header.AsSpan(5));
            return(header);
        }
Пример #4
0
        public void WriteBytes(Vector <double> value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.VectorDouble);

            var refIndex = context.ObjectReferenceTable.IndexOf(value);

            if (refIndex >= 0)
            {
                var header = (uint)refIndex << 1;
                WriteU29BytesImpl(header, context);
                return;
            }
            else
            {
                context.ObjectReferenceTable.Add(value);
                var header = ((uint)value.Count << 1) | 0x01;
                WriteU29BytesImpl(header, context);
                context.Buffer.WriteToBuffer(value.IsFixedSize ? (byte)0x01 : (byte)0x00);
                var buffer = _arrayPool.Rent(sizeof(double));
                try
                {
                    foreach (var i in value)
                    {
                        var contractRet = NetworkBitConverter.TryGetBytes(i, buffer);
                        Contract.Assert(contractRet);
                        context.Buffer.WriteToBuffer(buffer.AsSpan(0, sizeof(double)));
                    }
                }
                finally
                {
                    _arrayPool.Return(buffer);
                }
                return;
            }
        }
Пример #5
0
        public byte[] MultiplexFlv(Message data)
        {
            var dataBuffer = new ByteBuffer();
            var buffer     = new byte[4];

            if (data.MessageHeader.MessageLength == 0)
            {
                var messageBuffer = new ByteBuffer();
                var context       = new Networking.Rtmp.Serialization.SerializationContext()
                {
                    Amf0Writer  = _amf0Writer,
                    Amf3Writer  = _amf3Writer,
                    WriteBuffer = messageBuffer
                };

                data.Serialize(context);
                var length = messageBuffer.Length;
                data.MessageHeader.MessageLength = (uint)length;
                var bodyBuffer = new byte[length];
                messageBuffer.TakeOutMemory(bodyBuffer);

                dataBuffer.WriteToBuffer((byte)data.MessageHeader.MessageType);
                NetworkBitConverter.TryGetUInt24Bytes(data.MessageHeader.MessageLength, buffer);
                dataBuffer.WriteToBuffer(buffer.AsSpan(0, 3));
                NetworkBitConverter.TryGetBytes(data.MessageHeader.Timestamp, buffer);
                dataBuffer.WriteToBuffer(buffer.AsSpan(1, 3));
                dataBuffer.WriteToBuffer(buffer.AsSpan(0, 1));
                buffer.AsSpan().Clear();
                dataBuffer.WriteToBuffer(buffer.AsSpan(0, 3));
                dataBuffer.WriteToBuffer(bodyBuffer);
            }
            else
            {
                dataBuffer.WriteToBuffer((byte)data.MessageHeader.MessageType);
                NetworkBitConverter.TryGetUInt24Bytes(data.MessageHeader.MessageLength, buffer);
                dataBuffer.WriteToBuffer(buffer.AsSpan(0, 3));
                NetworkBitConverter.TryGetBytes(data.MessageHeader.Timestamp, buffer);
                dataBuffer.WriteToBuffer(buffer.AsSpan(1, 3));
                dataBuffer.WriteToBuffer(buffer.AsSpan(0, 1));
                buffer.AsSpan().Clear();
                dataBuffer.WriteToBuffer(buffer.AsSpan(0, 3));
                var context = new Networking.Rtmp.Serialization.SerializationContext()
                {
                    Amf0Writer  = _amf0Writer,
                    Amf3Writer  = _amf3Writer,
                    WriteBuffer = dataBuffer
                };

                data.Serialize(context);
            }

            NetworkBitConverter.TryGetBytes((data.MessageHeader.MessageLength + 11), buffer);
            dataBuffer.WriteToBuffer(buffer);

            var rawData = new byte[dataBuffer.Length];

            dataBuffer.TakeOutMemory(rawData);
            return(rawData);
        }
Пример #6
0
        private bool ProcessHandshakeC0C1(ReadOnlySequence <byte> buffer, ref int consumed)
        {
            if (buffer.Length - consumed < 1537)
            {
                return(false);
            }
            var arr = _arrayPool.Rent(1537);

            try
            {
                buffer.Slice(consumed, 9).CopyTo(arr);
                consumed += 9;
                var version = arr[0];
                //本文档中规范的版本号为 3。0、1、2 三个值是由早期其他产品使用的,是废弃值;4 - 31 被保留为 RTMP 协议的未来实现版本使用
                if (version < 3)
                {
                    throw new NotSupportedException();
                }
                if (version > 31)
                {
                    throw new ProtocolViolationException();
                }

                _readerTimestampEpoch = NetworkBitConverter.ToUInt32(arr.AsSpan(1, 4));
                _writerTimestampEpoch = 0;
                _s1Data = _arrayPool.Rent(1528);
                _random.NextBytes(_s1Data.AsSpan(0, 1528));

                // s0s1
                arr.AsSpan().Clear();
                arr[0] = 3;
                NetworkBitConverter.TryGetBytes(_writerTimestampEpoch, arr.AsSpan(1, 4));
                _s1Data.AsSpan(0, 1528).CopyTo(arr.AsSpan(9));
                _ = _ioPipeline.SendRawData(arr.AsMemory(0, 1537));

                // s2
                NetworkBitConverter.TryGetBytes(_readerTimestampEpoch, arr.AsSpan(0, 4));
                NetworkBitConverter.TryGetBytes((uint)0, arr.AsSpan(4, 4));

                _ = _ioPipeline.SendRawData(arr.AsMemory(0, 1536));

                buffer.Slice(consumed, 1528).CopyTo(arr.AsSpan(8));
                consumed += 1528;

                _ioPipeline.NextProcessState = ProcessState.HandshakeC2;
                return(true);
            }
            finally
            {
                _arrayPool.Return(arr);
            }
        }
Пример #7
0
        private void WriteStringBytesImpl(string str, SerializationContext context, out bool isLongString, bool marker = false, bool forceLongString = false)
        {
            var bytesNeed    = 0;
            var headerLength = 0;
            var bodyLength   = 0;

            bodyLength = Encoding.UTF8.GetByteCount(str);
            bytesNeed += bodyLength;

            if (bodyLength > ushort.MaxValue || forceLongString)
            {
                headerLength = Amf0CommonValues.LONG_STRING_HEADER_LENGTH;
                isLongString = true;
                if (marker)
                {
                    context.Buffer.WriteToBuffer((byte)Amf0Type.LongString);
                }
            }
            else
            {
                isLongString = false;
                headerLength = Amf0CommonValues.STRING_HEADER_LENGTH;
                if (marker)
                {
                    context.Buffer.WriteToBuffer((byte)Amf0Type.String);
                }
            }
            bytesNeed += headerLength;
            var bufferBackend = _arrayPool.Rent(bytesNeed);

            try
            {
                var buffer = bufferBackend.AsSpan(0, bytesNeed);
                if (isLongString)
                {
                    NetworkBitConverter.TryGetBytes((uint)bodyLength, buffer);
                }
                else
                {
                    var contractRet = NetworkBitConverter.TryGetBytes((ushort)bodyLength, buffer);
                    Contract.Assert(contractRet);
                }

                Encoding.UTF8.GetBytes(str, buffer.Slice(headerLength));

                context.Buffer.WriteToBuffer(buffer);
            }
            finally
            {
                _arrayPool.Return(bufferBackend);
            }
        }
Пример #8
0
        public override void Serialize(SerializationContext context)
        {
            var buffer = _arrayPool.Rent(sizeof(uint));

            try
            {
                NetworkBitConverter.TryGetBytes(BytesReceived, buffer);
                context.WriteBuffer.WriteToBuffer(buffer.AsSpan(0, sizeof(uint)));
            }
            finally
            {
                _arrayPool.Return(buffer);
            }
        }
Пример #9
0
        public override void Serialize(SerializationContext context)
        {
            var arr = ArrayPool <byte> .Shared.Rent(sizeof(uint));

            try
            {
                NetworkBitConverter.TryGetBytes(WindowSize, arr);
                context.WriteBuffer.WriteToBuffer(arr.AsSpan(0, sizeof(uint)));
            }
            finally
            {
                ArrayPool <byte> .Shared.Return(arr);
            }
        }
Пример #10
0
        public override void Serialize(SerializationContext context)
        {
            var buffer = _arrayPool.Rent(sizeof(uint));

            try
            {
                NetworkBitConverter.TryGetBytes(AbortedChunkStreamId, buffer);
                context.WriteBuffer.WriteToBuffer(buffer);
            }
            finally
            {
                _arrayPool.Return(buffer);
            }
        }
        public override void Serialize(SerializationContext context)
        {
            var buffer = _arrayPool.Rent(sizeof(uint) + sizeof(byte));

            try
            {
                NetworkBitConverter.TryGetBytes(WindowSize, buffer);
                buffer.AsSpan(sizeof(uint))[0] = (byte)LimitType;
                context.WriteBuffer.WriteToBuffer(buffer.AsSpan(0, sizeof(uint) + sizeof(byte)));
            }
            finally
            {
                _arrayPool.Return(buffer);
            }
        }
Пример #12
0
        public void WriteBytes(double value, SerializationContext context)
        {
            context.Buffer.WriteToBuffer((byte)Amf3Type.Double);
            var backend = _arrayPool.Rent(sizeof(double));

            try
            {
                var contractRet = NetworkBitConverter.TryGetBytes(value, backend);
                Contract.Assert(contractRet);
                context.Buffer.WriteToBuffer(backend.AsSpan(0, sizeof(double)));
            }
            finally
            {
                _arrayPool.Return(backend);
            }
        }
Пример #13
0
        public void WriteBytes(double val, SerializationContext context)
        {
            var bytesNeed     = Amf0CommonValues.MARKER_LENGTH + sizeof(double);
            var bufferBackend = _arrayPool.Rent(bytesNeed);

            try
            {
                var buffer = bufferBackend.AsSpan(0, bytesNeed);
                buffer[0] = (byte)Amf0Type.Number;
                var contractRet = NetworkBitConverter.TryGetBytes(val, buffer.Slice(Amf0CommonValues.MARKER_LENGTH));
                Contract.Assert(contractRet);
                context.Buffer.WriteToBuffer(buffer);
            }
            finally
            {
                _arrayPool.Return(bufferBackend);
            }
        }
Пример #14
0
        public override void Serialize(SerializationContext context)
        {
            var length = sizeof(ushort) + sizeof(uint);
            var buffer = _arrayPool.Rent(length);

            try
            {
                var span = buffer.AsSpan();
                NetworkBitConverter.TryGetBytes((ushort)UserControlEventType.StreamBegin, span);
                span = span.Slice(sizeof(ushort));
                NetworkBitConverter.TryGetBytes(StreamID, span);
            }
            finally
            {
                _arrayPool.Return(buffer);
            }
            context.WriteBuffer.WriteToBuffer(buffer.AsSpan(0, length));
        }
Пример #15
0
        private void WriteReferenceIndexBytes(ushort index, SerializationContext context)
        {
            var bytesNeed = Amf0CommonValues.MARKER_LENGTH + sizeof(ushort);
            var backend   = _arrayPool.Rent(bytesNeed);

            try
            {
                var buffer = backend.AsSpan(0, bytesNeed);
                buffer[0] = (byte)Amf0Type.Reference;
                var contractRet = NetworkBitConverter.TryGetBytes(index, buffer.Slice(Amf0CommonValues.MARKER_LENGTH));
                Contract.Assert(contractRet);
                context.Buffer.WriteToBuffer(buffer);
            }
            finally
            {
                _arrayPool.Return(backend);
            }
        }
Пример #16
0
        public void WriteBytes(DateTime dateTime, SerializationContext context)
        {
            var bytesNeed = Amf0CommonValues.MARKER_LENGTH + sizeof(double) + sizeof(short);

            var backend = _arrayPool.Rent(bytesNeed);

            try
            {
                var buffer = backend.AsSpan(0, bytesNeed);
                buffer.Slice(0, bytesNeed).Clear();
                buffer[0] = (byte)Amf0Type.Date;
                var dof         = new DateTimeOffset(dateTime);
                var timestamp   = (double)dof.ToUnixTimeMilliseconds();
                var contractRet = NetworkBitConverter.TryGetBytes(timestamp, buffer.Slice(Amf0CommonValues.MARKER_LENGTH));
                Contract.Assert(contractRet);
                context.Buffer.WriteToBuffer(buffer);
            }
            finally
            {
                _arrayPool.Return(backend);
            }
        }
Пример #17
0
        // strict array
        public void WriteBytes(List <object> value, SerializationContext context)
        {
            if (value == null)
            {
                WriteNullBytes(context);
                return;
            }

            var bytesNeed = Amf0CommonValues.MARKER_LENGTH + sizeof(uint);

            var refIndex = context.ReferenceTable.IndexOf(value);

            if (refIndex >= 0)
            {
                WriteReferenceIndexBytes((ushort)refIndex, context);
                return;
            }
            context.ReferenceTable.Add(value);

            context.Buffer.WriteToBuffer((byte)Amf0Type.StrictArray);
            var countBuffer = _arrayPool.Rent(sizeof(uint));

            try
            {
                var contractRet = NetworkBitConverter.TryGetBytes((uint)value.Count, countBuffer);
                Contract.Assert(contractRet);
                context.Buffer.WriteToBuffer(countBuffer.AsSpan(0, sizeof(uint)));
            }
            finally
            {
                _arrayPool.Return(countBuffer);
            }

            foreach (var data in value)
            {
                WriteValueBytes(data, context);
            }
        }
Пример #18
0
        // ecma array
        public void WriteBytes(Dictionary <string, object> value, SerializationContext context)
        {
            if (value == null)
            {
                WriteNullBytes(context);
                return;
            }

            var refIndex = context.ReferenceTable.IndexOf(value);

            if (refIndex >= 0)
            {
                WriteReferenceIndexBytes((ushort)refIndex, context);
                return;
            }
            context.Buffer.WriteToBuffer((byte)Amf0Type.EcmaArray);
            context.ReferenceTable.Add(value);
            var countBuffer = _arrayPool.Rent(sizeof(uint));

            try
            {
                var contractRet = NetworkBitConverter.TryGetBytes((uint)value.Count, countBuffer);
                Contract.Assert(contractRet);
                context.Buffer.WriteToBuffer(countBuffer.AsSpan(0, sizeof(uint)));
            }
            finally
            {
                _arrayPool.Return(countBuffer);
            }

            foreach ((var key, var data) in value)
            {
                WriteStringBytesImpl(key, context, out _);
                WriteValueBytes(data, context);
            }
            WriteStringBytesImpl("", context, out _);
            WriteObjectEndBytes(context);
        }
Пример #19
0
        private void WriteU29BytesImpl(uint value, SerializationContext context)
        {
            var length = 0;

            if (value <= 0x7F)
            {
                length = 1;
            }
            else if (value <= 0x3FFF)
            {
                length = 2;
            }
            else if (value <= 0x1FFFFF)
            {
                length = 3;
            }
            else if (value <= U29MAX)
            {
                length = 4;
            }
            else
            {
                throw new ArgumentOutOfRangeException();
            }
            var arr = ArrayPool <byte> .Shared.Rent(4);

            try
            {
                NetworkBitConverter.TryGetBytes(value, arr);

                switch (length)
                {
                case 4:
                    context.Buffer.WriteToBuffer((byte)(arr[0] << 2 | ((arr[1]) >> 6) | 0x80));
                    context.Buffer.WriteToBuffer((byte)(arr[1] << 1 | ((arr[2]) >> 7) | 0x80));
                    context.Buffer.WriteToBuffer((byte)(arr[2] | 0x80));
                    context.Buffer.WriteToBuffer(arr[3]);
                    break;

                case 3:
                    context.Buffer.WriteToBuffer((byte)(arr[1] << 2 | ((arr[2]) >> 6) | 0x80));
                    context.Buffer.WriteToBuffer((byte)(arr[2] << 1 | ((arr[3]) >> 7) | 0x80));
                    context.Buffer.WriteToBuffer((byte)(arr[3] & 0x7F));
                    break;

                case 2:
                    context.Buffer.WriteToBuffer((byte)(arr[2] << 1 | ((arr[3]) >> 7) | 0x80));
                    context.Buffer.WriteToBuffer((byte)(arr[3] & 0x7F));
                    break;

                case 1:
                    context.Buffer.WriteToBuffer((byte)(arr[3]));
                    break;

                default:
                    throw new ApplicationException();
                }
            }
            finally
            {
                ArrayPool <byte> .Shared.Return(arr);
            }
        }