示例#1
0
        private async Task StartAgentCallAndTransferFlowAsync(ICommunication communication, string agent, string callContext)
        {
            IAudioVideoInvitation invite = await EstablishCallWithAgentAsync(communication, agent).ConfigureAwait(false);

            lock (m_syncRoot)
            {
                m_outboundAVConversations.Add(invite.RelatedConversation);
            }

            int result = Interlocked.Exchange(ref m_outboundCallTransferLock, 1);

            if (result == 0)
            {
                //Step 4: do transfer
                Logger.Instance.Information("[HuntGroupJob] Transferring call to " + agent);

                IAudioVideoCall av = invite.RelatedConversation.AudioVideoCall;

                ITransfer t = await av.TransferAsync(null, callContext, LoggingContext).ConfigureAwait(false);

                await t.WaitForTransferCompleteAsync().TimeoutAfterAsync(TimeSpan.FromSeconds(30)).ConfigureAwait(false);

                Logger.Instance.Information("[HuntGroupJob] Transfer completed successfully!");
            }
            else
            {
                // The call is already accepted and transfered by some one else
                Logger.Instance.Information("[HuntGroupJob] The call is already accepted and transfered by some one else; cancelling the transfer for " + agent);

                await invite.RelatedConversation.DeleteAsync(LoggingContext).ConfigureAwait(false);
            }
        }
        public async Task StartAdhocMeetingShouldReturnATaskToWaitForInvitationStartedEvent()
        {
            // Given
            IAudioVideoInvitation invitation = null;

            m_applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => invitation = args.NewInvite;
            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall.json");

            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 = invitation.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 bool CanStartAdhocMeeting(IAudioVideoInvitation invitation)
        {
            #pragma warning disable CS0618 // Type or member is obsolete
            return(invitation.Supports(AudioVideoInvitationCapability.StartAdhocMeeting));

            #pragma warning restore CS0618 // Type or member is obsolete
        }
示例#4
0
        public void ShouldNotExposeAcceptCapabilityIfLinkNotAvailable()
        {
            // Given
            IAudioVideoInvitation invitation = null;

            m_applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => invitation = args.NewInvite;

            // When
            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall_NoActionLinks.json");

            // Then
            Assert.IsNotNull(invitation);
            Assert.IsFalse(invitation.Supports(AudioVideoInvitationCapability.Accept));
        }
示例#5
0
        public void ShouldExposeForwardCapabilityIfLinkAvailable()
        {
            // Given
            IAudioVideoInvitation invitation = null;

            m_applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => { invitation = args.NewInvite; };

            // When
            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall.json");

            // Then
            Assert.IsNotNull(invitation);
            Assert.IsTrue(invitation.Supports(AudioVideoInvitationCapability.Forward));
        }
示例#6
0
        public async Task AcceptAsyncShouldThrowIfLinkNotAvailable()
        {
            // Given
            IAudioVideoInvitation invitation = null;

            m_applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => invitation = args.NewInvite;
            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall_NoActionLinks.json");

            // When
            await invitation.AcceptAsync(m_loggingContext).ConfigureAwait(false);

            // Then
            // Exception is thrown
        }
示例#7
0
        public async Task StartAudioVideoShouldWork()
        {
            // Given
            m_restfulClient.HandleRequestProcessed += (sender, args) => { TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.AudioVideoInvitations, HttpMethod.Post, "Event_AudioVideoInvitationStarted.json", m_eventChannel); };

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

            // Then
            Assert.IsNotNull(invitation);
            Assert.IsNotNull(invitation.RelatedConversation);
            Assert.IsTrue(m_restfulClient.RequestsProcessed("POST " + DataUrls.AudioVideoInvitations));
        }
示例#8
0
        public async Task AcceptAndBridgeAsyncShouldThrowIfCapabilityNotAvailable()
        {
            // Given
            IAudioVideoInvitation invitation = null;

            m_applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => { invitation = args.NewInvite; };

            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall_NoActionLinks.json");

            // When
            await invitation.AcceptAndBridgeAsync(m_loggingContext, string.Empty, "sip:[email protected]").ConfigureAwait(false);

            // Then
            // Exception is thrown
        }
示例#9
0
        public void ShouldNotSupportStartAdhocMeetingIfLinkNotAvailable()
        {
            // Given
            IAudioVideoInvitation invitation = null;

            m_applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => invitation = args.NewInvite;

            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall_NoActionLinks.json");

            // When
            var supports = invitation.Supports(AudioVideoInvitationCapability.StartAdhocMeeting);

            // Then
            Assert.IsFalse(supports);
        }
示例#10
0
        public async Task AcceptAndBridgeAsyncShouldThrowIfBothMeetingUrlAndToNull()
        {
            // Given
            IAudioVideoInvitation invitation = null;

            m_applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => invitation = args.NewInvite;

            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall.json");

            // When
            await invitation.AcceptAndBridgeAsync(m_loggingContext, null, null).ConfigureAwait(false);

            // Then
            // Exception is thrown
        }
示例#11
0
        public async Task AcceptAndBridgeAsyncShouldMakeHttpRequest()
        {
            // Given
            IAudioVideoInvitation invitation = null;

            m_applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => invitation = args.NewInvite;

            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall.json");

            // When
            await invitation.AcceptAndBridgeAsync(new SipUri("sip:[email protected]"), m_loggingContext).ConfigureAwait(false);

            // Then
            Assert.IsTrue(m_restfulClient.RequestsProcessed("POST " + DataUrls.AudioVideoInvitationAcceptAndBridge));
        }
示例#12
0
        public async Task AcceptAndBridgeAsyncShouldMakeHttpRequest()
        {
            // Given
            IAudioVideoInvitation invitation = null;

            m_applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => { invitation = args.NewInvite; };

            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall.json");

            // When
            await invitation.AcceptAndBridgeAsync(m_loggingContext, "sip:[email protected];gruu;opaque=app:conf:focus:id:LB6557GF", "sip:[email protected]").ConfigureAwait(false);

            // Then
            Assert.IsTrue(m_restfulClient.RequestsProcessed("POST " + DataUrls.AudioVideoInvitationAcceptAndBridge));
        }
        public async Task StartAdhocMeetingShouldWorkWithNullLoggingContext()
        {
            // Given
            IAudioVideoInvitation invitation = null;

            m_applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => invitation = args.NewInvite;
            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall.json");
            m_restfulClient.HandleRequestProcessed +=
                (sender, args) => TestHelper.RaiseEventsOnHttpRequest(args, DataUrls.StartAdhocMeeting, HttpMethod.Post, "Event_OnlineMeetingInvitationStarted.json", m_mockEventChannel);

            // When
            await invitation.StartAdhocMeetingAsync("Test subject", "mycallbackContext", null).ConfigureAwait(false);

            // Then
            // No exception is thrown
        }
示例#14
0
        public async Task ForwardAsyncShouldThrowForInvalidInput()
        {
            // Given
            IAudioVideoInvitation invitation = null;

            m_applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => invitation = args.NewInvite;

            m_restfulClient.OverrideResponse(new Uri(DataUrls.AudioVideoInvitationForward), HttpMethod.Post, HttpStatusCode.NoContent, null);

            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall.json");

            // When
            HttpResponseMessage response = await invitation.ForwardAsync(null, m_loggingContext).ConfigureAwait(false);

            // Then
            // Exception is thrown
        }
示例#15
0
        public async Task AcceptAsyncShouldWork()
        {
            // Given
            IAudioVideoInvitation invitation = null;

            m_restfulClient.OverrideResponse(new Uri(DataUrls.AudioVideoInvitationAccept), HttpMethod.Post, HttpStatusCode.NoContent, null);

            m_applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => invitation = args.NewInvite;
            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall.json");

            // When
            HttpResponseMessage response = await invitation.AcceptAsync(m_loggingContext).ConfigureAwait(false);

            // Then
            Assert.AreEqual(HttpStatusCode.NoContent, response.StatusCode);
            Assert.IsTrue(m_restfulClient.RequestsProcessed("POST " + DataUrls.AudioVideoInvitationAccept));
        }
        public async Task StartAdhocMeetingShouldThrowIfAdhocMeetingStartedEventNotReceived()
        {
            // Given
            IAudioVideoInvitation invitation = null;

            m_applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => invitation = args.NewInvite;

            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall.json");

            ((AudioVideoInvitation)invitation).WaitForEvents = TimeSpan.FromMilliseconds(300);

            // When
            await invitation.StartAdhocMeetingAsync("Test subject", "myCallbackContext", m_loggingContext).ConfigureAwait(false);

            // Then
            // Exception is thrown
        }
示例#17
0
        public void ShouldNotSupportAcceptAndBridgeIfLinkIsNotAvailable()
        {
            // Given
            IAudioVideoInvitation invitation = null;

            m_applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => invitation = args.NewInvite;

            m_restfulClient.OverrideResponse(new Uri(DataUrls.AudioVideoInvitationForward), HttpMethod.Post, HttpStatusCode.NoContent, null);

            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall_NoActionLink.json");

            // When
            var supports = invitation.Supports(AudioVideoInvitationCapability.AcceptAndBridge);

            // Then
            Assert.IsFalse(supports);
        }
示例#18
0
        public async Task StartAdhocMeetingShouldMakeTheHttpRequest()
        {
            // Given
            IAudioVideoInvitation invitation = null;

            m_applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => { invitation = args.NewInvite; };

            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall.json");

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

            // When
            await invitation.StartAdhocMeetingAsync("Test subject", "myCallbackContext", m_loggingContext).ConfigureAwait(false);

            // Then
            Assert.IsTrue(m_restfulClient.RequestsProcessed("POST " + DataUrls.StartAdhocMeeting));
        }
示例#19
0
        private async Task <IAudioVideoInvitation> EstablishCallWithAgentAsync(ICommunication communication, string agent)
        {
            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("Making outbound call to " + agent);

            IAudioVideoInvitation invite = await communication.StartAudioAsync("customer call", agent, CallbackUrl, LoggingContext).ConfigureAwait(false);

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

            IConversation c = invite.RelatedConversation;

            if (c.AudioVideoCall != null)
            {
                await c.AudioVideoCall.WaitForAVFlowConnected().ConfigureAwait(false);
            }
            return(invite);
        }
        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);

            IAudioVideoInvitation invitation = null;

            applicationEndpoint.HandleIncomingAudioVideoCall += (sender, args) => invitation = args.NewInvite;

            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_IncomingAudioCall.json");
            TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_AudioVideoConnected.json");

            m_audioVideoCall = invitation.RelatedConversation.AudioVideoCall;
        }
示例#21
0
        private async Task HandleIncomingAudioVideoCallAsync(IncomingInviteEventArgs <IAudioVideoInvitation> e)
        {
            Logger.Instance.Information("[AudioVideoIVRJob] Incoming AudioVideoCall.");

            var input = JobInput as AudioVideoIVRJobInput;
            IAudioVideoInvitation invite = e.NewInvite;

            if (input.Action == AudioVideoIVRActions.TerminateCall)
            {
                Logger.Instance.Information("[AudioVideoIVRJob] Declining incoming call.");
                await invite.DeclineAsync(LoggingContext).ConfigureAwait(false);
            }

            if (input.Action == AudioVideoIVRActions.TransferToUser)
            {
                Logger.Instance.Information("[AudioVideoIVRJob] Forwarding the call to {0}.", input.User);
                await invite.ForwardAsync(LoggingContext, input.User).ConfigureAwait(false);
            }

            if (input.Action == AudioVideoIVRActions.PlayPrompt || input.Action == AudioVideoIVRActions.RepeatPrompt)
            {
                Logger.Instance.Information("[AudioVideoIVRJob] Accepting the call.");
                await invite.AcceptAsync(LoggingContext).ConfigureAwait(false);

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

                if (e.NewInvite.RelatedConversation?.AudioVideoCall == null)
                {
                    Logger.Instance.Warning("[AudioVideoIVRJob] AudioVideoModality not found in the conversation.");
                    return;
                }

                Logger.Instance.Information("[AudioVideoIVRJob] Call accepted.");

                var promptHandler = new AudioVideoIVRPromptHandler(input, this.AzureApplication, LoggingContext);
                promptHandler.HandleEstablishedAudioVideo(e.NewInvite.RelatedConversation.AudioVideoCall);
            }
        }
示例#22
0
 public Task <IOnlineMeetingInvitation> StartAdhocMeetingAsync(IAudioVideoInvitation invitation, string subject, string callbackContext, LoggingContext loggingContext = null)
 {
     return((invitation as AudioVideoInvitation).StartMeetingAsync(subject, callbackContext, loggingContext));
 }