void MpMediaTask::startFrameStartTimer() { if (!ms_bTestMode) { OsStatus result = OS_FAILED; m_pFrameStartCallback = new OsCallback(0, &signalFrameCallback); #ifdef _WIN32 m_pFrameStartTimer = new MpMMTimerWnt(MpMMTimer::Notification); // calculate timer period is microseconds double timerPeriod = (1 / (double)MpMisc.m_audioSamplesPerSec) * MpMisc.m_audioSamplesPerFrame * 1000000; m_pFrameStartTimer->setNotification(m_pFrameStartCallback); result = m_pFrameStartTimer->run((unsigned)timerPeriod); #else m_pFrameStartTimer = new OsTimer(m_pFrameStartCallback); // calculate timer period is milliseconds double timerPeriod = (1 / (double)MpMisc.m_audioSamplesPerSec) * MpMisc.m_audioSamplesPerFrame * 1000; result = m_pFrameStartTimer->periodicEvery(OsTime(0), OsTime((long)timerPeriod)); #endif if (result != OS_SUCCESS) { OsSysLog::add(FAC_MP, PRI_ERR, "MpMediaTask::startFrameStartTimer - timer couldn't be started, audio won't work!"); } } }
void testEnabledWithData() { MprToSpkr* pToSpkr = NULL; OsMsgQ* pSpkQ = NULL; OsMsgQ* pEchoQ = NULL; MpBufferMsg* pSpkMsg = NULL; MpBufferMsg* pEchoMsg = NULL; MpBufPtr pBuf; OsStatus res; // Create message queues to get data from MprToSpkr pSpkQ = new OsMsgQ(MSG_Q_LEN); CPPUNIT_ASSERT(pSpkQ != NULL); pEchoQ = new OsMsgQ(MSG_Q_LEN); CPPUNIT_ASSERT(pEchoQ != NULL); pToSpkr = new MprToSpkr("MprToSpkr", pSpkQ, pEchoQ); CPPUNIT_ASSERT(pToSpkr != NULL); setupFramework(pToSpkr); // pToSpkr enabled, there are buffers on the input 0, message queue // is not full. CPPUNIT_ASSERT(mpSourceResource->enable()); CPPUNIT_ASSERT(pToSpkr->enable()); res = mpFlowGraph->processNextFrame(); CPPUNIT_ASSERT(res == OS_SUCCESS); // Get messages from the queues (wait for 1 second) res = pSpkQ->receive((OsMsg*&)pSpkMsg, OsTime(1000)); CPPUNIT_ASSERT(res == OS_SUCCESS); res = pEchoQ->receive((OsMsg*&)pEchoMsg, OsTime(1000)); CPPUNIT_ASSERT(res == OS_SUCCESS); // Store output buffer for convenience pBuf = mpSourceResource->mLastDoProcessArgs.outBufs[0]; // Buffer is sent to queues and to output CPPUNIT_ASSERT( (mpSinkResource->mLastDoProcessArgs.inBufs[0] == pBuf) && (pSpkMsg->getBuffer().isValid()) && (pEchoMsg->getBuffer() == pBuf) ); // Free received message and stored buffer pSpkMsg->releaseMsg(); pEchoMsg->releaseMsg(); pBuf.release(); // Stop flowgraph haltFramework(); // Free message queue delete pSpkQ; delete pEchoQ; }
// Copy constructor PtPhoneButton::PtPhoneButton(const PtPhoneButton& rPtPhoneButton) : PtComponent(rPtPhoneButton) { mpEventMgr = OsProtectEventMgr::getEventMgr(); if (rPtPhoneButton.mpLamp) mpLamp = new PtPhoneLamp(*(rPtPhoneButton.mpLamp)); else mpLamp = 0; memset(mpInfo, 0, MAX_NAME_LENGTH + 1); if (rPtPhoneButton.mpInfo[0]) { int len = strlen(rPtPhoneButton.mpInfo); if (len > MAX_NAME_LENGTH) len = MAX_NAME_LENGTH; strncpy(mpInfo, rPtPhoneButton.mpInfo, len); mpInfo[len] = 0; } mpClient = rPtPhoneButton.mpClient; if (mpClient && !(mpClient->isStarted())) { mpClient->start(); } mTimeOut = OsTime(PT_CONST_EVENT_WAIT_TIMEOUT, 0); }
// Copy constructor PtPhoneMicrophone::PtPhoneMicrophone(const PtPhoneMicrophone& rPtPhoneMicrophone) : PtComponent(rPtPhoneMicrophone) { mpClient = rPtPhoneMicrophone.mpClient; mTimeOut = OsTime(PT_CONST_EVENT_WAIT_TIMEOUT, 0); mpEventMgr = OsProtectEventMgr::getEventMgr(); }
UtlBoolean MyPlayerListenerPoller::waitForState(PlayerState state) { mSemGuard.acquire() ; UtlBoolean bRetrieved = mStates[state] ; mSemGuard.release() ; while (bRetrieved == FALSE) { OsStatus status = mSemStateChange.acquire(OsTime(miTimeoutSec, 0)) ; if (status == OS_SUCCESS) { mSemGuard.acquire() ; bRetrieved = mStates[state] ; mSemGuard.release() ; } else { osPrintf("Timeout waiting for state %d\n", state) ; for (int i=0; i<MAX_STATES; i++) { osPrintf("\tState %2d: %d\n", i, mStates[i]) ; } break ; } } return bRetrieved ; }
// Constructor PtPhoneSpeaker::PtPhoneSpeaker() : PtComponent(PtComponent::SPEAKER) { mpClient = 0; mTimeOut = OsTime(PT_CONST_EVENT_WAIT_TIMEOUT, 0); mpEventMgr = OsProtectEventMgr::getEventMgr(); }
OsTime OsFileWnt::fileTimeToOsTime(FILETIME ft) { __int64 ll = (((__int64)ft.dwHighDateTime << 32) | ft.dwLowDateTime) - 116444736000000000; // See http://support.microsoft.com/?scid=kb%3Ben-us%3B167296&x=14&y=17 return OsTime((long)(ll / 10000000), (long)((ll / 10) % 1000000)); }
// Constructor PtPhoneMicrophone::PtPhoneMicrophone() : PtComponent(PtComponent::MICROPHONE) { mpClient = 0; mTimeOut = OsTime(PT_CONST_EVENT_WAIT_TIMEOUT, 0); mpEventMgr = OsProtectEventMgr::getEventMgr(); }
// Constructor PtPhoneLamp::PtPhoneLamp() : PtComponent(PtComponent::LAMP) { mpAssociatedButton = 0; mMode = MODE_OFF; mTimeOut = OsTime(PT_CONST_EVENT_WAIT_TIMEOUT, 0); mpEventMgr = OsProtectEventMgr::getEventMgr(); }
PtPhoneMicrophone::PtPhoneMicrophone(TaoClientTask *pClient) : PtComponent(PtComponent::MICROPHONE) { mpClient = pClient; if (mpClient && !(mpClient->isStarted())) { mpClient->start(); } mTimeOut = OsTime(PT_CONST_EVENT_WAIT_TIMEOUT, 0); mpEventMgr = OsProtectEventMgr::getEventMgr(); }
// Constructor PtPhoneButton::PtPhoneButton() : PtComponent(PtComponent::BUTTON) { memset(mpInfo, 0, MAX_NAME_LENGTH + 1); mpClient = 0; mpLamp = 0; mTimeOut = OsTime(PT_CONST_EVENT_WAIT_TIMEOUT, 0); mpEventMgr = OsProtectEventMgr::getEventMgr(); }
PtPhoneSpeaker::PtPhoneSpeaker(TaoClientTask *pClient) : PtComponent(PtComponent::SPEAKER) { mpClient = pClient; if (mpClient && !(mpClient->isStarted())) { mpClient->start(); } mTimeOut = OsTime(PT_CONST_EVENT_WAIT_TIMEOUT, 0); mpEventMgr = OsProtectEventMgr::getEventMgr(); }
// Copy constructor PtPhoneSpeaker::PtPhoneSpeaker(const PtPhoneSpeaker& rPtPhoneSpeaker) : PtComponent(rPtPhoneSpeaker) { mpClient = rPtPhoneSpeaker.mpClient; if (mpClient && !(mpClient->isStarted())) { mpClient->start(); } mTimeOut = OsTime(PT_CONST_EVENT_WAIT_TIMEOUT, 0); mpEventMgr = OsProtectEventMgr::getEventMgr(); }
OsStatus OsMsgDispatcher::post(const OsMsg& msg) { if (mMsgQueue->numMsgs() == mMsgQueue->maxMsgs()) { setMsgsLost(); return OS_LIMIT_REACHED; } else { // Send the message, give it 1 millisecond to send. mMsgQueue->send(msg, OsTime(1)); return OS_SUCCESS; } };
// Start the timer that triggers garbage collection and DB persistence, if it's not running. void RegistrarPersist::scheduleCleanAndPersist() { OsLock mutex(mLock); if (!mIsTimerRunning) { // Start the timer mIsTimerRunning = true; OsSysLog::add(FAC_SIP, PRI_DEBUG, "RegistrarPersist::scheduleCleanAndPersist in %d seconds" ,mPersistInterval); assert(mPersistInterval > 0); mPersistTimer.oneshotAfter(OsTime(mPersistInterval, 0)); } }
PtPhoneLamp::PtPhoneLamp(TaoClientTask *pClient) : PtComponent(PtComponent::LAMP) { mpClient = pClient; if (mpClient && !(mpClient->isStarted())) { mpClient->start(); } mMode = MODE_OFF; mpAssociatedButton = 0; mTimeOut = OsTime(PT_CONST_EVENT_WAIT_TIMEOUT, 0); mpEventMgr = OsProtectEventMgr::getEventMgr(); }
// Copy constructor PtPhoneLamp::PtPhoneLamp(const PtPhoneLamp& rPtPhoneLamp) : PtComponent(rPtPhoneLamp) { mpClient = rPtPhoneLamp.mpClient; if (mpClient && !(mpClient->isStarted())) { mpClient->start(); } if (rPtPhoneLamp.mpAssociatedButton != NULL) mpAssociatedButton = new PtPhoneButton(*rPtPhoneLamp.mpAssociatedButton); else mpAssociatedButton = NULL ; mMode = rPtPhoneLamp.mMode; mTimeOut = OsTime(PT_CONST_EVENT_WAIT_TIMEOUT, 0); mpEventMgr = OsProtectEventMgr::getEventMgr(); }
/* %%Function:DttmCur %%Owner:peterj */ struct DTTM DttmCur() { struct DTTM dttm; struct TIM tim; struct DAT dat; StartUMeas(umOsDateTime); OsTime(&tim); /* get current time */ OsDate(&dat); /* get current date */ StopUMeas(umOsDateTime); dttm.yr = dat.year - dyrBase; dttm.mon = dat.month; dttm.dom = dat.day; dttm.hr = tim.hour; dttm.mint = tim.minutes; dttm.wdy = dat.dayOfWeek; return (dttm); }
PtPhoneButton::PtPhoneButton(TaoClientTask *pClient, const char* name) : PtComponent(PtComponent::BUTTON) { mpEventMgr = OsProtectEventMgr::getEventMgr(); memset(mpInfo, 0, MAX_NAME_LENGTH + 1); if (name ) { int len = strlen(name); len = (len <= MAX_NAME_LENGTH) ? len : MAX_NAME_LENGTH; strncpy(mpInfo, name, len); } mpLamp = 0; mpClient = pClient; if (mpClient && !(mpClient->isStarted())) { mpClient->start(); } mTimeOut = OsTime(PT_CONST_EVENT_WAIT_TIMEOUT, 0); }
// Constructor SipXProxyCseObserver::SipXProxyCseObserver(SipUserAgent& sipUserAgent, const UtlString& dnsName, CallStateEventWriter* pWriter ) : OsServerTask("SipXProxyCseObserver-%d", NULL, 2000), mpSipUserAgent(&sipUserAgent), mpBuilder(NULL), mpWriter(pWriter), mSequenceNumber(0), mFlushTimer(getMessageQueue(), 0) { OsTime timeNow; OsDateTime::getCurTime(timeNow); UtlString event; if (mpWriter) { switch (pWriter->getLogType()) { case CallStateEventWriter::CseLogFile: mpBuilder = new CallStateEventBuilder_XML(dnsName); break; case CallStateEventWriter::CseLogDatabase: mpBuilder = new CallStateEventBuilder_DB(dnsName); break; } if (mpBuilder) { if (pWriter->openLog()) { mpBuilder->observerEvent(mSequenceNumber, timeNow, CallStateEventBuilder::ObserverReset, "SipXProxyCseObserver"); mpBuilder->finishElement(event); if (!mpWriter->writeLog(event.data())) { OsSysLog::add(FAC_SIP, PRI_ERR, "SipXProxyCseObserver initial event log write failed - disabling writer"); mpWriter = NULL; } else { mpWriter->flush(); // try to ensure that at least the sequence restart gets to the file } } else { OsSysLog::add(FAC_SIP, PRI_ERR, "SipXProxyCseObserver initial event log write failed - disabling writer"); mpWriter = NULL; // Set correct state even if nothing is written mpBuilder->observerEvent(mSequenceNumber, timeNow, CallStateEventBuilder::ObserverReset, ""); mpBuilder->finishElement(event); } } } // set up periodic timer to flush log file mFlushTimer.periodicEvery(OsTime(), OsTime(SipXProxyCallStateFlushInterval, 0)) ; // Register to get incoming requests sipUserAgent.addMessageObserver(*getMessageQueue(), SIP_BYE_METHOD, TRUE, // Requests, FALSE, //Responses, TRUE, //Incoming, FALSE, //OutGoing, "", //eventName, NULL, // any session NULL // no observerData ); sipUserAgent.addMessageObserver(*getMessageQueue(), SIP_INVITE_METHOD, TRUE, // Requests, TRUE, //Responses, TRUE, //Incoming, FALSE, //OutGoing, "", //eventName, NULL, // any session NULL // no observerData ); sipUserAgent.addMessageObserver(*getMessageQueue(), SIP_REFER_METHOD, TRUE, // Requests, FALSE, //Responses, TRUE, //Incoming, FALSE, //OutGoing, "", //eventName, NULL, // any session NULL // no observerData ); }
/// Check the signature and parse the identity bool SipXauthIdentity::decode(const UtlString& identityValue, const UtlString& callId, const UtlString& fromTag, DialogRule bindRule ) { /** * See SipXauthIdentity Encoding comment at the top of the file */ Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipXauthIdentity::decode " "parse '%s'", identityValue.data() ); mIdentity.remove(0); mIsValidIdentity = FALSE; bool decodeError = false; // false iff the identity was correctly signed and successfully parsed UtlString decodedIdentity; unsigned long epochTimestamp = 0; UtlString timestamp; UtlString actualSignatureHash; bool isBound = false; Url encodedUrl(identityValue, Url::NameAddr); if (Url::SipUrlScheme == encodedUrl.getScheme()) { // Only proceed if the URL parsing succeeded // Extract the identity encodedUrl.getIdentity(decodedIdentity); // Extract signature parameter UtlString signatureParamValue; if (encodedUrl.getUrlParameter(SignatureUrlParamName, signatureParamValue)) { // only proceed if signature parameter was found RegEx signatureRegEx(SignatureRegEx); if (signatureRegEx.Search(signatureParamValue)) { UtlString secondSeparator; isBound = ( signatureRegEx.MatchString(&secondSeparator,2) && secondSeparator.isNull()); // there is only one ':' separator if ( (requireDialogBinding == bindRule) // must be bound && ! isBound ) { decodeError = true; Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipXauthIdentity::decode " "'%s' is an unbound identity", identityValue.data() ); } else { // extract timestamp if ( !signatureRegEx.MatchString(×tamp,1) || !from_string(epochTimestamp, timestamp) ) { decodeError = true; Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipXauthIdentity::decode " "'%s' invalid timestamp", identityValue.data() ); } // extract signature else if (!signatureRegEx.MatchString(&actualSignatureHash,3)) { decodeError = true; Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipXauthIdentity::decode '%s' missing hash", identityValue.data() ); } } } else { decodeError = true; Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipXauthIdentity::decode " "'%s' invalid signature format", identityValue.data() ); } } else { decodeError = true; Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipXauthIdentity::decode " "'%s' missing '%s' param", identityValue.data(), SignatureUrlParamName ); } } else { decodeError = true; Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipXauthIdentity::decode " "'%s' URL parsing failed", identityValue.data() ); } // validate timestamp if (!decodeError && !sSignatureValidityInterval.isNoWait()) { // timestamp validity check if (epochTimestamp + sSignatureValidityInterval.seconds() < OsDateTime::getSecsSinceEpoch()) { decodeError = true; OsDateTime generateDate(OsTime(epochTimestamp,0)); UtlString generateTimeString; generateDate.getIsoTimeStringZ(generateTimeString); Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipXauthIdentity::decode(%s)" " timestamp '%lX' from '%s' too old with interval of '%d' seconds", identityValue.data(), epochTimestamp, generateTimeString.data(), sSignatureValidityInterval.seconds() ); } } // validate signature hash if (!decodeError) { UtlString validSignature; // signature-hash=MD5(<timestamp><secret><from-tag><call-id><identity>) NetMd5Codec signatureHash; signatureHash.hash(timestamp); signatureHash.hash(sSignatureSecret); if (isBound) { signatureHash.hash(fromTag); signatureHash.hash(callId); } signatureHash.hash(decodedIdentity); signatureHash.appendHashValue(validSignature); if (validSignature.compareTo(actualSignatureHash) == 0) { // the signature checks out mIdentity = decodedIdentity; mIsValidIdentity = TRUE; } else { Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipXauthIdentity::decode " "'%s' invalid signature '%s' != '%s'", identityValue.data(), actualSignatureHash.data(), validSignature.data() ); } } return mIsValidIdentity; }
void testMprDelay() { RTL_START(10000000); int i; // Create source (input) and sink (output) resources. MpTestResource sourceResource("TestSource", 0, 0, 1, 1); sourceResource.setGenOutBufMask(1); sourceResource.setOutSignalType(MpTestResource::MP_SINE_SAW); sourceResource.setSignalAmplitude(0, 16000); sourceResource.setSpeechType(0, MP_SPEECH_SILENT); MpTestResource sinkResource("TestSink", 1, 1, 0, 0); UtlString buffer; MprDelay delayResource("TestDelay", TEST_DELAY_FRAMES); try { // Add source and sink resources to flowgraph and link them together. CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, mpFlowGraph->addResource(sourceResource)); CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, mpFlowGraph->addResource(sinkResource)); CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, mpFlowGraph->addResource(delayResource)); CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, mpFlowGraph->addLink(sourceResource, 0, delayResource, 0)); CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, mpFlowGraph->addLink(delayResource, 0, sinkResource, 0)); // Create a queue.. OsMsg* pMsg; OsMsgDispatcher notfDisp; // Now we enable the flowgraph.. Which should enable resources. CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, mpFlowGraph->enable()); CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, mpFlowGraph->start()); mpFlowGraph->setNotificationDispatcher(¬fDisp); // TESTING BEGINS // Generate NULL frames for (i = 0; i < 2*TEST_DELAY_FRAMES; i++) { mpFlowGraph->processNextFrame(); CPPUNIT_ASSERT_EQUAL(0, notfDisp.numMsgs()); } CPPUNIT_ASSERT_EQUAL(0, delayResource.getDelayMs()); // Generate inactive frames sourceResource.setGenOutBufMask(1); sourceResource.setSpeechType(0, MP_SPEECH_SILENT); for (i = 0; i < 2*TEST_DELAY_FRAMES; i++) { mpFlowGraph->processNextFrame(); CPPUNIT_ASSERT_EQUAL(0, notfDisp.numMsgs()); } CPPUNIT_ASSERT_EQUAL(0, delayResource.getDelayMs()); // Generate first active frame sourceResource.setGenOutBufMask(1); sourceResource.setSpeechType(0, MP_SPEECH_ACTIVE); mpFlowGraph->processNextFrame(); CPPUNIT_ASSERT_EQUAL(1, notfDisp.numMsgs()); CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, notfDisp.receive((OsMsg*&)pMsg, OsTime(10))); CPPUNIT_ASSERT_EQUAL(MpResNotificationMsg::MPRNM_DELAY_SPEECH_STARTED, (MpResNotificationMsg::RNMsgType)((MpResNotificationMsg*)pMsg)->getMsg()); // Add few frames to check getDelayFrames() correctness. for (i = 0; i < TEST_DELAY_FRAMES/2-1; i++) { if (i%2 == 1) sourceResource.setGenOutBufMask(0); else sourceResource.setGenOutBufMask(1); mpFlowGraph->processNextFrame(); CPPUNIT_ASSERT_EQUAL(0, notfDisp.numMsgs()); } sourceResource.setGenOutBufMask(1); CPPUNIT_ASSERT_EQUAL(TEST_DELAY_FRAMES/2, delayResource.getDelayFrames()); // Start Play MprDelay::startPlay("TestDelay", *mpFlowGraph->getMsgQ()); // Push frames to test behaviour during the play. for (i = 0; i < TEST_DELAY_FRAMES; i++) { if (i%2 == 1) sourceResource.setGenOutBufMask(0); else sourceResource.setGenOutBufMask(1); mpFlowGraph->processNextFrame(); CPPUNIT_ASSERT_EQUAL(0, notfDisp.numMsgs()); } CPPUNIT_ASSERT_EQUAL(TEST_DELAY_FRAMES/2, delayResource.getDelayFrames()); // Test quiescent state during the play. sourceResource.setGenOutBufMask(1); sourceResource.setSpeechType(0, MP_SPEECH_ACTIVE); for (i = 0; i < TEST_DELAY_FRAMES; i++) { mpFlowGraph->processNextFrame(); CPPUNIT_ASSERT_EQUAL(0, notfDisp.numMsgs()); } sourceResource.setSpeechType(0, MP_SPEECH_SILENT); int delay = delayResource.getDelayFrames(); for (i = 0; i < delay; i++) { CPPUNIT_ASSERT_EQUAL(0, notfDisp.numMsgs()); mpFlowGraph->processNextFrame(); } CPPUNIT_ASSERT_EQUAL(1, notfDisp.numMsgs()); CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, notfDisp.receive((OsMsg*&)pMsg, OsTime(10))); CPPUNIT_ASSERT_EQUAL(MpResNotificationMsg::MPRNM_DELAY_QUIESCENCE, (MpResNotificationMsg::RNMsgType)((MpResNotificationMsg*)pMsg)->getMsg()); // Stop Play MprDelay::stopPlay("TestDelay", *mpFlowGraph->getMsgQ()); // Generate first active frame sourceResource.setGenOutBufMask(1); sourceResource.setSpeechType(0, MP_SPEECH_ACTIVE); mpFlowGraph->processNextFrame(); CPPUNIT_ASSERT_EQUAL(1, notfDisp.numMsgs()); CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, notfDisp.receive((OsMsg*&)pMsg, OsTime(10))); CPPUNIT_ASSERT_EQUAL(MpResNotificationMsg::MPRNM_DELAY_SPEECH_STARTED, (MpResNotificationMsg::RNMsgType)((MpResNotificationMsg*)pMsg)->getMsg()); // Add more frames to cause MprDelay's overflow. for (i = 0; i < 2*TEST_DELAY_FRAMES; i++) { if (i%2 == 1) sourceResource.setGenOutBufMask(0); else sourceResource.setGenOutBufMask(1); mpFlowGraph->processNextFrame(); CPPUNIT_ASSERT_EQUAL(0, notfDisp.numMsgs()); } CPPUNIT_ASSERT_EQUAL(TEST_DELAY_FRAMES, delayResource.getDelayFrames()); // TESTING END mpFlowGraph->processNextFrame(); // Remove resources from flowgraph. We should remove them explicitly // here, because they are stored on the stack and will be destroyed. CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, mpFlowGraph->removeResource(sinkResource)); CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, mpFlowGraph->removeResource(sourceResource)); CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, mpFlowGraph->removeResource(delayResource)); mpFlowGraph->processNextFrame(); } catch (CppUnit::Exception& e) { // Remove resources from flowgraph. We should remove them explicitly // here, because they are stored on the stack and will be destroyed. // If we will not catch this assert we'll have this resources destroyed // while still referenced in flowgraph, causing crash. if (sinkResource.getFlowGraph() != NULL) { CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, mpFlowGraph->removeResource(sinkResource)); } if (sourceResource.getFlowGraph() != NULL) { CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, mpFlowGraph->removeResource(sourceResource)); } if (delayResource.getFlowGraph() != NULL) { CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, mpFlowGraph->removeResource(delayResource)); } mpFlowGraph->processNextFrame(); // Rethrow exception. throw(e); } RTL_WRITE("testMprDelay.rtl"); RTL_STOP }
RedirectPlugin::LookUpStatus SipRedirectorJoin::lookUpDialog( const UtlString& requestString, const UtlString& incomingCallId, ContactList& contactList, RedirectPlugin::RequestSeqNo requestSeqNo, int redirectorNo, SipRedirectorPrivateStorage*& privateStorage, const char* subscribeUser, State stateFilter) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "%s::lookUpDialog requestString = '%s', " "requestSeqNo = %d, redirectorNo = %d, privateStorage = %p, " "subscribeUser = '******', stateFilter = %d", mLogName.data(), requestString.data(), requestSeqNo, redirectorNo, privateStorage, subscribeUser, stateFilter); // If the private storage is already allocated, then this is a // reprocessing cycle, and the dialog to pick up (if any) is // recorded in private storage. if (privateStorage) { // Cast the private storage pointer to the right type so we can // access the needed dialog information. SipRedirectorPrivateStorageJoin* dialog_info = dynamic_cast<SipRedirectorPrivateStorageJoin*> (privateStorage); if (dialog_info->mTargetDialogDuration != SipRedirectorPrivateStorageJoin::TargetDialogDurationAbsent) { // A dialog has been recorded. Construct a contact for it. // Beware that as recorded in the dialog event notice, the // target URI is in addr-spec format; any parameters are URI // parameters. (Field parameters have been broken out in // param elements.) Url contact_URI(dialog_info->mTargetDialogLocalURI, TRUE); // Construct the Join: header value the caller should use. UtlString header_value(dialog_info->mTargetDialogCallId); // Note that according to RFC 3891, the to-tag parameter is // the local tag at the destination of the INVITE/Join. // But the INVITE/Join goes to the end of the call that // we queried with SUBSCRIBE, so the to-tag in the // Join: header is the *local* tag from the NOTIFY. header_value.append(";to-tag="); header_value.append(dialog_info->mTargetDialogLocalTag); header_value.append(";from-tag="); header_value.append(dialog_info->mTargetDialogRemoteTag); // Add a header parameter to specify the Join: header. contact_URI.setHeaderParameter("Join", header_value.data()); // We add a header parameter to cause the redirection to // include a "Require: join" header. Then if the caller // phone does not support INVITE/Join:, the pick-up will // fail entirely. Without it, if the caller phone does not // support INVITE/Join, the caller will get a // simultaneous incoming call from the executing phone. // Previously, we thought the latter behavior was better, but // it is not -- Consider if the device is a gateway from the // PSTN. Then the INVITE/Join will generate an outgoing // call to the calling phone. contact_URI.setHeaderParameter(SIP_REQUIRE_FIELD, SIP_JOIN_EXTENSION); // Record the URI as a contact. contactList.add( contact_URI, *this ); } // We do not need to suspend this time. return RedirectPlugin::SUCCESS; } else { UtlString userId; Url requestUri(requestString); requestUri.getUserId(userId); Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "%s::lookUpDialog userId '%s'", mLogName.data(), userId.data()); // Construct the SUBSCRIBE for the call join. SipMessage subscribe; UtlString subscribeRequestUri("sip:"); // The user of the request URI is our subscribeUser parameter. subscribeRequestUri.append(subscribeUser); subscribeRequestUri.append("@"); subscribeRequestUri.append(mDomain); // Construct a Call-Id for the SUBSCRIBE. UtlString callId; CallId::getNewCallId(callId); // Construct the From: value. UtlString fromUri; { // Get the local address and port. UtlString address; int port; mpSipUserAgent->getLocalAddress(&address, &port); // Use the first 8 chars of the MD5 of the Call-Id as the from-tag. NetMd5Codec encoder; UtlString tag; encoder.encode(callId.data(), tag); tag.remove(8); // Assemble the URI. SipMessage::buildSipUri(&fromUri, address.data(), port, NULL, // protocol NULL, // user NULL, // userLabel, tag.data()); } // Set the standard request headers. // Allow the SipUserAgent to fill in Contact:. subscribe.setRequestData( SIP_SUBSCRIBE_METHOD, subscribeRequestUri.data(), // request URI fromUri, // From: subscribeRequestUri.data(), // To: callId, mCSeq); // Increment CSeq and roll it over if necessary. mCSeq++; mCSeq &= 0x0FFFFFFF; // Set the Expires header. // If "1 second subscriptions" is set (needed for some versions // of Snom phones), use a 1-second subscription. Otherwise, use // a 0-second subscription, so we get just one NOTIFY. subscribe.setExpiresField(mOneSecondSubscription ? 1 : 0); // Set the "Event: dialog" header. subscribe.setEventField("dialog"); // Set the "Accept: application/dialog-info+xml" header. // Not strictly necessary (per the I-D), but it makes the SUBSCRIBE // more strictly compliant. subscribe.setHeaderValue(SIP_ACCEPT_FIELD, DIALOG_EVENT_CONTENT_TYPE); // Set the References header for tracing dialog associations. { UtlString referencesValue(incomingCallId); referencesValue.append(";rel=inquiry"); subscribe.setHeaderValue(SIP_REFERENCES_FIELD, referencesValue); } // Send the SUBSCRIBE. mpSipUserAgent->send(subscribe); // Allocate private storage. SipRedirectorPrivateStorageJoin *storage = new SipRedirectorPrivateStorageJoin(requestSeqNo, redirectorNo); privateStorage = storage; // Record the Call-Id of the SUBSCRIBE, so we can correlated the // NOTIFYs with it. storage->mSubscribeCallId = callId; // Record the state filtering criterion. storage->mStateFilter = stateFilter; // If we are printing debug messages, record when the SUBSCRIBE // was sent, so we can report how long it took to get the NOTIFYs. if (Os::Logger::instance().willLog(FAC_SIP, PRI_DEBUG)) { OsDateTime::getCurTime(storage->mSubscribeSendTime); } // Set the timer to resume. storage->mTimer.oneshotAfter(OsTime(mWaitSecs, mWaitUSecs)); // Suspend processing the request. return RedirectPlugin::SEARCH_PENDING; } }
// Realizes the player by initiating a connection to the target, allocates // buffers, etc. OsStatus MpStreamPlayer::realize(UtlBoolean bBlock /* = TRUE */) { OsStatus status = OS_FAILED ; OsEvent eventHandle ; intptr_t eventData ; // Only proceed if we have a flow graph and the player is unrealized. if (getState() == PlayerUnrealized) { // Create an mpQueueEvent object to signal state changes in from // the MpStreamFeeder mpQueueEvent = new OsQueuedEvent(*getMessageQueue(), 0); // Realize the stream if (mSourceType == SourceUrl) { if (mpMsgQ != NULL) { MpStreamMsg msg(MpStreamMsg::STREAM_REALIZE_URL, mTarget, NULL, &eventHandle, mpQueueEvent, mFlags, (intptr_t) new Url(mUrl)) ; status = mpMsgQ->send(msg) ; } } else if (mSourceType == SourceBuffer) { if (mpMsgQ != NULL) { MpStreamMsg msg(MpStreamMsg::STREAM_REALIZE_BUFFER, mTarget, NULL, &eventHandle, mpQueueEvent, mFlags, (intptr_t) mpBuffer) ; status = mpMsgQ->send(msg) ; } } if (status == OS_SUCCESS) { // Wait for a response status = eventHandle.wait(OsTime(MAX_REALIZE_WAIT, 0)) ; if (status == OS_SUCCESS) { if (eventHandle.getEventData(eventData) == OS_SUCCESS) { mHandle = (StreamHandle) eventData ; if (mHandle != 0) mbRealized = TRUE ; } else { mHandle = NULL ; } } else { mHandle = NULL ; } } } if (mHandle == 0) { mState = PlayerDestroyed ; status = OS_FAILED ; mSemStateChange.release() ; } if (status == OS_SUCCESS) { // Start Server task if successfull if (start() == TRUE) { // Block while waiting for prefetch (if requested) if (bBlock) { while (getState() == PlayerUnrealized) { mSemStateChange.acquire(); } } else { // Wait for task to startup while (!isStarted()) { OsTask::yield() ; } } } else { syslog(FAC_STREAMING, PRI_CRIT, "Failed to create thread for MpStreamPlayer") ; // Unable to create thread; attempt to clean up status = OS_FAILED ; MpStreamMsg msgStop(MpStreamMsg::STREAM_STOP, mTarget, mHandle); mpMsgQ->send(msgStop) ; MpStreamMsg msgDestroy(MpStreamMsg::STREAM_DESTROY, mTarget, mHandle); mpMsgQ->send(msgDestroy) ; // YIKES: This is hard to recover from, we don't have a message queue // to wait for a response from the lower layers. If someone deletes // this immediately after this call, the lower layers could choke // on a now-deleted mpQueueEvent. There are two options that I can // think of: 1) garbage collect the player after some long period of // time, 2) block the thread context for some reasonable amount of // time. I'm going with #2 for now... OsTask::delay(1000) ; mbRealized = FALSE ; mState = PlayerDestroyed ; mSemStateChange.release() ; } } return status ; }
// Constructor SipXProxyCseObserver::SipXProxyCseObserver(SipUserAgent& sipUserAgent, const UtlString& dnsName, CallStateEventWriter* pWriter ) : OsServerTask("SipXProxyCseObserver-%d", NULL, 2000), SipOutputProcessor( CSE_AGENT_OUTPUT_PROC_PRIO ), mpSipUserAgent(&sipUserAgent), mpBuilder(NULL), mpWriter(pWriter), mSequenceNumber(0), mFlushTimer(getMessageQueue(), 0), mCallTransMutex(OsMutex::Q_FIFO) { OsTime timeNow; OsDateTime::getCurTime(timeNow); UtlString event; if (mpWriter) { switch (pWriter->getLogType()) { case CallStateEventWriter::CseLogFile: mpBuilder = new CallStateEventBuilder_XML(dnsName); break; case CallStateEventWriter::CseLogDatabase: mpBuilder = new CallStateEventBuilder_DB(dnsName); break; } if (mpBuilder) { if (pWriter->openLog()) { mpBuilder->observerEvent(mSequenceNumber, timeNow, CallStateEventBuilder::ObserverReset, "SipXProxyCseObserver"); mpBuilder->finishElement(event); if (!mpWriter->writeLog(event.data())) { Os::Logger::instance().log(FAC_SIP, PRI_ERR, "SipXProxyCseObserver initial event log write failed - disabling writer"); mpWriter = NULL; } else { mpWriter->flush(); // try to ensure that at least the sequence restart gets to the file } } else { Os::Logger::instance().log(FAC_SIP, PRI_ERR, "SipXProxyCseObserver initial event log write failed - disabling writer"); mpWriter = NULL; // Set correct state even if nothing is written mpBuilder->observerEvent(mSequenceNumber, timeNow, CallStateEventBuilder::ObserverReset, ""); mpBuilder->finishElement(event); } } } // set up periodic timer to flush log file mFlushTimer.periodicEvery(OsTime(), OsTime(SipXProxyCallStateFlushInterval, 0)) ; // Register to get incoming requests sipUserAgent.addMessageObserver(*getMessageQueue(), SIP_BYE_METHOD, TRUE, // Requests, FALSE, //Responses, TRUE, //Incoming, FALSE, //OutGoing, "", //eventName, NULL, // any session NULL // no observerData ); sipUserAgent.addMessageObserver(*getMessageQueue(), SIP_INVITE_METHOD, TRUE, // Requests, FALSE, //Responses, TRUE, //Incoming, FALSE, //OutGoing, "", //eventName, NULL, // any session NULL // no observerData ); sipUserAgent.addMessageObserver(*getMessageQueue(), SIP_REFER_METHOD, TRUE, // Requests, FALSE, //Responses, TRUE, //Incoming, FALSE, //OutGoing, "", //eventName, NULL, // any session NULL // no observerData ); sipUserAgent.addSipOutputProcessor( this ); // set up periodic timer to cleanup dead calls in the CallTransMap mpCleanupTimeoutCallback = new OsCallback((void*)this, CleanupTransMap); mpCleanupMapTimer = new OsTimer(*mpCleanupTimeoutCallback); mpCleanupMapTimer->periodicEvery(OsTime(), OsTime(SipXProxyCallStateCleanupInterval, 0)) ; }