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();
 }
Esempio n. 3
0
 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));
 }
Esempio n. 4
0
 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)));
 }
Esempio n. 5
0
 public Connection(ListenerContext context, UvStreamHandle socket) : base(context)
 {
     _socket           = socket;
     ConnectionControl = this;
 }
Esempio n. 6
0
 public SocketOutput(KestrelThread thread, UvStreamHandle socket)
 {
     _thread = thread;
     _socket = socket;
 }
Esempio n. 7
0
 private int UvReadStart(UvStreamHandle handle, uv_alloc_cb allocCallback, uv_read_cb readCallback)
 {
     AllocCallback = allocCallback;
     ReadCallback  = readCallback;
     return(0);
 }
Esempio n. 8
0
 private static void ReadCallback(UvStreamHandle handle, int status, object state)
 {
     ((UvTcpConnection)state).OnRead(handle, status);
 }
Esempio n. 9
0
 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);
 }
Esempio n. 10
0
 protected virtual void DispatchConnection(UvStreamHandle socket)
 {
     HandleConnection(socket);
 }
Esempio n. 11
0
        protected virtual void DispatchConnection(UvStreamHandle socket)
        {
            var connection = new Connection(this, socket);

            connection.Start();
        }
Esempio n. 12
0
 /// <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);
Esempio n. 13
0
 private Libuv.uv_buf_t OnAlloc(UvStreamHandle handle, int suggestedSize)
 {
     return(handle.Libuv.buf_init(
                SocketInput.Pin(2048),
                2048));
 }
Esempio n. 14
0
 // Called on Libuv thread
 private static LibuvFunctions.uv_buf_t AllocCallback(UvStreamHandle handle, int suggestedSize, object state)
 {
     return(((LibuvConnection)state).OnAlloc(handle, suggestedSize));
 }
Esempio n. 15
0
 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));
 }
Esempio n. 16
0
 public LibuvFunctions.uv_buf_t AllocCallback(UvStreamHandle dispatchPipe, int suggestedSize)
 {
     return(dispatchPipe.Libuv.buf_init(_bufPtr + _bytesRead, _bufferLength - _bytesRead));
 }
Esempio n. 17
0
        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();
            }
        }
Esempio n. 18
0
 private static Uv.uv_buf_t AllocCallback(UvStreamHandle handle, int status, object state)
 {
     return(((UvTcpConnection)state).OnAlloc(handle, status));
 }
Esempio n. 19
0
 private static void ReadCallback(UvStreamHandle handle, int nread, Exception error, object state)
 {
     ((Connection)state).OnRead(handle, nread, error);
 }