예제 #1
0
        /// <summary>
        ///     Determines whether the stream starts with the given string.
        /// </summary>
        /// <returns>
        ///     1: when starts with the given string, 0: when valid HTTP method, -1: otherwise
        /// </returns>
        private static async ValueTask <int> startsWith(IPeekStream httpReader, IBufferPool bufferPool, string expectedStart, CancellationToken cancellationToken = default)
        {
            const int lengthToCheck = 10;

            if (bufferPool.BufferSize < lengthToCheck)
            {
                throw new Exception($"Buffer is too small. Minimum size is {lengthToCheck} bytes");
            }

            byte[] buffer = bufferPool.GetBuffer(bufferPool.BufferSize);
            try
            {
                bool isExpected = true;
                int  i          = 0;
                while (i < lengthToCheck)
                {
                    int peeked = await httpReader.PeekBytesAsync(buffer, i, i, lengthToCheck - i, cancellationToken);

                    if (peeked <= 0)
                    {
                        return(-1);
                    }

                    peeked += i;

                    while (i < peeked)
                    {
                        int b = buffer[i];

                        if (b == ' ' && i > 2)
                        {
                            return(isExpected ? 1 : 0);
                        }
                        else
                        {
                            char ch = (char)b;
                            if (ch < 'A' || ch > 'z' || (ch > 'Z' && ch < 'a')) // ASCII letter
                            {
                                return(-1);
                            }
                            else if (i >= expectedStart.Length || ch != expectedStart[i])
                            {
                                isExpected = false;
                            }
                        }

                        i++;
                    }
                }

                // only letters
                return(0);
            }
            finally
            {
                bufferPool.ReturnBuffer(buffer);
            }
        }
예제 #2
0
        /// <summary>
        ///     Gets the HTTP method from the stream.
        /// </summary>
        public static async ValueTask <KnownMethod> GetMethod(IPeekStream httpReader, IBufferPool bufferPool, CancellationToken cancellationToken = default)
        {
            const int lengthToCheck = 20;

            if (bufferPool.BufferSize < lengthToCheck)
            {
                throw new Exception($"Buffer is too small. Minimum size is {lengthToCheck} bytes");
            }

            byte[] buffer = bufferPool.GetBuffer(bufferPool.BufferSize);
            try
            {
                int i = 0;
                while (i < lengthToCheck)
                {
                    int peeked = await httpReader.PeekBytesAsync(buffer, i, i, lengthToCheck - i, cancellationToken);

                    if (peeked <= 0)
                    {
                        return(KnownMethod.Invalid);
                    }

                    peeked += i;

                    while (i < peeked)
                    {
                        int b = buffer[i];

                        if (b == ' ' && i > 2)
                        {
                            return(getKnownMethod(buffer.AsSpan(0, i)));
                        }

                        char ch = (char)b;
                        if ((ch < 'A' || ch > 'z' || (ch > 'Z' && ch < 'a')) && (ch != '-')) // ASCII letter
                        {
                            return(KnownMethod.Invalid);
                        }

                        i++;
                    }
                }

                // only letters, but no space (or shorter than 3 characters)
                return(KnownMethod.Invalid);
            }
            finally
            {
                bufferPool.ReturnBuffer(buffer);
            }
        }