Example #1
0
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!");
      }
   }
}
Example #2
0
   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;
   }
Example #3
0
// 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);
}
Example #4
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 ;
}
Example #6
0
// Constructor
PtPhoneSpeaker::PtPhoneSpeaker()
: PtComponent(PtComponent::SPEAKER)
{
        mpClient = 0;
        mTimeOut = OsTime(PT_CONST_EVENT_WAIT_TIMEOUT, 0);
        mpEventMgr = OsProtectEventMgr::getEventMgr();
}
Example #7
0
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));
}
Example #8
0
// Constructor
PtPhoneMicrophone::PtPhoneMicrophone()
: PtComponent(PtComponent::MICROPHONE)
{
        mpClient = 0;
        mTimeOut = OsTime(PT_CONST_EVENT_WAIT_TIMEOUT, 0);
        mpEventMgr = OsProtectEventMgr::getEventMgr();

}
Example #9
0
// Constructor
PtPhoneLamp::PtPhoneLamp()
: PtComponent(PtComponent::LAMP)
{
        mpAssociatedButton = 0;
        mMode = MODE_OFF;
        mTimeOut = OsTime(PT_CONST_EVENT_WAIT_TIMEOUT, 0);
        mpEventMgr = OsProtectEventMgr::getEventMgr();
}
Example #10
0
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();
}
Example #11
0
// 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();
}
Example #12
0
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();
}
Example #13
0
// 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();
}
Example #14
0
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;
   }
};
Example #15
0
// 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));
   }
}
Example #16
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();
}
Example #17
0
// 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);
}
Example #19
0
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);
}
Example #20
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(&timestamp,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;
}
Example #22
0
   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(&notfDisp);

         // 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
   }
Example #23
0
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 = '%s', 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;
   }
}
Example #24
0
// 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)) ;
}