/// <summary> /// Try to compile using the server. Returns a null-containing Task if a response /// from the server cannot be retrieved. /// </summary> private static async Task <BuildResponse> TryCompile(NamedPipeClientStream pipeStream, BuildRequest request, CancellationToken cancellationToken) { BuildResponse response; using (pipeStream) { // Write the request try { Log("Begin writing request"); await request.WriteAsync(pipeStream, cancellationToken).ConfigureAwait(false); Log("End writing request"); } catch (Exception e) { LogException(e, "Error writing build request."); return(new RejectedBuildResponse()); } // Wait for the compilation and a monitor to detect if the server disconnects var serverCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); Log("Begin reading response"); var responseTask = BuildResponse.ReadAsync(pipeStream, serverCts.Token); var monitorTask = CreateMonitorDisconnectTask(pipeStream, "client", serverCts.Token); await Task.WhenAny(responseTask, monitorTask).ConfigureAwait(false); Log("End reading response"); if (responseTask.IsCompleted) { // await the task to log any exceptions try { response = await responseTask.ConfigureAwait(false); } catch (Exception e) { LogException(e, "Error reading response"); response = new RejectedBuildResponse(); } } else { Log("Server disconnect"); response = new RejectedBuildResponse(); } // Cancel whatever task is still around serverCts.Cancel(); Debug.Assert(response != null); return(response); } }
/// <summary> /// May throw exceptions if there are pipe problems. /// </summary> /// <param name="stream"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public static async Task <BuildResponse> ReadAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken)) { // Read the response length var lengthBuffer = new byte[4]; await ReadAllAsync(stream, lengthBuffer, 4, cancellationToken).ConfigureAwait(false); var length = BitConverter.ToUInt32(lengthBuffer, 0); // Read the response var responseBuffer = new byte[length]; await ReadAllAsync(stream, responseBuffer, responseBuffer.Length, cancellationToken).ConfigureAwait(false); using (var reader = new BinaryReader(new MemoryStream(responseBuffer), Encoding.Unicode)) { var responseType = (ResponseType)reader.ReadInt32(); switch (responseType) { case ResponseType.Completed: return(CompletedBuildResponse.Create(reader)); case ResponseType.MismatchedVersion: return(new MismatchedVersionBuildResponse()); case ResponseType.IncorrectHash: return(new IncorrectHashBuildResponse()); case ResponseType.AnalyzerInconsistency: return(AnalyzerInconsistencyBuildResponse.Create(reader)); case ResponseType.Shutdown: return(ShutdownBuildResponse.Create(reader)); case ResponseType.Rejected: return(RejectedBuildResponse.Create(reader)); default: throw new InvalidOperationException("Received invalid response type from server."); } } }
private async Task<ConnectionData> HandleRejectedRequest(CancellationToken cancellationToken) { var response = new RejectedBuildResponse(); await response.WriteAsync(_stream, cancellationToken).ConfigureAwait(false); return new ConnectionData(CompletionReason.CompilationNotStarted); }
/// <summary> /// Try to compile using the server. Returns a null-containing Task if a response /// from the server cannot be retrieved. /// </summary> private static async Task<BuildResponse> TryCompile(NamedPipeClientStream pipeStream, BuildRequest request, CancellationToken cancellationToken) { BuildResponse response; using (pipeStream) { // Write the request try { Log("Begin writing request"); await request.WriteAsync(pipeStream, cancellationToken).ConfigureAwait(false); Log("End writing request"); } catch (Exception e) { LogException(e, "Error writing build request."); return new RejectedBuildResponse(); } // Wait for the compilation and a monitor to detect if the server disconnects var serverCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); Log("Begin reading response"); var responseTask = BuildResponse.ReadAsync(pipeStream, serverCts.Token); var monitorTask = CreateMonitorDisconnectTask(pipeStream, serverCts.Token); await Task.WhenAny(responseTask, monitorTask).ConfigureAwait(false); Log("End reading response"); if (responseTask.IsCompleted) { // await the task to log any exceptions try { response = await responseTask.ConfigureAwait(false); } catch (Exception e) { LogException(e, "Error reading response"); response = new RejectedBuildResponse(); } } else { Log("Server disconnect"); response = new RejectedBuildResponse(); } // Cancel whatever task is still around serverCts.Cancel(); Debug.Assert(response != null); return response; } }