UtlBoolean SipSubscribeServer::enableEventType(const char* eventTypeToken,
                                             SipUserAgent* userAgent,
                                             SipPublishContentMgr* contentMgr,
                                             SipSubscribeServerEventHandler* eventHandler,
                                             SipSubscriptionMgr* subscriptionMgr)
{
    UtlBoolean addedEvent = FALSE;
    UtlString eventName(eventTypeToken ? eventTypeToken : "");
    lockForWrite();
    // Only add the event support if it does not already exist;
    SubscribeServerEventData* eventData = 
        (SubscribeServerEventData*) mEventDefinitions.find(&eventName);
    if(!eventData)
    {
        addedEvent = TRUE;
        eventData = new SubscribeServerEventData();
        *((UtlString*)eventData) = eventName;
        eventData->mpEventSpecificUserAgent = userAgent ? userAgent : mpDefaultUserAgent;
        eventData->mpEventSpecificContentMgr = contentMgr ? contentMgr : mpDefaultContentMgr;
        eventData->mpEventSpecificHandler = eventHandler ? eventHandler : mpDefaultEventHandler;
        eventData->mpEventSpecificSubscriptionMgr = subscriptionMgr ? subscriptionMgr : mpDefaultSubscriptionMgr;
        mEventDefinitions.insert(eventData);

        // Register an interest in SUBSCRIBE requests and NOTIFY responses
        // for this event type
        eventData->mpEventSpecificUserAgent->addMessageObserver(*(getMessageQueue()),
                                                                SIP_SUBSCRIBE_METHOD,
                                                                TRUE, // requests
                                                                FALSE, // not reponses
                                                                TRUE, // incoming
                                                                FALSE, // no outgoing
                                                                eventName,
                                                                NULL,
                                                                NULL);
        eventData->mpEventSpecificUserAgent->addMessageObserver(*(getMessageQueue()),
                                                                SIP_NOTIFY_METHOD,
                                                                FALSE, // no requests
                                                                TRUE, // reponses
                                                                TRUE, // incoming
                                                                FALSE, // no outgoing
                                                                eventName,
                                                                NULL,
                                                                NULL);

        // Register the callback for changes that occur in the
        // publish content manager
        eventData->mpEventSpecificContentMgr->setContentChangeObserver(eventName,
            this, contentChangeCallback);
    }

    unlockForWrite();

    return(addedEvent);
}
// Adds a buffer to the playlist
OsStatus MpStreamPlaylistPlayer::add(UtlString* pBuffer, int flags)
{
   PlayListEntry* e = new PlayListEntry();
   int index = mPlayListDb->entries();

   e->sourceType = SourceBuffer;
   e->pBuffer = pBuffer;
   e->flags = flags;
   e->pQueuedEvent = new OsQueuedEvent(*getMessageQueue(), (void*)index);
   e->index = index ;

   mPlayListDb->append(e);

   return OS_SUCCESS;
}
void
SipRedirectServer::resumeRequest(RedirectPlugin::RequestSeqNo requestSeqNo,
                                 int redirectorNo)
{
   // Create the appropriate message.
   RedirectResumeMsg message = RedirectResumeMsg(requestSeqNo, redirectorNo);

   // Send the message to the redirect server.
   // Note that send() copies its argument.
   getMessageQueue()->send(message);

   Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipRedirectServer::resumeRequest "
                 "Redirector %d sent message to resume request %d",
                 redirectorNo, requestSeqNo);
}
Exemple #4
0
// Constructor
SipPimClient::SipPimClient(SipUserAgent& userAgent,
                           Url& presentityAor)
{
    presentityAor.toString(mFromField);
    mPresentityAor = presentityAor;
    mpUserAgent = &userAgent;

    // Register to get incoming MESSAGE requests
    OsMsgQ* myQueue = getMessageQueue();
    userAgent.addMessageObserver(*myQueue,
                                SIP_MESSAGE_METHOD,
                                TRUE, // requests
                                FALSE, // responces
                                TRUE, // incoming
                                FALSE); // outgoing

}
/// Constructor
RegistrarPersist::RegistrarPersist(SipRegistrar& sipRegistrar) :
   OsServerTask("RegistrarPersist"),
   mLock(OsBSem::Q_PRIORITY, OsBSem::FULL),
   mIsTimerRunning(false),
   mPersistTimer(getMessageQueue(), 0),
   mRegistrar(sipRegistrar),
   mPersistInterval(-1)
{
   // Get the persist interval.  This configuration parameter is provided mainly for
   // testing and debugging.  Usually it is not set explicitly in the configuration file.
   mRegistrar.getConfigDB()->get("SIP_REGISTRAR_PERSIST_INTERVAL", mPersistInterval);
   if (mPersistInterval == -1)
   {
      mPersistInterval = SIP_REGISTRAR_DEFAULT_PERSIST_INTERVAL;
   }
   OsSysLog::add(FAC_SIP, PRI_DEBUG, "RegistrarPersist::RegistrarPersist "
                 "persist interval = %d seconds", mPersistInterval);
};
UtlBoolean SipSubscribeServer::disableEventType(const char* eventTypeToken,
                                             SipUserAgent*& userAgent,
                                             SipPublishContentMgr*& contentMgr,
                                             SipSubscribeServerEventHandler*& eventHandler,
                                             SipSubscriptionMgr*& subscriptionMgr)
{
    UtlBoolean removedEvent = FALSE;
    UtlString eventName(eventTypeToken ? eventTypeToken : "");
    lockForWrite();
    // Only add the event support if it does not already exist;
    SubscribeServerEventData* eventData = 
        (SubscribeServerEventData*) mEventDefinitions.remove(&eventName);
    if(eventData)
    {
        removedEvent = TRUE;
        userAgent = eventData->mpEventSpecificUserAgent == mpDefaultUserAgent ? 
                        NULL : eventData->mpEventSpecificUserAgent;
        contentMgr = eventData->mpEventSpecificContentMgr == mpDefaultContentMgr ? 
                        NULL : eventData->mpEventSpecificContentMgr;
        eventHandler = eventData->mpEventSpecificHandler == mpDefaultEventHandler ?
                        NULL : eventData->mpEventSpecificHandler;
        subscriptionMgr = eventData->mpEventSpecificSubscriptionMgr == mpDefaultSubscriptionMgr ?
                        NULL : eventData->mpEventSpecificSubscriptionMgr;

        // Unregister interest in SUBSCRIBE requests and NOTIFY
        // responses for this event type
        eventData->mpEventSpecificUserAgent->removeMessageObserver(*(getMessageQueue()));


        delete eventData;
        eventData = NULL;
    }
    else
    {
        userAgent = NULL;
        contentMgr = NULL;
        eventHandler = NULL;
        subscriptionMgr = NULL;
    }

    unlockForWrite();

    return(removedEvent);
}
// Destructor
SipRefreshManager::~SipRefreshManager()
{
    // Do not delete mpUserAgent ,mpDialogMgr.  They
    // may be used else where and need to be deleted outside the
    // SipRefreshManager.

    // Stop receiving SUBSCRIBE responses
    mpUserAgent->removeMessageObserver(*(getMessageQueue()));

    // Wait until this OsServerTask has stopped or handleMethod
    // might access something we are about to delete here.
    waitUntilShutDown();

    // Delete the event type strings
    mEventTypes.destroyAll();

    // Unsubscribe to anything that is in the list
    stopAllRefreshes();
    // mRefreshes should now be empty
}
UtlBoolean SipPublishServer::disableEventType(const char* eventType)
{
    UtlString eventName(eventType);
    lockForWrite();

    PublishServerEventData* eventData =
       dynamic_cast <PublishServerEventData*> (mEventDefinitions.remove(&eventName));

    if (eventData)
    {
        // Unregister interest in PUBLISH requests for this event type
        eventData->mpEventSpecificUserAgent->removeMessageObserver(*(getMessageQueue()));

        delete eventData;
    }

    unlockForWrite();

    return eventData != NULL;
}
Exemple #9
0
UtlBoolean SipSubscribeServer::disableEventType(const char* eventType)
{
   // :TODO: We should terminate all subscriptions for this event type.

   UtlString eventName(eventType);
   lockForWrite();

   SubscribeServerEventData* eventData =
      dynamic_cast <SubscribeServerEventData*> (mEventDefinitions.remove(&eventName));
   if (eventData)
   {
      // Unregister interest in SUBSCRIBE requests and NOTIFY
      // responses for this event type
      eventData->mpEventSpecificUserAgent->removeMessageObserver(*(getMessageQueue()));

      delete eventData;
   }

   unlockForWrite();

   return eventData != NULL;
}
UtlBoolean SipPublishServer::disableEventType(const char* eventTypeToken,
                                             SipUserAgent*& userAgent,
                                             SipPublishServerEventStateMgr*& eventStateMgr,
                                             SipPublishServerEventStateCompositor*& eventStateCompositor)
{
    UtlBoolean removedEvent = FALSE;
    UtlString eventName(eventTypeToken ? eventTypeToken : "");
    lockForWrite();
    // Only add the event support if it does not already exist;
    PublishServerEventData* eventData = 
        (PublishServerEventData*) mEventDefinitions.remove(&eventName);
        
    if(eventData)
    {
        removedEvent = TRUE;
        userAgent = eventData->mpEventSpecificUserAgent == mpDefaultUserAgent ? 
                        NULL : eventData->mpEventSpecificUserAgent;
        eventStateCompositor = eventData->mpEventSpecificStateCompositor == mpDefaultCompositor ?
                        NULL : eventData->mpEventSpecificStateCompositor;
        eventStateMgr = eventData->mpEventSpecificStateMgr == mpDefaultEventStateMgr ?
                        NULL : eventData->mpEventSpecificStateMgr;

        // Unregister interest in PUBLISH requests for this event type
        eventData->mpEventSpecificUserAgent->removeMessageObserver(*(getMessageQueue()));

        delete eventData;
        eventData = NULL;
    }
    else
    {
        userAgent = NULL;
        eventStateCompositor = NULL;
        eventStateMgr = NULL;
    }

    unlockForWrite();

    return(removedEvent);
}
void SipRefreshManager::setRefreshTimer(RefreshDialogState& state, 
                                        UtlBoolean isSuccessfulReschedule)
{
    // Create and set a new timer for the failed time out period
    int nextResendSeconds = 
        calculateResendTime(state.mExpirationPeriodSeconds,
                                  isSuccessfulReschedule);

    // If a signficant amount of time has passed since the prior
    // request was sent, decrease the error timeout a bit.
    // This is only a problem with the error case as in the
    // successful case we set the timer before sending the
    // request.
    if(!isSuccessfulReschedule)
    {
        long now = OsDateTime::getSecsSinceEpoch();
        if(state.mPendingStartTime > 0 &&
            now - state.mPendingStartTime > 5)
        {
            nextResendSeconds = nextResendSeconds - now + state.mPendingStartTime;
            if(nextResendSeconds < 30)
            {
                nextResendSeconds = 30;
            }
        }
    }

    OsSysLog::add(FAC_SIP, PRI_DEBUG,
                  "SipRefreshManager::setRefreshTimer setting resend timeout in %d seconds\n",
                  nextResendSeconds);

    OsMsgQ* incomingQ = getMessageQueue();
    OsTimer* resendTimer = new OsTimer(incomingQ,
        (int)&state);
    state.mpRefreshTimer = resendTimer;
    OsTime timerTime(nextResendSeconds, 0);
    resendTimer->oneshotAfter(timerTime);                

}
UtlBoolean SipPublishServer::enableEventType(const char* eventTypeToken,
                                             SipUserAgent* userAgent,
                                             SipPublishServerEventStateMgr* eventStateMgr,
                                             SipPublishServerEventStateCompositor* eventStateCompositor)
{
    UtlBoolean addedEvent = FALSE;
    UtlString eventName(eventTypeToken ? eventTypeToken : "");
    lockForWrite();
    // Only add the event support if it does not already exist;
    PublishServerEventData* eventData = 
        (PublishServerEventData*) mEventDefinitions.find(&eventName);
        
    if(!eventData)
    {
        addedEvent = TRUE;
        eventData = new PublishServerEventData();
        *((UtlString*)eventData) = eventName;
        eventData->mpEventSpecificUserAgent = userAgent ? userAgent : mpDefaultUserAgent;
        eventData->mpEventSpecificStateCompositor = eventStateCompositor ? eventStateCompositor : mpDefaultCompositor;
        eventData->mpEventSpecificStateMgr = eventStateMgr ? eventStateMgr : mpDefaultEventStateMgr;
        mEventDefinitions.insert(eventData);

        // Register an interest in PUBLISH requests for this event type
        eventData->mpEventSpecificUserAgent->addMessageObserver(*(getMessageQueue()),
                                                                SIP_PUBLISH_METHOD,
                                                                TRUE, // requests
                                                                FALSE, // not reponses
                                                                TRUE, // incoming
                                                                FALSE, // no outgoing
                                                                eventName,
                                                                NULL,
                                                                NULL);
    }

    unlockForWrite();

    return(addedEvent);
}
/// Insert a message into the buffer.
void SipClientWriteBuffer::insertMessage(SipMessage* message)
{
   UtlBoolean wasEmpty = mWriteBuffer.isEmpty();

    //
    // Let all outbound processors know about this message
    //
    if (message && mpSipUserAgent && mClientSocket && mClientSocket->isOk())
    {
      UtlString remoteHostAddress;
      int remotePort;
      mClientSocket->getRemoteHostIp(&remoteHostAddress, &remotePort);
      // We are about to post a message that will cause the
      // SIP message to be sent.  Notify the user agent so
      // that it can offer the message to all its registered
      // output processors.


      ssize_t msgLength = 0;
      UtlString msgText;
      message->getBytes(&msgText, &msgLength, true);
      if (msgLength)
      {
        system_tap_sip_tx(
             mLocalHostAddress.data(), portIsValid(mLocalHostPort) ? mLocalHostPort : defaultPort(),
             remoteHostAddress.data(), remotePort == PORT_NONE ? defaultPort() : remotePort,
             msgText.data(), msgLength);

        mpSipUserAgent->executeAllBufferedSipOutputProcessors(*message, remoteHostAddress.data(),
               remotePort == PORT_NONE ? defaultPort() : remotePort);
      }
    }

   // Add the message to the queue.
   mWriteBuffer.insert(message);

   // If the buffer was empty, we need to set mWriteString and
   // mWritePointer.
   if (wasEmpty)
   {
      ssize_t length;
      message->getBytes(&mWriteString, &length);
      mWritePointer = 0;
   }

   mWriteQueued = TRUE;

   // Check to see if our internal queue is getting too big, which means
   // that the socket has been blocked for writing for a long time.
   // We use the message queue length of this task as the limit, since
   // both queues are affected by the same traffic load factors.
   if (mWriteBuffer.entries() > (size_t) (getMessageQueue()->maxMsgs()))
   {
      // If so, abort all unsent messages and terminate this client (so
      // as to clear any state of the socket).
      Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                    "SipClientWriteBuffer[%s]::insertMessage "
                    "mWriteBuffer has '%d' entries, exceeding the limit of maxMsgs '%d'",
                    getName().data(), (int) mWriteBuffer.entries(),
                    getMessageQueue()->maxMsgs());
      emptyBuffer(TRUE);
      clientStopSelf();
   }
}
Exemple #14
0
// Handle an incoming message
// Return TRUE if the message was handled, otherwise FALSE.
UtlBoolean MpMediaTask::handleMessage(OsMsg& rMsg)
{
   UtlBoolean           handled;
   MpFlowGraphBase*    pFlowGraph;
   MpMediaTaskMsg*     pMsg;

   if (rMsg.getMsgType() != OsMsg::MP_TASK_MSG)
      return FALSE;    // the method only handles MP_TASK_MSG messages

   pMsg = (MpMediaTaskMsg*) &rMsg;
   pFlowGraph = (MpFlowGraphBase*) pMsg->getPtr1();

   handled = TRUE;     // until proven otherwise, assume we'll handle the msg
#ifdef _PROFILE /* [ */
   // Log the time it takes to handle messages other than WAIT_FOR_SIGNAL.
   long long start_time;
   if (pMsg->getMsg() != MpMediaTaskMsg::WAIT_FOR_SIGNAL)
   {
      timeval t;
      gettimeofday(&t, NULL);
      start_time = (t.tv_sec * 1000000) + t.tv_usec;
   }
#endif /* _PROFILE ] */

   if (getMessageQueue()->numMsgs() > 100)
   {
      OsSysLog::add(FAC_SIP, PRI_DEBUG,
                    "MpMediaTask::handleMessage msgType = %d, "
                    "queue length = %d",
                    pMsg->getMsg(), getMessageQueue()->numMsgs());
   }

   switch (pMsg->getMsg())
   {
   case MpMediaTaskMsg::MANAGE:
      if (!handleManage(pFlowGraph))
         mHandleMsgErrs++;
      break;
   case MpMediaTaskMsg::SET_FOCUS:
      if (!handleSetFocus(pFlowGraph))
         mHandleMsgErrs++;
      break;
   case MpMediaTaskMsg::START:
      if (!handleStart(pFlowGraph))
         mHandleMsgErrs++;
      break;
   case MpMediaTaskMsg::STOP:
      if (!handleStop(pFlowGraph))
         mHandleMsgErrs++;
      break;
   case MpMediaTaskMsg::UNMANAGE:
      if (!handleUnmanage(pFlowGraph))
         mHandleMsgErrs++;
      break;
   case MpMediaTaskMsg::WAIT_FOR_SIGNAL:
      if (!handleWaitForSignal(pMsg))
         mHandleMsgErrs++;
      break;
   default:
      handled = FALSE; // we didn't handle the message after all
      break;
   }
#ifdef _PROFILE /* [ */
   // Log the time it takes to handle messages other than WAIT_FOR_SIGNAL.
   if (pMsg->getMsg() != MpMediaTaskMsg::WAIT_FOR_SIGNAL)
   {
      timeval t;
      gettimeofday(&t, NULL);
      long long end_time = (t.tv_sec * 1000000) + t.tv_usec;
      mOtherMessages.tally(end_time - start_time);
   }
#endif /* _PROFILE ] */

   return handled;
}
Exemple #15
0
/// Terminate all subscriptions and accept no new ones.
void SipSubscribeServer::shutdown(const char* reason)
{
   // If reason is NULL, use the default reason established by the constructor.
   if (!reason)
   {
      reason = mDefaultTermination;
   }

   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "SipSubscribeServer::shutdown reason '%s'",
                 reason ? reason : "[null]");                 

   lockForRead();

   // Select the subscriptionChange value to describe what we're doing
   // with the subscriptions.
   enum SipSubscriptionMgr::subscriptionChange change;

   // Select the correct format for generating the Subscription-State value.
   UtlString* formatp = NULL; // We may need a temp UtlString.
   const char* format;

   if (reason == NULL)
   {
      format = "active;expires=%ld";
      change = SipSubscriptionMgr::subscriptionContinues;
   }
   else if (strcmp(reason, terminationReasonSilent) == 0)
   {
      // Do not admit that the subscription is ending.
      format = "active;expires=%ld";
      change = SipSubscriptionMgr::subscriptionTerminatedSilently;
   }
   else if (strcmp(reason, terminationReasonNone) == 0)
   {
      format = "terminated";
      change = SipSubscriptionMgr::subscriptionTerminated;
   }
   else
   {
      // Allocate a UtlString and assemble the Subscription-State format in it.
      formatp = new UtlString();
      formatp->append("terminated;reason=");
      formatp->append(reason);
      format = formatp->data();
      change = SipSubscriptionMgr::subscriptionTerminated;
   }

   // For each event type that is registered, delete all the subscriptions.

   UtlHashBagIterator event_itor(mEventDefinitions);
   SubscribeServerEventData* eventData;
   while ((eventData =
              dynamic_cast <SubscribeServerEventData*> (event_itor())))
   {
      // Unregister interest in SUBSCRIBE requests and NOTIFY
      // responses for this event type, so we do not service new subscriptions.

      eventData->mpEventSpecificUserAgent->removeMessageObserver(*(getMessageQueue()));
      
      int numSubscriptions = 0;
      SipMessage** notifyArray = NULL;
      UtlString** acceptHeaderValuesArray = NULL;
      UtlString** resourceIdArray = NULL;
      UtlString** eventTypeKeyArray = NULL;

      // :TODO: The four situations where NOTIFYs are generated should
      // be factored into a series of methods in
      // mpEventSpecificSubscriptionMgr that generate NOTIFYs
      // sequentially, and for each NOTIFY, call a common service
      // method that does the remaining operations and sends the
      // NOTIFY.

      // Construct a NOTIFY (without body) for every subscription, containing
      // the dialog-related information about each subscription.
      eventData->mpEventSpecificSubscriptionMgr->
         createNotifiesDialogInfoEvent(static_cast <const UtlString&> (*eventData),
                                       format,
                                       numSubscriptions,
                                       acceptHeaderValuesArray,
                                       notifyArray,
                                       resourceIdArray,
                                       eventTypeKeyArray);

      OsSysLog::add(FAC_SIP, PRI_DEBUG,
                    "SipSubscribeServer::shutdown eventType = '%s', numSubscriptions = %d",
                    eventData->data(), numSubscriptions);

      // For each NOTIFY, add the subscription-related information and then
      // send it.
      for (int notifyIndex = 0;
           notifyIndex < numSubscriptions;
           notifyIndex++)
      {
         SipMessage* notify = notifyArray[notifyIndex];

         // Check to see if the dialog information could be added.
         // (The subscription might have been destroyed between when
         // it was decided to respond to it, and when the dialog information
         // was retrieved.)
         UtlString callId;
         notify->getCallIdField(&callId);
         if (!callId.isNull())
         {
            if (change != SipSubscriptionMgr::subscriptionTerminatedSilently)
            {
               // Fill in the NOTIFY request body/content
               eventData->mpEventSpecificHandler->
                  getNotifyContent(*(resourceIdArray[notifyIndex]),
                                   *(eventTypeKeyArray[notifyIndex]),
                                   *eventData,
                                   *(eventData->mpEventSpecificContentMgr),
                                   *(acceptHeaderValuesArray[notifyIndex]),
                                   *notify,
                                   eventData->mEventSpecificFullState,
                                   NULL);

               // Call the application callback to edit the NOTIFY
               // content if that is required for this event type.
               // Also gets 'version' (if relevant) and 'savedEventTypeKey'.
               int version;
               UtlString savedEventTypeKey;
               eventData->mpEventSpecificSubscriptionMgr->
                  updateNotifyVersion(eventData->mpEventSpecificContentVersionCallback,
                                      *notify,
                                      version,
                                      savedEventTypeKey);

               // Set the Contact header.
               setContact(notify);

               // Send the NOTIFY request.
               eventData->mpEventSpecificUserAgent->send(*notify);
            }

            // Remove the record of the subscription.
            UtlString dialogHandle;
            notify->getDialogHandle(dialogHandle);
            eventData->mpEventSpecificSubscriptionMgr->
               endSubscription(dialogHandle, change);
         }
      }

      // Free the NOTIFY requests and accept header field values.
      SipSubscriptionMgr::freeNotifies(numSubscriptions,
                                       acceptHeaderValuesArray,
                                       notifyArray);

      // Free the resource and event type arrays.
      for (int index = 0;
           index < numSubscriptions;
           index++)
      {
         delete resourceIdArray[index];
         delete eventTypeKeyArray[index];
      }
      delete[] resourceIdArray;
      delete[] eventTypeKeyArray;

      // Remove eventData from mEventDefinitions.
      mEventDefinitions.removeReference(eventData);
      delete eventData;
   }

   unlockForRead();

   // Free the temporary UtlString, if necessary.
   if (formatp)
   {
      delete formatp;
   }

   lockForWrite();
   mEventDefinitions.destroyAll();
   unlockForWrite();
}
Exemple #16
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 ;
}
UtlBoolean SipSubscribeServer::handleSubscribe(const SipMessage& subscribeRequest)
{
    UtlBoolean handledSubscribe = FALSE;
    UtlString eventName;
    subscribeRequest.getEventField(&eventName, NULL);

    // Not modifying the SubscribeServerEventData, just reading it
    lockForRead();

    // Get the event specific handler and information
    SubscribeServerEventData* eventPackageInfo = (SubscribeServerEventData*)
        mEventDefinitions.find(&eventName);

    // We handle this event type
    if(eventPackageInfo)
    {
        handledSubscribe = TRUE;
        UtlString resourceId;
        UtlString eventTypeKey, eventType;
        SipSubscribeServerEventHandler* handler =
            eventPackageInfo->mpEventSpecificHandler;

        // Get the keys used to identify the event state content
        handler->getKeys(subscribeRequest,
                         resourceId,
                         eventTypeKey,
                         eventType);

        SipMessage subscribeResponse;

        // Check if authenticated (or if it needs to be authenticated)
        if(handler->isAuthenticated(subscribeRequest,
                                     resourceId,
                                     eventTypeKey,
                                     subscribeResponse))
        {
            // Check if authorized (or if authorization is required)
            if(handler->isAuthorized(subscribeRequest,
                                     resourceId,
                                     eventTypeKey,
                                     subscribeResponse))
            {
                // The subscription is allowed, so update the
                // subscription state.  Set the To field tag if
                // this request initiated the dialog
                UtlString subscribeDialogHandle;
                UtlBoolean isNewDialog;
                UtlBoolean isExpiredSubscription;
                eventPackageInfo->mpEventSpecificSubscriptionMgr->updateDialogInfo(
                                                            subscribeRequest,
                                                            resourceId, 
                                                            eventTypeKey, 
                                                            getMessageQueue(),
                                                            subscribeDialogHandle, 
                                                            isNewDialog, 
                                                            isExpiredSubscription,
                                                            subscribeResponse);

                // Send the response ASAP to minimize resend handling of request
                 eventPackageInfo->mpEventSpecificUserAgent->send(subscribeResponse);

                 // Build a NOTIFY
                 SipMessage notifyRequest;

                 // Set the dialog information
                 eventPackageInfo->mpEventSpecificSubscriptionMgr->getNotifyDialogInfo(subscribeDialogHandle,
                                                                    notifyRequest);

                 // Set the NOTIFY content
                 UtlString acceptHeaderValue;
                 subscribeRequest.getAcceptField(acceptHeaderValue);
                 handler->getNotifyContent(resourceId, 
                                           eventTypeKey, 
                                           eventType, 
                                           *(eventPackageInfo->mpEventSpecificContentMgr),
                                           acceptHeaderValue,
                                           notifyRequest);

                 // Send the notify request
                 eventPackageInfo->mpEventSpecificUserAgent->send(notifyRequest);
            }
            // Not authorized
            else
            {
                // Send the response
                eventPackageInfo->mpEventSpecificUserAgent->send(subscribeResponse);
            }
        }

        // Not authenticated
        else
        {
            // Send the response
            eventPackageInfo->mpEventSpecificUserAgent->send(subscribeResponse);
        }
    }


    // We should not have received SUBSCRIBE requests for this event type
    // This event type has not been enabled in this SubscribeServer
    else
    {
        OsSysLog::add(FAC_SIP, PRI_ERR, 
            "SipSubscribeServer::handleSubscribe event type: %s not enabled",
            eventName.data());

        SipMessage eventTypeNotHandled;
        eventTypeNotHandled.setResponseData(&subscribeRequest,
            SIP_BAD_EVENT_CODE, SIP_BAD_EVENT_TEXT);

        mpDefaultUserAgent->send(eventTypeNotHandled);
    }
    unlockForRead();

    return(handledSubscribe);
}
// 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)) ;
}
UtlBoolean SipRefreshManager::initiateRefresh(SipMessage& subscribeOrRegisterRequest,
                                               void* applicationData,
                                               const RefreshStateCallback refreshStateCallback,
                                               UtlString& earlyDialogHandle)
{

    UtlBoolean intitialRequestSent = FALSE;

    // Make sure we do not have an existing dialog or refresh session state
    // going for the given message
    UtlString messageDialogHandle;
    subscribeOrRegisterRequest.getDialogHandle(messageDialogHandle);
    UtlBoolean existingRefreshState = FALSE;
    UtlBoolean existingDialogState = FALSE;
    if(!SipDialog::isEarlyDialog(messageDialogHandle))
    {
        existingDialogState = TRUE;
        OsSysLog::add(FAC_SIP, PRI_ERR,
                "SipRefreshManager::initiateRefresh called with established dialog handle: %s",
                messageDialogHandle.data());
    }

    else
    {
        OsLock localLock(mRefreshMgrMutex);
        // See if there is an early or established dialog for this message
        if(getAnyDialog(messageDialogHandle))
        {
            existingRefreshState = TRUE;
            intitialRequestSent = FALSE;
            OsSysLog::add(FAC_SIP, PRI_ERR,
                "SipRefreshManager::initiateRefresh called with pre-existing refresh state: %s",
                messageDialogHandle.data());
        }

        // The dialog should not exist either
        else if(mpDialogMgr->dialogExists(messageDialogHandle) ||
            mpDialogMgr->earlyDialogExistsFor(messageDialogHandle))
        {
            existingDialogState = TRUE;
            OsSysLog::add(FAC_SIP, PRI_ERR,
                "SipRefreshManager::initiateRefresh called with pre-existing dialog: %s",
                messageDialogHandle.data());
        }
    }

    // Should not be any existing refresh or dialog states
    // for this message
    if(!existingRefreshState && !existingDialogState)
    {
        // Make sure we are registered to receive responses
        // for the message we are about to send
        UtlString method;
        subscribeOrRegisterRequest.getRequestMethod(&method);
        if(method.compareTo(SIP_REGISTER_METHOD) == 0)
        {
            lock();
            if(!mReceivingRegisterResponses)
            {
                mReceivingRegisterResponses = TRUE;
                // receive REGISTER responses 
                mpUserAgent->addMessageObserver(*(getMessageQueue()), 
                                                SIP_REGISTER_METHOD,
                                                FALSE, // yes requests
                                                TRUE, // no responses
                                                TRUE, // incoming,
                                                FALSE, // outgoing
                                                NULL);
            }
            unlock();
        }
        else if(method.compareTo(SIP_SUBSCRIBE_METHOD) == 0)
        {
            UtlString eventType;
            subscribeOrRegisterRequest.getEventField(&eventType, NULL);
            // Check to see if we have already registered to
            // receive the event type
            lock();
            if(mEventTypes.find(&eventType) == NULL)
            {
                mEventTypes.insert(new UtlString(eventType));
                // receive SUBSCRIBE responses for this event type
                mpUserAgent->addMessageObserver(*(getMessageQueue()), 
                                                SIP_SUBSCRIBE_METHOD,
                                                FALSE, // no requests
                                                TRUE, // yes responses
                                                TRUE, // incoming,
                                                FALSE, // outgoing
                                                eventType);
            }
            unlock();

        }

        // Create a new refresh state
        int requestedExpiration = 0;  // returned from following call
        RefreshDialogState* state = createNewRefreshState(subscribeOrRegisterRequest,
                                                        messageDialogHandle,
                                                        applicationData,
                                                        refreshStateCallback,
                                                        requestedExpiration);

        // create a new dialog
        mpDialogMgr->createDialog(subscribeOrRegisterRequest, 
                                  TRUE, // message from this side
                                  messageDialogHandle);

        // Keep track of when we send this request to be refreshed
        long now = OsDateTime::getSecsSinceEpoch();
        state->mPendingStartTime = now;
        state->mRequestState = REFRESH_REQUEST_PENDING;

        // Set a timer  at which to resend the next refresh based upon the 
        // assumption that the request will succeed.  When we receive a 
        // failed response, we will cancel the timer and reschedule
        // a new timer based upon a smaller fraction of the requested 
        // expiration period 
        setRefreshTimer(*state, 
                        TRUE); // Resend with successful timeout
        OsTimer* resendTimer = state->mpRefreshTimer;

        // Mark the refresh state as having an outstanding request
        // and make a copy of the request.  The copy needs to be
        // attached to the state before the send incase the response
        // comes back before we return from the send.
        state->mRequestState = REFRESH_REQUEST_PENDING;
        state->mpLastRequest = new SipMessage(subscribeOrRegisterRequest);

        // Add the state to the container of refresh states
        // No need to lock this refreshMgr earlier as this is a new
        // state and no one can touch it until it is in the list.
        lock();
        mRefreshes.insert(state);
        unlock();
        // NOTE: at this point is is no longer safe to touch the state
        // without locking it again.  Avoid locking this refresh mgr
        // when something can block (e.g. like calling SipUserAgent ::send)

        // Send the request
        // Is the correct?  Should we send the request first and only set
        // a timer if the request succeeds??
        intitialRequestSent = mpUserAgent->send(subscribeOrRegisterRequest);

        // We do not clean up the state even if the send fails.
        // The application must end the refresh as the refresh
        // manager should retry the send if it failed
        if(!intitialRequestSent)
        {
            // Need to lock this refresh mgr and make sure the state
            // still exists.  It could have been deleted while this
            // was unlocked above.
            lock();
            if(stateExists(state))
            {
                // It is now safe to touch the state again

                // Mark the state of the last request as having 
                // failed, so we know to resend when the timer
                // fires
                state->mRequestState = REFRESH_REQUEST_FAILED;

                // The expiration should still be set to zero

                // the initial send failed, cancel the timer and
                // fire the notification.  The handleMessage method
                // will see that the subscription or registration
                // has never succeeded and reshedule the timer for
                // a failure timeout.  We cannot reschedule the
                // timer here as there is a race condition between
                // deleting the timer here (in the applications context)
                // and in handleMessage in this refresh manager's 
                // context.
                // If the timer has not changed assume it is still safe
                // to touch it
                if(state->mpRefreshTimer == resendTimer)
                {
                    stopTimerForFailureReschedule(state->mpRefreshTimer);
                }

                // Do not notify the application that the request failed
                // when it occurs on the first invokation.  The application
                // will know by the return.
            }
            unlock();
        }
    }

    return(intitialRequestSent);
}
// 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
                                   );                                   
}
Exemple #21
0
// Handle a timer service request.
// Return TRUE if the request was handled, otherwise FALSE.
UtlBoolean OsTimerTask::handleMessage(OsMsg& rMsg)
{
   // Process a message.

   // If not an OS_TIMERTASK_COMMAND message, return FALSE to indicate it should be
   // passed to our superclass.
   if (rMsg.getMsgType() != OsMsg::OS_TIMERTASK_COMMAND)
   {
      return FALSE;
   }

   // Process an OS_TIMERTASK_COMMAND message.

   OsTimerTaskCommandMsg& message = dynamic_cast <OsTimerTaskCommandMsg&> (rMsg);

   // Process a OS_TIMER_SHUTDOWN message, which is special
   if (message.getMsgSubType() == OsTimerTaskCommandMsg::OS_TIMER_SHUTDOWN)
   {
      OsSysLog::add(FAC_KERNEL, PRI_INFO,
                    "OsTimerTask::handleMessage OS_TIMER_SHUTDOWN seen, mState = %d",
                    mState);
      // Verify that there are no other requests in the timer task's queue.
      assert(getMessageQueue()->isEmpty());

      // Stop all the timers in the timer queue.
      OsTimer* link;
      for (OsTimer* timer = mTimerQueue; timer; timer = link)
      {
         // This lock should never block, since the application should not
         // be accessing the timer.
         OsLock lock(timer->mBSem);

         // Check that the application and task states are the same.
         // If they aren't, the application is mucking with the timer.
         assert(timer->mTaskState == timer->mApplicationState);
         // Increment the state fields, to show the timer is stopped.
         timer->mTaskState =
            timer->mApplicationState = timer->mApplicationState + 1;

         // Get the link field.
         link = timer->mTimerQueueLink;

         // Clear the link field of the timer.
         timer->mTimerQueueLink = 0;
      }
      // Empty the timer queue.
      mTimerQueue = 0;

      // Change mState so the main loop will exit.
      requestShutdown();

      // Signal the event so our caller knows we're done.
      message.getEventP()->signal(0);
      OsSysLog::add(FAC_KERNEL, PRI_INFO,
                    "OsTimerTask::handleMessage OS_TIMER_SHUTDOWN seen, mState = %d",
                    mState);
      return TRUE;
   }

   OsTimer* timer = message.getTimerP();
#ifndef NDEBUG
   CHECK_VALIDITY(timer);
#endif
   unsigned int applicationState;
   OsTimer::Time expiresAt;
   UtlBoolean periodic;
   OsTimer::Interval period;
   {
      OsLock lock(timer->mBSem);

      // mDeleting may be true, if the destructor has started running.

      // Decrement the outstanding message count.
      timer->mOutstandingMessages--;

      // Get mApplicationState.
      applicationState = timer->mApplicationState;

      // Get the timing information.
      expiresAt = timer->mExpiresAt;
      periodic = timer->mPeriodic;
      period = timer->mPeriod;
   }	    

   // Determine whether the timer needs to be stopped.
   // (The comparison between applicationState and mTaskState is really
   // ">", taking into account wraparound.  But that is difficult to
   // implement, so given that mApplicationState is always >= mTaskState
   // by design, we can use "!=".)
   if (applicationState != timer->mTaskState &&
       OsTimer::isStarted(timer->mTaskState))
   {
      // Stop the timer.
      removeTimer(timer);
   }
   // Determine whether the timer needs to be started.
   if (applicationState != timer->mTaskState &&
       OsTimer::isStarted(applicationState))
   {
      // Start the timer.
      // Set the saved timing information.
      timer->mQueuedExpiresAt = expiresAt;
      timer->mQueuedPeriodic = periodic;
      timer->mQueuedPeriod = period;
      insertTimer(timer);
   }
	    
   // Update the task state.
   timer->mTaskState = applicationState;

   switch (message.getMsgSubType())
   {
   case OsTimerTaskCommandMsg::OS_TIMER_UPDATE:
      // No further processing is needed.
      break;

   case OsTimerTaskCommandMsg::OS_TIMER_UPDATE_SYNC:
      // If it is an UPDATE_SYNC message, signal the event.
      message.getEventP()->signal(0);
      break;

   case OsTimerTaskCommandMsg::OS_TIMER_UPDATE_DELETE:
      // If it is an UPDATE_DELETE, delete the timer.

      // Timer will not be accessed by any other thread, so we
      // can access it without locking.
#ifndef NDEBUG
      // Deletion in progress.
      assert(timer->mDeleting);
#endif
      // Timer should be stopped already.
      assert(OsTimer::isStopped(timer->mApplicationState));
      // No outstanding messages.
      assert(timer->mOutstandingMessages == 0);
#ifndef NDEBUG
      // Set mDeleting to FALSE to the destructor won't fail.
      timer->mDeleting = FALSE;
#endif

      // Use ordinary destructor to delete the timer.
      // Because of the state of the timer, it will not send a message to
      // the timer task.
      delete timer;
      break;

   default:
      // Catch invalid values.
      assert(FALSE);
   }

   return TRUE;
}
Exemple #22
0
// The entry point for the task.
// This method executes a message processing loop until either
// requestShutdown(), deleteForce(), or the destructor for this object
// is called.
int OsTimerTask::run(void* pArg)
{
   UtlBoolean doShutdown;
   OsMsg*    pMsg = NULL;
   OsStatus     res;

   // "now" is the current time.
   OsTimer::Time now = OsTimer::now();
   doShutdown = FALSE;
   do
   {
      // Do not attempt to receive message if a timer has already fired.
      // (This also avoids an edge case if the timeout value is zero
      // or negative.)
      if (!(mTimerQueue &&
            OsTimer::compareTimes(now, mTimerQueue->mQueuedExpiresAt) >= 0))
      {
         // Set the timeout till the next timer fires.
         OsTime timeout;
         if (mTimerQueue)
         {
            OsTimer::cvtToOsTime(timeout,
                                 OsTimer::subtractTimes(mTimerQueue->mQueuedExpiresAt,
                                                        now));
         }
         else
         {
            timeout = OsTime::OS_INFINITY;
         }

         res = receiveMessage((OsMsg*&) pMsg, timeout); // wait for a message
         if (res == OS_SUCCESS)
         {
            // A message was received.  Process it.
            doShutdown = isShuttingDown();
            if (!doShutdown)
            {                                           // comply with shutdown
               if (!handleMessage(*pMsg))               // process the message
               {
                  OsServerTask::handleMessage(*pMsg);
               }
            }

            if (!pMsg->getSentFromISR())
            {
               pMsg->releaseMsg();                      // free the message
            }
         }
         else
         {
            assert(pMsg==NULL);
         }

         now = OsTimer::now();     // Update our record of the current time.
      }

      // Now check for timers that have expired.
      while (mTimerQueue &&
             OsTimer::compareTimes(now, mTimerQueue->mQueuedExpiresAt) >= 0)
      {
         // Fire the the timer (and remove it from the queue).
         OsTimer* timer = mTimerQueue;
         mTimerQueue = timer->mTimerQueueLink;
         // Clear the timer's mTimerQueueLink to indicate it is not
         // in the timer queue.
         timer->mTimerQueueLink = 0;
         fireTimer(timer);
      }

      if (OsSysLog::willLog(FAC_KERNEL, PRI_WARNING))
      {
         // Check to see if timer firing took too long.
         OsTimer::Time after = OsTimer::now();
         OsTimer::Time t = OsTimer::subtractTimes(after, now);
         if (t >= 1000000 /* 1 second */)
         {
            OsSysLog::add(FAC_KERNEL, PRI_WARNING,
                          "OsTimerTask::run firing took %"PRId64" usecs,"
                          " queue length = %d, before fire = %"PRId64", after fire = %"PRId64,
                          t, getMessageQueue()->numMsgs(), now, after);
         }
      }
   }
   while (!doShutdown);

   OsSysLog::add(FAC_KERNEL, PRI_INFO,
                 "OsTimerTask::run OsTimerTask shutting down");

   return 0;        // and then exit
}
Exemple #23
0
// Thread execution code.
int SipClient::run(void* runArg)
{
   OsMsg*    pMsg = NULL;
   OsStatus  res;
   // Buffer to hold data read from the socket but not yet parsed
   // into incoming SIP messages.
   UtlString readBuffer;
   bool      waitingToReportErr  = FALSE;    // controls whether to read-select on socket
   bool      tcpOnErrWaitForSend = TRUE;
   int       repeatedEOFs = 0;

   Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                 "SipClient[%s]::run start  "
                 "tcpOnErrWaitForSend-%d waitingToReportErr-%d mbTcpOnErrWaitForSend-%d repeatedEOFs-%d",
                 mName.data(), tcpOnErrWaitForSend, waitingToReportErr,
                 mbTcpOnErrWaitForSend, repeatedEOFs);

   // Wait structure:
   struct pollfd fds[2];
   // Incoming message on the message queue (to be sent on the socket).
   fds[0].fd = mPipeReadingFd;
   // Socket ready to write (to continue sending message).
   // Socket ready to read (message to be received).

   do
   {
      assert(repeatedEOFs < 20);
      // The file descriptor for the socket may changemsg->getSendAddress(&fromIpAddress, &fromPort);, as OsSocket's
      // can be re-opened.
      fds[1].fd = mClientSocket->getSocketDescriptor();

      // Initialize the revents members.
      // This may not be necessary (the man page is not clear), but
      // Valgrind flags 'fds[*].revents' as undefined if they aren't
      // initialized.
      fds[0].revents = 0;
      fds[1].revents = 0;

      fds[0].events = POLLIN;   // only read-select on pipe

      // For non-blocking connect failures, don't read-select on socket if
      // the initial read showed an error but we have to wait to report it.
      if (!waitingToReportErr)
      {
          // This is the normal path.
          // Read the socket only if the socket is not shared.
          // If it is shared, the ancestral SipClient will read it.
          // If multiple threads attempt to read the socket, poll() may
          // succeed but another may read the data, leaving us to block on
          // read.
          fds[1].events = mbSharedSocket ? 0 : POLLIN;

          // Set wait for writing the socket if there is queued messages to
          // send.
          if (mWriteQueued)
          {
             // Wait for output on the socket to not block.
             fds[1].events |= POLLOUT;
          }

      }
      else
      {
          // just waiting to report error, ignore the socket
          fds[1].fd =-1;
          fds[1].events = 0;
      }

      // If there is residual data in the read buffer,
      // pretend the socket is ready to read.
      if (!readBuffer.isNull())
      {
         fds[1].revents = POLLIN;
      }
      else
      {
         // Otherwise, call poll() to wait.
         int resPoll = poll(&fds[0], sizeof (fds) / sizeof (fds[0]),
                        POLL_TIMEOUT);
         assert(resPoll >= 0 || (resPoll == -1 && errno == EINTR));
         if (resPoll != 0)
         {
             Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                           "SipClient[%s]::run "
                           "resPoll= %d revents: fd[0]= %x fd[1]= %x",
                           mName.data(),
                           resPoll, fds[0].revents, fds[1].revents );
         }
      }

      if ((fds[1].revents & (POLLERR | POLLHUP)) != 0)
      {
          Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                        "SipClient[%s]::run "
                        "SipMessage::poll error(%d) ",
                        mName.data(), errno);

          if (OsSocket::isFramed(mClientSocket->getIpProtocol()))
          {
              Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                            "SipClient[%s]::run "
                            "SipMessage::poll error(%d) got POLLERR | POLLHUP on UDP socket",
                            mName.data(), errno);

          }
          else	// eg. tcp socket
          // This client's socket is a connection-oriented protocol and the
          // connection has been terminated (probably by the remote end).
          // We must terminate the SipClient.
          // We drop the queued messages, but we do not report them to
          // SipUserAgent as failed sends.  This will cause SipUserAgent to
          // retry the send using the same transport (rather than continuing
          // to the next transport), which should cause a new connection to
          // be made to the remote end.
          {
              // On non-blocking connect failures, we need to get the first send message
              // in order to successfully trigger the protocol fallback mechanism
              if (!tcpOnErrWaitForSend)
              {
                 // Return all buffered messages with a transport error indication.
                 emptyBuffer(TRUE);
                 clientStopSelf();
              }
              else
              {
                 fds[1].revents &= ~(POLLERR | POLLHUP);  // clear error bit if waiting
                 waitingToReportErr = TRUE;
              }
          }
      }

      // Check for message queue messages (fds[0]) before checking the socket(fds[1]),
      // to make sure that we process shutdown messages promptly, even
      // if we would be spinning trying to service the socket.
      else if ((fds[0].revents & POLLIN) != 0)
      {
         // Poll finished because the pipe is ready to read.
         // (One byte in pipe means message available in queue.)
         // Only a SipClient with a derived SipClientWriteBuffer
         // uses the pipe in the Sip message send process

         // Check to see how many messages are in the queue.
         int numberMsgs = (getMessageQueue())->numMsgs();
         Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                       "SipClient[%s]::run got pipe-select  "
                       "Number of Messages waiting: %d",
                       mName.data(),
                       numberMsgs);
         int i;
         char buffer[1];
         for (i = 0; i < numberMsgs; i++)
         {
            // Receive the messages.
            res = receiveMessage((OsMsg*&) pMsg, OsTime::NO_WAIT);
            assert(res == OS_SUCCESS);

            // Normally, this is a SIP message for the write buffer.  Once we have gotten
            // here, we are able to report any initial non-blocking connect error.
            mbTcpOnErrWaitForSend = FALSE;
            tcpOnErrWaitForSend = FALSE;
            Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                          "SipClient[%s]::run got pipe-select  "
                          "mbTcpOnErrWaitForSend-%d waitingToReportErr-%d mbTcpOnErrWaitForSend-%d repeatedEOFs-%d",
                          mName.data(), mbTcpOnErrWaitForSend, waitingToReportErr,
                          mbTcpOnErrWaitForSend, repeatedEOFs);

            // Read 1 byte from the pipe to clear it for this message.  One byte is
            // inserted into the pipe for each message.
            assert(read(mPipeReadingFd, &buffer, 1) == 1);

            if (!handleMessage(*pMsg))            // process the message (from queue)
            {
               OsServerTask::handleMessage(*pMsg);
            }

            if (!pMsg->getSentFromISR())
            {
               pMsg->releaseMsg();                         // free the message
            }

            // In order to report an unframed(eg TCP) socket error to SipUserAgent dispatcher,
            // the error must be carried in a sip message from the client's message queue.
            // The message holds all the identifying information.
            if (waitingToReportErr)
            {
                // Return all buffered messages with a transport error indication.
                emptyBuffer(TRUE);
                clientStopSelf();
            }
         }
      } // end reading msg-available-for-output-queue pipe

      else if ((fds[1].revents & POLLOUT) != 0)
      {
         // Poll finished because socket is ready to write.

         // Call method to continue writing data.
         writeMore();
      }
      else if ((fds[1].revents & POLLIN) != 0)
      {
         // Poll finished because socket is ready to read.

         // Read message.
         // Must allocate a new message because SipUserAgent::dispatch will
         // take ownership of it.

         SipMessage* msg = new SipMessage;
         int res = msg->read(mClientSocket,
                             HTTP_DEFAULT_SOCKET_BUFFER_SIZE,
                             &readBuffer);

         if (res >= 65536)
         {
           //
           // This is more than the allowable size of a SIP message.  Discard!
           //
            UtlString remoteHostAddress;
            int remoteHostPort;
            msg->getSendAddress(&remoteHostAddress, &remoteHostPort);
            OS_LOG_WARNING(FAC_SIP, "Received a SIP Message ("
             << res << " bytes) beyond the maximum allowable size from host "
             << remoteHostAddress.data() << ":" << remoteHostPort);
            delete msg;
            readBuffer.remove(0);
            continue;
         }

         // Use readBuffer to hold any unparsed data after the message
         // we read.
         // Note that if a message was successfully parsed, readBuffer
         // still contains as its prefix the characters of that message.
         // We save them for logging purposes below and will delete them later.

         UtlString remoteHostAddress;
         int remoteHostPort;
         msg->getSendAddress(&remoteHostAddress, &remoteHostPort);
         if (!mClientSocket->isSameHost(remoteHostAddress.data(), mLocalHostAddress.data()))
         {
           try
           {
             if (!remoteHostAddress.isNull())
             {
               boost::asio::ip::address remoteIp = boost::asio::ip::address::from_string(remoteHostAddress.data());

               if (rateLimit().isBannedAddress(remoteIp))
               {
                  delete msg;
                  readBuffer.remove(0);
                  continue;
               }

               rateLimit().logPacket(remoteIp, 0);
             }
           }
           catch(const std::exception& e)
           {
             Os::Logger::instance().log(FAC_SIP_INCOMING, PRI_CRIT, 
               "SipClient[%s]::run rate limit exception: %s",  mName.data(), e.what());
           }
         }


         // Note that input was processed at this time.
         touch();

         //
         // Count the CR/LF to see if this is a keep-alive
         //
         int crlfCount = 0;
         for (int i = 0; i < res; i++)
         {
           if (readBuffer(i) == '\r' || readBuffer(i) == '\n')
           {
             crlfCount++;
           } else
           {
             break;
           }
         }

         if (res == crlfCount)
         {
             repeatedEOFs = 0;
             // The 'message' was a keepalive (CR-LF or CR-LF-CR-LF).
             UtlString fromIpAddress;
             int fromPort;
             UtlString buffer;
             int bufferLen;

             // send one CRLF set in the reply
             buffer.append("\r\n");
             bufferLen = buffer.length();

             // Get the send address for response.
             msg->getSendAddress(&fromIpAddress, &fromPort);
             if ( !portIsValid(fromPort))
             {
                 fromPort = defaultPort();
             }

            // Log the message at DEBUG level.
            // Only bother processing if the logs are enabled
            if (   mpSipUserAgent->isMessageLoggingEnabled()
                   || Os::Logger::instance().willLog(FAC_SIP_INCOMING, PRI_DEBUG)
               )
            {
               UtlString logMessage;
               logMessage.append("Read keepalive message:\n");
               logMessage.append("----Local Host:");
               logMessage.append(mLocalHostAddress);
               logMessage.append("---- Port: ");
               logMessage.appendNumber(
                  portIsValid(mLocalHostPort) ? mLocalHostPort : defaultPort());
               logMessage.append("----\n");
               logMessage.append("----Remote Host:");
               logMessage.append(fromIpAddress);
               logMessage.append("---- Port: ");
               logMessage.appendNumber(
                  portIsValid(fromPort) ? fromPort : defaultPort());
               logMessage.append("----\n");

               logMessage.append(readBuffer.data(), res);
               UtlString messageString;
               logMessage.append(messageString);
               logMessage.append("====================END====================\n");

               // Don't bother to send the message to the SipUserAgent for its internal log.

               // Write the message to the syslog.
               Os::Logger::instance().log(FAC_SIP_INCOMING, PRI_DEBUG, "%s", logMessage.data());
            }

            // send the CR-LF response message
            switch (mSocketType)
            {
            case OsSocket::TCP:
            {
               Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                             "SipClient[%s]::run send TCP keep-alive CR-LF response, ",
                             mName.data());
               SipClientSendMsg sendMsg(OsMsg::OS_EVENT,
                                        SipClientSendMsg::SIP_CLIENT_SEND_KEEP_ALIVE,
                                        fromIpAddress,
                                        fromPort);
                handleMessage(sendMsg);     // add newly created keep-alive to write buffer
            }
               break;
            case OsSocket::UDP:
            {
                Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                              "SipClient[%s]::run send UDP keep-alive CR-LF response, ",
                              mName.data());
               (dynamic_cast <OsDatagramSocket*> (mClientSocket))->write(buffer.data(),
                                                                         bufferLen,
                                                                         fromIpAddress,
                                                                         fromPort);
            }
               break;
            default:
               break;
            }

            // Delete the SipMessage allocated above, which is no longer needed.
            delete msg;

            // Now that logging is done, remove the parsed bytes and
            // remember any unparsed input for later use.
            readBuffer.remove(0, res);
         }  // end keep-alive msg

         else if (res > 0)      // got message, but not keep-alive
         {
            // Message successfully read.
            repeatedEOFs = 0;

            // Do preliminary processing of message to log it,
            // clean up its data, and extract any needed source address.
            preprocessMessage(*msg, readBuffer, res);

            // Dispatch the message.
            // dispatch() takes ownership of *msg.
            mpSipUserAgent->dispatch(msg);

            // Now that logging is done, remove the parsed bytes and
            // remember any unparsed input for later use.
            readBuffer.remove(0, res);
         }  // end process read of >0 bytes
         else
         {
            // Something went wrong while reading the message.
            // (Possibly EOF on a connection-oriented socket.)
            repeatedEOFs++;

            // Delete the SipMessage allocated above, which is no longer needed.
            delete msg;
            Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                          "SipClient[%s]::run SipMessage::read returns %d (error(%d) or EOF), "
                          "readBuffer = '%.1000s'",
                          mName.data(), res, errno, readBuffer.data());

            Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                          "SipClient[%s]::run error wait status  "
                          "tcpOnErrWaitForSend-%d waitingToReportErr-%d "
                          "mbTcpOnErrWaitForSend-%d repeatedEOFs-%d "
                          "protocol %d framed %d",
                          mName.data(),
                          tcpOnErrWaitForSend, waitingToReportErr,
                          mbTcpOnErrWaitForSend, repeatedEOFs,
                          mClientSocket->getIpProtocol(),
                          OsSocket::isFramed(mClientSocket->getIpProtocol()));

            // If the socket is not framed (is connection-oriented),
            // we need to abort the connection and post a message
            // :TODO: This doesn't work right for framed connection-oriented
            // protocols (like SCTP), but OsSocket doesn't have an EOF-query
            // method -- we need to close all connection-oriented
            // sockets as well in case it was an EOF.
            // Define a virtual function that returns the correct bit.
            if (!OsSocket::isFramed(mClientSocket->getIpProtocol()))
            {
                // On non-blocking connect failures, we need to get the first send message
                // in order to successfully trigger the protocol fallback mechanism
                if (!tcpOnErrWaitForSend)
                {
                   // Return all buffered messages with a transport error indication.
                   emptyBuffer(TRUE);
                   clientStopSelf();
                }
                else
                {
                   fds[1].revents &= ~(POLLERR | POLLHUP);  // clear error bit if waiting
                   waitingToReportErr = TRUE;
                }
            }
            // Delete the data read so far, which will not have been
            // deleted by HttpMessage::read.
            readBuffer.remove(0);
         }
      } // end POLLIN reading socket
   }
   while (isStarted());

   return 0;        // and then exit
}