Beispiel #1
0
            private static void PlainText(ref WritableBuffer outputBuffer)
            {
                var writer = new WritableBufferWriter(outputBuffer);

                // HTTP 1.1 OK
                writer.Write(_http11OK);

                // Server headers
                writer.Write(_headerServer);

                // Date header
                writer.Write(_dateHeaderValueManager.GetDateHeaderValues().Bytes);
                writer.Write(_crlf);

                // Content-Type header
                writer.Write(_headerContentTypeText);
                writer.Write(_crlf);

                // Content-Length header
                writer.Write(_headerContentLength);
                PipelineExtensions.WriteNumeric(ref writer, (ulong)_plainTextBody.Length);
                writer.Write(_crlf);

                // End of headers
                writer.Write(_crlf);

                // Body
                writer.Write(_plainTextBody);
            }
Beispiel #2
0
            private static void Json(ref WritableBuffer outputBuffer)
            {
                var writer = new WritableBufferWriter(outputBuffer);

                // HTTP 1.1 OK
                writer.Write(_http11OK);

                // Server headers
                writer.Write(_headerServer);

                // Date header
                writer.Write(_dateHeaderValueManager.GetDateHeaderValues().Bytes);
                writer.Write(_crlf);

                // Content-Type header
                writer.Write(_headerContentTypeJson);
                writer.Write(_crlf);

                var jsonPayload = JsonSerializer.SerializeUnsafe(new { message = "Hello, World!" });

                // Content-Length header
                writer.Write(_headerContentLength);
                PipelineExtensions.WriteNumeric(ref writer, (ulong)jsonPayload.Count);
                writer.Write(_crlf);

                // End of headers
                writer.Write(_crlf);

                // Body
                writer.Write(jsonPayload.Array, jsonPayload.Offset, jsonPayload.Count);
            }
        public Task WriteAsync(
            ArraySegment <byte> buffer,
            CancellationToken cancellationToken)
        {
            var writableBuffer = default(WritableBuffer);

            lock (_contextLock)
            {
                if (_completed)
                {
                    throw new ObjectDisposedException("Response is already completed");
                }

                writableBuffer = _pipe.Writer.Alloc(1);
                // TODO obsolete
#pragma warning disable CS0618 // Type or member is obsolete
                var writer = new WritableBufferWriter(writableBuffer);
#pragma warning restore CS0618 // Type or member is obsolete
                if (buffer.Count > 0)
                {
                    writer.Write(buffer.Array, buffer.Offset, buffer.Count);
                }

                writableBuffer.Commit();
            }

            return(FlushAsync(writableBuffer, cancellationToken));
        }
Beispiel #4
0
        public static int WriteBeginChunkBytes(ref WritableBufferWriter start, int dataCount)
        {
            var chunkSegment = BeginChunkBytes(dataCount);

            start.Write(chunkSegment.Array, chunkSegment.Offset, chunkSegment.Count);
            return(chunkSegment.Count);
        }
        private unsafe static void WriteAsciiMultiWrite(ref WritableBufferWriter buffer, string data)
        {
            var remaining = data.Length;

            fixed(char *input = data)
            {
                var inputSlice = input;

                while (remaining > 0)
                {
                    var writable = Math.Min(remaining, buffer.Span.Length);

                    if (writable == 0)
                    {
                        buffer.Ensure();
                        continue;
                    }

                    fixed(byte *output = &buffer.Span.DangerousGetPinnableReference())
                    {
                        EncodeAsciiCharsToBytes(inputSlice, output, writable);
                    }

                    inputSlice += writable;
                    remaining  -= writable;

                    buffer.Advance(writable);
                }
            }
        }
Beispiel #6
0
        private Task WriteAsync(
            ArraySegment <byte> buffer,
            CancellationToken cancellationToken)
        {
            var  writableBuffer = default(WritableBuffer);
            long bytesWritten   = 0;

            lock (_contextLock)
            {
                if (_completed)
                {
                    return(Task.CompletedTask);
                }

                writableBuffer = _pipeWriter.Alloc(1);
                var writer = new WritableBufferWriter(writableBuffer);
                if (buffer.Count > 0)
                {
                    writer.Write(buffer.Array, buffer.Offset, buffer.Count);
                    bytesWritten += buffer.Count;
                }

                writableBuffer.Commit();
            }

            return(FlushAsync(writableBuffer, bytesWritten, cancellationToken));
        }
Beispiel #7
0
        public void ThrowsForInvalidParameters(int arrayLength, int offset, int length)
        {
            _buffer = _pipe.Writer.Alloc(1);
            var initialLength = _buffer.Buffer.Length;

            var writer = new WritableBufferWriter(_buffer);
            var array  = new byte[arrayLength];

            for (int i = 0; i < array.Length; i++)
            {
                array[i] = (byte)(i + 1);
            }

            writer.Write(array, 0, 0);
            writer.Write(array, array.Length, 0);

            try
            {
                writer.Write(array, offset, length);
                Assert.True(false);
            }
            catch (Exception ex)
            {
                Assert.True(ex is ArgumentOutOfRangeException);
            }

            writer.Write(array, 0, array.Length);
            Assert.Equal(array, Read());
        }
        public unsafe static void WriteAsciiNoValidation(ref WritableBufferWriter buffer, string data)
        {
            if (string.IsNullOrEmpty(data))
            {
                return;
            }

            var dest         = buffer.Span;
            var destLength   = dest.Length;
            var sourceLength = data.Length;

            // Fast path, try copying to the available memory directly
            if (sourceLength <= destLength)
            {
                fixed(char *input = data)
                fixed(byte *output = &dest.DangerousGetPinnableReference())
                {
                    EncodeAsciiCharsToBytes(input, output, sourceLength);
                }

                buffer.Advance(sourceLength);
            }
            else
            {
                WriteAsciiMultiWrite(ref buffer, data);
            }
        }
            private void Json(ref WritableBuffer outputBuffer)
            {
                var writer = new WritableBufferWriter(outputBuffer);

                // HTTP 1.1 OK
                writer.Write(_bytesHttpVersion11);
                writer.Write(ReasonPhrases.ToStatusBytes(200, reasonPhrase: null));

                // Headers
                var values = _dateHeaderValueManager.GetDateHeaderValues();

                ResponseHeaders.SetRawDate(values.String, values.Bytes);
                ResponseHeaders.SetRawServer("Custom", _headerServer);
                ResponseHeaders.HeaderContentType = "application/json";
                var jsonPayload = JsonSerializer.SerializeUnsafe(new { message = "Hello, World!" });

                ResponseHeaders.ContentLength = jsonPayload.Count;

                // Write headers
                ResponseHeaders.CopyTo(ref writer);
                writer.Write(_bytesEndHeaders);

                // Body
                writer.Write(jsonPayload.Array, jsonPayload.Offset, jsonPayload.Count);
            }
        public void WriteHeader(AsciiString name, ulong value)
        {
            Output.Write(name);
            var output = new WritableBufferWriter(Output);

            PipelineExtensions.WriteNumeric(ref output, value);
            Output.Write(_crlf);
        }
Beispiel #11
0
        public void ExposesSpan()
        {
            _buffer = _pipe.Writer.Alloc(1);
            var writer = new WritableBufferWriter(_buffer);

            Assert.Equal(_buffer.Buffer.Length, writer.Span.Length);
            Assert.Equal(new byte[] { }, Read());
        }
Beispiel #12
0
        public void CanWriteIntoHeadlessBuffer()
        {
            _buffer = _pipe.Writer.Alloc();
            var writer = new WritableBufferWriter(_buffer);

            writer.Write(new byte[] { 1, 2, 3 });
            Assert.Equal(new byte[] { 1, 2, 3 }, Read());
        }
Beispiel #13
0
        public void EnsureAllocatesSpan()
        {
            _buffer = _pipe.Writer.Alloc();
            var writer = new WritableBufferWriter(_buffer);

            writer.Ensure(10);

            Assert.True(writer.Span.Length > 10);
            Assert.Equal(new byte[] {}, Read());
        }
Beispiel #14
0
        public void CanWriteEmpty()
        {
            _buffer = _pipe.Writer.Alloc();
            var writer = new WritableBufferWriter(_buffer);
            var array  = new byte[] { };

            writer.Write(array);
            writer.Write(array, 0, array.Length);

            Assert.Equal(array, Read());
        }
Beispiel #15
0
        public void CanWriteMultipleTimes()
        {
            _buffer = _pipe.Writer.Alloc();
            var writer = new WritableBufferWriter(_buffer);

            writer.Write(new byte[] { 1 });
            writer.Write(new byte[] { 2 });
            writer.Write(new byte[] { 3 });

            Assert.Equal(new byte[] { 1, 2, 3 }, Read());
        }
Beispiel #16
0
        public void CanWriteWithOffsetAndLenght(int alloc, int offset, int length)
        {
            _buffer = _pipe.Writer.Alloc(alloc);

            var writer = new WritableBufferWriter(_buffer);
            var array  = new byte[] { 1, 2, 3 };

            writer.Write(array, offset, length);

            Assert.Equal(array.Skip(offset).Take(length).ToArray(), Read());
        }
Beispiel #17
0
        public void CanWriteOverTheBlockLength()
        {
            _buffer = _pipe.Writer.Alloc(1);
            var writer = new WritableBufferWriter(_buffer);

            var source        = Enumerable.Range(0, _buffer.Buffer.Length).Select(i => (byte)i);
            var expectedBytes = source.Concat(source).Concat(source).ToArray();

            writer.Write(expectedBytes);

            Assert.Equal(expectedBytes, Read());
        }
Beispiel #18
0
        public void SlicesSpanAndAdvancesAfterWrite()
        {
            _buffer = _pipe.Writer.Alloc(1);
            var initialLength = _buffer.Buffer.Length;

            var writer = new WritableBufferWriter(_buffer);

            writer.Write(new byte[] { 1, 2, 3 });

            Assert.Equal(initialLength - 3, writer.Span.Length);
            Assert.Equal(_buffer.Buffer.Length, writer.Span.Length);
            Assert.Equal(new byte[] { 1, 2, 3 }, Read());
        }
        public void WriteAsciiNoValidationWritesOnlyOneBytePerChar(string input)
        {
            // WriteAscii doesn't validate if characters are in the ASCII range
            // but it shouldn't produce more than one byte per character
            var writerBuffer = _pipe.Writer.Alloc();
            var writer       = new WritableBufferWriter(writerBuffer);

            PipelineExtensions.WriteAsciiNoValidation(ref writer, input);
            writerBuffer.FlushAsync().GetAwaiter().GetResult();
            var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();

            Assert.Equal(input.Length, reader.Buffer.Length);
        }
        public unsafe static void WriteNumeric(ref WritableBufferWriter buffer, ulong number)
        {
            const byte AsciiDigitStart = (byte)'0';

            var span             = buffer.Span;
            var bytesLeftInBlock = span.Length;

            // Fast path, try copying to the available memory directly
            var simpleWrite = true;

            fixed(byte *output = &span.DangerousGetPinnableReference())
            {
                var start = output;

                if (number < 10 && bytesLeftInBlock >= 1)
                {
                    *(start) = (byte)(((uint)number) + AsciiDigitStart);
                    buffer.Advance(1);
                }
                else if (number < 100 && bytesLeftInBlock >= 2)
                {
                    var val  = (uint)number;
                    var tens = (byte)((val * 205u) >> 11); // div10, valid to 1028

                    *(start)     = (byte)(tens + AsciiDigitStart);
                    *(start + 1) = (byte)(val - (tens * 10) + AsciiDigitStart);
                    buffer.Advance(2);
                }
                else if (number < 1000 && bytesLeftInBlock >= 3)
                {
                    var val      = (uint)number;
                    var digit0   = (byte)((val * 41u) >> 12);  // div100, valid to 1098
                    var digits01 = (byte)((val * 205u) >> 11); // div10, valid to 1028

                    *(start)     = (byte)(digit0 + AsciiDigitStart);
                    *(start + 1) = (byte)(digits01 - (digit0 * 10) + AsciiDigitStart);
                    *(start + 2) = (byte)(val - (digits01 * 10) + AsciiDigitStart);
                    buffer.Advance(3);
                }
                else
                {
                    simpleWrite = false;
                }
            }

            if (!simpleWrite)
            {
                WriteNumericMultiWrite(ref buffer, number);
            }
        }
        public void WritesNumericToAscii(ulong number)
        {
            var writerBuffer = _pipe.Writer.Alloc();
            var writer       = new WritableBufferWriter(writerBuffer);

            PipelineExtensions.WriteNumeric(ref writer, number);
            writerBuffer.FlushAsync().GetAwaiter().GetResult();

            var reader   = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
            var numAsStr = number.ToString();
            var expected = Encoding.ASCII.GetBytes(numAsStr);

            AssertExtensions.Equal(expected, reader.Buffer.Slice(0, numAsStr.Length).ToArray());
        }
            private void Default(ref WritableBuffer outputBuffer)
            {
                var writer = new WritableBufferWriter(outputBuffer);

                // HTTP 1.1 OK
                writer.Write(_bytesHttpVersion11);
                writer.Write(ReasonPhrases.ToStatusBytes(200, reasonPhrase: null));

                // Headers
                var values = _dateHeaderValueManager.GetDateHeaderValues();

                ResponseHeaders.SetRawDate(values.String, values.Bytes);
                ResponseHeaders.SetRawServer("Custom", _headerServer);
                ResponseHeaders.ContentLength = 0;

                // Write headers
                ResponseHeaders.CopyTo(ref writer);
                writer.Write(_bytesEndHeaders);
            }
        private static void WriteNumericMultiWrite(ref WritableBufferWriter buffer, ulong number)
        {
            const byte AsciiDigitStart = (byte)'0';

            var value      = number;
            var position   = _maxULongByteLength;
            var byteBuffer = NumericBytesScratch;

            do
            {
                // Consider using Math.DivRem() if available
                var quotient = value / 10;
                byteBuffer[--position] = (byte)(AsciiDigitStart + (value - quotient * 10)); // 0x30 = '0'
                value = quotient;
            }while (value != 0);

            var length = _maxULongByteLength - position;

            buffer.Write(byteBuffer, position, length);
        }
Beispiel #24
0
        public void WriteResponseHeaders(int statusCode, string reasonPhrase, HttpResponseHeaders responseHeaders)
        {
            lock (_contextLock)
            {
                if (_completed)
                {
                    return;
                }

                var buffer = _pipeWriter.Alloc(1);
                var writer = new WritableBufferWriter(buffer);

                writer.Write(_bytesHttpVersion11);
                var statusBytes = ReasonPhrases.ToStatusBytes(statusCode, reasonPhrase);
                writer.Write(statusBytes);
                responseHeaders.CopyTo(ref writer);
                writer.Write(_bytesEndHeaders);
                buffer.Commit();
            }
        }
        public void WriteAsciiNoValidation()
        {
            const byte maxAscii     = 0x7f;
            var        writerBuffer = _pipe.Writer.Alloc();
            var        writer       = new WritableBufferWriter(writerBuffer);

            for (var i = 0; i < maxAscii; i++)
            {
                PipelineExtensions.WriteAsciiNoValidation(ref writer, new string((char)i, 1));
            }
            writerBuffer.FlushAsync().GetAwaiter().GetResult();

            var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
            var data   = reader.Buffer.Slice(0, maxAscii).ToArray();

            for (var i = 0; i < maxAscii; i++)
            {
                Assert.Equal(i, data[i]);
            }
        }
 public void CopyTo(ref WritableBufferWriter output)
 {
     CopyToFast(ref output);
     if (MaybeUnknown != null)
     {
         foreach (var kv in MaybeUnknown)
         {
             foreach (var value in kv.Value)
             {
                 if (value != null)
                 {
                     output.Write(_CrLf);
                     PipelineExtensions.WriteAsciiNoValidation(ref output, kv.Key);
                     output.Write(_colonSpace);
                     PipelineExtensions.WriteAsciiNoValidation(ref output, value);
                 }
             }
         }
     }
 }
        public void EncodesAsAscii(string input, byte[] expected)
        {
            var writerBuffer = _pipe.Writer.Alloc();
            var writer       = new WritableBufferWriter(writerBuffer);

            PipelineExtensions.WriteAsciiNoValidation(ref writer, input);
            writerBuffer.FlushAsync().GetAwaiter().GetResult();
            var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();

            if (expected.Length > 0)
            {
                AssertExtensions.Equal(
                    expected,
                    reader.Buffer.ToArray());
            }
            else
            {
                Assert.Equal(0, reader.Buffer.Length);
            }
        }
Beispiel #28
0
            private static void Default(ref WritableBuffer outputBuffer)
            {
                var writer = new WritableBufferWriter(outputBuffer);

                // HTTP 1.1 OK
                writer.Write(_http11OK);

                // Server headers
                writer.Write(_headerServer);

                // Date header
                writer.Write(_dateHeaderValueManager.GetDateHeaderValues().Bytes);
                writer.Write(_crlf);

                // Content-Length 0
                writer.Write(_headerContentLengthZero);
                writer.Write(_crlf);

                // End of headers
                writer.Write(_crlf);
            }
        public void WritesNumericAcrossSpanBoundaries(int gapSize)
        {
            var writerBuffer = _pipe.Writer.Alloc(100);
            var writer       = new WritableBufferWriter(writerBuffer);
            // almost fill up the first block
            var spacer = new byte[writer.Span.Length - gapSize];

            writer.Write(spacer);

            var bufferLength = writer.Span.Length;

            PipelineExtensions.WriteNumeric(ref writer, ulong.MaxValue);
            Assert.NotEqual(bufferLength, writer.Span.Length);

            writerBuffer.FlushAsync().GetAwaiter().GetResult();

            var reader      = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
            var numAsString = ulong.MaxValue.ToString();
            var written     = reader.Buffer.Slice(spacer.Length, numAsString.Length);

            Assert.False(written.IsSingleSpan, "The buffer should cross spans");
            AssertExtensions.Equal(Encoding.ASCII.GetBytes(numAsString), written.ToArray());
        }
        private Task WriteAsync(
            ArraySegment <byte> buffer,
            CancellationToken cancellationToken,
            bool chunk = false)
        {
            var writableBuffer = default(WritableBuffer);

            lock (_contextLock)
            {
                if (_completed)
                {
                    return(Task.CompletedTask);
                }

                writableBuffer = _pipe.Writer.Alloc(1);
                var writer = new WritableBufferWriter(writableBuffer);
                if (buffer.Count > 0)
                {
                    if (chunk)
                    {
                        ChunkWriter.WriteBeginChunkBytes(ref writer, buffer.Count);
                    }

                    writer.Write(buffer.Array, buffer.Offset, buffer.Count);

                    if (chunk)
                    {
                        ChunkWriter.WriteEndChunkBytes(ref writer);
                    }
                }

                writableBuffer.Commit();
            }

            return(FlushAsync(writableBuffer, cancellationToken));
        }