Index: res/res_pjsip/pjsip_options.c =================================================================== --- res/res_pjsip/pjsip_options.c (revision 410964) +++ res/res_pjsip/pjsip_options.c (working copy) @@ -34,8 +34,6 @@ #define DEFAULT_ENCODING "text/plain" #define QUALIFIED_BUCKETS 211 -static int qualify_contact(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact); - /*! * \internal * \brief Create a ast_sip_contact_status object. @@ -152,12 +150,34 @@ /*! * \internal + * \brief Match a container contact object URI with the contact URI 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_uri(void *obj, void *arg, int flags) +{ + struct ast_sip_contact *contact = obj; + struct ast_sip_contact *looking_for = arg; + + /* Do the contact URI's match? */ + return strcmp(contact->uri, looking_for->uri) ? 0 : CMP_MATCH; +} + +/*! + * \internal * \brief For an endpoint try to match on a given contact. */ static int on_endpoint(void *obj, void *arg, int flags) { struct ast_sip_endpoint *endpoint = obj; - char *aor_name, *aors; + struct ast_sip_contact *contact = arg; + struct ast_sip_contact *matching_contact; + char *aor_name; + char *aors; if (!arg || ast_strlen_zero(endpoint->aors)) { return 0; @@ -174,7 +194,9 @@ continue; } - if (ao2_find(contacts, arg, OBJ_NODATA | OBJ_POINTER)) { + matching_contact = ao2_callback(contacts, 0, match_contact_uri, contact); + if (matching_contact) { + ao2_ref(matching_contact, -1); return CMP_MATCH; } } @@ -217,7 +239,7 @@ * \internal * \brief Attempt to qualify the contact * - * \detail Sends a SIP OPTIONS request to the given contact in order to make + * \details Sends a SIP OPTIONS request to the given contact in order to make * sure that contact is available. */ static int qualify_contact(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact) @@ -236,6 +258,11 @@ endpoint_local = ao2_iterator_next(endpoint_iterator); ao2_iterator_destroy(endpoint_iterator); } + if (!endpoint_local) { + ast_log(LOG_ERROR, "Unable to find endpoint to qualify contact %s\n", + contact->uri); + return -1; + } } if (ast_sip_create_request("OPTIONS", NULL, NULL, NULL, contact, &tdata)) { @@ -378,14 +405,15 @@ */ static void unschedule_qualify(struct ast_sip_contact *contact) { - RAII_VAR(struct sched_data *, data, ao2_find( - sched_qualifies, contact, OBJ_UNLINK), ao2_cleanup); + struct sched_data *data; + data = ao2_find(sched_qualifies, contact, OBJ_UNLINK); if (!data) { return; } AST_SCHED_DEL_UNREF(sched, data->id, ao2_cleanup(data)); + ao2_cleanup(data); } /*! @@ -803,7 +831,7 @@ * \internal * \brief Qualify and schedule an endpoint's contacts * - * \detail For the given endpoint retrieve its list of aors, qualify all + * \details For the given endpoint retrieve its list of aors, qualify all * contacts, and schedule for checks if configured. */ static int qualify_and_schedule_all_cb(void *obj, void *arg, int flags)