public static bool TryGetFrame(ref ReadableBuffer buffer, out ReadableBuffer messageBuffer) { messageBuffer = default(ReadableBuffer); if (buffer.Length < 5) { return(false); } var frameType = buffer.ReadBigEndian <RecordType>(); if (frameType != RecordType.Alert && frameType != RecordType.Application && frameType != RecordType.Handshake) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.decode_error, $"unknown frame type {frameType}"); } var version = buffer.Slice(1).ReadBigEndian <ushort>(); if (version < 0x0300 || version > 0x0400) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.decode_error, $"The frame version was outside the range {version}"); } var length = buffer.Slice(3).ReadBigEndian <ushort>(); if (buffer.Length >= (length + RecordHeaderLength)) { messageBuffer = buffer.Slice(0, length + RecordHeaderLength); buffer = buffer.Slice(length + RecordHeaderLength); return(true); } return(false); }
public static void ReadServerHello(ReadableBuffer readable, IConnectionStateTls13 connectionState) { var original = readable; ushort version, cipherCode; readable = readable.Slice(HandshakeProcessor.HandshakeHeaderSize); readable = readable.SliceBigEndian(out version); //skip random readable = readable.Slice(RandomLength); readable = readable.SliceBigEndian(out cipherCode); connectionState.CipherSuite = connectionState.CryptoProvider.GetCipherSuiteFromCode(cipherCode, connectionState.Version); if (connectionState.CipherSuite == null) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "Could not get a cipher suite during server hello"); } connectionState.StartHandshakeHash(original); readable = BufferExtensions.SliceVector <ushort>(ref readable); ExtensionType ext; readable = readable.SliceBigEndian(out ext); if (ext != ExtensionType.key_share) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "There was no keyshare on the server hello"); } readable = BufferExtensions.SliceVector <ushort>(ref readable); NamedGroup group; readable = readable.SliceBigEndian(out group); if (group != connectionState.KeyShare.NamedGroup) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "The named group didn't match the keyshare during server hello"); } readable = BufferExtensions.SliceVector <ushort>(ref readable); connectionState.KeyShare.SetPeerKey(readable); }
public override RecordState ReadRecord(ref ReadableBuffer buffer, out ReadableBuffer messageBuffer) { messageBuffer = default; if (buffer.Length < _minimumMessageSize) { return(RecordState.Incomplete); } var header = buffer.Slice(0, _minimumMessageSize).ToSpan().Read <RecordHeader>(); if (buffer.Length < header.Length + _minimumMessageSize) { return(RecordState.Incomplete); } _currentRecordType = header.RecordType; if (_connection?.ReadKey == null) { messageBuffer = buffer.Slice(_minimumMessageSize, header.Length); buffer = buffer.Slice(messageBuffer.End); } else { messageBuffer = buffer.Slice(_minimumMessageSize, header.Length); buffer = buffer.Slice(messageBuffer.End); _connection.ReadKey.Decrypt(ref messageBuffer, header.RecordType, header.Version); } return(RecordState.Record); }
protected override void WriteRecords(ref ReadableBuffer buffer, ref WritableBuffer writer, RecordType recordType) { ReadableBuffer append; while (buffer.Length > 0) { append = buffer.Slice(0, Math.Min(_maxMessageSize, buffer.Length)); buffer = buffer.Slice(append.End); var recordHeader = new RecordHeader() { RecordType = recordType, Length = (ushort)append.Length, Version = _recordVersion }; writer.Ensure(_minimumMessageSize); if (_connection?.WriteKey != null) { recordHeader.Length += (ushort)(8 + _connection.WriteKey.Overhead); } writer.Buffer.Span.Write(recordHeader); writer.Advance(_minimumMessageSize); if (_connection?.WriteKey != null) { _connection.WriteKey.Encrypt(ref writer, append, recordType, _recordVersion); } else { writer.Append(append); } } }
public static ReadableBuffer SliceVector <[Primitive] T>(ref ReadableBuffer buffer) where T : struct { uint length = 0; if (typeof(T) == typeof(byte) || typeof(T) == typeof(sbyte)) { length = buffer.ReadBigEndian <byte>(); buffer = buffer.Slice(sizeof(byte)); } else if (typeof(T) == typeof(ushort) || typeof(T) == typeof(short)) { length = buffer.ReadBigEndian <ushort>(); buffer = buffer.Slice(sizeof(ushort)); } else if (typeof(T) == typeof(uint) || typeof(T) == typeof(int)) { length = buffer.ReadBigEndian <uint>(); buffer = buffer.Slice(sizeof(uint)); } else { Internal.ExceptionHelper.ThrowException(new InvalidCastException($"The type {typeof(T)} is not a primitave integer type")); } var returnBuffer = buffer.Slice(0, (int)length); buffer = buffer.Slice(returnBuffer.End); return(returnBuffer); }
public unsafe void Decrypt(ref ReadableBuffer messageBuffer) { var tag = stackalloc byte[_overhead]; messageBuffer.Slice(messageBuffer.Length - _overhead).CopyTo(new Span <byte>(tag, _overhead)); messageBuffer = messageBuffer.Slice(0, messageBuffer.Length - _overhead); ThrowOnError(EVP_CipherInit_ex(_ctx, _cipherType, IntPtr.Zero, (void *)_keyPointer, (void *)_ivPointer, (int)KeyMode.Decryption)); ThrowOnError(EVP_CIPHER_CTX_ctrl(_ctx, EVP_CIPHER_CTRL.EVP_CTRL_GCM_SET_TAG, _overhead, tag)); int outLength; foreach (var b in messageBuffer) { if (b.Length > 0) { GCHandle handle; var ptr = b.GetPointer(out handle); outLength = b.Length; ThrowOnError(EVP_CipherUpdate(_ctx, ptr, ref outLength, ptr, outLength)); if (outLength != b.Length) { throw new InvalidOperationException(); } } } outLength = 0; ThrowOnError(EVP_CipherFinal_ex(_ctx, null, ref outLength)); IncrementSequence(); }
public static string ReadString(ref ReadableBuffer buffer, out bool compressed) { int header = buffer.Peek(); if (header < 0) { ThrowEndOfStreamException(); } compressed = (header & 0x80) != 0; buffer = buffer.Slice(1); int len = checked ((int)ReadUInt64(ref buffer, header, 7)); string result; if (compressed) { result = HuffmanCode.ReadString(buffer.Slice(0, len)); } else { result = buffer.Slice(0, len).GetAsciiString(); } buffer = buffer.Slice(len); return(result); }
private static void RemovePadding(ref ReadableBuffer buffer) { while (buffer.Slice(buffer.Length - 1).Peek() == 0) { buffer = buffer.Slice(0, buffer.Length - 1); } }
static bool FullRequestRb() { ReadableBuffer buffer = ReadableBuffer.Create(s_plaintextTechEmpowerRequestBytes); var parser = new HttpParser(); var request = new Request(); int consumedBytes = 0; ReadCursor examined; ReadCursor consumed = buffer.Start; bool success = true; foreach (var iteration in Benchmark.Iterations) { using (iteration.StartMeasurement()) { for (int i = 0; i < Benchmark.InnerIterationCount; i++) { success = success && parser.ParseRequestLine(request, buffer, out consumed, out examined); success = success && parser.ParseHeaders(request, buffer.Slice(consumed), out consumed, out examined, out consumedBytes); success = success && parser.ParseRequestLine(request, buffer, out consumed, out examined); success = success && parser.ParseHeaders(request, buffer.Slice(consumed), out consumed, out examined, out consumedBytes); success = success && parser.ParseRequestLine(request, buffer, out consumed, out examined); success = success && parser.ParseHeaders(request, buffer.Slice(consumed), out consumed, out examined, out consumedBytes); success = success && parser.ParseRequestLine(request, buffer, out consumed, out examined); success = success && parser.ParseHeaders(request, buffer.Slice(consumed), out consumed, out examined, out consumedBytes); success = success && parser.ParseRequestLine(request, buffer, out consumed, out examined); success = success && parser.ParseHeaders(request, buffer.Slice(consumed), out consumed, out examined, out consumedBytes); } } } return(success); }
public static ReadableBuffer SliceVector24Bit(ref ReadableBuffer buffer) { var length = buffer.ReadBigEndian24bit(); var returnBuffer = buffer.Slice(3, length); buffer = buffer.Slice(returnBuffer.End); return(returnBuffer); }
public unsafe void Decrypt(ref ReadableBuffer messageBuffer) { var tag = stackalloc byte[_overhead]; messageBuffer.Slice(messageBuffer.Length - _overhead).CopyTo(new Span <byte>(tag, _overhead)); messageBuffer = messageBuffer.Slice(0, messageBuffer.Length - _overhead); throw new NotImplementedException(); }
public void DecryptSession(ref ReadableBuffer buffer, IConnectionStateTls13 state) { var nounce = buffer.Slice(0, 12).ToArray(); buffer = buffer.Slice(12); ushort cipherCode, version; buffer = buffer.SliceBigEndian(out cipherCode); buffer = buffer.SliceBigEndian(out version); state.CipherSuite = state.CryptoProvider.GetCipherSuiteFromCode(cipherCode, state.Version); state.KeySchedule = new KeySchedule13(state, state.Listener.KeyScheduleProvider.BufferPool, buffer); }
public static void ReadExtensionListTls(ref ReadableBuffer buffer, IConnectionState connectionState) { var listLength = buffer.ReadBigEndian <ushort>(); ReadableBuffer signatureAlgoBuffer = default(ReadableBuffer); buffer = buffer.Slice(sizeof(ushort)); if (buffer.Length < listLength) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.decode_error, "The extension list is not as long as the header says"); } var currentbuffer = buffer.Slice(0, listLength); buffer = buffer.Slice(currentbuffer.End); while (currentbuffer.Length > 3) { var extensionType = currentbuffer.ReadBigEndian <ExtensionType>(); var extensionLength = currentbuffer.Slice(sizeof(ExtensionType)).ReadBigEndian <ushort>(); currentbuffer = currentbuffer.Slice(sizeof(ExtensionType) + sizeof(ushort)); if (currentbuffer.Length < extensionLength) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.decode_error, $"The extension of type {extensionType} is too long for the remaining buffer"); } var extensionBuffer = currentbuffer.Slice(0, extensionLength); currentbuffer = currentbuffer.Slice(extensionLength); switch (extensionType) { case ExtensionType.server_name: ReadServerName(extensionBuffer, connectionState); break; //case ExtensionType.signature_algorithms: // signatureAlgoBuffer = extensionBuffer; // break; case ExtensionType.supported_groups: if (connectionState.CipherSuite.ExchangeType == KeyExchange.KeyExchangeType.Ecdhe) { connectionState.CryptoProvider.GetKeyshareFromNamedGroups(extensionBuffer); } break; case ExtensionType.renegotiation_info: ReadRenegotiationInfo(extensionBuffer, connectionState); break; } } //Wait until the end to check the signature, here we select the //certificate and this could depend on the server name indication //as well as the trusted CA roots. if (signatureAlgoBuffer.Length != 0) { ReadSignatureScheme(signatureAlgoBuffer, connectionState); } }
private void ParseExtension(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) { // Chunk-extensions not currently parsed // Just drain the data consumed = buffer.Start; examined = buffer.Start; do { ReadCursor extensionCursor; if (ReadCursorOperations.Seek(buffer.Start, buffer.End, out extensionCursor, ByteCR) == -1) { // End marker not found yet consumed = buffer.End; examined = buffer.End; AddAndCheckConsumedBytes(buffer.Length); return; } ; var charsToByteCRExclusive = buffer.Slice(0, extensionCursor).Length; var sufixBuffer = buffer.Slice(extensionCursor); if (sufixBuffer.Length < 2) { consumed = extensionCursor; examined = buffer.End; AddAndCheckConsumedBytes(charsToByteCRExclusive); return; } sufixBuffer = sufixBuffer.Slice(0, 2); var sufixSpan = sufixBuffer.ToSpan(); if (sufixSpan[1] == '\n') { // We consumed the \r\n at the end of the extension, so switch modes. _mode = _inputLength > 0 ? Mode.Data : Mode.Trailer; consumed = sufixBuffer.End; examined = sufixBuffer.End; AddAndCheckConsumedBytes(charsToByteCRExclusive + 2); } else { // Don't consume suffixSpan[1] in case it is also a \r. buffer = buffer.Slice(charsToByteCRExclusive + 1); consumed = extensionCursor; AddAndCheckConsumedBytes(charsToByteCRExclusive + 1); } } while (_mode == Mode.Extension); }
public static ulong ReadUInt64(ref ReadableBuffer buffer, int firstByte, int n) { if (n < 0 || n > 8) { throw new ArgumentOutOfRangeException(nameof(n)); } int mask = ~(~0 << n); int prefix = firstByte & mask; if (prefix != mask) { return((ulong)prefix); // short value encoded directly } ulong value = 0; int shift = 0, nextByte; for (int i = 0; i < 9; i++) { nextByte = buffer.Peek(); if (nextByte < 0) { ThrowEndOfStreamException(); } buffer = buffer.Slice(1); value |= ((ulong)nextByte & 0x7F) << shift; if ((nextByte & 0x80) == 0) { // lack of continuation bit return(value + (ulong)mask); } shift += 7; } switch (nextByte = buffer.Peek()) { case 0: case 1: // note: lack of continuation bit (or anything else) buffer = buffer.Slice(1); value |= ((ulong)nextByte & 0x7F) << shift; return(value + (ulong)mask); default: if (nextByte < 0) { ThrowEndOfStreamException(); } // 7*9=63, so max 9 groups of 7 bits plus either 0 or 1; // after that: we've overflown throw new OverflowException(); } }
public static bool HandleMessage(ref ReadableBuffer reader) { if (reader.Length < 4) { return(false); } var messageLength = reader.ReadBigEndian <ushort>(); if (reader.Length < (messageLength + 4)) { return(false); } messageLength = reader.ReadBigEndian <ushort>(); reader = reader.Slice(2); var messageType = (MessageTypes)reader.ReadBigEndian <ushort>(); var messageBuff = reader.Slice(2, messageLength); switch (messageType) { case MessageTypes.LoginAck: try { var md = new LoginResponse(ref messageBuff); ///Fire off to low priority queue because it's not very important } catch (Exception ex) { errorCount++; Console.WriteLine("Number of errors" + errorCount); } break; case MessageTypes.SomeDataUpdate: try { var md = new SomeDataUpdate(ref messageBuff); ///Fire off to very important queue as its realtime } catch (Exception ex) { errorCount++; Console.WriteLine("Number of errors" + errorCount); } break; } return(true); }
private unsafe void TestIndexOfWorksForAllLocations(ref ReadableBuffer readBuffer, byte emptyValue) { byte huntValue = (byte)~emptyValue; // we're going to fully index the final locations of the buffer, so that we // can mutate etc in constant time var addresses = BuildPointerIndex(ref readBuffer); // check it isn't there to start with ReadableBuffer slice; ReadCursor cursor; var found = readBuffer.TrySliceTo(huntValue, out slice, out cursor); Assert.False(found); // correctness test all values for (int i = 0; i < readBuffer.Length; i++) { *addresses[i] = huntValue; found = readBuffer.TrySliceTo(huntValue, out slice, out cursor); *addresses[i] = emptyValue; Assert.True(found); var remaining = readBuffer.Slice(cursor); void *pointer; Assert.True(remaining.First.TryGetPointer(out pointer)); Assert.True((byte *)pointer == addresses[i]); } }
// TODO: not sure how to do this; basically I want to lease a writable, expandable area // for a duration, and be able to access it for reading, and release internal void AddBacklog(ref ReadableBuffer buffer, ref WebSocketsFrame frame) { var length = frame.PayloadLength; if (length == 0) { return; // nothing to store! } var slicedBuffer = buffer.Slice(0, length); // unscramble the data if (frame.Mask != 0) { WebSocketsFrame.ApplyMask(ref slicedBuffer, frame.Mask); } var backlog = this.backlog; if (backlog == null) { var newBacklog = new List <ReadableBuffer>(); backlog = Interlocked.CompareExchange(ref this.backlog, newBacklog, null) ?? newBacklog; } backlog.Add(slicedBuffer.Preserve()); }
/// <summary> /// Trim whitespace starting from the specified <see cref="ReadableBuffer"/>. /// </summary> /// <param name="buffer">The <see cref="ReadableBuffer"/> to trim</param> /// <returns>A new <see cref="ReadableBuffer"/> with the starting whitespace trimmed.</returns> public static ReadableBuffer TrimEnd(this ReadableBuffer buffer) { var end = -1; var i = 0; foreach (var memory in buffer) { var span = memory.Span; for (int j = 0; j < span.Length; j++) { i++; if (IsWhitespaceChar(span[j])) { if (end == -1) { end = i; } } else { end = -1; } } } return(end != -1 ? buffer.Slice(0, end - 1) : buffer); }
public static bool TryParse(ReadableBuffer payload, out WebSocketCloseResult result, out ushort?actualCloseCode) { if (payload.Length == 0) { // Empty payload is OK actualCloseCode = null; result = new WebSocketCloseResult(WebSocketCloseStatus.Empty, string.Empty); return(true); } else if (payload.Length < 2) { actualCloseCode = null; result = default(WebSocketCloseResult); return(false); } else { var status = payload.ReadBigEndian <ushort>(); actualCloseCode = status; var description = string.Empty; payload = payload.Slice(2); if (payload.Length > 0) { description = payload.GetUtf8String(); } result = new WebSocketCloseResult((WebSocketCloseStatus)status, description); return(true); } }
public static int ReadBigEndian24bit(this ReadableBuffer buffer) { uint contentSize = buffer.ReadBigEndian <ushort>(); contentSize = (contentSize << 8) + buffer.Slice(2).ReadBigEndian <byte>(); return((int)contentSize); }
// the `unsafe` here is so that in the "multiple spans, header crosses spans", we can use stackalloc to // collate the header bytes in one place, and pass that down for analysis internal unsafe static bool TryReadFrameHeader(ref ReadableBuffer buffer, out WebSocketsFrame frame) { int bytesAvailable = buffer.Length; if (bytesAvailable < 2) { frame = default(WebSocketsFrame); return(false); // can't read that; frame takes at minimum two bytes } var firstSpan = buffer.First; if (buffer.IsSingleSpan || firstSpan.Length >= MaxHeaderLength) { return(TryReadFrameHeader(firstSpan.Length, firstSpan.Span, ref buffer, out frame)); } else { // header is at most 14 bytes; can afford the stack for that - but note that if we aim for 16 bytes instead, // we will usually benefit from using 2 qword copies byte *header = stackalloc byte[16]; var slice = buffer.Slice(0, Math.Min(16, bytesAvailable)); var headerSpan = new Span <byte>(header, slice.Length); slice.CopyTo(headerSpan); // note that we're using the "slice" above to preview the header, but we // still want to pass the *original* buffer down below, so that we can // check the overall length (payload etc) return(TryReadFrameHeader(slice.Length, headerSpan, ref buffer, out frame)); } }
private void ParseChunkedTrailer(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) { consumed = buffer.Start; examined = buffer.Start; if (buffer.Length < 2) { examined = buffer.End; return; } var trailerBuffer = buffer.Slice(0, 2); var trailerSpan = trailerBuffer.ToSpan(); if (trailerSpan[0] == '\r' && trailerSpan[1] == '\n') { consumed = trailerBuffer.End; examined = trailerBuffer.End; AddAndCheckConsumedBytes(2); _mode = Mode.Complete; } else { _mode = Mode.TrailerHeaders; } }
private void ParseChunkedSuffix(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) { consumed = buffer.Start; examined = buffer.Start; if (buffer.Length < 2) { examined = buffer.End; return; } var suffixBuffer = buffer.Slice(0, 2); var suffixSpan = suffixBuffer.ToSpan(); if (suffixSpan[0] == '\r' && suffixSpan[1] == '\n') { consumed = suffixBuffer.End; examined = suffixBuffer.End; AddAndCheckConsumedBytes(2); _mode = Mode.Prefix; } else { _context.ThrowRequestRejected(RequestRejectionReason.BadChunkSuffix); } }
public static void ReadCertificates(ReadableBuffer buffer, SecurePipelineListener listener) { buffer = buffer.Slice(HandshakeProcessor.HandshakeHeaderSize); //ignore context BufferExtensions.SliceVector <byte>(ref buffer); //slice the list buffer = BufferExtensions.SliceVector24Bit(ref buffer); X509Certificate2Collection collection; if (listener.CertificateValidation == null) { collection = null; } else { collection = new X509Certificate2Collection(); } while (buffer.Length > 0) { var cert = BufferExtensions.SliceVector24Bit(ref buffer); var ext = BufferExtensions.SliceVector <ushort>(ref buffer); if (cert.Length > 0 && collection != null) { var x509 = new X509Certificate2(cert.ToArray()); collection.Add(x509); } } if (collection != null) { if (!listener.CertificateValidation(collection)) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.bad_certificate, "Failed to verify the certificate chain via the callback"); } } }
private static ReadCursor ProcessHeader(HttpContext context, ref ReadableBuffer currentSlice) { if (!currentSlice.TrySliceTo(HttpConsts.EndOfLine, out ReadableBuffer headerLine, out ReadCursor cursor)) { headerLine = currentSlice; currentSlice = currentSlice.Slice(currentSlice.Length); }
internal unsafe static bool TryReadFrameHeader(ref ReadableBuffer buffer, out WebSocketsFrame frame) { int bytesAvailable = buffer.Length; if (bytesAvailable < 2) { frame = default(WebSocketsFrame); return(false); // can't read that; frame takes at minimum two bytes } var span = buffer.FirstSpan; if (buffer.IsSingleSpan || span.Length >= MaxHeaderLength) { return(TryReadFrameHeader(span.Length, (byte *)span.BufferPtr, ref buffer, out frame)); } else { // header is at most 14 bytes; can afford the stack for that - but note that if we aim for 16 bytes instead, // we will usually benefit from using 2 qword copies (handled internally); very very small messages ('a') might // have to use the slower version, but... meh byte *header = stackalloc byte[16]; var slice = buffer.Slice(0, Math.Min(16, bytesAvailable)); slice.CopyTo(header, slice.Length); // note that we're using the "slice" above to preview the header, but we // still want to pass the original buffer down below, so that we can // check the overall length (payload etc) return(TryReadFrameHeader(slice.Length, header, ref buffer, out frame)); } }
private unsafe void TestIndexOfWorksForAllLocations(ref ReadableBuffer readBuffer, byte emptyValue) { byte huntValue = (byte)~emptyValue; Vector <byte> huntVector = new Vector <byte>(huntValue); // we're going to fully index the final locations of the buffer, so that we // can mutate etc in constant time var addresses = BuildPointerIndex(ref readBuffer); // check it isn't there to start with var found = readBuffer.IndexOf(ref huntVector); Assert.True(found == ReadCursor.NotFound); // correctness test all values for (int i = 0; i < readBuffer.Length; i++) { *addresses[i] = huntValue; found = readBuffer.IndexOf(ref huntVector); *addresses[i] = emptyValue; Assert.True(found != ReadCursor.NotFound); var slice = readBuffer.Slice(found); Assert.True(slice.FirstSpan.UnsafePointer == addresses[i]); } }
public bool TakeMessageHeaders(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) { // Make sure the buffer is limited bool overLength = false; if (buffer.Length >= _remainingRequestHeadersBytesAllowed) { buffer = buffer.Slice(buffer.Start, _remainingRequestHeadersBytesAllowed); // If we sliced it means the current buffer bigger than what we're // allowed to look at overLength = true; } var result = _parser.ParseHeaders(new Http1ParsingHandler(this), buffer, out consumed, out examined, out var consumedBytes); _remainingRequestHeadersBytesAllowed -= consumedBytes; if (!result && overLength) { ThrowRequestRejected(RequestRejectionReason.HeadersExceedMaxTotalSize); } if (result) { TimeoutControl.CancelTimeout(); } return(result); }
public void RegisterSessionTicket(ReadableBuffer buffer) { //slice off the head first buffer = buffer.Slice(HandshakeProcessor.HandshakeHeaderSize); uint ticketAge, ageRandom; buffer = buffer.SliceBigEndian(out ticketAge); buffer = buffer.SliceBigEndian(out ageRandom); var ticketData = BufferExtensions.SliceVector <ushort>(ref buffer); if (buffer.Length > 0) { //Extensions buffer = BufferExtensions.SliceVector <ushort>(ref buffer); if (buffer.Length > 0) { //seems we can resume data ExtensionType type; buffer = buffer.SliceBigEndian(out type); if (type != ExtensionType.ticket_early_data_info) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "Early session ticket received had an invalid extension"); } } } }
private unsafe void TestIndexOfWorksForAllLocations(ref ReadableBuffer readBuffer, byte emptyValue) { byte huntValue = (byte)~emptyValue; // we're going to fully index the final locations of the buffer, so that we // can mutate etc in constant time var addresses = BuildPointerIndex(ref readBuffer); // check it isn't there to start with ReadableBuffer slice; ReadCursor cursor; var found = readBuffer.TrySliceTo(huntValue, out slice, out cursor); Assert.False(found); // correctness test all values for (int i = 0; i < readBuffer.Length; i++) { *addresses[i] = huntValue; found = readBuffer.TrySliceTo(huntValue, out slice, out cursor); *addresses[i] = emptyValue; Assert.True(found); var remaining = readBuffer.Slice(cursor); void* pointer; Assert.True(remaining.First.TryGetPointer(out pointer)); Assert.True((byte*)pointer == addresses[i]); } }
public ParseResult ParseRequest(ref ReadableBuffer buffer) { if (_state == ParsingState.StartLine) { // Find \n ReadCursor delim; ReadableBuffer startLine; if (!buffer.TrySliceTo((byte)'\r', (byte)'\n', out startLine, out delim)) { return ParseResult.Incomplete; } // Move the buffer to the rest buffer = buffer.Slice(delim).Slice(2); ReadableBuffer method; if (!startLine.TrySliceTo((byte)' ', out method, out delim)) { return ParseResult.BadRequest; } _method = method.Preserve(); // Skip ' ' startLine = startLine.Slice(delim).Slice(1); ReadableBuffer path; if (!startLine.TrySliceTo((byte)' ', out path, out delim)) { return ParseResult.BadRequest; } _path = path.Preserve(); // Skip ' ' startLine = startLine.Slice(delim).Slice(1); var httpVersion = startLine; if (httpVersion.IsEmpty) { return ParseResult.BadRequest; } _httpVersion = httpVersion.Preserve(); _state = ParsingState.Headers; } // Parse headers // key: value\r\n while (!buffer.IsEmpty) { var headerName = default(ReadableBuffer); var headerValue = default(ReadableBuffer); // End of the header // \n ReadCursor delim; ReadableBuffer headerPair; if (!buffer.TrySliceTo((byte)'\r', (byte)'\n', out headerPair, out delim)) { return ParseResult.Incomplete; } buffer = buffer.Slice(delim).Slice(2); // End of headers if (headerPair.IsEmpty) { return ParseResult.Complete; } // : if (!headerPair.TrySliceTo((byte)':', out headerName, out delim)) { return ParseResult.BadRequest; } headerName = headerName.TrimStart(); headerPair = headerPair.Slice(delim).Slice(1); headerValue = headerPair.TrimStart(); RequestHeaders.SetHeader(ref headerName, ref headerValue); } return ParseResult.Incomplete; }
private unsafe void TestValue(ref ReadableBuffer readBuffer, ulong value) { void* pointer; Assert.True(readBuffer.First.TryGetPointer(out pointer)); var ptr = (byte*)pointer; string s = value.ToString(CultureInfo.InvariantCulture); int written; fixed (char* c = s) { written = Encoding.ASCII.GetBytes(c, s.Length, ptr, readBuffer.Length); } var slice = readBuffer.Slice(0, written); Assert.Equal(value, slice.GetUInt64()); }