public async Task GetResponseAsync(HttpListenerContext context, string localBaseUrl, string remoteBaseUrl, CancellationToken ct) { string postUri = null; if (context.Request.IsWebSocketRequest) { UriBuilder ub = new UriBuilder(PostUri) { Scheme = "wss" }; postUri = ub.Uri.ToString(); } else { postUri = PostUri.ToString(); } HttpWebRequest request = (HttpWebRequest)WebRequest.Create(postUri); request.Method = context.Request.HttpMethod; request.ServerCertificateValidationCallback += ValidateCertificate; if (!context.Request.IsWebSocketRequest) { SetRequestHeaders(request, context.Request.Headers, localBaseUrl, remoteBaseUrl); } // Add RTVS headers var remoteUri = GetRemoteUri(context.Request.Url, remoteBaseUrl); request.Headers.Add(CustomHttpHeaders.RTVSRequestedURL, remoteUri.ToString()); if (context.Request.ContentLength64 > 0) { using (Stream reqStream = await request.GetRequestStreamAsync()) { await context.Request.InputStream.CopyAndFlushAsync(reqStream, null, ct); } } HttpWebResponse response = null; try { response = (HttpWebResponse)await request.GetResponseAsync(); if (response != null) { if (context.Request.IsWebSocketRequest && response.StatusCode == HttpStatusCode.SwitchingProtocols) { Stream respStream = response.GetResponseStream(); string subProtocol = response.Headers[Constants.Headers.SecWebSocketProtocol]; var remoteWebSocket = CommonWebSocket.CreateClientWebSocket(respStream, subProtocol, TimeSpan.FromMinutes(10), receiveBufferSize: 65335, useZeroMask: true); var websocketContext = await context.AcceptWebSocketAsync(subProtocol, receiveBufferSize: 65335, keepAliveInterval: TimeSpan.FromMinutes(10)); await WebSocketHelper.SendReceiveAsync(websocketContext.WebSocket, remoteWebSocket, ct); } else { context.Response.StatusCode = (int)response.StatusCode; SetResponseHeaders(response, context.Response, localBaseUrl, remoteBaseUrl); using (Stream respStream = response.GetResponseStream()) using (Stream outStream = context.Response.OutputStream) { await respStream.CopyAndFlushAsync(outStream, null, ct); } response.Close(); } } } catch (WebException wex) when (wex.Status == WebExceptionStatus.ProtocolError) { response = wex.Response as HttpWebResponse; } catch (OperationCanceledException) { WebServer.Stop(remoteUri.Port); } catch (Exception ex) when (!ex.IsCriticalException()) { _log?.WriteLine(LogVerbosity.Normal, MessageCategory.Error, Resources.Error_RemoteWebServerException.FormatInvariant(ex.Message)); _console?.WriteErrorLine(Resources.Error_RemoteWebServerException.FormatInvariant(ex.Message)); WebServer.Stop(remoteUri.Port); } finally { response?.Close(); } }
public async Task InitializeAsync(CancellationToken ct) { await TaskUtilities.SwitchToBackgroundThread(); Random r = new Random(); // if remote port is between 10000 and 32000, select a port in the same range. // R Help uses ports in that range. int localPortMin = (RemotePort >= 10000 && RemotePort <= 32000) ? 10000 : 49152; int localPortMax = (RemotePort >= 10000 && RemotePort <= 32000) ? 32000 : 65535; _console.WriteErrorLine(Resources.Info_RemoteWebServerStarting.FormatInvariant(_name)); while (true) { ct.ThrowIfCancellationRequested(); _listener = new HttpListener(); LocalPort = r.Next(localPortMin, localPortMax); _listener.Prefixes.Add(Invariant($"http://{LocalHost}:{LocalPort}/")); try { _listener.Start(); } catch (HttpListenerException) { _listener.Close(); continue; } catch (ObjectDisposedException) { // Socket got closed _log.WriteLine(LogVerbosity.Minimal, MessageCategory.Error, Resources.Error_RemoteWebServerCreationFailed.FormatInvariant(_name)); _console.WriteErrorLine(Resources.Error_RemoteWebServerCreationFailed.FormatInvariant(_name)); throw new OperationCanceledException(); } break; } try { _log.WriteLine(LogVerbosity.Minimal, MessageCategory.General, Resources.Info_RemoteWebServerStarted.FormatInvariant(_name, LocalHost, LocalPort)); _console.WriteErrorLine(Resources.Info_RemoteWebServerStarted.FormatInvariant(_name, LocalHost, LocalPort)); _console.WriteErrorLine(Resources.Info_RemoteWebServerDetails.FormatInvariant(Environment.MachineName, LocalHost, LocalPort, _name, _baseAddress)); } catch { } }
public static void RHostProcessStarted(this IActionLog log, ProcessStartInfo psi) { var sb = new StringBuilder(); sb.AppendLine(Invariant($"R Host process started: {psi.FileName}")); if (psi.EnvironmentVariables.Count > 0) { sb.AppendLine("Environment variables:"); foreach (var variable in psi.Environment) { sb.Append(' ', 4).AppendLine(Invariant($"{variable.Key}={variable.Value}")); } } log.WriteLine(LogVerbosity.Minimal, MessageCategory.General, sb.ToString()); }
public static void WatcherApplyRecoveryChange(this IActionLog log, string change) { log.WriteLine(LogVerbosity.Normal, MessageCategory.General, Invariant($"Apply recovery change: {change}")); }
public static void WatcherConsumeChangesFinished(this IActionLog log) { log.WriteLine(LogVerbosity.Normal, MessageCategory.General, "File system changes consumer finished"); }
public static void WatcherStarted(this IActionLog log) { log.WriteLine(LogVerbosity.Normal, MessageCategory.General, "MsBuildFileSystemWatcher started"); }
public static void ApplyProjectChangesStarted(this IActionLog log) { log.WriteLine(LogVerbosity.Normal, MessageCategory.General, "Starting applying changes to file-mirroring project"); }
public static void MsBuildAfterChangesApplied(this IActionLog log, ProjectRootElement rootElement) { log.WriteLine(LogVerbosity.Normal, MessageCategory.General, "File mirroring project after changes applied:" + Environment.NewLine + rootElement.RawXml); }
public static void ExitRLoop(this IActionLog log, int depth) { log.WriteLine(LogVerbosity.Normal, MessageCategory.General, Invariant($"Exit R loop, depth={depth}")); }
public static void FailedToConnectToRHost(this IActionLog log) { log.WriteLine(LogVerbosity.Minimal, MessageCategory.General, Invariant($"Timed out waiting for RHost to connect")); }
public static void ConnectedToRHostWebSocket(this IActionLog log, string uri, int attempt) { log.WriteLine(LogVerbosity.Minimal, MessageCategory.General, Invariant($"Connected to R Web Host socket at {uri} on attempt #{attempt}")); }
public static void RHostProcessExited(this IActionLog log) { log.WriteLine(LogVerbosity.Minimal, MessageCategory.General, "R Host process exited"); }
public static void Request(this IActionLog log, string request, int depth) => log.WriteLine(LogVerbosity.Traffic, MessageCategory.General, Invariant($"[Request,depth={depth}]:{request}"));
public static void WatcherApplyRecoveryChangeFailed(this IActionLog log, string change, Exception exception) { log.WriteLine(LogVerbosity.Normal, MessageCategory.Error, Invariant($"Failed to apply recovery change '{change}', closing watcher:{exception}")); }
public static void Response(this IActionLog log, string response, int depth) { log.WriteLine(LogVerbosity.Traffic, MessageCategory.General, Invariant($"[Response,depth={depth}]:{response}")); }
public void WriteLine(LogVerbosity verbosity, MessageCategory category, string message) => _log.WriteLine(verbosity, category, message);
public void Write(string text) { _window.LogMessage(MessageType.Info, text); _log.WriteLine(LogVerbosity.Normal, MessageCategory.General, text); }