Esempio n. 1
0
 internal HuntForAgentAsyncResult(AcdAgentHunter hunter, AcdCustomerSession session, List <AgentSkill> requestedSkills, AsyncCallback callback, object state)
     : base(callback, state)
 {
     _agentHunter     = hunter;
     _session         = session;
     _requestedSkills = requestedSkills;
 }
Esempio n. 2
0
 internal FindAgentAsyncResult(AsyncCallback asyncCallback, Object state, AcdCustomerSession requestor, AcdAgentMatchMaker matchMaker, List <Agent> exclusionList, List <AgentSkill> requestedSkills)
     : base(asyncCallback, state)
 {
     _matchMaker      = matchMaker;
     _configuration   = matchMaker._configuration;
     _exclusionList   = exclusionList;
     _requestedSkills = requestedSkills;
     _requestor       = requestor;
 }
 internal AcdConferenceServicesAnchor(AcdCustomerSession session, ApplicationEndpoint endpoint, AcdLogger logger)
 {
     _endpoint     = endpoint;
     _state        = ConferenceServicesAnchorState.Idle;
     _logger       = logger;
     _session      = session;
     _conversation = new Conversation(endpoint);
     _conversation.Impersonate("sip:" + Guid.NewGuid() + "@" + endpoint.DefaultDomain, null, null);
     _conversation.ApplicationContext = this;
 }
Esempio n. 4
0
        /// <summary>
        /// Attempts to find an agent available to serve a customer. The operation may time out if no agent
        /// is available within a configurable max duration.
        /// </summary>
        internal IAsyncResult BeginFindAgent(AcdCustomerSession owner, List <Agent> exclusionList, List <AgentSkill> requestedSkills, AsyncCallback callback, object state)
        {
            var result = new FindAgentAsyncResult(callback, state, owner, this, exclusionList, requestedSkills);

            ThreadPool.QueueUserWorkItem((waitState) =>
            {
                var tempAr = waitState as FindAgentAsyncResult;
                tempAr.Process();
            }, result);

            return(result);
        }
Esempio n. 5
0
        internal IAsyncResult BeginHuntForAgent(AcdCustomerSession session, List <AgentSkill> requestedSkills, AsyncCallback callback, object state)
        {
            HuntForAgentAsyncResult ar = new HuntForAgentAsyncResult(this, session, requestedSkills, callback, state);

            ThreadPool.QueueUserWorkItem((waitState) =>
            {
                var tempAr = waitState as HuntForAgentAsyncResult;
                tempAr.Process(true);
            }, ar);

            return(ar);
        }
Esempio n. 6
0
        /// <summary>
        /// Handles an incoming Application Sharing call. The incoming Application  Sharing call can be one of two things:
        /// this can be a brand new customer session or a modality escalation. Else decline.
        /// </summary>
        private void HandleApplicationSharingCallReceived(object sender, CallReceivedEventArgs <ApplicationSharingCall> args)
        {
            //Declines if it is a brand new Conversation as we only expect, modality escalation in
            // an existing customer session for Application Sharing.
            if (args.IsNewConversation == true)
            {
                try
                {
                    args.Call.Decline(new CallDeclineOptions(ResponseCode.TemporarilyUnavailable));
                }
                catch (InvalidOperationException ivoex)
                {
                    _logger.Log("AcdPortal cannot decline an imcoming Application Sharing Call properly", ivoex);
                }
                catch (RealTimeException ex)
                {
                    _logger.Log("AcdPortal cannot decline an imcoming Application Sharing Call properly", ex);
                }
            }
            else if (args.IsNewConversation == false)
            {
                //this an Application Sharing escalation, hand off the call to the AcdCustomerSession for futher processing
                if (null != args.Call.Conversation.ApplicationContext)
                {
                    AcdCustomerSession session = args.Call.Conversation.ApplicationContext as AcdCustomerSession;
                    args.RingBackDisabled = true;

                    ThreadPool.QueueUserWorkItem((waitState) =>
                    {
                        session.HandleNewModality(args.Call);
                    });
                }
                else
                {
                    // There was an issue retrieving the AcdCustomerSession, we are declining the call.
                    try
                    {
                        args.Call.Decline(new CallDeclineOptions(ResponseCode.TemporarilyUnavailable));
                    }
                    catch (InvalidOperationException ivoex)
                    {
                        _logger.Log("AcdPortal cannot decline an imcoming Application Sharing Call properly", ivoex);
                    }
                    catch (RealTimeException ex)
                    {
                        _logger.Log("AcdPortal cannot decline incoming Application Sharing call properly", ex);
                    }
                }
            }
        }
Esempio n. 7
0
        private void OnMonitoringSessionTerminated(object sender, MonitoringSessionStateChangedEventArgs args)
        {
            AcdMonitoringSession monitoringSession = sender as AcdMonitoringSession;

            switch (args.NewState)
            {
            case MonitoringSessionState.Terminating:
                _agentSessionToMonitor = null;
                _agentToMonitor        = null;
                this.UpdateState(SupervisorSessionState.GeneralAgentActivityTracking);

                break;

            case MonitoringSessionState.Terminated:
                monitoringSession.StateChanged -= this.OnMonitoringSessionTerminated;
                break;
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Allocates the agent so that she cannot be allocated twice.
        /// </summary>
        internal void Allocate(AcdCustomerSession requestor)
        {
            lock (_syncRoot)
            {
                if (_allocated)
                {
                    throw new InvalidOperationException("Agent is already allocated.");
                }
                if (requestor == null)
                {
                    throw new InvalidOperationException("Agent Requestor cannot be null.");
                }
                Debug.Write("Agent " + this.SignInAddress.ToString() + "was allocated to" + requestor.ToString());

                _owner                 = requestor;
                _allocated             = true;
                _activeIdleSince       = DateTime.UtcNow;
                _havePropertiesChanged = true;
                _allocationStatus      = AgentAllocationStatus.AllocatedByMatchMaker;
            }
        }
Esempio n. 9
0
 /// <summary>
 /// Releases the agent so that she can be allocated subsequently.
 /// </summary>
 internal void Deallocate(object owner)
 {
     lock (_syncRoot)
     {
         if (!_allocated)
         {
             _logger.Log("Agent is not allocated.");
         }
         else if (_owner == owner) // we verify that only the one, that allocated the agent, deallocates her
         {
             _logger.Log("Agent " + this.SignInAddress.ToString() + "was deallocated by " + owner.ToString());
             _allocated             = false;
             _allocationStatus      = AgentAllocationStatus.NotAllocated;
             _activeIdleSince       = DateTime.UtcNow;
             _asyncResult           = null;
             _owner                 = null;
             _havePropertiesChanged = true;
         }
         else
         {
             _logger.Log("Agent can only be deallocated by its owner");
         }
     }
 }
Esempio n. 10
0
        /// <summary>
        /// Handles an incoming Instant Messaging call. The incoming Instant Messaging call can be one of two things:
        /// this can be a brand new customer session or a modality escalation. Else decline.
        /// </summary>
        private void HandleInstantMessagingCallReceived(object sender, CallReceivedEventArgs <InstantMessagingCall> args)
        {
            //Determines whether it is a new Call
            if (args.IsNewConversation == true)  //New acd customer session
            {
                //Decline the call if the portal is draining its calls, else hand it off to a newly created Acd Customer session.
                if (_portalState < PortalState.Draining)  //Only take new calls is we're not in the process of shutting down.
                {
                    AcdCustomerSession session = new AcdCustomerSession(_logger, _matchMaker, this);

                    //add the session to the list.
                    lock (_syncRoot)
                    {
                        _sessions.Add(session);
                        _numberOfSessionsEstablished++;
                    }
                    session.CustomerSessionStateChanged += CustomerSessionStateChanged;

                    if (args.CustomMimeParts.Count > 0)
                    {
                        productType       productInfo;
                        List <AgentSkill> listOfRequestedSkills = new List <AgentSkill>(this.ProcessMimeParts(args.CustomMimeParts, out productInfo));

                        ThreadPool.QueueUserWorkItem((waitState) =>
                        {
                            session.HandleInitialCall(args.Call, listOfRequestedSkills, productInfo);
                        });
                    }
                    else
                    {
                        ThreadPool.QueueUserWorkItem((waitState) =>
                        {
                            session.HandleInitialCall(args.Call, null, null);
                        });
                    }
                }
                else //If the call comes in while we're shutting down, terminate it
                {
                    //UNDONE: Nice to have: - Play a message to the user that the portal is shutting down.
                    try
                    {
                        args.Call.Decline(new CallDeclineOptions(ResponseCode.TemporarilyUnavailable));
                    }
                    catch (RealTimeException ex)
                    {
                        _logger.Log("AcdPortal cannot decline incoming IM call properly while draining/terminating the portal", ex);
                    }
                }
            }
            else
            {
                //this an audio escalation, hand off the call to the AcdCustomerSession for futher processing
                if (null != args.Call.Conversation.ApplicationContext)
                {
                    AcdCustomerSession session = args.Call.Conversation.ApplicationContext as AcdCustomerSession;

                    ThreadPool.QueueUserWorkItem((waitState) =>
                    {
                        session.HandleNewModality(args.Call);
                    });
                }
                else
                {
                    // There was an issue retrieving the AcdCustomerSession, we are declining the call.

                    try
                    {
                        args.Call.Decline();
                    }
                    catch (InvalidOperationException ex)
                    {
                        _logger.Log("AcdPortal cannot decline incoming IM call properly; the call must already be terminated", ex);
                    }
                    catch (RealTimeException ex)
                    {
                        _logger.Log("AcdPortal cannot decline incoming IM call properly", ex);
                    }
                }
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Handles incoming AudioVideoCall. The incoming call can be one of three things: a brand new conversation,
        /// a self transfer of an existing customer-facing call, an audio escalation. In Draining mode, only the incoming
        /// calls for existing Conversations will be processed. Initial Conversation calls coming in will be declined by the
        /// endpoint.
        /// </summary>
        private void HandleAudioVideoCallReceived(object sender, CallReceivedEventArgs <AudioVideoCall> args)
        {
            //Determines whether it is a new Call
            if (args.IsNewConversation && args.CallToBeReplaced == null)   //New Acd customer session
            {
                AcdCustomerSession session = new AcdCustomerSession(_logger, _matchMaker, this);

                //add the session to the list.
                lock (_syncRoot)
                {
                    _sessions.Add(session);
                    _numberOfSessionsEstablished++;
                }

                //registering for an event to monitor the customer session state in order to determine when the draining is complete.
                session.CustomerSessionStateChanged += CustomerSessionStateChanged;

                if (args.CustomMimeParts.Count > 0)
                {
                    productType productInformation;

                    List <AgentSkill> listOfRequestedSkills = new List <AgentSkill>(this.ProcessMimeParts(args.CustomMimeParts, out productInformation));

                    ThreadPool.QueueUserWorkItem((waitState) =>
                    {
                        session.HandleInitialCall(args.Call, listOfRequestedSkills, productInformation);
                    });
                }
                else
                {
                    ThreadPool.QueueUserWorkItem((waitState) =>
                    {
                        session.HandleInitialCall(args.Call, null, null);
                    });
                }
            }
            //it is not a new call but a modality addition
            else if (args.IsNewConversation == false && args.CallToBeReplaced == null)
            {
                if (null != args.Call.Conversation.ApplicationContext)
                {
                    //this an audio escalation, hand-off the call to the AcdCustomerSession for futher processing
                    AcdCustomerSession session = args.Call.Conversation.ApplicationContext as AcdCustomerSession;
                    args.RingBackDisabled = true;
                    session.HandleNewModality(args.Call);
                }
                else
                {
                    // There was an issue retrieving the AcdCustomerSession, we are declining the call.
                    try
                    {
                        args.Call.Decline(new CallDeclineOptions(ResponseCode.TemporarilyUnavailable));
                    }
                    catch (RealTimeException ex)
                    {
                        _logger.Log("AcdPortal cannot decline incoming audio call properly", ex);
                    }
                }
            }
            else if (args.CallToBeReplaced != null)
            {
                try
                {
                    args.Call.Decline();
                }
                catch (RealTimeException ex)
                {
                    _logger.Log("AcdPortal failed declining an incoming call replacing an exisiting one", ex);
                }
            }
            else
            {
                //unexpected. Decline the incoming call
                try
                {
                    args.Call.Decline();
                }
                catch (RealTimeException ex)
                {
                    _logger.Log("Acd customer session failed to decline an unexpected incoming Audio call", ex);
                }
            }
        }
Esempio n. 12
0
 internal PendingAgentMatchRequestQueueItem(AcdCustomerSession requestor, FindAgentAsyncResult findAgentAsyncResult, TimerItem tmrItem)
 {
     _Requestor = requestor;
     this.FindAgentAsyncResult = findAgentAsyncResult;
     _TmrItem = tmrItem;
 }