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); }); }); }
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 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 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 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)); } }
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 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(); } }
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"); } } }