Beispiel #1
0
std::string JSONEnumService::lookup_uri_from_user(const std::string &user, SAS::TrailId trail) const
{
  std::string uri;

  TRC_DEBUG("Translating URI via JSON ENUM lookup");

  if (user.empty())
  {
    TRC_INFO("No dial string supplied, so don't do ENUM lookup");
    return std::string();
  }

  std::string aus = user_to_aus(user);

  // Take a read lock on the mutex in RAII style
  boost::shared_lock<boost::shared_mutex> read_lock(_number_prefixes_rw_lock);

  const struct NumberPrefix* pfix = prefix_match(aus);

  if (pfix == NULL)
  {
    TRC_WARNING("No matching number range %s from ENUM lookup", user.c_str());
    SAS::Event event(trail, SASEvent::ENUM_INCOMPLETE, 0);
    event.add_var_param(user);
    SAS::report_event(event);
    return uri;
  }

  // Apply the regular expression to the user string to generate a new
  // URI.
  try
  {
    uri = boost::regex_replace(aus, pfix->match, pfix->replace);
  }
  catch(...) // LCOV_EXCL_START Only throws if expression too complex or similar hard-to-hit conditions
  {
    TRC_ERROR("Failed to translate number with regex");
    SAS::Event event(trail, SASEvent::ENUM_INCOMPLETE, 1);
    event.add_var_param(user);
    SAS::report_event(event);
    return uri;
    // LCOV_EXCL_STOP
  }

  TRC_INFO("Number %s found, translated URI = %s", user.c_str(), uri.c_str());
  SAS::Event event(trail, SASEvent::ENUM_COMPLETE, 0);
  event.add_var_param(user);
  event.add_var_param(uri);
  SAS::report_event(event);

  return uri;
}
Beispiel #2
0
std::string JSONEnumService::lookup_uri_from_user(const std::string &user, SAS::TrailId trail) const
{
  std::string uri;

  TRC_DEBUG("Translating URI via JSON ENUM lookup");

  if (user.empty())
  {
    TRC_INFO("No dial string supplied, so don't do ENUM lookup");
    return std::string();
  }

  std::string aus = user_to_aus(user);
  struct NumberPrefix* pfix = prefix_match(aus);

  if (pfix == NULL)
  {
    TRC_INFO("No matching number range %s from ENUM lookup", user.c_str());
    return uri;
  }

  // Apply the regular expression to the user string to generate a new
  // URI.
  try
  {
    uri = boost::regex_replace(aus, pfix->match, pfix->replace);
  }
  catch(...) // LCOV_EXCL_START Only throws if expression too complex or similar hard-to-hit conditions
  {
    TRC_ERROR("Failed to translate number with regex");
    return uri;
    // LCOV_EXCL_STOP
  }

  TRC_INFO("Number %s found, translated URI = %s", user.c_str(), uri.c_str());

  return uri;
}
Beispiel #3
0
std::string DNSEnumService::lookup_uri_from_user(const std::string& user, SAS::TrailId trail) const
{
  if (user.empty())
  {
    TRC_INFO("No dial string supplied, so don't do ENUM lookup");
    return std::string();
  }

  // Log starting ENUM processing.
  SAS::Event event(trail, SASEvent::ENUM_START, 0);
  event.add_var_param(user);
  SAS::report_event(event);

  // Determine the Application Unique String (AUS) from the user.  This is
  // used to form the first key, and also as the input into the regular
  // expressions.
  std::string aus = user_to_aus(user);
  std::string string = aus;
  // Get the resolver to use.  This comes from thread-local data.
  DNSResolver* resolver = get_resolver();
  // Spin round until we've finished (successfully or otherwise) or we've done
  // the maximum number of queries.
  bool complete = false;
  bool failed = false;
  bool server_failed = false;
  int dns_queries = 0;
  while ((!complete) &&
         (!failed) &&
         (dns_queries < MAX_DNS_QUERIES))
  {
    // Translate the key into a domain and issue a query for it.
    std::string domain = key_to_domain(string);
    struct ares_naptr_reply* naptr_reply = NULL;
    int status = resolver->perform_naptr_query(domain, naptr_reply, trail);
    if (status == ARES_SUCCESS)
    {
      // Parse the reply into a sorted list of rules.
      std::vector<Rule> rules;
      parse_naptr_reply(naptr_reply, rules);
      // Now spin through the rules, looking for the first match.
      std::vector<DNSEnumService::Rule>::const_iterator rule;
      for (rule = rules.begin();
           rule != rules.end();
           ++rule)
      {
        if (rule->matches(string))
        {
          // We found a match, so apply the regular expression to the AUS (not
          // the previous string - this is what ENUM mandates).  If this was a
          // terminal rule, we now have a SIP URI and we're finished.
          // Otherwise, the output of the regular expression is used as the
          // next key.
          try
          {
            string = rule->replace(aus, trail);
            complete = rule->is_terminal();
          }
          catch(...) // LCOV_EXCL_START Only throws if expression too complex or similar hard-to-hit conditions
          {
            TRC_ERROR("Failed to translate number with regex");
            failed = true;
            // LCOV_EXCL_STOP
          }
          break;
        }
      }
      // If we didn't find a match (and so hit the end of the list), consider
      // this a failure.
      failed = failed || (rule == rules.end());
    }
    else if (status == ARES_ENOTFOUND)
    {
      // Our DNS query failed, so give up, but this is not an ENUM server issue -
      // we just tried to look up an unknown name.
      failed = true;
    }
    else
    {
      // Our DNS query failed. Give up, and track an ENUM server failure.
      failed = true;
      server_failed = true;
    }


    // Free off the NAPTR reply if we have one.
    if (naptr_reply != NULL)
    {
      resolver->free_naptr_reply(naptr_reply);
      naptr_reply = NULL;
    }

    dns_queries++;
  }

  // Log that we've finished processing (and whether it was successful or not).
  if (complete)
  {
    TRC_DEBUG("Enum lookup completes: %s", string.c_str());
    SAS::Event event(trail, SASEvent::ENUM_COMPLETE, 0);
    event.add_var_param(user);
    event.add_var_param(string);
    SAS::report_event(event);
  }
  else
  {
    TRC_WARNING("Enum lookup did not complete for user %s", user.c_str());
    SAS::Event event(trail, SASEvent::ENUM_INCOMPLETE, 0);
    event.add_var_param(user);
    SAS::report_event(event);
    // On failure, we must return an empty (rather than incomplete) string.
    string = std::string("");
  }

  // Report state of last communication attempt (which may potentially set/clear
  // an associated alarm). 
  if (_comm_monitor)
  {
    if (server_failed)
    {
      _comm_monitor->inform_failure();
    }
    else
    {
      _comm_monitor->inform_success();
    }
  }

  return string;
}