示例#1
0
//: Find a transaction for the given message
SipTransaction*
SipTransactionList::findTransactionFor(const SipMessage& message,
                                       UtlBoolean isOutgoing,
                   enum SipTransaction::messageRelationship& relationship)
{
    SipTransaction* transactionFound = NULL;
    UtlString callId;
    SipTransaction::buildHash(message, isOutgoing, callId);

    lock();

    // See if the message knows its transaction
    // DO NOT TOUCH THE CONTENTS of this transaction as it may no
    // longer exist.  It can only be used as an ID for the transaction.
    SipTransaction* messageTransaction = message.getSipTransaction();

    UtlString matchTransaction(callId);

    UtlHashBagIterator iterator(mTransactions, &matchTransaction);

    relationship = SipTransaction::MESSAGE_UNKNOWN;
    while ((transactionFound = (SipTransaction*) iterator()))
    {
        // If the message knows its SIP transaction
        // and the found transaction pointer does not match, skip the
        // expensive relationship calculation
        // The messageTransaction MUST BE TREATED AS OPAQUE
        // as it may have been deleted.
        if(   messageTransaction && transactionFound != messageTransaction )
        {
           continue;
        }

        // If the transaction has never sent the original rquest
        // it should never get a match for any messages.
        if(   messageTransaction == NULL // this message does not point to this TX
           && ((transactionFound->getState()) == SipTransaction::TRANSACTION_LOCALLY_INIITATED)
           )
        {
            continue;
        }

        relationship = transactionFound->whatRelation(message, isOutgoing);
        if(relationship == SipTransaction::MESSAGE_REQUEST ||
            relationship ==  SipTransaction::MESSAGE_PROVISIONAL ||
            relationship ==  SipTransaction::MESSAGE_FINAL ||
            relationship ==  SipTransaction::MESSAGE_NEW_FINAL ||
            relationship ==  SipTransaction::MESSAGE_CANCEL ||
            relationship ==  SipTransaction::MESSAGE_CANCEL_RESPONSE ||
            relationship ==  SipTransaction::MESSAGE_ACK ||
            relationship ==  SipTransaction::MESSAGE_2XX_ACK ||
            relationship ==  SipTransaction::MESSAGE_DUPLICATE)
        {
            break;
        }
    }

    UtlBoolean isBusy = FALSE;
    if(transactionFound == NULL)
    {
        relationship =
            SipTransaction::MESSAGE_UNKNOWN;
    }
    else
    {
        isBusy = transactionFound->isBusy();
        if(!isBusy)
        {
            transactionFound->markBusy();
        }
    }

    unlock();

    if(transactionFound && isBusy)
    {
        // If we cannot lock it, it does not exist
        if(!waitUntilAvailable(transactionFound, callId))
        {
            if (OsSysLog::willLog(FAC_SIP, PRI_WARNING))
            {
                UtlString relationString;
                SipTransaction::getRelationshipString(relationship, relationString);
                OsSysLog::add(FAC_SIP, PRI_WARNING,
                              "SipTransactionList::findTransactionFor %p not available relation: %s",
                              transactionFound, relationString.data());
            }
            transactionFound = NULL;
        }
    }

#if 0 // enable only for transaction match debugging - log is confusing otherwise
    UtlString relationString;
    SipTransaction::getRelationshipString(relationship, relationString);
    UtlString bytes;
    int len;
    message.getBytes(&bytes, &len);
    OsSysLog::add(FAC_SIP, PRI_DEBUG
                  ,"SipTransactionList::findTransactionFor %p %s %s %s"
#                 ifdef TIME_LOG
                  "\n\tTime Log %s"
#                 endif
                  ,&message
                  ,isOutgoing ? "OUTGOING" : "INCOMING"
                  ,transactionFound ? "FOUND" : "NOT FOUND"
                  ,relationString.data()
#                 ifdef TIME_LOG
                  ,findTimeLog.data()
#                 endif
                  );
    
#endif


    return(transactionFound);
}
示例#2
0
UtlBoolean CommandMsgProcessor::handleMessage(OsMsg& eventMessage)
{
        int msgType = eventMessage.getMsgType();
        // int msgSubType = eventMessage.getMsgSubType();

        if(msgType == OsMsg::PHONE_APP)
        // && msgSubType == CP_SIP_MESSAGE)
        {
                osPrintf("CommandMsgProcessor::handleMessage Got a message\n");
                int messageType = ((SipMessageEvent&)eventMessage).getMessageStatus();

                const SipMessage* sipMsg = ((SipMessageEvent&)eventMessage).getMessage();
                UtlString callId;
                if(sipMsg)
                {
                        osPrintf("numRespondToMessages: %d isResponse: %d messageType: %d TransErro: %d\n",
                                numRespondToMessages, sipMsg->isResponse(), messageType,
                                SipMessageEvent::TRANSPORT_ERROR);
                        if((numRespondToMessages == -1 || numRespondToMessages > 0) &&
                                !sipMsg->isResponse() && messageType != SipMessageEvent::TRANSPORT_ERROR)
                        {
                                osPrintf("valid message\n");
                                if(numRespondToMessages > 0)
                                {
                                        numRespondToMessages--;
                                }

                                SipMessage response;
                if(mpResponseMessage)
                {
                    response = *mpResponseMessage;
                }
                response.setResponseData(sipMsg, responseStatusCode, responseStatusText.data());

            UtlString address;
            int port;
            UtlString protocol;
            UtlString tag;

            sipMsg->getToAddress(&address,
               &port,
               &protocol,
               NULL,
               NULL,
               &tag) ;

            if( tag.isNull())
            {
               int tagNum = rand();
                                   char tag[100];
                                   sprintf(tag, "%d", tagNum);
               UtlString tagWithDot(tag);
               tagWithDot.append(".34756498567498567");
                                   response.setToFieldTag(tagWithDot);
            }

                                UtlString msgBytes;
                                int msgLen;
                                response.getBytes(&msgBytes, &msgLen);
                                osPrintf("%s",msgBytes.data());

                if(mpLastResponseMessage)
                {
                    delete mpLastResponseMessage;
                    mpLastResponseMessage = NULL;
                }
                // Keep a copy of the last response sent
                mpLastResponseMessage = new SipMessage(response);

                                if(userAgent->send(response))
                                {
                                        osPrintf("Sent response\n");
                                }
                                else
                                {
                                        osPrintf("Send failed\n");
                                }
                        }
                }
        }
        return(TRUE);
}
示例#3
0
bool SipDialogMonitor::removeExtension(UtlString& groupName, Url& contactUrl)
{
   bool result = false;
   mLock.acquire();
   // Check whether the group exists or not. If not, return false.
   SipResourceList* list =
      dynamic_cast <SipResourceList *> (mMonitoredLists.findValue(&groupName));
   if (list == NULL)
   {
      OsSysLog::add(FAC_SIP, PRI_DEBUG,
                    "SipDialogMonitor::removeExtension group %s does not exist",
                    groupName.data());
   }
   else
   {
      // Check whether the contact exists in the group or not.
      UtlString resourceId;
      contactUrl.getIdentity(resourceId);
      Resource* resource = list->getResource(resourceId);
      if (resource)
      {
         // If it exists, get the early dialog handle for the SUBSCRIBE,
         // which specifies all of its subscriptions.
         UtlString* earlyDialogHandle =
            dynamic_cast <UtlString *> (mDialogHandleList.findValue(&resourceId));
         if (earlyDialogHandle)
         {
            OsSysLog::add(FAC_SIP, PRI_DEBUG,
                          "SipDialogMonitor::removeExtension Calling endSubscription(%s)",
                          earlyDialogHandle->data());
            // Terminate the subscription.
            UtlBoolean status = mpSipSubscribeClient->endSubscriptionGroup(earlyDialogHandle->data());

            if (!status)
            {
               OsSysLog::add(FAC_SIP, PRI_ERR,
                             "SipDialogMonitor::removeExtension Unsubscription failed for %s.",
                             resourceId.data());
            }

            // Remove the remembered state for dialog event notices.
            destroyDialogState(earlyDialogHandle);
         }
         else
         {
            OsSysLog::add(FAC_SIP, PRI_ERR,
                          "SipDialogMonitor::removeExtension no dialogHandle for %s.",
                          resourceId.data());
         }

         // Now delete all the references to this URI.
         mDialogHandleList.destroy(&resourceId);
         resource = list->removeResource(resource);
         delete resource;

         result = true;
      }
      else
      {
         OsSysLog::add(FAC_LOG, PRI_WARNING,
                       "SipDialogMonitor::removeExtension subscription for contact %s does not exists.",
                       resourceId.data());
      }
   }

   mLock.release();
   return result;
}
示例#4
0
bool cAlarmServer::loadAlarmData(TiXmlElement* element, cAlarmData* data)
{

   UtlString codeStr;
   UtlString idStr;
   UtlString compStr("");
   UtlString sevStr("minor");
   UtlString resStr("");
   UtlString groupName("disabled");
   bool actEmail = true;
   bool actSms = true;
   bool actLog = true;
   bool actTrap = true;
   int  filtMax = INT_MAX;
   int  filtMin = 0;
   if (element && data)
   {
      idStr = element->Attribute("id");
      if (idStr.isNull())
      {
         OsSysLog::add(FAC_ALARM, PRI_ERR,"code=%s: alarm ID is required", codeStr.data());
         return false;
      }

      TiXmlElement* codeElement = element->FirstChildElement("code");
      if ( !codeElement )
      {
         OsSysLog::add(FAC_ALARM, PRI_ERR,
               "id=%s: alarm code is required", element->Attribute("id"));
         return false;
      }
      textContentShallow(codeStr, codeElement);

      codeElement = element->FirstChildElement("severity");
      if ( codeElement )
      {
         textContentShallow(sevStr, codeElement);
      }
      else
      {
         OsSysLog::add(FAC_ALARM, PRI_WARNING,
               "id=%s: no severity; assuming %s", idStr.data(), sevStr.data());
      }

      codeElement = element->FirstChildElement("component");
      if ( codeElement )
      {
         textContentShallow(compStr, codeElement);
      }
      else
      {
         OsSysLog::add(FAC_ALARM, PRI_WARNING,"id=%s: no component; set to null", idStr.data());
      }

      codeElement = element->FirstChildElement("action");
      actLog   = getBoolAttribute(codeElement, "log", true);
      if ( codeElement )
      {
         // Get the alarm group name used for both regular emails and SMS emails.
         groupName = codeElement->Attribute("email");
         if (strcmp(groupName.data(), "disabled") == 0)
         {
            // All regular/SMS notifications for this alarm type must be disabled.
            actEmail = false;
            actSms = false;
            actTrap = false;
         }
      }
      codeElement = element->FirstChildElement("filter");
      filtMax  = getIntAttribute(codeElement, "max_reports", INT_MAX);
      filtMin  = getIntAttribute(codeElement, "min_threshold");
   }
   else
   {
      return false;
   }

   data->setAlarmId(idStr);
   data->setCode(codeStr);
   data->setSeverity(sevToSyslogPri(sevStr));
   data->setComponent(compStr);
   data->setShortTitle(idStr);  // default fallback title is internal id
   data->setDescription(idStr); // default fallback description is internal id
   data->setResolution(resStr);
   data->actions[cAlarmData::eActionLog] = actLog;
   data->actions[cAlarmData::eActionEmail] = actEmail;
   data->actions[cAlarmData::eActionSms] = actSms;
   data->actions[cAlarmData::eActionTrap] = actTrap;
   data->group_name = groupName;
   data->max_report = filtMax;
   data->min_threshold = filtMin;
   data->resetCount();

   return true;

}
示例#5
0
bool cAlarmServer::loadAlarmConfig(const UtlString& alarmFile, const UtlString& groupFile)
{
   // load global alarm config from alarm-config.xml
   OsSysLog::add(FAC_ALARM, PRI_DEBUG, "Loading alarm config files '%s' '%s'",
                 alarmFile.data(), groupFile.data());

   // Load the alarm configuration file
   TiXmlDocument alarmDoc(alarmFile);
   TiXmlHandle alarmDocHandle( &alarmDoc );
   if (!alarmDoc.LoadFile())
   {
      UtlString errorMsg;
      XmlErrorMsg( alarmDoc, errorMsg );
      OsSysLog::add(FAC_ALARM, PRI_ERR, "Failed to load alarm config file: %s", errorMsg.data());
      return false;
   }
   TiXmlHandle alarmDocH( &alarmDoc );
   TiXmlHandle alarmServerHandle = alarmDocH.FirstChildElement("alarm_server");

   // Load the alarm group configuration file
   TiXmlDocument groupDoc(groupFile);
   TiXmlHandle groupDocHandle( &groupDoc );
   if (!groupDoc.LoadFile())
   {
      UtlString errorMsg;
      XmlErrorMsg( groupDoc, errorMsg );
      OsSysLog::add(FAC_ALARM, PRI_ERR, "Failed to load alarm group config file: %s", errorMsg.data());
      return false;
   }
   TiXmlHandle groupDocH( &groupDoc );
   TiXmlHandle groupServerHandle = groupDocH.FirstChildElement("alarm_groups");

   // Continue to process the alarm configuration file
   TiXmlElement* settingsElement = alarmServerHandle.FirstChildElement("settings").Element();
   if (!settingsElement)
   {
      OsSysLog::add(FAC_ALARM, PRI_ERR,
                    "No <settings> element in alarm config file '%s'",
                    alarmFile.data());
      return false;
   }

   TiXmlElement* langElement = settingsElement->FirstChildElement("language");
   if (langElement)
   {
      textContentShallow(mLanguage, langElement);
      OsSysLog::add(FAC_ALARM, PRI_INFO, "Language for alarm notifications: %s", mLanguage.data());
   }

   //load alarm action settings
   TiXmlElement* alarmActionsElement = settingsElement->FirstChildElement("actions");
   if (alarmActionsElement)
   {
      TiXmlElement* element = alarmActionsElement->FirstChildElement("log");
      if (getBoolAttribute(element, "enabled"))
      {
         LogNotifier* pLogNotifier = new LogNotifier();
         if (mpNotifiers[cAlarmData::eActionLog])
         {
            delete mpNotifiers[cAlarmData::eActionLog];
         }
         mpNotifiers[cAlarmData::eActionLog] = pLogNotifier;
         if (pLogNotifier)
         {
            pLogNotifier->init(element, NULL);
            gbActions[cAlarmData::eActionLog] = true;
         }
      }

      // Alarm email notifications
      element = alarmActionsElement->FirstChildElement("email");
      if (getBoolAttribute(element, "enabled"))
      {
         EmailNotifier* pEmailNotifier = new EmailNotifier();
         if (mpNotifiers[cAlarmData::eActionEmail])
         {
            delete mpNotifiers[cAlarmData::eActionEmail];
         }
         mpNotifiers[cAlarmData::eActionEmail] = pEmailNotifier;
         if (pEmailNotifier)
         {
            TiXmlElement* groupElement = groupServerHandle.FirstChildElement("definitions").Element();
            pEmailNotifier->init(element, groupElement);
            gbActions[cAlarmData::eActionEmail] = true;
         }
      }

      element = alarmActionsElement->FirstChildElement("sms");
      if (getBoolAttribute(element, "enabled"))
      {
         SmsNotifier* pSmsNotifier = new SmsNotifier();
         if (mpNotifiers[cAlarmData::eActionSms])
         {
            delete mpNotifiers[cAlarmData::eActionSms];
         }
         mpNotifiers[cAlarmData::eActionSms] = pSmsNotifier;
         if (pSmsNotifier)
         {
            TiXmlElement* groupElement = groupServerHandle.FirstChildElement("definitions").Element();
            pSmsNotifier->init(element, groupElement);
            gbActions[cAlarmData::eActionSms] = true;
         }
      }

      // Alarm SNMPv2 trap notifications
      element = alarmActionsElement->FirstChildElement("trap");
      if (getBoolAttribute(element, "enabled"))
      {
         TrapNotifier* pTrapNotifier = new TrapNotifier();
         if (mpNotifiers[cAlarmData::eActionTrap])
         {
            delete mpNotifiers[cAlarmData::eActionTrap];
         }
         mpNotifiers[cAlarmData::eActionTrap] = pTrapNotifier;
         if (pTrapNotifier)
         {
            TiXmlElement* groupElement = groupServerHandle.FirstChildElement("definitions").Element();
            pTrapNotifier->init(element, groupElement);
            gbActions[cAlarmData::eActionTrap] = true;
         }
      }
      else
      {
         // The trap notification of alarms is disabled.
         // So, delete the notifier
         if (mpNotifiers[cAlarmData::eActionTrap])
         {
            delete mpNotifiers[cAlarmData::eActionTrap];
            mpNotifiers[cAlarmData::eActionTrap] = 0;
         }
         gbActions[cAlarmData::eActionTrap] = false;
      }
   }
   return true;
}
示例#6
0
// Constructor
ResourceListServer::ResourceListServer(const UtlString& domainName,
                                       const UtlString& realm,
                                       SipLineMgr* lineMgr,
                                       const char* eventType,
                                       const char* contentType,
                                       int tcpPort,
                                       int udpPort,
                                       int tlsPort,
                                       const UtlString& bindIp,
                                       UtlString* resourceListFile,
                                       int refreshInterval,
                                       int resubscribeInterval,
                                       int minResubscribeInterval,
                                       int publishingDelay,
                                       int maxRegSubscInResource,
                                       int maxContInRegSubsc,
                                       int maxResInstInCont,
                                       int maxDialogsInResInst,
                                       int serverMinExpiration,
                                       int serverDefaultExpiration,
                                       int serverMaxExpiration,
                                       const UtlString&  subscriptionDbName,
                                       const UtlString&  credentialDbName) :
   mDomainName(domainName),
   mEventType(eventType),
   mContentType(contentType),
   mResourceListFile(*resourceListFile),
   mRefreshInterval(refreshInterval),
   mResubscribeInterval(resubscribeInterval),
   mMinResubscribeInterval(minResubscribeInterval),
   mPublishingDelay(publishingDelay),
   mMaxRegSubscInResource(maxRegSubscInResource),
   mMaxContInRegSubsc(maxContInRegSubsc),
   mMaxResInstInCont(maxResInstInCont),
   mMaxDialogsInResInst(maxDialogsInResInst),
   mServerUserAgent(
      tcpPort, // sipTcpPort
      udpPort, // sipUdpPort
      tcpPort, // sipTlsPort
      NULL, // publicAddress
      NULL, // defaultUser
      bindIp, // defaultSipAddress
      NULL, // sipProxyServers
      NULL, // sipDirectoryServers
      NULL, // sipRegistryServers
      NULL, // authenticationScheme
      NULL, // authenicateRealm
      NULL, // authenticateDb
      NULL, // authorizeUserIds
      NULL, // authorizePasswords
      NULL, // lineMgr
      SIP_DEFAULT_RTT, // sipFirstResendTimeout
      TRUE, // defaultToUaTransactions
      -1, // readBufferSize
      OsServerTask::DEF_MAX_MSGS, // queueSize
      FALSE // bUseNextAvailablePort
      ),
   mClientUserAgent(
      PORT_DEFAULT, // sipTcpPort
      PORT_DEFAULT, // sipUdpPort
      PORT_DEFAULT, // sipTlsPort
      NULL, // publicAddress
      NULL, // defaultUser
      bindIp, // defaultSipAddress
      domainName.data(), // sipProxyServers
      NULL, // sipDirectoryServers
      NULL, // sipRegistryServers
      NULL, // authenticationScheme
      NULL, // authenicateRealm
      NULL, // authenticateDb
      NULL, // authorizeUserIds
      NULL, // authorizePasswords
      lineMgr, // lineMgr
      SIP_DEFAULT_RTT, // sipFirstResendTimeout
      TRUE, // defaultToUaTransactions
      -1, // readBufferSize
      OsServerTask::DEF_MAX_MSGS, // queueSize
      FALSE // bUseNextAvailablePort
      ),
   mSubscriptionMgr(SUBSCRIPTION_COMPONENT_RLS, mDomainName, subscriptionDbName),
   mPolicyHolder(domainName, realm, credentialDbName),
   mSubscribeServer(mServerUserAgent, mEventPublisher, mSubscriptionMgr,
                    mPolicyHolder),
   mRefreshMgr(mClientUserAgent, mDialogManager),
   mSubscribeClient(mClientUserAgent, mDialogManager, mRefreshMgr),
   mResourceListTask(this),
   mResourceListSet(this),
   // Do not set the resource list file name yet, so the ResourceListFileReader
   // doesn't add elements to the ResourceListSet before we have the
   // SIP tasks set up.
   mResourceListFileReader(UtlString(""), &mResourceListSet)
{
   OsSysLog::add(FAC_RLS, PRI_DEBUG,
                 "ResourceListServer::_ this = %p, mDomainName = '%s', mEventType = '%s', mContentType = '%s', "
                 "mRefreshInterval = %d, mResubscribeInterval = %d",
                 this, mDomainName.data(), mEventType.data(), mContentType.data(), mRefreshInterval,
                 mResubscribeInterval);
   OsSysLog::add(FAC_RLS, PRI_DEBUG,
                 "ResourceListServer::_ this = %p, mPublishingDelay = %d, mMaxRegSubscInResource = %d, "
                 "mMaxContInRegSubsc = %d, mMaxResInstInCont = %d, mMaxDialogsInResInst = %d",
                 this, publishingDelay, mMaxRegSubscInResource, mMaxContInRegSubsc, mMaxResInstInCont,
                 mMaxDialogsInResInst);

   // Initialize the call processing objects.

   // Construct addresses:
   // our local host-part
   // contact address to be used in client outgoing requests (primarily SUBSCRIBEs)
   {
      // Get our address and the client port.
      UtlString localAddress;
      int localPort;
      mClientUserAgent.getLocalAddress(&localAddress, &localPort);

      char buffer[100];

      // Construct the server's host-part.
      sprintf(buffer, "%s:%d", localAddress.data(), portIsValid(udpPort) ? udpPort : tcpPort);
      mServerLocalHostPart = buffer;

      // Construct the client's From URI.
      sprintf(buffer, "sip:sipXrls@%s:%d", localAddress.data(), localPort);
      mClientFromURI = buffer;

      // Obtain the client's Contact URI.
      mClientUserAgent.getContactURI(mClientContactURI);
   }

   // Initialize the SipUserAgent's.
   // Set the user-agent strings.
   mServerUserAgent.setUserAgentHeaderProperty("sipXecs/rls");
   mClientUserAgent.setUserAgentHeaderProperty("sipXecs/rls");

   // Require the "eventlist" extension in the Resource List clients.
   mServerUserAgent.requireExtension(SIP_EVENTLIST_EXTENSION);

   // Set the subscribe server grant times.
   if (!mSubscriptionMgr.setSubscriptionTimes(serverMinExpiration,
                                              serverDefaultExpiration,
                                              serverMaxExpiration))
   {
      OsSysLog::add(FAC_RLS, PRI_ERR,
                    "ResourceListServer given unacceptable server subscription times: min = %d, default = %d, max = %d.  Using the default subscription times.",
                    serverMinExpiration,
                    serverDefaultExpiration,
                    serverMaxExpiration);
   }
}
示例#7
0
   void testTwoHookTypes()
      {
         OsConfigDb configuration;

         configuration.set("TWO_TYPE_NOTPASSED_HOOK_LIBRARY.Error", PLUGIN_LIB_DIR "libfoo" PLUGIN_EXT);
         configuration.set("TWO_TYPE_OTHERPARAM", "DummyValue");

         // Configure two different hook types - each in its own library
         //   (we cheat - it's the same source, modified by configuration
         //    switches; see comments in ../testplugin/TestPlugin.cpp)
         configuration.set("TWO_TYPE1_HOOK_LIBRARY.First",
                           PLUGIN_LIB_DIR "libtestpluginA" PLUGIN_EXT);
         configuration.set("TWO_TYPE1.First.VALUE", "FirstValue");

         configuration.set("TWO_TYPE2_HOOK_LIBRARY.Second",
                           PLUGIN_LIB_DIR "libtestpluginB" PLUGIN_EXT);
         configuration.set("TWO_TYPE2.Second.VALUE", "SecondValue");

         // load the first hook type
         PluginHooks test1Plugins("getTestPlugin", "TWO_TYPE1");
         test1Plugins.readConfig(configuration);

         // load the second hook type
         PluginHooks test2Plugins("getTestPlugin", "TWO_TYPE2");
         test2Plugins.readConfig(configuration);

         // create iterators for both hook types
         PluginIterator plugin1(test1Plugins);
         PluginIterator plugin2(test2Plugins);

         UtlString name;
         TestPlugin* thePlugin;
         UtlString fullName;

         // get the first instance of the first hook type and confirm the names
         thePlugin = static_cast<TestPlugin*>(plugin1.next(&name));
         CPPUNIT_ASSERT(thePlugin != NULL);
         thePlugin->pluginName(fullName);
         ASSERT_STR_EQUAL("TestPluginA::First",fullName.data());

         // confirm the first hook type is using the correct configuration value
         const UtlString ValueKey("VALUE");
         UtlString pluginValue;
         CPPUNIT_ASSERT(thePlugin->getConfiguredValueFor(ValueKey, pluginValue));
         ASSERT_STR_EQUAL("FirstValue",pluginValue.data());

         // get the first instance of the second hook type and confim its names
         thePlugin = static_cast<TestPlugin*>(plugin2.next(&name));
         CPPUNIT_ASSERT(thePlugin != NULL);
         thePlugin->pluginName(fullName);
         ASSERT_STR_EQUAL("TestPluginB::Second",fullName.data());

         // confirm the configuration of the second hook type
         CPPUNIT_ASSERT(thePlugin->getConfiguredValueFor(ValueKey, pluginValue));
         ASSERT_STR_EQUAL("SecondValue",pluginValue.data());

         // make sure each type only has the one instance
         CPPUNIT_ASSERT(plugin1.next(&name) == NULL);
         CPPUNIT_ASSERT(name.isNull());
         CPPUNIT_ASSERT(plugin2.next(&name) == NULL);
         CPPUNIT_ASSERT(name.isNull());
      }
示例#8
0
      void handleRemoteNATedToRemoteNATedCall()
      {
         const char* message =
            "INVITE sip:[email protected]:5060;x-sipX-pubcontact=47.135.162.145%3A29544 SIP/2.0\r\n"
            "Record-Route: <sip:192.168.0.2:5060;lr>\r\n"
            "From: caller <sip:[email protected]>;tag=94bc25b8-c0a80165-13c4-3e635-37aa1989-3e635\r\n"
            "To: <sip:[email protected]>\r\n"
            "Call-Id: 94bb2520-c0a80165-13c4-3e635-3ccd2971-3e635@rjolyscs2.ca.nortel.com\r\n"
            "Cseq: 1 INVITE\r\n"
            "Max-Forwards: 19\r\n"
            "Supported: replaces\r\n"
            "User-Agent: LG-Nortel LIP 6804 v1.2.38sp SN/00405A187376\r\n"
            "Contact: <sip:[email protected]:5060;x-sipX-pubcontact=47.135.162.145%3A14956>\r\n"
            "Content-Type: application/sdp\r\n"
            "Content-Length: 297\r\n"
            "Date: Thu, 12 Jun 2008 19:14:29 GMT\r\n"
            "Via: SIP/2.0/UDP 192.168.0.2;branch=z9hG4bK-sipXecs-01a17f9662b96b1d454a71775bbda1ec6bf6~9d6590763d78764b93a42e94dbd6b75a\r\n"
            "Via: SIP/2.0/UDP 192.168.1.101:5060;branch=z9hG4bK-3e635-f3b41fc-310ddca7;received=47.135.162.145;rport=14956\r\n"
            "\r\n"
            "\r\n"
            "v=0\r\n"
            "o=LGEIPP 874 874 IN IP4 192.168.1.101\r\n"
            "s=SIP Call\r\n"
            "c=IN IP4 192.168.1.101\r\n"
            "t=0 0\r\n"
            "m=audio 23000 RTP/AVP 18 0 8 4 101\r\n"
            "a=rtpmap:18 G729/8000\r\n"
            "a=rtpmap:0 PCMU/8000\r\n"
            "a=rtpmap:8 PCMA/8000\r\n"
            "a=rtpmap:4 G723/8000\r\n"
            "a=rtpmap:101 telephone-event/8000\r\n"
            "a=fmtp:18 annexb=no\r\n"
            "a=fmtp:101 0-11\r\n"
            "a=sendrecv\r\n";
         SipMessage testMsg(message, strlen(message));

         UtlString rejectReason;
         UtlSList emptyList;
         RouteState routeState( message, emptyList, "192.168.0.2:5060" );         

         AuthPlugin::AuthResult result;
         result = pNatTraversalAgent->authorizeAndModify( "id",                             //dummy
                                                          Url("sip:[email protected]:5060"), //dummy
                                                          routeState,
                                                          "INVITE",
                                                          AuthPlugin::CONTINUE,
                                                          testMsg,
                                                          false,
                                                          rejectReason );

         // check auth result
         CPPUNIT_ASSERT( result == AuthPlugin::CONTINUE );

         // check that call tracker got created
         UtlString callId;
         CallTracker* pTracker;
         testMsg.getCallIdField( &callId );
         pTracker = pNatTraversalAgent->getCallTrackerFromCallId( callId );   
         CPPUNIT_ASSERT( pTracker != 0 );
         
         // check that public transport of caller got encoded in route state
         UtlString transportInfo;
         routeState.getParameter( pNatTraversalAgent->mInstanceName.data(), CALLER_PUBLIC_TRANSPORT_PARAM, transportInfo );
         ASSERT_STR_EQUAL( "47.135.162.145:14956;transport=udp", transportInfo.data()  );
         
         // check that public transport of callee got encoded in route state
         routeState.getParameter( pNatTraversalAgent->mInstanceName.data(), CALLEE_PUBLIC_TRANSPORT_PARAM, transportInfo );
         ASSERT_STR_EQUAL( "47.135.162.145:29544;transport=udp", transportInfo.data()  );

         // Check that sipX NAT route is set to reach the callee's public IP address
         UtlString natRoute;
         CPPUNIT_ASSERT( testMsg.getSipXNatRoute( &natRoute ) == true );
         ASSERT_STR_EQUAL( "47.135.162.145:29544;transport=udp", natRoute.data() );
         // Now present the message to the Output Processor and verify that it got processed correctly.
         routeState.update( &testMsg ); // uodate route state as it would normally be done by SipRouter.
         pNatTraversalAgent->handleOutputMessage( testMsg, "47.135.162.145", 29544 );
         
         // verify that top via got adjusted to reflect our public IP address
         UtlString topmostVia;
         CPPUNIT_ASSERT( testMsg.getViaFieldSubField( &topmostVia, 0 ) );
         ASSERT_STR_EQUAL( "SIP/2.0/UDP 47.135.162.140:5060;branch=z9hG4bK-sipXecs-01a17f9662b96b1d454a71775bbda1ec6bf6~9d6590763d78764b93a42e94dbd6b75a",
                           topmostVia.data() );
         
         // verify that top route got modfified to reflect our public address
         UtlString tmpRecordRoute;
         CPPUNIT_ASSERT( testMsg.getRecordRouteUri( 0, &tmpRecordRoute ) );
         Url tmpRecordRouteUrl( tmpRecordRoute );
         UtlString tmpRecordRouteHost;
         tmpRecordRouteUrl.getHostWithPort( tmpRecordRouteHost );
         ASSERT_STR_EQUAL( "47.135.162.140:5060", tmpRecordRouteHost.data() );         

         // recall the call tracker based on message and compare with previous
         CallTracker* pTracker2;
         pTracker2 = pNatTraversalAgent->getCallTrackerForMessage( testMsg );
         CPPUNIT_ASSERT( pTracker2 == pTracker );

         // check that the SDP got changed properly to relay media 
         const SdpBody* pSdpBody = testMsg.getSdpBody();
         CPPUNIT_ASSERT( pSdpBody );
         UtlString mediaType, mediaTransportType;
         int mediaPort, mediaPortPairs, numPayloadTypes, payloadTypes[10];
         SdpDirectionality dir;
         
         CPPUNIT_ASSERT( pSdpBody->getMediaData( 0, 
                                 &mediaType,
                                 &mediaPort,
                                 &mediaPortPairs,
                                 &mediaTransportType,
                                 10,
                                 &numPayloadTypes,
                                 payloadTypes,
                                 &dir ) == TRUE );
         CPPUNIT_ASSERT( mediaType == "audio" );
         CPPUNIT_ASSERT( mediaPort == 10000 );
         CPPUNIT_ASSERT( mediaPortPairs == 1 );
         CPPUNIT_ASSERT( mediaTransportType == "RTP/AVP" );
         CPPUNIT_ASSERT( numPayloadTypes == 5 );
         CPPUNIT_ASSERT( payloadTypes[0] == 18 );
         CPPUNIT_ASSERT( payloadTypes[1] == 0 );
         CPPUNIT_ASSERT( payloadTypes[2] == 8 );
         CPPUNIT_ASSERT( payloadTypes[3] == 4 );
         CPPUNIT_ASSERT( payloadTypes[4] == 101 );
         CPPUNIT_ASSERT( dir == sdpDirectionalitySendRecv );
     
         // check that we are using the public IP address of the media relay
         UtlString mediaAddress;
         CPPUNIT_ASSERT( pSdpBody->getMediaAddress(0, &mediaAddress ) );
         ASSERT_STR_EQUAL( pNatTraversalAgent->mNatTraversalRules.getMediaRelayPublicAddress(), mediaAddress );
 
         // Mow simulalate the reception of the response
         const char* response = 
         "SIP/2.0 200 OK\r\n"
         "From: \"R1_2 - 602\"<sip:[email protected]>;tag=94bc25b8-c0a80165-13c4-3e635-37aa1989-3e635\r\n"
         "To: <sip:[email protected]>;tag=94bf84d0-c0a8010b-13c4-3e8d1-496994c2-3e8d1\r\n"
         "Call-ID: 94bb2520-c0a80165-13c4-3e635-3ccd2971-3e635@rjolyscs2.ca.nortel.com\r\n"
         "CSeq: 1 INVITE\r\n"
         "Via: SIP/2.0/UDP 192.168.1.101:5060;received=47.135.162.145;rport=14956;branch=z9hG4bK-3e635-f3b41fc-310ddca7;id=1234-0\r\n"
         "Supported: replaces\r\n"
         "Contact: <sip:[email protected]:5060>\r\n"
         "Record-Route: <sip:47.135.162.140:5060;lr;sipXecs-rs=%2Afrom%7EOTRiYzI1YjgtYzBhODAxNjUtMTNjNC0zZTYzNS0zN2FhMTk4OS0zZTYzNQ%60%60.400_authrules%2Aauth%7E.900_ntap%2ACeT%7ENDcuMTM1LjE2Mi4xNDU6Mjk1NDQ7dHJhbnNwb3J0PXVkcA%60%60.900_ntap%2ACrT%7ENDcuMTM1LjE2Mi4xNDU6MTQ5NTY7dHJhbnNwb3J0PXVkcA%60%60.900_ntap%2Aid%7EMC0w%215d4c53f8d9c9ecd8d089e57ba7a59513>\r\n"
         "Content-Type: application/sdp\r\n"
         "Content-Length: 202\r\n"
         "\r\n"
         "\r\n"
         "v=0\r\n"
         "o=LGEIPP 5466 5466 IN IP4 192.168.1.11\r\n"
         "s=SIP Call\r\n"
         "c=IN IP4 192.168.1.11\r\n"
         "t=0 0\r\n"
         "m=audio 23020 RTP/AVP 0 101\r\n"
         "a=rtpmap:0 PCMU/8000\r\n"
         "a=rtpmap:101 telephone-event/8000\r\n"
         "a=fmtp:101 0-11\r\n"
         "a=sendrecv\r\n"
         "a=x-sipx-ntap:192.168.0.2;1\r\n";
         SipMessage okResp( response, strlen(response) );

         pNatTraversalAgent->handleOutputMessage( okResp, "47.135.162.145", 14956 );

         // check that the record route still has our public IP address
         CPPUNIT_ASSERT( okResp.getRecordRouteUri( 0, &tmpRecordRoute ) );
         Url tmpRecordRouteUrl2( tmpRecordRoute );
         tmpRecordRouteUrl2.getHostWithPort( tmpRecordRouteHost );
         ASSERT_STR_EQUAL( "47.135.162.140:5060", tmpRecordRouteHost.data() );         
         
         // check that the SDP got changed properly to relay media 
         pSdpBody = okResp.getSdpBody();
         CPPUNIT_ASSERT( pSdpBody );
         CPPUNIT_ASSERT( pSdpBody->getMediaData( 0, 
                                 &mediaType,
                                 &mediaPort,
                                 &mediaPortPairs,
                                 &mediaTransportType,
                                 10,
                                 &numPayloadTypes,
                                 payloadTypes,
                                 &dir ) == TRUE );
         CPPUNIT_ASSERT( mediaType == "audio" );
         CPPUNIT_ASSERT( mediaPort == 11000 );
         CPPUNIT_ASSERT( mediaPortPairs == 1 );
         CPPUNIT_ASSERT( mediaTransportType == "RTP/AVP" );
         CPPUNIT_ASSERT( numPayloadTypes == 2 );
         CPPUNIT_ASSERT( payloadTypes[0] == 0);
         CPPUNIT_ASSERT( payloadTypes[1] == 101 );
         CPPUNIT_ASSERT( dir == sdpDirectionalitySendRecv );

         // check that we are using the public IP address of the media relay
         CPPUNIT_ASSERT( pSdpBody->getMediaAddress(0, &mediaAddress ) );
         ASSERT_STR_EQUAL( pNatTraversalAgent->mNatTraversalRules.getMediaRelayPublicAddress(), mediaAddress );
      }
示例#9
0
void
SipRedirectorMPT::processForm(const HttpRequestContext& requestContext,
                              const HttpMessage& request,
                              HttpMessage*& response)
{
   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "%s::processForm entered", mLogName.data());
   UtlString* user;

   // Process the request.

   // Get the body of the request.
   const HttpBody* request_body = request.getBody();

   // Get the value from the form.
   // This is quite a chore, because getMultipartBytes gets the entire
   // multipart section, including the trailing delimiter, rather than just
   // the body, which is what we need.
   const char* value;
   int length;
   request_body->getMultipartBytes(0, &value, &length);
#if 0
   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "%s::processForm A *** seeing '%.*s'", mLogName.data(), length, value);
#endif
   // Advance 'value' over the first \r\n\r\n, which ends the headers.
   const char* s = strstr(value, "\r\n\r\n");
   if (s)
   {
      s += 4;                   // Allow for length of \r\n\r\n.
      length -= s - value;
      value = s;
   }
   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "%s::processForm B *** seeing '%.*s'", mLogName.data(), length, value);
#if 0
   // Search backward for the last \r, excepting the one in the second-to-last
   // position, which marks the end of the contents.
   if (length >= 3)
   {
      for (s = value + length - 3;
           !(s == value || *s == '\r');
           s--)
      {
         /* empty */
      }
      length = s - value;
   }
   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "%s::processForm seeing '%.*s'", mLogName.data(), length, value);
#endif

   // Add the mappings.
   const char* error_msg;
   int error_location;
   UtlBoolean success =
      MPTredirector->addMappings(value, length, user, error_msg,
                                 error_location);

   // Construct the response.

   response = new HttpMessage();

   // Send 200 OK reply.
   response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION,
                                        HTTP_OK_CODE,
                                        HTTP_OK_TEXT);
   // Construct the HTML.
   char buffer1[100];
#if 0
   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "%s::processForm *** domain '%s'", mLogName.data(),
                 MPTredirector->mDomainName.data());
#endif
   if (success)
   {
      OsSysLog::add(FAC_SIP, PRI_DEBUG,
                    "%s::processForm success user '%s'", mLogName.data(),
                    user->data());
      sprintf(buffer1, "<code>sip:<font size=\"+1\">%s</font>@%s:65070</code> redirects to:<br />",
              user->data(), MPTredirector->mDomainName.data());
   }
   else
   {
      OsSysLog::add(FAC_SIP, PRI_DEBUG,
                    "%s::processForm failure error_msg '%s', error_location %d", mLogName.data(),
                    error_msg, error_location);
      strcpy(buffer1, "<i>Error:</i>");
   }
   // Transcribe the input value into buffer2.
   char buffer2[FORM_SIZE];
   char* p;
   int i;
   if (success)
   {
      // An impossible location.
      error_location = -1;
   }
   for (p = buffer2, i = 0;
        ;
        i++)
   {
      // If this is the error location, insert the error message.
      if (i == error_location)
      {
         *p++ = '!';
         *p++ = '-';
         *p++ = '-';
         strcpy(p, error_msg);
         p += strlen(error_msg);
         *p++ = '-';
         *p++ = '-';
         *p++ = '!';
      }
      // Test for ending the loop after testing to insert the error message,
      // because the error message may be after the last character.
      if (i >= length)
      {
         break;
      }
      switch (value[i])
      {
      case '<':
         *p++ = '&';
         *p++ = 'l';
         *p++ = 't';
         *p++ = ';';
         break;
      case '>':
         *p++ = '&';
         *p++ = 'g';
         *p++ = 't';
         *p++ = ';';
         break;
      case '&':
         *p++ = '&';
         *p++ = 'a';
         *p++ = 'm';
         *p++ = 'p';
         *p++ = ';';
         break;
      default:
         *p++ = value[i];
         break;
      }
   }
   *p++ = '\0';
   char buffer[FORM_SIZE];
   sprintf(buffer, form, buffer1, buffer2);
   // Insert the HTML into the response.
   HttpBody* response_body = new HttpBody(buffer, -1, CONTENT_TYPE_TEXT_HTML);
   response->setBody(response_body);
}
示例#10
0
int HttpGetCommand::execute(int argc, char* argv[])
{
    int commandStatus = CommandProcessor::COMMAND_FAILED;
    if(argc == 2)
    {
        commandStatus = CommandProcessor::COMMAND_SUCCESS;
        const char* url = argv[1];
        const char* serverBegin = strstr(url, "http://");
        if(serverBegin != url)
        {
            printf("unsupported protocol in Url: %s\n",
                url);
                    commandStatus = CommandProcessor::COMMAND_BAD_SYNTAX;
        }

        else
        {
            serverBegin += 7;
            UtlString uri(serverBegin);
            int serverEndIndex = uri.index("/");
            if(serverEndIndex < 0) serverEndIndex = uri.length();
            if(serverEndIndex > 0)
            {
                UtlString server = uri;
                server.remove(serverEndIndex);
                int portIndex = server.index(":");
                int port = PORT_NONE;
                if(portIndex > 0)
                {
                    UtlString portString = server;
                    server.remove(portIndex);
                    portString.remove(0, portIndex + 1);
                    printf("port string: %s\n", portString.data());
                    port = atoi(portString.data());
                }
                uri.remove(0, serverEndIndex);
                if(uri.isNull()) uri = "/";
                printf("HTTP get of %s from server %s port: %d\n",
                    uri.data(), server.data(), port);

                if (!portIsValid(port))
                {
                    port = 80;
                    printf("defaulting to http port 80\n");
                }

                OsConnectionSocket getSocket(port, server.data());
                HttpMessage getRequest;
                getRequest.setFirstHeaderLine("GET", uri.data(), HTTP_PROTOCOL_VERSION);

                int wroteBytes = getRequest.write(&getSocket);
                printf("wrote %d\n", wroteBytes);

                HttpMessage getResponse;
                getResponse.read(&getSocket);

                UtlString responseBytes;
                int responseLength;
                getResponse.getBytes(&responseBytes, &responseLength);
                printf("Got %d bytes\n", responseLength);
                printf("Response: ++++++++++++++++++++++++++++++++++\n%s\n",
                    responseBytes.data());
            }

            else
            {
                printf("invalid server in Url: %s\n",
                url);
                        commandStatus = CommandProcessor::COMMAND_BAD_SYNTAX;
            }
        }
    }

        else
        {
                UtlString usage;
                getUsage(argv[0], &usage);
                printf("%s", usage.data());
                commandStatus = CommandProcessor::COMMAND_BAD_SYNTAX;
                //commandStatus = CommandProcessor::COMMAND_FAILED;
        }

        return(commandStatus);
}
示例#11
0
      void handleLocalNATedToRemoteNATedCall()
      {
         const char* message =
           "INVITE sip:[email protected]:5060;x-sipX-pubcontact=47.135.162.145%3A29544 SIP/2.0\r\n"
           "Record-Route: <sip:192.168.0.2:5060;lr>\r\n"
           "From: \"L3\"<sip:[email protected]>;tag=94bb9480-c0a80065-13c4-50045-20c55bd3-50045\r\n"
           "To: <sip:[email protected]>\r\n"
           "Call-Id: 94bb55a0-c0a80065-13c4-50045-61a3ad3-50045@rjolyscs2.ca.nortel.com\r\n"
           "Cseq: 1 INVITE\r\n"
           "Via: SIP/2.0/UDP 192.168.0.2;branch=z9hG4bK-sipXecs-8130adee90e0277761fec4ee1c194a56838f~9d6590763d78764b93a42e94dbd6b75a\r\n"
           "Via: SIP/2.0/UDP 192.168.0.101:5060;branch=z9hG4bK-50045-13890e4e-4f17a229\r\n"
           "Max-Forwards: 19\r\n"
           "Supported: replaces\r\n"
           "User-Agent: LG-Nortel LIP 6812 v1.2.38sp SN/00405A183385\r\n"
           "Contact: <sip:[email protected]:5060;x-sipX-nonat>\r\n"
           "Content-Type: application/sdp\r\n"
           "Content-Length: 301\r\n"
           "Date: Fri, 13 Jun 2008 14:48:44 GMT\r\n"
           "\r\n"
           "\r\n"
           "v=0\r\n"
           "o=LGEIPP 14595 14595 IN IP4 192.168.0.101\r\n"
           "s=SIP Call\r\n"
           "c=IN IP4 192.168.0.101\r\n"
           "t=0 0\r\n"
           "m=audio 23016 RTP/AVP 18 4 0 8 101\r\n"
           "a=rtpmap:18 G729/8000\r\n"
           "a=rtpmap:4 G723/8000\r\n"
           "a=rtpmap:0 PCMU/8000\r\n"
           "a=rtpmap:8 PCMA/8000\r\n"
           "a=rtpmap:101 telephone-event/8000\r\n"
           "a=fmtp:18 annexb=no\r\n"
           "a=fmtp:101 0-11\r\n"
           "a=sendrecv\r\n";
         SipMessage testMsg(message, strlen(message));

         UtlString rejectReason;
         UtlSList emptyList;
         RouteState routeState( message, emptyList, "192.168.0.2:5060" );         

         AuthPlugin::AuthResult result;
         result = pNatTraversalAgent->authorizeAndModify( "id",                             //dummy
                                                          Url("sip:[email protected]:5060"), //dummy
                                                          routeState,
                                                          "INVITE",
                                                          AuthPlugin::CONTINUE,
                                                          testMsg,
                                                          false,
                                                          rejectReason );

         // check auth result
         CPPUNIT_ASSERT( result == AuthPlugin::CONTINUE );

         // check that call tracker got created
         UtlString callId;
         CallTracker* pTracker;
         testMsg.getCallIdField( &callId );
         pTracker = pNatTraversalAgent->getCallTrackerFromCallId( callId );   
         CPPUNIT_ASSERT( pTracker != 0 );
         
         // check that no public transport of caller got encoded in route state
         UtlString transportInfo;
         CPPUNIT_ASSERT( !routeState.getParameter( pNatTraversalAgent->mInstanceName.data(), CALLER_PUBLIC_TRANSPORT_PARAM, transportInfo ) );
         
         // check that public transport of callee got encoded in route state
         routeState.getParameter( pNatTraversalAgent->mInstanceName.data(), CALLEE_PUBLIC_TRANSPORT_PARAM, transportInfo );
         ASSERT_STR_EQUAL( "47.135.162.145:29544;transport=udp", transportInfo.data()  );

         // Check that sipX NAT route is set to reach the callee's public IP address
         UtlString natRoute;
         CPPUNIT_ASSERT( testMsg.getSipXNatRoute( &natRoute ) == true );
         ASSERT_STR_EQUAL( "47.135.162.145:29544;transport=udp", natRoute.data() );
         // Now present the message to the Output Processor and verify that it got processed correctly.
         routeState.update( &testMsg ); // uodate route state as it would normally be done by SipRouter.
         pNatTraversalAgent->handleOutputMessage( testMsg, "47.135.162.145", 29544 );
         
         // verify that top via got adjusted to reflect our public IP address
         UtlString topmostVia;
         CPPUNIT_ASSERT( testMsg.getViaFieldSubField( &topmostVia, 0 ) );
         ASSERT_STR_EQUAL( "SIP/2.0/UDP 47.135.162.140:5060;branch=z9hG4bK-sipXecs-8130adee90e0277761fec4ee1c194a56838f~9d6590763d78764b93a42e94dbd6b75a",
                           topmostVia.data() );
         
         // verify that top route got modfified to reflect our public address
         UtlString tmpRecordRoute;
         CPPUNIT_ASSERT( testMsg.getRecordRouteUri( 0, &tmpRecordRoute ) );
         Url tmpRecordRouteUrl( tmpRecordRoute );
         UtlString tmpRecordRouteHost;
         tmpRecordRouteUrl.getHostWithPort( tmpRecordRouteHost );
         ASSERT_STR_EQUAL( "47.135.162.140:5060", tmpRecordRouteHost.data() );         

         // recall the call tracker based on message and compare with previous
         CallTracker* pTracker2;
         pTracker2 = pNatTraversalAgent->getCallTrackerForMessage( testMsg );
         CPPUNIT_ASSERT( pTracker2 == pTracker );

         // check that the SDP got changed properly to relay media 
         const SdpBody* pSdpBody = testMsg.getSdpBody();
         CPPUNIT_ASSERT( pSdpBody );
         UtlString mediaType, mediaTransportType;
         int mediaPort, mediaPortPairs, numPayloadTypes, payloadTypes[10];
         SdpDirectionality dir;
         
         CPPUNIT_ASSERT( pSdpBody->getMediaData( 0, 
                                 &mediaType,
                                 &mediaPort,
                                 &mediaPortPairs,
                                 &mediaTransportType,
                                 10,
                                 &numPayloadTypes,
                                 payloadTypes,
                                 &dir ) == TRUE );
         CPPUNIT_ASSERT( mediaType == "audio" );
         CPPUNIT_ASSERT( mediaPort == 10000 );
         CPPUNIT_ASSERT( mediaPortPairs == 1 );
         CPPUNIT_ASSERT( mediaTransportType == "RTP/AVP" );
         CPPUNIT_ASSERT( numPayloadTypes == 5 );
         CPPUNIT_ASSERT( payloadTypes[0] == 18 );
         CPPUNIT_ASSERT( payloadTypes[1] == 4 );
         CPPUNIT_ASSERT( payloadTypes[2] == 0 );
         CPPUNIT_ASSERT( payloadTypes[3] == 8 );
         CPPUNIT_ASSERT( payloadTypes[4] == 101 );
         CPPUNIT_ASSERT( dir == sdpDirectionalitySendRecv );

         // check that we are using the public IP address of the media relay
         UtlString mediaAddress;
         CPPUNIT_ASSERT( pSdpBody->getMediaAddress(0, &mediaAddress ) );
         ASSERT_STR_EQUAL( pNatTraversalAgent->mNatTraversalRules.getMediaRelayPublicAddress(), mediaAddress );

         // Mow simulalate the reception of the response
         const char* response = 
         "SIP/2.0 200 OK\r\n"
         "From: \"L3\"<sip:[email protected]>;tag=94bb9480-c0a80065-13c4-50045-20c55bd3-50045\r\n"
         "To: <sip:[email protected]>;tag=94bf81c0-c0a8010b-13c4-4fc07-650a9211-4fc07\r\n"
         "Call-Id: 94bb55a0-c0a80065-13c4-50045-61a3ad3-50045@rjolyscs2.ca.nortel.com\r\n"
         "Cseq: 1 INVITE\r\n"
         "Via: SIP/2.0/UDP 192.168.0.101:5060;branch=z9hG4bK-50045-13890e4e-4f17a229;id=1234-1\r\n"
         "Supported: replaces\r\n"
         "Contact: <sip:[email protected]:5060>\r\n"
         "Record-Route: <sip:47.135.162.140:5060;lr;sipXecs-rs=%2Afrom%7EOTRiYjk0ODAtYzBhODAwNjUtMTNjNC01MDA0NS0yMGM1NWJkMy01MDA0NQ%60%60.400_authrules%2Aauth%7E.900_ntap%2ACeT%7ENDcuMTM1LjE2Mi4xNDU6Mjk1NDQ7dHJhbnNwb3J0PXVkcA%60%60.900_ntap%2Aid%7EMy0z%21641c6aa1807d3544000f310a64a5360a>\r\n"
         "Content-Type: application/sdp\r\n"
         "Content-Length: 250\r\n"
         "Date: Fri, 13 Jun 2008 14:48:46 GMT\r\n"
         "\r\n"
         "\r\n"
         "v=0\r\n"
         "o=LGEIPP 12617 12617 IN IP4 192.168.1.11\r\n"
         "s=SIP Call\r\n"
         "c=IN IP4 192.168.1.11\r\n"
         "t=0 0\r\n"
         "m=audio 25038 RTP/AVP 4 101\r\n"
         "c=IN IP4 192.168.0.2\r\n"
         "a=rtpmap:4 G723/8000\r\n"
         "a=rtpmap:101 telephone-event/8000\r\n"
         "a=fmtp:101 0-11\r\n"
         "a=sendrecv\r\n"
         "a=x-sipx-ntap:192.168.0.2;3\r\n";
         SipMessage okResp( response, strlen(response) );
         
         pNatTraversalAgent->handleOutputMessage( okResp, "192.168.0.101", 5060 );

         // check that the record route  has our private IP address
         CPPUNIT_ASSERT( okResp.getRecordRouteUri( 0, &tmpRecordRoute ) );
         Url tmpRecordRouteUrl2( tmpRecordRoute );
         tmpRecordRouteUrl2.getHostWithPort( tmpRecordRouteHost );
         ASSERT_STR_EQUAL( "192.168.0.2:5060", tmpRecordRouteHost.data() );         
            
         // check that the SDP got changed properly to relay media 
         pSdpBody = okResp.getSdpBody();
         CPPUNIT_ASSERT( pSdpBody );
         CPPUNIT_ASSERT( pSdpBody->getMediaData( 0, 
                                 &mediaType,
                                 &mediaPort,
                                 &mediaPortPairs,
                                 &mediaTransportType,
                                 10,
                                 &numPayloadTypes,
                                 payloadTypes,
                                 &dir ) == TRUE );
         CPPUNIT_ASSERT( mediaType == "audio" );
         CPPUNIT_ASSERT( mediaPort == 11000 );
         CPPUNIT_ASSERT( mediaPortPairs == 1 );
         CPPUNIT_ASSERT( mediaTransportType == "RTP/AVP" );
         CPPUNIT_ASSERT( numPayloadTypes == 2 );
         CPPUNIT_ASSERT( payloadTypes[0] == 4);
         CPPUNIT_ASSERT( payloadTypes[1] == 101 );
         CPPUNIT_ASSERT( dir == sdpDirectionalitySendRecv );

         // check that we are using the native IP address of the media relay
         CPPUNIT_ASSERT( pSdpBody->getMediaAddress(0, &mediaAddress ) );
         ASSERT_STR_EQUAL( pNatTraversalAgent->mNatTraversalRules.getMediaRelayNativeAddress(), mediaAddress );
      }
示例#12
0
/* //////////////////////////// PROTECTED ///////////////////////////////// */
void Connection::postTaoListenerMessage(int state, int newCause, int isLocal)
{
    int eventId = PtEvent::EVENT_INVALID;
    int termEventId = PtEvent::EVENT_INVALID;
    UtlString causeStr;
    causeStr.remove(0);

#ifdef TEST_PRINT
    Os::Logger::instance().log(FAC_CP, PRI_DEBUG, "Connection::postTaoListenerMessage: "
                  "Enter- %s state %d cause %d "
                  "eventid-  %d termeventid %d",
                  (isLocal?"LOCAL":"REMOTE"),
                  state, newCause,
                  eventId, termEventId);
#endif

    switch(state)
    {
    case CONNECTION_IDLE:
        eventId = PtEvent::CONNECTION_CREATED;
        termEventId = PtEvent::TERMINAL_CONNECTION_IDLE;
        break;

    case CONNECTION_INITIATED:
        eventId = PtEvent::CONNECTION_INITIATED;
        termEventId = PtEvent::TERMINAL_CONNECTION_CREATED;
        break;

    case CONNECTION_QUEUED:
        eventId = PtEvent::CONNECTION_QUEUED;
        termEventId = PtEvent::CONNECTION_CREATED;
        break;

    case CONNECTION_OFFERING:
        eventId = PtEvent::CONNECTION_OFFERED;
        break;

    case CONNECTION_DIALING:
        eventId = PtEvent::CONNECTION_DIALING ;
        break;

    case CONNECTION_ALERTING:
        eventId = PtEvent::CONNECTION_ALERTING;
        termEventId = PtEvent::TERMINAL_CONNECTION_RINGING;
        break;

    case CONNECTION_ESTABLISHED:
        eventId = PtEvent::CONNECTION_ESTABLISHED;
        termEventId = PtEvent::TERMINAL_CONNECTION_TALKING;
        break;

    case CONNECTION_FAILED:
        eventId = PtEvent::CONNECTION_FAILED;
        termEventId = PtEvent::TERMINAL_CONNECTION_DROPPED;
        break;

    case CONNECTION_DISCONNECTED:
        eventId = PtEvent::CONNECTION_DISCONNECTED;
        termEventId = PtEvent::TERMINAL_CONNECTION_DROPPED;
        break;

    case PtEvent::TERMINAL_CONNECTION_HELD:
        termEventId = PtEvent::TERMINAL_CONNECTION_HELD;
        break;

    default:
        eventId = PtEvent::CONNECTION_UNKNOWN;
        termEventId = PtEvent::TERMINAL_CONNECTION_UNKNOWN;
        break;

    }

    int cause;
    switch(newCause)
    {
     case CONNECTION_CAUSE_UNKNOWN:
        cause = PtEvent::CAUSE_UNKNOWN;
        causeStr.append("CAUSE_UNKNOWN");
        break;
    case CONNECTION_CAUSE_REDIRECTED:
        cause = PtEvent::CAUSE_REDIRECTED;
        causeStr.append("CAUSE_REDIRECTED");
        break ;

     case CONNECTION_CAUSE_NETWORK_CONGESTION:
        cause = PtEvent::CAUSE_NETWORK_CONGESTION;
        causeStr.append("CAUSE_NETWORK_CONGESTION");
        break;

     case CONNECTION_CAUSE_NETWORK_NOT_OBTAINABLE:
        cause = PtEvent::CAUSE_NETWORK_NOT_OBTAINABLE;
        causeStr.append("CAUSE_NETWORK_NOT_OBTAINABLE");
        break;

     case CONNECTION_CAUSE_DEST_NOT_OBTAINABLE:
        cause = PtEvent::CAUSE_DESTINATION_NOT_OBTAINABLE;
        causeStr.append("CAUSE_DESTINATION_NOT_OBTAINABLE");
        break;

     case CONNECTION_CAUSE_INCOMPATIBLE_DESTINATION:
        cause = PtEvent::CAUSE_INCOMPATIBLE_DESTINATION;
        causeStr.append("CAUSE_INCOMPATIBLE_DESTINATION");
        break;

     case CONNECTION_CAUSE_NOT_ALLOWED:
        cause = PtEvent::CAUSE_NOT_ALLOWED;
        causeStr.append("CAUSE_NOT_ALLOWED");
        break;

     case CONNECTION_CAUSE_NETWORK_NOT_ALLOWED:
        cause = PtEvent::CAUSE_NETWORK_NOT_ALLOWED;
        causeStr.append("CAUSE_NETWORK_NOT_ALLOWED");
        break;

    case CONNECTION_CAUSE_BUSY:
    case CONNECTION_CAUSE_SERVICE_UNAVAILABLE:
        cause = PtEvent::CAUSE_BUSY;
        causeStr.append("CAUSE_BUSY");
        break ;

    case CONNECTION_CAUSE_CANCELLED:
        cause = PtEvent::CAUSE_CALL_CANCELLED;
        causeStr.append("CAUSE_CALL_CANCELLED");
        break ;

    case CONNECTION_CAUSE_TRANSFER:
        cause = PtEvent::CAUSE_TRANSFER;
        causeStr.append("CAUSE_TRANSFER");
        break;

    default:
    case CONNECTION_CAUSE_NORMAL:
        cause = PtEvent::CAUSE_NORMAL;
        causeStr.append("CAUSE_NORMAL");
        break;
    }

    int cnt = 0;
    if (mpListenerCnt)
        cnt = mpListenerCnt->getRef();

    if (cnt > 0)
    {
        TaoObjHandle* pListeners;
        pListeners = new TaoObjHandle[cnt];
        mpListeners->getActiveObjects(pListeners, cnt);

        UtlString callId;

        // Use the connection call id first -- followed by call if
        // unavailable
        getCallId(&callId);                          // arg[0], callId
        if (callId.isNull())
        {
            mpCall->getCallId(callId);
#ifdef TEST_PRINT
            Os::Logger::instance().log(FAC_CP, PRI_DEBUG, "Connection::postTaoListenerMessage: "
                          "Connection call id not found, "
                          "Using CpCall Id = %s ",
                          callId.data());
#endif
        }

        callId += TAOMESSAGE_DELIMITER + mLocalAddress;        // arg[1], localAddress

        UtlString remoteAddress;
        getRemoteAddress(&remoteAddress, TRUE);

        if (remoteAddress.isNull())                            // arg[2], remote address
        {
            callId += TAOMESSAGE_DELIMITER + (UtlString)"UNKNOWN";    // not available yet
        }
        else
        {
            callId += TAOMESSAGE_DELIMITER + remoteAddress;
        }

        char buff[128];
        sprintf(buff, "%d", (int)mRemoteIsCallee);
        callId += TAOMESSAGE_DELIMITER + UtlString(buff);    // arg[3], remoteIsCallee

        sprintf(buff, "%d", cause);
        callId += TAOMESSAGE_DELIMITER + UtlString(buff);    // arg[4], cause

        if (mRemoteIsCallee)
        {
            remoteAddress.insert(0, "foreign-terminal-");
            callId += TAOMESSAGE_DELIMITER + remoteAddress;    // arg[5], remote terminal name
        }
        else
        {
            mpCall->getLocalTerminalId(buff, 127);
            callId += TAOMESSAGE_DELIMITER + UtlString(buff);    // arg[5], local terminal name
        }

        if (isLocal)                                        // TAO_OFFER_PARAM_LOCAL_CONNECTION
        {
            callId += TAOMESSAGE_DELIMITER + "1";            // arg[6], isLocal
        }
        else
        {
            callId += TAOMESSAGE_DELIMITER + "0";            // isLocal
        }

        sprintf(buff, "%d", mResponseCode);
        callId += TAOMESSAGE_DELIMITER + UtlString(buff);    // arg[7], SIP response code

        callId += TAOMESSAGE_DELIMITER + mResponseText;        // arg[8], SIP response text

        int argCnt = 9;
        if(mpCall)
        {
            int metaEventId = 0;
            int metaEventType = PtEvent::META_EVENT_NONE;
            int numCalls = 0;
            const UtlString* metaEventCallIds = NULL;
            mpCall->getMetaEvent(metaEventId, metaEventType, numCalls,
                &metaEventCallIds);
            if (metaEventId != PtEvent::META_EVENT_NONE)
            {
                sprintf(buff, "%d", metaEventId);
                callId += TAOMESSAGE_DELIMITER + UtlString(buff);    // arg[9], meta event id
                sprintf(buff, "%d", metaEventType);
                callId += TAOMESSAGE_DELIMITER + UtlString(buff);    // arg[10], meta code
                argCnt += 2;
                for (int i = 0; i < numCalls; i++)
                {
                    if (metaEventCallIds && metaEventCallIds[i])
                    {
                        callId += TAOMESSAGE_DELIMITER + metaEventCallIds[i];    // meta call ids
                        argCnt++;
                    }
                }
            }
        }

        TaoMessage msg(TaoMessage::EVENT,
                       0,
                       0,
                       eventId,
                       0,
                       argCnt,
                       callId);

        UtlString eventIdStr;
        if (eventId != PtEvent::EVENT_INVALID)
        {
            for (int i = 0; i < cnt; i++) // post connection events
            {
                ((OsServerTask*) pListeners[i])->postMessage((OsMsg&)msg);
            }
            mpCall->getStateString(eventId, &eventIdStr);
            mpCallManager->logCallState(callId.data(), eventIdStr.data(), causeStr);
        }

        if (termEventId != PtEvent::EVENT_INVALID)    // post terminal connection events
        {
            msg.setObjHandle(termEventId);
            for (int i = 0; i < cnt; i++)
            {
                ((OsServerTask*) pListeners[i])->postMessage((OsMsg&)msg);
            }

            mpCall->getStateString(termEventId, &eventIdStr);
            mpCallManager->logCallState(callId.data(), eventIdStr.data(), causeStr);

        }

        delete[] pListeners;
        callId.remove(0);
        eventIdStr.remove(0);
        remoteAddress.remove(0);
    }
#ifdef TEST_PRINT
    Os::Logger::instance().log(FAC_CP, PRI_DEBUG, "Connection::postTaoListenerMessage: "
                  "Leave- %s state %d cause %d "
                  "eventid-  %d termeventid %d",
                  (isLocal?"LOCAL":"REMOTE"),
                  state, newCause,
                  eventId, termEventId);
#endif

    causeStr.remove(0);
}
示例#13
0
// Constructor
Connection::Connection(CpCallManager* callMgr,
                       CpCall* call,
                       CpMediaInterface* mediaInterface,
                       //UiContext* callUiContext,
                       int offeringDelayMilliSeconds,
                       int availableBehavior,
                       const char* forwardUnconditionalUrl,
                       int busyBehavior, const char* forwardOnBusyUrl,
                       int forwardOnNoAnswerSeconds)
   : mConnectionId(-1)
   , callIdMutex(OsMutex::Q_FIFO)
   , mDeleteAfter(OsTime::OS_INFINITY)
{
#ifdef TEST_PRINT
    UtlString callId;

    if (call) {
       call->getCallId(callId);
       Os::Logger::instance().log(FAC_CP, PRI_DEBUG,
                     "Connection::Connection- %s\n",
                     callId.data());
    } else
       Os::Logger::instance().log(FAC_CP, PRI_DEBUG,
                     "Connection::Connection- call is Null\n");
#endif

    mOfferingDelay = offeringDelayMilliSeconds;
    mLineAvailableBehavior = availableBehavior;
    if(mLineAvailableBehavior == FORWARD_UNCONDITIONAL &&
        forwardUnconditionalUrl != NULL)
    {
        mForwardUnconditional.append(forwardUnconditionalUrl);
    }
    mLineBusyBehavior = busyBehavior;
    if(mLineBusyBehavior == FORWARD_ON_BUSY &&
        forwardOnBusyUrl != NULL)
    {
        mForwardOnBusy.append(forwardOnBusyUrl);
    }
    mForwardOnNoAnswerSeconds = forwardOnNoAnswerSeconds;

    mRemoteIsCallee = FALSE;
    mRemoteRequestedHold = FALSE;
    remoteRtpPort = PORT_NONE;
    sendCodec = -1;
    receiveCodec = -1;
    mLocalConnectionState = CONNECTION_IDLE;
    mRemoteConnectionState = CONNECTION_IDLE;
    mConnectionStateCause = CONNECTION_CAUSE_NORMAL;
    mTerminalConnState = PtTerminalConnection::IDLE;
    mFarEndHoldState = TERMCONNECTION_NONE;
    mResponseCode = 0;
    mResponseText.remove(0);

    mpCallManager = callMgr;
    mpCall = call;
    mpMediaInterface = mediaInterface;
    mConnectionId = -10;
    //mpCallUiContext = callUiContext;

    mpListenerCnt = new TaoReference();
    mpListeners = new TaoObjectMap();

    m_eLastMajor = (SIPX_CALLSTATE_EVENT) -1 ;
    m_eLastMinor = (SIPX_CALLSTATE_CAUSE) -1 ;
    m_eLastAudioMajor = (SIPX_CALLSTATE_EVENT) -1 ;
    m_eLastAudioMinor = (SIPX_CALLSTATE_CAUSE) -1 ;

    CallId::getNewCallId(*this) ;

#ifdef TEST_PRINT
    if (!callId.isNull())
       Os::Logger::instance().log(FAC_CP, PRI_DEBUG,
                     "Connection::Connection -leaving: %s\n",
                     callId.data());
    else
       Os::Logger::instance().log(FAC_CP, PRI_DEBUG,
                     "Connection::Connection -leaving: call is Null\n");
#endif
}
示例#14
0
void Connection::setState(int newState, int isLocal, int newCause, int termState)
{
   UtlString oldStateString;
   UtlString newStateString;
   int currentState = isLocal ? mLocalConnectionState : mRemoteConnectionState;
   getStateString(currentState, &oldStateString);
   getStateString(newState, &newStateString);

   int metaEventId = 0;
   int metaEventType = PtEvent::META_EVENT_NONE;
   int numCalls = 0;
   const UtlString* metaEventCallIds = NULL;
   if (mpCall)
   {
      mpCall->getMetaEvent(metaEventId, metaEventType, numCalls,
                           &metaEventCallIds);
   }

   UtlString callId;
   if (mpCall) {
      mpCall->getCallId(callId);
   }
   if (callId.isNull())
      callId="null";

   UtlString strCallName;
   if (mpCall) {
      strCallName = mpCall->getName();
   }
   if (strCallName.isNull())
   {
      strCallName="null";
   }

   if (!isStateTransitionAllowed(newState, currentState))
   {
      // Under some conditions, "invalid" state changes are allowed.
      if (!(!isLocal && metaEventId > 0
            && (metaEventType == PtEvent::META_CALL_TRANSFERRING
                || metaEventType == PtEvent::META_CALL_REPLACING)))
      {
         if (newState == currentState)
         {
            Os::Logger::instance().log(FAC_CP, PRI_DEBUG,
                          "Connection::setState: "
                          "Questionable connection state change - isLocal %d, for call "
                          "'%s' with callid '%s' from %s to %s, cause %d",
                          isLocal, strCallName.data(), callId.data(),
                          oldStateString.data(), newStateString.data(), newCause);
         }
         else
         {
            Os::Logger::instance().log(FAC_CP, PRI_ERR,
                          "Connection::setState: "
                          "Invalid connection state change - isLocal %d, for call "
                          "'%s' with callid '%s' from %s to %s, cause %d",
                          isLocal, strCallName.data(), callId.data(),
                          oldStateString.data(), newStateString.data(), newCause);
         }
         return;
      }
   }

   UtlBoolean bPostStateChange = FALSE;

   if (newState != currentState ||
       newCause != CONNECTION_CAUSE_NORMAL ||
       (newState == currentState &&
           newState == CONNECTION_ALERTING &&
           (0 == isLocal)))
   {
      if (isLocal && newState == CONNECTION_DISCONNECTED)
      {
         if ((   mpCall->canDisconnectConnection(this)
              || newCause == CONNECTION_CAUSE_CANCELLED)
             && metaEventType != PtEvent::META_CALL_TRANSFERRING
             && metaEventType != PtEvent::META_CALL_REPLACING)
         {
            bPostStateChange = TRUE;
         }
      }
      else
      {
         bPostStateChange = TRUE;
      }
   }

   Os::Logger::instance().log(FAC_CP, PRI_DEBUG,
                 "Connection::setState "
                 "Call %s %s state isLocal %d\n"
                 "change\n"
                 "from %s to\n"
                 "\t %s\n"
                 "cause=%d\n"
                 "post change to upper layer %d",
            strCallName.data(),
            callId.data(),
            isLocal,
            oldStateString.data(),
            newStateString.data(),
            newCause,
            bPostStateChange);

   if (bPostStateChange)
   {
      mConnectionStateCause = newCause;
      mTerminalConnState = termState == -1 ? terminalConnectionState(newState) : termState;

      if (isLocal)
      {
         mLocalConnectionState = newState;
      }
      else
      {
         mRemoteConnectionState = newState;
      }

      postTaoListenerMessage(newState, newCause, isLocal);
   }
}
示例#15
0
// Returns an escaped version of the specified source string
UtlString OsSysLog::escape(const UtlString& source)
{
   UtlString    results ;        
   const char* pStart = source.data() ;
   const char* pTraverse = pStart ;
   const char* pLast = pStart ;

   while (*pTraverse)
   {
      switch (*pTraverse)
      {
         case '\\':
            // Copy old data
            if (pLast < pTraverse)
            {
               results.append(pLast, pTraverse-pLast);               
            }
            pLast = pTraverse + 1 ;

            // Add escaped Text
            results.append("\\\\") ;
            break ;
         case '\r':
            // Copy old data
            if (pLast < pTraverse)
            {
               results.append(pLast, pTraverse-pLast);               
            }
            pLast = pTraverse + 1 ;

            // Add escaped Text
            results.append("\\r") ;
            break ;
         case '\n':
            // Copy old data
            if (pLast < pTraverse)
            {
               results.append(pLast, pTraverse-pLast);               
            }
            pLast = pTraverse + 1 ;

            // Add escaped Text
            results.append("\\n") ;
            break ;
         case '\"':
            // Copy old data
            if (pLast < pTraverse)
            {
               results.append(pLast, pTraverse-pLast);
            }
            pLast = pTraverse + 1 ;

            // Add escaped Text
            results.append("\\\"") ;
            break ;            
         default:
            break ;
      }
      pTraverse++ ;
   }

   // if nothing to escape, short-circuit
   if (pLast == pStart)
   {
      return source ;
   } 
   else if (pLast < pTraverse)
   {
      results.append(pLast, pTraverse-pLast);
   }
  
   return results ;
}
示例#16
0
// Construct mappings from an input string.
UtlBoolean
SipRedirectorMPT::addMappings(const char* value,
                              int length,
                              UtlString*& user,
                              const char*& error_msg,
                              int& location)
{
   // Process the input string one character at a time.
   // Buffer into which to edit the input string.
   char buffer[FORM_SIZE];
   // Pointer for filling the edit buffer.
   char* p = buffer;
   char c;
   int count = length;
   while (count-- > 0)
   {
      c = *value++;
      switch (c)
      {
      case '\n':
         // Trim trailing whitespace on the line.
         while (p > buffer && p[-1] != '\n' && isspace(p[-1]))
         {
            p--;
         }
         // Fall through to insert if not at the beginning of a line.
      case ' ':
      case '\t':
         // If at the beginning of a line, ignore it.
         if (p > buffer && p[-1] != '\n' && p[-1] != '{')
         {
            *p++ = c;
         }
         break;
      case '}':
      {
         // Process component redirection.
         // Trim trailing whitespace.
         while (p > buffer && isspace(p[-1]))
         {
            p--;
         }
         // Find the matching '{'.
         *p = '\0';             // End scope of strrchr.
         char* open = strrchr(buffer, '{');
         if (open == NULL)
         {
            error_msg = "Unmatched '}'";
            location = length - count;
            return FALSE;
         }
         if (open+1 == p)
         {
            error_msg = "No contacts given";
            location = length - count;
            return FALSE;
         }
         // Insert the addresses into the map and get the assigned user name.
         UtlString* user = MPTredirector->addMapping(open+1, p - (open+1));
         // Truncate off the sub-redirection.
         p = open;
         // Append the resulting user name.
         strcpy(p, user->data());
         p += strlen(user->data());
      }
         break;
      case '{':
         // '{' is copied into the buffer like other characters.
      default:
         // Ordinary characters are just copied.
         *p++ = c;
         break;
      }
   }
   // Trim trailing whitespace.
   while (p > buffer && isspace(p[-1]))
   {
      p--;
   }
   // Check that there are no unclosed '{'.
   *p = '\0';                   // To limit strchr's search.
   if (strchr(buffer, '{') != NULL)
   {
      error_msg = "Unmatched '{'";
      // Report at end of string because we have no better choice.
      location = length;
      return FALSE;
   }
   // Check that the contacts are not empty.
   if (p == buffer)
   {
      error_msg = "No contacts given";
      location = 0;
      return FALSE;
   }
   // Insert the addresses into the map and return the assigned user name.
   user = MPTredirector->addMapping(buffer, p - buffer);
   return TRUE;
}
示例#17
0
// Unescapes previously escaped Quotes and CrLfs 
UtlString OsSysLog::unescape(const UtlString& source)
{
   UtlString    results ;        
   const char* pStart = source.data() ;
   const char* pTraverse = pStart ;
   const char* pLast = pStart ;
   UtlBoolean   bLastWasEscapeChar = false;

   while (*pTraverse)
   {
      if (bLastWasEscapeChar)
      {
         switch (*pTraverse)
         {
            case '\\':
            case '"':
               if (pLast < pTraverse)
               {
                  results.append(pLast, pTraverse-pLast-1);               
               }
               pLast = pTraverse + 1 ;
               results.append(*pTraverse) ;
               break ;
            case 'r':
               if (pLast < pTraverse)
               {
                  results.append(pLast, pTraverse-pLast-1);               
               }
               pLast = pTraverse + 1 ;
               results.append("\r") ;
               break ;
            case 'n':
               if (pLast < pTraverse)
               {
                  results.append(pLast, pTraverse-pLast-1);               
               }
               pLast = pTraverse + 1 ;
               results.append("\n") ;
               break;
            default:
               // Invalid/Illegal Escape Character
               break ;
         }
         bLastWasEscapeChar = false ;
      }
      else
      {
         if (*pTraverse == '\\')
         {
            bLastWasEscapeChar = true ;
         }
      }

      pTraverse++ ;
   }

   // if nothing to escape, short-circuit
   if (pLast == pStart)
   {
      return source ;
   } 
   else if (pLast < pTraverse)
   {
      results.append(pLast, (pTraverse-1)-pLast);
   }  
  
   return results ;
}
示例#18
0
void SipSubscribeServer::handleNotifyResponse(const SipMessage& notifyResponse)
{
    int responseCode = notifyResponse.getResponseStatusCode();

    // If it is a non-Timeout error response and has no Retry-After header,
    // terminate the subscription.
    if (responseCode >= SIP_3XX_CLASS_CODE)
    {
       UtlString dialogHandle;
       notifyResponse.getDialogHandleReverse(dialogHandle);

       if (   SIP_REQUEST_TIMEOUT_CODE == responseCode
           || SIP_LOOP_DETECTED_CODE == responseCode
           || SIP_SERVER_INTERNAL_ERROR_CODE == responseCode)
       {
          // Log the response.
          OsSysLog::add(FAC_SIP, PRI_WARNING,
                        "SipSubscribeServer::handleNotifyResponse "
                        "Not terminating subscription due to %d response. Handle: %s",
                        responseCode, dialogHandle.data());

          // RFC 3265 section 3.2.2 says that when a "NOTIFY request
          // fails ... due to a timeout condition ... the notifier
          // SHOULD remove the subscription."  However, we feel this
          // is a problem with the spec.  Endpoints that become
          // temporarily unavailable and do not respond to the NOTIFY
          // (or do not respond in time) should not cause the
          // subscription to be silently terminated.  Our deviation
          // from the spec will cause subscriptions to now-defunct
          // subscribers to continue, but only until the subscription
          // expires.  This is far preferable to the alternative.

          // Similarly, RFC 3265 prescribes that when the notifier
          // receives a 482 response, it should remove the
          // subscription.  But that seems to be counterproductive in
          // practice, as a 482 response shows that the subscriber did
          // receive the NOTIFY.  Unfortunately, under congested
          // circumstances, a notifier can receive a 482 response
          // rather than the more informative 2xx response.

          // Similar problems arise with the 500 response, which usually
          // indicates that a request was retried with a second transport.
          // But note that SipTransaction translates 503 into 500,
          // so 503 is also exempt.
       }
       else if (notifyResponse.getHeaderValue(0, SIP_RETRY_AFTER_FIELD) == NULL)
       {
          OsSysLog::add(FAC_SIP, PRI_WARNING,
                        "SipSubscribeServer::handleNotifyResponse "
                        "Terminating subscription due to %d response. Handle: %s",
                        responseCode, dialogHandle.data());

          // End this subscription because we got an error response from
          // the NOTIFY request.
          generateTerminatingNotify(dialogHandle);
       }
       else
       {
          // This was an error response, but because there was a Retry-After
          // header, we should not terminate the subscription.
          OsSysLog::add(FAC_SIP, PRI_WARNING,
                        "SipSubscribeServer::handleNotifyResponse "
                        "Not terminating subscription due to Retry-After header. Handle: %s",
                        dialogHandle.data());
       }
    }
}
示例#19
0
   void testHandleAlarm()
   {
      OsSysLog::add(FAC_ALARM, PRI_DEBUG, "AlarmServerTest::testHandleAlarm");

      UtlString localhost("localhost");
      UtlString alarmId("NO_LOG");
      UtlString alarmParam("testing");
      UtlSList alarmParams;
      alarmParams.append(&alarmParam);
      UtlString oldLastString;
      tail(mAlarmFile, oldLastString);
      OsSysLog::add(FAC_ALARM, PRI_DEBUG, "oldLastString %s", oldLastString.data());
      bool rc=cAlarmServer::getInstance()->handleAlarm(localhost, alarmId, alarmParams);
      OsTask::delay(500);
      CPPUNIT_ASSERT_MESSAGE("handleAlarm('NO_LOG') failed", rc==true);
      UtlString newLastString;
      tail(mAlarmFile, newLastString);
      OsSysLog::add(FAC_ALARM, PRI_DEBUG, "newLastString %s", newLastString.data());
      CPPUNIT_ASSERT_MESSAGE("alarm with 'NO_LOG' was logged", !oldLastString.compareTo(newLastString));

      alarmId = "TEST_LOG";
      alarmParam = "single parameter";
      alarmParams.removeAll();
      alarmParams.append(&alarmParam);
      OsSysLog::add(FAC_ALARM, PRI_DEBUG, "Test TEST_LOG");
      cAlarmServer::getInstance()->handleAlarm(localhost, alarmId, alarmParams);
      OsTask::delay(DELAY);
      UtlString actualString;
      UtlString expectedString = "This is a test of the log function. Single parameter should be here: single parameter, and that's all that is required";
      tail(mAlarmFile, actualString);
      char msg[1000];
      sprintf(msg, "incorrect message was logged: actualString '%s'  expected '%s'", actualString.data(), expectedString.data());
      CPPUNIT_ASSERT_MESSAGE(msg, actualString.contains(expectedString));

      // test that non-existant alarm returns false
      alarmId = "NONEXISTANT_ID";
      rc=cAlarmServer::getInstance()->handleAlarm(localhost, alarmId, alarmParams);
      CPPUNIT_ASSERT_MESSAGE("handleAlarm('NONEXISTANT_ID') did not fail, and should have", rc!=true);

      // test that alarm with min_threshold is only logged after n attempts
      alarmId = "MIN_THRESHOLD";
      alarmParam = "one";
      alarmParams.removeAll();
      alarmParams.append(&alarmParam);
      tail(mAlarmFile, oldLastString);
      OsSysLog::add(FAC_ALARM, PRI_DEBUG, "oldLastString %s", oldLastString.data());
      cAlarmServer::getInstance()->handleAlarm(localhost, alarmId, alarmParams);
      OsTask::delay(DELAY);
      tail(mAlarmFile, newLastString);
      OsSysLog::add(FAC_ALARM, PRI_DEBUG, "newLastString %s", newLastString.data());
      CPPUNIT_ASSERT_MESSAGE("first instance of alarm with 'min_threshold' was logged", !oldLastString.compareTo(newLastString));
      alarmParam = "two";
      alarmParams.append(&alarmParam);
      cAlarmServer::getInstance()->handleAlarm(localhost, alarmId, alarmParams);
      OsTask::delay(DELAY);
      tail(mAlarmFile, actualString);
      expectedString = "This should only be logged the second time";
      sprintf(msg, "incorrect message was logged: actualString '%s'  expected '%s'", actualString.data(), expectedString.data());
      CPPUNIT_ASSERT_MESSAGE(msg, actualString.contains(expectedString));

   }
示例#20
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();
}
示例#21
0
   void testReconfigure()
      {
         PluginHooks testPlugins("getTestPlugin", "RECONFIG_TEST");

         const UtlString ValueKey("VALUE");

         UtlString name;
         TestPlugin* thePlugin;
         UtlString pluginValue;
         UtlString fullName;


         {
            // Do the initial configuration of two instances of a hook
            OsConfigDb configuration;

            configuration.set("RECONFIG_TEST_HOOK_LIBRARY.First",
                              PLUGIN_LIB_DIR "libtestpluginA" PLUGIN_EXT);
            configuration.set("RECONFIG_TEST.First.VALUE", "FirstValue");

            configuration.set("RECONFIG_TEST_HOOK_LIBRARY.Second",
                              PLUGIN_LIB_DIR "libtestpluginA" PLUGIN_EXT);
            configuration.set("RECONFIG_TEST.Second.VALUE", "SecondValue");

            // load them up
            testPlugins.readConfig(configuration);

            PluginIterator plugin(testPlugins);

            // check the first instance
            thePlugin = static_cast<TestPlugin*>(plugin.next(&name));
            CPPUNIT_ASSERT(thePlugin != NULL);
            CPPUNIT_ASSERT(!name.isNull());
            ASSERT_STR_EQUAL("First",name.data());
            thePlugin->pluginName(fullName);
            ASSERT_STR_EQUAL("TestPluginA::First",fullName.data());
            CPPUNIT_ASSERT(thePlugin->getConfiguredValueFor(ValueKey, pluginValue));
            ASSERT_STR_EQUAL("FirstValue",pluginValue.data());

            // check the second instance
            thePlugin = static_cast<TestPlugin*>(plugin.next(&name));
            CPPUNIT_ASSERT(thePlugin != NULL);
            CPPUNIT_ASSERT(!name.isNull());
            ASSERT_STR_EQUAL("Second",name.data());
            thePlugin->pluginName(fullName);
            ASSERT_STR_EQUAL("TestPluginA::Second",fullName.data());
            CPPUNIT_ASSERT(thePlugin->getConfiguredValueFor(ValueKey, pluginValue));
            ASSERT_STR_EQUAL("SecondValue",pluginValue.data());

            // and confirm that is the end
            CPPUNIT_ASSERT(plugin.next(&name) == NULL);
            CPPUNIT_ASSERT(name.isNull());
         }

         {
            // Now create a new configuration that eliminates the First instance
            // and changes the configuration value for the Second instance
            OsConfigDb configuration;
            configuration.set("RECONFIG_TEST_HOOK_LIBRARY.Second",
                              PLUGIN_LIB_DIR "libtestpluginA" PLUGIN_EXT);
            configuration.set("RECONFIG_TEST.Second.VALUE", "NewValue");

            // reconfigure the plugins
            testPlugins.readConfig(configuration);

            PluginIterator plugin(testPlugins);

            // confirm that we still get the Second instance (but we get it first :-)
            thePlugin = static_cast<TestPlugin*>(plugin.next(&name));
            CPPUNIT_ASSERT(thePlugin != NULL);
            CPPUNIT_ASSERT(!name.isNull());
            ASSERT_STR_EQUAL("Second",name.data());
            thePlugin->pluginName(fullName);
            ASSERT_STR_EQUAL("TestPluginA::Second",fullName.data());

            // and check that it has the new configuration value
            CPPUNIT_ASSERT(thePlugin->getConfiguredValueFor(ValueKey, pluginValue));
            ASSERT_STR_EQUAL("NewValue",pluginValue.data());

            // and that it's the only hook configured now
            CPPUNIT_ASSERT(plugin.next(&name) == NULL);
            CPPUNIT_ASSERT(name.isNull());
         }

         {
            // Now create a third configuration that changes the library for the Second instance
            OsConfigDb configuration;
            configuration.set("RECONFIG_TEST_HOOK_LIBRARY.Second",
                              PLUGIN_LIB_DIR "libtestpluginB" PLUGIN_EXT);
            configuration.set("RECONFIG_TEST.Second.VALUE", "ChangedValue");

            // reconfigure the plugins
            testPlugins.readConfig(configuration);

            PluginIterator plugin(testPlugins);

            // confirm that we still get the Second instance (but we get it first :-)
            thePlugin = static_cast<TestPlugin*>(plugin.next(&name));
            CPPUNIT_ASSERT(thePlugin != NULL);
            CPPUNIT_ASSERT(!name.isNull());
            ASSERT_STR_EQUAL("Second",name.data());
            thePlugin->pluginName(fullName);
            ASSERT_STR_EQUAL("TestPluginB::Second",fullName.data());

            // and check that it has the new configuration value
            CPPUNIT_ASSERT(thePlugin->getConfiguredValueFor(ValueKey, pluginValue));
            ASSERT_STR_EQUAL("ChangedValue",pluginValue.data());

            // and that it's the only hook configured now
            CPPUNIT_ASSERT(plugin.next(&name) == NULL);
            CPPUNIT_ASSERT(name.isNull());
         }
      }
示例#22
0
// Send a NOTIFY to all subscribers to the given resourceId and eventTypeKey.
UtlBoolean SipSubscribeServer::notifySubscribers(const char* resourceId,
                                                 const char* eventTypeKey,
                                                 const char* eventType,
                                                 const char* reason)
{
   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "SipSubscribeServer::notifySubscribers resourceId '%s', eventTypeKey '%s', eventType '%s', reason '%s'",
                 resourceId, eventTypeKey, eventType,
                 reason ? reason : "[null]");
    UtlBoolean notifiedSubscribers = FALSE;
    UtlString eventName(eventType);

    lockForRead();
    SubscribeServerEventData* eventData =
       dynamic_cast <SubscribeServerEventData*>
           (mEventDefinitions.find(&eventName));

    // Get the event-specific info to find subscriptions interested in
    // this content.
    if (eventData)
    {
        int numSubscriptions = 0;
        SipMessage** notifyArray = NULL;
        UtlString** acceptHeaderValuesArray = NULL;

        // 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;
           }

           // Construct a NOTIFY (without body) for each subscription, containing
           // the dialog-related information about each subscription.
           eventData->mpEventSpecificSubscriptionMgr->
              createNotifiesDialogInfo(resourceId,
                                       eventTypeKey,
                                       format,
                                       numSubscriptions,
                                       acceptHeaderValuesArray,
                                       notifyArray);

           OsSysLog::add(FAC_SIP, PRI_DEBUG,
                         "SipSubscribeServer::notifySubscribers numSubscriptions for '%s' = %d",
                         resourceId, numSubscriptions);

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

        // 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(resourceId,
                                      eventTypeKey,
                                      eventType,
                                      *(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);

                  // Update the saved record of the NOTIFY CSeq and the
                  // XML version number for the specified savedEventTypeKey,
                  // as needed by the subscription manager.
                  // In practice, this is only used by SipPersistentSubscriptionMgr
                  // to write the NOTIFY Cseq and XML version into the IMDB.
                  eventData->mpEventSpecificSubscriptionMgr->
                     updateVersion(*notify, version, savedEventTypeKey);

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

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

               if (change != SipSubscriptionMgr::subscriptionContinues)
               {
                  // 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.
        eventData->mpEventSpecificSubscriptionMgr->
           freeNotifies(numSubscriptions,
                        acceptHeaderValuesArray,
                        notifyArray);
    }
    // event type not enabled
    else
    {
        OsSysLog::add(FAC_SIP, PRI_ERR,
                      "SipSubscribeServer::notifySubscribers "
                      "event type: %s not enabled - "
                      "Why are we seeing a callback for this?",
            eventName.data());
    }

    unlockForRead();

    return notifiedSubscribers;
}
示例#23
0
bool cAlarmServer::loadAlarmStringsFile(const UtlString& stringsFile)
{
   OsSysLog::add(FAC_ALARM, PRI_DEBUG, " load alarm strings file %s", stringsFile.data());

   TiXmlDocument doc(stringsFile);
   TiXmlHandle docHandle( &doc );
   if (!doc.LoadFile())
   {
      UtlString errorMsg;
      XmlErrorMsg( doc, errorMsg );
      OsSysLog::add(FAC_ALARM, PRI_ERR, "failed to load alarm strings file: %s", errorMsg.data());
      return false;
   }

   TiXmlHandle docH( &doc );
   TiXmlHandle alarmServerHandle = docH.FirstChildElement("alarm_server");

   TiXmlElement* settingsElement = alarmServerHandle.FirstChildElement("settings").Element();
   if (settingsElement)
   {
      //load alarm action strings
      TiXmlElement* alarmActionsElement = settingsElement->FirstChildElement("actions");
      if (alarmActionsElement)
      {
         TiXmlElement* element = alarmActionsElement->FirstChildElement("log");
         if (mpNotifiers[cAlarmData::eActionLog])
         {
            mpNotifiers[cAlarmData::eActionLog]->initStrings(element);
         }

         element = alarmActionsElement->FirstChildElement("email");
         if (mpNotifiers[cAlarmData::eActionEmail])
         {
            mpNotifiers[cAlarmData::eActionEmail]->initStrings(element);
         }

         element = alarmActionsElement->FirstChildElement("sms");
         if (mpNotifiers[cAlarmData::eActionSms])
         {
            mpNotifiers[cAlarmData::eActionSms]->initStrings(element);
         }
         /* Not implemented as Strings are not needed for TrapNotifier.
         element = alarmActionsElement->FirstChildElement("trap");
         if (mpNotifiers[cAlarmData::eActionTrap])
         {
            mpNotifiers[cAlarmData::eActionTrap]->initStrings(element);
         }
         */
      }
   }
   else
   {
      OsSysLog::add(FAC_ALARM, PRI_DEBUG,
                    "no <settings> element in alarm config file '%s'",
                    stringsFile.data());
   }

   //load alarm description strings
   TiXmlElement*  alarmDefElement = alarmServerHandle.
                     FirstChildElement("definitions").Element();
   if (alarmDefElement)
   {
      TiXmlElement* element = alarmDefElement->FirstChildElement();
      UtlString idStr;
      UtlString descStr;
      UtlString resStr;

      for (; element; element=element->NextSiblingElement() )
      {
         idStr = element->Attribute("id");
         if (idStr.isNull())
         {
            OsSysLog::add(FAC_ALARM, PRI_ERR,"Parsing alarm strings file %s: alarm ID is required", stringsFile.data());
            continue;
         }

         cAlarmData* alarmData = lookupAlarm(idStr);
         if (!alarmData)
         {
            OsSysLog::add(FAC_ALARM, PRI_ERR,"unknown alarm ID %s", idStr.data());
            continue;
         }

         TiXmlElement* codeElement = element->FirstChildElement("shorttitle");
         if (codeElement)
         {
            textContentShallow(descStr, codeElement);
            if (!descStr.isNull())
            {
               UtlString tempStr;
               XmlUnEscape(tempStr, descStr);
               alarmData->setShortTitle(tempStr);
            }
         }

         codeElement = element->FirstChildElement("description");
         if (codeElement)
         {
            textContentShallow(descStr, codeElement);
            if (!descStr.isNull())
            {
               UtlString tempStr;
               XmlUnEscape(tempStr, descStr);
               alarmData->setDescription(tempStr);
            }
         }

         codeElement = element->FirstChildElement("resolution");
         if (codeElement)
         {
            textContentShallow(resStr, codeElement);
            if (!resStr.isNull())
            {
               UtlString tempStr;
               XmlUnEscape(tempStr, resStr);
               alarmData->setResolution(tempStr);
            }
         }

      }
   }

   return true;
}
示例#24
0
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 =
       dynamic_cast <SubscribeServerEventData*> (mEventDefinitions.find(&eventName));

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

        SipMessage subscribeResponse;

        // Check if authenticated (or if it needs to be authenticated)
        if (handler->isAuthenticated(subscribeRequest,
                                     subscribeResponse))
        {
            // Check if authorized (or if authorization is required)
            if (handler->isAuthorized(subscribeRequest,
                                     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;
                UtlString resourceId, eventTypeKey, eventType;
                eventPackageInfo->mpEventSpecificSubscriptionMgr->
                   updateDialogInfo(
                      subscribeRequest,
                      resourceId,
                      eventTypeKey,
                      eventType,
                      subscribeDialogHandle,
                      isNewDialog,
                      isExpiredSubscription,
                      subscribeResponse,
                      // The event-specific handler provides a getKeys method
                      // which is used to determine the resource ID
                      // and event type if this is a new subscription.
                      *handler);

                 // Build a NOTIFY
                 SipMessage notifyRequest;

                 // Set the dialog information into the NOTIFY.
                 // Note that the dialog can have ended by now, because of
                 // a race condition with the processing of dialog-ending
                 // messages from the outside world.
                 if (eventPackageInfo->mpEventSpecificSubscriptionMgr->
                     getNotifyDialogInfo(subscribeDialogHandle,
                                         notifyRequest,
                                         "active;expires=%ld"))
                 {
                    // We still have record of the dialog, so the
                    // NOTIFY headers were set.

                    // Set the NOTIFY content
                    UtlString acceptHeaderValue;
                    if (!subscribeRequest.getAcceptField(acceptHeaderValue))
                    {
                       // No Accept header seen, set special value allowing any
                       // content type.
                       acceptHeaderValue = SipPublishContentMgr::acceptAllTypes;
                    }
                    // Note that since this NOTIFY is due to a SUBSCRIBE,
                    // it should contain 'full' content.  Hence,
                    // the fullState parameter of getNotifyContent is TRUE,
                    // and is not taken from
                    // eventPackageInfo->mEventSpecificFullState.
                    UtlString availableMediaTypes;
                    if (handler->getNotifyContent(resourceId,
                                                  eventTypeKey,
                                                  eventType,
                                                  *(eventPackageInfo->mpEventSpecificContentMgr),
                                                  acceptHeaderValue,
                                                  notifyRequest,
                                                  TRUE,
                                                  &availableMediaTypes))
                    {
                       // Update the NOTIFY content if required for this event type.
                       // Sets 'version' and 'eventTypeKey'.
                       int version;
                       eventPackageInfo->mpEventSpecificSubscriptionMgr->
                          updateNotifyVersion(eventPackageInfo->mpEventSpecificContentVersionCallback,
                                              notifyRequest,
                                              version,
                                              eventTypeKey);

                       // Update the saved record of the NOTIFY CSeq and the
                       // XML version number for the specified eventTypeKey,
                       // as needed by the subscription manager.
                       // In practice, this is only used by SipPersistentSubscriptionMgr
                       // to write the NOTIFY Cseq and XML version into the IMDB.
                       eventPackageInfo->mpEventSpecificSubscriptionMgr->
                          updateVersion(notifyRequest, version, eventTypeKey);

                       // Send the NOTIFY request
                       setContact(&notifyRequest);
                       eventPackageInfo->mpEventSpecificUserAgent->send(notifyRequest);

                       if (OsSysLog::willLog(FAC_SIP, PRI_INFO))
                       {
                          UtlString requestContact;
                          subscribeRequest.getContactField(0, requestContact);
                          OsSysLog::add(FAC_SIP, PRI_INFO,
                              "SipSubscribeServer::handleSubscribe: %s has setup subscription to %s, eventTypeKey %s",
                              requestContact.data(), resourceId.data(), eventTypeKey.data());
                       }
                    }
                    else
                    {
                       // No content was available, so the subscription fails.

                       // Determine the reason and set the response code.
                       if (availableMediaTypes.isNull())
                       {
                          // No MIME types are available, so the resource does not exist.
                          subscribeResponse.setResponseFirstHeaderLine(SIP_PROTOCOL_VERSION,
                                                                       SIP_NOT_FOUND_CODE,
                                                                       SIP_NOT_FOUND_TEXT);
                       }
                       else
                       {
                          // MIME types are available, so the resource exists.
                          subscribeResponse.setResponseFirstHeaderLine(SIP_PROTOCOL_VERSION,
                                                                       SIP_BAD_MEDIA_CODE,
                                                                       SIP_BAD_MEDIA_TEXT);
                          subscribeResponse.setAcceptField(availableMediaTypes);
                       }

                       // Destroy the subscription.
                       eventPackageInfo->mpEventSpecificSubscriptionMgr->
                          endSubscription(subscribeDialogHandle,
                                          SipSubscriptionMgr::subscriptionTerminated);

                       // Do not send the NOTIFY.
                    }
                 }
                 else
                 {
                    // Oops, the subscription was destroyed while we looked.
                    OsSysLog::add(FAC_SIP, PRI_WARNING,
                                  "SipSubscribeServer::handleSubscribe "
                                  "subscription '%s' vanished while being processed",
                                  subscribeDialogHandle.data());
                 }

                 // Send the response ASAP to minimize resending.
                 setContact(&subscribeResponse);
                 eventPackageInfo->mpEventSpecificUserAgent->send(subscribeResponse);
            }
            // Not authorized
            else
            {
                // Send the response that was prepared by ::isAuthorized().
                setContact(&subscribeResponse);
                eventPackageInfo->mpEventSpecificUserAgent->send(subscribeResponse);
            }
        }

        // Not authenticated
        else
        {
            // Send the response that was prepared by ::isAuthenticated().
            setContact(&subscribeResponse);
            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);

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

    return(handledSubscribe);
}
示例#25
0
bool cAlarmServer::loadAlarms()
{
   // load global alarm config from alarm-config.xml
   UtlString strAlarmFilename = SipXecsService::Path(SipXecsService::ConfigurationDirType,
         "alarm-config.xml");
   UtlString strGroupFilename = SipXecsService::Path(SipXecsService::ConfigurationDirType,
         "alarm-groups.xml");
   loadAlarmConfig(strAlarmFilename, strGroupFilename);

   // load specific alarm definitions from ${confdir}/alarms/*.xml
   UtlString alarmDefDir = SipXecsService::Path(SipXecsService::ConfigurationDirType);
   alarmDefDir.append("/alarms/");
   OsSysLog::add(FAC_ALARM, PRI_INFO, "Looking for alarm def files in '%s'", alarmDefDir.data());
   OsFileIterator files(alarmDefDir);
   OsPath entry;

   // for each file in the ${confdir}/alarms, load alarm definitions
   OsStatus status;
   int numFound;
   for (status=files.findFirst(entry, ".*\\.xml$", OsFileIterator::FILES), numFound=0;
        status == OS_SUCCESS;
        status = files.findNext(entry) )
   {
      loadAlarmDefinitions(alarmDefDir + entry);
   }

   // load alarm strings and local language version from ${datadir}/alarms/*.xml
   UtlString alarmStringsDir = SipXecsService::Path(SipXecsService::DataDirType);
   alarmStringsDir.append("/alarms/");
   OsSysLog::add(FAC_ALARM, PRI_INFO, "Looking for alarm string files in '%s'",
                 alarmStringsDir.data());
   OsFileIterator stringFiles(alarmStringsDir);

   // for each "base" file (*-strings.xml) in the ${datadir}/alarms, load alarm strings
   for (status=stringFiles.findFirst(entry, ".*-strings\\.xml$", OsFileIterator::FILES), numFound=0;
        status == OS_SUCCESS;
        status = stringFiles.findNext(entry) )
   {
      loadAlarmStrings(alarmStringsDir + entry);
   }


#ifdef DEBUG
   UtlHashMapIterator alarmIter(mAlarmMap);
   UtlString* alarmKey;
   int count=0;
   while ((alarmKey = dynamic_cast<UtlString*>(alarmIter())))
   {
      cAlarmData* alarm = dynamic_cast<cAlarmData*>(alarmIter.value());
      OsSysLog::add(FAC_ALARM, PRI_DEBUG,
            "alarm[%d]: %s %s: %s, Log:%d, Email:%d",
            count, alarmKey->data(), alarm->getCode().data(),
            OsSysLog::priorityName(alarm->getSeverity()),
            alarm->actions[cAlarmData::eActionLog], alarm->actions[cAlarmData::eActionEmail]);
      OsSysLog::add(FAC_ALARM, PRI_DEBUG,
            "           Title:%s", alarm->getShortTitle().data());
      OsSysLog::add(FAC_ALARM, PRI_DEBUG,
            "           Description:%s", alarm->getDescription().data());
      OsSysLog::add(FAC_ALARM, PRI_DEBUG,
            "           Resolution:%s", alarm->getResolution().data());
      count++;
   }
#endif

   return true;
}
示例#26
0
int SipLSendCommand::execute(int argc, char* argv[])
{
        int commandStatus = CommandProcessor::COMMAND_FAILED;
        UtlString messageBuffer;
        char buffer[1025];
        int bufferSize = 1024;
        int charsRead;

        printf("send command with %d arguments\n", argc);
        if(argc != 5)
        {
                UtlString usage;
                getUsage(argv[0], &usage);
                printf("%s", usage.data());
        }

        else
        {
        UtlString protocol(argv[2]);
        protocol.toUpper();

        UtlString hostAddress(argv[3]);
        int hostPort = atoi(argv[4]);

        FILE* sipMessageFile = fopen(argv[1], "r");
                if(sipMessageFile && hostPort > 0 && !hostAddress.isNull() &&
            (protocol.compareTo("TCP") == 0 || protocol.compareTo("UDP") == 0))
                {
                        //printf("opened file: \"%s\"\n", argv[1]);
                        do
                        {
                                charsRead = fread(buffer, 1, bufferSize, sipMessageFile);
                                if(charsRead > 0)
                                {
                                        messageBuffer.append(buffer, charsRead);
                                }
                        }
                        while(charsRead);
            fclose(sipMessageFile);

            OsSocket* writeSocket = NULL;
            if(protocol.compareTo("TCP") == 0)
                writeSocket = new OsConnectionSocket(hostPort ,hostAddress);
            else if(protocol.compareTo("UDP") == 0)
                writeSocket = new OsDatagramSocket(hostPort ,hostAddress);

                        //printf("Read file contents:\n%s\n====END====\n", messageBuffer.data());
                        //SipMessage message(messageBuffer.data());

            int bytesSent;
                        if((bytesSent = writeSocket->write(messageBuffer.data(),
                                                                                        messageBuffer.length())) > 0)
                        {
                                commandStatus = CommandProcessor::COMMAND_SUCCESS;
                        }
                        else
                        {
                                printf("Failed to send SIP message");
                        }
            printf("Send message with %d bytes\n", bytesSent);
                }
                else if(!sipMessageFile)
                {
                        printf("send file: \"%s\" does not exist\n", argv[1]);
                        commandStatus = CommandProcessor::COMMAND_FAILED;
                }
        else if(hostPort <= 0)
        {
                        printf("Invalid destination port: %s\n", argv[4]);
                        commandStatus = CommandProcessor::COMMAND_FAILED;
                }
        else if(hostAddress.isNull())
        {
                        printf("Invalid destination address: %s\n", argv[3]);
                        commandStatus = CommandProcessor::COMMAND_FAILED;
                }
        else if(protocol.compareTo("TCP")  && protocol.compareTo("UDP"))
        {
                        printf("Invalid protocol: %s\n", argv[2]);
                        commandStatus = CommandProcessor::COMMAND_FAILED;
                }

        }

        return(commandStatus);
}
示例#27
0
bool SipDialogMonitor::addExtension(UtlString& groupName, Url& contactUrl)
{
   bool result = false;
   mLock.acquire();

   // Check whether the group already exists. If not, create one.
   SipResourceList* list =
      dynamic_cast <SipResourceList *> (mMonitoredLists.findValue(&groupName));
   if (list == NULL)
   {
      UtlString* listName = new UtlString(groupName);
      list = new SipResourceList((UtlBoolean)TRUE, listName->data(),
                                 DIALOG_EVENT_TYPE);

      mMonitoredLists.insertKeyAndValue(listName, list);
      OsSysLog::add(FAC_SIP, PRI_DEBUG,
                    "SipDialogMonitor::addExtension insert listName %s and object %p to the resource list",
                    groupName.data(), list);
   }

   // Check whether the contact has already been added to the group.
   UtlString resourceId;
   contactUrl.getIdentity(resourceId);
   Resource* resource = list->getResource(resourceId);
   if (resource == NULL)
   {
      // If not, add it.
      resource = new Resource(resourceId);

      UtlString userName;
      contactUrl.getDisplayName(userName);
      resource->setName(userName);

      UtlString id;
      NetMd5Codec::encode(resourceId, id);
      resource->setInstance(id, STATE_PENDING);
      list->insertResource(resource);

      // Set up the subscription to the URI.
      OsSysLog::add(FAC_LOG, PRI_DEBUG,
                    "SipDialogMonitor::addExtension Sending out the SUBSCRIBE to contact %s",
                    resourceId.data());

      UtlString toUrl;
      contactUrl.toString(toUrl);

      UtlString fromUri = "dialogMonitor@" + mDomainName;
      UtlString earlyDialogHandle;

      UtlBoolean status = mpSipSubscribeClient->addSubscription(resourceId.data(),
                                                                DIALOG_EVENT_TYPE,
                                                                DIALOG_EVENT_CONTENT_TYPE,
                                                                fromUri.data(),
                                                                toUrl.data(),
                                                                mContact.data(),
                                                                mRefreshTimeout,
                                                                (void *) this,
                                                                SipDialogMonitor::subscriptionStateCallback,
                                                                SipDialogMonitor::notifyEventCallback,
                                                                earlyDialogHandle);

      if (!status)
      {
         result = false;
         OsSysLog::add(FAC_LOG, PRI_ERR,
                       "SipDialogMonitor::addExtension Subscription failed to contact %s.",
                       resourceId.data());
      }
      else
      {
         mDialogHandleList.insertKeyAndValue(new UtlString(resourceId),
                                             new UtlString(earlyDialogHandle));
         createDialogState(&earlyDialogHandle);
         OsSysLog::add(FAC_SIP, PRI_DEBUG,
                       "SipDialogMonitor::addExtension Added earlyDialogHandle: %s",
                       earlyDialogHandle.data());
         result = true;
      }
   }
   else
   {
      OsSysLog::add(FAC_LOG, PRI_WARNING,
                    "SipDialogMonitor::addExtension contact %s already exists.",
                    resourceId.data());
   }

   list->buildBody();

   mLock.release();
   return result;
}
示例#28
0
// Add a log entry given a variable argument list
OsStatus OsSysLog::vadd(const char*            taskName,
                        const OsTaskId_t       taskId,                        
                        const OsSysLogFacility facility,
                        const OsSysLogPriority priority,
                        const char*            format,
                        va_list                ap)
{
   // If the log has not been initialized, print everything to the console
   if (!isTaskPtrNull())
   {
      if (willLog(facility, priority))
      {
         UtlString logData;
         UtlString logEntry;
         myvsprintf(logData, format, ap) ;
         logData = escape(logData) ;

#ifdef ANDROID
         __android_log_print(androidPri(priority), "sipXsyslog", "[%s] %s",
                             OsSysLog::sFacilityNames[facility], logData.data());
#endif

         OsTime timeNow;
         OsDateTime::getCurTime(timeNow); 
         OsDateTime logTime(timeNow);
         
         UtlString   strTime ;
         logTime.getIsoTimeStringZus(strTime) ;
         UtlString   taskHex;
         // TODO: Should get abstracted into a OsTaskBase method
#ifdef __pingtel_on_posix__
         OsTaskLinux::getIdString_X(taskHex, taskId);
#endif

         mysprintf(logEntry, "\"%s\":%d:%s:%s:%s:%s:%s:%s:\"%s\"",
               strTime.data(),
               ++sEventCount,
               OsSysLog::sFacilityNames[facility], 
               OsSysLog::sPriorityNames[priority],
               sHostname.data(),
               (taskName == NULL) ? "" : taskName,
               taskHex.data(),
               sProcessId.data(),
               logData.data()) ;         

         // If the logger for some reason trys to log a message
         // there is a recursive problem.  Drop the message on the
         // floor for now.  This can occur if one of the os utilities
         // logs a message.
         if(strcmp("syslog", taskName) == 0)
         {
             // Just discard the log entry
             //
             // (rschaaf):
             // NOTE: Don't try to use osPrintf() to emit the log entry since this
             // can cause consternation for applications (e.g. CGIs) that expect to
             // use stdout for further processing.
         }
         else
         {
             char* szPtr = strdup(logEntry.data()) ;
             OsSysLogMsg msg(OsSysLogMsg::LOG, szPtr) ;
             OsTime timeout(1000) ;
             OsSysLogTask *pOsSysLogTask = spOsSysLogTask;
             if ( pOsSysLogTask != NULL &&
                  pOsSysLogTask->postMessage(msg, timeout) != OS_SUCCESS)
             {
                 printf("OsSysLog jammed: %s\n", szPtr) ;
                 free(szPtr) ;
                 OsTask::yield() ;
              }
          }
       }
   }

   return OS_SUCCESS ;
}
示例#29
0
StateChangeNotifier::Status
SipDialogMonitor::mergeEventInformation(SipDialogEvent* dialogEvent,
                                        const char* earlyDialogHandle,
                                        const char* dialogHandle)
{
   // Status to be returned to caller.
   StateChangeNotifier::Status rc;

   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "SipDialogMonitor::mergeEventInformation "
                 "earlyDialogHandle = '%s', dialogHandle = '%s'",
                 earlyDialogHandle, dialogHandle);

   // Get the list of active dialogs for the group of subscriptions generated
   // by this SUBSCRIBE.
   UtlString earlyDialogHandleString(earlyDialogHandle);
   UtlHashBag* active_dialog_list =
      dynamic_cast <UtlHashBag*> (mDialogState.findValue(&earlyDialogHandleString));
   // Ignore the event if there is no entry in mDialogState -- this is a
   // NOTIFY that arrived after and un-SUBSCRIBE terminated its subscription.
   if (active_dialog_list)
   {
      // If this is a full update, remove from the active list any dialog
      // for this dialog handle.
      UtlString notify_state;
      dialogEvent->getState(notify_state);
      if (notify_state.compareTo("full") == 0)
      {
         OsSysLog::add(FAC_SIP, PRI_DEBUG,
                       "SipDialogMonitor::mergeEventInformation "
                       "active_dialog_list elements for handle '%s'",
                       dialogHandle);
         // Iterate through the active dialog list, removing elements
         // for this dialog handle.
         UtlHashBagIterator dialog_id_itor(*active_dialog_list);
         UtlString* dialog_id;
         while ((dialog_id = dynamic_cast <UtlString*> (dialog_id_itor())))
         {
            // Extract the dialog handle part of the dialog identifier string
            // and compare it to the dialog handle of this event notice.
            if (strcmp(dialogHandle,
                       dialog_id->data() + dialog_id->index("\001") + 1) == 0)
            {
               // This is a dialog for this subscription, so remove it.
               active_dialog_list->remove(dialog_id);
            }
         }
      }

      // Iterate through the dialog event, updating active_dialog_list for
      // each dialog mentioned.
      UtlSListIterator* dialog_itor = dialogEvent->getDialogIterator();
      Dialog* dialog;
      UtlString state, event, code, dialogId;
      while ((dialog = dynamic_cast <Dialog*> ((*dialog_itor)())))
      {
         // Construct the dialog identifier string,
         // <dialog id><ctrl-A><dialog handle>
         dialog->getDialogId(dialogId);
         dialogId.append("\001");
         dialogId.append(dialogHandle);

         dialog->getState(state, event, code);
         OsSysLog::add(FAC_SIP, PRI_DEBUG,
                       "SipDialogMonitor::mergeEventInformation "
                       "dialogId '%s' state '%s' event '%s' code '%s'",
                       dialogId.data(), state.data(), event.data(), code.data());
         if (state.compareTo("terminated") != 0)
         {
            // Active dialog.
            // If it is not in active_dialog_list, add it.
            if (!active_dialog_list->contains(&dialogId))
            {
               OsSysLog::add(FAC_SIP, PRI_DEBUG,
                             "SipDialogMonitor::mergeEventInformation "
                             "adding dialog '%s'",
                             dialogId.data());
               active_dialog_list->insert(new UtlString(dialogId));
            }
         }
         else
         {
            // Terminated dialog
            // If it is in active_dialog_list, remove it.
            OsSysLog::add(FAC_SIP, PRI_DEBUG,
                          "SipDialogMonitor::mergeEventInformation "
                          "removing dialog '%s'",
                          dialogId.data());
            active_dialog_list->destroy(&dialogId);
         }
      }
      delete dialog_itor;

      // If debugging, list the active dialog list.
      if (OsSysLog::willLog(FAC_SIP, PRI_DEBUG))
      {
         UtlHashBagIterator dialog_list_itor(*active_dialog_list);
         UtlString* dialog;
         while ((dialog = dynamic_cast <UtlString*> (dialog_list_itor())))
         {
            OsSysLog::add(FAC_SIP, PRI_DEBUG,
                          "SipDialogMonitor::mergeEventInformation "
                          "active dialog '%s'",
                          dialog->data());
         }
         OsSysLog::add(FAC_SIP, PRI_DEBUG,
                       "SipDialogMonitor::mergeEventInformation "
                       "End of list");
      }

      // Set the return code based on whether there are any active dialogs.
      rc = active_dialog_list->isEmpty() ?
         StateChangeNotifier::ON_HOOK :
         StateChangeNotifier::OFF_HOOK;
   }
   else
   {
      // This is a late NOTIFY and there are (should be) no notifiers for it,
      // so the return code is arbitrary.
      OsSysLog::add(FAC_SIP, PRI_DEBUG,
                    "SipDialogMonitor::mergeEventInformation "
                    "No active dialog list found");
      rc = StateChangeNotifier::ON_HOOK;
   }
   return rc;
}
示例#30
0
UtlBoolean SipTransactionList::waitUntilAvailable(SipTransaction* transaction,
                                                 const UtlString& hash)
{
    UtlBoolean exists;
    UtlBoolean busy = FALSE;
    int numTries = 0;

    do
    {
        numTries++;

        lock();
        exists = transactionExists(transaction, hash);

        if(exists)
        {
            busy =  transaction->isBusy();
            if(!busy)
            {
                transaction->markBusy();
                unlock();
//#ifdef TEST_PRINT
                OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipTransactionList::waitUntilAvailable %p locked after %d tries\n",
                    transaction, numTries);
//#endif
            }
            else
            {
                // We set an event to be signaled when a
                // transaction is released.
                OsEvent* waitEvent = new OsEvent;
                transaction->notifyWhenAvailable(waitEvent);

                // Must unlock while we wait or there is a dead lock
                unlock();

//#ifdef TEST_PRINT
                OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipTransactionList::waitUntilAvailable %p waiting on: %p after %d tries\n",
                    transaction, waitEvent, numTries);
//#endif

                OsStatus waitStatus;
                OsTime transBusyTimeout(1, 0);
                int waitTime = 0;
                do
                {
                    if(waitTime > 0)
                        OsSysLog::add(FAC_SIP, PRI_WARNING, "SipTransactionList::waitUntilAvailable %p still waiting: %d",
                            transaction, waitTime);

                    waitStatus = waitEvent->wait(transBusyTimeout);
                    waitTime+=1;
                }
                while(waitStatus != OS_SUCCESS && waitTime < 30);

                // If we were never signaled, then we signal the
                // event so the other side knows that it has to
                // free up the event
                if(waitEvent->signal(-1) == OS_ALREADY_SIGNALED)
                {
                    delete waitEvent;
                    waitEvent = NULL;
                }

                // If we bailed out before the event was signaled
                // pretend the transaction does not exist.
                if(waitStatus != OS_SUCCESS)
                {
                    exists = FALSE;
                }

                if(waitTime > 1)
                {
                    if (OsSysLog::willLog(FAC_SIP, PRI_WARNING))
                    {
                        UtlString transTree;
                        UtlString waitingTaskName;
                        OsTask* waitingTask = OsTask::getCurrentTask();
                        if(waitingTask) waitingTaskName = waitingTask->getName();
                        transaction->dumpTransactionTree(transTree, FALSE);
                        OsSysLog::add(FAC_SIP, PRI_WARNING, "SipTransactionList::waitUntilAvailable status: %d wait time: %d transaction: %p task: %s transaction tree: %s",
                            waitStatus, waitTime, transaction, waitingTaskName.data(), transTree.data());
                    }
                }

//#ifdef TEST_PRINT
                OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipTransactionList::waitUntilAvailable %p done waiting after %d tries\n",
                    transaction, numTries);
//#endif
            }
        }
        else
        {
            unlock();
//#ifdef TEST_PRINT
            OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipTransactionList::waitUntilAvailable %p gone after %d tries\n",
                    transaction, numTries);
//#endif
        }
    }
    while(exists && busy);

    return(exists && !busy);
}