res_pjsip: Fix SEGV on pending-qualify contacts
Permanent contacts that hadn't been qualified yet were missing their contact_status entries causing SEGVs when running CLI commands. This patch makes sure that contact_statuses are created for both dynamic and permanent contacts when they are created. It also adds checks in the CLI code to make sure there's a contact_status, just in case. ASTERISK-25018 #close Reported-by: Ivan Poddubny Tested-by: Ivan Poddubny Tested-by: George Joseph Change-Id: I3cc13e5cedcafb24c400368b515b02d7fb81e029
This commit is contained in:
parent
d7f4788341
commit
356568dc7f
|
@ -319,4 +319,9 @@ void internal_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter
|
|||
*/
|
||||
int internal_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj);
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Finds or creates contact_status for a contact
|
||||
*/
|
||||
struct ast_sip_contact_status *ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact);
|
||||
#endif /* RES_PJSIP_PRIVATE_H_ */
|
||||
|
|
|
@ -376,6 +376,11 @@ static int permanent_uri_handler(const struct aco_option *opt, struct ast_variab
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!ast_res_pjsip_find_or_create_contact_status(contact)) {
|
||||
ao2_ref(contact, -1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_string_field_set(contact, uri, contact_uri);
|
||||
ao2_link(aor->permanent_contacts, contact);
|
||||
ao2_ref(contact, -1);
|
||||
|
@ -750,8 +755,8 @@ static int cli_contact_print_body(void *obj, void *arg, int flags)
|
|||
"Contact",
|
||||
flexwidth, flexwidth,
|
||||
wrapper->contact_id,
|
||||
ast_sip_get_contact_short_status_label(status->status),
|
||||
(status->status != UNKNOWN ? ((long long) status->rtt) / 1000.0 : NAN));
|
||||
ast_sip_get_contact_short_status_label(status ? status->status : UNKNOWN),
|
||||
(status && (status->status != UNKNOWN) ? ((long long) status->rtt) / 1000.0 : NAN));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -874,6 +879,17 @@ static struct ast_cli_entry cli_commands[] = {
|
|||
struct ast_sip_cli_formatter_entry *contact_formatter;
|
||||
struct ast_sip_cli_formatter_entry *aor_formatter;
|
||||
|
||||
/*! \brief Always create a contact_status for each contact */
|
||||
static int contact_apply_handler(const struct ast_sorcery *sorcery, void *object)
|
||||
{
|
||||
struct ast_sip_contact_status *status;
|
||||
struct ast_sip_contact *contact = object;
|
||||
|
||||
status = ast_res_pjsip_find_or_create_contact_status(contact);
|
||||
|
||||
return status ? 0 : -1;
|
||||
}
|
||||
|
||||
/*! \brief Initialize sorcery with location support */
|
||||
int ast_sip_initialize_sorcery_location(void)
|
||||
{
|
||||
|
@ -881,7 +897,7 @@ int ast_sip_initialize_sorcery_location(void)
|
|||
ast_sorcery_apply_default(sorcery, "contact", "astdb", "registrar");
|
||||
ast_sorcery_apply_default(sorcery, "aor", "config", "pjsip.conf,criteria=type=aor");
|
||||
|
||||
if (ast_sorcery_object_register(sorcery, "contact", contact_alloc, NULL, NULL) ||
|
||||
if (ast_sorcery_object_register(sorcery, "contact", contact_alloc, NULL, contact_apply_handler) ||
|
||||
ast_sorcery_object_register(sorcery, "aor", aor_alloc, NULL, NULL)) {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -76,11 +76,10 @@ static void *contact_status_alloc(const char *name)
|
|||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Retrieve a ast_sip_contact_status object from sorcery creating
|
||||
* one if not found.
|
||||
*/
|
||||
static struct ast_sip_contact_status *find_or_create_contact_status(const struct ast_sip_contact *contact)
|
||||
struct ast_sip_contact_status *ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact)
|
||||
{
|
||||
struct ast_sip_contact_status *status;
|
||||
|
||||
|
@ -98,6 +97,10 @@ static struct ast_sip_contact_status *find_or_create_contact_status(const struct
|
|||
return NULL;
|
||||
}
|
||||
|
||||
status->status = UNKNOWN;
|
||||
status->rtt_start = ast_tv(0, 0);
|
||||
status->rtt = 0;
|
||||
|
||||
if (ast_sorcery_create(ast_sip_get_sorcery(), status)) {
|
||||
ast_log(LOG_ERROR, "Unable to persist ast_sip_contact_status for contact %s\n",
|
||||
contact->uri);
|
||||
|
@ -118,7 +121,7 @@ static void update_contact_status(const struct ast_sip_contact *contact,
|
|||
struct ast_sip_contact_status *status;
|
||||
struct ast_sip_contact_status *update;
|
||||
|
||||
status = find_or_create_contact_status(contact);
|
||||
status = ast_res_pjsip_find_or_create_contact_status(contact);
|
||||
if (!status) {
|
||||
ast_log(LOG_ERROR, "Unable to find ast_sip_contact_status for contact %s\n",
|
||||
contact->uri);
|
||||
|
@ -143,8 +146,6 @@ static void update_contact_status(const struct ast_sip_contact *contact,
|
|||
|
||||
update->rtt_start = ast_tv(0, 0);
|
||||
|
||||
|
||||
|
||||
ast_test_suite_event_notify("AOR_CONTACT_QUALIFY_RESULT",
|
||||
"Contact: %s\r\n"
|
||||
"Status: %s\r\n"
|
||||
|
@ -172,7 +173,7 @@ static void init_start_time(const struct ast_sip_contact *contact)
|
|||
struct ast_sip_contact_status *status;
|
||||
struct ast_sip_contact_status *update;
|
||||
|
||||
status = find_or_create_contact_status(contact);
|
||||
status = ast_res_pjsip_find_or_create_contact_status(contact);
|
||||
if (!status) {
|
||||
ast_log(LOG_ERROR, "Unable to find ast_sip_contact_status for contact %s\n",
|
||||
contact->uri);
|
||||
|
|
Loading…
Reference in New Issue