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();
        }
Example #3
0
        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();
        }
Example #7
0
    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}");
    }
Example #8
0
        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;
            }
        }
Example #9
0
        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());
            }
        }
Example #10
0
        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();
        }
Example #11
0
        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);
        }
Example #14
0
        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;
                    }
                }
            }
Example #16
0
        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());
            }
        }
Example #17
0
        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);
        }
Example #18
0
            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);
        }
Example #20
0
        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));
            }
        }
Example #21
0
        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");
        }
Example #22
0
        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);
                }
            }
        }
Example #23
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);
        }
Example #25
0
        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();
        }
Example #26
0
            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);
        }
Example #28
0
        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);
        }
Example #31
0
        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);
        }
Example #32
0
            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);
                    }
                }
            }
Example #33
0
        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);
        }
Example #34
0
        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;
     }
 }
Example #37
0
 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]);
            }
        }
Example #39
0
 public ReadResult(ReadableBuffer buffer, bool isCancelled, bool isCompleted)
 {
     Buffer = buffer;
     IsCancelled = isCancelled;
     IsCompleted = isCompleted;
 }
Example #40
0
        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());
 }
Example #42
0
 internal PreservedBuffer(ref ReadableBuffer buffer)
 {
     _buffer = buffer;
 }
Example #43
0
 /// <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;
        }
Example #48
0
        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;
            }
        }