예제 #1
0
        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);
                });
            });
        }
예제 #2
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);
                });
            });
        }
예제 #3
0
        public EchoService()
        {
            IContextChannel channel = OperationContext.Current?.Channel;

            this.trackingId = channel?.GetProperty <TrackingContext>()?.TrackingId;
            RelayTraceSource.TraceVerbose($"{nameof(EchoService)} instance created. TrackingId:{this.trackingId}");
        }
예제 #4
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));
        }
예제 #5
0
        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;
            }
        }
예제 #6
0
        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}");
        }
예제 #7
0
        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.");
            }
        }
예제 #8
0
        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));
                });
            });
        }
예제 #9
0
        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);
                });
            });
        }
예제 #10
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));
            }
        }
예제 #11
0
        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"));
        }
예제 #12
0
        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);
        }
예제 #13
0
        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);
                });
            });
        }
예제 #14
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));
                }
            }
        }
예제 #15
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));
            }
        }
예제 #16
0
 public void Dispose()
 {
     RelayTraceSource.TraceVerbose($"{nameof(EchoService)} instance disposed. TrackingId:{this.trackingId}");
 }
예제 #17
0
        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");
                }
            }
        }
예제 #18
0
        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();
            }
        }
예제 #19
0
        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");
                    }
                }
            }
        }
예제 #20
0
        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);
        }