|
|
|
@ -237,31 +237,12 @@ static void init_start_time(const struct ast_sip_contact *contact)
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \internal
|
|
|
|
|
* \brief Match a container contact object with the contact sorcery id looking for.
|
|
|
|
|
*
|
|
|
|
|
* \param obj pointer to the (user-defined part) of an object.
|
|
|
|
|
* \param arg callback argument from ao2_callback()
|
|
|
|
|
* \param flags flags from ao2_callback()
|
|
|
|
|
*
|
|
|
|
|
* \return Values are a combination of enum _cb_results.
|
|
|
|
|
*/
|
|
|
|
|
static int match_contact_id(void *obj, void *arg, int flags)
|
|
|
|
|
{
|
|
|
|
|
struct ast_sip_contact *contact = obj;
|
|
|
|
|
const char *looking_for = arg;
|
|
|
|
|
|
|
|
|
|
return strcmp(ast_sorcery_object_get_id(contact), looking_for) ? 0 : CMP_MATCH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \internal
|
|
|
|
|
* \brief For an endpoint try to match the given contact sorcery id.
|
|
|
|
|
* \brief For an endpoint try to match the given contact->aor.
|
|
|
|
|
*/
|
|
|
|
|
static int on_endpoint(void *obj, void *arg, int flags)
|
|
|
|
|
{
|
|
|
|
|
struct ast_sip_endpoint *endpoint = obj;
|
|
|
|
|
struct ast_sip_contact *contact;
|
|
|
|
|
char *looking_for = arg;
|
|
|
|
|
char *contact_aor = arg;
|
|
|
|
|
char *aor_name;
|
|
|
|
|
char *aors;
|
|
|
|
|
|
|
|
|
@ -271,24 +252,7 @@ static int on_endpoint(void *obj, void *arg, int flags)
|
|
|
|
|
|
|
|
|
|
aors = ast_strdupa(endpoint->aors);
|
|
|
|
|
while ((aor_name = ast_strip(strsep(&aors, ",")))) {
|
|
|
|
|
struct ast_sip_aor *aor;
|
|
|
|
|
struct ao2_container *contacts;
|
|
|
|
|
|
|
|
|
|
aor = ast_sip_location_retrieve_aor(aor_name);
|
|
|
|
|
if (!aor) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
contacts = ast_sip_location_retrieve_aor_contacts(aor);
|
|
|
|
|
ao2_ref(aor, -1);
|
|
|
|
|
if (!contacts) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
contact = ao2_callback(contacts, 0, match_contact_id, looking_for);
|
|
|
|
|
ao2_ref(contacts, -1);
|
|
|
|
|
if (contact) {
|
|
|
|
|
ao2_ref(contact, -1);
|
|
|
|
|
if (!strcmp(contact_aor, aor_name)) {
|
|
|
|
|
return CMP_MATCH;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -302,12 +266,26 @@ static int on_endpoint(void *obj, void *arg, int flags)
|
|
|
|
|
*/
|
|
|
|
|
static struct ast_sip_endpoint *find_an_endpoint(struct ast_sip_contact *contact)
|
|
|
|
|
{
|
|
|
|
|
char *looking_for = (char *) ast_sorcery_object_get_id(contact);
|
|
|
|
|
struct ao2_container *endpoints = ast_sip_get_endpoints();
|
|
|
|
|
struct ao2_container *endpoints;
|
|
|
|
|
struct ast_sip_endpoint *endpoint;
|
|
|
|
|
struct ast_variable *var;
|
|
|
|
|
char *aor = ast_alloca(strlen(contact->aor) + 3);
|
|
|
|
|
|
|
|
|
|
sprintf(aor, "%%%s%%", contact->aor);
|
|
|
|
|
var = ast_variable_new("aors LIKE", aor, "");
|
|
|
|
|
endpoints = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
|
|
|
|
|
"endpoint", AST_RETRIEVE_FLAG_MULTIPLE, var);
|
|
|
|
|
|
|
|
|
|
ast_variables_destroy(var);
|
|
|
|
|
|
|
|
|
|
endpoint = ao2_callback(endpoints, 0, on_endpoint, looking_for);
|
|
|
|
|
/*
|
|
|
|
|
* Because aors are a string list, we have to use a pattern match but since a simple
|
|
|
|
|
* pattern match could return an endpoint that has an aor of "aaabccc" when searching
|
|
|
|
|
* for "abc", we still have to iterate over them to find an exact aor match.
|
|
|
|
|
*/
|
|
|
|
|
endpoint = ao2_callback(endpoints, 0, on_endpoint, (char *)contact->aor);
|
|
|
|
|
ao2_ref(endpoints, -1);
|
|
|
|
|
|
|
|
|
|
return endpoint;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -346,23 +324,18 @@ static int qualify_contact(struct ast_sip_endpoint *endpoint, struct ast_sip_con
|
|
|
|
|
pjsip_tx_data *tdata;
|
|
|
|
|
RAII_VAR(struct ast_sip_endpoint *, endpoint_local, NULL, ao2_cleanup);
|
|
|
|
|
|
|
|
|
|
if (contact->authenticate_qualify) {
|
|
|
|
|
if (endpoint) {
|
|
|
|
|
endpoint_local = ao2_bump(endpoint);
|
|
|
|
|
} else {
|
|
|
|
|
endpoint_local = find_an_endpoint(contact);
|
|
|
|
|
if (!endpoint_local) {
|
|
|
|
|
/*
|
|
|
|
|
* Find the "first" endpoint to completely qualify the contact - any
|
|
|
|
|
* endpoint that is associated with the contact should do.
|
|
|
|
|
*/
|
|
|
|
|
endpoint_local = find_an_endpoint(contact);
|
|
|
|
|
if (!endpoint_local) {
|
|
|
|
|
ast_log(LOG_ERROR, "Unable to find an endpoint to qualify contact %s\n",
|
|
|
|
|
contact->uri);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
ast_log(LOG_ERROR, "Unable to find an endpoint to qualify contact %s\n",
|
|
|
|
|
contact->uri);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ast_sip_create_request("OPTIONS", NULL, NULL, NULL, contact, &tdata)) {
|
|
|
|
|
if (ast_sip_create_request("OPTIONS", NULL, endpoint_local, NULL, contact, &tdata)) {
|
|
|
|
|
ast_log(LOG_ERROR, "Unable to create request to qualify contact %s\n",
|
|
|
|
|
contact->uri);
|
|
|
|
|
return -1;
|
|
|
|
|