System.Net.WebSockets.WebSocketBase.CloseOutputAsyncCore C# (CSharp) Method

CloseOutputAsyncCore() private method

private CloseOutputAsyncCore ( WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken ) : Task
closeStatus WebSocketCloseStatus
statusDescription string
cancellationToken System.Threading.CancellationToken
return Task
        private async Task CloseOutputAsyncCore(WebSocketCloseStatus closeStatus,
            string statusDescription,
            CancellationToken cancellationToken)
        {
            string inputParameter = string.Empty;
            if (NetEventSource.IsEnabled)
            {
                inputParameter = string.Format(CultureInfo.InvariantCulture,
                    "closeStatus: {0}, statusDescription: {1}",
                    closeStatus,
                    statusDescription);
                NetEventSource.Enter(this, inputParameter);
            }

            try
            {
                ThrowIfPendingException();
                if (IsStateTerminal(State))
                {
                    return;
                }
                ThrowIfDisposed();

                bool thisLockTaken = false;
                bool sessionHandleLockTaken = false;
                bool needToCompleteSendOperation = false;
                bool ownsCloseOutputCancellationTokenSource = false;
                bool ownsSendCancellationTokenSource = false;
                CancellationToken linkedCancellationToken = CancellationToken.None;
                try
                {
                    TakeLocks(ref thisLockTaken, ref sessionHandleLockTaken);
                    ThrowIfPendingException();
                    ThrowIfDisposed();

                    if (IsStateTerminal(State))
                    {
                        return;
                    }

                    ThrowOnInvalidState(State, WebSocketState.Open, WebSocketState.CloseReceived);
                    ownsCloseOutputCancellationTokenSource = _closeOutputOutstandingOperationHelper.TryStartOperation(cancellationToken, out linkedCancellationToken);
                    if (!ownsCloseOutputCancellationTokenSource)
                    {
                        Task closeOutputTask = _closeOutputTask;

                        if (closeOutputTask != null)
                        {
                            ReleaseLocks(ref thisLockTaken, ref sessionHandleLockTaken);
                            await closeOutputTask.SuppressContextFlow();
                            TakeLocks(ref thisLockTaken, ref sessionHandleLockTaken);
                        }
                    }
                    else
                    {
                        needToCompleteSendOperation = true;
                        while (!(ownsSendCancellationTokenSource =
                            _sendOutstandingOperationHelper.TryStartOperation(cancellationToken,
                                out linkedCancellationToken)))
                        {
                            if (_keepAliveTask != null)
                            {
                                Task keepAliveTask = _keepAliveTask;

                                ReleaseLocks(ref thisLockTaken, ref sessionHandleLockTaken);
                                await keepAliveTask.SuppressContextFlow();
                                TakeLocks(ref thisLockTaken, ref sessionHandleLockTaken);

                                ThrowIfPendingException();
                            }
                            else
                            {
                                throw new InvalidOperationException(
                                    SR.Format(SR.net_Websockets_AlreadyOneOutstandingOperation, nameof(SendAsync)));
                            }

                            _sendOutstandingOperationHelper.CompleteOperation(ownsSendCancellationTokenSource);
                        }

                        EnsureCloseOutputOperation();
                        _closeOutputOperation.CloseStatus = closeStatus;
                        _closeOutputOperation.CloseReason = statusDescription;
                        _closeOutputTask = _closeOutputOperation.Process(null, linkedCancellationToken);

                        ReleaseLocks(ref thisLockTaken, ref sessionHandleLockTaken);
                        await _closeOutputTask.SuppressContextFlow();
                        TakeLocks(ref thisLockTaken, ref sessionHandleLockTaken);

                        if (OnCloseOutputCompleted())
                        {
                            bool callCompleteOnCloseCompleted = false;

                            try
                            {
                                callCompleteOnCloseCompleted = await StartOnCloseCompleted(
                                    thisLockTaken, sessionHandleLockTaken, linkedCancellationToken).SuppressContextFlow();
                            }
                            catch (Exception)
                            {
                                // If an exception is thrown we know that the locks have been released,
                                // because we enforce IWebSocketStream.CloseNetworkConnectionAsync to yield
                                ResetFlagsAndTakeLocks(ref thisLockTaken, ref sessionHandleLockTaken);
                                throw;
                            }

                            if (callCompleteOnCloseCompleted)
                            {
                                ResetFlagsAndTakeLocks(ref thisLockTaken, ref sessionHandleLockTaken);
                                FinishOnCloseCompleted();
                            }
                        }
                    }
                }
                catch (Exception exception)
                {
                    bool aborted = linkedCancellationToken.IsCancellationRequested;
                    Abort();
                    ThrowIfConvertibleException(nameof(CloseOutputAsync), exception, cancellationToken, aborted);
                    throw;
                }
                finally
                {
                    _closeOutputOutstandingOperationHelper.CompleteOperation(ownsCloseOutputCancellationTokenSource);

                    if (needToCompleteSendOperation)
                    {
                        _sendOutstandingOperationHelper.CompleteOperation(ownsSendCancellationTokenSource);
                    }

                    _closeOutputTask = null;
                    ReleaseLocks(ref thisLockTaken, ref sessionHandleLockTaken);
                }
            }
            finally
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Exit(this, inputParameter);
                }
            }
        }