}
AST_RWLIST_UNLOCK(&supplements);
- if ((tsx->status_code == 401 || tsx->status_code == 407) && req_data->endpoint) {
- if (!ast_sip_create_request_with_auth(&req_data->endpoint->outbound_auths, challenge, tsx, &tdata)) {
- pjsip_endpt_send_request(ast_sip_get_pjsip_endpoint(), tdata, -1, req_data->token, req_data->callback);
- }
+ if ((tsx->status_code == 401 || tsx->status_code == 407)
+ && req_data->endpoint
+ && !ast_sip_create_request_with_auth(&req_data->endpoint->outbound_auths, challenge, tsx, &tdata)
+ && pjsip_endpt_send_request(ast_sip_get_pjsip_endpoint(), tdata, -1, req_data->token, req_data->callback)
+ == PJ_SUCCESS) {
return;
}
struct ast_sip_contact *contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
if (!req_data) {
+ pjsip_tx_data_dec_ref(tdata);
return -1;
}
ast_log(LOG_ERROR, "Error attempting to send outbound %.*s request to endpoint %s\n",
(int) pj_strlen(&tdata->msg->line.req.method.name),
pj_strbuf(&tdata->msg->line.req.method.name),
- ast_sorcery_object_get_id(endpoint));
+ endpoint ? ast_sorcery_object_get_id(endpoint) : "<unknown>");
ao2_cleanup(req_data);
return -1;
}
#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.
/*!
* \internal
- * \brief For an endpoint try to match on a given contact.
+ * \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.
*/
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;
+ char *looking_for = arg;
+ char *aor_name;
+ char *aors;
if (!arg || ast_strlen_zero(endpoint->aors)) {
return 0;
continue;
}
- if (ao2_find(contacts, arg, OBJ_NODATA | OBJ_POINTER)) {
+ contact = ao2_callback(contacts, 0, match_contact_id, looking_for);
+ if (contact) {
+ ao2_ref(contact, -1);
return CMP_MATCH;
}
}
/*!
* \internal
- * \brief Find endpoints associated with the given contact.
+ * \brief Find an endpoint associated with the given contact.
*/
-static struct ao2_iterator *find_endpoints(struct ast_sip_contact *contact)
+static struct ast_sip_endpoint *find_an_endpoint(struct ast_sip_contact *contact)
{
- RAII_VAR(struct ao2_container *, endpoints,
- ast_sip_get_endpoints(), ao2_cleanup);
+ RAII_VAR(struct ao2_container *, endpoints, ast_sip_get_endpoints(), ao2_cleanup);
+ char *looking_for = (char *) ast_sorcery_object_get_id(contact);
- return ao2_callback(endpoints, OBJ_MULTIPLE, on_endpoint, contact);
+ return ao2_callback(endpoints, 0, on_endpoint, looking_for);
}
/*!
*/
static void qualify_contact_cb(void *token, pjsip_event *e)
{
- RAII_VAR(struct ast_sip_contact *, contact, token, ao2_cleanup);
+ struct ast_sip_contact *contact = token;
switch(e->body.tsx_state.type) {
case PJSIP_EVENT_TRANSPORT_ERROR:
update_contact_status(contact, AVAILABLE);
break;
}
+ ao2_cleanup(contact);
}
/*!
* \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)
{
pjsip_tx_data *tdata;
- RAII_VAR(struct ast_sip_endpoint *, endpoint_local, ao2_bump(endpoint), ao2_cleanup);
-
-
- if (!endpoint_local && contact->authenticate_qualify) {
- struct ao2_iterator *endpoint_iterator = find_endpoints(contact);
-
- /* try to find endpoints that are associated with the contact */
- if (endpoint_iterator) {
- /* find "first" endpoint in order to authenticate - actually any
- endpoint should do that matched on the contact */
- endpoint_local = ao2_iterator_next(endpoint_iterator);
- ao2_iterator_destroy(endpoint_iterator);
+ RAII_VAR(struct ast_sip_endpoint *, endpoint_local, NULL, ao2_cleanup);
+
+ if (contact->authenticate_qualify) {
+ endpoint_local = ao2_bump(endpoint);
+ 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;
+ }
}
}
init_start_time(contact);
ao2_ref(contact, +1);
- if (ast_sip_send_request(tdata, NULL, contact->authenticate_qualify ? endpoint_local : NULL, contact,
- qualify_contact_cb) != PJ_SUCCESS) {
- /* The callback will be called so we don't need to drop the contact ref*/
+ if (ast_sip_send_request(tdata, NULL, endpoint_local, contact, qualify_contact_cb)
+ != PJ_SUCCESS) {
ast_log(LOG_ERROR, "Unable to send request to qualify contact %s\n",
contact->uri);
+ ao2_ref(contact, -1);
return -1;
}
struct ast_sip_aor *aor = arg;
contact->qualify_frequency = aor->qualify_frequency;
+ contact->authenticate_qualify = aor->authenticate_qualify;
qualify_and_schedule(contact);
* \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)