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 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(); } }
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); } } }
public static ValueTask <int> ReadAsync(this IPipeReader input, ArraySegment <byte> destination) { while (true) { var awaiter = input.ReadAsync(); if (!awaiter.IsCompleted) { break; } var result = awaiter.GetResult(); var inputBuffer = result.Buffer; var length = (int)Math.Min(inputBuffer.Length, destination.Count); var sliced = inputBuffer.Slice(0, length); sliced.CopyTo(destination); input.Advance(sliced.End); if (length != 0) { return(new ValueTask <int>(length)); } if (result.IsCompleted) { return(new ValueTask <int>(0)); } } return(new ValueTask <int>(input.ReadAsyncAwaited(destination))); }
public static IObservable <ReadOnlyMemory <byte> > CreateObservable(this PipeFactory pfac, IPipeReader reader) { return(Observable.Create <ReadOnlyMemory <byte> >(async(ob, ct) => { try { while (true) { ct.ThrowIfCancellationRequested(); var result = await reader.ReadAsync(); if (result.IsCancelled || (result.IsCompleted && result.Buffer.IsEmpty)) { break; } foreach (var rbuf in result.Buffer) { ob.OnNext(rbuf); } reader.Advance(result.Buffer.End); } ob.OnCompleted(); } catch (Exception e) { try { reader.CancelPendingRead(); } catch { } ob.OnError(e); } })); }
private async Task <int> ReadAsync(ArraySegment <byte> buffer) { while (true) { var result = await _input.ReadAsync(); var readableBuffer = result.Buffer; try { if (!readableBuffer.IsEmpty) { var count = Math.Min(readableBuffer.Length, buffer.Count); readableBuffer = readableBuffer.Slice(0, count); readableBuffer.CopyTo(buffer); return(count); } else if (result.IsCompleted) { return(0); } } finally { _input.Advance(readableBuffer.End, readableBuffer.End); } } }
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); } } }
private static async Task <int> ReadAsyncAwaited(this IPipeReader input, Span <byte> destination) { while (true) { var result = await input.ReadAsync(); var inputBuffer = result.Buffer; var fin = result.IsCompleted; var sliced = inputBuffer.Slice(0, Math.Min(inputBuffer.Length, destination.Length)); sliced.CopyTo(destination); int actual = sliced.Length; input.Advance(sliced.End); if (actual != 0) { return(actual); } else if (fin) { return(0); } } }
public static ValueTask <int> ReadAsync(this IPipeReader input, Span <byte> destination) { while (true) { var awaiter = input.ReadAsync(); if (!awaiter.IsCompleted) { break; } var result = awaiter.GetResult(); var inputBuffer = result.Buffer; var fin = result.IsCompleted; var sliced = inputBuffer.Slice(0, Math.Min(inputBuffer.Length, destination.Length)); sliced.CopyTo(destination); int actual = sliced.Length; input.Advance(sliced.End); if (actual != 0) { return(new ValueTask <int>(actual)); } else if (fin) { return(new ValueTask <int>(0)); } } return(new ValueTask <int>(input.ReadAsyncAwaited(destination))); }
private async void Consume(IPipeReader input) { while (true) { var result = await input.ReadAsync(); var buffer = result.Buffer; try { if (buffer.IsEmpty && result.IsCompleted) { break; } await WriteAsync(buffer); } finally { input.Advance(buffer.End); } } input.Complete(); }
protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context) { long remaining = ContentLength; while (remaining > 0) { var result = await _output.ReadAsync(); var inputBuffer = result.Buffer; var fin = result.IsCompleted; var consumed = inputBuffer.Start; try { if (inputBuffer.IsEmpty && fin) { return; } var data = inputBuffer.Slice(0, remaining); foreach (var memory in data) { ArraySegment <byte> buffer; unsafe { if (!memory.TryGetArray(out buffer)) { // Fall back to copies if this was native memory and we were unable to get // something we could write buffer = new ArraySegment <byte>(memory.Span.ToArray()); } } await stream.WriteAsync(buffer.Array, buffer.Offset, buffer.Count); } consumed = data.End; remaining -= data.Length; } finally { _output.Advance(consumed); } } }
public static async Task <ReadableBuffer> ReadToEndAsync(this IPipeReader input) { while (true) { // Wait for more data var result = await input.ReadAsync(); if (result.IsCompleted) { // Read all the data, return it return(result.Buffer); } // Don't advance the buffer so remains in buffer input.Advance(result.Buffer.Start, result.Buffer.End); } }
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(); } }
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 static async Task CopyToAsync(this IPipeReader input, Stream stream, int bufferSize, CancellationToken cancellationToken) { // TODO: Use bufferSize argument while (!cancellationToken.IsCancellationRequested) { var result = await input.ReadAsync(); var inputBuffer = result.Buffer; try { if (inputBuffer.IsEmpty && result.IsCompleted) { return; } await inputBuffer.CopyToAsync(stream); } finally { input.Advance(inputBuffer.End); } } }
protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context) { long remaining = ContentLength; while (remaining > 0) { var result = await _output.ReadAsync(); var inputBuffer = result.Buffer; var fin = result.IsCompleted; var consumed = inputBuffer.Start; try { if (inputBuffer.IsEmpty && fin) { return; } var data = inputBuffer.Slice(0, remaining); foreach (var memory in data) { await stream.WriteAsync(memory); } consumed = data.End; remaining -= data.Length; } finally { _output.Advance(consumed); } } }
private static async Task <int> ReadAsyncAwaited(this IPipeReader input, ArraySegment <byte> destination) { while (true) { var result = await input.ReadAsync(); var inputBuffer = result.Buffer; var length = (int)Math.Min(inputBuffer.Length, destination.Count); var sliced = inputBuffer.Slice(0, length); sliced.CopyTo(destination); input.Advance(sliced.End); if (length != 0) { return(length); } if (result.IsCompleted) { return(0); } } }
public async Task ProcessAllRequests() { Reset(); while (true) { var result = await _input.ReadAsync(); var buffer = result.Buffer; var consumed = buffer.Start; var examined = buffer.Start; try { if (buffer.IsEmpty && result.IsCompleted) { // We're done with this connection return; } var parserResult = _parser.ParseRequest(buffer, out consumed, out examined); switch (parserResult) { case HttpRequestParser.ParseResult.Incomplete: if (result.IsCompleted) { // Didn't get the whole request and the connection ended throw new EndOfStreamException(); } // Need more data continue; case HttpRequestParser.ParseResult.Complete: // Done break; case HttpRequestParser.ParseResult.BadRequest: // TODO: Don't throw here; throw new Exception(); default: break; } } catch (Exception) { StatusCode = 400; await EndResponse(); return; } finally { _input.Advance(consumed, examined); } var context = _application.CreateContext(this); try { await _application.ProcessRequestAsync(context); } catch (Exception ex) { StatusCode = 500; _application.DisposeContext(context, ex); } finally { await EndResponse(); } if (!KeepAlive) { break; } Reset(); } }
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 static void Advance(this IPipeReader input, ReadCursor cursor) { input.Advance(cursor, cursor); }
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(); }
private async Task DoSend() { Exception error = null; try { while (true) { // Wait for data to write from the pipe producer var result = await _output.ReadAsync(); var buffer = result.Buffer; if (result.IsCancelled) { break; } try { if (!buffer.IsEmpty) { if (buffer.IsSingleSpan) { await _socket.SendAsync(GetArraySegment(buffer.First), SocketFlags.None); } else { SetupSendBuffers(buffer); try { await _socket.SendAsync(_sendBufferList, SocketFlags.None); } finally { _sendBufferList.Clear(); } } } else if (result.IsCompleted) { break; } } finally { _output.Advance(buffer.End); } } _socket.Shutdown(SocketShutdown.Send); } catch (SocketException ex) when(ex.SocketErrorCode == SocketError.OperationAborted) { error = null; } catch (ObjectDisposedException) { error = null; } catch (IOException ex) { error = ex; } catch (Exception ex) { error = new IOException(ex.Message, ex); } finally { _connectionContext.OnConnectionClosed(error); _output.Complete(error); } }
internal static async Task <HttpRequest> ParseHttpRequest(IPipeReader input) { PreservedBuffer Method = default(PreservedBuffer), Path = default(PreservedBuffer), HttpVersion = default(PreservedBuffer); Dictionary <string, PreservedBuffer> Headers = new Dictionary <string, PreservedBuffer>(); try { ParsingState _state = ParsingState.StartLine; bool needMoreData = true; while (needMoreData) { var read = await input.ReadAsync(); var buffer = read.Buffer; var consumed = buffer.Start; needMoreData = true; try { if (buffer.IsEmpty && read.IsCompleted) { throw new EndOfStreamException(); } if (_state == ParsingState.StartLine) { // Find \n ReadCursor delim; ReadableBuffer startLine; if (!buffer.TrySliceTo((byte)'\r', (byte)'\n', out startLine, out delim)) { continue; } // Move the buffer to the rest buffer = buffer.Slice(delim).Slice(2); ReadableBuffer method; if (!startLine.TrySliceTo((byte)' ', out method, out delim)) { throw new Exception(); } Method = method.Preserve(); // Skip ' ' startLine = startLine.Slice(delim).Slice(1); ReadableBuffer path; if (!startLine.TrySliceTo((byte)' ', out path, out delim)) { throw new Exception(); } Path = path.Preserve(); // Skip ' ' startLine = startLine.Slice(delim).Slice(1); var httpVersion = startLine; if (httpVersion.IsEmpty) { throw new Exception(); } HttpVersion = httpVersion.Preserve(); _state = ParsingState.Headers; consumed = buffer.Start; } // Parse headers // key: value\r\n while (!buffer.IsEmpty) { var ch = Peek(ref buffer); if (ch == -1) { break; } if (ch == '\r') { // Check for final CRLF. buffer = buffer.Slice(1); ch = Peek(ref buffer); buffer = buffer.Slice(1); if (ch == -1) { break; } else if (ch == '\n') { consumed = buffer.Start; needMoreData = false; break; } // Headers don't end in CRLF line. throw new Exception(); } var headerName = default(ReadableBuffer); var headerValue = default(ReadableBuffer); // End of the header // \n ReadCursor delim; ReadableBuffer headerPair; if (!buffer.TrySliceTo((byte)'\n', out headerPair, out delim)) { break; } buffer = buffer.Slice(delim).Slice(1); // : if (!headerPair.TrySliceTo((byte)':', out headerName, out delim)) { throw new Exception(); } headerName = headerName.TrimStart(); headerPair = headerPair.Slice(delim).Slice(1); // \r if (!headerPair.TrySliceTo((byte)'\r', out headerValue, out delim)) { // Bad request throw new Exception(); } headerValue = headerValue.TrimStart(); Headers[ToHeaderKey(ref headerName)] = headerValue.Preserve(); // Move the consumed consumed = buffer.Start; } } finally { input.Advance(consumed); } } var result = new HttpRequest(Method, Path, HttpVersion, Headers); Method = Path = HttpVersion = default(PreservedBuffer); Headers = null; return(result); } finally { Method.Dispose(); Path.Dispose(); HttpVersion.Dispose(); if (Headers != null) { foreach (var pair in Headers) { pair.Value.Dispose(); } } } }
private static async void WriteToSocket(TSocket tsocket, IPipeReader reader) { Exception error = null; try { while (true) { var readResult = await reader.ReadAsync(); ReadableBuffer buffer = readResult.Buffer; ReadCursor end = buffer.Start; try { if ((buffer.IsEmpty && readResult.IsCompleted) || readResult.IsCancelled) { // EOF or TransportThread stopped break; } if (!buffer.IsEmpty) { var result = TrySend(tsocket.Fd, ref buffer); if (result.Value == buffer.Length) { end = buffer.End; } else if (result.IsSuccess) { end = buffer.Move(buffer.Start, result.Value); } else if (result == PosixResult.EAGAIN || result == PosixResult.EWOULDBLOCK) { if (!await Writable(tsocket)) { // TransportThread stopped break; } } else { error = result.AsException(); break; } } } finally { // We need to call Advance to end the read reader.Advance(end); } } } catch (Exception ex) { error = ex; } finally { tsocket.ConnectionContext.OnConnectionClosed(error); reader.Complete(error); tsocket.StopReadFromSocket(); CleanupSocketEnd(tsocket); } }
public async Task WriteOutputAsync() { var pool = _thread.WriteReqPool; while (true) { ReadResult result; try { result = await _pipe.ReadAsync(); } catch { // Handled in OnWriterCompleted return; } var buffer = result.Buffer; var consumed = buffer.End; try { if (result.IsCancelled) { break; } if (!buffer.IsEmpty) { var writeReq = pool.Allocate(); try { if (_socket.IsClosed) { break; } var writeResult = await writeReq.WriteAsync(_socket, buffer); LogWriteInfo(writeResult.Status, writeResult.Error); if (writeResult.Error != null) { consumed = buffer.Start; throw writeResult.Error; } } finally { // Make sure we return the writeReq to the pool pool.Return(writeReq); } } else if (result.IsCompleted) { break; } } finally { _pipe.Advance(consumed); } } }
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(); } }