static void ConfigureWcfCountCommand(CommandLineApplication wcfCommand) { wcfCommand.RelayCommand("count", (countCommand) => { countCommand.Description = "Get WCF Relay Count"; var connectionStringArgument = countCommand.Argument("connectionString", "Relay ConnectionString"); countCommand.OnExecute(async() => { string connectionString = ConnectionStringUtility.ResolveConnectionString(connectionStringArgument); if (string.IsNullOrEmpty(connectionString)) { TraceMissingArgument(connectionStringArgument.Name); countCommand.ShowHelp(); return(1); } var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString); Uri namespaceUri = namespaceManager.Address; string namespaceHost = namespaceUri.Host; var tokenProvider = namespaceManager.Settings.TokenProvider; RelayTraceSource.TraceVerbose($"Getting WcfRelay count for '{namespaceUri}"); int count = await NamespaceUtility.GetEntityCountAsync(namespaceUri, tokenProvider, "Relays"); RelayTraceSource.TraceInfo(string.Format($"{{0,-{namespaceHost.Length}}} {{1}}", "Namespace", "WcfRelayCount")); RelayTraceSource.TraceInfo(string.Format($"{{0,-{namespaceHost.Length}}} {{1}}", namespaceHost, count)); return(0); }); }); }
static void ConfigureWcfDeleteCommand(CommandLineApplication wcfCommand) { wcfCommand.RelayCommand("delete", (deleteCmd) => { deleteCmd.Description = "Delete a WcfRelay"; var pathArgument = deleteCmd.Argument("path", "WcfRelay path"); var connectionStringArgument = deleteCmd.Argument("connectionString", "Relay ConnectionString"); var protocolOption = deleteCmd.AddSecurityProtocolOption(); deleteCmd.OnExecute(async() => { ConfigureSecurityProtocol(protocolOption); string connectionString = ConnectionStringUtility.ResolveConnectionString(connectionStringArgument); if (string.IsNullOrEmpty(connectionString) || string.IsNullOrEmpty(pathArgument.Value)) { TraceMissingArgument(string.IsNullOrEmpty(connectionString) ? connectionStringArgument.Name : pathArgument.Name); deleteCmd.ShowHelp(); return(1); } var connectionStringBuilder = new ServiceBusConnectionStringBuilder(connectionString); RelayTraceSource.TraceInfo($"Deleting WcfRelay '{pathArgument.Value}' in {connectionStringBuilder.Endpoints.First().Host}..."); var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString); await namespaceManager.DeleteRelayAsync(pathArgument.Value); RelayTraceSource.TraceInfo($"Deleting WcfRelay '{pathArgument.Value}' in {connectionStringBuilder.Endpoints.First().Host} succeeded"); return(0); }); }); }
public EchoService() { IContextChannel channel = OperationContext.Current?.Channel; this.trackingId = channel?.GetProperty <TrackingContext>()?.TrackingId; RelayTraceSource.TraceVerbose($"{nameof(EchoService)} instance created. TrackingId:{this.trackingId}"); }
static async Task TestStreaming(HybridConnectionListener listener, RelayConnectionStringBuilder connectionString, TraceSource traceSource) { traceSource.TraceInformation("Testing Streaming (WebSocket) mode"); RunAcceptPump(listener); var client = new HybridConnectionClient(connectionString.ToString()); var requestBytes = Encoding.UTF8.GetBytes("<data>Request payload from sender</data>"); HybridConnectionStream stream = await client.CreateConnectionAsync(); string connectionName = $"S:HybridConnectionStream({stream.TrackingContext.TrackingId})"; RelayTraceSource.TraceInfo($"{connectionName} initiated"); RunConnectionPump(stream, connectionName); for (int i = 0; i < 2; i++) { await stream.WriteAsync(requestBytes, 0, requestBytes.Length); RelayTraceSource.TraceVerbose($"{connectionName} wrote {requestBytes.Length} bytes"); } using (var closeCts = new CancellationTokenSource(TimeSpan.FromSeconds(5))) { RelayTraceSource.TraceVerbose($"{connectionName} closing"); await stream.CloseAsync(closeCts.Token); RelayTraceSource.TraceInfo($"{connectionName} closed"); } await Task.Delay(TimeSpan.FromMilliseconds(100)); }
public static int VerifyListen(string connectionString, string path, Binding binding, ConnectivityMode connectivityMode, string response, ServiceThrottlingBehavior throttlingBehavior) { RelayTraceSource.TraceInfo($"Open relay listener using {binding.GetType().Name}, ConnectivityMode.{connectivityMode}..."); ServiceHost serviceHost = null; try { var connectionStringBuilder = new ServiceBusConnectionStringBuilder(connectionString); var tp = TokenProvider.CreateSharedAccessSignatureTokenProvider(connectionStringBuilder.SharedAccessKeyName, connectionStringBuilder.SharedAccessKey); string relayNamespace = connectionStringBuilder.Endpoints.First().Host; ServiceBusEnvironment.SystemConnectivity.Mode = connectivityMode; EchoService.DefaultResponse = response; if (!(binding is WebHttpRelayBinding)) { serviceHost = new ServiceHost(typeof(EchoService)); } else { serviceHost = new WebServiceHost(typeof(EchoService)); } Type contractType = IsOneWay(binding) ? typeof(ITestOneway) : typeof(IEcho); ServiceEndpoint endpoint = serviceHost.AddServiceEndpoint(contractType, binding, new Uri($"{binding.Scheme}://{relayNamespace}/{path}")); var listenerActivityId = Guid.NewGuid(); RelayTraceSource.TraceVerbose($"Listener ActivityId:{listenerActivityId}"); endpoint.EndpointBehaviors.Add(new TransportClientEndpointBehavior(tp) { ActivityId = listenerActivityId }); serviceHost.Description.Behaviors.Add(throttlingBehavior); // Trace status changes var connectionStatus = new ConnectionStatusBehavior(); connectionStatus.Connecting += (s, e) => RelayTraceSource.TraceException(connectionStatus.LastError, TraceEventType.Warning, "Relay listener Re-Connecting"); connectionStatus.Online += (s, e) => RelayTraceSource.Instance.TraceEvent(TraceEventType.Information, (int)ConsoleColor.Green, "Relay Listener is online"); EventHandler offlineHandler = (s, e) => RelayTraceSource.TraceException(connectionStatus.LastError, "Relay Listener is OFFLINE"); connectionStatus.Offline += offlineHandler; endpoint.EndpointBehaviors.Add(connectionStatus); serviceHost.Faulted += (s, e) => RelayTraceSource.TraceException(connectionStatus.LastError, "Relay listener ServiceHost Faulted"); serviceHost.Open(); RelayTraceSource.TraceInfo("Relay listener \"" + endpoint.Address.Uri + "\" is open"); RelayTraceSource.TraceInfo("Press <ENTER> to close the listener "); Console.ReadLine(); RelayTraceSource.TraceInfo("Closing Connection..."); connectionStatus.Offline -= offlineHandler; // Avoid a spurious trace on expected shutdown. serviceHost.Close(); RelayTraceSource.TraceInfo("Closed"); return(0); } catch (Exception) { serviceHost?.Abort(); throw; } }
void ITestOneway.Operation(DateTime start, string message) { string duration = string.Empty; if (start != default) { duration = $"({(int)DateTime.UtcNow.Subtract(start).TotalMilliseconds}ms from start)"; } RelayTraceSource.TraceInfo($"Listener received request: ITestOneway.Operation({message}) {duration}"); RelayTraceSource.TraceVerbose($"Request MessageId:{OperationContext.Current.IncomingMessageHeaders.MessageId}, TrackingId:{this.trackingId}"); }
static void SetServicePointManagerDefaultSslProtocols(SslProtocols sslProtocols) { FieldInfo s_defaultSslProtocols = typeof(ServicePointManager).GetField("s_defaultSslProtocols", BindingFlags.Static | BindingFlags.NonPublic); if (s_defaultSslProtocols != null) { s_defaultSslProtocols.SetValue(null, sslProtocols); } else { RelayTraceSource.TraceWarning("ServicePointManager.s_defaultSslProtocols field not found."); } }
static void ConfigureWcfListenCommand(CommandLineApplication wcfCommand) { wcfCommand.RelayCommand("listen", (listenCmd) => { listenCmd.Description = "WcfRelay listen command"; var pathArgument = listenCmd.Argument("path", "WcfRelay path"); var connectionStringArgument = listenCmd.Argument("connectionString", "Relay ConnectionString"); var bindingOption = listenCmd.Option(BindingOptionTemplate, BindingOptionDescription, CommandOptionType.SingleValue); var noClientAuthOption = listenCmd.Option("--no-client-auth", "Skip client authentication", CommandOptionType.NoValue); var connectivityModeOption = listenCmd.Option(CommandStrings.ConnectivityModeTemplate, CommandStrings.ConnectivityModeDescription, CommandOptionType.SingleValue); var responseOption = listenCmd.Option("--response <response>", "Response to return", CommandOptionType.SingleValue); var protocolOption = listenCmd.AddSecurityProtocolOption(); var maxConcurrentSessionsOption = listenCmd.Option("--max-concurrent-sessions <count>", "Max Concurrent Sessions", CommandOptionType.SingleValue); var maxConcurrentInstancesOption = listenCmd.Option("--max-concurrent-instances <count>", "Max Concurrent Instances", CommandOptionType.SingleValue); listenCmd.OnExecute(() => { ConfigureSecurityProtocol(protocolOption); string connectionString = ConnectionStringUtility.ResolveConnectionString(connectionStringArgument); string path = pathArgument.Value ?? DefaultPath; if (string.IsNullOrEmpty(connectionString)) { TraceMissingArgument(connectionStringArgument.Name); listenCmd.ShowHelp(); return(1); } Binding binding = GetBinding(bindingOption, noClientAuthOption, null, null, null); try { var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString); namespaceManager.Settings.OperationTimeout = TimeSpan.FromSeconds(5); if (!string.IsNullOrEmpty(path) && namespaceManager.RelayExists(path)) { dynamic dynamicBinding = binding; dynamicBinding.IsDynamic = false; } } catch (Exception exception) { RelayTraceSource.TraceException(exception, "Error calling RelayExists"); } var throttlingBehavior = GetThrottlingBehavior(maxConcurrentSessionsOption, maxConcurrentInstancesOption); return(VerifyListen(connectionString, path, binding, GetConnectivityMode(connectivityModeOption), responseOption.Value(), throttlingBehavior)); }); }); }
static void ConfigureWcfListCommand(CommandLineApplication wcfCommand) { wcfCommand.RelayCommand("list", (listCmd) => { listCmd.Description = "List WcfRelay(s)"; var pathArgument = listCmd.Argument("path", "Optional WcfRelay path"); var connectionStringArgument = listCmd.Argument("connectionString", "Relay ConnectionString"); var protocolOption = listCmd.AddSecurityProtocolOption(); listCmd.OnExecute(async() => { ConfigureSecurityProtocol(protocolOption); string connectionString = ConnectionStringUtility.ResolveConnectionString(connectionStringArgument); if (string.IsNullOrEmpty(connectionString)) { TraceMissingArgument(connectionStringArgument.Name); listCmd.ShowHelp(); return(1); } string path = pathArgument.Value; var connectionStringBuilder = new ServiceBusConnectionStringBuilder(connectionString); var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString); IEnumerable <RelayDescription> relays; if (string.IsNullOrEmpty(path)) { RelayTraceSource.TraceInfo($"Listing WcfRelays for {connectionStringBuilder.Endpoints.First().Host}"); relays = await namespaceManager.GetRelaysAsync(); } else { RelayTraceSource.TraceInfo($"Getting WcfRelay {connectionStringBuilder.Endpoints.First().Host}/{path}"); relays = new[] { await namespaceManager.GetRelayAsync(path) }; } RelayTraceSource.TraceInfo($"{"Path",-38} {"ListenerCount",-15} {"RequiresClientAuth",-20} RelayType"); foreach (var relay in relays) { RelayTraceSource.TraceInfo($"{relay.Path,-38} {relay.ListenerCount,-15} {relay.RequiresClientAuthorization,-20} {relay.RelayType}"); } return(0); }); }); }
public static int VerifySend( string request, ServiceBusConnectionStringBuilder connectionString, string path, int number, Binding binding, bool noClientAuth, ConnectivityMode connectivityMode, TimeSpan requestDelay) { RelayTraceSource.TraceInfo($"Send to relay listener using {binding.GetType().Name}, ConnectivityMode.{connectivityMode}..."); string relayNamespace = connectionString.Endpoints.First().Host; string keyName = connectionString.SharedAccessKeyName; string keyValue = connectionString.SharedAccessKey; if (IsOneWay(binding)) { return(VerifySendCore <ITestOnewayClient>(request, relayNamespace, path, number, binding, noClientAuth, connectivityMode, keyName, keyValue, requestDelay)); } else { return(VerifySendCore <IEchoClient>(request, relayNamespace, path, number, binding, noClientAuth, connectivityMode, keyName, keyValue, requestDelay)); } }
public string Get(DateTime start, string message, TimeSpan delay) { string duration = string.Empty; if (start != default) { duration = $"({(int)DateTime.UtcNow.Subtract(start).TotalMilliseconds}ms from start)"; } RelayTraceSource.TraceInfo($"Listener received request: Get({message}) {duration}"); RelayTraceSource.TraceVerbose($"Request MessageId:{OperationContext.Current.IncomingMessageHeaders.MessageId}, TrackingId:{this.trackingId}"); if (delay != TimeSpan.Zero) { RelayTraceSource.TraceVerbose($"Request MessageId:{OperationContext.Current.IncomingMessageHeaders.MessageId} delaying for {delay}"); Thread.Sleep(delay); } return(DefaultResponse ?? DateTime.UtcNow.ToString("o")); }
static async Task <bool> EnsureHybridConnectionExists(TraceSource traceSource, RelayConnectionStringBuilder connectionString, RelayNamespaceManager namespaceManager) { bool createdHybridConnection = false; try { traceSource.TraceVerbose($"Checking whether HybridConnection '{connectionString.EntityPath}' exists"); if (!await namespaceManager.HybridConnectionExistsAsync(connectionString.EntityPath)) { traceSource.TraceEvent(TraceEventType.Information, (int)ConsoleColor.White, $"Creating HybridConnection '{connectionString.EntityPath}'"); createdHybridConnection = true; await namespaceManager.CreateHybridConnectionAsync(new HybridConnectionDescription(connectionString.EntityPath)); traceSource.TraceInformation("Created"); } } catch (Exception exception) { RelayTraceSource.TraceException(exception, $"Ensuring HybridConnection '{connectionString.EntityPath}' exists"); } return(createdHybridConnection); }
static void ConfigureWcfCreateCommand(CommandLineApplication wcfCommand) { wcfCommand.RelayCommand("create", (createCmd) => { createCmd.Description = "Create a WcfRelay"; var pathArgument = createCmd.Argument("path", "WcfRelay path"); var connectionStringArgument = createCmd.Argument("connectionString", "Relay ConnectionString"); var relayTypeOption = createCmd.Option( "-t|--relaytype <relaytype>", "The RelayType (nettcp|http)", CommandOptionType.SingleValue); var requireClientAuthOption = createCmd.Option( CommandStrings.RequiresClientAuthTemplate, CommandStrings.RequiresClientAuthDescription, CommandOptionType.SingleValue); var protocolOption = createCmd.AddSecurityProtocolOption(); createCmd.OnExecute(async() => { ConfigureSecurityProtocol(protocolOption); string connectionString = ConnectionStringUtility.ResolveConnectionString(connectionStringArgument); if (string.IsNullOrEmpty(connectionString) || string.IsNullOrEmpty(pathArgument.Value)) { TraceMissingArgument(string.IsNullOrEmpty(connectionString) ? connectionStringArgument.Name : pathArgument.Name); createCmd.ShowHelp(); return(1); } var connectionStringBuilder = new ServiceBusConnectionStringBuilder(connectionString); RelayTraceSource.TraceInfo($"Creating WcfRelay '{pathArgument.Value}' in {connectionStringBuilder.Endpoints.First().Host}..."); var relayDescription = new RelayDescription(pathArgument.Value, GetRelayType(relayTypeOption)); relayDescription.RequiresClientAuthorization = GetBoolOption(requireClientAuthOption, true); var namespaceManager = NamespaceManager.CreateFromConnectionString(connectionString); await namespaceManager.CreateRelayAsync(relayDescription); RelayTraceSource.TraceInfo($"Creating WcfRelay '{pathArgument.Value}' in {connectionStringBuilder.Endpoints.First().Host} succeeded"); return(0); }); }); }
static async void RunAcceptPump(HybridConnectionListener listener) { while (true) { try { HybridConnectionStream stream = await listener.AcceptConnectionAsync(); if (stream == null) { return; } string connectionName = $"L:HybridConnectionStream({stream.TrackingContext.TrackingId})"; RelayTraceSource.TraceInfo($"{connectionName} accepted"); RunConnectionPump(stream, connectionName, echoBytes: true); } catch (Exception exception) { RelayTraceSource.TraceException(exception, nameof(RunAcceptPump)); await Task.Delay(TimeSpan.FromMilliseconds(100)); } } }
static async void RunConnectionPump(HybridConnectionStream stream, string connectionName, bool echoBytes = false) { try { var buffer = new byte[256]; while (true) { int read = await stream.ReadAsync(buffer, 0, buffer.Length); RelayTraceSource.TraceVerbose($"{connectionName} received {read} bytes: \"{Encoding.UTF8.GetString(buffer, 0, read)}\""); if (read == 0) { using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10))) { RelayTraceSource.TraceVerbose($"{connectionName} closing"); await stream.CloseAsync(cts.Token); RelayTraceSource.TraceInfo($"{connectionName} closed"); } return; } if (echoBytes) { await stream.WriteAsync(buffer, 0, read); RelayTraceSource.TraceVerbose($"{connectionName} echoed {read} bytes"); } } } catch (Exception exception) { RelayTraceSource.TraceException(exception, nameof(RunConnectionPump)); } }
public void Dispose() { RelayTraceSource.TraceVerbose($"{nameof(EchoService)} instance disposed. TrackingId:{this.trackingId}"); }
internal static async Task VerifySendAsync(RelayConnectionStringBuilder connectionString, int number, string httpMethod, string requestData, TraceSource traceSource) { Uri hybridHttpUri = new Uri($"https://{connectionString.Endpoint.GetComponents(UriComponents.HostAndPort, UriFormat.SafeUnescaped)}/{connectionString.EntityPath}"); var tokenProvider = GetTokenProvider(connectionString); if (string.Equals("WS", httpMethod, StringComparison.OrdinalIgnoreCase) || string.Equals("WEBSOCKET", httpMethod, StringComparison.OrdinalIgnoreCase)) { var client = new HybridConnectionClient(connectionString.ToString()); var requestBytes = Encoding.UTF8.GetBytes(requestData ?? string.Empty); HybridConnectionStream stream = await client.CreateConnectionAsync(); string connectionName = $"S:HybridConnectionStream({stream.TrackingContext.TrackingId})"; RelayTraceSource.TraceInfo($"{connectionName} initiated"); RunConnectionPump(stream, connectionName); for (int i = 0; i < number; i++) { await stream.WriteAsync(requestBytes, 0, requestBytes.Length); RelayTraceSource.TraceVerbose($"{connectionName} wrote {requestBytes.Length} bytes"); } await Task.Delay(TimeSpan.FromSeconds(1)); using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5))) { RelayTraceSource.TraceVerbose($"{connectionName} closing"); await stream.CloseAsync(cts.Token); RelayTraceSource.TraceInfo($"{connectionName} closed"); } return; } string token = null; if (tokenProvider != null) { token = (await tokenProvider.GetTokenAsync(hybridHttpUri.AbsoluteUri, TimeSpan.FromDays(2))).TokenString; } var stopwatch = new Stopwatch(); using (var client = new HttpClient { BaseAddress = hybridHttpUri }) { client.DefaultRequestHeaders.ExpectContinue = false; for (int i = 0; i < number; i++) { stopwatch.Restart(); var httpRequest = new HttpRequestMessage(); if (token != null) { httpRequest.Headers.Add("ServiceBusAuthorization", token); } httpRequest.Method = new HttpMethod(httpMethod); if (requestData != null) { httpRequest.Content = new StringContent(requestData); } LogHttpRequest(httpRequest, client, traceSource); using (HttpResponseMessage response = await client.SendAsync(httpRequest)) { LogHttpResponse(response, traceSource); } traceSource.TraceInformation($"Elapsed: {stopwatch.ElapsedMilliseconds} ms"); } } }
static int VerifySendCore <TChannel>( string request, string relayNamespace, string path, int number, Binding binding, bool noClientAuth, ConnectivityMode connectivityMode, string keyName, string keyValue, TimeSpan requestDelay) where TChannel : class, IClientChannel { ChannelFactory <TChannel> channelFactory = null; TChannel channel = null; try { ServiceBusEnvironment.SystemConnectivity.Mode = connectivityMode; Uri address = new Uri($"{binding.Scheme}://{relayNamespace}/{path}"); if (binding is WebHttpRelayBinding) { channelFactory = new WebChannelFactory <TChannel>(binding, address); } else { channelFactory = new ChannelFactory <TChannel>(binding, new EndpointAddress(address)); } var tp = TokenProvider.CreateSharedAccessSignatureTokenProvider(keyName, keyValue); if (!noClientAuth) { channelFactory.Endpoint.EndpointBehaviors.Add(new TransportClientEndpointBehavior(tp)); } RelayTraceSource.TraceVerbose("Sender opening channel factory"); var stopwatch = new Stopwatch(); stopwatch.Restart(); channelFactory.Open(); RelayTraceSource.TraceVerbose($"Sender opened channel factory in {stopwatch.ElapsedMilliseconds} ms"); channel = channelFactory.CreateChannel(); RelayTraceSource.TraceInfo("Sender opening channel"); using (new OperationContextScope(channel)) { Guid trackingId = Guid.NewGuid(); RelayTraceSource.TraceVerbose($"Channel TrackingId:{trackingId}"); if (binding.MessageVersion.Addressing != AddressingVersion.None) { OperationContext.Current.OutgoingMessageHeaders.MessageId = new UniqueId(trackingId); } stopwatch.Restart(); channel.Open(); RelayTraceSource.TraceVerbose($"Sender opened channel in {stopwatch.ElapsedMilliseconds} ms"); RelayTraceSource.TraceVerbose($"Channel SessionId:{channel.SessionId}"); } for (int i = 0; i < number; i++) { using (new OperationContextScope(channel)) { var messageId = Guid.NewGuid(); RelayTraceSource.TraceVerbose($"Sending MessageId:{messageId}"); if (binding.MessageVersion.Addressing != AddressingVersion.None) { OperationContext.Current.OutgoingMessageHeaders.MessageId = new UniqueId(messageId); } stopwatch.Restart(); if (channel is IEchoClient echoChannel) { string response = echoChannel.Echo(DateTime.UtcNow, request, requestDelay); RelayTraceSource.TraceInfo($"Sender received response: {response} ({stopwatch.ElapsedMilliseconds} ms)"); } else if (channel is ITestOnewayClient onewayClient) { onewayClient.Operation(DateTime.UtcNow, request); RelayTraceSource.TraceInfo($"Sender sent oneway request: {request} ({stopwatch.ElapsedMilliseconds} ms)"); } else { throw new NotSupportedException($"Contract {typeof(TChannel)} is not supported"); } } } RelayTraceSource.TraceInfo("Sender closing channel"); stopwatch.Restart(); channel.Close(); RelayTraceSource.TraceVerbose($"Sender closed channel in {stopwatch.ElapsedMilliseconds} ms"); channel = null; RelayTraceSource.TraceVerbose("Sender closing channel factory"); stopwatch.Restart(); channelFactory.Close(); RelayTraceSource.TraceVerbose($"Sender closed channel factory in {stopwatch.ElapsedMilliseconds} ms"); channelFactory = null; return(0); } finally { channel?.Abort(); channelFactory?.Abort(); } }
public static async Task <int> VerifyListenAsync(TraceSource traceSource, RelayConnectionStringBuilder connectionString, string responseBody, int responseChunkLength, HttpStatusCode statusCode, string statusDescription) { var namespaceManager = new RelayNamespaceManager(connectionString.ToString()); bool createdHybridConnection = await EnsureHybridConnectionExists(traceSource, connectionString, namespaceManager); HybridConnectionListener listener = null; try { listener = new HybridConnectionListener(connectionString.ToString()); listener.Connecting += (s, e) => RelayTraceSource.TraceException(listener.LastError, TraceEventType.Warning, "HybridConnectionListener Re-Connecting"); listener.Online += (s, e) => RelayTraceSource.Instance.TraceEvent(TraceEventType.Information, (int)ConsoleColor.Green, "HybridConnectionListener is online"); EventHandler offlineHandler = (s, e) => RelayTraceSource.TraceException(listener.LastError, "HybridConnectionListener is OFFLINE"); listener.Offline += offlineHandler; var responseBytes = Encoding.UTF8.GetBytes(responseBody); listener.RequestHandler = async(context) => { try { var stopwatch = new Stopwatch(); LogHttpRequest(context, traceSource); context.Response.StatusCode = statusCode; if (statusDescription != null) { context.Response.StatusDescription = statusDescription; } context.Response.Headers[HttpResponseHeader.ContentType] = "text/html"; int bytesWritten = 0; do { int countToWrite = Math.Min(responseBody.Length - bytesWritten, responseChunkLength); stopwatch.Restart(); await context.Response.OutputStream.WriteAsync(responseBytes, bytesWritten, countToWrite); bytesWritten += countToWrite; traceSource.TraceEvent(TraceEventType.Verbose, 0, "Sent {0} bytes in {1} ms", countToWrite, stopwatch.ElapsedMilliseconds); }while (bytesWritten < responseBody.Length); stopwatch.Restart(); await context.Response.CloseAsync(); traceSource.TraceEvent(TraceEventType.Verbose, 0, "Close completed in {0} ms", stopwatch.ElapsedMilliseconds); } catch (Exception exception) { RelayTraceSource.TraceException(exception, $"RequestHandler Error"); } }; traceSource.TraceInformation($"Opening {listener}"); await listener.OpenAsync(); RunAcceptPump(listener); traceSource.TraceInformation("Press <ENTER> to close the listener "); Console.ReadLine(); traceSource.TraceInformation($"Closing {listener}"); listener.Offline -= offlineHandler; // Avoid a spurious trace on expected shutdown. await listener.CloseAsync(); traceSource.TraceInformation("Closed"); return(0); } catch (Exception) { listener?.CloseAsync(); throw; } finally { if (createdHybridConnection) { try { traceSource.TraceEvent(TraceEventType.Information, (int)ConsoleColor.White, $"Deleting HybridConnection '{connectionString.EntityPath}'"); await namespaceManager.DeleteHybridConnectionAsync(connectionString.EntityPath); traceSource.TraceInformation("Deleted"); } catch (Exception exception) { RelayTraceSource.TraceException(exception, "Deleting HybridConnection"); } } } }
public static async Task <int> RunTestsAsync(RelayConnectionStringBuilder connectionString, TraceSource traceSource) { if (string.IsNullOrEmpty(connectionString.EntityPath)) { connectionString.EntityPath = HybridConnectionCommands.DefaultPath; } var namespaceManager = new RelayNamespaceManager(connectionString.ToString()); namespaceManager.Settings.OperationTimeout = TimeSpan.FromSeconds(5); HybridConnectionListener listener = null; bool createdHybridConnection = false; int returnCode = 0; var testResults = new List <TestResult>(); var cts = new CancellationTokenSource(TimeSpan.FromSeconds(70)); try { createdHybridConnection = await EnsureHybridConnectionExists(traceSource, connectionString, namespaceManager); listener = new HybridConnectionListener(connectionString.ToString()); traceSource.TraceInformation($"Opening {listener}"); await listener.OpenAsync(cts.Token); traceSource.TraceInformation("Listener Opened"); Uri hybridHttpUri = new Uri($"https://{connectionString.Endpoint.GetComponents(UriComponents.HostAndPort, UriFormat.SafeUnescaped)}/{connectionString.EntityPath}"); var token = await listener.TokenProvider.GetTokenAsync(hybridHttpUri.AbsoluteUri, TimeSpan.FromMinutes(20)); using (var client = new HttpClient { BaseAddress = hybridHttpUri }) { client.DefaultRequestHeaders.ExpectContinue = false; await RunTestAsync("TestPostLargeRequestSmallResponse", null, testResults, () => TestPostLargeRequestSmallResponse(listener, token, client, traceSource)); await RunTestAsync("TestPostLargeRequestWithLargeResponse", null, testResults, () => TestPostLargeRequestWithLargeResponse(listener, token, client, traceSource)); await RunTestAsync("TestGetLargeResponse", null, testResults, () => TestGetLargeResponse(listener, token, client, traceSource)); await RunTestAsync("TestGetSmallResponse", null, testResults, () => TestGetSmallResponse(listener, token, client, traceSource)); } await RunTestAsync("TestStreaming", null, testResults, () => TestStreaming(listener, connectionString, traceSource)); returnCode = ReportTestResults(testResults); } catch (Exception exception) { traceSource.TraceError("FAILURE WHILE RUNNING TESTS"); RelayTraceSource.TraceException(exception, nameof(HybridConnectionTests)); returnCode = exception.HResult; } finally { cts.Dispose(); var cleanupCancelSource = new CancellationTokenSource(TimeSpan.FromSeconds(10)); try { if (listener != null) { traceSource.TraceInformation($"Closing {listener}"); await listener.CloseAsync(cleanupCancelSource.Token); traceSource.TraceInformation("Listener Closed"); } if (createdHybridConnection) { traceSource.TraceEvent(TraceEventType.Information, (int)ConsoleColor.White, $"Deleting HybridConnection '{connectionString.EntityPath}'"); await namespaceManager.DeleteHybridConnectionAsync(connectionString.EntityPath); } } catch (Exception cleanupException) { traceSource.TraceWarning($"Error during cleanup: {cleanupException.GetType()}: {cleanupException.Message}"); } finally { cleanupCancelSource.Dispose(); } } return(returnCode); }