bool ACDQueue_Linear::buildTargetAgentList(UtlSList& rTargetAgentList, ACDCall* pCallRef) { ACDAgent* pAgent; ACDAgent* pLastAttemptedAgent; // Always rebuild the list to get the agents added on the fly buildACDAgentList(); UtlSListIterator listIterator(mAcdAgentList); int numAgents = mAcdAgentList.entries(); // Iterate through the ACDAgent list, starting after the agent that // The ACDCall was last using. If the end of the list is // reached, wrap around to the beginning. If this LastAttemptedAgent // is NULL, start from the head of the list pLastAttemptedAgent = pCallRef->getLastAgent(); if (pLastAttemptedAgent != NULL) { // walk the iterator to point after pLastAttemptedAgent if (listIterator.findNext(pLastAttemptedAgent) == NULL) { // Didn't find pLastAttemptedAgent, start again from the top. listIterator.reset(); pCallRef->setLastAgent(NULL); } } for(int i=0; i<numAgents; i++) { // Check the next agent pAgent = dynamic_cast<ACDAgent*>(listIterator()); if (pAgent == NULL) { // We've hit the end of the list start back from the head of the list listIterator.reset(); pAgent = dynamic_cast<ACDAgent*>(listIterator()); if (pAgent == NULL) { // All out of agents to try return false; } } if (pAgent->isAvailable(true)) { rTargetAgentList.append(pAgent); // Remember the agent chosen pCallRef->setLastAgent(pAgent); OsSysLog::add(FAC_ACD, gACD_DEBUG, "%s::buildTargetAgentList - agent(%s) is added to the target list", mAcdSchemeString, pAgent->getUriString()->data()); return true; } } // The whole list was tried, yet no appropriate agents were found. return false; }
bool ACDQueue_LongestIdle::buildTargetAgentList(UtlSList& rTargetAgentList, ACDCall* pCallRef) { // Always rebuild the list to get the agents added on the fly buildACDAgentList(); // Iterate through the ACDAgent list, starting at the head of the list // and find the agent that has been idle the longest. for(;;) { ACDAgent* pAgent; ACDAgent* pLongestIdleAgent = NULL; unsigned long maxIdleTime = 0; UtlSListIterator listIterator(mAcdAgentList); // Find the available agent with the longest idle time while ((pAgent = dynamic_cast<ACDAgent*>(listIterator())) != NULL) { if (pAgent->isAvailable(false)) { if (pAgent->getIdleTime() >= maxIdleTime) { maxIdleTime = pAgent->getIdleTime(); pLongestIdleAgent = pAgent; } } } if (pLongestIdleAgent == NULL) { // None available break ; } // If he is still available, use him. Otherwise start again. if (pLongestIdleAgent->isAvailable(true)) { rTargetAgentList.append(pLongestIdleAgent); OsSysLog::add(FAC_ACD, gACD_DEBUG, "%s::buildTargetAgentList - agent(%s) is added to the target list. Idle time was %lu seconds", mAcdSchemeString, pLongestIdleAgent->getUriString()->data(), maxIdleTime); return true ; } } // The whole list was tried, yet no appropriate agents were found. return false; }
void ACDCallManager::updateTransferCallState(SIPX_CALLSTATE_INFO* pCallInfo) { SIPX_CALL hCallHandle = SIPX_CALL_NULL; SIPX_CALL hAssociatedCallHandle; int callEvent; int callCause; const char* remUri; char userUri[512]; ACDCall* pCallRef; mLock.acquire(); // Extract the call handle and state info hAssociatedCallHandle = pCallInfo->hAssociatedCall; callEvent = pCallInfo->event; callCause = pCallInfo->cause; remUri = pCallInfo->remoteAddress; /** * For the NEWCALL_TRANSFER event - find the ACDCall object instance * on the basis of the Associated call handle (from the older leg). */ if (pCallInfo->cause == CALLSTATE_NEW_CALL_TRANSFER) { if (TRUE == validateTransferToLine(pCallInfo)) { // Don't allow agents to transfer calls INTO the acd. It screws // things up. The correct behavior would be to move the call // the agent is currently handling into a new queue, but due to // the inability to remove calls from a conference, this just doesn't // work. Hangup on the transfer attempt. Ths should leave // caller and agent connected. OsSysLog::add(FAC_ACD, PRI_WARNING, "ACDCallManager::updateTransferCallState - " "CALLSTATE_OFFERING::%d to the ACD Line REJECTED", pCallInfo->cause); sipxCallReject(pCallInfo->hCall, SIP_BAD_REQUEST_CODE, "Agent Transfer Loop Rejected"); return ; } // not an agent transferring into the acd hCallHandle = hAssociatedCallHandle; UtlInt callKey(hCallHandle); pCallRef = dynamic_cast<ACDCall*>(mAgentCallHandleMap.findValue(&callKey)); } else // not new call transfer { UtlInt searchKey(pCallInfo->hCall); pCallRef = dynamic_cast<ACDCall*>(mTransferCallHandleMap.findValue(&searchKey)); } if (pCallRef != NULL) { if (callCause == CALLSTATE_NEW_CALL_TRANSFER) { addMapTransferAgentCallHandleToCall(pCallInfo->hCall, pCallRef); pCallRef->mFlagTransfer = TRUE; // only set TRUE here. } if ( (callCause == CALLSTATE_REMOTE_OFFERING_NORMAL) && (pCallRef->mFlagTransfer == TRUE)) { UtlString userId, hostAddress; Url remoteUrl(remUri); remoteUrl.getUserId(userId); remoteUrl.getHostAddress(hostAddress); if (remUri) { // Now find the agent for this remUri sprintf(userUri,"sip:%s@%s",userId.data(),hostAddress.data()); UtlString agentUri(userUri); ACDAgent* pAgentRef = mpAcdServer->getAcdAgentManager()->getAcdAgentReference(agentUri); if (!pAgentRef) { OsSysLog::add(FAC_ACD, gACD_DEBUG, "ACDCallManager::updateTransferCallState - " "Failed to find Agent. This is probably an agent that is not signed in: " "call(%d), TransferAgentCall(%d), agentUri(%s)", pCallRef->getCallHandle(), pCallInfo->hCall, agentUri.data()); // A non registered agent is not yet supported - so do not try ! pAgentRef = mpAcdServer->getAcdAgentManager()->createACDAgent(userUri, "dummy", "", FALSE, FALSE, NULL, TRUE); if (!pAgentRef) { assert(0); } } //set the mhCallHandle of the Agent object pAgentRef->setCallHandle(pCallInfo->hCall); // set the transfer agent object in the call object pCallRef->mpTransferAgent = pAgentRef; OsSysLog::add(FAC_ACD, gACD_DEBUG, "ACDCallManager::updateTransferCallState - " "success in finding Agent: call(%d), TransferAgentCall(%d) AgentUri(%s)", pCallRef->getCallHandle(), pCallInfo->hCall, pAgentRef->getUriString()->data()); } } if ( (callCause == CALLSTATE_REMOTE_OFFERING_NORMAL) && (pCallRef->mFlagTransfer == FALSE)) { ; // do nothing } else { pCallRef->updateState(hCallHandle, callEvent, callCause); } } mLock.release(); return; }