Пример #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 static ExtensionType Parse(MemoryCursor cursor)
        {
            var codeBytes = cursor.Move(2);
            var code      = (ushort)NetworkBitConverter.ParseUnaligned(codeBytes.Span);

            return(new ExtensionType(code));
        }
Пример #3
0
            public void Dispose()
            {
                type.WriteBytes(cursor);

                var payloadLength = cursor - startLengthOfBody;

                if (payloadLength > MaxLength)
                {
                    throw new EncodingException();
                }

                var payloadData            = cursor.Move(-payloadLength);
                var headerLength           = cursor - startLengthOfMessage;
                var headerData             = cursor.Peek(-headerLength);
                var encryptedPayloadLength = payloadLength + aead.TagLength;

                if (encryptedPayloadLength > MaxLength)
                {
                    throw new EncodingException();
                }

                cursor.Move(encryptedPayloadLength);

                var tag = cursor.Peek(-aead.TagLength);

                NetworkBitConverter.WriteUnaligned(lengthBytes, (ulong)encryptedPayloadLength, 2);

                aead.Encrypt(payloadData.Span, tag.Span, sequenceNumber, headerData.Span);
            }
Пример #4
0
        public static MemoryBuffer DecryptBytes(MemoryCursor cursor, int startOffsetOfMessage, IAead aead, ulong sequenceNumber)
        {
            var headerLength = cursor - startOffsetOfMessage + 2;
            var lengthBytes  = cursor.Move(2);
            var headerBytes  = cursor.Peek(-headerLength);
            var length       = (int)NetworkBitConverter.ParseUnaligned(lengthBytes.Span);

            if (length > MaxLength)
            {
                throw new EncodingException();
            }

            if (length < aead.TagLength)
            {
                throw new EncodingException();
            }

            var startOffsetOfBody = cursor.AsOffset();
            var encryptedLength   = length - aead.TagLength;
            var encryptedBytes    = cursor.Move(encryptedLength);
            var tag = cursor.Move(aead.TagLength);

            aead.Decrypt(encryptedBytes.Span, tag.Span, sequenceNumber, headerBytes.Span);

            return(new MemoryBuffer(startOffsetOfBody, encryptedLength));
        }
Пример #5
0
        private bool TryGetReference(Span <byte> buffer, out object value, out int consumedLength)
        {
            var index = 0;

            value          = default;
            consumedLength = default;
            if (!TryDescribeData(buffer, out var type, out var length))
            {
                return(false);
            }

            if (type != Amf0Type.Reference)
            {
                return(false);
            }

            index          = NetworkBitConverter.ToUInt16(buffer.Slice(Amf0CommonValues.MARKER_LENGTH, sizeof(ushort)));
            consumedLength = Amf0CommonValues.MARKER_LENGTH + sizeof(ushort);
            if (_referenceTable.Count <= index)
            {
                return(false);
            }
            value = _referenceTable[index];
            return(true);
        }
Пример #6
0
        public static SignatureScheme Parse(MemoryCursor cursor)
        {
            var bytes = cursor.Move(2);
            var code  = (ushort)NetworkBitConverter.ParseUnaligned(bytes.Span);

            return(new SignatureScheme(code));
        }
Пример #7
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;
            }
        }
Пример #8
0
        public static NamedGroup Parse(MemoryCursor cursor)
        {
            var codeBytes = cursor.Move(2);
            var code      = (ushort)NetworkBitConverter.ParseUnaligned(codeBytes.Span);

            return(new NamedGroup(code));
        }
Пример #9
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);
            }
        }
Пример #10
0
        public int Write(MemoryCursor cursor, int?minLength = null, ValueBuffer?mask = null)
        {
            if (minLength < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(minLength));
            }

            var length = NetworkBitConverter.GetByteLength(value);

            if (minLength.HasValue)
            {
                length = Math.Max(length, minLength.Value);
            }

            var bytes = cursor.Move(length);

            NetworkBitConverter.WriteUnaligned(bytes.Span, value, length);

            if (mask.HasValue)
            {
                Mask(bytes.Span, mask.Value);
            }

            return(length);
        }
Пример #11
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);
        }
Пример #12
0
        private bool ProcessHandshakeC2(ReadOnlySequence <byte> buffer, ref int consumed)
        {
            if (buffer.Length - consumed < 1536)
            {
                return(false);
            }
            var arr = _arrayPool.Rent(1536);

            try
            {
                buffer.Slice(consumed, 1536).CopyTo(arr);
                consumed += 1536;
                var s1Timestamp = NetworkBitConverter.ToUInt32(arr.AsSpan(0, 4));
                if (s1Timestamp != _writerTimestampEpoch)
                {
                    throw new ProtocolViolationException();
                }
                if (!arr.AsSpan(8, 1528).SequenceEqual(_s1Data.AsSpan(0, 1528)))
                {
                    throw new ProtocolViolationException();
                }

                _ioPipeline.OnHandshakeSuccessful();
                return(true);
            }
            finally
            {
                _arrayPool.Return(_s1Data);
                _arrayPool.Return(arr);
                _s1Data = null;
                Dispose();
            }
        }
Пример #13
0
        private MessageData DeserializeMessage(Span <byte> buffer, out int consumed)
        {
            consumed = 0;
            var header = new MessageHeader();

            header.MessageType     = (MessageType)buffer[0];
            buffer                 = buffer.Slice(sizeof(byte));
            consumed              += sizeof(byte);
            header.MessageLength   = NetworkBitConverter.ToUInt24(buffer);
            buffer                 = buffer.Slice(3);
            consumed              += 3;
            header.Timestamp       = NetworkBitConverter.ToUInt32(buffer);
            buffer                 = buffer.Slice(sizeof(uint));
            consumed              += sizeof(uint);
            header.MessageStreamId = header.MessageStreamId;
            // Override message stream id
            buffer    = buffer.Slice(3);
            consumed += 3;
            var offset = consumed;

            consumed += (int)header.MessageLength;

            header.Timestamp += MessageHeader.Timestamp;

            return(new MessageData()
            {
                Header = header,
                DataOffset = offset,
                DataLength = header.MessageLength
            });
        }
Пример #14
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);
        }
Пример #15
0
        public static CursorWritingContext StartVectorWriting(MemoryCursor cursor, Range range)
        {
            var lengthSizeInBytes = NetworkBitConverter.GetByteLength((ulong)range.End.Value);
            var lengthBytes       = cursor.Move(lengthSizeInBytes).Span;
            var startLength       = cursor.AsOffset();

            return(new CursorWritingContext(cursor, startLength, lengthBytes, range));
        }
Пример #16
0
        public void Fill(Span <byte> bytes, ValueBuffer?mask = null)
        {
            NetworkBitConverter.WriteUnaligned(bytes, value, bytes.Length);

            if (mask.HasValue)
            {
                Mask(bytes, mask.Value);
            }
        }
Пример #17
0
 public int Write(byte[] buffer, ref int offset)
 {
     offset += LabelEncoding.PutBytes(Name, buffer, offset);
     offset += NetworkBitConverter.PutBytes((ushort)Type,
                                            buffer, offset);
     offset += NetworkBitConverter.PutBytes((ushort)Class,
                                            buffer, offset);
     return(offset);
 }
Пример #18
0
        public override void Deserialize(SerializationContext context)
        {
            var span      = context.ReadBuffer.Span;
            var eventType = (UserControlEventType)NetworkBitConverter.ToUInt16(span);

            span = span.Slice(sizeof(ushort));
            Contract.Assert(eventType == UserControlEventType.StreamIsRecorded);
            StreamID = NetworkBitConverter.ToUInt32(span);
        }
Пример #19
0
        public static MemoryBuffer Slice(MemoryCursor cursor)
        {
            var payloadLengthBytes = cursor.Move(2);
            var payloadLength      = (int)NetworkBitConverter.ParseUnaligned(payloadLengthBytes.Span);
            var startOffsetOfBody  = cursor.AsOffset();

            cursor.Move(payloadLength);

            return(new MemoryBuffer(startOffsetOfBody, payloadLength));
        }
Пример #20
0
 public bool ReadNet64(out ulong x)
 {
     if (position + 8 > count)
     {
         x = 0;
         return(false);
     }
     x         = NetworkBitConverter.ToUInt64(data, position);
     position += 8;
     return(true);
 }
Пример #21
0
 public bool ReadNet32(out uint x)
 {
     if (position + 4 > count)
     {
         x = 0;
         return(false);
     }
     x         = NetworkBitConverter.ToUInt32(data, position);
     position += 4;
     return(true);
 }
Пример #22
0
 public bool ReadNet16(out ushort x)
 {
     if (position + 2 > count)
     {
         x = 0;
         return(false);
     }
     x         = NetworkBitConverter.ToUInt16(data, position);
     position += 2;
     return(true);
 }
Пример #23
0
            public void Dispose()
            {
                var payloadLength = cursor - startLength;

                if (payloadLength < range.Start.Value || payloadLength > range.End.Value)
                {
                    throw new EncodingException();
                }

                NetworkBitConverter.WriteUnaligned(lengthBytes, (ulong)payloadLength, lengthBytes.Length);
            }
Пример #24
0
        public Message Provide(MessageHeader header, SerializationContext context, out int consumed)
        {
            var type = (UserControlEventType)NetworkBitConverter.ToUInt16(context.ReadBuffer.Span);

            if (!_messageFactories.TryGetValue(type, out var t))
            {
                throw new NotSupportedException();
            }
            consumed = 0;
            return((Message)Activator.CreateInstance(t));
        }
Пример #25
0
            public void Dispose()
            {
                var payloadLength = cursor - startOffset;

                if (payloadLength > MaxLength)
                {
                    throw new EncodingException();
                }

                NetworkBitConverter.WriteUnaligned(lengthBytes, (ulong)payloadLength, 2);
            }
Пример #26
0
 public static bool GetProtocol(Bytes packet, out ushort protocol)
 {
     try {
         int offset = EthernetAddress.Length * 2;
         protocol = NetworkBitConverter.ToUInt16(packet, offset);
     }
     catch {
         protocol = 0;
         return(false);
     }
     return(true);
 }        //Get the protocol for this packet
Пример #27
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);
            }
        }
Пример #28
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);
            }
        }
Пример #29
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);
            }
        }
Пример #30
0
        public static WritingContext StartVectorWriting(ref Span <byte> bytes, Range range)
        {
            var context           = new WritingContext(bytes, range);
            var lengthSizeInBytes = NetworkBitConverter.GetByteLength((ulong)range.End.Value);

            if (bytes.Length < lengthSizeInBytes)
            {
                throw new EncodingException();
            }

            bytes = bytes.Slice(lengthSizeInBytes);

            return(context);
        }