Esempio n. 1
0
void SipDialog::updateDialogData(const SipMessage& message)
{
    UtlString messageCallId;
    message.getCallIdField(&messageCallId);
    Url messageFromUrl;
    message.getFromUrl(messageFromUrl);
    UtlString messageFromTag;
    messageFromUrl.getFieldParameter("tag", messageFromTag);
    Url messageToUrl;
    message.getToUrl(messageToUrl);
    UtlString messageToTag;
    messageToUrl.getFieldParameter("tag", messageToTag);

    int cSeq;
    UtlString method;
    message.getCSeqField(&cSeq, &method);
    int responseCode = message.getResponseStatusCode();

    // Figure out if the request is from the local or
    // the remote side
    if(isTransactionLocallyInitiated(messageCallId,
                                     messageFromTag,
                                     messageToTag))
    {
        // This message is part of a transaction initiated by
        // the local side of the dialog

        if(cSeq > mLastLocalCseq)
        {
            mLastLocalCseq = cSeq;
        }

        if(cSeq >= mLastLocalCseq)
        {
            // Always update the contact if it is set
            UtlString messageContact;
            // Get the Contact value, but as an addr-spec.
            if(message.getContactUri(0, &messageContact) &&
                !messageContact.isNull())
            {
                if(message.isResponse())
                {
                   mRemoteContact.fromString(messageContact, TRUE);
                }
                else
                {
                   mLocalContact.fromString(messageContact, TRUE);
                }
            }
        }

        // Cannot assume that we only establish a dialog with the
        // initial cseq.  For example if there is an authentication
        // challenge, the dialog will not be established until the
        // second transaction.
        if(cSeq == mLastLocalCseq)
        {
            // A successful response to an INVITE or SUBSCRIBE
            // make this early dialog a set up dialog
            if(mLocalInitiatedDialog &&
               message.isResponse() &&
               responseCode >= SIP_2XX_CLASS_CODE && // successful dialog setup
               responseCode < SIP_3XX_CLASS_CODE &&
               mRemoteTag.isNull() && // tag not set
               mRouteSet.isNull()) // have not yet set the route set
            {
                // Change this early dialog to a set up dialog.
                // The tag gets set in the 2xx response
                // so we need to update the URL
                message.getToUrl(mRemoteField);
                mRemoteField.getFieldParameter("tag", mRemoteTag);

                // Need to get the route set as well
                // Make sure the Request Method is allowed to set Record-Routes
                if(message.isRecordRouteAccepted())
                {
                    message.buildRouteField(&mRouteSet);
                }
            }
        }
    }
    else if(isTransactionRemotelyInitiated(messageCallId,
                                           messageFromTag,
                                           messageToTag))
    {
        int prevRemoteCseq = mLastRemoteCseq;

        // This message is part of a transaction initiated by
        // the callee/destination of the session
        if(cSeq > mLastRemoteCseq)
        {
            mLastRemoteCseq = cSeq;
        }

        if(cSeq >= mLastRemoteCseq)
        {
            // Always update the contact if it is set
            UtlString messageContact;
            // Get the Contact value, but as an addr-spec.
            if(message.getContactUri(0, &messageContact) &&
                !messageContact.isNull())
            {
                if(message.isResponse())
                {
                   mLocalContact.fromString(messageContact, TRUE);
                }
                else
                {
                   mRemoteContact.fromString(messageContact, TRUE);
                }
            }
        }

        // First transaction from the otherside
        if(cSeq == mLastRemoteCseq && prevRemoteCseq == -1)
        {
            // A response (e.g. NOTIFY) can come before we get the
            // successful response to the initial transaction
            if(!mLocalInitiatedDialog &&
               !message.isResponse() &&
               mRemoteTag.isNull()) // tag not set
            {
                // Change this early dialog to a set up dialog.
                // The tag gets set in the 2xx response
                // so we need to update the URL
                message.getFromUrl(mRemoteField);
                mRemoteField.getFieldParameter("tag", mRemoteTag);
            }
        }

        // First successful response from the local side
        if(cSeq == mLastRemoteCseq)
        {
            if(!mLocalInitiatedDialog &&
               message.isResponse() &&
               responseCode >= SIP_2XX_CLASS_CODE && // successful dialog setup
               responseCode < SIP_3XX_CLASS_CODE &&
               mLocalTag.isNull())
            {
                // Update the local tag
                message.getToUrl(mLocalField);
                mLocalField.getFieldParameter("tag", mLocalTag);
            }
        }
    }
}
UtlBoolean SipPersistentSubscriptionMgr::updateDialogInfo(
   const SipMessage& subscribeRequest,
   UtlString& resourceId,
   UtlString& eventTypeKey,
   UtlString& eventType,
   UtlString& subscribeDialogHandle,
   UtlBoolean& isNew,
   UtlBoolean& isSubscriptionExpired,
   SipMessage& subscribeResponse,
   SipSubscribeServerEventHandler& handler)
{
   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "SipPersistentSubscriptionMgr::updateDialogInfo "
                 "resourceId = '%s', eventTypeKey = '%s'",
                 resourceId.data(), eventTypeKey.data());

   UtlBoolean ret;

   // Call SipSubscriptionMgr to update the in-memory data.
   ret = SipSubscriptionMgr::updateDialogInfo(subscribeRequest,
                                              resourceId,
                                              eventTypeKey,
                                              eventType,
                                              subscribeDialogHandle,
                                              isNew,
                                              isSubscriptionExpired,
                                              subscribeResponse,
                                              handler);

   // If that succeeded, update the IMDB.
   if (ret)
   {
      UtlString requestUri;
      UtlString callId;
      UtlString contactEntry;
      UtlString to;
      UtlString from;
      UtlString route;
      UtlString accept;

      subscribeRequest.getRequestUri(&requestUri);
      subscribeRequest.getCallIdField(&callId);
      subscribeRequest.getContactEntry(0, &contactEntry);
      subscribeRequest.getToField(&to);
      subscribeRequest.getFromField(&from);
      subscribeRequest.buildRouteField(&route);
      accept.append(subscribeRequest.getHeaderValue(0, SIP_ACCEPT_FIELD));

      int expires = 0;
      subscribeResponse.getExpiresField(&expires);
      expires += OsDateTime::getSecsSinceEpoch();

      int subscribeCseq;
      UtlString subscribeCseqMethod;
      subscribeRequest.getCSeqField(&subscribeCseq, &subscribeCseqMethod);

      OsSysLog::add(FAC_SIP, PRI_DEBUG,
                    "SipPersistentSubscriptionMgr::updateDialogInfo "
                    "mComponent = '%s', requestUri = '%s', callId = '%s', contactEntry = '%s', expires = %d, to = '%s', from = '%s', key = '%s', route = '%s', accept = '%s'",
                    mComponent.data(), requestUri.data(),
                    callId.data(), contactEntry.data(), expires,
                    to.data(), from.data(), resourceId.data(), route.data(),
                    accept.data());

      // Attempt to update an existing row.
      int now = (int)OsDateTime::getSecsSinceEpoch();
      ret = mSubscriptionDBInstance->updateSubscribeUnexpiredSubscription(
         mComponent, to, from, callId, eventTypeKey, "",
         now, expires, subscribeCseq);
      
      if (!ret)
      {
         // Add a new row.

         // This call assumes that eventTypeKey is OK for use as the <eventtype>,
         // and that the NOTIFY CSeq's will start at 1.  0 is used as
         // the initial XML version.
         ret = mSubscriptionDBInstance->insertRow(
            mComponent, requestUri, callId, contactEntry,
            expires, subscribeCseq, eventTypeKey, "",
            to, from, resourceId, route, 1, accept, 0);

         if (!ret)
         {
            OsSysLog::add(FAC_SIP, PRI_ERR,
                          "SipPersistantSubscriptionMgr::addSubscription "
                          "Could not update or insert record in database");
         }
      }

      // Start the save timer.
      mPersistenceTimer.oneshotAfter(sPersistInterval);
   }

   return ret;
}