Example #1
0
        /// <summary>
        /// Create an send-side HybridConnectionStream, send N bytes to it, receive N bytes response from it,
        /// then close the HybridConnectionStream.
        /// </summary>
        async Task RunEchoClientAsync(HybridConnectionStream clientStream, int byteCount)
        {
            var cancelSource = new CancellationTokenSource(TimeSpan.FromSeconds(20));

            try
            {
                byte[] sendBuffer = this.CreateBuffer(byteCount, new[] { (byte)(byteCount % byte.MaxValue) });
                await clientStream.WriteAsync(sendBuffer, 0, sendBuffer.Length, cancelSource.Token);

                byte[] readBuffer = new byte[sendBuffer.Length + 10];
                int    bytesRead  = await clientStream.ReadAsync(readBuffer, 0, readBuffer.Length, cancelSource.Token);

                Assert.Equal(sendBuffer.Length, bytesRead);

                await clientStream.CloseAsync(cancelSource.Token);
            }
            catch (Exception e)
            {
                TestUtility.Log($"[byteCount={byteCount}] {e.GetType().Name}: {e.Message}");
                await clientStream.CloseAsync(cancelSource.Token);

                throw;
            }
            finally
            {
                cancelSource.Dispose();
            }
        }
        private async void ProcessMessage(HybridConnectionStream relayConnection, CancellationTokenSource cts)
        {
            // Bi-directional streams for read and write to the relay
            var reader = new StreamReader(relayConnection);
            var writer = new StreamWriter(relayConnection)
            {
                AutoFlush = true
            };

            while (!cts.IsCancellationRequested)
            {
                // Read a message in input from the relay
                var message = await reader.ReadToEndAsync();

                // Resolve address by invoking a service on the GIS server
                GisObject gisObject = JsonConvert.DeserializeObject <GisObject>(message);
                await new GisServer().ResolveAddressAsync(gisObject);

                // Write the message back to the relay
                message = JsonConvert.SerializeObject(gisObject);
                await writer.WriteLineAsync(message);
            }

            await relayConnection.CloseAsync(cts.Token);
        }
Example #3
0
        private async void ProcessMessagesOnConnection(HybridConnectionStream connection, CancellationToken token)
        {
            try
            {
                try
                {
                    try
                    {
                        while (!token.IsCancellationRequested)
                        {
                            IFeatureCollection features = await _featureSerializerManager.ReadAsync(connection, new[] { typeof(IHttpRequestFeature) }, token);

                            PrepareDefaultFeatures(features);

                            await _requestReceivedCallback(features, token);

                            await _featureSerializerManager.WriteAsync(connection, features, new[] { typeof(IHttpResponseFeature) }, token);
                        }
                    }
                    finally
                    {
                        await connection.ShutdownAsync(token);
                    }
                }
                catch (IOException)
                { }
                catch (RelayException)
                { }
            }
            finally
            {
                await connection.CloseAsync(token);
            }
        }
        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));
        }
Example #5
0
        private static async void ProcessMessagesOnConnection(HybridConnectionStream relayConnection, CancellationTokenSource cts)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("New session established...");
            Console.ForegroundColor = ConsoleColor.White;

            // The connection is a fully bidrectional stream.
            // We put a stream reader and a stream writer over it
            // which allows us to read UTF-8 text that comes from
            // the sender and to write text replies back.
            var reader = new StreamReader(relayConnection);
            var writer = new StreamWriter(relayConnection)
            {
                AutoFlush = true
            };

            // Write the line back to the client, prepending "Echo:"
            await writer.WriteLineAsync("Hello client from the server!");

            while (!cts.IsCancellationRequested)
            {
                try
                {
                    // Read a line of input until a newline is encountered
                    var line = await reader.ReadLineAsync();

                    if (string.IsNullOrEmpty(line))
                    {
                        // If there's no input data, we will signal that
                        // we will no longer send data on this connection
                        // and then break out of the processing loop.
                        await relayConnection.ShutdownAsync(cts.Token);

                        break;
                    }

                    // Output the line on the console
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine("Received from client: " + line);
                    Console.ForegroundColor = ConsoleColor.White;

                    // Write the line back to the client, prepending "Echo:"
                    await writer.WriteLineAsync($"Thanks for sending: {line}");
                }
                catch (Exception ex)
                {
                    // Catch an IO exception that is likely caused because
                    // the client disconnected.
                    Console.WriteLine("Looks like the client closed connection...");
                    break;
                }
            }

            Console.WriteLine("Session ended with client...");

            // Closing the connection
            await relayConnection.CloseAsync(cts.Token);
        }
Example #6
0
        static async Task CloseConnection(HybridConnectionStream hybridConnectionStream)
        {
            using (var cts = new CancellationTokenSource(TimeSpan.FromMinutes(1)))
            {
                await hybridConnectionStream.ShutdownAsync(cts.Token);

                await hybridConnectionStream.CloseAsync(cts.Token);
            }
        }
        /// <summary>
        /// We run two concurrent loops on the connection. One reads input from the console and writes it to the connection
        /// with a stream writer. The other reads lines of input from the connection with a stream reader and writes them to the console.
        /// Entering a blank line will shut down the write task after sending it to the server. The server will then cleanly shut down
        /// the connection which will terminate the read task.
        /// </summary>
        /// <returns></returns>
        protected async Task RunAsync()
        {
            // Initiate the connection
            _relayConnection = await _client.CreateConnectionAsync();

            var reads = GetReads(_relayConnection);

            // Wait for both tasks to complete
            await Task.WhenAll(reads);

            await _relayConnection.CloseAsync(CancellationToken.None);
        }
        private static async void ProcessMessagesOnConnection(HybridConnectionStream relayConnection, CancellationTokenSource cts)
        {
            Console.WriteLine("New session");

            // The connection is a fully bidrectional stream.
            // Put a stream reader and a stream writer over it.
            // This allows you to read UTF-8 text that comes from
            // the sender, and to write text replies back.
            var reader = new StreamReader(relayConnection);
            var writer = new StreamWriter(relayConnection)
            {
                AutoFlush = true
            };

            while (!cts.IsCancellationRequested)
            {
                try
                {
                    // Read a line of input until a newline is encountered.
                    var line = await reader.ReadLineAsync();

                    if (string.IsNullOrEmpty(line))
                    {
                        // If there's no input data, signal that
                        // you will no longer send data on this connection.
                        // Then, break out of the processing loop.
                        await relayConnection.ShutdownAsync(cts.Token);

                        break;
                    }

                    // Write the line on the console.
                    Console.WriteLine(line);

                    // Write the line back to the client, prepended with "Echo:"
                    await writer.WriteLineAsync($"Echo: {line}");
                }
                catch (IOException)
                {
                    // Catch an I/O exception. This likely occurred when
                    // the client disconnected.
                    Console.WriteLine("Client closed connection");
                    break;
                }
            }

            Console.WriteLine("End session");

            // Close the connection.
            await relayConnection.CloseAsync(cts.Token);
        }
Example #9
0
        public async Task CloseAsync(CancellationToken token)
        {
            try
            {
                if (_connection == null)
                {
                    return;
                }
                await _connection.ShutdownAsync(token);

                await _connection.CloseAsync(token);
            }
            finally
            {
                IsOpen      = false;
                GoodStatus  = false;
                _connection = null;
            }
        }
Example #10
0
        private static async void ProcessMessagesOnConnection(HybridConnectionStream relayConnection,
                                                              CancellationTokenSource cts)
        {
            Console.WriteLine("New	session");
            //	The	connection	is	a	fully	bidrectional	stream, enabling	the	Listener
            //to	echo	the	text	from	the	Sender.
            var reader = new StreamReader(relayConnection);
            var writer = new StreamWriter(relayConnection)
            {
                AutoFlush = true
            };

            while (!cts.IsCancellationRequested)
            {
                try
                {
                    //	Read	a	line	of	input	until	a	newline	is encountered
                    var line = await reader.ReadLineAsync();

                    if (string.IsNullOrEmpty(line))
                    {
                        await relayConnection.ShutdownAsync(cts.Token);

                        break;
                    }

                    Console.WriteLine(line);
                    //	Echo	the	line	back	to	the	client
                    await writer.WriteLineAsync($"Echo:	{line}");
                }
                catch (IOException)
                {
                    Console.WriteLine("Client	closed	connection");
                    break;
                }
            }

            Console.WriteLine("End	session");
            //	Close	the	connection
            await relayConnection.CloseAsync(cts.Token);
        }
Example #11
0
        private static async void ProcessMessagesOnConnection(HybridConnectionStream relayConnection, CancellationTokenSource cts)
        {
            Console.WriteLine("New Session");

            var reader = new StreamReader(relayConnection);
            var writer = new StreamWriter(relayConnection)
            {
                AutoFlush = true
            };

            while (!cts.IsCancellationRequested)
            {
                try
                {
                    var line = reader.ReadLine();

                    if (string.IsNullOrEmpty(line))
                    {
                        await relayConnection.ShutdownAsync(cts.Token);

                        break;
                    }

                    Console.WriteLine(line);
                    await writer.WriteLineAsync($"Echo: {line}");
                }
                catch (IOException ex)
                {
                    Console.WriteLine(ex.Message);
                    break;
                }
            }

            Console.WriteLine("End session");
            await relayConnection.CloseAsync(cts.Token);
        }
        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));
            }
        }
Example #13
0
 public async Task CloseRelayStreamAsync()
 {
     await _relayStream.CloseAsync(CancellationToken.None);
 }
        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");
                }
            }
        }
Example #15
0
        static async Task Main(string[] args)
        {
            string hostAddress;
            string hybridConnectionName;
            string clientId     = null;
            string tenantId     = null;
            string clientSecret = null;
            RbacAuthenticationOption option;

            if (args.Length == 2)
            {
                option               = RbacAuthenticationOption.ManagedIdentity;
                hostAddress          = args[0];
                hybridConnectionName = args[1];
            }
            else if (args.Length == 3)
            {
                option               = RbacAuthenticationOption.UserAssignedIdentity;
                hostAddress          = args[0];
                hybridConnectionName = args[1];
                clientId             = args[2];
            }
            else if (args.Length == 5)
            {
                option               = RbacAuthenticationOption.AAD;
                hostAddress          = args[0];
                hybridConnectionName = args[1];
                clientId             = args[2];
                tenantId             = args[3];
                clientSecret         = args[4];
            }
            else
            {
                Console.WriteLine("Please run with parameters of the following format for the corresponding RBAC authentication method:");
                Console.WriteLine("System Managed Identity: [HostAddress] [HybridConnectionName]");
                Console.WriteLine("User Assigned Identity: [HostAddress] [HybridConnectionName] [ClientId]");
                Console.WriteLine("Azure Active Directory:  [HostAddress] [HybridConnectionName] [ClientId] [TenantId] [ClientSecret]");
                Console.WriteLine("Press <Enter> to exit...");
                Console.ReadLine();
                return;
            }

            TokenProvider tokenProvider = null;

            switch (option)
            {
            case RbacAuthenticationOption.ManagedIdentity:
                tokenProvider = TokenProvider.CreateManagedIdentityTokenProvider();
                break;

            case RbacAuthenticationOption.UserAssignedIdentity:
                var managedCredential = new ManagedIdentityCredential(clientId);
                tokenProvider = TokenProvider.CreateManagedIdentityTokenProvider(managedCredential);
                break;

            case RbacAuthenticationOption.AAD:
                tokenProvider = GetAadTokenProvider(clientId, tenantId, clientSecret);
                break;
            }

            var hybridConnectionUri           = new Uri($"{hostAddress}/{hybridConnectionName}");
            HybridConnectionListener listener = null;

            try
            {
                // The HybridConnection should be already created through Azure Portal or other means
                Console.WriteLine($"Creating the Relay listener instance with RBAC option: {option}");
                listener = new HybridConnectionListener(hybridConnectionUri, tokenProvider);

                await listener.OpenAsync(TimeSpan.FromSeconds(10));

                Console.WriteLine("Created and connected the Relay listener instance.");

                Console.WriteLine($"Creating the Relay sender instance with RBAC option: {option}");
                var sender             = new HybridConnectionClient(hybridConnectionUri, tokenProvider);
                var createSenderTask   = sender.CreateConnectionAsync();
                var listenerAcceptTask = listener.AcceptConnectionAsync();
                using (HybridConnectionStream senderStream = await createSenderTask)
                    using (HybridConnectionStream listenerStream = await listenerAcceptTask)
                    {
                        Console.WriteLine("Created and connected the Relay sender instance.");
                        var senderCloseTask = senderStream.CloseAsync(CancellationToken.None);
                        await listenerStream.CloseAsync(CancellationToken.None);

                        await senderCloseTask;
                    }

                // Configure a RequestHandler for HTTP request/response mode
                listener.RequestHandler = (context) =>
                {
                    context.Response.StatusCode = HttpStatusCode.OK;
                    using (var sw = new StreamWriter(context.Response.OutputStream))
                    {
                        sw.WriteLine("hello!");
                    }

                    // The context must be closed to complete sending the response
                    context.Response.Close();
                };

                Console.WriteLine($"Sending a HTTP request by setting the token in request header with RBAC option: {option}");
                SecurityToken token = await tokenProvider.GetTokenAsync(hybridConnectionUri.AbsoluteUri, TimeSpan.FromMinutes(30));

                var request = new HttpRequestMessage();
                request.Headers.Add(HttpRequestHeader.Authorization.ToString(), token.TokenString);
                var requestUri = new UriBuilder(hybridConnectionUri)
                {
                    Scheme = "https"
                }.Uri;
                using (HttpClient client = new HttpClient {
                    BaseAddress = requestUri
                })
                {
                    using (var response = await client.SendAsync(request))
                    {
                        Console.WriteLine($"Response status code: {response.StatusCode}. Response reason phrase: {response.ReasonPhrase}");
                    }
                }

                Console.WriteLine($"Sending a HTTP request by setting the token in query string with RBAC option: {option}");
                token = await tokenProvider.GetTokenAsync(hybridConnectionUri.AbsoluteUri, TimeSpan.FromMinutes(30));

                request    = new HttpRequestMessage();
                requestUri = new UriBuilder(requestUri)
                {
                    Query = $"?sb-hc-token={token.TokenString}"
                }.Uri;
                using (HttpClient client = new HttpClient {
                    BaseAddress = requestUri
                })
                {
                    using (var response = await client.SendAsync(request))
                    {
                        Console.WriteLine($"Response status code: {response.StatusCode}. Response reason phrase: {response.ReasonPhrase}");
                    }
                }

                Console.WriteLine("Press <Enter> to exit...");
                Console.ReadLine();
            }
            finally
            {
                if (listener != null)
                {
                    await listener.CloseAsync();
                }
            }
        }