// Caller must hold mLock. void SipPresenceMonitor::notifyStateChange(UtlString& contact, SipPresenceEvent* presenceEvent) { // Loop through the notifier list UtlHashMapIterator iterator(mStateChangeNotifiers); UtlString* listUri; StateChangeNotifier* notifier; Url contactUrl(contact); while ((listUri = dynamic_cast <UtlString *> (iterator()))) { notifier = dynamic_cast <StateChangeNotifier *> (mStateChangeNotifiers.findValue(listUri)); UtlString id; makeId(id, contact); Tuple* tuple = presenceEvent->getTuple(id); if (tuple) { UtlString status; tuple->getStatus(status); notifier->setStatus(contactUrl, status.compareTo(STATUS_CLOSED) == 0 ? StateChangeNotifier::AWAY : StateChangeNotifier::PRESENT); } else { notifier->setStatus(contactUrl, StateChangeNotifier::AWAY); } } }
// Report to all the notifiers in mStateChangeNotifiers a new event // 'dialogEvent' for AOR 'contact'. void SipDialogMonitor::notifyStateChange(UtlString& contact, StateChangeNotifier::Status status) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::notifyStateChange " "AOR = '%s', status = %s", contact.data(), (status == StateChangeNotifier::ON_HOOK ? "ON_HOOK" : status == StateChangeNotifier::OFF_HOOK ? "OFF_HOOK" : "UNKNOWN")); Url contactUrl(contact); // Loop through the notifier list, reporting the status to the notifiers. UtlHashMapIterator iterator(mStateChangeNotifiers); UtlString* listUri; UtlVoidPtr* container; StateChangeNotifier* notifier; while ((listUri = dynamic_cast <UtlString *> (iterator()))) { container = dynamic_cast <UtlVoidPtr *> (mStateChangeNotifiers.findValue(listUri)); notifier = (StateChangeNotifier *) container->getValue(); // Report the status to the notifier. notifier->setStatus(contactUrl, status); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::notifyStateChange setting state to %d", status); } }
void SipDialogMonitor::notifyStateChange(UtlString& contact, SipDialogEvent* dialogEvent) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::notifyStateChange contact = %s", contact.data()); // Loop through the notifier list UtlHashMapIterator iterator(mStateChangeNotifiers); UtlString* listUri; UtlVoidPtr* container; StateChangeNotifier* notifier; Url contactUrl(contact); mLock.acquire(); while (listUri = dynamic_cast <UtlString *> (iterator())) { container = dynamic_cast <UtlVoidPtr *> (mStateChangeNotifiers.findValue(listUri)); notifier = (StateChangeNotifier *) container->getValue(); if (dialogEvent->isEmpty()) { notifier->setStatus(contactUrl, StateChangeNotifier::ON_HOOK); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::notifyStateChange dialog is empty, setting state to on hook"); } else { Dialog* dialog = dialogEvent->getFirstDialog(); UtlString state, event, code; dialog->getState(state, event, code); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::notifyStateChange dialog state = %s", state.data()); if (state.compareTo(STATE_CONFIRMED) == 0) { notifier->setStatus(contactUrl, StateChangeNotifier::OFF_HOOK); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::notifyStateChange setting state to off hook"); } else { if (state.compareTo(STATE_TERMINATED) == 0) { notifier->setStatus(contactUrl, StateChangeNotifier::ON_HOOK); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::notifyStateChange setting state to on hook"); } else { notifier->setStatus(contactUrl, StateChangeNotifier::RINGING); OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipDialogMonitor::notifyStateChange setting state to ringing"); } } } } mLock.release(); }
void AvatarQueryJob::start() { d->baseDir = KUrl( KStandardDirs::locateLocal("appdata", QLatin1String("avatars") ) ); if( d->category & Kopete::AvatarManager::User ) { d->listAvatarDirectory( UserDir ); } if( d->category & Kopete::AvatarManager::Contact ) { KUrl contactUrl(d->baseDir); contactUrl.addPath( ContactDir ); const QDir contactDir(contactUrl.toLocalFile()); const QStringList subdirsList = contactDir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot ); foreach(const QString &subdir, subdirsList) { d->listAvatarDirectory( ContactDir + QDir::separator() + subdir ); }
void SipPresenceMonitor::notifyStateChange(UtlString& contact, SipPresenceEvent* presenceEvent) { // Loop through the notifier list UtlHashMapIterator iterator(mStateChangeNotifiers); UtlString* listUri; StateChangeNotifier* notifier; Url contactUrl(contact); mLock.acquire(); while (listUri = dynamic_cast <UtlString *> (iterator())) { notifier = dynamic_cast <StateChangeNotifier *> (mStateChangeNotifiers.findValue(listUri)); if (presenceEvent->isEmpty()) { notifier->setStatus(contactUrl, StateChangeNotifier::AWAY); } else { UtlString id; NetMd5Codec::encode(contact, id); Tuple* tuple = presenceEvent->getTuple(id); UtlString status; tuple->getStatus(status); if (status.compareTo(STATUS_CLOSE) == 0) { notifier->setStatus(contactUrl, StateChangeNotifier::AWAY); } else { notifier->setStatus(contactUrl, StateChangeNotifier::PRESENT); } } } mLock.release(); }
SubscribeServerThread::SubscribeStatus SubscribeServerThread::addSubscription( const int timeNow, const SipMessage* subscribeMessage, const char* domain, const UtlString& eventType, const UtlString& eventId, const UtlHashMap& eventParams, UtlString& newToTag, int& grantedExpiration) { SubscribeStatus returnStatus = STATUS_INTERNAL_ERROR; int subscribeCseqInt = 0; UtlString callId; UtlString contactEntry; UtlString to; UtlString from; UtlString route; UtlString key; UtlString method; Url identity; // Construct the identity UtlString uriUser, requestUri; subscribeMessage->getUri( NULL, NULL, NULL, &uriUser ); subscribeMessage->getRequestUri( &requestUri ); identity.setUserId( uriUser ); identity.setUrlType( "sip" ); identity.setHostAddress( domain ); subscribeMessage->getToField(&to); subscribeMessage->getFromField(&from); subscribeMessage->getCallIdField(&callId); subscribeMessage->getCSeqField(&subscribeCseqInt, &method); subscribeMessage->getContactEntry(0, &contactEntry); subscribeMessage->buildRouteField(&route); Url toUrl; subscribeMessage->getToUrl(toUrl); int commonExpires = -1; if ( subscribeMessage->getExpiresField( &commonExpires ) ) { if( commonExpires > 0 ) // came from request { if (commonExpires < mMinExpiresTimeint) { returnStatus = STATUS_LESS_THAN_MINEXPIRES; OsSysLog::add( FAC_SIP, PRI_ERR, "addSubscription: " "Expires (%d) less than Minimum (%d)", commonExpires, mMinExpiresTimeint); return returnStatus; } else if (commonExpires > mDefaultSubscribePeriod) { commonExpires = mDefaultSubscribePeriod; } else { // commonExpires is in the allowed range - use the requested value } } else if( commonExpires == 0 ) { // remove subscription binding // remove all bindings because one contact value is * OsSysLog::add(FAC_SIP, PRI_DEBUG,"SubscribeServerThread::addSubscription -" " subscription for url %s and event %s to be removed after sending NOTIFY", toUrl.toString().data(), eventType.data()); returnStatus = STATUS_TO_BE_REMOVED; return returnStatus; } else if( commonExpires == -1) // no expires value in request { // Assume the default value commonExpires = mDefaultSubscribePeriod; OsSysLog::add(FAC_SIP, PRI_DEBUG,"SubscribeServerThread::addSubscription -" " No Expires Value, assigning default value (%d)", commonExpires); } } UtlString sipxImpliedParameter(SIPX_IMPLIED_SUB); UtlString* sipxImpliedDuration = NULL; int grantedExpirationTime; if (( sipxImpliedDuration = dynamic_cast<UtlString*>(eventParams.findValue(&sipxImpliedParameter)))) { /* * This request was generated by the registrar as an implied subscription; * its duration must therefore match that of the registration, which has * already been randomized. */ grantedExpirationTime = atoi(sipxImpliedDuration->data()); } else { /* * The request is for a new or refreshed subscription (other cases were handled above); * commonExpires is now the requested duration in the range: * mMinExpiresTimeint <= commonExpires <= mDefaultSubscribePeriod * In order to distribute expirations smoothly, we actually grant a randomized duration */ int spreadFloor = mMinExpiresTimeint*2; if ( commonExpires > spreadFloor ) { // a normal (long) registration // - spread it between twice the min and the longest they asked for grantedExpirationTime = ( (rand() % (commonExpires - spreadFloor)) + spreadFloor); } else if ( commonExpires > mMinExpiresTimeint ) { // a short but not minimum registration // - spread it between the min and the longest they asked for grantedExpirationTime = ( (rand() % (commonExpires - mMinExpiresTimeint) ) + mMinExpiresTimeint ); } else // longestExpiration == mMinExpiresTimeint { // minimum - can't randomize because we can't shorten or lengthen it grantedExpirationTime = mMinExpiresTimeint; } } // Handle the to-tag: // If no to-tag, this is a new subscription, for which we must create // a to-tag. // If there is a to-tag, this is a renewal of a subscription, and we // must first check that the subscription exists. (This is because if // the UA thinks there is a subscription, but we do not know of it, we // cannot reconstitute the subscription, as we do not know the NOTIFY CSeq // that the UA expects. See XECS-406 for the ill consequences of // this problem.) // Clear the returned new to-tag. newToTag.remove(0); { UtlString x; bool r = toUrl.getFieldParameter("tag", x); OsSysLog::add(FAC_SIP, PRI_DEBUG,"SubscribeServerThread::addSubscription getting to-tag, return %d, value '%s'", (int) r, x.data()); } UtlString toTag; if (toUrl.getFieldParameter("tag", toTag)) { // Check to see if this subscription exists. // Critical Section here OsLock mutex(mLock); bool exists = SubscriptionDB::getInstance()->subscriptionExists( SUBSCRIPTION_COMPONENT_STATUS, to, from, callId, OsDateTime::getSecsSinceEpoch()); OsSysLog::add(FAC_SIP, PRI_DEBUG,"SubscribeServerThread::addSubscription subscriptionExists(..., '%s', '%s', '%s', %d) = %d", to.data(), from.data(), callId.data(), (int) OsDateTime::getSecsSinceEpoch(), exists); if (!exists) { returnStatus = STATUS_BAD_SUBSCRIPTION; return returnStatus; } } else { // Generate a random to-tag. CallId::getNewTag(newToTag); // Add it to the remembered To header value. to.append(";tag="); to.append(newToTag); OsSysLog::add(FAC_SIP, PRI_DEBUG,"SubscribeServerThread::addSubscription generated to-tag '%s'", newToTag.data()); } OsSysLog::add(FAC_SIP, PRI_DEBUG, "SubscribeServerThread::addSubscription -" " Adding/updating subscription for URI '%s' event %s duration %d to '%s'", toUrl.toString().data(), eventType.data(), grantedExpirationTime, contactEntry.data()); // trim the contact to just the uri Url contactUrl(contactEntry); contactUrl.getUri(contactEntry); // add bindings identity.getIdentity( key ); // Insert or update the information for this subscription. // (Note that the "notify CSeq" parameter is ignored if there is // an existing SubscriptionDB row for this subscription.) if (insertRow(requestUri, // identity, callId, contactEntry, grantedExpirationTime + timeNow, subscribeCseqInt, eventType, eventId, to, from, key, // this will be searched for later route, 1)) // initial notify cseq (sent to phone) { grantedExpiration = grantedExpirationTime; returnStatus = STATUS_SUCCESS; } else { // log the error and send error indication to subscriber OsSysLog::add(FAC_SIP, PRI_ERR, "SubscribeServerThread::addSubscription -" " Could not insert record in Database"); returnStatus = STATUS_INTERNAL_ERROR; } return returnStatus; }
void testBranchIdUniqueness() { # define CASES 10 // The test succeeds if at least 9 of the 16 digits differ between all // pairs of Call-Ids we generate. If the generated Call-Ids are random, this // test will fail 0.00023% of the time for any one pair, or about 0.011% // of the time for one of the 45 pairs. # define MIN_DIFFS 9 UtlString stableTestSecret("stable"); BranchId::setSecret(stableTestSecret); const char* testMsg = "INVITE sip:[email protected] SIP/2.0" "To: sip:[email protected]\r\n" "From: Caller <sip:[email protected]>; tag=30543f3483e1cb11ecb40866edd3295b\r\n" "Call-Id: f88dfabce84b6a2787ef024a7dbe8749\r\n" "Cseq: 1 INVITE\r\n" "Max-Forwards: 20\r\n" "Contact: [email protected]\r\n" "Content-Length: 0\r\n" "\r\n"; SipMessage sipMsg(testMsg); UtlString output[CASES]; // Generate some BranchIds. Os::Logger::instance().log(FAC_SIP,PRI_DEBUG,"BranchIdTest::testBranchIdUniqueness unique cases"); for (int i = 0; i < CASES; i++) { BranchId branchId(sipMsg); output[i].append(branchId.data()); Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "case %d initial: %s\n", i, output[i].data()); } // Compare that they're different enough. for (int i = 0; i < CASES; i++) { for (int j = i+1; j < CASES; j++) { UtlString* s1 = &output[i]; UtlString* s2 = &output[j]; int differences = 0; for (size_t k = 0; k < s1->length() && k < s1->length(); k++) { if ((*s1)(k) != (*s2)(k)) { differences++; } } if (differences < MIN_DIFFS) { char msg[200]; sprintf(msg, "BranchId '%s' and '%s' have %d different characters, " "which is less than the minimum, %d", s1->data(), s2->data(), differences, MIN_DIFFS); CPPUNIT_ASSERT_MESSAGE(msg, FALSE); } } } // Now regenerate those as child ids without forks Os::Logger::instance().log(FAC_SIP,PRI_DEBUG,"BranchIdTest::testBranchIdUniqueness child cases"); for (int i = 0; i < CASES; i++) { BranchId parentBranchId(output[i]); // no addFork calls before creating the child BranchId branchId(parentBranchId, sipMsg); output[i].remove(0); output[i].append(branchId.data()); Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "case %d child : %s\n", i, output[i].data()); } // Compare that they're different enough. for (int i = 0; i < CASES; i++) { for (int j = i+1; j < CASES; j++) { UtlString* s1 = &output[i]; UtlString* s2 = &output[j]; int differences = 0; for (size_t k = 0; k < s1->length() && k < s1->length(); k++) { if ((*s1)(k) != (*s2)(k)) { differences++; } } if (differences < MIN_DIFFS) { char msg[200]; sprintf(msg, "BranchId '%s' and '%s' have %d different characters, " "which is less than the minimum, %d", s1->data(), s2->data(), differences, MIN_DIFFS); CPPUNIT_ASSERT_MESSAGE(msg, FALSE); } } } // And then add a fork to each to see if the forks are different Os::Logger::instance().log(FAC_SIP,PRI_DEBUG,"BranchIdTest::testBranchIdUniqueness forked cases"); for (int i = 0; i < CASES; i++) { BranchId parentBranchId(output[i]); char forkContact[32]; sprintf(forkContact, "sip:someuser%02d@domain", i); Url contactUrl(forkContact); parentBranchId.addFork(contactUrl); BranchId branchId(parentBranchId, sipMsg); output[i].remove(0); output[i].append(branchId.data()); Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "case %d forked : %s\n", i, output[i].data()); } // Compare that they're different enough. for (int i = 0; i < CASES; i++) { for (int j = i+1; j < CASES; j++) { UtlString* s1 = &output[i]; UtlString* s2 = &output[j]; int differences = 0; for (size_t k = 0; k < s1->length() && k < s1->length(); k++) { if ((*s1)(k) != (*s2)(k)) { differences++; } } if (differences < MIN_DIFFS) { char msg[200]; sprintf(msg, "BranchId '%s' and '%s' have %d different characters, " "which is less than the minimum, %d", s1->data(), s2->data(), differences, MIN_DIFFS); CPPUNIT_ASSERT_MESSAGE(msg, FALSE); } } } }
ProvisioningAttrList* XmlRpcSignIn::Action(ProvisioningAttrList& rRequestAttributes) { ProvisioningAttrList* pResponse; UtlString uriString; UtlString status; osPrintf("{method} = action\n{object-class} = login\n"); rRequestAttributes.dumpAttributes(); osPrintf("\n"); // Extract the action attribute from the request // operate on either sign-in or sign-out attributes if (rRequestAttributes.getAttribute(XMLRPC_SIGN_IN_TAG, uriString)) { // See if the Agent is not already signed-in Url contactUrl(uriString); mpSipPresenceMonitor->getState(contactUrl, status); if (status.compareTo(STATUS_OPEN) == 0) { // Already signed-in, return error pResponse = new ProvisioningAttrList; pResponse->setAttribute("method-name", "action"); pResponse->setAttribute("result-code", ProvisioningAgent::SUCCESS); pResponse->setAttribute("result-text", "SUCCESS: User already signed-in"); return pResponse; } // Sign-in the Agent mpSipPresenceMonitor->setStatus(contactUrl, StateChangeNotifier::PRESENT); // Build up the response. pResponse = new ProvisioningAttrList; pResponse->setAttribute("method-name", "action"); pResponse->setAttribute("result-code", ProvisioningAgent::SUCCESS); pResponse->setAttribute("result-text", "SUCCESS: sign-in"); return pResponse; } else if (rRequestAttributes.getAttribute(XMLRPC_SIGN_OUT_TAG, uriString)) { // See if the Agent is not already signed-out Url contactUrl(uriString); mpSipPresenceMonitor->getState(contactUrl, status); if (status.compareTo(STATUS_CLOSED) == 0) { // Already signed-out, return error pResponse = new ProvisioningAttrList; pResponse->setAttribute("method-name", "action"); pResponse->setAttribute("result-code", ProvisioningAgent::SUCCESS); pResponse->setAttribute("result-text", "SUCCESS: User already signed-out"); return pResponse; } // Sign-out the Agent mpSipPresenceMonitor->setStatus(contactUrl, StateChangeNotifier::AWAY); // Build up the response. pResponse = new ProvisioningAttrList; pResponse->setAttribute("method-name", "action"); pResponse->setAttribute("result-code", ProvisioningAgent::SUCCESS); pResponse->setAttribute("result-text", "SUCCESS: sign-out"); return pResponse; } else if (rRequestAttributes.getAttribute(XMLRPC_SIGN_IN_STATUS_TAG, uriString)) { // Get the Agent status Url contactUrl(uriString); mpSipPresenceMonitor->getState(contactUrl, status); // Build up the response. pResponse = new ProvisioningAttrList; pResponse->setAttribute("method-name", "action"); pResponse->setAttribute("result-code", ProvisioningAgent::SUCCESS); pResponse->setAttribute("result-text", status); return pResponse; } else { // Unrecognized or missing action-object pResponse = new ProvisioningAttrList; pResponse->setAttribute("method-name", "action"); pResponse->setAttribute("result-code", ProvisioningAgent::FAILURE); pResponse->setAttribute("result-text", "Invalid action operation"); return pResponse; } }