HTTPCode SubscriberManager::remove_bindings(const std::string& public_id, const std::vector<std::string>& binding_ids, const SubscriberDataUtils::EventTrigger& event_trigger, Bindings& bindings, SAS::TrailId trail) { TRC_DEBUG("Removing bindings from IMPU %s", public_id.c_str()); int now = time(NULL); // Get cached subscriber information from the HSS. std::string aor_id; HSSConnection::irs_info irs_info; HTTPCode rc = get_cached_default_id(public_id, aor_id, irs_info, trail); if (rc != HTTP_OK) { return rc; } // Get the original AoR from S4. AoR* orig_aor = NULL; uint64_t unused_version; rc = _s4->handle_get(aor_id, &orig_aor, unused_version, trail); if (rc != HTTP_OK) { delete orig_aor; orig_aor = NULL; if (rc == HTTP_NOT_FOUND) { // If there is no AoR, we still count that as a success. TRC_DEBUG("Removing bindings for AoR %s succeeded because no bindings are present in the store", aor_id.c_str()); return HTTP_OK; } TRC_DEBUG("Removing bindings for AoR %s failed during GET with return code %d", aor_id.c_str(), rc); return rc; } // We log removed bindings before writing to the store so that in the case // that the write fails, our estimate of how many active bindings we have will // be an underestimate, not an overestimate. log_removed_bindings(*orig_aor, binding_ids); // Check if there are any subscriptions that share the same contact as // the removed bindings, and delete them too. std::vector<std::string> subscription_ids_to_remove = subscriptions_to_remove(orig_aor->bindings(), orig_aor->subscriptions(), Bindings(), binding_ids); PatchObject patch_object; build_patch(patch_object, binding_ids, subscription_ids_to_remove, irs_info._associated_uris); // PATCH the existing AoR. AoR* updated_aor = NULL; rc = _s4->handle_patch(aor_id, patch_object, &updated_aor, trail); if (rc != HTTP_OK) { TRC_DEBUG("Removing bindings for AoR %s failed during PATCH with return code %d", aor_id.c_str(), rc); delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return rc; } log_subscriptions(aor_id, *orig_aor, *updated_aor, subscription_ids_to_remove, now); // Get all bindings to return to the caller bindings = SubscriberDataUtils::copy_active_bindings(updated_aor->bindings(), now, trail); send_notifys(aor_id, orig_aor, updated_aor, event_trigger, now, trail); // Update HSS if all bindings expired. if (bindings.empty()) { // If this action was not triggered by the HSS e.g. because of an RTR, we // should dergister with the HSS. if (event_trigger != SubscriberDataUtils::EventTrigger::HSS) { std::string dereg_reason = (event_trigger == SubscriberDataUtils::EventTrigger::USER) ? HSSConnection::DEREG_USER : HSSConnection::DEREG_ADMIN; rc = deregister_with_hss(aor_id, dereg_reason, updated_aor->_scscf_uri, irs_info, trail); if (rc != HTTP_OK) { TRC_DEBUG("Failed to deregister subscriber %s with HSS", aor_id.c_str()); delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return rc; } } // Send 3rd party deREGISTERs. _registration_sender->deregister_with_application_servers(public_id, irs_info._service_profiles[public_id], trail); } delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return HTTP_OK; }
HTTPCode SubscriberManager::register_subscriber_internal(const std::string& aor_id, const std::string& server_name, const AssociatedURIs& associated_uris, const Bindings& add_bindings, Bindings& all_bindings, HSSConnection::irs_info& irs_info, bool retry, SAS::TrailId trail) { TRC_DEBUG("Registering AoR %s for the first time", aor_id.c_str()); int now = time(NULL); // We are registering a subscriber for the first time, so there is no stored // AoR. PUT the new bindings to S4. AoR* orig_aor = NULL; AoR* updated_aor = NULL; // We may have been called with no bindings to update. This is the case when // we receive a fetch bindings register from a subscriber that is unregistered. // In that situation, we do not have any data to PUT to S4, but we should // deregister the subscriber with the HSS. if (!add_bindings.empty()) { PatchObject patch_object; build_patch(patch_object, add_bindings, associated_uris); updated_aor = new AoR(aor_id); updated_aor->patch_aor(patch_object); updated_aor->_scscf_uri = server_name; // PUT a new AoR. HTTPCode rc = _s4->handle_put(aor_id, *updated_aor, trail); // If the PUT resulted in precondition failed (which happens if there is // already an AoR in the store), we retry with a reregister. if ((rc == HTTP_PRECONDITION_FAILED) && (retry)) { TRC_DEBUG("Registering AoR %s failed with 412 PRECONDITION FAILED - retry with reregister", aor_id.c_str()); delete updated_aor; updated_aor = NULL; return reregister_subscriber_internal(aor_id, server_name, associated_uris, add_bindings, {}, all_bindings, irs_info, false, trail); } else if (rc != HTTP_OK) { TRC_DEBUG("Registering AoR %s failed with return code %d", aor_id.c_str(), rc); delete updated_aor; updated_aor = NULL; return rc; } log_updated_bindings(*updated_aor, add_bindings, now); // Get all bindings to return to the caller all_bindings = SubscriberDataUtils::copy_active_bindings(updated_aor->bindings(), now, trail); } else { // The was nothing to store for this subscriber so we should deregister the // subscriber with the HSS since they will have previously been registered // incorrectly when the registrar was figuring out the default public ID. if (all_bindings.empty()) { HTTPCode rc = deregister_with_hss(aor_id, HSSConnection::DEREG_USER, server_name, irs_info, trail); if (rc != HTTP_OK) { TRC_DEBUG("Failed to deregister subscriber %s with HSS", aor_id.c_str()); delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return rc; } } } delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return HTTP_OK; }
HTTPCode SubscriberManager::reregister_subscriber_internal(const std::string& aor_id, const std::string& server_name, const AssociatedURIs& associated_uris, const Bindings& updated_bindings, const std::vector<std::string>& binding_ids_to_remove, Bindings& all_bindings, HSSConnection::irs_info& irs_info, bool retry, SAS::TrailId trail) { TRC_DEBUG("Reregistering AoR %s", aor_id.c_str()); int now = time(NULL); AoR* orig_aor = NULL; uint64_t unused_version; HTTPCode rc = _s4->handle_get(aor_id, &orig_aor, unused_version, trail); // We are reregistering a subscriber, so there must be an existing AoR in the // store. AoR* updated_aor = NULL; if ((rc == HTTP_NOT_FOUND) && (retry)) { TRC_DEBUG("Reregistering AoR %s failed with 404 NOT FOUND - retry with register", aor_id.c_str()); return register_subscriber_internal(aor_id, server_name, associated_uris, updated_bindings, all_bindings, irs_info, false, trail); } else if (rc != HTTP_OK) { TRC_DEBUG("Reregistering AoR %s failed during GET with return code %d", aor_id.c_str(), rc); delete orig_aor; orig_aor = NULL; return rc; } // Check if there are any subscriptions that share the same contact as // the removed bindings, and delete them too. std::vector<std::string> subscription_ids_to_remove = subscriptions_to_remove(orig_aor->bindings(), orig_aor->subscriptions(), updated_bindings, binding_ids_to_remove); // We log removed bindings before writing to the store so that in the case // that the write fails, our estimate of how many active bindings we have will // be an underestimate, not an overestimate. log_removed_bindings(*orig_aor, binding_ids_to_remove); PatchObject patch_object; build_patch(patch_object, updated_bindings, binding_ids_to_remove, subscription_ids_to_remove, associated_uris); // PATCH the existing AoR. rc = _s4->handle_patch(aor_id, patch_object, &updated_aor, trail); // If we didn't find an existing AoR, that means the subscriber does not // currently exist. We might want to retry by registering the subscriber // afresh. if ((rc == HTTP_NOT_FOUND) && (retry)) { TRC_DEBUG("Reregistering AoR %s failed with 404 NOT FOUND - retry with register", aor_id.c_str()); delete orig_aor; orig_aor = NULL; return register_subscriber_internal(aor_id, server_name, associated_uris, updated_bindings, all_bindings, irs_info, false, trail); } else if (rc != HTTP_OK) { TRC_DEBUG("Reregistering AoR %s failed during PATCH with return code %d", aor_id.c_str(), rc); delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return rc; } log_updated_bindings(*updated_aor, updated_bindings, now); log_subscriptions(aor_id, *orig_aor, *updated_aor, subscription_ids_to_remove, now); // Get all bindings to return to the caller all_bindings = SubscriberDataUtils::copy_active_bindings(updated_aor->bindings(), now, trail); send_notifys(aor_id, orig_aor, updated_aor, SubscriberDataUtils::EventTrigger::USER, now, trail); // Update HSS if all bindings expired. if (all_bindings.empty()) { rc = deregister_with_hss(aor_id, HSSConnection::DEREG_USER, updated_aor->_scscf_uri, irs_info, trail); if (rc != HTTP_OK) { TRC_DEBUG("Failed to deregister subscriber %s with HSS", aor_id.c_str()); delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return rc; } } delete orig_aor; orig_aor = NULL; delete updated_aor; updated_aor = NULL; return HTTP_OK; }