diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h index 5e3e439fda..ac1ed58be5 100644 --- a/include/asterisk/res_pjsip.h +++ b/include/asterisk/res_pjsip.h @@ -2647,6 +2647,8 @@ void *ast_sip_dict_set(pj_pool_t* pool, void *ht, int ast_sip_for_each_contact(const struct ast_sip_aor *aor, ao2_callback_fn on_contact, void *arg); +int ast_sip_for_each_contact_nowrap(const struct ast_sip_aor *aor, + ao2_callback_fn on_contact, void *arg); /*! * \brief Handler used to convert a contact to a string. * diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c index cef5ad78ff..3dc20c6212 100644 --- a/res/res_pjsip/location.c +++ b/res/res_pjsip/location.c @@ -369,6 +369,8 @@ struct ast_sip_contact *ast_sip_location_create_contact(struct ast_sip_aor *aor, return NULL; } + ast_log(LOG_NOTICE, "LBOX creating contacts\n"); + ast_string_field_set(contact, uri, uri); contact->expiration_time = expiration_time; contact->qualify_frequency = aor->qualify_frequency; @@ -399,8 +401,10 @@ struct ast_sip_contact *ast_sip_location_create_contact(struct ast_sip_aor *aor, ast_string_field_set(contact, call_id, call_id); } + ast_log(LOG_NOTICE, "inc endpoint refcount/copy\n"); contact->endpoint = ao2_bump(endpoint); if (endpoint) { + ast_log(LOG_NOTICE, "setting endpoint_name\n"); ast_string_field_set(contact, endpoint_name, ast_sorcery_object_get_id(endpoint)); } @@ -764,6 +768,57 @@ int ast_sip_for_each_contact(const struct ast_sip_aor *aor, return res; } +int ast_sip_for_each_contact_nowrap(const struct ast_sip_aor *aor, + ao2_callback_fn on_contact, void *arg) +{ + struct ao2_container *contacts; + struct ao2_iterator i; + int res = 0; + void *object = NULL; + + if (!on_contact || + !(contacts = ast_sip_location_retrieve_aor_contacts(aor))) { + return 0; + } + + i = ao2_iterator_init(contacts, 0); + while ((object = ao2_iterator_next(&i))) { + RAII_VAR(struct ast_sip_contact *, contact, object, ao2_cleanup); + RAII_VAR(struct ast_sip_contact_wrapper *, wrapper, NULL, ao2_cleanup); + const char *aor_id = ast_sorcery_object_get_id(aor); + + wrapper = ao2_alloc_options(sizeof(struct ast_sip_contact_wrapper), + contact_wrapper_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK); + if (!wrapper) { + res = -1; + break; + } + wrapper->contact_id = ast_malloc(strlen(aor_id) + strlen(contact->uri) + 2); + if (!wrapper->contact_id) { + res = -1; + break; + } + sprintf(wrapper->contact_id, "%s/%s", aor_id, contact->uri); + wrapper->aor_id = ast_strdup(aor_id); + if (!wrapper->aor_id) { + res = -1; + break; + } + wrapper->contact = contact; + ao2_bump(wrapper->contact); + + // set aor id as endpoint, TODO - i dont know how to get real endpoint name + ast_string_field_set(contact, endpoint_name, aor_id); + + if ((res = on_contact(contact, arg, 0))) { + break; + } + } + ao2_iterator_destroy(&i); + ao2_ref(contacts, -1); + return res; +} + int ast_sip_contact_to_str(void *object, void *arg, int flags) { struct ast_sip_contact_wrapper *wrapper = object; @@ -1050,6 +1105,7 @@ static struct ao2_container *cli_contact_get_container(const char *regex) ao2_ref(contacts_container, -1); return NULL; } + ast_log(LOG_NOTICE, "after get sorcery, contacts count: %i contacts_container: %i\n", ao2_container_count(contacts), ao2_container_count(contacts_container)); ao2_callback(contacts, OBJ_NODATA, cli_gather_contact, contacts_container); aors = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), @@ -1059,8 +1115,14 @@ static struct ao2_container *cli_contact_get_container(const char *regex) return NULL; } + ast_log(LOG_NOTICE, "after get aors, aors: %i contacts_container: %i\n", ao2_container_count(aors), ao2_container_count(contacts_container)); + + ao2_callback(aors, OBJ_NODATA, cli_aor_gather_contacts, contacts_container); + ast_log(LOG_NOTICE, "after cli_aor_gather_contacts, aors: %i contacts_container: %i\n", ao2_container_count(aors), ao2_container_count(contacts_container)); + + if (!ast_strlen_zero(regex)) { if (regcomp(®exbuf, regex, REG_EXTENDED | REG_NOSUB)) { ao2_ref(contacts_container, -1); diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index 80bad02b37..098b217aba 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -1612,17 +1612,25 @@ int ast_sip_sorcery_object_to_ami(const void *obj, struct ast_str **buf) ast_sip_get_sorcery(), obj, AST_HANDLER_ONLY_STRING), ast_variables_destroy); struct ast_variable *i; + ast_log(LOG_NOTICE, "LBOX start\n"); + if (!objset) { return -1; } + ast_log(LOG_NOTICE, "LBOX after objset\n"); + sip_sorcery_object_ami_set_type_name(obj, buf); + ast_log(LOG_NOTICE, "LBOX sip_sorcery_object_ami_set_type_name\n"); + for (i = objset; i; i = i->next) { RAII_VAR(char *, camel, ast_to_camel_case(i->name), ast_free); ast_str_append(buf, 0, "%s: %s\r\n", camel, i->value); } + ast_log(LOG_NOTICE, "LBOX end\n"); + return 0; } diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c index 579165fdde..8c90cc6cff 100644 --- a/res/res_pjsip/pjsip_options.c +++ b/res/res_pjsip/pjsip_options.c @@ -30,6 +30,7 @@ #include "asterisk/cli.h" #include "asterisk/time.h" #include "asterisk/test.h" +#include "asterisk/paths.h" #include "asterisk/statsd.h" #include "include/res_pjsip_private.h" #include "asterisk/taskprocessor.h" @@ -1338,6 +1339,8 @@ static void sip_options_apply_aor_configuration(struct sip_options_aor *aor_opti sip_options_contact_status_available_count, &aor_options->available); } + ast_log(LOG_NOTICE, "LBOX creating contacts\n"); + aor_options->authenticate_qualify = aor->authenticate_qualify; aor_options->qualify_timeout = aor->qualify_timeout; @@ -2397,14 +2400,145 @@ static char *cli_qualify(struct ast_cli_entry *e, int cmd, struct ast_cli_args * return CLI_SUCCESS; } +static int cli_contact_populate_container(void *obj, void *arg, int flags) +{ + ao2_link(arg, obj); + + return 0; +} + +static int cli_aor_gather_contacts(void *obj, void *arg, int flags) +{ + struct ast_sip_aor *aor = obj; + + return ast_sip_for_each_contact_nowrap(aor, cli_contact_populate_container, arg); +} + +static void contact_wrapper_destroy(void *obj) +{ + struct ast_sip_contact_wrapper *wrapper = obj; + + ast_free(wrapper->aor_id); + ast_free(wrapper->contact_id); + ao2_cleanup(wrapper->contact); +} + +static int cli_gather_contact(void *obj, void *arg, int flags) +{ + struct ast_sip_contact *contact = obj; + RAII_VAR(struct ast_sip_contact_wrapper *, wrapper, NULL, ao2_cleanup); + + if (strcmp(contact->reg_server, ast_config_AST_SYSTEM_NAME ?: "")) { + return 0; + } + + wrapper = ao2_alloc_options(sizeof(struct ast_sip_contact_wrapper), + contact_wrapper_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK); + if (!wrapper) { + return -1; + } + + wrapper->contact_id = ast_malloc(strlen(contact->aor) + strlen(contact->uri) + 2); + if (!wrapper->contact_id) { + return -1; + } + sprintf(wrapper->contact_id, "%s/%s", contact->aor, contact->uri); + + wrapper->aor_id = ast_strdup(contact->aor); + if (!wrapper->aor_id) { + return -1; + } + + wrapper->contact = ao2_bump(contact); + + ao2_link(arg, contact); + + return 0; +} + +static int cli_contact_sort(const void *obj, const void *arg, int flags) +{ + const struct ast_sip_contact *left_wrapper = obj; + const struct ast_sip_contact *right_wrapper = arg; + const char *right_key = arg; + int cmp = 0; + + switch (flags & OBJ_SEARCH_MASK) { + case OBJ_SEARCH_OBJECT: + right_key = right_wrapper->endpoint_name; + /* Fall through */ + case OBJ_SEARCH_KEY: + cmp = strcmp(left_wrapper->endpoint_name, right_key); + break; + case OBJ_SEARCH_PARTIAL_KEY: + cmp = strncmp(left_wrapper->endpoint_name, right_key, strlen(right_key)); + break; + default: + cmp = 0; + break; + } + + return cmp; +} + +static int cli_contact_compare(void *obj, void *arg, int flags) +{ + const struct ast_sip_contact *left_wrapper = obj; + const struct ast_sip_contact *right_wrapper = arg; + const char *right_key = arg; + int cmp = 0; + + switch (flags & OBJ_SEARCH_MASK) { + case OBJ_SEARCH_OBJECT: + right_key = right_wrapper->endpoint_name; + /* Fall through */ + case OBJ_SEARCH_KEY: + if (strcmp(left_wrapper->endpoint_name, right_key) == 0) {; + cmp = CMP_MATCH | CMP_STOP; + } + break; + case OBJ_SEARCH_PARTIAL_KEY: + if (strncmp(left_wrapper->endpoint_name, right_key, strlen(right_key)) == 0) { + cmp = CMP_MATCH; + } + break; + default: + cmp = 0; + break; + } + + return cmp; +} + static struct ao2_container *get_all_contacts(void) { + struct ao2_container *aors; struct ao2_container *contacts; + struct ao2_container *contacts_container; - contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "contact", - AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); + ast_log(LOG_NOTICE, "LBOX start\n"); - return contacts; + contacts_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, + cli_contact_sort, cli_contact_compare); + if (!contacts_container) { + return NULL; + } + + contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "contact", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); + aors = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "aor", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); + ast_log(LOG_NOTICE, "LBOX after get contacts and aors, contacts = %i, aors = %i, contacts_container = %i\n", + ao2_container_count(aors), ao2_container_count(contacts), ao2_container_count(contacts_container)); + + + ao2_callback(aors, OBJ_NODATA, cli_aor_gather_contacts, contacts_container); + ast_log(LOG_NOTICE, "LBOX after cli_aor_gather_contacts, contacts = %i, aors = %i, contacts_container = %i\n", + ao2_container_count(aors), ao2_container_count(contacts), ao2_container_count(contacts_container)); + + ao2_callback(contacts, OBJ_NODATA, cli_gather_contact, contacts_container); + ast_log(LOG_NOTICE, "LBOX after cli_gather_contact, contacts = %i, aors = %i, contacts_container = %i\n", + ao2_container_count(aors), ao2_container_count(contacts), ao2_container_count(contacts_container)); + + return contacts_container; } static int sip_contact_to_ami(const struct ast_sip_contact *contact, @@ -2420,15 +2554,19 @@ static int format_ami_contactlist_handler(void *obj, void *arg, int flags) struct ast_str *buf; struct ast_sip_contact_status *status; + ast_log(LOG_NOTICE, "LBOX formating contact start\n"); + buf = ast_sip_create_ami_event("ContactList", ami); if (!buf) { return CMP_STOP; } + ast_log(LOG_NOTICE, "LBOX formating contact after create ami event\n"); if (sip_contact_to_ami(contact, &buf)) { ast_free(buf); return CMP_STOP; } + ast_log(LOG_NOTICE, "LBOX formating contact after to ami\n"); /* Add extra info */ status = ast_sip_get_contact_status(contact); @@ -2456,6 +2594,7 @@ static int ami_show_contacts(struct mansession *s, const struct message *m) struct ao2_container *contacts; contacts = get_all_contacts(); + if (!contacts) { astman_send_error(s, m, "Could not get Contacts\n"); return 0;