diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c index 5e0fc76cb57d5eaae10360dbf5ab9a6d9b7e784b..a282224c92fd05111f60f06f808d0c97b18470e5 100644 --- a/res/res_pjsip/pjsip_options.c +++ b/res/res_pjsip/pjsip_options.c @@ -53,6 +53,9 @@ static const char *short_status_map [] = { [REMOVED] = "Removed", }; +static void contact_deleted(const void *obj); +static void qualify_and_schedule(struct ast_sip_contact *contact); + const char *ast_sip_get_contact_status_label(const enum ast_sip_contact_status_type status) { return status_map[status]; @@ -108,6 +111,29 @@ static void *contact_status_alloc(const char *name) return status; } +static int qualify_and_schedule_aor_contact(void *obj) +{ + struct ast_sip_contact *contact = obj; + struct ast_sip_aor *aor; + + if (!contact || ast_strlen_zero(contact->aor) || + !(aor = ast_sip_location_retrieve_aor(contact->aor))) { + ao2_ref(contact, -1); + return -1; + } + + contact->qualify_frequency = aor->qualify_frequency; + contact->qualify_timeout = aor->qualify_timeout; + contact->authenticate_qualify = aor->authenticate_qualify; + + ao2_ref(aor, -1); + + qualify_and_schedule(contact); + ao2_ref(contact, -1); + + return 0; +} + AST_MUTEX_DEFINE_STATIC(creation_lock); /*! @@ -144,6 +170,18 @@ struct ast_sip_contact_status *ast_res_pjsip_find_or_create_contact_status(const return NULL; } + /* The permanent contact added after asterisk start should be qualified. */ + if (ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED) && ast_tvzero(contact->expiration_time)) { + /* + * The FULLY_BOOTED to filter out contacts that already existed when asterisk started. + * The zero expiration_time to select only permanent contacts. + */ + ao2_ref((struct ast_sip_contact *) contact, +1); + if (ast_sip_push_task(NULL, qualify_and_schedule_aor_contact, (struct ast_sip_contact *) contact)) { + ao2_ref((struct ast_sip_contact *) contact, -1); + } + } + ast_statsd_log_string_va("PJSIP.contacts.states.%s", AST_STATSD_GAUGE, "+1", 1.0, ast_sip_get_contact_status_label(status->status)); @@ -368,8 +406,9 @@ static int qualify_contact(struct ast_sip_endpoint *endpoint, struct ast_sip_con endpoint_local = find_an_endpoint(contact); } if (!endpoint_local) { - ast_log(LOG_ERROR, "Unable to find an endpoint to qualify contact %s\n", + ast_log(LOG_WARNING, "Unable to find an endpoint to qualify contact %s. Deleting this contact\n", contact->uri); + contact_deleted(contact); return -1; } }