示例#1
0
        public void SkipAdvancesBuffer()
        {
            // Arrange
            var baton = new Baton {Buffer = "xxhello world".ToArraySegment()};
            baton.Skip(2);

            // Act
            baton.Skip(5);

            // Assert
            Assert.Equal(6, baton.Buffer.Count);
            Assert.Equal(" world", baton.Buffer.ToString(Encoding.Default));
        }
示例#2
0
        public void TakeAdvancesBufferAndReturnsTakenSegment()
        {
            // Arrange
            var baton = new Baton { Buffer = "xxhello world".ToArraySegment() };
            baton.Skip(2);

            // Act
            var taken = baton.Take(5);

            // Assert
            Assert.Equal(6, baton.Buffer.Count);
            Assert.Equal(" world", baton.Buffer.ToString(Encoding.Default));
            Assert.Equal(5, taken.Count);
            Assert.Equal("hello", taken.ToString(Encoding.Default));
        }
示例#3
0
        public unsafe override bool TakeMessageHeader(Baton baton, out bool endOfHeaders)
        {
            var remaining = baton.Buffer;
            endOfHeaders = false;
            if (remaining.Count < 2) return false;
            var ch0 = remaining.Array[remaining.Offset];
            var ch1 = remaining.Array[remaining.Offset + 1];
            if (ch0 == '\r' && ch1 == '\n')
            {
                endOfHeaders = true;
                baton.Skip(2);
                return true;
            }

            if (remaining.Count < 3) return false;
            var wrappedHeaders = false;
            var colonIndex = -1;
            var valueStartIndex = -1;
            var valueEndIndex = -1;
            var indexEnd = remaining.Count - 2;
            fixed (byte* pch = remaining.Array)
            {
                var scan = pch + remaining.Offset + 2;
                for (var index = 0; index != indexEnd; ++index)
                {
                    var ch2 = *scan++;
                    if (ch0 == '\r' &&
                        ch1 == '\n' &&
                        ch2 != ' ' &&
                        ch2 != '\t')
                    {
                        var name = Encoding.Default.GetString(remaining.Array, remaining.Offset, colonIndex);
                        var value = "";
                        if (valueEndIndex != -1)
                            value = Encoding.Default.GetString(remaining.Array, remaining.Offset + valueStartIndex, valueEndIndex - valueStartIndex);
                        if (wrappedHeaders)
                            value = value.Replace("\r\n", " ");
                        AddRequestHeader(name, value);
                        baton.Skip(index + 2);
                        return true;
                    }
                    if (colonIndex == -1 && ch0 == ':')
                    {
                        colonIndex = index;
                    }
                    else if (colonIndex != -1 &&
                        ch0 != ' ' &&
                        ch0 != '\t' &&
                        ch0 != '\r' &&
                        ch0 != '\n')
                    {
                        if (valueStartIndex == -1)
                            valueStartIndex = index;
                        valueEndIndex = index + 1;
                    }
                    else if (!wrappedHeaders &&
                        ch0 == '\r' &&
                        ch1 == '\n' &&
                        (ch2 == ' ' ||
                        ch2 == '\t'))
                    {
                        wrappedHeaders = true;
                    }

                    ch0 = ch1;
                    ch1 = ch2;
                }
            }
            return false;
        }
示例#4
0
            private static bool TakeChunkedLine(Baton baton, ref int chunkSizeOut)
            {
                var remaining = baton.Buffer;
                if (remaining.Count < 2) return false;
                var ch0 = remaining.Array[remaining.Offset];
                var chunkSize = 0;
                var mode = 0;
                for (var index = 0; index != remaining.Count - 1; ++index)
                {
                    var ch1 = remaining.Array[remaining.Offset + index + 1];

                    if (mode == 0)
                    {
                        if (ch0 >= '0' && ch0 <= '9')
                        {
                            chunkSize = chunkSize * 0x10 + (ch0 - '0');
                        }
                        else if (ch0 >= 'A' && ch0 <= 'F')
                        {
                            chunkSize = chunkSize * 0x10 + (ch0 - ('A' - 10));
                        }
                        else if (ch0 >= 'a' && ch0 <= 'f')
                        {
                            chunkSize = chunkSize * 0x10 + (ch0 - ('a' - 10));
                        }
                        else
                        {
                            throw new NotImplementedException("INVALID REQUEST FORMAT");
                        }
                        mode = 1;
                    }
                    else if (mode == 1)
                    {
                        if (ch0 >= '0' && ch0 <= '9')
                        {
                            chunkSize = chunkSize * 0x10 + (ch0 - '0');
                        }
                        else if (ch0 >= 'A' && ch0 <= 'F')
                        {
                            chunkSize = chunkSize * 0x10 + (ch0 - ('A' - 10));
                        }
                        else if (ch0 >= 'a' && ch0 <= 'f')
                        {
                            chunkSize = chunkSize * 0x10 + (ch0 - ('a' - 10));
                        }
                        else if (ch0 == ';')
                        {
                            mode = 2;
                        }
                        else if (ch0 == '\r' && ch1 == '\n')
                        {
                            baton.Skip(index + 2);
                            chunkSizeOut = chunkSize;
                            return true;
                        }
                        else
                        {
                            throw new NotImplementedException("INVALID REQUEST FORMAT");
                        }
                    }
                    else if (mode == 2)
                    {
                        if (ch0 == '\r' && ch1 == '\n')
                        {
                            baton.Skip(index + 2);
                            chunkSizeOut = chunkSize;
                            return true;
                        }
                        else
                        {
                            // chunk-extensions not currently parsed
                        }
                    }

                    ch0 = ch1;
                }
                return false;
            }
示例#5
0
        private bool TakeStartLine(Baton baton)
        {
            var remaining = baton.Buffer;
            if (remaining.Count < 2) return false;
            var firstSpace = -1;
            var secondSpace = -1;
            var questionMark = -1;
            var ch0 = remaining.Array[remaining.Offset];
            for (var index = 0; index != remaining.Count - 1; ++index)
            {
                var ch1 = remaining.Array[remaining.Offset + index + 1];
                if (ch0 == '\r' && ch1 == '\n')
                {
                    if (secondSpace == -1)
                    {
                        throw new InvalidOperationException("INVALID REQUEST FORMAT");
                    }
                    _method = GetString(remaining, 0, firstSpace);
                    _requestUri = GetString(remaining, firstSpace + 1, secondSpace);
                    if (questionMark == -1)
                    {
                        _path = _requestUri;
                        _queryString = string.Empty;
                    }
                    else
                    {
                        _path = GetString(remaining, firstSpace + 1, questionMark);
                        _queryString = GetString(remaining, questionMark + 1, secondSpace);
                    }
                    _httpVersion = GetString(remaining, secondSpace + 1, index);
                    baton.Skip(index + 2);
                    return true;
                }

                if (ch0 == ' ' && firstSpace == -1)
                {
                    firstSpace = index;
                }
                else if (ch0 == ' ' && firstSpace != -1 && secondSpace == -1)
                {
                    secondSpace = index;
                }
                else if (ch0 == '?' && firstSpace != -1 && questionMark == -1 && secondSpace == -1)
                {
                    questionMark = index;
                }
                ch0 = ch1;
            }
            return false;
        }