diff options
author | George Joseph <george.joseph@fairview5.com> | 2015-04-27 11:11:40 -0600 |
---|---|---|
committer | George Joseph <george.joseph@fairview5.com> | 2015-04-27 11:11:40 -0600 |
commit | 99fb87ae13a1fc28bd5043600def3b373f85a0f6 (patch) | |
tree | f936206632f0ecfc59a065c39e43d0de7390cbf5 /res/res_pjsip | |
parent | e9788056e9f60a8ef6f810f0c5d31e0f3700e3bb (diff) |
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
Diffstat (limited to 'res/res_pjsip')
-rw-r--r-- | res/res_pjsip/include/res_pjsip_private.h | 5 | ||||
-rw-r--r-- | res/res_pjsip/location.c | 22 | ||||
-rw-r--r-- | res/res_pjsip/pjsip_options.c | 13 |
3 files changed, 31 insertions, 9 deletions
diff --git a/res/res_pjsip/include/res_pjsip_private.h b/res/res_pjsip/include/res_pjsip_private.h index bf428d5c5..c1f7e236e 100644 --- a/res/res_pjsip/include/res_pjsip_private.h +++ b/res/res_pjsip/include/res_pjsip_private.h @@ -313,4 +313,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_ */ diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c index 45370dd24..887053b07 100644 --- a/res/res_pjsip/location.c +++ b/res/res_pjsip/location.c @@ -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; } diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c index 40b6f7b4c..8ffb88c49 100644 --- a/res/res_pjsip/pjsip_options.c +++ b/res/res_pjsip/pjsip_options.c @@ -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); |