private void OnRead(UvStreamHandle handle, int status) { if (status == 0) { // EAGAIN/EWOULDBLOCK so just return the buffer. // http://docs.libuv.org/en/v1.x/stream.html#c.uv_read_cb Debug.Assert(_currentWritableBuffer != null); _currentWritableBuffer.Value.Commit(); } else if (status > 0) { Log.ConnectionRead(ConnectionId, status); Debug.Assert(_currentWritableBuffer != null); var currentWritableBuffer = _currentWritableBuffer.Value; currentWritableBuffer.Advance(status); var flushTask = currentWritableBuffer.FlushAsync(); if (!flushTask.IsCompleted) { // We wrote too many bytes to the reader, so pause reading and resume when // we hit the low water mark. _ = ApplyBackpressureAsync(flushTask); } } else { // Given a negative status, it's possible that OnAlloc wasn't called. _currentWritableBuffer?.Commit(); _socket.ReadStop(); IOException error = null; if (status == LibuvConstants.EOF) { Log.ConnectionReadFin(ConnectionId); } else { handle.Libuv.Check(status, out var uvError); // Log connection resets at a lower (Debug) level. if (LibuvConstants.IsConnectionReset(status)) { Log.ConnectionReset(ConnectionId); error = new ConnectionResetException(uvError.Message, uvError); } else { Log.ConnectionError(ConnectionId, uvError); error = new IOException(uvError.Message, uvError); } } // Complete after aborting the connection Input.Complete(error); } // Cleanup state from last OnAlloc. This is safe even if OnAlloc wasn't called. _currentWritableBuffer = null; _bufferHandle.Dispose(); }
private void ConnectionCallback(UvStreamHandle streamhandle, int status) { _uvTcpClientSocketChannel.StartRead(); }
private unsafe Uv.uv_buf_t OnAlloc(UvStreamHandle handle, int status) { _inputBuffer = _input.Alloc(2048); return(handle.Libuv.buf_init((IntPtr)_inputBuffer.Memory.UnsafePointer, _inputBuffer.Memory.Length)); }
unsafe private int UvWrite(UvRequest req, UvStreamHandle handle, uv_buf_t *bufs, int nbufs, uv_write_cb cb) { return(_onWrite(handle, nbufs, status => cb(req.InternalGetHandle(), status))); }
public Connection(ListenerContext context, UvStreamHandle socket) : base(context) { _socket = socket; ConnectionControl = this; }
public SocketOutput(KestrelThread thread, UvStreamHandle socket) { _thread = thread; _socket = socket; }
private int UvReadStart(UvStreamHandle handle, uv_alloc_cb allocCallback, uv_read_cb readCallback) { AllocCallback = allocCallback; ReadCallback = readCallback; return(0); }
private static void ReadCallback(UvStreamHandle handle, int status, object state) { ((UvTcpConnection)state).OnRead(handle, status); }
protected virtual void DispatchConnection(UvStreamHandle socket) { // REVIEW: This task should be tracked by the server for graceful shutdown // Today it's handled specifically for http but not for arbitrary middleware _ = HandleConnectionAsync(socket); }
protected virtual void DispatchConnection(UvStreamHandle socket) { HandleConnection(socket); }
protected virtual void DispatchConnection(UvStreamHandle socket) { var connection = new Connection(this, socket); connection.Start(); }
/// <summary> /// Handles an incoming connection /// </summary> /// <param name="listenSocket">Socket being used to listen on</param> /// <param name="status">Connection status</param> protected abstract void OnConnection(UvStreamHandle listenSocket, int status);
private Libuv.uv_buf_t OnAlloc(UvStreamHandle handle, int suggestedSize) { return(handle.Libuv.buf_init( SocketInput.Pin(2048), 2048)); }
// Called on Libuv thread private static LibuvFunctions.uv_buf_t AllocCallback(UvStreamHandle handle, int suggestedSize, object state) { return(((LibuvConnection)state).OnAlloc(handle, suggestedSize)); }
private Libuv.uv_buf_t OnAlloc(UvStreamHandle handle, int status) { _buffer = _input.Alloc(2048); return(handle.Libuv.buf_init(_buffer.Memory.BufferPtr, _buffer.Memory.Length)); }
public LibuvFunctions.uv_buf_t AllocCallback(UvStreamHandle dispatchPipe, int suggestedSize) { return(dispatchPipe.Libuv.buf_init(_bufPtr + _bytesRead, _bufferLength - _bytesRead)); }
private async void OnRead(UvStreamHandle handle, int status) { if (status == 0) { // A zero status does not indicate an error or connection end. It indicates // there is no data to be read right now. // See the note at http://docs.libuv.org/en/v1.x/stream.html#c.uv_read_cb. UnpinInputBuffer(); return; } var normalRead = status > 0; var normalDone = status == EOF; var errorDone = !(normalDone || normalRead); var readCount = normalRead ? status : 0; if (!normalRead) { handle.ReadStop(); } IOException error = null; if (errorDone) { handle.Libuv.Check(status, out Exception uvError); error = new IOException(uvError.Message, uvError); UnpinInputBuffer(); // REVIEW: Should we treat ECONNRESET as an error? // Ignore the error for now _input.Writer.Complete(); } else { _input.Writer.Advance(readCount); UnpinInputBuffer(); // Flush if there was data if (readCount > 0) { var awaitable = _input.Writer.FlushAsync(); if (!awaitable.IsCompleted) { // If there's back pressure handle.ReadStop(); // Resume reading when the awaitable completes var flushResult = await awaitable; if (!flushResult.IsCompleted) { StartReading(); } else { // We're done writing, the reading is gone _input.Writer.Complete(); } } } } if (normalDone) { _input.Writer.Complete(); } }
private static Uv.uv_buf_t AllocCallback(UvStreamHandle handle, int status, object state) { return(((UvTcpConnection)state).OnAlloc(handle, status)); }
private static void ReadCallback(UvStreamHandle handle, int nread, Exception error, object state) { ((Connection)state).OnRead(handle, nread, error); }