Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}