Exemplo n.º 1
0
void acd_agent::SetStatus(const acd::AgentStatusT& agentStatus, const acd::CallEventReasonT& reason,
                          const string& restReason) {
    time_t lastStatusTime = m_currStatusTime;
    acd::AgentStatusT lastAgentStatus = m_agentStatus;
    m_currStatusTime = time(NULL);
    m_agentStatus = agentStatus;

    switch (lastAgentStatus.get_value()) {
    case acd::AgentStatusT::AsReadyState:
        m_freeTotalTime += m_currStatusTime - lastStatusTime;
        break;

    case acd::AgentStatusT::AsBusyState:
        m_busyTotalTime += m_currStatusTime - lastStatusTime;
        break;

    case acd::AgentStatusT::AsRestState:
        m_restTotalTime += m_currStatusTime - lastStatusTime;
        break;

    default:
        break;
    }

    SendEventT* p_agentEvent = new SendEventT;
    p_agentEvent->m_event_id                     = acd_tool::CreatEventId();
    p_agentEvent->m_callback_proxy               = m_callback_ptr;
    p_agentEvent->m_event_type                   = AGENT_EVENT;
    p_agentEvent->m_agent_event.agentId          = m_agentId;
    p_agentEvent->m_agent_event.eventId          = acd::CallEventTypeT::CeUnKnownEvent;
    p_agentEvent->m_agent_event.agentDn          = m_agentDn;
    p_agentEvent->m_agent_event.callId           = "";
    p_agentEvent->m_agent_event.sessionId        = 0;
    p_agentEvent->m_agent_event.agentStatus      = m_agentStatus;
    p_agentEvent->m_agent_event.originalCallid   = "";
    p_agentEvent->m_agent_event.partyNum         = 0;
    p_agentEvent->m_agent_event.otherParty       = "";
    p_agentEvent->m_agent_event.otherAttr        = acd::PartyAttributeT::PaUnknown;
    p_agentEvent->m_agent_event.originatingParty = "";
    p_agentEvent->m_agent_event.originalAni      = "";
    p_agentEvent->m_agent_event.originalDnis     = "";
    p_agentEvent->m_agent_event.reason           = reason;
    p_agentEvent->m_agent_event.timestamp        = bgcc::TimeUtil::get_timestamp_us();

    WriteTraceLog(restReason);
    acd_tool::m_send_event_manager.send_event(p_agentEvent, m_handle);
}
Exemplo n.º 2
0
void acd_agent::ProcessIMSEvent(const ims::CallEventT& event) {
    SingleRWLocker s(&m_RWLock, true);

    m_sessionId = event.sessionid;
    m_callId = event.callid;
    time_t lastStatusTime = m_currStatusTime;
    acd::AgentStatusT lastAgentStatus = m_agentStatus;
    m_currStatusTime = time(NULL);

    switch (lastAgentStatus.get_value()) {
    case acd::AgentStatusT::AsReadyState:
        m_freeTotalTime += m_currStatusTime - lastStatusTime;
        break;

    case acd::AgentStatusT::AsBusyState:
        m_busyTotalTime += m_currStatusTime - lastStatusTime;
        break;

    case acd::AgentStatusT::AsRestState:
        m_restTotalTime += m_currStatusTime - lastStatusTime;
        break;

    default:
        break;
    }

    SendEventT* p_agentEvent = new SendEventT;
    p_agentEvent->m_event_id                     = acd_tool::CreatEventId();
    p_agentEvent->m_callback_proxy               = m_callback_ptr;
    p_agentEvent->m_event_type                   = AGENT_EVENT;
    p_agentEvent->m_agent_event.agentId          = m_agentId;
    p_agentEvent->m_agent_event.eventId          = acd_tool::TranslateCallEvent(event.eventType);
    p_agentEvent->m_agent_event.agentDn          = event.device;
    p_agentEvent->m_agent_event.callId           = event.callid;
    p_agentEvent->m_agent_event.sessionId        = event.sessionid;
    //p_agentEvent->m_agent_event.agentStatus      = m_agentStatus;
    p_agentEvent->m_agent_event.originalCallid   = event.originalCallid;
    p_agentEvent->m_agent_event.partyNum         = event.partyNum;
    p_agentEvent->m_agent_event.otherParty       = event.otherDevice;
    p_agentEvent->m_agent_event.otherAttr        = acd_tool::TranslatePartyAtt(event.otherAttr);
    p_agentEvent->m_agent_event.originatingParty = event.originatingParty;
    p_agentEvent->m_agent_event.originalAni      = event.originalAni;
    p_agentEvent->m_agent_event.originalDnis     = event.originalDnis;
    //p_agentEvent->m_agent_event.reason           = reason;
    p_agentEvent->m_agent_event.timestamp        = bgcc::TimeUtil::get_timestamp_us();
    acd::CallEventReasonT reason = acd_tool::TranslateCallReason(event.reason);

    switch (event.state.get_value()) {
    case ims::CallStateT::SG_UnknownState:
        m_agentStatus = acd::AgentStatusT::AsUnknownState;
        break;

    case ims::CallStateT::SG_IdleState: {
        if (lastAgentStatus == acd::AgentStatusT::AsAlertingState ||
                lastAgentStatus == acd::AgentStatusT::AsHalfAlertingState ||
                lastAgentStatus == acd::AgentStatusT::AsConnectingState ||
                lastAgentStatus == acd::AgentStatusT::AsHalfConnectedState ||
                lastAgentStatus == acd::AgentStatusT::AsConsultConnectingState) { // 振铃中挂断
            if (event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnected_InternalCall ||
                    event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnected_NormalCall ||
                    event.eventType == ims::CallEventTypeT::SG_ThisPartyTransferred_NormalCall ||
                    event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnected_ConsultCall ||
                    event.eventType == ims::CallEventTypeT::SG_ThisPartyTransferred_ConsultCall ||
                    event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnect_ConferenceCall ||
                    event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnect_MonitorCall ||
                    event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnect_IntrudeCall) { // 本方挂断
                reason = acd::CallEventReasonT::CerIdleErrorSelfHangup;
                m_callinfo.SetReleaseCause(ReleaseCauseT::THISPARTY);
            } else {
                reason = acd::CallEventReasonT::CerIdleErrorOtherHangup;
                m_callinfo.SetReleaseCause(ReleaseCauseT::OTHERPARTY);
            }

            if (0 < m_callTime) {
                m_callTotalTime += m_currStatusTime - m_callTime;
            }

            if (0 < m_answerTime) {
                m_answerTotalTime += m_currStatusTime - m_answerTime;
            }

            m_callinfo.SetAniDnis(event.originalAni, event.originalDnis);
            if (lastAgentStatus == acd::AgentStatusT::AsConnectingState) {
                m_callinfo.SetConnectEnd(m_currStatusTime);
                m_callinfo.SetCallEnd(m_currStatusTime);
            }
            else if (lastAgentStatus == acd::AgentStatusT::AsConsultConnectingState) {
                m_callinfo.SetCallEnd(m_currStatusTime);
            }
            else {
                m_callinfo.SetAckEnd(m_currStatusTime);
                m_callinfo.SetCallEnd(m_currStatusTime);
            }

            if (m_callinfo.isValid()) { // 如果话单没有起始信息,则不必要写
                m_callinfo.WriteCallLog();
                m_callinfo.reset();
            }

            Reset();
        } else if (lastAgentStatus == acd::AgentStatusT::AsConnectedState ||
                   lastAgentStatus == acd::AgentStatusT::AsInternalConnectedState ||
                   lastAgentStatus == acd::AgentStatusT::AsSuspendedState ||
                   lastAgentStatus == acd::AgentStatusT::AsConsultConnectedState ||
                   lastAgentStatus == acd::AgentStatusT::AsConferenceState ||
                   lastAgentStatus == acd::AgentStatusT::AsMonitorState ||
                   lastAgentStatus == acd::AgentStatusT::AsInsertState ||
                   lastAgentStatus == acd::AgentStatusT::AsMonitoredState ||
                   lastAgentStatus == acd::AgentStatusT::AsInsertedState) { // 通话中挂断
            if (event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnected_InternalCall ||
                    event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnected_NormalCall ||
                    event.eventType == ims::CallEventTypeT::SG_ThisPartyTransferred_NormalCall ||
                    event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnected_ConsultCall ||
                    event.eventType == ims::CallEventTypeT::SG_ThisPartyTransferred_ConsultCall ||
                    event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnect_ConferenceCall ||
                    event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnect_MonitorCall ||
                    event.eventType == ims::CallEventTypeT::SG_ThisPartyDisconnect_IntrudeCall) { // 本方挂断
                reason = acd::CallEventReasonT::CerIdleNormalSelfHangup;
                m_callinfo.SetReleaseCause(ReleaseCauseT::THISPARTY);
            } else {
                reason = acd::CallEventReasonT::CerIdleNormalOtherHangup;
                m_callinfo.SetReleaseCause(ReleaseCauseT::OTHERPARTY);
            }

            if (0 < m_callTime) {
                m_callTotalTime += m_currStatusTime - m_callTime;
            }

            if (0 < m_answerTime) {
                m_answerTotalTime += m_currStatusTime - m_answerTime;
            }

            m_callinfo.SetAniDnis(event.originalAni, event.originalDnis);
            m_callinfo.SetCallEnd(m_currStatusTime);

            if (m_callinfo.isValid()) { // 如果话单没有起始信息,则不必要写
                m_callinfo.WriteCallLog();
                m_callinfo.reset();
            }

            Reset();
        } else {
            reason = acd::CallEventReasonT::CerIdleIdle;
        }

        if (m_statusChangetype == acd::StatusChangeT::ScBusy) {
            m_agentStatus = acd::AgentStatusT::AsBusyState;
        } else {
            m_agentStatus = acd::AgentStatusT::AsReadyState;
        }

        break;
    }

    case ims::CallStateT::SG_AlertingState: {
        if (!m_callinfo.GetRoutecall()) {
            if (m_callinfo.isValid()) { // 如果话单没有结束信息,则需要写
                m_callinfo.WriteCallLog();
                m_callinfo.reset();
            }

            m_callinfo.Initial(event.sessionid, event.callid, m_agentId, m_agentDn, _m_cur_skill, event.originalAni,
                               event.originalDnis, 0, 0);
        }

        m_callinfo.SetAckBegin(m_currStatusTime);
        m_callinfo.SetCallType(event.otherAttr);
        m_callinfo.SetCallDirect(CallDirectT::INBOUND);

        m_origCaller = event.originalAni;
        m_origCallee = event.originalDnis;
        m_callTime = m_currStatusTime;
        m_callTimes++;
        m_agentStatus = acd::AgentStatusT::AsAlertingState;
        break;
    }

    case ims::CallStateT::SG_HalfAlertingState: {
        if (m_callinfo.isValid()) { // 如果话单没有结束信息,则需要写
            m_callinfo.WriteCallLog();
            m_callinfo.reset();
        }

        m_callinfo.Initial(event.sessionid, event.callid, m_agentId, m_agentDn, _m_cur_skill, event.originalAni,
                           event.originalDnis, 0, 0);
        m_callinfo.SetAckBegin(m_currStatusTime);
        m_callinfo.SetCallDirect(CallDirectT::OUTBOUND);

        m_origCaller = event.originalAni;
        m_origCallee = event.originalDnis;
        m_callTime = m_currStatusTime;
        m_callTimes++;
        m_agentStatus = acd::AgentStatusT::AsHalfAlertingState;
        break;
    }

    case ims::CallStateT::SG_ConnectingState: {
        if (event.eventType == ims::CallEventTypeT::SG_DestSeized_ConsultCall) {
            m_agentStatus = acd::AgentStatusT::AsConsultConnectingState;
        } else if (event.eventType == ims::CallEventTypeT::SG_OtherPartyDisconnected_ConsultCall) {
            m_agentStatus = acd::AgentStatusT::AsConnectingState;
        } else {
            m_callinfo.SetCallType(event.otherAttr);
            m_agentStatus = acd::AgentStatusT::AsConnectingState;
            m_callinfo.SetConnectBegin(m_currStatusTime);
        }

        break;
    }

    case ims::CallStateT::SG_ConnectedState: {
        if (event.eventType == ims::CallEventTypeT::SG_ThisPartyAnswered_InternalCall ||
                event.eventType == ims::CallEventTypeT::SG_ThisPartyAnswered_NormalCall) {
            Record();
            m_callinfo.SetConnectEnd(m_currStatusTime);
            m_callinfo.SetCallBegin(m_currStatusTime);
            m_callinfo.SetRecordFilename(m_recordFilename);
            m_answerTime = m_currStatusTime;
            m_answerTimes++;
            reason = acd::CallEventReasonT::CerTalkOtherCreat;
        } else if (event.eventType == ims::CallEventTypeT::SG_OtherPartyAnswered_InternalCall ||
                   event.eventType == ims::CallEventTypeT::SG_OtherPartyAnswered_NormalCall) {
            Record();
            m_callinfo.SetConnectEnd(m_currStatusTime);
            m_callinfo.SetCallBegin(m_currStatusTime);
            m_callinfo.SetRecordFilename(m_recordFilename);
            m_answerTime = m_currStatusTime;
            m_answerTimes++;
            reason = acd::CallEventReasonT::CerTalkSelfCreat;
        } else if (event.eventType == ims::CallEventTypeT::SG_OtherPartyDisconnected_ConsultCall) {
            reason = acd::CallEventReasonT::CerTalkOtherRetrieve;
        } else {
            reason = acd::CallEventReasonT::CerTalkSelfRetrieve;
        }

        if (event.eventType == ims::CallEventTypeT::SG_OtherPartyAnswered_ConsultCall) {
            m_agentStatus = acd::AgentStatusT::AsConsultConnectedState;
        } else if (event.otherAttr == ims::PartyAttributeT::P_Internal) {
            m_agentStatus = acd::AgentStatusT::AsInternalConnectedState;
        } else {
            m_agentStatus = acd::AgentStatusT::AsConnectedState;
        }

        break;
    }

    case ims::CallStateT::SG_HalfConnectedState:
        m_agentStatus = acd::AgentStatusT::AsHalfConnectedState;
        m_callinfo.SetAckEnd(m_currStatusTime);
        break;

    case ims::CallStateT::SG_SuspendedState:
        m_agentStatus = acd::AgentStatusT::AsSuspendedState;
        break;

    case ims::CallStateT::SG_ConferenceState: {
        if (event.eventType == ims::CallEventTypeT::SG_ThisPartyConferenced_MonitorCall) {
            if (acd::AgentStatusT::AsHalfConnectedState == lastAgentStatus) {
                Record();
                m_callinfo.SetConnectEnd(m_currStatusTime);
                m_callinfo.SetCallBegin(m_currStatusTime);
                m_callinfo.SetCallType(event.otherAttr);
                m_callinfo.SetRecordFilename(m_recordFilename);
                m_answerTime = m_currStatusTime;
                m_answerTimes++;
            }

            m_agentStatus = acd::AgentStatusT::AsMonitorState;
        } else if (event.eventType == ims::CallEventTypeT::SG_OtherPartyConferenced_MonitorCall) {
            m_agentStatus = acd::AgentStatusT::AsMonitoredState;
        } else if (event.eventType == ims::CallEventTypeT::SG_ThisPartyConferenced_IntrudeCall) {
            if (acd::AgentStatusT::AsHalfConnectedState == lastAgentStatus) {
                Record();
                m_callinfo.SetConnectEnd(m_currStatusTime);
                m_callinfo.SetCallBegin(m_currStatusTime);
                m_callinfo.SetCallType(event.otherAttr);
                m_callinfo.SetRecordFilename(m_recordFilename);
                m_answerTime = m_currStatusTime;
                m_answerTimes++;
            }

            m_agentStatus = acd::AgentStatusT::AsInsertState;
        } else if (event.eventType == ims::CallEventTypeT::SG_OtherPartyConferenced_IntrudeCall) {
            m_agentStatus = acd::AgentStatusT::AsInsertedState;
        } else {
            m_agentStatus = acd::AgentStatusT::AsConferenceState;
        }

        break;
    }

    default:
        m_agentStatus = acd::AgentStatusT::AsUnknownState;
        break;
    }

    p_agentEvent->m_agent_event.agentStatus = m_agentStatus;
    p_agentEvent->m_agent_event.reason = reason;

    WriteTraceLog();
    acd_tool::m_send_event_manager.send_event(p_agentEvent, m_handle);
}
Exemplo n.º 3
0
LONG
__cdecl
WriteRefTraceLogEx(
    IN PTRACE_LOG Log,
    IN LONG NewRefCount,
    IN CONST VOID * Context,
    IN CONST VOID * Context1, // optional extra context
    IN CONST VOID * Context2, // optional extra context
    IN CONST VOID * Context3  // optional extra context
    )
/*++

Routine Description:

    Writes a new "extended" entry to the specified ref count trace log.
    The entry written contains the updated reference count, stack backtrace
    leading up to the current caller and extra context information.

Arguments:

    Log - The log to write to.

    NewRefCount - The updated reference count.

    Context  - An uninterpreted context to associate with the log entry.
    Context1 - An uninterpreted context to associate with the log entry.
    Context2 - An uninterpreted context to associate with the log entry.
    Context3 - An uninterpreted context to associate with the log entry.

    NOTE Context1/2/3 are "optional" in that the caller may suppress
    debug display of these values by passing REF_TRACE_EMPTY_CONTEXT
    for each of them.

Return Value:

    Index of entry in log.

--*/
{

    REF_TRACE_LOG_ENTRY entry;
    ULONG hash;
    DWORD cStackFramesSkipped;

    //
    // Initialize the entry.
    //

    RtlZeroMemory(
        &entry,
        sizeof(entry)
        );

    //
    //  Set log entry members.
    //

    entry.NewRefCount = NewRefCount;
    entry.Context = Context;
    entry.Thread = GetCurrentThreadId();
    entry.Context1 = Context1;
    entry.Context2 = Context2;
    entry.Context3 = Context3;

    //
    // Capture the stack backtrace. Normally, we skip two stack frames:
    // one for this routine, and one for RtlCaptureBacktrace() itself.
    // For non-Ex callers who come in via WriteRefTraceLog,
    // we skip three stack frames.
    //

    if (    entry.Context1 == REF_TRACE_EMPTY_CONTEXT
         && entry.Context2 == REF_TRACE_EMPTY_CONTEXT
         && entry.Context3 == REF_TRACE_EMPTY_CONTEXT
         ) {

         cStackFramesSkipped = 2;

    } else {

         cStackFramesSkipped = 1;

    }

    RtlCaptureStackBackTrace(
        cStackFramesSkipped,
        REF_TRACE_LOG_STACK_DEPTH,
        entry.Stack,
        &hash
        );

    //
    // Write it to the log.
    //

    return WriteTraceLog(
        Log,
        &entry
        );

}   // WriteRefTraceLogEx