public async Task <BuildRequest> ReadBuildRequestAsync(CancellationToken cancellationToken)
        {
            var request = await BuildRequest.ReadAsync(Stream, cancellationToken).ConfigureAwait(false);

            // Now that we've read data from the stream we can validate the identity.
            if (!NamedPipeUtil.CheckClientElevationMatches(Stream))
            {
                throw new Exception("Client identity does not match server identity.");
            }

            // The result is deliberately discarded here. The idea is to kick off the monitor code and
            // when it completes it will trigger the task. Don't want to block on that here.
            _ = MonitorDisconnect();

            return(request);

            async Task MonitorDisconnect()
            {
                try
                {
                    await BuildServerConnection.MonitorDisconnectAsync(Stream, request.RequestId, Logger, DisconnectCancellationTokenSource.Token).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    Logger.LogException(ex, $"Error monitoring disconnect {request.RequestId}");
                }
                finally
                {
                    DisconnectTaskCompletionSource.TrySetResult(this);
                }
            }
        }
Example #2
0
        /// <summary>
        ///     Changes the state of the connection to the specified <paramref name="state"/> and raises events with the
        ///     optionally specified <paramref name="message"/>.
        /// </summary>
        /// <param name="state">The state to which to change.</param>
        /// <param name="message">The optional message describing the nature of the change.</param>
        /// <param name="exception">The optional Exception associated with the change.</param>
        protected void ChangeState(ConnectionState state, string message, Exception exception = null)
        {
            var eventArgs = new ConnectionStateChangedEventArgs(previousState: State, currentState: state, message: message, exception: exception);

            State = state;

            Interlocked.CompareExchange(ref StateChanged, null, null)?
            .Invoke(this, eventArgs);

            if (State == ConnectionState.Connected)
            {
                Interlocked.CompareExchange(ref Connected, null, null)?
                .Invoke(this, EventArgs.Empty);
            }
            else if (State == ConnectionState.Disconnected)
            {
                Interlocked.CompareExchange(ref Disconnected, null, null)?
                .Invoke(this, new ConnectionDisconnectedEventArgs(message, exception));

                if (exception != null)
                {
                    DisconnectTaskCompletionSource.SetException(exception);
                }
                else
                {
                    DisconnectTaskCompletionSource.SetResult(message);
                }
            }
        }
        public void Dispose()
        {
            if (!IsDisposed)
            {
                try
                {
                    DisconnectTaskCompletionSource.TrySetResult(new object());
                    DisconnectCancellationTokenSource.Cancel();
                    Stream.Close();
                }
                catch (Exception ex)
                {
                    Logger.LogException(ex, $"Error closing client connection");
                }

                IsDisposed = true;
            }
        }