// Update the subscriptions we maintain to agree with the current contact state void ContactSet::updateSubscriptions() { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions mUri = '%s'", mUri.data()); // First, scan mSubscriptions to construct a list of all the // call-id/contact combinations. // (If a phone reboots and starts registering with a different Call-Id, // the call-id/contact combination will be different even if the contact // URI is unchanged. So the new registration will appear to be different // to this machinery, and it will establish a new SubscriptionSet to // the contact URI. This compensates for the fact that the previous // SubscriptionSet to the contact URI appears to the RLS to be // working but the phone no longer knows of the subscription. The // reg events will eventually terminate the old combination and we // will delete its SubscriptionSet.) UtlHashBag callid_contacts; UtlHashMapIterator subs_itor(mSubscriptions); while (subs_itor()) { if (OsSysLog::willLog(FAC_RLS, PRI_DEBUG)) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions subscription '%s'", (dynamic_cast <UtlString*> (subs_itor.key()))->data()); } UtlHashMap* contact_state = dynamic_cast <UtlHashMap*> (subs_itor.value()); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions contact_state = %p", contact_state); UtlHashMapIterator contact_itor(*contact_state); while (contact_itor()) { UtlString* contact = dynamic_cast <UtlString*> (contact_itor.value()); if (OsSysLog::willLog(FAC_RLS, PRI_DEBUG)) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions contact id '%s', Call-Id/URI '%s'", (dynamic_cast <UtlString*> (contact_itor.key()))->data(), contact->data()); } // Check if the contact is already in callid_contacts. if (!callid_contacts.find(contact)) { // If not, add it. UtlString* c = new UtlString(*contact); callid_contacts.insert(c); OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions contact added"); } } } // If the list of callid_contacts is empty, add mUri as the default contact // (with an empty registration Call-Id). if (callid_contacts.isEmpty()) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions adding default contact mUri = '%s'", mUri.data()); UtlString* c = new UtlString(";"); c->append(mUri); callid_contacts.insert(c); } // Now that we have a clean list of callid_contacts, update // SubscriptionSets to match it. // If we both terminate subscriptions and create subscriptions, // wait a short while to allow the terminations to complete. This // should not be necessary, but it makes life easier on Polycom // phones which (at this time) cannot support two subscriptions at // a time, and if the termination of the old subscription arrives // after the initiation of the new subscription, the new // subscription will be lost. // This variable tracks whether such a wait is needed before a // subscription is started. bool subscription_ended_but_no_wait_done_yet = false; // Iterate through the list of SubscriptionSets and remove any that aren't // in callid_contacts. { UtlHashMapIterator itor(mSubscriptionSets); UtlString* ss; while ((ss = dynamic_cast <UtlString*> (itor()))) { if (!callid_contacts.find(ss)) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions deleting subscription for '%s' in mUri = '%s'", ss->data(), mUri.data()); mSubscriptionSets.destroy(ss); subscription_ended_but_no_wait_done_yet = true; } } } // Iterate through callid_contacts and add a SubscriptionSet for // any that aren't in mSubscriptionSets. // We don't limit the number of additions here, as the size of // callid_contacts is guarded by the tests in notifyEventCallback. { UtlHashBagIterator itor(callid_contacts); UtlString* callid_contact; while ((callid_contact = dynamic_cast <UtlString*> (itor()))) { if (!mSubscriptionSets.find(callid_contact)) { // If we both terminate subscriptions and create subscriptions, // wait a short while to allow the terminations to complete. // Note that this wait must be no more than the bulk add/delete // change delay, as that is how fast ResourceListFileReader // generates requests to the ResourceListServer task. int wait = getResourceListServer()->getChangeDelay(); if (wait > 0) { if (subscription_ended_but_no_wait_done_yet) { OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions waiting for %d msec", wait); OsTask::delay(wait); subscription_ended_but_no_wait_done_yet = false; } } OsSysLog::add(FAC_RLS, PRI_DEBUG, "ContactSet::updateSubscriptions adding subscription for '%s' in mUri = '%s'", callid_contact->data(), mUri.data()); // Get the contact URI into a UtlString. UtlString uri(callid_contact->data() + callid_contact->index(';') + 1); mSubscriptionSets.insertKeyAndValue(new UtlString(*callid_contact), new SubscriptionSet(mResource, uri)); } } } // Free callid_contacts. callid_contacts.destroyAll(); }
// Update the subscriptions we maintain to agree with the current contact state void AppearanceGroup::updateSubscriptions() { Os::Logger::instance().log(FAC_SAA, PRI_DEBUG, "AppearanceGroup::updateSubscriptions mUri = '%s'", mSharedUser.data()); // First, scan mSubscriptions to construct a list of all the // call-id/contact combinations. // (If a phone reboots and starts registering with a different Call-Id, // the call-id/contact combination will be different even if the contact // URI is unchanged. So the new registration will appear to be different // to this machinery, and it will establish a new Appearance to // the contact URI. This compensates for the fact that the previous // Appearance to the contact URI appears to the Appearance Agent to be // working but the phone no longer knows of the subscription. The // reg events will eventually terminate the old combination and we // will delete its Appearance.) UtlHashBag callid_contacts; UtlHashMapIterator subs_itor(mSubscriptions); while (subs_itor()) { if (Os::Logger::instance().willLog(FAC_SAA, PRI_DEBUG)) { Os::Logger::instance().log(FAC_SAA, PRI_DEBUG, "AppearanceGroup::updateSubscriptions subscription '%s'", (dynamic_cast <UtlString*> (subs_itor.key()))->data()); } UtlHashMap* contact_state = dynamic_cast <UtlHashMap*> (subs_itor.value()); Os::Logger::instance().log(FAC_SAA, PRI_DEBUG, "AppearanceGroup::updateSubscriptions contact_state = %p", contact_state); UtlHashMapIterator contact_itor(*contact_state); while (contact_itor()) { UtlString* contact = dynamic_cast <UtlString*> (contact_itor.value()); if (Os::Logger::instance().willLog(FAC_SAA, PRI_DEBUG)) { Os::Logger::instance().log(FAC_SAA, PRI_DEBUG, "AppearanceGroup::updateSubscriptions contact id '%s', Call-Id/URI '%s'", (dynamic_cast <UtlString*> (contact_itor.key()))->data(), contact->data()); } // Check if the contact is already in callid_contacts. if (!callid_contacts.find(contact)) { // If not, add it. UtlString* c = new UtlString(*contact); callid_contacts.insert(c); Os::Logger::instance().log(FAC_SAA, PRI_DEBUG, "AppearanceGroup::updateSubscriptions contact '%s' added", c->data()); } } } // Now that we have a clean list of callid_contacts, update // Appearances to match it. // If we both terminate subscriptions and create subscriptions, // wait a short while to allow the terminations to complete. This // should not be necessary, but it makes life easier on Polycom // phones which (at this time) cannot support two subscriptions at // a time, and if the termination of the old subscription arrives // after the initiation of the new subscription, the new // subscription will be lost. // This variable tracks whether such a wait is needed before a // subscription is started. bool subscription_ended_but_no_wait_done_yet = false; // Iterate through the list of Appearances and remove any that aren't // in callid_contacts. { UtlHashMapIterator itor(mAppearances); UtlString* ss; while ((ss = dynamic_cast <UtlString*> (itor()))) { if (!callid_contacts.find(ss)) { Os::Logger::instance().log(FAC_SAA, PRI_DEBUG, "AppearanceGroup::updateSubscriptions deleting subscription for '%s' in mUri = '%s'", ss->data(), mSharedUser.data()); // Terminate all dialogs for this Appearance, then publish - before we delete it bool bContentChanged = false; SipDialogEvent* lPartialContent = new SipDialogEvent("partial", mSharedUser.data()); Appearance* inst = dynamic_cast <Appearance*> (itor.value()); bContentChanged = inst->terminateDialogs(true); // terminate all dialogs inst->getDialogs(lPartialContent); if (bContentChanged) { lPartialContent->buildBody(); publish(true, true, lPartialContent); delete lPartialContent; } mAppearances.destroy(ss); subscription_ended_but_no_wait_done_yet = true; } else { Os::Logger::instance().log(FAC_SAA, PRI_DEBUG, "AppearanceGroup::updateSubscriptions found subscription for '%s' in mUri = '%s'", ss->data(), mSharedUser.data()); } } } // Iterate through callid_contacts and add an Appearance for // any that aren't in mAppearances. // We don't limit the number of additions here, as the size of // callid_contacts is guarded by the tests in notifyEventCallback. { UtlHashBagIterator itor(callid_contacts); UtlString* callid_contact; while ((callid_contact = dynamic_cast <UtlString*> (itor()))) { if (!mAppearances.find(callid_contact)) { // If we both terminate subscriptions and create subscriptions, // wait a short while to allow the terminations to complete. if (SUBSCRIPTION_WAIT > 0) { if (subscription_ended_but_no_wait_done_yet) { Os::Logger::instance().log(FAC_SAA, PRI_DEBUG, "AppearanceGroup::updateSubscriptions waiting for %d msec", SUBSCRIPTION_WAIT); OsTask::delay(SUBSCRIPTION_WAIT); subscription_ended_but_no_wait_done_yet = false; } } Os::Logger::instance().log(FAC_SAA, PRI_DEBUG, "AppearanceGroup::updateSubscriptions adding subscription for '%s' in mUri = '%s'", callid_contact->data(), mSharedUser.data()); // Get the contact URI into a UtlString. UtlString uri(callid_contact->data() + callid_contact->index(';') + 1); mAppearances.insertKeyAndValue(new UtlString(*callid_contact), new Appearance(getAppearanceAgent(), this, uri) ); } else { Os::Logger::instance().log(FAC_SAA, PRI_DEBUG, "AppearanceGroup::updateSubscriptions using existing subscription for '%s' in mUri = '%s'", callid_contact->data(), mSharedUser.data()); } } } // Free callid_contacts. callid_contacts.destroyAll(); }