private static ValueTask <int> WritePacketAsync(IByteHandler byteHandler, int sequenceNumber, ArraySegment <byte> contents, IOBehavior ioBehavior) { var bufferLength = contents.Count + 4; var buffer = ArrayPool <byte> .Shared.Rent(bufferLength); SerializationUtility.WriteUInt32((uint)contents.Count, buffer, 0, 3); buffer[3] = (byte)sequenceNumber; Buffer.BlockCopy(contents.Array, contents.Offset, buffer, 4, contents.Count); var task = byteHandler.WriteBytesAsync(new ArraySegment <byte>(buffer, 0, bufferLength), ioBehavior); if (task.IsCompletedSuccessfully) { ArrayPool <byte> .Shared.Return(buffer); return(default(ValueTask <int>)); } return(AddContinuation(task, buffer)); // NOTE: use a local function (with no captures) to defer creation of lambda objects ValueTask <int> AddContinuation(ValueTask <int> task_, byte[] buffer_) { return(task_.ContinueWith(x => { ArrayPool <byte> .Shared.Return(buffer_); return default(ValueTask <int>); })); } }
public CompressedPayloadHandler(IByteHandler byteHandler) { m_uncompressedStream = new MemoryStream(); m_uncompressedStreamByteHandler = new StreamByteHandler(m_uncompressedStream); m_byteHandler = byteHandler; m_bufferedByteReader = new BufferedByteReader(); }
public static ValueTask <int> WritePacketAsync(IByteHandler byteHandler, int sequenceNumber, ArraySegment <byte> contents, IOBehavior ioBehavior) { var bufferLength = contents.Count + 4; var buffer = ArrayPool <byte> .Shared.Rent(bufferLength); SerializationUtility.WriteUInt32((uint)contents.Count, buffer, 0, 3); buffer[3] = (byte)sequenceNumber; Buffer.BlockCopy(contents.Array, contents.Offset, buffer, 4, contents.Count); return(byteHandler.WriteBytesAsync(new ArraySegment <byte>(buffer, 0, bufferLength), ioBehavior) .ContinueWith(x => { ArrayPool <byte> .Shared.Return(buffer); return default(ValueTask <int>); })); }
private static ValueTask <int> WritePacketAsync(IByteHandler byteHandler, int sequenceNumber, ArraySegment <byte> contents, IOBehavior ioBehavior) { var bufferLength = contents.Count + 4; var buffer = ArrayPool <byte> .Shared.Rent(bufferLength); SerializationUtility.WriteUInt32((uint)contents.Count, buffer, 0, 3); buffer[3] = (byte)sequenceNumber; Buffer.BlockCopy(contents.Array, contents.Offset, buffer, 4, contents.Count); var task = byteHandler.WriteBytesAsync(new ArraySegment <byte>(buffer, 0, bufferLength), ioBehavior); if (task.IsCompletedSuccessfully) { ArrayPool <byte> .Shared.Return(buffer); return(default);
public static ValueTask <int> WritePayloadAsync(IByteHandler byteHandler, Func <int> getNextSequenceNumber, ArraySegment <byte> payload, IOBehavior ioBehavior) { if (payload.Count <= MaxPacketSize) { return(WritePacketAsync(byteHandler, getNextSequenceNumber(), payload, ioBehavior)); } var writeTask = default(ValueTask <int>); for (var bytesSent = 0; bytesSent < payload.Count; bytesSent += MaxPacketSize) { var contents = new ArraySegment <byte>(payload.Array, payload.Offset + bytesSent, Math.Min(MaxPacketSize, payload.Count - bytesSent)); writeTask = writeTask.ContinueWith(x => WritePacketAsync(byteHandler, getNextSequenceNumber(), contents, ioBehavior)); } return(writeTask); }
public static ValueTask <int> WritePayloadAsync(IByteHandler byteHandler, Func <int> getNextSequenceNumber, ArraySegment <byte> payload, IOBehavior ioBehavior) { return(payload.Count <= MaxPacketSize?WritePacketAsync(byteHandler, getNextSequenceNumber(), payload, ioBehavior) : CreateTask(byteHandler, getNextSequenceNumber, payload, ioBehavior)); // NOTE: use a local function (with no captures) to defer creation of lambda objects ValueTask <int> CreateTask(IByteHandler byteHandler_, Func <int> getNextSequenceNumber_, ArraySegment <byte> payload_, IOBehavior ioBehavior_) { var writeTask = default(ValueTask <int>); for (var bytesSent = 0; bytesSent < payload_.Count; bytesSent += MaxPacketSize) { var contents = new ArraySegment <byte>(payload_.Array, payload_.Offset + bytesSent, Math.Min(MaxPacketSize, payload_.Count - bytesSent)); writeTask = writeTask.ContinueWith(x => WritePacketAsync(byteHandler_, getNextSequenceNumber_(), contents, ioBehavior_)); } return(writeTask); } }
public ValueTask <ArraySegment <byte> > ReadBytesAsync(IByteHandler byteHandler, int count, IOBehavior ioBehavior) { if (m_remainingData.Count >= count) { var readBytes = m_remainingData.Slice(0, count); m_remainingData = m_remainingData.Slice(count); return(new ValueTask <ArraySegment <byte> >(readBytes)); } var buffer = count > m_buffer.Length ? new byte[count] : m_buffer; if (m_remainingData.Count > 0) { Buffer.BlockCopy(m_remainingData.Array, m_remainingData.Offset, buffer, 0, m_remainingData.Count); m_remainingData = new ArraySegment <byte>(buffer, 0, m_remainingData.Count); } return(ReadBytesAsync(byteHandler, new ArraySegment <byte>(buffer, m_remainingData.Count, buffer.Length - m_remainingData.Count), count, ioBehavior)); }
public ValueTask <ArraySegment <byte> > ReadBytesAsync(IByteHandler byteHandler, int count, IOBehavior ioBehavior) { // check if read can be satisfied from the buffer if (m_remainingData.Count >= count) { var readBytes = m_remainingData.Slice(0, count); m_remainingData = m_remainingData.Slice(count); return(new ValueTask <ArraySegment <byte> >(readBytes)); } // get a buffer big enough to hold all the data, and move any buffered data to the beginning var buffer = count > m_buffer.Length ? new byte[count] : m_buffer; if (m_remainingData.Count > 0) { Buffer.BlockCopy(m_remainingData.Array, m_remainingData.Offset, buffer, 0, m_remainingData.Count); m_remainingData = new ArraySegment <byte>(buffer, 0, m_remainingData.Count); } return(ReadBytesAsync(byteHandler, new ArraySegment <byte>(buffer, m_remainingData.Count, buffer.Length - m_remainingData.Count), count, ioBehavior)); }
public ValueTask <ArraySegment <byte> > ReadBytesAsync(IByteHandler byteHandler, int count, IOBehavior ioBehavior) { if (m_remainingData.Count >= count) { var readBytes = m_remainingData.Slice(0, count); m_remainingData = m_remainingData.Slice(count); return(new ValueTask <ArraySegment <byte> >(readBytes)); } if (m_remainingData.Count == 0) { return(ReadBytesAsync(byteHandler, default(ArraySegment <byte>), count, ioBehavior)); } // save data from m_remainingData.Array because calling ReadAsync may invalidate it var buffer = new byte[Math.Max(count, 16384)]; Buffer.BlockCopy(m_remainingData.Array, m_remainingData.Offset, buffer, 0, m_remainingData.Count); var previousReadBytes = new ArraySegment <byte>(buffer, 0, m_remainingData.Count); return(ReadBytesAsync(byteHandler, previousReadBytes, count, ioBehavior)); }
private ValueTask <ArraySegment <byte> > ReadBytesAsync(IByteHandler byteHandler, ArraySegment <byte> buffer, int totalBytesToRead, IOBehavior ioBehavior) { // keep reading data synchronously while it is available var readBytesTask = byteHandler.ReadBytesAsync(buffer, ioBehavior); while (readBytesTask.IsCompleted) { ValueTask <ArraySegment <byte> > result; if (HasReadAllData(readBytesTask.Result, ref buffer, totalBytesToRead, out result)) { return(result); } readBytesTask = byteHandler.ReadBytesAsync(buffer, ioBehavior); } // call .ContinueWith (as a separate method, so that the temporary class for the lambda is only allocated if necessary) return(AddContinuation(readBytesTask, byteHandler, buffer, totalBytesToRead, ioBehavior)); ValueTask <ArraySegment <byte> > AddContinuation(ValueTask <int> readBytesTask_, IByteHandler byteHandler_, ArraySegment <byte> buffer_, int totalBytesToRead_, IOBehavior ioBehavior_) => readBytesTask_.ContinueWith(x => HasReadAllData(x, ref buffer_, totalBytesToRead_, out var result_) ? result_ : ReadBytesAsync(byteHandler_, buffer_, totalBytesToRead_, ioBehavior_)); }
private ValueTask <ArraySegment <byte> > ReadBytesAsync(IByteHandler byteHandler, ArraySegment <byte> previousReadBytes, int count, IOBehavior ioBehavior) { return(byteHandler.ReadBytesAsync(count - previousReadBytes.Count, ioBehavior) .ContinueWith(readBytes => { if (readBytes.Count == 0) { return new ValueTask <ArraySegment <byte> >(previousReadBytes); } if (previousReadBytes.Array == null && readBytes.Count >= count) { m_remainingData = readBytes.Slice(count); return new ValueTask <ArraySegment <byte> >(readBytes.Slice(0, count)); } var previousReadBytesArray = previousReadBytes.Array; if (previousReadBytesArray == null) { previousReadBytesArray = new byte[Math.Max(count, 16384)]; } else if (previousReadBytesArray.Length < previousReadBytes.Count + readBytes.Count) { Array.Resize(ref previousReadBytesArray, Math.Max(previousReadBytesArray.Length * 2, previousReadBytes.Count + readBytes.Count)); } Buffer.BlockCopy(readBytes.Array, readBytes.Offset, previousReadBytesArray, previousReadBytes.Offset + previousReadBytes.Count, readBytes.Count); previousReadBytes = new ArraySegment <byte>(previousReadBytesArray, previousReadBytes.Offset, previousReadBytes.Count + readBytes.Count); if (previousReadBytes.Count >= count) { m_remainingData = previousReadBytes.Slice(count); return new ValueTask <ArraySegment <byte> >(previousReadBytes.Slice(0, count)); } return ReadBytesAsync(byteHandler, previousReadBytes, count, ioBehavior); })); }
private ValueTask <ArraySegment <byte> > ReadBytesAsync(IByteHandler byteHandler, ArraySegment <byte> buffer, int count, IOBehavior ioBehavior) { return(byteHandler.ReadBytesAsync(buffer, ioBehavior) .ContinueWith(readBytesCount => { if (readBytesCount == 0) { var data = m_remainingData; m_remainingData = default(ArraySegment <byte>); return new ValueTask <ArraySegment <byte> >(data); } var bufferSize = buffer.Offset + readBytesCount; if (bufferSize >= count) { var bufferBytes = new ArraySegment <byte>(buffer.Array, 0, bufferSize); var requestedBytes = bufferBytes.Slice(0, count); m_remainingData = bufferBytes.Slice(count); return new ValueTask <ArraySegment <byte> >(requestedBytes); } return ReadBytesAsync(byteHandler, new ArraySegment <byte>(buffer.Array, bufferSize, buffer.Array.Length - bufferSize), count, ioBehavior); })); }
public StandardPayloadHandler(IByteHandler byteHandler) { ByteHandler = byteHandler; }
static ValueTask <Packet> AddContinuation(ValueTask <ArraySegment <byte> > headerBytes_, BufferedByteReader bufferedByteReader_, IByteHandler byteHandler_, Func <int> getNextSequenceNumber_, ProtocolErrorBehavior protocolErrorBehavior_, IOBehavior ioBehavior_) => headerBytes_.ContinueWith(x => ReadPacketAfterHeader(x, bufferedByteReader_, byteHandler_, getNextSequenceNumber_, protocolErrorBehavior_, ioBehavior_));
public static ValueTask <Packet> ReadPacketAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int?> getNextSequenceNumber, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { return(bufferedByteReader.ReadBytesAsync(byteHandler, 4, ioBehavior) .ContinueWith(headerBytes => { if (headerBytes.Count < 4) { return protocolErrorBehavior == ProtocolErrorBehavior.Throw ? ValueTaskExtensions.FromException <Packet>(new EndOfStreamException()) : default(ValueTask <Packet>); } var payloadLength = (int)SerializationUtility.ReadUInt32(headerBytes.Array, headerBytes.Offset, 3); int packetSequenceNumber = headerBytes.Array[headerBytes.Offset + 3]; var expectedSequenceNumber = getNextSequenceNumber() % 256; if (expectedSequenceNumber.HasValue && packetSequenceNumber != expectedSequenceNumber.Value) { if (protocolErrorBehavior == ProtocolErrorBehavior.Ignore) { return default(ValueTask <Packet>); } var exception = new InvalidOperationException("Packet received out-of-order. Expected {0}; got {1}.".FormatInvariant(expectedSequenceNumber.Value, packetSequenceNumber)); return ValueTaskExtensions.FromException <Packet>(exception); } return bufferedByteReader.ReadBytesAsync(byteHandler, payloadLength, ioBehavior) .ContinueWith(payloadBytes => { if (payloadBytes.Count < payloadLength) { return protocolErrorBehavior == ProtocolErrorBehavior.Throw ? ValueTaskExtensions.FromException <Packet>(new EndOfStreamException()) : default(ValueTask <Packet>); } return new ValueTask <Packet>(new Packet(packetSequenceNumber, payloadBytes)); }); })); }
private static ValueTask <ArraySegment <byte> > DoReadPayloadAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int> getNextSequenceNumber, ArraySegmentHolder <byte> previousPayloads, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { var readPacketTask = ReadPacketAsync(bufferedByteReader, byteHandler, getNextSequenceNumber, protocolErrorBehavior, ioBehavior); while (readPacketTask.IsCompleted) { if (HasReadPayload(previousPayloads, readPacketTask.Result, protocolErrorBehavior, out var result)) { return(result); } readPacketTask = ReadPacketAsync(bufferedByteReader, byteHandler, getNextSequenceNumber, protocolErrorBehavior, ioBehavior); } return(AddContinuation(readPacketTask, bufferedByteReader, byteHandler, getNextSequenceNumber, previousPayloads, protocolErrorBehavior, ioBehavior)); // NOTE: use a local function (with no captures) to defer creation of lambda objects ValueTask <ArraySegment <byte> > AddContinuation(ValueTask <Packet> readPacketTask_, BufferedByteReader bufferedByteReader_, IByteHandler byteHandler_, Func <int> getNextSequenceNumber_, ArraySegmentHolder <byte> previousPayloads_, ProtocolErrorBehavior protocolErrorBehavior_, IOBehavior ioBehavior_) { return(readPacketTask_.ContinueWith(packet => HasReadPayload(previousPayloads_, packet, protocolErrorBehavior_, out var result_) ? result_ : DoReadPayloadAsync(bufferedByteReader_, byteHandler_, getNextSequenceNumber_, previousPayloads_, protocolErrorBehavior_, ioBehavior_))); } }
public static ValueTask <ArraySegment <byte> > ReadPayloadAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int> getNextSequenceNumber, ArraySegmentHolder <byte> cache, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { cache.Clear(); return(DoReadPayloadAsync(bufferedByteReader, byteHandler, getNextSequenceNumber, cache, protocolErrorBehavior, ioBehavior)); }
private static ValueTask <Packet> ReadPacketAfterHeader(ArraySegment <byte> headerBytes, BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int> getNextSequenceNumber, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { if (headerBytes.Count < 4) { return(protocolErrorBehavior == ProtocolErrorBehavior.Throw ? ValueTaskExtensions.FromException <Packet>(new EndOfStreamException("Expected to read 4 header bytes but only received {0}.".FormatInvariant(headerBytes.Count))) : default(ValueTask <Packet>)); } var payloadLength = (int)SerializationUtility.ReadUInt32(headerBytes.Array, headerBytes.Offset, 3); int packetSequenceNumber = headerBytes.Array[headerBytes.Offset + 3]; var expectedSequenceNumber = getNextSequenceNumber() % 256; if (expectedSequenceNumber != -1 && packetSequenceNumber != expectedSequenceNumber) { if (protocolErrorBehavior == ProtocolErrorBehavior.Ignore) { return(default(ValueTask <Packet>)); } var exception = MySqlProtocolException.CreateForPacketOutOfOrder(expectedSequenceNumber, packetSequenceNumber); return(ValueTaskExtensions.FromException <Packet>(exception)); } var payloadBytesTask = bufferedByteReader.ReadBytesAsync(byteHandler, payloadLength, ioBehavior); if (payloadBytesTask.IsCompleted) { return(CreatePacketFromPayload(payloadBytesTask.Result, payloadLength, protocolErrorBehavior)); } return(AddContinuation(payloadBytesTask, payloadLength, protocolErrorBehavior)); // NOTE: use a local function (with no captures) to defer creation of lambda objects ValueTask <Packet> AddContinuation(ValueTask <ArraySegment <byte> > payloadBytesTask_, int payloadLength_, ProtocolErrorBehavior protocolErrorBehavior_) => payloadBytesTask_.ContinueWith(x => CreatePacketFromPayload(x, payloadLength_, protocolErrorBehavior_)); }
private static ValueTask <Packet> ReadPacketAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int> getNextSequenceNumber, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { var headerBytesTask = bufferedByteReader.ReadBytesAsync(byteHandler, 4, ioBehavior); if (headerBytesTask.IsCompleted) { return(ReadPacketAfterHeader(headerBytesTask.Result, bufferedByteReader, byteHandler, getNextSequenceNumber, protocolErrorBehavior, ioBehavior)); } return(AddContinuation(headerBytesTask, bufferedByteReader, byteHandler, getNextSequenceNumber, protocolErrorBehavior, ioBehavior)); // NOTE: use a local function (with no captures) to defer creation of lambda objects ValueTask <Packet> AddContinuation(ValueTask <ArraySegment <byte> > headerBytes_, BufferedByteReader bufferedByteReader_, IByteHandler byteHandler_, Func <int> getNextSequenceNumber_, ProtocolErrorBehavior protocolErrorBehavior_, IOBehavior ioBehavior_) => headerBytes_.ContinueWith(x => ReadPacketAfterHeader(x, bufferedByteReader_, byteHandler_, getNextSequenceNumber_, protocolErrorBehavior_, ioBehavior_)); }
public StandardPayloadHandler(IByteHandler byteHandler) { ByteHandler = byteHandler; m_getNextSequenceNumber = () => m_sequenceNumber++; }
static async ValueTask <Packet> AddContinuation(ValueTask <ArraySegment <byte> > headerBytes_, BufferedByteReader bufferedByteReader_, IByteHandler byteHandler_, Func <int> getNextSequenceNumber_, ProtocolErrorBehavior protocolErrorBehavior_, IOBehavior ioBehavior_) => await ReadPacketAfterHeader(await headerBytes_.ConfigureAwait(false), bufferedByteReader_, byteHandler_, getNextSequenceNumber_, protocolErrorBehavior_, ioBehavior_).ConfigureAwait(false);
private static ValueTask <Packet> ReadPacketAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int> getNextSequenceNumber, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { var headerBytesTask = bufferedByteReader.ReadBytesAsync(byteHandler, 4, ioBehavior); if (headerBytesTask.IsCompleted) { return(ReadPacketAfterHeader(headerBytesTask.Result, bufferedByteReader, byteHandler, getNextSequenceNumber, protocolErrorBehavior, ioBehavior)); } return(AddContinuation(headerBytesTask, bufferedByteReader, byteHandler, getNextSequenceNumber, protocolErrorBehavior, ioBehavior));
public static ValueTask <ArraySegment <byte> > ReadPayloadAsync(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int?> getNextSequenceNumber, ArraySegment <byte> previousPayloads, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { return(ReadPacketAsync(bufferedByteReader, byteHandler, getNextSequenceNumber, protocolErrorBehavior, ioBehavior).ContinueWith(packet => ContinueRead(bufferedByteReader, byteHandler, getNextSequenceNumber, previousPayloads, packet, protocolErrorBehavior, ioBehavior))); }
private static ValueTask <ArraySegment <byte> > ContinueRead(BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int?> getNextSequenceNumber, ArraySegment <byte> previousPayloads, Packet packet, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) { if (packet == null && protocolErrorBehavior == ProtocolErrorBehavior.Ignore) { return(default(ValueTask <ArraySegment <byte> >)); } var previousPayloadsArray = previousPayloads.Array; if (previousPayloadsArray == null && packet.Contents.Count < MaxPacketSize) { return(new ValueTask <ArraySegment <byte> >(packet.Contents)); } if (previousPayloadsArray == null) { previousPayloadsArray = new byte[ProtocolUtility.MaxPacketSize + 1]; } else if (previousPayloads.Offset + previousPayloads.Count + packet.Contents.Count > previousPayloadsArray.Length) { Array.Resize(ref previousPayloadsArray, previousPayloadsArray.Length * 2); } Buffer.BlockCopy(packet.Contents.Array, packet.Contents.Offset, previousPayloadsArray, previousPayloads.Offset + previousPayloads.Count, packet.Contents.Count); previousPayloads = new ArraySegment <byte>(previousPayloadsArray, previousPayloads.Offset, previousPayloads.Count + packet.Contents.Count); return(packet.Contents.Count < ProtocolUtility.MaxPacketSize ? new ValueTask <ArraySegment <byte> >(previousPayloads) : ReadPayloadAsync(bufferedByteReader, byteHandler, getNextSequenceNumber, previousPayloads, protocolErrorBehavior, ioBehavior)); }