// Must be called with _writeLock
        private void Append(ArraySegment <byte> data)
        {
            if (_completed)
            {
                return;
            }

            var writeableBuffer = _outputWriter.Alloc(1);

            writeableBuffer.Write(data);
            writeableBuffer.Commit();
        }
Exemple #2
0
        public void Write <T>(Action <WritableBuffer, T> callback, T state)
        {
            lock (_contextLock)
            {
                if (_completed)
                {
                    return;
                }

                var buffer = _pipeWriter.Alloc(1);
                callback(buffer, state);
                buffer.Commit();
            }
        }
Exemple #3
0
        public static Task WriteAsync(this IPipeWriter output, ArraySegment <byte> source)
        {
            var writeBuffer = output.Alloc();

            writeBuffer.Write(source);
            return(FlushAsync(writeBuffer));
        }
Exemple #4
0
            public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
            {
                var output = _writer.Alloc();

                output.Write(new Span <byte>(buffer, offset, count));
                await output.FlushAsync();
            }
        public static async void Echo(IPipeReader input, IPipeWriter output)
        {
            try
            {
                while (true)
                {
                    var result = await input.ReadAsync();

                    var request = result.Buffer;

                    if (request.IsEmpty && result.IsCompleted)
                    {
                        input.Advance(request.End);
                        break;
                    }

                    int len      = request.Length;
                    var response = output.Alloc();
                    response.Append(request);
                    await response.FlushAsync();

                    input.Advance(request.End);
                }
            }
            catch
            {
                input.Complete();
                output.Complete();
            }
        }
        public static async Task CopyToAsync(this IPipeReader input, IPipeWriter output)
        {
            while (true)
            {
                var result = await input.ReadAsync();

                var inputBuffer = result.Buffer;

                var fin = result.IsCompleted;

                try
                {
                    if (inputBuffer.IsEmpty && fin)
                    {
                        return;
                    }

                    var buffer = output.Alloc();

                    buffer.Append(inputBuffer);

                    await buffer.FlushAsync();
                }
                finally
                {
                    input.Advance(inputBuffer.End);
                }
            }
        }
        public static Task WriteAsync(this IPipeWriter output, Span <byte> source)
        {
            var writeBuffer = output.Alloc();

            writeBuffer.Write(source);
            return(AwaitFlushAsync(writeBuffer));
        }
Exemple #8
0
        public static async Task WriteAsync(this IPipeWriter output, Span <byte> source)
        {
            var writeBuffer = output.Alloc();

            writeBuffer.Write(source);
            await writeBuffer.FlushAsync();
        }
Exemple #9
0
        private async Task EndResponse()
        {
            var buffer = _output.Alloc();

            if (!HasStarted)
            {
                WriteBeginResponseHeaders(buffer);
            }

            if (_autoChunk)
            {
                WriteEndResponse(buffer);
            }

            await buffer.FlushAsync();
        }
        public static async Task CopyToAsync(this IPipeReader input, IPipeWriter output)
        {
            while (true)
            {
                var result = await input.ReadAsync();

                var inputBuffer = result.Buffer;

                try
                {
                    if (inputBuffer.IsEmpty && result.IsCompleted)
                    {
                        return;
                    }

                    var buffer = output.Alloc();

                    foreach (var memory in inputBuffer)
                    {
                        buffer.Write(memory.Span);
                    }


                    await buffer.FlushAsync();
                }
                finally
                {
                    input.Advance(inputBuffer.End);
                }
            }
        }
Exemple #11
0
            public async Task Execute(IPipeReader reader, IPipeWriter writer)
            {
                List <MemoryHandle> handles = new List <MemoryHandle>();

                while (true)
                {
                    var result = await reader.ReadAsync();

                    var inputBuffer = result.Buffer;

                    if (inputBuffer.IsEmpty)
                    {
                        if (result.IsCompleted)
                        {
                            break;
                        }

                        reader.Advance(inputBuffer.End);
                        continue;
                    }

                    var writerBuffer = writer.Alloc();
                    var buffer       = inputBuffer.First;
                    if (buffer.Length > 0)
                    {
                        unsafe
                        {
                            var handle = buffer.Retain(pin: true);
                            handles.Add(handle);
                            _inflater.SetInput((IntPtr)handle.PinnedPointer, buffer.Length);

                            writerBuffer.Ensure();
                            handle = writerBuffer.Buffer.Retain(pin: true);
                            handles.Add(handle);
                            int written = _inflater.Inflate((IntPtr)handle.PinnedPointer, writerBuffer.Buffer.Length);
                            writerBuffer.Advance(written);

                            var consumed = buffer.Length - _inflater.AvailableInput;

                            inputBuffer = inputBuffer.Slice(0, consumed);
                        }
                    }

                    reader.Advance(inputBuffer.End);

                    await writerBuffer.FlushAsync();
                }

                reader.Complete();

                writer.Complete();

                _inflater.Dispose();

                foreach (var handle in handles)
                {
                    handle.Dispose();
                }
            }
 private void EnsureBuffer()
 {
     if (_needAlloc)
     {
         _writableBuffer = _writer.Alloc();
         _needAlloc      = false;
     }
 }
Exemple #13
0
        public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken token)
        {
            var output = _output.Alloc();

            if (buffer != null)
            {
                output.Write(new ArraySegment <byte>(buffer, offset, count));
            }

            await output.FlushAsync(token);
        }
Exemple #14
0
 public void WriteRecords(IPipeReader pipeReader, RecordType recordType)
 {
     lock (_connectionOutputLock)
     {
         if (!pipeReader.TryRead(out var reader))
         {
             return;
         }
         var buffer = reader.Buffer;
         var output = _output.Alloc();
         try
         {
             WriteRecords(ref buffer, ref output, recordType);
         }
         finally
         {
             pipeReader.Advance(buffer.End);
         }
         output.Commit();
     }
 }
Exemple #15
0
    private static async Task WriteSimpleMessage(IPipeWriter output, string command)
    {
        // keep things simple: using the text protocol guarantees a text-protocol response
        // (in real code we'd use the RESP format, but ... meh)
        await Console.Out.WriteLineAsync($">> sending '{command}'...");

        var buffer = output.Alloc();

        var arr = Encoding.ASCII.GetBytes($"{command}\r\n"); // there's a nice way to do this; I've forgotten

        buffer.Write(arr);
        await buffer.FlushAsync();
    }
Exemple #16
0
    private static async Task WriteSimpleMessage(IPipeWriter output, string command)
    {
        // keep things simple: using the text protocol guarantees a text-protocol response
        // (in real code we'd use the RESP format, but ... meh)
        var msg = (!ShowDetails && command.StartsWith("AUTH", StringComparison.OrdinalIgnoreCase)) ? "AUTH ****" : command;
        await Console.Out.WriteLineAsync($">> sending '{msg}'...");

        var buffer = output.Alloc();

        buffer.WriteUtf8(command.AsReadOnlySpan());
        buffer.Ensure(CRLF.Length);
        buffer.Write(CRLF);
        buffer.Commit();
        await buffer.FlushAsync();
    }
Exemple #17
0
        public static Task WriteAsync(this IPipeWriter output, ReadOnlyMemory <byte> source)
        {
            var writeBuffer = output.Alloc();

            writeBuffer.Write(source.Span);

            var awaitable = writeBuffer.FlushAsync();

            if (awaitable.IsCompleted)
            {
                awaitable.GetResult();
                return(_completedTask);
            }

            return(FlushAsyncAwaited(awaitable));
        }
Exemple #18
0
        internal WritableBufferAwaitable WriteAsync(IPipeWriter output)
        {
            var write = output.Alloc();

            if (_buffers != null)
            {
                foreach (var buffer in _buffers)
                {
                    write.Append(buffer.Buffer);
                }
            }
            else
            {
                ApplyMask();
                write.Append(_buffer);
            }
            return(write.FlushAsync());
        }
Exemple #19
0
        private async Task CopyCompletedAsync(IPipeReader input, IPipeWriter output)
        {
            var result = await input.ReadAsync();

            var inputBuffer = result.Buffer;

            while (true)
            {
                try
                {
                    if (inputBuffer.IsEmpty && result.IsCompleted)
                    {
                        return;
                    }

                    var buffer = output.Alloc();
                    foreach (var memory in inputBuffer)
                    {
                        buffer.Write(memory.Span);
                    }
                    await buffer.FlushAsync();
                }
                finally
                {
                    input.Advance(inputBuffer.End);
                }

                var awaiter = input.ReadAsync();

                if (!awaiter.IsCompleted)
                {
                    // No more data
                    break;
                }

                result = await input.ReadAsync();

                inputBuffer = result.Buffer;
            }
        }
        private static async Task CopyCompletedAsync(IPipeReader input, IPipeWriter output)
        {
            var result = await input.ReadAsync();

            var inputBuffer = result.Buffer;

            while (true)
            {
                try
                {
                    if (inputBuffer.IsEmpty && result.IsCompleted)
                    {
                        return;
                    }

                    var buffer = output.Alloc();

                    buffer.Append(inputBuffer);

                    await buffer.FlushAsync();
                }
                finally
                {
                    input.Advance(inputBuffer.End);
                }

                var awaiter = input.ReadAsync();

                if (!awaiter.IsCompleted)
                {
                    // No more data
                    break;
                }

                result = await input.ReadAsync();

                inputBuffer = result.Buffer;
            }
        }
            public async Task Execute(IPipeReader reader, IPipeWriter writer)
            {
                while (true)
                {
                    var result = await reader.ReadAsync();

                    var inputBuffer = result.Buffer;

                    if (inputBuffer.IsEmpty)
                    {
                        if (result.IsCompleted)
                        {
                            break;
                        }

                        reader.Advance(inputBuffer.End);
                        continue;
                    }

                    var writerBuffer = writer.Alloc();
                    var memory       = inputBuffer.First;
                    if (memory.Length > 0)
                    {
                        unsafe
                        {
                            void *pointer;
                            if (memory.TryGetPointer(out pointer))
                            {
                                _inflater.SetInput((IntPtr)pointer, memory.Length);

                                void *writePointer;
                                writerBuffer.Ensure();
                                if (writerBuffer.Memory.TryGetPointer(out writePointer))
                                {
                                    int written = _inflater.Inflate((IntPtr)writePointer, writerBuffer.Memory.Length);
                                    writerBuffer.Advance(written);
                                }
                                else
                                {
                                    throw new InvalidOperationException("Pointer needs to be pinned");
                                }
                            }
                            else
                            {
                                throw new InvalidOperationException("Pointer needs to be pinned");
                            }

                            var consumed = memory.Length - _inflater.AvailableInput;

                            inputBuffer = inputBuffer.Slice(0, consumed);
                        }
                    }

                    reader.Advance(inputBuffer.End);

                    await writerBuffer.FlushAsync();
                }

                reader.Complete();

                writer.Complete();

                _inflater.Dispose();
            }
            public async Task Execute(IPipeReader reader, IPipeWriter writer)
            {
                while (true)
                {
                    var result = await reader.ReadAsync();

                    var inputBuffer = result.Buffer;

                    if (inputBuffer.IsEmpty)
                    {
                        if (result.IsCompleted)
                        {
                            break;
                        }

                        reader.Advance(inputBuffer.End);
                        continue;
                    }

                    var writerBuffer = writer.Alloc();
                    var memory       = inputBuffer.First;

                    unsafe
                    {
                        // TODO: Pin pointer if not pinned
                        void *inPointer;
                        if (memory.TryGetPointer(out inPointer))
                        {
                            _deflater.SetInput((IntPtr)inPointer, memory.Length);
                        }
                        else
                        {
                            throw new InvalidOperationException("Pointer needs to be pinned");
                        }
                    }

                    while (!_deflater.NeedsInput())
                    {
                        unsafe
                        {
                            void *outPointer;
                            writerBuffer.Ensure();
                            if (writerBuffer.Memory.TryGetPointer(out outPointer))
                            {
                                int written = _deflater.ReadDeflateOutput((IntPtr)outPointer, writerBuffer.Memory.Length);
                                writerBuffer.Advance(written);
                            }
                            else
                            {
                                throw new InvalidOperationException("Pointer needs to be pinned");
                            }
                        }
                    }

                    var consumed = memory.Length - _deflater.AvailableInput;

                    inputBuffer = inputBuffer.Slice(0, consumed);

                    reader.Advance(inputBuffer.End);

                    await writerBuffer.FlushAsync();
                }

                bool flushed = false;

                do
                {
                    // Need to do more stuff here
                    var writerBuffer = writer.Alloc();

                    unsafe
                    {
                        void *pointer;
                        writerBuffer.Ensure();
                        var memory = writerBuffer.Memory;
                        if (memory.TryGetPointer(out pointer))
                        {
                            int compressedBytes;
                            flushed = _deflater.Flush((IntPtr)pointer, memory.Length, out compressedBytes);
                            writerBuffer.Advance(compressedBytes);
                        }
                        else
                        {
                            throw new InvalidOperationException("Pointer needs to be pinned");
                        }
                    }

                    await writerBuffer.FlushAsync();
                }while (flushed);

                bool finished = false;

                do
                {
                    // Need to do more stuff here
                    var writerBuffer = writer.Alloc();

                    unsafe
                    {
                        void *pointer;
                        writerBuffer.Ensure();
                        var memory = writerBuffer.Memory;
                        if (memory.TryGetPointer(out pointer))
                        {
                            int compressedBytes;
                            finished = _deflater.Finish((IntPtr)pointer, memory.Length, out compressedBytes);
                            writerBuffer.Advance(compressedBytes);
                        }
                    }

                    await writerBuffer.FlushAsync();
                }while (!finished);

                reader.Complete();

                writer.Complete();

                _deflater.Dispose();
            }
Exemple #23
0
        private async Task DoReceive()
        {
            Exception error = null;

            try
            {
                while (true)
                {
                    // Ensure we have some reasonable amount of buffer space
                    var buffer = _input.Alloc(MinAllocBufferSize);

                    try
                    {
                        var bytesReceived = await _socket.ReceiveAsync(GetArraySegment(buffer.Buffer), SocketFlags.None);

                        if (bytesReceived == 0)
                        {
                            // FIN
                            break;
                        }

                        buffer.Advance(bytesReceived);
                    }
                    finally
                    {
                        buffer.Commit();
                    }

                    var result = await buffer.FlushAsync();

                    if (result.IsCompleted)
                    {
                        // Pipe consumer is shut down, do we stop writing
                        break;
                    }
                }
            }
            catch (SocketException ex) when(ex.SocketErrorCode == SocketError.ConnectionReset)
            {
                error = new ConnectionResetException(ex.Message, ex);
            }
            catch (SocketException ex) when(ex.SocketErrorCode == SocketError.OperationAborted)
            {
                error = new ConnectionAbortedException();
            }
            catch (ObjectDisposedException)
            {
                error = new ConnectionAbortedException();
            }
            catch (IOException ex)
            {
                error = ex;
            }
            catch (Exception ex)
            {
                error = new IOException(ex.Message, ex);
            }
            finally
            {
                _connectionContext.Abort(error);
                _input.Complete(error);
            }
        }
        private static async void ReadFromSocket(TSocket tsocket, IPipeWriter writer, bool dataMayBeAvailable)
        {
            Exception error = null;

            try
            {
                var  availableBytes = dataMayBeAvailable ? tsocket.Socket.GetAvailableBytes() : 0;
                bool readable0      = true;
                if (availableBytes == 0 &&
                    (readable0 = await Readable(tsocket))) // Readable
                {
                    availableBytes = tsocket.Socket.GetAvailableBytes();
                }
                else if (!readable0)
                {
                    error = new ConnectionAbortedException();
                }
                while (availableBytes != 0)
                {
                    var buffer = writer.Alloc(2048);
                    try
                    {
                        error = Receive(tsocket.Fd, availableBytes, ref buffer);
                        if (error != null)
                        {
                            break;
                        }
                        availableBytes = 0;
                        var flushResult = await buffer.FlushAsync();

                        bool readable = true;
                        if (!flushResult.IsCompleted && // Reader hasn't stopped
                            !flushResult.IsCancelled && // TransportThread hasn't stopped
                            (readable = await Readable(tsocket))) // Readable
                        {
                            availableBytes = tsocket.Socket.GetAvailableBytes();
                        }
                        else if (flushResult.IsCancelled || !readable)
                        {
                            error = new ConnectionAbortedException();
                        }
                    }
                    catch (Exception e)
                    {
                        availableBytes = 0;
                        buffer.Commit();
                        error = e;
                    }
                }
            }
            catch (Exception ex)
            {
                error = ex;
            }
            finally
            {
                // even when error == null, we call Abort
                // this mean receiving FIN causes Abort
                // rationale: https://github.com/aspnet/KestrelHttpServer/issues/1139#issuecomment-251748845
                tsocket.ConnectionContext.Abort(error);
                writer.Complete(error);

                CleanupSocketEnd(tsocket);
            }
        }
Exemple #25
0
            public async Task Execute(IPipeReader reader, IPipeWriter writer)
            {
                List <MemoryHandle> handles = new List <MemoryHandle>();

                while (true)
                {
                    var result = await reader.ReadAsync();

                    var inputBuffer = result.Buffer;

                    if (inputBuffer.IsEmpty)
                    {
                        if (result.IsCompleted)
                        {
                            break;
                        }

                        reader.Advance(inputBuffer.End);
                        continue;
                    }

                    var writerBuffer = writer.Alloc();
                    var buffer       = inputBuffer.First;

                    unsafe
                    {
                        var handle = buffer.Retain(pin: true);
                        handles.Add(handle);
                        _deflater.SetInput((IntPtr)handle.PinnedPointer, buffer.Length);
                    }

                    while (!_deflater.NeedsInput())
                    {
                        unsafe
                        {
                            writerBuffer.Ensure();
                            var handle = writerBuffer.Buffer.Retain(pin: true);
                            handles.Add(handle);
                            int written = _deflater.ReadDeflateOutput((IntPtr)handle.PinnedPointer, writerBuffer.Buffer.Length);
                            writerBuffer.Advance(written);
                        }
                    }

                    var consumed = buffer.Length - _deflater.AvailableInput;

                    inputBuffer = inputBuffer.Slice(0, consumed);

                    reader.Advance(inputBuffer.End);

                    await writerBuffer.FlushAsync();
                }

                bool flushed = false;

                do
                {
                    // Need to do more stuff here
                    var writerBuffer = writer.Alloc();

                    unsafe
                    {
                        writerBuffer.Ensure();
                        var memory = writerBuffer.Buffer;
                        var handle = memory.Retain(pin: true);
                        handles.Add(handle);
                        int compressedBytes;
                        flushed = _deflater.Flush((IntPtr)handle.PinnedPointer, memory.Length, out compressedBytes);
                        writerBuffer.Advance(compressedBytes);
                    }

                    await writerBuffer.FlushAsync();
                }while (flushed);

                bool finished = false;

                do
                {
                    // Need to do more stuff here
                    var writerBuffer = writer.Alloc();

                    unsafe
                    {
                        writerBuffer.Ensure();
                        var memory = writerBuffer.Buffer;
                        var handle = memory.Retain(pin: true);
                        handles.Add(handle);
                        int compressedBytes;
                        finished = _deflater.Finish((IntPtr)handle.PinnedPointer, memory.Length, out compressedBytes);
                        writerBuffer.Advance(compressedBytes);
                    }

                    await writerBuffer.FlushAsync();
                }while (!finished);

                reader.Complete();

                writer.Complete();

                _deflater.Dispose();

                foreach (var handle in handles)
                {
                    handle.Dispose();
                }
            }