public async Task <bool> ForwardToSkillAsync(ITurnContext turnContext, Activity activity, Action <Activity> tokenRequestHandler = null)
        {
            if (_streamingTransportClient == null)
            {
                // acquire AAD token
                MicrosoftAppCredentials.TrustServiceUrl(_skillManifest.Endpoint.AbsoluteUri);
                var token = await _serviceClientCredentials.GetTokenAsync();

                // put AAD token in the header
                var headers = new Dictionary <string, string>();
                headers.Add("Authorization", $"Bearer {token}");

                // establish websocket connection
                _streamingTransportClient = new WebSocketClient(
                    EnsureWebSocketUrl(_skillManifest.Endpoint.ToString()),
                    new SkillCallingRequestHandler(
                        turnContext,
                        GetTokenCallback(turnContext, tokenRequestHandler),
                        GetHandoffActivityCallback()),
                    headers);

                await _streamingTransportClient.ConnectAsync();
            }

            // Serialize the activity and POST to the Skill endpoint
            var body    = new StringContent(JsonConvert.SerializeObject(activity, SerializationSettings.BotSchemaSerializationSettings), Encoding.UTF8, SerializationSettings.ApplicationJson);
            var request = Request.CreatePost(string.Empty, body);
            await _streamingTransportClient.SendAsync(request);

            return(endOfConversation);
        }
        public async Task <Activity> ForwardToSkillAsync(SkillManifest skillManifest, IServiceClientCredentials serviceClientCredentials, ITurnContext turnContext, Activity activity, Action <Activity> tokenRequestHandler = null, Action <Activity> fallbackHandler = null)
        {
            if (_streamingTransportClient == null)
            {
                // establish websocket connection
                _streamingTransportClient = new WebSocketClient(
                    EnsureWebSocketUrl(skillManifest.Endpoint.ToString()),
                    new SkillCallingRequestHandler(
                        turnContext,
                        _botTelemetryClient,
                        GetTokenCallback(turnContext, tokenRequestHandler),
                        GetFallbackCallback(turnContext, fallbackHandler),
                        GetHandoffActivityCallback()));
            }

            // acquire AAD token
            MicrosoftAppCredentials.TrustServiceUrl(skillManifest.Endpoint.AbsoluteUri);
            var token = await serviceClientCredentials.GetTokenAsync();

            // put AAD token in the header
            var headers = new Dictionary <string, string>();

            headers.Add("Authorization", $"Bearer {token}");

            await _streamingTransportClient.ConnectAsync(headers);

            // set recipient to the skill
            var recipientId = activity.Recipient.Id;

            activity.Recipient.Id = skillManifest.MSAappId;

            // Serialize the activity and POST to the Skill endpoint
            var body    = new StringContent(JsonConvert.SerializeObject(activity, SerializationSettings.BotSchemaSerializationSettings), Encoding.UTF8, SerializationSettings.ApplicationJson);
            var request = StreamingRequest.CreatePost(string.Empty, body);

            // set back recipient id to make things consistent
            activity.Recipient.Id = recipientId;

            var stopWatch = new System.Diagnostics.Stopwatch();

            stopWatch.Start();
            await _streamingTransportClient.SendAsync(request);

            stopWatch.Stop();

            _botTelemetryClient.TrackEvent(
                "SkillWebSocketTurnLatency",
                new Dictionary <string, string>
            {
                { "SkillName", skillManifest.Name },
                { "SkillEndpoint", skillManifest.Endpoint.ToString() },
            },
                new Dictionary <string, double>
            {
                { "Latency", stopWatch.ElapsedMilliseconds },
            });

            return(_handoffActivity);
        }
        private static void SimulateMultiTurnConversation(int conversationId, Activity[] activities, IStreamingTransportClient client, ILogger logger, SemaphoreSlim throttler = null)
        {
            try
            {
                foreach (var activity in activities)
                {
                    var timer = Stopwatch.StartNew();

                    var content  = new StringContent(JsonConvert.SerializeObject(activity), Encoding.UTF8, "application/json");
                    var response = client.SendAsync(StreamingRequest.CreatePost("/api/messages", content)).Result;

                    logger.LogInformation($"Conversation {conversationId} latency: {timer.ElapsedMilliseconds}. Status code: {response.StatusCode}");
                }
            }
            finally
            {
                if (throttler != null)
                {
                    throttler.Release();
                }
            }
        }