public void SetHeader(ref ReadableBuffer key, ref ReadableBuffer value) { string headerKey = GetHeaderKey(ref key); _headers[headerKey] = new HeaderValue { Raw = value.Preserve() }; }
private string GetHeaderKey(ref ReadableBuffer key) { // Uppercase the things foreach (var memory in key) { var data = memory.Span; for (int i = 0; i < memory.Length; i++) { var mask = IsAlpha(data[i]) ? 0xdf : 0xff; data[i] = (byte)(data[i] & mask); } } if (EqualsIgnoreCase(ref key, AcceptBytes)) { return "Accept"; } if (EqualsIgnoreCase(ref key, AcceptEncodingBytes)) { return "Accept-Encoding"; } if (EqualsIgnoreCase(ref key, AcceptLanguageBytes)) { return "Accept-Language"; } if (EqualsIgnoreCase(ref key, HostBytes)) { return "Host"; } if (EqualsIgnoreCase(ref key, UserAgentBytes)) { return "User-Agent"; } if (EqualsIgnoreCase(ref key, CacheControlBytes)) { return "Cache-Control"; } if (EqualsIgnoreCase(ref key, ConnectionBytes)) { return "Connection"; } if (EqualsIgnoreCase(ref key, UpgradeInsecureRequests)) { return "Upgrade-Insecure-Requests"; } return key.GetAsciiString(); }
public bool TryParse(ref ReadableBuffer buffer) { if (buffer.IsEmpty || !_contentLength.HasValue) { return true; } while (!buffer.IsEmpty && _contentLength > 0) { var next = buffer; ReadCursor delim; ReadableBuffer key; if (!next.TrySliceTo((byte)'=', out key, out delim)) { break; } next = next.Slice(delim).Slice(1); ReadableBuffer value; if (next.TrySliceTo((byte)'&', out value, out delim)) { next = next.Slice(delim).Slice(1); } else { var remaining = _contentLength - buffer.Length; if (remaining == 0) { value = next; next = next.Slice(next.End); } else { break; } } // TODO: Combine multi value keys _data[key.GetUtf8String()] = value.GetUtf8String(); _contentLength -= (buffer.Length - next.Length); buffer = next; } return _contentLength == 0; }
public ReadableBufferReader(ReadableBuffer buffer) { _end = false; _index = 0; _overallIndex = 0; _enumerator = buffer.GetEnumerator(); _currentMemory = default(Span<byte>); while (_enumerator.MoveNext()) { if (!_enumerator.Current.IsEmpty) { _currentMemory = _enumerator.Current.Span; return; } } _end = true; }
private async static void Echo(IChannel channel) { try { while (true) { ReadableBuffer request = await channel.Input.ReadAsync(); if (request.IsEmpty && channel.Input.Reading.IsCompleted) { channel.Input.Advance(request.End); break; } int len = request.Length; var response = channel.Output.Alloc(); response.Append(ref request); await response.FlushAsync(); channel.Input.Advance(request.End); } channel.Input.Complete(); channel.Output.Complete(); } catch (Exception ex) { if (!(channel.Input?.Reading?.IsCompleted ?? true)) { channel.Input.Complete(ex); } if (!(channel.Output?.Writing?.IsCompleted ?? true)) { channel.Output.Complete(ex); } } finally { channel?.Dispose(); } }
private async Task ProcessSends() { while (true) { await _output; var buffer = _output.BeginRead(); if (buffer.IsEmpty && _output.Completion.IsCompleted) { break; } var enumerator = buffer.GetEnumerator(); if (enumerator.MoveNext()) { var current = enumerator.Current; while (enumerator.MoveNext()) { var next = enumerator.Current; await SendAsync(current, endOfMessage : false); current = next; } await PreviousSendingComplete; _sendingBuffer = buffer.Clone(); await SendAsync(current, endOfMessage : true); } _output.EndRead(buffer); } _output.CompleteReading(); }
private void OnAccept(Tcp client, ReadableBuffer data) { if (data.Count == 0) { log($"server OnAccept: data count is 0"); return; } ////log($"server read {data.Count}"); Interlocked.Increment(ref this.receiveCount); // Echo back var buffer = new byte[data.Count]; data.ReadBytes(buffer, buffer.Length); data.Dispose(); var writableBuffer = WritableBuffer.From(buffer); client.QueueWriteStream( writableBuffer, (streamHandle, exception) => { writableBuffer.Dispose(); if (exception != null) { log($"server write error: {exception.Message}"); streamHandle.CloseHandle(h => h.Dispose()); } else { client.OnRead( this.OnAccept, (_h, _e) => { log($"read error {_e.Message}"); }); } }); ////log($"server wrote {buffer.Length}"); }
public void ParseRequest(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) { consumed = buffer.Start; examined = buffer.End; switch (_requestProcessingStatus) { case RequestProcessingStatus.RequestPending: if (buffer.IsEmpty) { break; } TimeoutControl.ResetTimeout(_requestHeadersTimeoutTicks, TimeoutAction.SendTimeoutResponse); _requestProcessingStatus = RequestProcessingStatus.ParsingRequestLine; goto case RequestProcessingStatus.ParsingRequestLine; case RequestProcessingStatus.ParsingRequestLine: if (TakeStartLine(buffer, out consumed, out examined)) { buffer = buffer.Slice(consumed, buffer.End); _requestProcessingStatus = RequestProcessingStatus.ParsingHeaders; goto case RequestProcessingStatus.ParsingHeaders; } else { break; } case RequestProcessingStatus.ParsingHeaders: if (TakeMessageHeaders(buffer, out consumed, out examined)) { _requestProcessingStatus = RequestProcessingStatus.AppStarted; } break; } }
public void CanUseOwnedBufferBasedReadableBuffers() { var data = Encoding.ASCII.GetBytes("***abc|def|ghijk****"); // note sthe padding here - verifying that it is omitted correctly OwnedBuffer <byte> owned = data; var buffer = ReadableBuffer.Create(owned, 3, data.Length - 7); Assert.Equal(13, buffer.Length); var split = buffer.Split((byte)'|'); Assert.Equal(3, split.Count()); using (var iter = split.GetEnumerator()) { Assert.True(iter.MoveNext()); var current = iter.Current; Assert.Equal("abc", current.GetAsciiString()); using (var preserved = iter.Current.Preserve()) { Assert.Equal("abc", preserved.Buffer.GetAsciiString()); } Assert.True(iter.MoveNext()); current = iter.Current; Assert.Equal("def", current.GetAsciiString()); using (var preserved = iter.Current.Preserve()) { Assert.Equal("def", preserved.Buffer.GetAsciiString()); } Assert.True(iter.MoveNext()); current = iter.Current; Assert.Equal("ghijk", current.GetAsciiString()); using (var preserved = iter.Current.Preserve()) { Assert.Equal("ghijk", preserved.Buffer.GetAsciiString()); } Assert.False(iter.MoveNext()); } }
private unsafe void TestIndexOfWorksForAllLocations(ref ReadableBuffer readBuffer, byte emptyValue) { byte huntValue = (byte)~emptyValue; var handles = new List <BufferHandle>(); // 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, handles); // 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); var handle = remaining.First.Retain(pin: true); Assert.True(handle.PinnedPointer != null); Assert.True((byte *)handle.PinnedPointer == addresses[i]); handle.Dispose(); } // free up memory handles foreach (var handle in handles) { handle.Dispose(); } handles.Clear(); }
void OnReceive(Udp udp, IDatagramReadCompletion completion) { var error = completion.Error as OperationException; if (error != null && error.ErrorCode == ErrorCode.ECANCELED) // UV_ECANCELED { return; } ReadableBuffer data = completion.Data; string message = data.ReadString(Encoding.UTF8); if (!string.IsNullOrEmpty(message) && message != ExpectedMessage) { Console.WriteLine( $"Udp pummel {this.numberOfSenders}v{this.numberOfReceivers} failed, wrong message '{message}' received."); } this.receiveCount++; }
void OnReceive(Udp udp, IDatagramReadCompletion completion) { if (completion.Error != null || completion.RemoteEndPoint == null) { return; } ReadableBuffer buffer = completion.Data; string message = buffer.ReadString(Encoding.UTF8); if (message == "PING" || message == "PANG") { this.serverReceiveCount++; } if (this.serverReceiveCount == 2) { udp.CloseHandle(this.OnClose); } }
private static bool IsCaseInsensitiveAsciiMatch(ReadableBuffer bufferUnknownCase, string valueLowerCase) { if (bufferUnknownCase.Length != valueLowerCase.Length) { return(false); } int charIndex = 0; foreach (var memory in bufferUnknownCase) { var span = memory.Span; for (int spanIndex = 0; spanIndex < span.Length; spanIndex++) { char x = (char)span[spanIndex], y = valueLowerCase[charIndex++]; if (x != y && char.ToLowerInvariant(x) != y) { return(false); } } } return(true); }
public async Task TakeTraversesSegments() { using (var factory = new PipeFactory()) { var readerWriter = factory.Create(); var w = readerWriter.Writer.Alloc(); w.Append(ReadableBuffer.Create(new byte[] { 1 }, 0, 1)); w.Append(ReadableBuffer.Create(new byte[] { 2 }, 0, 1)); w.Append(ReadableBuffer.Create(new byte[] { 3 }, 0, 1)); await w.FlushAsync(); var result = await readerWriter.Reader.ReadAsync(); var buffer = result.Buffer; var reader = new ReadableBufferReader(buffer); Assert.Equal(1, reader.Take()); Assert.Equal(2, reader.Take()); Assert.Equal(3, reader.Take()); Assert.Equal(-1, reader.Take()); } }
private void ParseHttpRequest(ReadableBuffer inputBuffer, out ReadCursor consumed, out ReadCursor examined) { consumed = inputBuffer.Start; examined = inputBuffer.End; if (_state == State.StartLine) { if (_parser.ParseRequestLine(this, inputBuffer, out consumed, out examined)) { _state = State.Headers; inputBuffer = inputBuffer.Slice(consumed); } } if (_state == State.Headers) { if (_parser.ParseHeaders(this, inputBuffer, out consumed, out examined, out int consumedBytes)) { _state = State.Body; } } }
public async Task PeekTraversesSegments() { using (var channelFactory = new ChannelFactory()) { var channel = channelFactory.CreateChannel(); var w = channel.Alloc(); w.Append(ReadableBuffer.Create(new byte[] { 1 }, 0, 1)); w.Append(ReadableBuffer.Create(new byte[] { 2 }, 0, 1)); await w.FlushAsync(); var result = await channel.ReadAsync(); var buffer = result.Buffer; var reader = new ReadableBufferReader(buffer); Assert.Equal(1, reader.Take()); Assert.Equal(2, reader.Peek()); Assert.Equal(2, reader.Take()); Assert.Equal(-1, reader.Peek()); Assert.Equal(-1, reader.Take()); } }
private List <ArraySegment <byte> > GetBufferList(ReadableBuffer buffer) { Debug.Assert(!buffer.IsEmpty); Debug.Assert(!buffer.IsSingleSpan); if (_bufferList == null) { _bufferList = new List <ArraySegment <byte> >(); } else { // Buffers are pooled, so it's OK to root them until the next multi-buffer write. _bufferList.Clear(); } foreach (var b in buffer) { _bufferList.Add(b.GetArray()); } return(_bufferList); }
public async Task ValidMultiFramePayloads(byte[] payload1, byte[] payload2, string decoded) { using (var pair = WebSocketPair.Create()) { var server = pair.ServerSocket.ExecuteAndCaptureFramesAsync(); var client = pair.ClientSocket.ExecuteAndCaptureFramesAsync(); var frame = new WebSocketFrame( endOfMessage: false, opcode: WebSocketOpcode.Text, payload: ReadableBuffer.Create(payload1)); await pair.ClientSocket.SendAsync(frame).OrTimeout(); frame = new WebSocketFrame( endOfMessage: true, opcode: WebSocketOpcode.Continuation, payload: ReadableBuffer.Create(payload2)); await pair.ClientSocket.SendAsync(frame).OrTimeout(); await pair.ClientSocket.CloseAsync(WebSocketCloseStatus.NormalClosure).OrTimeout(); var serverSummary = await server.OrTimeout(); await pair.ServerSocket.CloseAsync(WebSocketCloseStatus.NormalClosure).OrTimeout(); var clientSummary = await client.OrTimeout(); Assert.Equal(0, clientSummary.Received.Count); Assert.Equal(2, serverSummary.Received.Count); Assert.False(serverSummary.Received[0].EndOfMessage); Assert.Equal(WebSocketOpcode.Text, serverSummary.Received[0].Opcode); Assert.True(serverSummary.Received[1].EndOfMessage); Assert.Equal(WebSocketOpcode.Continuation, serverSummary.Received[1].Opcode); var finalPayload = serverSummary.Received.SelectMany(f => f.Payload.ToArray()).ToArray(); Assert.Equal(decoded, Encoding.UTF8.GetString(finalPayload)); } }
public void ParseHeadersConsumesBytesCorrectlyAtEnd() { var parser = CreateParser(Mock.Of <IKestrelTrace>()); const string headerLine = "Header: value\r\n\r"; var buffer1 = ReadableBuffer.Create(Encoding.ASCII.GetBytes(headerLine)); var requestHandler = new RequestHandler(); Assert.False(parser.ParseHeaders(requestHandler, buffer1, out var consumed, out var examined, out var consumedBytes)); Assert.Equal(buffer1.Move(buffer1.Start, headerLine.Length - 1), consumed); Assert.Equal(buffer1.End, examined); Assert.Equal(headerLine.Length - 1, consumedBytes); var buffer2 = ReadableBuffer.Create(Encoding.ASCII.GetBytes("\r\n")); Assert.True(parser.ParseHeaders(requestHandler, buffer2, out consumed, out examined, out consumedBytes)); Assert.Equal(buffer2.End, consumed); Assert.Equal(buffer2.End, examined); Assert.Equal(2, consumedBytes); }
public static Header ReadHeader(ref ReadableBuffer buffer, ref HeaderTable headerTable, IBufferPool memoryPool) { int firstByte = buffer.Peek(); if (firstByte < 0) { ThrowEndOfStreamException(); } buffer = buffer.Slice(1); if ((firstByte & 0x80) != 0) { // 6.1. Indexed Header Field Representation return(headerTable.GetHeader(ReadUInt32(ref buffer, firstByte, 7))); } else if ((firstByte & 0x40) != 0) { // 6.2.1. Literal Header Field with Incremental Indexing var result = ReadHeader(ref buffer, ref headerTable, firstByte, 6, HeaderOptions.IndexAddNewValue); headerTable = headerTable.Add(result, memoryPool); return(result); } else if ((firstByte & 0x20) != 0) { // 6.3. Dynamic Table Size Update var newSize = ReadInt32(ref buffer, firstByte, 5); headerTable = headerTable.SetMaxLength(newSize, memoryPool); return(Header.Resize(newSize)); } else { // 6.2.2.Literal Header Field without Indexing // 6.2.3.Literal Header Field Never Indexed return(ReadHeader(ref buffer, ref headerTable, firstByte, 4, (firstByte & 0x10) == 0 ? HeaderOptions.IndexNotIndexed : HeaderOptions.IndexNeverIndexed)); } }
public unsafe void GetCipherSuiteFromExtension(ReadableBuffer buffer, IConnectionState state) { var list = GetCipherSuites(state.Version); if (buffer.Length % 2 != 0) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "Cipher suite extension is not divisable by zero"); } var numberOfCiphers = buffer.Length / 2; var peerCipherList = stackalloc ushort[numberOfCiphers]; for (var i = 0; i < numberOfCiphers; i++) { peerCipherList[i] = buffer.ReadBigEndian <ushort>(); buffer = buffer.Slice(sizeof(ushort)); if (peerCipherList[i] == 0x00FF) { state.SecureRenegotiation = true; } } for (var i = 0; i < list.Length; i++) { for (var x = 0; x < numberOfCiphers; x++) { var suite = list[i]; if (peerCipherList[x] == suite.CipherCode) { if (suite.RequiredCertificateType == CertificateType.anonymous || _certificateList.GetCertificate(null, (SignatureScheme)((ushort)suite.HashType << 8 | (ushort)suite.RequiredCertificateType)) != null) { state.CipherSuite = list[i]; return; } } } } Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.insufficient_security, "Failed to get a bulk cipher from the cipher extensions"); }
internal unsafe static void ApplyMask(ref ReadableBuffer buffer, int mask) { if (mask == 0) { return; } ulong mask8 = (uint)mask; mask8 = (mask8 << 32) | mask8; foreach (var span in buffer) { int len = span.Length; if ((len & ~7) != 0) // >= 8 { var ptr = (ulong *)span.BufferPtr; do { (*ptr++) ^= mask8; len -= 8; } while ((len & ~7) != 0); // >= 8 } // TODO: worth doing an int32 mask here if >= 4? if (len != 0) { var ptr = ((byte *)span.BufferPtr) + (buffer.Length & ~7); // forwards everything except the last chunk do { var b = (byte)(mask8 & 255); (*ptr++) ^= b; // rotate the mask (need to preserve LHS in case we have another span) mask8 = (mask8 >> 8) | (((ulong)b) << 56); len--; } while (len != 0); } } }
private void OnAccept(StreamHandle stream, ReadableBuffer data) { if (data.Count == 0) { log($"client OnAccept: data count is 0"); return; } ////log($"client accept {data.Count}"); // Echo back var buffer = new byte[data.Count]; data.ReadBytes(buffer, buffer.Length); data.Dispose(); var writableBuffer = WritableBuffer.From(buffer); stream.QueueWriteStream( writableBuffer, (handle, exception) => { writableBuffer.Dispose(); if (exception != null) { log($"client write error: {exception.Message}"); handle.CloseHandle(h => h.Dispose()); } else { stream.OnRead( this.OnAccept, (_h, _e) => { log($"read error {_e.Message}"); }); } }); ////log($"client wrote {buffer.Length}"); }
public void ExceptionDetailNotIncludedWhenLogLevelInformationNotEnabled() { var mockTrace = new Mock <IKestrelTrace>(); mockTrace .Setup(trace => trace.IsEnabled(LogLevel.Information)) .Returns(false); var parser = CreateParser(mockTrace.Object); // Invalid request line var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes("GET % HTTP/1.1\r\n")); var requestHandler = new RequestHandler(); var exception = Assert.Throws <BadHttpRequestException>(() => parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined)); Assert.Equal("Invalid request line: ''", exception.Message); Assert.Equal(StatusCodes.Status400BadRequest, (exception as BadHttpRequestException).StatusCode); // Unrecognized HTTP version buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes("GET / HTTP/1.2\r\n")); exception = Assert.Throws <BadHttpRequestException>(() => parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined)); Assert.Equal(CoreStrings.FormatBadRequest_UnrecognizedHTTPVersion(string.Empty), exception.Message); Assert.Equal(StatusCodes.Status505HttpVersionNotsupported, (exception as BadHttpRequestException).StatusCode); // Invalid request header buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes("Header: value\n\r\n")); exception = Assert.Throws <BadHttpRequestException>(() => parser.ParseHeaders(requestHandler, buffer, out var consumed, out var examined, out var consumedBytes)); Assert.Equal(CoreStrings.FormatBadRequest_InvalidRequestHeader_Detail(string.Empty), exception.Message); Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode); }
private async Task ProcessSends() { while (true) { var buffer = await _output.ReadAsync(); if (buffer.IsEmpty && _output.WriterCompleted.IsCompleted) { break; } var enumerator = buffer.GetEnumerator(); if (enumerator.MoveNext()) { var current = enumerator.Current; while (enumerator.MoveNext()) { var next = enumerator.Current; await SendAsync(current, endOfMessage : false); current = next; } await PreviousSendingComplete; _sendingBuffer = buffer.Preserve(); await SendAsync(current, endOfMessage : true); } buffer.Consumed(); } _output.CompleteReading(); }
public async Task InvalidSingleFramePayloads(byte[] payload) { using (var pair = WebSocketPair.Create()) { var server = pair.ServerSocket.ExecuteAndCaptureFramesAsync(); var client = pair.ClientSocket.ExecuteAndCaptureFramesAsync(); var frame = new WebSocketFrame( endOfMessage: true, opcode: WebSocketOpcode.Text, payload: ReadableBuffer.Create(payload)); await pair.ClientSocket.SendAsync(frame).OrTimeout(); var clientSummary = await client.OrTimeout(); var serverSummary = await server.OrTimeout(); Assert.Equal(0, serverSummary.Received.Count); Assert.Equal(0, clientSummary.Received.Count); Assert.Equal(WebSocketCloseStatus.InvalidPayloadData, clientSummary.CloseResult.Status); Assert.Equal("An invalid Text frame payload was received", clientSummary.CloseResult.Description); } }
public void SegmentStartIsConsideredInBoundsCheck() { // 0 50 100 0 50 100 // [ ##############] -> [############## ] // ^c1 ^c2 var bufferSegment1 = new BufferSegment(); bufferSegment1.SetMemory(new OwnedArray <byte>(new byte[100]), 50, 99); var bufferSegment2 = new BufferSegment(); bufferSegment2.SetMemory(new OwnedArray <byte>(new byte[100]), 0, 50); bufferSegment1.SetNext(bufferSegment2); var readableBuffer = new ReadableBuffer(new ReadCursor(bufferSegment1, 0), new ReadCursor(bufferSegment2, 50)); var c1 = readableBuffer.Move(readableBuffer.Start, 25); // segment 1 index 75 var c2 = readableBuffer.Move(readableBuffer.Start, 55); // segment 2 index 5 var sliced = readableBuffer.Slice(c1, c2); Assert.Equal(30, sliced.Length); }
public ServerKeyExchangeParser(ReadableBuffer reader) { var originalSpan = reader.ToSpan(); var span = new BigEndianAdvancingSpan(originalSpan); span.Read <HandshakeHeader>(); _curveType = span.Read <ECCurveType>(); if (_curveType != ECCurveType.named_curve) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "We only support named curves"); } _namedGroup = span.Read <NamedGroup>(); _key = span; span.ReadVector <byte>(); var dataLength = originalSpan.Length - span.Length; _data = originalSpan.Slice(4, dataLength - 4); _signatureScheme = span.Read <SignatureScheme>(); _signature = span.ReadVector <ushort>().ToSpan(); Debug.Assert(span.Length == 0); }
public void ParsesRequestLine( string requestLine, string expectedMethod, string expectedRawTarget, string expectedRawPath, string expectedDecodedPath, string expectedQueryString, string expectedVersion) { var parser = CreateParser(Mock.Of <IKestrelTrace>()); var buffer = ReadableBuffer.Create(Encoding.ASCII.GetBytes(requestLine)); var requestHandler = new RequestHandler(); Assert.True(parser.ParseRequestLine(requestHandler, buffer, out var consumed, out var examined)); Assert.Equal(requestHandler.Method, expectedMethod); Assert.Equal(requestHandler.Version, expectedVersion); Assert.Equal(requestHandler.RawTarget, expectedRawTarget); Assert.Equal(requestHandler.RawPath, expectedRawPath); Assert.Equal(requestHandler.Version, expectedVersion); Assert.Equal(buffer.End, consumed); Assert.Equal(buffer.End, examined); }
internal static unsafe SecurityStatus Decrypt <T>(this T context, ReadableBuffer buffer, WritableBuffer decryptedData) where T : ISecureContext { void *pointer; if (buffer.IsSingleSpan) { buffer.First.TryGetPointer(out pointer); } else { if (buffer.Length > SecurityContext.MaxStackAllocSize) { throw new OverflowException($"We need to create a buffer on the stack of size {buffer.Length} but the max is {SecurityContext.MaxStackAllocSize}"); } byte * tmpBuffer = stackalloc byte[buffer.Length]; Span <byte> span = new Span <byte>(tmpBuffer, buffer.Length); buffer.CopyTo(span); pointer = tmpBuffer; } int offset = 0; int count = buffer.Length; var secStatus = DecryptMessage(pointer, ref offset, ref count, context.ContextHandle); if (buffer.IsSingleSpan) { buffer = buffer.Slice(offset, count); decryptedData.Append(ref buffer); } else { decryptedData.Ensure(buffer.Length); decryptedData.Write(new Span <byte>(pointer, buffer.Length)); } return(secStatus); }
public override void Encrypt(ref WritableBuffer writer, ReadableBuffer plainText, RecordType recordType, TlsVersion tlsVersion) { _key.IV.Span.Slice(4).WriteBigEndian(_sequenceNumber); _key.Init(KeyMode.Encryption); var additionalInfo = new AdditionalInfo() { SequenceNumber = _sequenceNumber, RecordType = recordType, TlsVersion = tlsVersion, PlainTextLength = (ushort)plainText.Length }; _key.AddAdditionalInfo(ref additionalInfo); writer.WriteBigEndian(_sequenceNumber); var totalBytes = plainText.Length; foreach (var b in plainText) { if (b.Length == 0) { continue; } totalBytes -= b.Length; writer.Ensure(b.Length); int bytesWritten; if (totalBytes == 0) { bytesWritten = _key.Finish(b.Span, writer.Buffer.Span); writer.Advance(bytesWritten); break; } bytesWritten = _key.Update(b.Span, writer.Buffer.Span); writer.Advance(bytesWritten); } IncrementSequence(); WriteTag(ref writer); }
public async Task InvalidMultiFramePayloads(byte[] payload1, byte[] payload2) { using (var pair = WebSocketPair.Create()) { var timeoutToken = TestUtil.CreateTimeoutToken(); using (timeoutToken.Register(() => pair.Dispose())) { var server = pair.ServerSocket.ExecuteAndCaptureFramesAsync(); var client = pair.ClientSocket.ExecuteAndCaptureFramesAsync(); var frame = new WebSocketFrame( endOfMessage: false, opcode: WebSocketOpcode.Text, payload: ReadableBuffer.Create(payload1)); await pair.ClientSocket.SendAsync(frame).OrTimeout(); frame = new WebSocketFrame( endOfMessage: true, opcode: WebSocketOpcode.Continuation, payload: ReadableBuffer.Create(payload2)); await pair.ClientSocket.SendAsync(frame).OrTimeout(); var clientSummary = await client.OrTimeout(); var serverSummary = await server.OrTimeout(); Assert.Equal(1, serverSummary.Received.Count); Assert.False(serverSummary.Received[0].EndOfMessage); Assert.Equal(WebSocketOpcode.Text, serverSummary.Received[0].Opcode); Assert.Equal(payload1, serverSummary.Received[0].Payload.ToArray()); Assert.Equal(0, clientSummary.Received.Count); Assert.Equal(WebSocketCloseStatus.InvalidPayloadData, clientSummary.CloseResult.Status); Assert.Equal("An invalid Text frame payload was received", clientSummary.CloseResult.Description); } } }
public unsafe bool ParseRequestLine <T>(T handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) where T : IHttpRequestLineHandler { consumed = buffer.Start; examined = buffer.End; // Prepare the first span var span = buffer.First.Span; var lineIndex = span.IndexOf(ByteLF); if (lineIndex >= 0) { consumed = buffer.Move(consumed, lineIndex + 1); span = span.Slice(0, lineIndex + 1); } else if (buffer.IsSingleSpan) { return(false); } else { span = TryGetNewLineSpan(ref buffer, out consumed); if (span.Length == 0) { // No request line end return(false); } } // Fix and parse the span fixed(byte *data = &span.DangerousGetPinnableReference()) { ParseRequestLine(handler, data, span.Length); } examined = consumed; return(true); }
public static void ReadPskKey(ReadableBuffer pskBuffer, IConnectionStateTls13 connectionState) { var identities = BufferExtensions.SliceVector <ushort>(ref pskBuffer); while (identities.Length > 0) { var identity = BufferExtensions.SliceVector <ushort>(ref identities); long serviceId, keyId; identity = identity.SliceBigEndian(out serviceId); identity = identity.SliceBigEndian(out keyId); int ticketAge; identities = identities.SliceBigEndian(out ticketAge); if (!connectionState.ResumptionProvider.TryToResume(serviceId, keyId, identity, connectionState)) { continue; } if ((connectionState.PskKeyExchangeMode & PskKeyExchangeMode.psk_dhe_ke) == 0) { connectionState.KeyShare?.Dispose(); connectionState.KeyShare = null; } return; } }
internal void Append(ReadableBuffer buffer) { if (buffer.IsEmpty) { return; // nothing to do } EnsureAlloc(); BufferSegment clonedEnd; var clonedBegin = BufferSegment.Clone(buffer.Start, buffer.End, out clonedEnd); if (_writingHead == null) { // No active write if (_commitHead == null) { // No allocated buffers yet, not locking as _readHead will be null _commitHead = clonedBegin; } else { Debug.Assert(_commitHead.Next == null); // Allocated buffer, append as next segment _commitHead.Next = clonedBegin; } } else { Debug.Assert(_writingHead.Next == null); // Active write, append as next segment _writingHead.Next = clonedBegin; } // Move write head to end of buffer _writingHead = clonedEnd; }
private void EqualsDetectsDeltaForAllLocations(ReadableBuffer slice, byte[] expected, int offset, int length) { Assert.Equal(length, slice.Length); Assert.True(slice.Equals(new Span<byte>(expected, offset, length))); // change one byte in buffer, for every position for (int i = 0; i < length; i++) { expected[offset + i] ^= 42; Assert.False(slice.Equals(new Span<byte>(expected, offset, length))); expected[offset + i] ^= 42; } }
protected abstract Task WriteAsync(ReadableBuffer buffer);
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 ReadResult(ReadableBuffer buffer, bool isCancelled, bool isCompleted) { Buffer = buffer; IsCancelled = isCancelled; IsCompleted = isCompleted; }
private void BeginWrite(ReadableBuffer buffer) { var writeReq = _thread.WriteReqPool.Allocate(); _pendingWrites++; writeReq.Write(_handle, buffer, _writeCallback, this); }
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()); }
internal PreservedBuffer(ref ReadableBuffer buffer) { _buffer = buffer; }
/// <summary> /// Appends the <see cref="ReadableBuffer"/> to the <see cref="WritableBuffer"/> in-place without copies. /// </summary> /// <param name="buffer">The <see cref="ReadableBuffer"/> to append</param> public void Append(ReadableBuffer buffer) { _output.Append(buffer); }
private bool EqualsIgnoreCase(ref ReadableBuffer key, byte[] buffer) { if (key.Length != buffer.Length) { return false; } return key.Equals(buffer); }
private unsafe void ReadUInt64GivesExpectedValues(ref ReadableBuffer readBuffer) { Assert.True(readBuffer.IsSingleSpan); for (ulong i = 0; i < 1024; i++) { TestValue(ref readBuffer, i); } TestValue(ref readBuffer, ulong.MinValue); TestValue(ref readBuffer, ulong.MaxValue); var rand = new Random(41234); // low numbers for (int i = 0; i < 10000; i++) { TestValue(ref readBuffer, (ulong)rand.Next()); } // wider range of numbers for (int i = 0; i < 10000; i++) { ulong x = (ulong)rand.Next(), y = (ulong)rand.Next(); TestValue(ref readBuffer, (x << 32) | y); TestValue(ref readBuffer, (y << 32) | x); } }
private static unsafe byte*[] BuildPointerIndex(ref ReadableBuffer readBuffer) { byte*[] addresses = new byte*[readBuffer.Length]; int index = 0; foreach (var memory in readBuffer) { void* pointer; memory.TryGetPointer(out pointer); var ptr = (byte*)pointer; for (int i = 0; i < memory.Length; i++) { addresses[index++] = ptr++; } } return addresses; }
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; }
public unsafe void Write( UvStreamHandle handle, ReadableBuffer buffer, Action<UvWriteReq, int, object> callback, object state) { try { // Preserve the buffer for the async call _buffer = buffer.Preserve(); buffer = _buffer.Buffer; int nBuffers = 0; if (buffer.IsSingleSpan) { nBuffers = 1; } else { foreach (var span in buffer) { nBuffers++; } } // add GCHandle to keeps this SafeHandle alive while request processing _pins.Add(GCHandle.Alloc(this, GCHandleType.Normal)); var pBuffers = (Uv.uv_buf_t*)_bufs; if (nBuffers > BUFFER_COUNT) { // create and pin buffer array when it's larger than the pre-allocated one var bufArray = new Uv.uv_buf_t[nBuffers]; var gcHandle = GCHandle.Alloc(bufArray, GCHandleType.Pinned); _pins.Add(gcHandle); pBuffers = (Uv.uv_buf_t*)gcHandle.AddrOfPinnedObject(); } if (nBuffers == 1) { var memory = buffer.First; void* pointer; if (memory.TryGetPointer(out pointer)) { pBuffers[0] = Libuv.buf_init((IntPtr)pointer, memory.Length); } else { throw new InvalidOperationException("Memory needs to be pinned"); } } else { int i = 0; void* pointer; foreach (var memory in buffer) { if (memory.TryGetPointer(out pointer)) { pBuffers[i++] = Libuv.buf_init((IntPtr)pointer, memory.Length); } else { throw new InvalidOperationException("Memory needs to be pinned"); } } } _callback = callback; _state = state; _uv.write(this, handle, pBuffers, nBuffers, _uv_write_cb); } catch { _callback = null; _state = null; _buffer.Dispose(); Unpin(this); throw; } }