public bool CanStartAdhocMeeting(IMessagingInvitation invitation)
        {
            #pragma warning disable CS0618 // Type or member is obsolete
            return(invitation.Supports(MessagingInvitationCapability.StartAdhocMeeting));

            #pragma warning restore CS0618 // Type or member is obsolete
        }
示例#2
0
        public async Task EstalbishAsyncInviteShouldCompleteOnlyOnCompletedEvent()
        {
            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_MessagingDisconnected.json");

            // Save OperationId of the MessagingInvitation when HTTP request is made to start the invitation.
            string operationId = null;

            m_restfulClient.HandleRequestProcessed += (sender, args) =>
            {
                if (args.Uri == new Uri(DataUrls.EstablishMessagingCall) && args.Method == HttpMethod.Post && args.Input is InvitationInput)
                {
                    // We need to replace operationContext in invitation completed event with what was provided in the input
                    operationId = ((InvitationInput)args.Input).OperationContext;
                }
            };

            // Start MessagingInvitation
            var inviteCompleted         = false;
            IMessagingInvitation invite = await m_messagingCall.EstablishAsync(m_loggingContext).ConfigureAwait(false);

            invite.HandleResourceCompleted += (sender, args) => inviteCompleted = true;

            await Task.Delay(TimeSpan.FromMilliseconds(300)).ConfigureAwait(false);

            // Make sure invitation is not completed
            Assert.IsFalse(inviteCompleted);
            Assert.IsFalse(string.IsNullOrEmpty(operationId));

            // When
            TestHelper.RaiseEventsFromFileWithOperationId(m_mockEventChannel, "Event_MessagingInvitationCompleted.json", operationId);

            // then
            Assert.IsTrue(inviteCompleted);
        }
        public async void TestSetup()
        {
            m_loggingContext = new LoggingContext(Guid.NewGuid());
            var data = TestHelper.CreateApplicationEndpoint();

            m_restfulClient = data.RestfulClient;
            m_eventChannel  = data.EventChannel;

            await data.ApplicationEndpoint.InitializeAsync(m_loggingContext).ConfigureAwait(false);

            await data.ApplicationEndpoint.InitializeApplicationAsync(m_loggingContext).ConfigureAwait(false);

            var communication = data.ApplicationEndpoint.Application.Communication;

            m_restfulClient.HandleRequestProcessed += (sender, args) =>
            {
                // Deliver invitation started events
                TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.MessagingInvitations, HttpMethod.Post, "Event_MessagingInvitationStarted.json", m_eventChannel);
                TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.AudioInvitations, HttpMethod.Post, "Event_AudioInvitationStarted.json", m_eventChannel);
                TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.AudioVideoInvitations, HttpMethod.Post, "Event_AudioVideoInvitationStarted.json", m_eventChannel);

                // Deliver conversation deleted event
                TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.Conversation, HttpMethod.Delete, "Event_ConversationDeleted.json", m_eventChannel);
            };

            // Start a conversation with messaging modality
            IMessagingInvitation invitation = await communication
                                              .StartMessagingAsync("Test message", new SipUri("sip:[email protected]"), "https://example.com/callback")
                                              .ConfigureAwait(false);

            m_conversation = invitation.RelatedConversation;
        }
示例#4
0
        public async Task StartAdhocMeetingShouldReturnATaskToWaitForInvitationStartedEvent()
        {
            // Given
            m_messagingInvitation = await StartIncomingMessagingInvitationAsync("Event_IncomingIMCall.json").ConfigureAwait(false);

            var invitationOperationid = string.Empty;

            m_restfulClient.HandleRequestProcessed += (sender, args) =>
            {
                string operationId = TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.StartAdhocMeeting, HttpMethod.Post, null, null);
                if (!string.IsNullOrEmpty(operationId))
                {
                    invitationOperationid = operationId;
                }
            };

            Task invitationTask = m_messagingInvitation.StartAdhocMeetingAsync("Test subject", "https://example.com/callback", m_loggingContext);
            await Task.Delay(TimeSpan.FromMilliseconds(200)).ConfigureAwait(false);

            Assert.IsFalse(invitationTask.IsCompleted);

            // When
            TestHelper.RaiseEventsFromFileWithOperationId(m_mockEventChannel, "Event_OnlineMeetingInvitationStarted.json", invitationOperationid);

            // Then
            Assert.IsTrue(invitationTask.IsCompleted);
        }
        public async void TestSetup()
        {
            m_loggingContext = new LoggingContext(Guid.NewGuid());
            var data = TestHelper.CreateApplicationEndpoint();

            m_mockEventChannel = data.EventChannel;
            m_restfulClient    = data.RestfulClient;

            ApplicationEndpoint applicationEndpoint = data.ApplicationEndpoint;
            await applicationEndpoint.InitializeAsync(m_loggingContext).ConfigureAwait(false);

            await applicationEndpoint.InitializeApplicationAsync(m_loggingContext).ConfigureAwait(false);

            m_restfulClient.HandleRequestProcessed += (sender, args) =>
            {
                TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.MessagingInvitations, HttpMethod.Post, "Event_MessagingInvitationStarted.json", m_mockEventChannel);
                TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.MessagingInvitations, HttpMethod.Post, "Event_ConversationConnected.json", m_mockEventChannel);
                TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.MessagingInvitations, HttpMethod.Post, "Event_ParticipantAdded.json", m_mockEventChannel);
            };

            IMessagingInvitation invitation = await applicationEndpoint.Application.Communication
                                              .StartMessagingAsync("Test subject", new SipUri("sip:[email protected]"), "https://example.com/callback", m_loggingContext)
                                              .ConfigureAwait(false);

            m_conversation = invitation.RelatedConversation;
        }
        public async void TestSetup()
        {
            m_loggingContext = new LoggingContext(Guid.NewGuid());
            var data = TestHelper.CreateApplicationEndpoint();

            m_restfulClient = data.RestfulClient;
            m_eventChannel  = data.EventChannel;

            await data.ApplicationEndpoint.InitializeAsync(m_loggingContext).ConfigureAwait(false);

            await data.ApplicationEndpoint.InitializeApplicationAsync(m_loggingContext).ConfigureAwait(false);

            var communication = data.ApplicationEndpoint.Application.Communication;

            m_restfulClient.HandleRequestProcessed +=
                (sender, args) => TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.MessagingInvitations, HttpMethod.Post, "Event_MessagingInvitationStarted.json", m_eventChannel);

            // Start a conversation with messaging modality
            IMessagingInvitation invitation = await communication
                                              .StartMessagingWithIdentityAsync("Test message", "sip:[email protected]", "https://example.com/callback", "Test user 1", "sip:[email protected]")
                                              .ConfigureAwait(false);

            TestHelper.RaiseEventsFromFile(m_eventChannel, "Event_ConversationConferenceAdded.json");
            TestHelper.RaiseEventsFromFile(m_eventChannel, "Event_ConversationConferenced.json");

            m_conversationConference = invitation.RelatedConversation.ConversationConference;
        }
示例#7
0
        public async void TestSetup()
        {
            m_loggingContext = new LoggingContext(Guid.NewGuid());
            var data = TestHelper.CreateApplicationEndpoint();

            m_mockEventChannel = data.EventChannel;
            m_restfulClient    = data.RestfulClient;

            m_applicationEndpoint = data.ApplicationEndpoint;
            await m_applicationEndpoint.InitializeAsync(m_loggingContext).ConfigureAwait(false);

            await m_applicationEndpoint.InitializeApplicationAsync(m_loggingContext).ConfigureAwait(false);

            ICommunication communication = m_applicationEndpoint.Application.Communication;

            m_restfulClient.HandleRequestProcessed += (sender, args) =>
            {
                TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.MessagingInvitations, HttpMethod.Post, "Event_MessagingInvitationStarted.json", m_mockEventChannel);
                TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.EstablishMessagingCall, HttpMethod.Post, "Event_MessagingInvitationStarted.json", m_mockEventChannel);
            };

            // Start a messaging invitation
            m_messagingInvitation = await communication.StartMessagingWithIdentityAsync(
                "Test subject",
                "sip:[email protected]",
                "https://example.com/callback",
                "Local user",
                "sip:[email protected]",
                m_loggingContext);
        }
示例#8
0
        public async Task AcceptAndBridgeAsyncShouldWorkWithNullLoggingContext()
        {
            // Given
            m_messagingInvitation = await StartIncomingMessagingInvitationAsync("Event_IncomingIMCall.json").ConfigureAwait(false);

            // When
            await m_messagingInvitation.AcceptAndBridgeAsync(null, "https://example.com", "Example User").ConfigureAwait(false);

            // Then
            // No exception is thrown
        }
示例#9
0
        public async Task AcceptAndBridgeAsyncShouldMakeHttpRequest()
        {
            // Given
            m_messagingInvitation = await StartIncomingMessagingInvitationAsync("Event_IncomingIMCall.json").ConfigureAwait(false);

            // When
            await m_messagingInvitation.AcceptAndBridgeAsync(m_loggingContext, "https://example.com", "Example User").ConfigureAwait(false);

            // Then
            Assert.IsTrue(m_restfulClient.RequestsProcessed("POST " + DataUrls.AcceptAndBridge));
        }
示例#10
0
        public async Task AcceptAndBridgeAsyncShouldThrowIfCapabilityNotAvailable()
        {
            // Given
            m_messagingInvitation = await StartIncomingMessagingInvitationAsync("Event_IncomingIMCall_NoActionLinks.json").ConfigureAwait(false);

            // When
            await m_messagingInvitation.AcceptAndBridgeAsync(m_loggingContext, "https://example.com", "Example User").ConfigureAwait(false);

            // Then
            // Exception is thrown
        }
示例#11
0
        public async Task AcceptAndBridgeAsyncShouldThrowIfMeetingUrlIsWhitespaces()
        {
            // Given
            m_messagingInvitation = await StartIncomingMessagingInvitationAsync("Event_IncomingIMCall.json").ConfigureAwait(false);

            // When
            await m_messagingInvitation.AcceptAndBridgeAsync(m_loggingContext, "   ", "Example User").ConfigureAwait(false);

            // Then
            // Exception is thrown
        }
示例#12
0
        public async Task ShouldSupportStartAdhocMeetingIfLinkAvailable()
        {
            // Given
            m_messagingInvitation = await StartIncomingMessagingInvitationAsync("Event_IncomingIMCall.json").ConfigureAwait(false);

            // When
            bool supported = m_messagingInvitation.Supports(MessagingInvitationCapability.StartAdhocMeeting);

            // Then
            Assert.IsTrue(supported);
        }
示例#13
0
        public async Task ShouldNotSupportAcceptAndBridgeIfLinkNotAvailable()
        {
            // Given
            m_messagingInvitation = await StartIncomingMessagingInvitationAsync("Event_IncomingIMCall_NoActionLinks.json").ConfigureAwait(false);

            // When
            bool supported = m_messagingInvitation.Supports(MessagingInvitationCapability.AcceptAndBridge);

            // Then
            Assert.IsFalse(supported);
        }
示例#14
0
        public async Task StartAdhocMeetingShouldThrowIfCapabilityNotAvailable()
        {
            // Given
            m_messagingInvitation = await StartIncomingMessagingInvitationAsync("Event_IncomingIMCall_NoActionLinks.json").ConfigureAwait(false);

            // When
            await m_messagingInvitation.StartAdhocMeetingAsync("Test subject", "https://example.com/callback", m_loggingContext).ConfigureAwait(false);

            // Then
            // Exception is thrown
        }
示例#15
0
        public async Task StartAdhocMeetingShouldThrowIfAdhocMeetingStartedEventNotReceived()
        {
            // Given
            m_messagingInvitation = await StartIncomingMessagingInvitationAsync("Event_IncomingIMCall.json").ConfigureAwait(false);

            ((MessagingInvitation)m_messagingInvitation).WaitForEvents = TimeSpan.FromMilliseconds(300);

            // When
            await m_messagingInvitation.StartAdhocMeetingAsync("Test subject", "https://example.com/callback", m_loggingContext).ConfigureAwait(false);

            // Then
            // Exception is thrown
        }
        public async Task StartAdhocMeetingShouldMakeTheHttpRequest()
        {
            // Given
            m_messagingInvitation = await StartIncomingMessagingInvitationAsync("Event_IncomingIMCall.json").ConfigureAwait(false);

            m_restfulClient.HandleRequestProcessed +=
                (sender, args) => TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.StartAdhocMeeting, HttpMethod.Post, "Event_OnlineMeetingInvitationStarted.json", m_mockEventChannel);

            // When
            await m_messagingInvitation.StartAdhocMeetingAsync("Test subject", "https://example.com/callback", m_loggingContext).ConfigureAwait(false);

            // Then
            Assert.IsTrue(m_restfulClient.RequestsProcessed("POST " + DataUrls.StartAdhocMeeting));
        }
        public async Task StartAdhocMeetingShouldWorkWithNullLoggingContext()
        {
            // Given
            m_messagingInvitation = await StartIncomingMessagingInvitationAsync("Event_IncomingIMCall.json").ConfigureAwait(false);

            m_restfulClient.HandleRequestProcessed +=
                (sender, args) => TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.StartAdhocMeeting, HttpMethod.Post, "Event_OnlineMeetingInvitationStarted.json", m_mockEventChannel);

            // When
            await m_messagingInvitation.StartAdhocMeetingAsync("Test subject", "https://example.com/callback", null).ConfigureAwait(false);

            // Then
            // No exception is thrown
        }
示例#18
0
        public async Task StartMessagingWithIdentityShouldWork()
        {
            // Given
            // If ClientModel starts a MessagingInvitation, delive the corresponding invitation started event.
            m_restfulClient.HandleRequestProcessed += (sender, args) => { TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.MessagingInvitations, HttpMethod.Post, "Event_MessagingInvitationStarted.json", m_eventChannel); };

            // When
            IMessagingInvitation invitation = await m_communication
                                              .StartMessagingWithIdentityAsync("Test message", "sip:[email protected]", "https://example.com/callback", "Test user 1", "sip:[email protected]")
                                              .ConfigureAwait(false);

            // Then
            Assert.IsNotNull(invitation);
            Assert.IsNotNull(invitation.RelatedConversation);
            Assert.IsTrue(m_restfulClient.RequestsProcessed("POST " + DataUrls.MessagingInvitations));
        }
示例#19
0
        public async Task StartMessagingShouldWork()
        {
            // Given
            m_restfulClient.OverrideResponse(new Uri(DataUrls.Communication), HttpMethod.Get, HttpStatusCode.OK, "Communication_WithStartMessaging.json");
            await m_communication.RefreshAsync(m_loggingContext).ConfigureAwait(false);

            // If ClientModel starts a MessagingInvitation, delive the corresponding invitation started event.
            m_restfulClient.HandleRequestProcessed += (sender, args) => { TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.MessagingInvitations, HttpMethod.Post, "Event_MessagingInvitationStarted.json", m_eventChannel); };

            // When
            IMessagingInvitation invitation = await m_communication.StartMessagingAsync("Test message", "sip:[email protected]", "https://example.com/callback").ConfigureAwait(false);

            // Then
            Assert.IsNotNull(invitation);
            Assert.IsNotNull(invitation.RelatedConversation);
            Assert.IsTrue(m_restfulClient.RequestsProcessed("POST " + DataUrls.MessagingInvitations));
        }
示例#20
0
        public async void TestSetup()
        {
            m_loggingContext = new LoggingContext(Guid.NewGuid());
            var data = TestHelper.CreateApplicationEndpoint();

            m_mockEventChannel = data.EventChannel;
            m_restfulClient    = data.RestfulClient;

            ApplicationEndpoint applicationEndpoint = data.ApplicationEndpoint;
            await applicationEndpoint.InitializeAsync(m_loggingContext).ConfigureAwait(false);

            await applicationEndpoint.InitializeApplicationAsync(m_loggingContext).ConfigureAwait(false);

            ICommunication communication = applicationEndpoint.Application.Communication;

            m_restfulClient.HandleRequestProcessed += (sender, args) =>
            {
                TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.MessagingInvitations, HttpMethod.Post, "Event_MessagingInvitationStarted.json", m_mockEventChannel);
                TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.EstablishMessagingCall, HttpMethod.Post, "Event_MessagingInvitationStarted.json", m_mockEventChannel);

                // Message completed event has to be delivered after the response, so start a new thread to wait some time before delivering the event
                if (m_deliverMessageCompletedEvent)
                {
                    Task.Run(async() =>
                    {
                        await Task.Delay(TimeSpan.FromMilliseconds(10)).ConfigureAwait(false);
                        TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.SendMessage, HttpMethod.Post, "Event_MessageCompleted.json", m_mockEventChannel);
                    });
                }
            };

            // Establish a messaging call
            IMessagingInvitation invitation = await communication.StartMessagingWithIdentityAsync(
                "Test subject",
                "sip:[email protected]",
                "https://example.com/callback",
                "Local user",
                "sip:[email protected]",
                m_loggingContext).ConfigureAwait(false);

            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_ConversationConnected.json"); // It has link to the messaging call
            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_ParticipantAdded.json");
            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_MessagingConnected.json");    // It has the messaging call

            m_messagingCall = invitation.RelatedConversation.MessagingCall;
        }
        public async Task StartAdhocMeetingShouldNotPassCallbackContextInTheHttpRequest()
        {
            // Given
            var callbackContextNotPassed = false;

            m_messagingInvitation = await StartIncomingMessagingInvitationAsync("Event_IncomingIMCall.json").ConfigureAwait(false);

            m_restfulClient.HandleRequestProcessed += (sender, args) =>
            {
                var operationId = TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.StartAdhocMeeting, HttpMethod.Post, "Event_OnlineMeetingInvitationStarted.json", m_mockEventChannel);
                if (operationId != null)
                {
                    var input = args.Input as StartAdhocMeetingInput;
                    callbackContextNotPassed = input.CallbackContext == null;
                }
            };

            // When
            await m_messagingInvitation.StartAdhocMeetingAsync("Test subject", "https://example.com/callback", m_loggingContext).ConfigureAwait(false);

            // Then
            Assert.IsTrue(callbackContextNotPassed);
        }
示例#22
0
 public Task <IOnlineMeetingInvitation> StartAdhocMeetingAsync(IMessagingInvitation invitation, string subject, string callbackContext, LoggingContext loggingContext = null)
 {
     return((invitation as MessagingInvitation).StartAdhocMeetingAsync(subject, callbackContext, null, loggingContext));
 }
        private async Task StartInstantMessagingBridgeFlowAsync(IncomingInviteEventArgs <IMessagingInvitation> e)
        {
            Logger.Instance.Information(string.Format("[InstantMessagingBridgeFlow] StartInstantMessagingBridgeFlow: LoggingContext: {0}", LoggingContext));

            CallbackContext callbackcontext = new CallbackContext {
                InstanceId = this.InstanceId, JobId = this.JobId
            };
            string callbackContextJsonString = JsonConvert.SerializeObject(callbackcontext);
            string CallbackUrl = string.Format(CultureInfo.InvariantCulture, AzureApplication.CallbackUriFormat, HttpUtility.UrlEncode(callbackContextJsonString));

            string meetingUrl = string.Empty;

            //There will be two conversation legs for the saas app
            m_p2pConversation  = null;
            m_confConversation = null;

            #region Step 1 Start adhoc meeting
            //Step1:
            Logger.Instance.Information(string.Format("[InstantMessagingBridgeFlow] Step 1: Start adhoc meeting: LoggingContext: {0}", LoggingContext));

            IOnlineMeetingInvitation onlineMeetingInvite = await e.NewInvite.StartAdhocMeetingAsync(m_handleIncomingMessageInput.Subject, CallbackUrl, LoggingContext).ConfigureAwait(false);

            if (string.IsNullOrEmpty(onlineMeetingInvite.MeetingUrl))
            {
                throw new PlatformserviceApplicationException("Do not get valid MeetingUrl on onlineMeetingInvitation resource after startAdhocMeeting!");
            }
            meetingUrl = onlineMeetingInvite.MeetingUrl;

            Logger.Instance.Information(string.Format("[InstantMessagingBridgeFlow] Get meeting uri: {0} LoggingContext: {1}", onlineMeetingInvite.MeetingUrl, LoggingContext));

            //wait on embedded onlinemeetingInvitation to complete, so that we can have valid related conversation
            await onlineMeetingInvite.WaitForInviteCompleteAsync().ConfigureAwait(false);

            //this is conference conversation leg
            m_confConversation = onlineMeetingInvite.RelatedConversation;
            if (m_confConversation == null)
            {
                throw new PlatformserviceApplicationException("onlineMeetingInvite.RelatedConversation is null? this is propably app code bug!");
            }
            #endregion

            #region Step 2 add Messaging modality on conference conversation
            //Step2:
            Logger.Instance.Information(string.Format("[InstantMessagingBridgeFlow] Step2: add Messaging modality on conference conversation: LoggingContext: {0}", LoggingContext));
            IMessagingCall confMessaging = m_confConversation.MessagingCall;
            if (confMessaging == null)
            {
                throw new PlatformserviceApplicationException("[InstantMessagingBridgeFlow] No valid Messaging resource on conference conversation");
            }
            //Hook up the event handler on "MessagingModality" of the conference leg and make sure what ever message anon user , or agent input , the app can all know and note down
            confMessaging.IncomingMessageReceived      += OnIncomingMessageReceived;
            m_confConversation.HandleParticipantChange += this.OnParticipantChange;
            IMessagingInvitation messageInvitation = await confMessaging.EstablishAsync(LoggingContext).ConfigureAwait(false);

            await messageInvitation.WaitForInviteCompleteAsync().ConfigureAwait(false);//messageInvitation cannot be null here

            #endregion

            #region Step 3 Start AcceptAndBridge
            //Step3:
            Logger.Instance.Information(string.Format("[InstantMessagingBridgeFlow] Step3:  Start AcceptAndBridge: LoggingContext: {0}", LoggingContext));
            await e.NewInvite.AcceptAndBridgeAsync(LoggingContext, meetingUrl, m_handleIncomingMessageInput.Subject).ConfigureAwait(false);

            await e.NewInvite.WaitForInviteCompleteAsync().ConfigureAwait(false);

            m_p2pConversation = e.NewInvite.RelatedConversation;

            //This is to clean the conf conversation leg when the p2p conversation is removed
            m_p2pConversation.HandleResourceRemoved += (o, args) =>
            {
                m_p2pConversation.HandleResourceRemoved = null;
                this.OnClientChatDisconnected();
            };

            IMessagingCall p2pMessaging = m_p2pConversation.MessagingCall;
            if (p2pMessaging == null || p2pMessaging.State != Rtc.Internal.Platform.ResourceContract.CallState.Connected)
            {
                Logger.Instance.Error(string.Format("[InstantMessagingBridgeFlow] p2pMessaging is null or not in connected state: LoggingContext: {0}", LoggingContext));
                throw new PlatformserviceApplicationException("[InstantMessagingBridgeFlow] p2pMessaging is null or not in connected state");
            }
            #endregion

            #region Step 4 Send welcome message
            //Step4:
            Logger.Instance.Information(string.Format("[InstantMessagingBridgeFlow] Step4:  Send welcome message: LoggingContext: {0}", LoggingContext));
            await p2pMessaging.SendMessageAsync(m_handleIncomingMessageInput.WelcomeMessage, LoggingContext).ConfigureAwait(false);

            #endregion

            #region Step 5 Add bridged participant to enable agent send message to client chat
            //Step5:
            Logger.Instance.Information(string.Format("[InstantMessagingBridgeFlow] Step5: Add bridged participant to enable agent send message to client chat. LoggingContext: {0}", LoggingContext));
            IConversationBridge conversationBridge = m_p2pConversation.ConversationBridge;
            if (conversationBridge == null)
            {
                Logger.Instance.Error(string.Format("[InstantMessagingBridgeFlow] conversationBridge == null after accept and bridge. LoggingContext: {0}", LoggingContext));
                throw new PlatformserviceApplicationException("[InstantMessagingBridgeFlow]  conversationBridge == null after accept and bridge");
            }
            await conversationBridge.AddBridgedParticipantAsync(LoggingContext, m_handleIncomingMessageInput.InvitedTargetDisplayName, m_handleIncomingMessageInput.InviteTargetUri, false).ConfigureAwait(false);

            #endregion

            #region Step 6 Start addParticipant to conference
            //Step 6:
            Logger.Instance.Information(string.Format("[HandleIncomingMessageJob] Step5: Start addParticipant to conference: LoggingContext: {0}", LoggingContext));
            IParticipantInvitation participantInvitation = await m_confConversation.AddParticipantAsync(m_handleIncomingMessageInput.InviteTargetUri, LoggingContext).ConfigureAwait(false);

            await participantInvitation.WaitForInviteCompleteAsync().ConfigureAwait(false);

            #endregion
        }
        /// <summary>
        /// Implement the interface ExecuteCoreAsync
        /// </summary>
        /// <returns></returns>
        public override async Task ExecuteCoreAsync()
        {
            ICommunication communication = AzureApplication.ApplicationEndpoint.Application.Communication;

            //Construct callbackUrl with callbackContext for callback message routing
            CallbackContext callbackcontext = new CallbackContext { InstanceId = this.InstanceId, JobId = this.JobId };
            string callbackContextJsonString = JsonConvert.SerializeObject(callbackcontext);
            string CallbackUrl = string.Format(CultureInfo.InvariantCulture, AzureApplication.CallbackUriFormat, HttpUtility.UrlEncode(callbackContextJsonString));

            Logger.Instance.Information("[SimpleNotifyJob] start to send messaging invitation");

            SimpleNotifyJobInput jobinput = this.JobInput as SimpleNotifyJobInput;
            if (jobinput == null)
            {
                throw new InvalidOperationException("Failed to get SimpleNotifyJobInput instance");
            }

            IMessagingInvitation invite = null;

            try
            {
                //Invite resource will be there when this taskc completes
                invite = await communication.StartMessagingAsync("Notification", jobinput.TargetUri, CallbackUrl, LoggingContext).ConfigureAwait(false);

                //Waiting for invite complete
                await invite.WaitForInviteCompleteAsync().ConfigureAwait(false);

                IMessagingCall messagingCall = invite.RelatedConversation.MessagingCall;
                messagingCall.IncomingMessageReceived += OnIncomingMessageReceived;

                Logger.Instance.Information("[SimpleNotifyJob] sending notification message");
                await messagingCall.SendMessageAsync(jobinput.NotificationMessage, LoggingContext).ConfigureAwait(false);

                Task reseponseReceived = m_responseMessageNotified.Task;

                try
                {
                    await reseponseReceived.TimeoutAfterAsync(TimeSpan.FromSeconds(30)).ConfigureAwait(false);
                }
                catch (TimeoutException)
                {
                    Logger.Instance.Warning("[SimpleNotifyJob] Do not get a response with in 30 seconds");
                }

                if (reseponseReceived.IsCompleted)
                {
                    Logger.Instance.Information("[SimpleNotifyJob] sending thank you message");
                    await messagingCall.SendMessageAsync("Thank you!", LoggingContext).ConfigureAwait(false);
                }
            }
            catch(CapabilityNotAvailableException ex)
            {
                Logger.Instance.Error("[SimpleNotifyJob] Failed!", ex);
            }
            catch(RemotePlatformServiceException ex)
            {
                Logger.Instance.Error("[SimpleNotifyJob] Failed!", ex);
            }
            finally
            {
                if (invite?.RelatedConversation != null)
                {
                    await invite.RelatedConversation.DeleteAsync(LoggingContext).ConfigureAwait(false);
                }
            }
        }