bool SipXMessageObserver::handleIncomingInfoMessage(SipMessage* pMessage)
{
    bool bRet = false;
    SIPX_INSTANCE_DATA* pInst = (SIPX_INSTANCE_DATA*) pMessage->getResponseListenerData();

    if (NULL != pInst && NULL != pMessage)
    {

        if (mTestResponseCode != 0)  // for unit testing purposes.
        {
            if (mTestResponseCode == 408)   // a timeout response is being tested
            {
                // simulate a timeout ....
                OsTask::delay(1000);
                // respond to whomever sent us the message
                SipMessage sipResponse;
                sipResponse.setOkResponseData(pMessage);
                sipResponse.setResponseFirstHeaderLine(SIP_PROTOCOL_VERSION, mTestResponseCode, "timed out");
                pInst->pSipUserAgent->send(sipResponse);
                return true ;
            }
        }
        else
        {
            // respond to whomever sent us the message
            SipMessage sipResponse;
            sipResponse.setOkResponseData(pMessage);
            pInst->pSipUserAgent->send(sipResponse);
        }

        // Find Line
        UtlString lineId;
        pMessage->getToUri(&lineId);
        UtlString requestUri;
        pMessage->getRequestUri(&requestUri);
        SIPX_LINE hLine = sipxLineLookupHandle(pInst, lineId.data(), requestUri);

        if (!pMessage->isResponse())
        {
            // find call
            UtlString callId;
            pMessage->getCallIdField(&callId);
            SIPX_CALL hCall = sipxCallLookupHandle(callId, pInst->pCallManager);

            if (0 == hCall)
            {
                // we are unaware of the call context
            }

            SIPX_INFO_DATA* pInfoData = new SIPX_INFO_DATA;

            memset((void*)pInfoData, 0, sizeof(SIPX_INFO_DATA));
            pInfoData->infoData.nSize = sizeof(SIPX_INFO_INFO);
            pInfoData->infoData.hCall = hCall;
            pInfoData->infoData.hLine = hLine;
            Url fromUrl;

            pInfoData->infoData.szFromURL = lineId.data();
            pInfoData->infoData.nContentLength = pMessage->getContentLength();

            // get and set the content type
            UtlString contentType;
            pMessage->getContentType(&contentType) ;
            pInfoData->infoData.szContentType = strdup(contentType.data());

            // get the user agent
            UtlString userAgent;
            pMessage->getUserAgentField(&userAgent);
            pInfoData->infoData.szUserAgent = strdup(userAgent.data());

            // get the content
            UtlString body;
            ssize_t dummyLength = pMessage->getContentLength();
            const HttpBody* pBody = pMessage->getBody();
            if (pBody == NULL) {
                return false;
            }
            pBody->getBytes(&body, &dummyLength);
            pInfoData->infoData.pContent = body.data();

            // set the Instance
            pInfoData->pInst = pInst;

            // Create Mutex
            pInfoData->pMutex = new OsRWMutex(OsRWMutex::Q_FIFO);

            UtlVoidPtr* ptr = NULL;
            UtlSListIterator eventListenerItor(*g_pEventListeners);
            while ((ptr = (UtlVoidPtr*) eventListenerItor()) != NULL)
            {
                EVENT_LISTENER_DATA *pData = (EVENT_LISTENER_DATA*) ptr->getValue();
                if (pData->pInst == pInfoData->pInst)
                {
                    pData->pCallbackProc(EVENT_CATEGORY_INFO, &(pInfoData->infoData), pData->pUserData);
                }
            }

            bRet = true;
        } // if (0 != hLine)
    } // if (NULL != pInst && NULL != pMessage)
    return bRet;
}
bool SipXMessageObserver::handleIncomingInfoStatus(SipMessage* pSipMessage)
{
    if (NULL == pSipMessage)
    {
        // something went wrong
        return false;
    }

    SIPX_INFO hInfo = (SIPX_INFO)pSipMessage->getResponseListenerData();
    if (hInfo)
    {
        SIPX_INFOSTATUS_INFO infoStatus;

        memset((void*) &infoStatus, 0, sizeof(SIPX_INFOSTATUS_INFO));

        infoStatus.hInfo = hInfo;
        SIPX_INFO_DATA* pInfoData = sipxInfoLookup(hInfo, SIPX_LOCK_READ);
        infoStatus.nSize = sizeof(SIPX_INFOSTATUS_INFO);
        infoStatus.responseCode = pSipMessage->getResponseStatusCode();
        infoStatus.event = INFOSTATUS_RESPONSE;

        int statusCode = pSipMessage->getResponseStatusCode();
        if (statusCode < 400)
        {
        infoStatus.status = SIPX_MESSAGE_OK;
        }
        else if (statusCode < 500)
        {
            infoStatus.status = SIPX_MESSAGE_FAILURE;
        }
        else if (statusCode < 600)
        {
            infoStatus.status = SIPX_MESSAGE_SERVER_FAILURE;
        }
        else
        {
            infoStatus.status = SIPX_MESSAGE_GLOBAL_FAILURE;
        }

        UtlString sResponseText;
        pSipMessage->getResponseStatusText(&sResponseText);
        infoStatus.szResponseText = sResponseText.data();

        UtlVoidPtr* ptr = NULL;
        UtlSListIterator eventListenerItor(*g_pEventListeners);
        while ((ptr = (UtlVoidPtr*) eventListenerItor()) != NULL)
        {
            EVENT_LISTENER_DATA *pData = (EVENT_LISTENER_DATA*) ptr->getValue();
            if (pInfoData->pInst == pData->pInst)
            {
                pData->pCallbackProc(EVENT_CATEGORY_INFO_STATUS, &infoStatus, pData->pUserData);
            }
        }

        pInfoData->pInst->pSipUserAgent->removeMessageObserver(*(this->getMessageQueue()), (void*)hInfo);

        // release lock
        sipxInfoReleaseLock(pInfoData, SIPX_LOCK_READ);
        // info message has been handled, so go ahead and delete the object
        sipxInfoObjectFree(hInfo);
     }
     return true;
}
bool SipXMessageObserver::handleIncomingInfoStatus(SipMessage* pSipMessage, int messageType)
{
    OsStackTraceLogger stackLogger(FAC_SIPXTAPI, PRI_DEBUG, "SipXMessageObserver::handleIncomingInfoStatus");

    if (NULL == pSipMessage)
    {
        // something went wrong
        return false;
    }
    
    SIPX_INFO hInfo = (SIPX_INFO)pSipMessage->getResponseListenerData();
    if (hInfo)
    {
        SIPX_INFOSTATUS_INFO infoStatus;
        
        memset((void*) &infoStatus, 0, sizeof(SIPX_INFOSTATUS_INFO));
        infoStatus.nSize = sizeof(SIPX_INFOSTATUS_INFO);
        infoStatus.responseCode = pSipMessage->getResponseStatusCode();
        infoStatus.event = INFOSTATUS_RESPONSE;
        
        infoStatus.hInfo = hInfo;
        SIPX_INFO_DATA* pInfoData = sipxInfoLookup(hInfo, SIPX_LOCK_READ, stackLogger);

        if(pInfoData)
        {
            
            int statusCode = pSipMessage->getResponseStatusCode();
            if (statusCode < 400)
            {
                infoStatus.status = SIPX_MESSAGE_OK;
            }
            // May want to add special case for authentication
            //else if(statusCode == HTTP_PROXY_UNAUTHORIZED_CODE || statusCode == HTTP_UNAUTHORIZED_CODE)
            //{
            //    infoStatus.status = 
            //}
            else if (statusCode < 500)
            {
                infoStatus.status = SIPX_MESSAGE_FAILURE;
            }
            else if (statusCode < 600)
            {
                infoStatus.status = SIPX_MESSAGE_SERVER_FAILURE;
            }
            else 
            {
                infoStatus.status = SIPX_MESSAGE_GLOBAL_FAILURE;
            }
            
            UtlString sResponseText;
            pSipMessage->getResponseStatusText(&sResponseText);
            infoStatus.szResponseText = sResponseText.data();
            
            UtlVoidPtr* ptr = NULL;
            OsLock eventLock(*g_pEventListenerLock) ;
            UtlSListIterator eventListenerItor(*g_pEventListeners);
            while ((ptr = (UtlVoidPtr*) eventListenerItor()) != NULL)
            {
                EVENT_LISTENER_DATA *pData = (EVENT_LISTENER_DATA*) ptr->getValue();
                if (pData)
                {
                    if(pInfoData->pInst == pData->pInst)
                    {
                        pData->pCallbackProc(EVENT_CATEGORY_INFO_STATUS, &infoStatus, pData->pUserData);
                    }
                }
                else
                {
                    OsSysLog::add(FAC_SIPXTAPI, PRI_ERR,
                            "SipXMessageObserver::handleIncomingInfoStatus NULL pData  in listener");
                }
            }

            // I think the following is incorrect.  I think this is not added as a global mssage observer, only
            // as an obsever to individual transactions when the INFO is sent.  So this is not needed.
            pInfoData->pInst->pSipUserAgent->removeMessageObserver(*(this->getMessageQueue()), (void*)hInfo);
            
            // release lock
            sipxInfoReleaseLock(pInfoData, SIPX_LOCK_READ, stackLogger);
        }

        // If an INFO was resent with auth credentials, don't remove the INFO object.  Wait
        // for the response to the resend.
        if(messageType != SipMessageEvent::AUTHENTICATION_RETRY)
        {
            // info message has been handled, so go ahead and delete the object    
            sipxInfoObjectFree(hInfo);
        }
     }
     return true;
}