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); } }
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); } }
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); }
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; } }
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); }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } }
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)); }
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); } }
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); } }
// 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); } }
// 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); }
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); } }