diff --git a/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsServerRouter/DiagnosticsServerRouterFactory.cs b/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsServerRouter/DiagnosticsServerRouterFactory.cs index c79bd3c15e..e7287c0fd9 100644 --- a/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsServerRouter/DiagnosticsServerRouterFactory.cs +++ b/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsServerRouter/DiagnosticsServerRouterFactory.cs @@ -356,9 +356,11 @@ public static WebSocketServerRouterFactory CreateDefaultInstance(string webSocke public WebSocketServerRouterFactory(string webSocketURL, int runtimeTimeoutMs, ILogger logger) : base(runtimeTimeoutMs, logger) { - _webSocketURL = string.IsNullOrEmpty(webSocketURL) ? "ws://127.0.0.1:8088/diagnostics" : webSocketURL; + Debug.Assert(!string.IsNullOrEmpty(webSocketURL)); - _webSocketServer = new ReversedDiagnosticsServer(_webSocketURL, ReversedDiagnosticsServer.Kind.WebSocket); + _webSocketURL = webSocketURL; + + _webSocketServer = new ReversedDiagnosticsServer(_webSocketURL, ReversedDiagnosticsServer.Kind.WebSocket, TimeSpan.FromMilliseconds(750)); _webSocketServer.TransportCallback = this; } diff --git a/src/Microsoft.Diagnostics.NETCore.Client/ReversedServer/ReversedDiagnosticsServer.cs b/src/Microsoft.Diagnostics.NETCore.Client/ReversedServer/ReversedDiagnosticsServer.cs index b0ea799412..72c690c49e 100644 --- a/src/Microsoft.Diagnostics.NETCore.Client/ReversedServer/ReversedDiagnosticsServer.cs +++ b/src/Microsoft.Diagnostics.NETCore.Client/ReversedServer/ReversedDiagnosticsServer.cs @@ -21,7 +21,7 @@ internal sealed class ReversedDiagnosticsServer : IAsyncDisposable { // The amount of time to allow parsing of the advertise data before cancelling. This allows the server to // remain responsive in case the advertise data is incomplete and the stream is not closed. - private static readonly TimeSpan ParseAdvertiseTimeout = TimeSpan.FromMilliseconds(250); + private readonly TimeSpan ParseAdvertiseTimeout; private readonly CancellationTokenSource _disposalSource = new(); private readonly HandleableCollection _endpointInfos = new(); @@ -52,6 +52,7 @@ public enum Kind public ReversedDiagnosticsServer(string address) { _address = address; + ParseAdvertiseTimeout = TimeSpan.FromMilliseconds(250); } /// @@ -69,12 +70,38 @@ public ReversedDiagnosticsServer(string address) /// Otherwise if kind is TcpIp as a supported protocol for ReversedDiagnosticServer. When Kind is Tcp, address will /// be analyzed and if on format host:port, ReversedDiagnosticServer will try to bind /// a TcpIp listener to host and port, otherwise it will use a Unix domain socket or a Windows named pipe. - /// /// public ReversedDiagnosticsServer(string address, Kind kind) { _address = address; _kind = kind; + ParseAdvertiseTimeout = TimeSpan.FromMilliseconds(250); + } + + /// + /// Constructs the instance with an endpoint bound + /// to the location specified by . + /// + /// + /// The server endpoint. + /// On Windows, this can be a full pipe path or the name without the "\\.\pipe\" prefix. + /// On all other systems, this must be the full file path of the socket. + /// + /// + /// If kind is WebSocket, start a Kestrel web server. + /// Otherwise if kind is TcpIp as a supported protocol for ReversedDiagnosticServer. When Kind is Tcp, address will + /// be analyzed and if on format host:port, ReversedDiagnosticServer will try to bind + /// a TcpIp listener to host and port, otherwise it will use a Unix domain socket or a Windows named pipe. + /// + /// + /// The amount of time to allow parsing of the advertise data before cancelling. This allows the server to + /// remain responsive in case the advertise data is incomplete and the stream is not closed. + /// + public ReversedDiagnosticsServer(string address, Kind kind, TimeSpan timeout) + { + _address = address; + _kind = kind; + ParseAdvertiseTimeout = timeout; } public async ValueTask DisposeAsync() diff --git a/src/Microsoft.Diagnostics.WebSocketServer/WebSocketServerImpl.cs b/src/Microsoft.Diagnostics.WebSocketServer/WebSocketServerImpl.cs index f34e5907ce..e7e53cf986 100644 --- a/src/Microsoft.Diagnostics.WebSocketServer/WebSocketServerImpl.cs +++ b/src/Microsoft.Diagnostics.WebSocketServer/WebSocketServerImpl.cs @@ -40,9 +40,18 @@ public async Task StartServer(string endpoint, CancellationToken cancellationTok ParseWebSocketURL(endpoint, out Uri uri); + string scheme = uri.Scheme switch + { + "ws" => "http", + "http" => "http", + "wss" => "https", + "https" => "https", + _ => throw new ArgumentException(string.Format("Unsupported Uri schema, \"{0}\"", uri.Scheme)) + }; + EmbeddedWebSocketServer.Options options = new() { - Scheme = uri.Scheme, + Scheme = scheme, Host = uri.Host, Port = uri.Port.ToString(), Path = uri.PathAndQuery, diff --git a/src/Tools/dotnet-dsrouter/Program.cs b/src/Tools/dotnet-dsrouter/Program.cs index 253ad35b4a..b5cd886ab7 100644 --- a/src/Tools/dotnet-dsrouter/Program.cs +++ b/src/Tools/dotnet-dsrouter/Program.cs @@ -95,7 +95,7 @@ private static Command IpcServerWebSocketServerRouterCommand() command.SetAction((parseResult, ct) => new DiagnosticsServerRouterCommands().RunIpcServerWebSocketServerRouter( ct, ipcServer: parseResult.GetValue(IpcServerAddressOption) ?? "", - webSocket: parseResult.GetValue(WebSocketURLAddressOption) ?? "", + webSocket: parseResult.GetValue(WebSocketURLAddressOption), runtimeTimeout: parseResult.GetValue(RuntimeTimeoutOption), verbose: parseResult.GetValue(VerboseOption) )); @@ -117,7 +117,7 @@ private static Command IpcClientWebSocketServerRouterCommand() command.SetAction((parseResult, ct) => new DiagnosticsServerRouterCommands().RunIpcClientWebSocketServerRouter( ct, ipcClient: parseResult.GetValue(IpcClientAddressOption) ?? "", - webSocket: parseResult.GetValue(WebSocketURLAddressOption) ?? "", + webSocket: parseResult.GetValue(WebSocketURLAddressOption), runtimeTimeout: parseResult.GetValue(RuntimeTimeoutOption), verbose: parseResult.GetValue(VerboseOption) )); @@ -267,7 +267,8 @@ private static Command AndroidRouterCommand() new("--web-socket", "-ws") { Description = "The router WebSocket address using format ws://[host]:[port]/[path] or wss://[host]:[port]/[path]. " + - "Launch app with WasmExtraConfig property specifying diagnostic_options with a server connect_url" + "Launch app with WasmExtraConfig property specifying diagnostic_options with a server connect_url", + DefaultValueFactory = _ => "ws://127.0.0.1:8088/diagnostics" }; private static readonly Option RuntimeTimeoutOption =