Example #1
0
        internal async Task <CompletionData> ProcessAsync(
            Task <IClientConnection> clientConnectionTask,
            bool allowCompilationRequests       = true,
            CancellationToken cancellationToken = default)
        {
            try
            {
                return(await ProcessCore().ConfigureAwait(false));
            }
            catch (Exception ex)
            {
                CompilerServerLogger.LogException(ex, $"Error processing request for client");
                return(CompletionData.RequestError);
            }

            async Task <CompletionData> ProcessCore()
            {
                using var clientConnection = await clientConnectionTask.ConfigureAwait(false);

                var request = await clientConnection.ReadBuildRequestAsync(cancellationToken).ConfigureAwait(false);

                if (request.ProtocolVersion != BuildProtocolConstants.ProtocolVersion)
                {
                    var response = new MismatchedVersionBuildResponse();
                    await clientConnection.WriteBuildResponseAsync(response, cancellationToken).ConfigureAwait(false);

                    return(CompletionData.RequestCompleted);
                }

                if (!string.Equals(request.CompilerHash, BuildProtocolConstants.GetCommitHash(), StringComparison.OrdinalIgnoreCase))
                {
                    var response = new IncorrectHashBuildResponse();
                    await clientConnection.WriteBuildResponseAsync(response, cancellationToken).ConfigureAwait(false);

                    return(CompletionData.RequestCompleted);
                }

                if (request.Arguments.Count == 1 && request.Arguments[0].ArgumentId == BuildProtocolConstants.ArgumentId.Shutdown)
                {
                    var id       = Process.GetCurrentProcess().Id;
                    var response = new ShutdownBuildResponse(id);
                    await clientConnection.WriteBuildResponseAsync(response, cancellationToken).ConfigureAwait(false);

                    return(new CompletionData(CompletionReason.RequestCompleted, shutdownRequested: true));
                }

                if (!allowCompilationRequests)
                {
                    var response = new RejectedBuildResponse("Compilation not allowed at this time");
                    await clientConnection.WriteBuildResponseAsync(response, cancellationToken).ConfigureAwait(false);

                    return(CompletionData.RequestCompleted);
                }

                return(await ProcessCompilationRequestAsync(clientConnection, request, cancellationToken).ConfigureAwait(false));
            }
        }
        public async Task <ConnectionData> HandleConnection(bool allowCompilationRequests = true, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                BuildRequest request;
                try
                {
                    Log("Begin reading request.");
                    request = await BuildRequest.ReadAsync(_stream, cancellationToken).ConfigureAwait(false);

                    ValidateBuildRequest(request);
                    Log("End reading request.");
                }
                catch (Exception e)
                {
                    LogException(e, "Error reading build request.");
                    return(new ConnectionData(CompletionReason.CompilationNotStarted));
                }

                if (request.ProtocolVersion != BuildProtocolConstants.ProtocolVersion)
                {
                    return(await HandleMismatchedVersionRequest(cancellationToken).ConfigureAwait(false));
                }
                else if (!string.Equals(request.CompilerHash, BuildProtocolConstants.GetCommitHash(), StringComparison.OrdinalIgnoreCase))
                {
                    return(await HandleIncorrectHashRequest(cancellationToken).ConfigureAwait(false));
                }
                else if (IsShutdownRequest(request))
                {
                    return(await HandleShutdownRequest(cancellationToken).ConfigureAwait(false));
                }
                else if (!allowCompilationRequests)
                {
                    return(await HandleRejectedRequest(cancellationToken).ConfigureAwait(false));
                }
                else
                {
                    return(await HandleCompilationRequest(request, cancellationToken).ConfigureAwait(false));
                }
            }
            finally
            {
                Close();
            }
        }
        /// <summary>
        /// Handles a client connection. The returned task here will never fail. Instead all exceptions will be wrapped
        /// in a <see cref="CompletionReason.RequestError"/>
        /// </summary>
        internal async Task <CompletionData> ProcessAsync(
            Task <IClientConnection> clientConnectionTask,
            bool allowCompilationRequests       = true,
            CancellationToken cancellationToken = default)
        {
            try
            {
                return(await ProcessCore().ConfigureAwait(false));
            }
            catch (Exception ex)
            {
                Logger.LogException(ex, $"Error processing request for client");
                return(CompletionData.RequestError);
            }

            async Task <CompletionData> ProcessCore()
            {
                using var clientConnection = await clientConnectionTask.ConfigureAwait(false);

                var request = await clientConnection.ReadBuildRequestAsync(cancellationToken).ConfigureAwait(false);

                Logger.Log($"Received request {request.RequestId} of type {request.GetType()}");

                if (!string.Equals(request.CompilerHash, BuildProtocolConstants.GetCommitHash(), StringComparison.OrdinalIgnoreCase))
                {
                    return(await WriteBuildResponseAsync(
                               clientConnection,
                               request.RequestId,
                               new IncorrectHashBuildResponse(),
                               CompletionData.RequestError,
                               cancellationToken).ConfigureAwait(false));
                }

                if (request.Arguments.Count == 1 && request.Arguments[0].ArgumentId == BuildProtocolConstants.ArgumentId.Shutdown)
                {
                    return(await WriteBuildResponseAsync(
                               clientConnection,
                               request.RequestId,
                               new ShutdownBuildResponse(Process.GetCurrentProcess().Id),
                               new CompletionData(CompletionReason.RequestCompleted, shutdownRequested : true),
                               cancellationToken).ConfigureAwait(false));
                }

                if (!allowCompilationRequests)
                {
                    return(await WriteBuildResponseAsync(
                               clientConnection,
                               request.RequestId,
                               new RejectedBuildResponse("Compilation not allowed at this time"),
                               CompletionData.RequestCompleted,
                               cancellationToken).ConfigureAwait(false));
                }

                if (!Environment.Is64BitProcess && !MemoryHelper.IsMemoryAvailable(Logger))
                {
                    return(await WriteBuildResponseAsync(
                               clientConnection,
                               request.RequestId,
                               new RejectedBuildResponse("Not enough resources to accept connection"),
                               CompletionData.RequestError,
                               cancellationToken).ConfigureAwait(false));
                }

                return(await ProcessCompilationRequestAsync(clientConnection, request, cancellationToken).ConfigureAwait(false));
            }
        }