public async Task Start()
        {
            try
            {
                OutputConsumer = new LibuvOutputConsumer(Output, Thread, _socket, ConnectionId, Log);

                StartReading();

                Exception error = null;

                try
                {
                    // This *must* happen after socket.ReadStart
                    // The socket output consumer is the only thing that can close the connection. If the
                    // output pipe is already closed by the time we start then it's fine since, it'll close gracefully afterwards.
                    await OutputConsumer.WriteOutputAsync();
                }
                catch (UvException ex)
                {
                    error = new IOException(ex.Message, ex);
                }
                finally
                {
                    // Now, complete the input so that no more reads can happen
                    Input.Complete(error ?? new ConnectionAbortedException());
                    Output.Complete(error);

                    // Make sure it isn't possible for a paused read to resume reading after calling uv_close
                    // on the stream handle
                    Input.CancelPendingFlush();

                    // Send a FIN
                    Log.ConnectionWriteFin(ConnectionId);

                    // We're done with the socket now
                    _socket.Dispose();
                    ThreadPool.QueueUserWorkItem(state => ((LibuvConnection)state).CancelConnectionClosedToken(), this);
                }
            }
            catch (Exception e)
            {
                Log.LogCritical(0, e, $"{nameof(LibuvConnection)}.{nameof(Start)}() {ConnectionId}");
            }
        }
Exemplo n.º 2
0
        private async Task StartCore()
        {
            try
            {
                OutputConsumer = new LibuvOutputConsumer(Output, Thread, _socket, ConnectionId, Log);

                StartReading();

                Exception inputError  = null;
                Exception outputError = null;

                try
                {
                    // This *must* happen after socket.ReadStart
                    // The socket output consumer is the only thing that can close the connection. If the
                    // output pipe is already closed by the time we start then it's fine since, it'll close gracefully afterwards.
                    await OutputConsumer.WriteOutputAsync();
                }
                catch (UvException ex)
                {
                    // The connection reset/error has already been logged by LibuvOutputConsumer
                    if (ex.StatusCode == LibuvConstants.ECANCELED)
                    {
                        // Connection was aborted.
                    }
                    else if (LibuvConstants.IsConnectionReset(ex.StatusCode))
                    {
                        // Don't cause writes to throw for connection resets.
                        inputError = new ConnectionResetException(ex.Message, ex);
                    }
                    else
                    {
                        // This is unexpected.
                        Log.ConnectionError(ConnectionId, ex);

                        inputError  = ex;
                        outputError = ex;
                    }
                }
                finally
                {
                    inputError ??= _abortReason ?? new ConnectionAbortedException("The libuv transport's send loop completed gracefully.");

                    // Now, complete the input so that no more reads can happen
                    Input.Complete(inputError);
                    Output.Complete(outputError);

                    // Make sure it isn't possible for a paused read to resume reading after calling uv_close
                    // on the stream handle
                    Input.CancelPendingFlush();

                    // Send a FIN
                    Log.ConnectionWriteFin(ConnectionId, inputError.Message);

                    // We're done with the socket now
                    _socket.Dispose();

                    // Ensure this always fires
                    FireConnectionClosed();

                    await _waitForConnectionClosedTcs.Task;
                }
            }
            catch (Exception e)
            {
                Log.LogCritical(0, e, $"{nameof(LibuvConnection)}.{nameof(Start)}() {ConnectionId}");
            }
        }