예제 #1
0
 private void EnsureBuffer()
 {
     if (_needAlloc)
     {
         _writableBuffer = _writer.Alloc();
         _needAlloc = false;
     }
 }
예제 #2
0
        private void ProcessReceives()
        {
            _buffer = _input.Alloc(2048);
            var receiveBufferSeg = GetSegmentFromMemory(_buffer.Memory);

            if (!_rio.RioReceive(_requestQueue, ref receiveBufferSeg, 1, RioReceiveFlags.None, 0))
            {
                ThrowError(ErrorType.Receive);
            }
        }
예제 #3
0
        private static unsafe Exception Receive(int fd, int availableBytes, ref WritableBuffer wb)
        {
            int ioVectorLength = availableBytes <= wb.Buffer.Length ? 1 :
                                 Math.Min(1 + (availableBytes - wb.Buffer.Length + MaxPooledBlockLength - 1) / MaxPooledBlockLength, MaxIOVectorReceiveLength);
            var ioVectors = stackalloc IOVector[ioVectorLength];
            var allocated = 0;

            var advanced      = 0;
            int ioVectorsUsed = 0;

            for (; ioVectorsUsed < ioVectorLength; ioVectorsUsed++)
            {
                wb.Ensure(1);
                var   memory = wb.Buffer;
                var   length = memory.Length;
                void *pointer;
                wb.Buffer.TryGetPointer(out pointer);

                ioVectors[ioVectorsUsed].Base  = pointer;
                ioVectors[ioVectorsUsed].Count = (void *)length;
                allocated += length;

                if (allocated >= availableBytes)
                {
                    // Every Memory (except the last one) must be filled completely.
                    ioVectorsUsed++;
                    break;
                }

                wb.Advance(length);
                advanced += length;
            }
            var expectedMin = Math.Min(availableBytes, allocated);

            // Ideally we get availableBytes in a single receive
            // but we are happy if we get at least a part of it
            // and we are willing to take {MaxEAgainCount} EAGAINs.
            // Less data could be returned due to these reasons:
            // * TCP URG
            // * packet was not placed in receive queue (race with FIONREAD)
            // * ?
            const int MaxEAgainCount = 10;
            var       eAgainCount    = 0;
            var       received       = 0;

            do
            {
                var result = SocketInterop.Receive(fd, ioVectors, ioVectorsUsed);
                if (result.IsSuccess)
                {
                    received += result.Value;
                    if (received >= expectedMin)
                    {
                        // We made it!
                        wb.Advance(received - advanced);
                        return(null);
                    }
                    eAgainCount = 0;
                    // Update ioVectors to match bytes read
                    var skip = result.Value;
                    for (int i = 0; (i < ioVectorsUsed) && (skip > 0); i++)
                    {
                        var length  = (int)ioVectors[i].Count;
                        var skipped = Math.Min(skip, length);
                        ioVectors[i].Count = (void *)(length - skipped);
                        ioVectors[i].Base  = (byte *)ioVectors[i].Base + skipped;
                        skip -= skipped;
                    }
                }
                else if (result == PosixResult.EAGAIN || result == PosixResult.EWOULDBLOCK)
                {
                    eAgainCount++;
                    if (eAgainCount == MaxEAgainCount)
                    {
                        return(new NotSupportedException("Too many EAGAIN, unable to receive available bytes."));
                    }
                }
                else if (result == PosixResult.ECONNRESET)
                {
                    return(new ConnectionResetException(result.ErrorDescription(), result.AsException()));
                }
                else
                {
                    return(result.AsException());
                }
            } while (true);
        }
예제 #4
0
 void IMessageWriter.WritePayload(WritableBuffer buffer)
 => buffer.WriteUtf8String(value);
예제 #5
0
        public unsafe int SignHash(IHashProvider provider, SignatureScheme scheme, ref WritableBuffer writer, byte *message, int messageLength)
        {
            var    keySize = SignatureSize(scheme);
            IntPtr hashType;

            switch (scheme)
            {
            case SignatureScheme.rsa_pkcs1_sha256:
            case SignatureScheme.rsa_pss_sha256:
                hashType = EVP_sha256;
                break;

            case SignatureScheme.rsa_pkcs1_sha512:
            case SignatureScheme.rsa_pss_sha512:
                hashType = EVP_sha512;
                break;

            case SignatureScheme.rsa_pkcs1_sha384:
            case SignatureScheme.rsa_pss_sha384:
                hashType = EVP_sha384;
                break;

            default:
                ExceptionHelper.ThrowException(new ArgumentOutOfRangeException(nameof(scheme)));
                hashType = IntPtr.Zero;
                break;
            }

            EVP_MD_CTX   ctx = EVP_MD_CTX_new();
            EVP_PKEY_CTX pctx;
            GCHandle     handle;

            try
            {
                ThrowOnError(EVP_DigestSignInit(ctx, &pctx, hashType, IntPtr.Zero, _key));
                ThrowIfNegative(EVP_PKEY_CTX_ctrl(pctx, EVP_PKEY_type.EVP_PKEY_RSA, EVP_PKEY_Ctrl_OP.EVP_PKEY_OP_TYPE_SIG,
                                                  EVP_PKEY_Ctrl_Command.EVP_PKEY_CTRL_MD, 0, (void *)hashType));
                if ((((ushort)scheme) & 0x00FF) == 1)
                {
                    ThrowIfNegative(EVP_PKEY_CTX_ctrl(pctx, EVP_PKEY_type.EVP_PKEY_RSA, EVP_PKEY_Ctrl_OP.EVP_PKEY_OP_NONE
                                                      , EVP_PKEY_Ctrl_Command.EVP_PKEY_CTRL_RSA_PADDING, (int)RSA_PADDING.RSA_PKCS1_PADDING, null));
                }
                else
                {
                    //PSS Padding
                    ThrowIfNegative(EVP_PKEY_CTX_ctrl(pctx, EVP_PKEY_type.EVP_PKEY_RSA, EVP_PKEY_Ctrl_OP.EVP_PKEY_OP_SIGN
                                                      , EVP_PKEY_Ctrl_Command.EVP_PKEY_CTRL_RSA_PADDING, (int)RSA_PADDING.RSA_PKCS1_PSS_PADDING, null));
                    ThrowIfNegative(EVP_PKEY_CTX_ctrl(pctx, EVP_PKEY_type.EVP_PKEY_RSA, EVP_PKEY_Ctrl_OP.EVP_PKEY_OP_SIGN
                                                      , EVP_PKEY_Ctrl_Command.EVP_PKEY_CTRL_RSA_PSS_SALTLEN, 32, null));
                }
                ThrowOnError(EVP_DigestUpdate(ctx, message, messageLength));
                var size = UIntPtr.Zero;
                ThrowOnError(EVP_DigestSignFinal(ctx, null, ref size));
                writer.Ensure((int)size);
                var output = writer.Memory.GetPointer(out handle);
                ThrowOnError(EVP_DigestSignFinal(ctx, output, ref size));
                writer.Advance((int)size);
                return((int)size);
            }
            finally
            {
                ctx.Free();
                if (handle.IsAllocated)
                {
                    handle.Free();
                }
            }
        }
예제 #6
0
 protected void WriteTag(ref WritableBuffer writer)
 {
     writer.Ensure(_key.TagSize);
     _key.GetTag(writer.Buffer.Span.Slice(0, _key.TagSize));
     writer.Advance(_key.TagSize);
 }
예제 #7
0
 public static void WriteEndChunkBytes(ref WritableBuffer start)
 {
     start.Write(_endChunkBytes.Array, _endChunkBytes.Offset, _endChunkBytes.Count);
 }
예제 #8
0
 private void WriteEndResponse(ref WritableBuffer buffer)
 {
     buffer.Write(_chunkedEndBytes, 0, _chunkedEndBytes.Length);
 }
예제 #9
0
        public static void WriteUInt64(this WritableBuffer buffer, ulong value)
        {
            // optimized versions for 0-1000
            int len;

            if (value < 10)
            {
                buffer.Ensure(len = 1);
                var span = buffer.Memory.Span;
                span[0] = (byte)('0' + value);
            }
            else if (value < 100)
            {
                buffer.Ensure(len = 2);
                var span = buffer.Memory.Span;
                span[0] = (byte)('0' + value / 10);
                span[1] = (byte)('0' + value % 10);
            }
            else if (value < 1000)
            {
                buffer.Ensure(len = 3);
                var span = buffer.Memory.Span;
                span[2] = (byte)('0' + value % 10);
                value  /= 10;
                span[0] = (byte)('0' + value / 10);
                span[1] = (byte)('0' + value % 10);
            }
            else
            {
                // more generic version for all other numbers; first find the number of digits;
                // lost of ways to do this, but: http://stackoverflow.com/a/6655759/23354
                ulong remaining = value;
                len = 1;
                if (remaining >= 10000000000000000)
                {
                    remaining /= 10000000000000000; len += 16;
                }
                if (remaining >= 100000000)
                {
                    remaining /= 100000000; len += 8;
                }
                if (remaining >= 10000)
                {
                    remaining /= 10000; len += 4;
                }
                if (remaining >= 100)
                {
                    remaining /= 100; len += 2;
                }
                if (remaining >= 10)
                {
                    remaining /= 10; len += 1;
                }
                buffer.Ensure(len);

                // now we'll walk *backwards* from the last character, adding the digit each time
                // and dividing by 10
                int index = len - 1;
                var span  = buffer.Memory.Span;

                do
                {
                    span[index--] = (byte)('0' + value % 10);
                    value        /= 10;
                } while (value != 0);
            }
            buffer.Advance(len);
        }
예제 #10
0
 internal virtual void Visit(WritableBuffer key, WritableBuffer value)
 {
     key.PutInt(0, this.Key);
     value.PutInt(0, this.Value);
 }
예제 #11
0
        public override void HandleHandshakeMessage(HandshakeType handshakeMessageType, ReadableBuffer buffer, ref WritableBuffer outBuffer)
        {
            switch (State)
            {
            case StateType.None:
                if (handshakeMessageType != HandshakeType.client_hello)
                {
                    Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, "Tls 12 didnt get a client hello");
                }
                Hello.ReadClientHelloTls12(buffer, this);
                if (CipherSuite == null)
                {
                    //Couldn't agree a set of ciphers
                    Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "Could not agree on a cipher suite during reading client hello");
                }
                this.StartHandshakeHash(buffer);
                //Write server hello
                ChangeState(StateType.SendServerHello);
                _frameWriter.StartFrame(RecordType.Handshake, ref outBuffer);
                this.WriteHandshake(ref outBuffer, HandshakeType.server_hello, Hello.SendServerHello12);
                _frameWriter.FinishFrame(ref outBuffer);
                _frameWriter.StartFrame(RecordType.Handshake, ref outBuffer);
                this.WriteHandshake(ref outBuffer, HandshakeType.certificate, ServerHandshakeTls12.SendCertificates);
                _frameWriter.FinishFrame(ref outBuffer);

                if (CipherSuite.ExchangeType == KeyExchangeType.Ecdhe || CipherSuite.ExchangeType == KeyExchangeType.Dhe)
                {
                    if (KeyShare == null)
                    {
                        KeyShare = CryptoProvider.GetDefaultKeyShare(CipherSuite.ExchangeType);
                    }
                    _frameWriter.StartFrame(RecordType.Handshake, ref outBuffer);
                    this.WriteHandshake(ref outBuffer, HandshakeType.server_key_exchange, ServerHandshakeTls12.SendKeyExchange);
                    _frameWriter.FinishFrame(ref outBuffer);
                }
                _frameWriter.StartFrame(RecordType.Handshake, ref outBuffer);
                this.WriteHandshake(ref outBuffer, HandshakeType.server_hello_done, (w, state) => w);
                _frameWriter.FinishFrame(ref outBuffer);
                ChangeState(StateType.WaitClientKeyExchange);
                break;

            case StateType.WaitClientKeyExchange:
                if (handshakeMessageType != HandshakeType.client_key_exchange)
                {
                    Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, $"Received a {handshakeMessageType} when we expected a {HandshakeType.client_key_exchange}");
                }
                HandshakeHash.HashData(buffer);
                KeyShare.SetPeerKey(buffer.Slice(5));
                _schedule.GenerateMasterSecret();
                _schedule.CalculateClientFinished();
                //We can send the server finished because we have the expected client finished
                _schedule.GenerateKeyMaterial();
                ChangeState(StateType.ChangeCipherSpec);
                break;

            case StateType.WaitClientFinished:
                if (handshakeMessageType != HandshakeType.finished)
                {
                    Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, $"unexpected message");
                }
                _schedule.CompareClientFinishedGenerateServerFinished(buffer);
                _frameWriter.StartFrame(RecordType.ChangeCipherSpec, ref outBuffer);
                outBuffer.WriteBigEndian <byte>(1);
                _frameWriter.FinishFrame(ref outBuffer);

                _writeKey = _schedule.GetServerKey();

                _frameWriter.StartFrame(RecordType.Handshake, ref outBuffer);
                this.WriteHandshake(ref outBuffer, HandshakeType.finished, _schedule.WriteServerFinished);
                _frameWriter.FinishFrame(ref outBuffer);
                KeyShare?.Dispose();
                KeyShare = null;
                ChangeState(StateType.HandshakeComplete);
                break;

            default:
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.unexpected_message, $"Not in any known state {State} that we expected a handshake messge from {handshakeMessageType}");
                break;
            }
        }
예제 #12
0
 private unsafe Uv.uv_buf_t OnAlloc(UvStreamHandle handle, int status)
 {
     _inputBuffer = _input.Alloc(2048);
     return(handle.Libuv.buf_init((IntPtr)_inputBuffer.Memory.UnsafePointer, _inputBuffer.Memory.Length));
 }
예제 #13
0
 public async Task FlushAsync(WritableBuffer buffer)
 {
     await buffer.FlushAsync();
 }
예제 #14
0
        public static WritableBuffer SendKeyExchange(WritableBuffer buffer, IConnectionState connectionState)
        {
            connectionState.KeyShare.WritePublicKey(ref buffer);

            return(buffer);
        }
예제 #15
0
 public void write(string s, WritableBuffer header)
 {
 }
 protected virtual bool Read(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
 {
     throw new NotImplementedException();
 }
예제 #17
0
 public Benchmarks()
 {
     _buffer = new byte[1024];
     _stream = new MemoryStream(_buffer);
     _writer = new WritableBuffer(_buffer, () => new byte[1024], buf => { });
 }
예제 #18
0
 public abstract void HandleHandshakeMessage(HandshakeType handshakeMessageType, ReadableBuffer buffer, ref WritableBuffer outBuffer);
예제 #19
0
 public TcpWriteBatch()
 {
     byte[] bytes = Encoding.UTF8.GetBytes(Content);
     this.dataBuffer = WritableBuffer.From(bytes);
     this.writeCount = 0;
 }
예제 #20
0
 public void StartHandshake(ref WritableBuffer writer)
 {
     this.WriteHandshake(ref writer, HandshakeType.client_hello, Hello.WriteClientHello);
     _helloBuffer = writer.AsReadableBuffer().ToArray();
     State        = StateType.WaitServerHello;
 }
예제 #21
0
 private Uv.uv_buf_t OnAlloc(UvStreamHandle handle, int status)
 {
     _inputBuffer = _input.Alloc(2048);
     return(handle.Libuv.buf_init(_inputBuffer.Memory.BufferPtr, _inputBuffer.Memory.Length));
 }
예제 #22
0
 private void WriteEndResponse(WritableBuffer buffer)
 {
     buffer.Write(_chunkedEndBytes);
 }
예제 #23
0
 public abstract void Encrypt(ref WritableBuffer writer, Span <byte> plainText, RecordType recordType, TlsVersion tlsVersion);
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public boolean visit(WritableBuffer key, WritableBuffer value) throws java.io.IOException
            public bool visit(WritableBuffer key, WritableBuffer value)
            {
                throw new IOException("boom!");
            }
 private static void WriteHeaders(HttpHeaders headers, ref WritableBuffer buffer)
 {
     foreach (var header in headers)
     {
         buffer.Append($"{header.Key}:{string.Join(",", header.Value)}\r\n", TextEncoding.Utf8);
     }
 }
예제 #26
0
 protected virtual bool Read(ReadableBuffer readableBuffer, WritableBuffer writableBuffer, out ReadCursor consumed, out ReadCursor examined)
 {
     throw new NotImplementedException();
 }
예제 #27
0
        private async void ReceiveFromSocketAndPushToWriterAsync()
        {
            SocketAsyncEventArgs args = null;

            try
            {
                // if the consumer says they don't want the data, we need to shut down the receive
                GC.KeepAlive(_input.Writing.ContinueWith(delegate
                {// GC.KeepAlive here just to shut the compiler up
                    try { Socket.Shutdown(SocketShutdown.Receive); } catch { }
                }));

                // wait for someone to be interested in data before we
                // start allocating buffers and probing the socket
                await _input.ReadingStarted;

                args = GetOrCreateSocketAsyncEventArgs();
                while (!_input.Writing.IsCompleted)
                {
                    bool           haveWriteBuffer = false;
                    WritableBuffer buffer          = default(WritableBuffer);
                    var            initialSegment  = default(ArraySegment <byte>);

                    try
                    {
                        int bytesFromInitialDataBuffer = 0;

                        if (Socket.Available == 0)
                        {
                            // now, this gets a bit messy unfortunately, because support for the ideal option
                            // (zero-length reads) is platform dependent
                            switch (_bufferStyle)
                            {
                            case BufferStyle.Unknown:
                                try
                                {
                                    initialSegment = await ReceiveInitialDataUnknownStrategyAsync(args);
                                }
                                catch
                                {
                                    initialSegment = default(ArraySegment <byte>);
                                }
                                if (initialSegment.Array == null)
                                {
                                    continue;     // redo from start
                                }
                                break;

                            case BufferStyle.UseZeroLengthBuffer:
                                // if we already have a buffer, use that (but: zero count); otherwise use a shared
                                // zero-length; this avoids constantly changing the buffer that the args use, which
                                // avoids some overheads
                                args.SetBuffer(args.Buffer ?? _zeroLengthBuffer, 0, 0);

                                // await async for the io work to be completed
                                await Socket.ReceiveSignalAsync(args);

                                break;

                            case BufferStyle.UseSmallBuffer:
                                // We need  to do a speculative receive with a *cheap* buffer while we wait for input; it would be *nice* if
                                // we could do a zero-length receive, but this is not supported equally on all platforms (fine on Windows, but
                                // linux hates it). The key aim here is to make sure that we don't tie up an entire block from the memory pool
                                // waiting for input on a socket; fine for 1 socket, not so fine for 100,000 sockets

                                // do a short receive while we wait (async) for data
                                initialSegment = LeaseSmallBuffer();
                                args.SetBuffer(initialSegment.Array, initialSegment.Offset, initialSegment.Count);

                                // await async for the io work to be completed
                                await Socket.ReceiveSignalAsync(args);

                                break;
                            }
                            if (args.SocketError != SocketError.Success)
                            {
                                throw new SocketException((int)args.SocketError);
                            }

                            // note we can't check BytesTransferred <= 0, as we always
                            // expect 0; but if we returned, we expect data to be
                            // buffered *on the socket*, else EOF
                            if ((bytesFromInitialDataBuffer = args.BytesTransferred) <= 0)
                            {
                                if (ReferenceEquals(initialSegment.Array, _zeroLengthBuffer))
                                {
                                    // sentinel value that means we should just
                                    // consume sync (we expect there to be data)
                                    initialSegment = default(ArraySegment <byte>);
                                }
                                else
                                {
                                    // socket reported EOF
                                    RecycleSmallBuffer(ref initialSegment);
                                }
                                if (Socket.Available == 0)
                                {
                                    // yup, definitely an EOF
                                    break;
                                }
                            }
                        }


                        // note that we will try to coalesce things here to reduce the number of flushes; we
                        // certainly want to coalesce the initial buffer (from the speculative receive) with the initial
                        // data, but we probably don't want to buffer indefinitely; for now, it will buffer up to 4 pages
                        // before flushing (entirely arbitrarily) - might want to make this configurable later
                        buffer          = _input.Alloc(SmallBufferSize * 2);
                        haveWriteBuffer = true;

                        const int FlushInputEveryBytes = 4 * MemoryPool.MaxPooledBlockLength;

                        if (initialSegment.Array != null)
                        {
                            // need to account for anything that we got in the speculative receive
                            if (bytesFromInitialDataBuffer != 0)
                            {
                                buffer.Write(new Span <byte>(initialSegment.Array, initialSegment.Offset, bytesFromInitialDataBuffer));
                            }
                            // make the small buffer available to other consumers
                            RecycleSmallBuffer(ref initialSegment);
                        }

                        bool isEOF = false;
                        while (Socket.Available != 0 && buffer.BytesWritten < FlushInputEveryBytes)
                        {
                            buffer.Ensure(); // ask for *something*, then use whatever is available (usually much much more)
                            SetBuffer(buffer.Memory, args);
                            // await async for the io work to be completed
                            await Socket.ReceiveSignalAsync(args);

                            // either way, need to validate
                            if (args.SocketError != SocketError.Success)
                            {
                                throw new SocketException((int)args.SocketError);
                            }
                            int len = args.BytesTransferred;
                            if (len <= 0)
                            {
                                // socket reported EOF
                                isEOF = true;
                                break;
                            }

                            // record what data we filled into the buffer
                            buffer.Advance(len);
                        }
                        if (isEOF)
                        {
                            break;
                        }
                    }
                    finally
                    {
                        RecycleSmallBuffer(ref initialSegment);
                        if (haveWriteBuffer)
                        {
                            await buffer.FlushAsync();
                        }
                    }
                }
                _input.CompleteWriter();
            }
            catch (Exception ex)
            {
                // don't trust signal after an error; someone else could
                // still have it and invoke Set
                if (args != null)
                {
                    args.UserToken = null;
                }
                _input?.CompleteWriter(ex);
            }
            finally
            {
                RecycleSocketAsyncEventArgs(args);
            }
        }
예제 #28
0
 public void WriteMessage(ref WritableBuffer buffer)
 {
     buffer.WriteBigEndian(MessageId);
 }
예제 #29
0
        private unsafe Uv.uv_buf_t OnAlloc(UvStreamHandle handle, int status)
        {
            _inputBuffer = _input.Alloc(2048);

            void* pointer;
            if (!_inputBuffer.Memory.TryGetPointer(out pointer))
            {
                throw new InvalidOperationException("Pointer must be pinned");
            }

            return handle.Libuv.buf_init((IntPtr)pointer, _inputBuffer.Memory.Length);
        }
예제 #30
0
 public static void WriteAsciiString(this WritableBuffer buffer, string value)
 => WriteString(buffer, value, ASCIIEncoding);
예제 #31
0
 public WriteableBufferFormatter(ref WritableBuffer writableBuffer, FormattingData formattingData)
 {
     _writableBuffer = writableBuffer;
     FormattingData  = formattingData;
 }
예제 #32
0
 public static void WriteUtf8String(this WritableBuffer buffer, string value)
 => WriteString(buffer, value, Utf8Encoding);
            protected override bool Read(ReadOnlyBuffer readableBuffer, WritableBuffer writableBuffer, out Position consumed, out Position examined)
            {
                consumed = default(Position);
                examined = default(Position);

                while (_mode < Mode.Trailer)
                {
                    if (_mode == Mode.Prefix)
                    {
                        ParseChunkedPrefix(readableBuffer, out consumed, out examined);

                        if (_mode == Mode.Prefix)
                        {
                            return(false);
                        }

                        readableBuffer = readableBuffer.Slice(consumed);
                    }

                    if (_mode == Mode.Extension)
                    {
                        ParseExtension(readableBuffer, out consumed, out examined);

                        if (_mode == Mode.Extension)
                        {
                            return(false);
                        }

                        readableBuffer = readableBuffer.Slice(consumed);
                    }

                    if (_mode == Mode.Data)
                    {
                        ReadChunkedData(readableBuffer, writableBuffer, out consumed, out examined);

                        if (_mode == Mode.Data)
                        {
                            return(false);
                        }

                        readableBuffer = readableBuffer.Slice(consumed);
                    }

                    if (_mode == Mode.Suffix)
                    {
                        ParseChunkedSuffix(readableBuffer, out consumed, out examined);

                        if (_mode == Mode.Suffix)
                        {
                            return(false);
                        }

                        readableBuffer = readableBuffer.Slice(consumed);
                    }
                }

                // Chunks finished, parse trailers
                if (_mode == Mode.Trailer)
                {
                    ParseChunkedTrailer(readableBuffer, out consumed, out examined);

                    if (_mode == Mode.Trailer)
                    {
                        return(false);
                    }

                    readableBuffer = readableBuffer.Slice(consumed);
                }

                // _consumedBytes aren't tracked for trailer headers, since headers have seperate limits.
                if (_mode == Mode.TrailerHeaders)
                {
                    if (_context.TakeMessageHeaders(readableBuffer, out consumed, out examined))
                    {
                        _mode = Mode.Complete;
                    }
                }

                return(_mode == Mode.Complete);
            }
예제 #34
0
 // REVIEW: See if we can use IFormatter here
 public static void WriteUInt32(this WritableBuffer buffer, uint value) => WriteUInt64(buffer, value);