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