From ed9134282e22c6985ce853f53d7569aa5b93ebe0 Mon Sep 17 00:00:00 2001 From: George Joseph <george.joseph@fairview5.com> Date: Mon, 30 Nov 2015 21:19:18 -0700 Subject: [PATCH] res_pjsip: Update logging to show contact->uri in messages An earlier commit changed the id of dynamic contacts to contain a hash instead of the uri. This patch updates status change logging to show the aor/uri instead of the id. This required adding the aor id to contact and contact_status and adding uri to contact_status. The aor id gets added to contact and contact_status in their allocators and the uri gets added to contact_status in pjsip_options when the contact_status is created or updated. ASTERISK-25598 #close Reported-by: George Joseph Tested-by: George Joseph Change-Id: I56cbec1d2ddbe8461367dd8b6da8a6f47f6fe511 --- include/asterisk/res_pjsip.h | 6 ++ res/res_pjsip/location.c | 23 ++++- res/res_pjsip/pjsip_configuration.c | 148 +++++++++++----------------- res/res_pjsip/pjsip_options.c | 74 ++++++++++---- 4 files changed, 142 insertions(+), 109 deletions(-) diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h index 37b7662119..6ca56bdcf3 100644 --- a/include/asterisk/res_pjsip.h +++ b/include/asterisk/res_pjsip.h @@ -170,6 +170,8 @@ struct ast_sip_contact { double qualify_timeout; /*! Endpoint that added the contact, only available in observers */ struct ast_sip_endpoint *endpoint; + /*! The name of the aor this contact belongs to */ + char *aor; }; #define CONTACT_STATUS "contact_status" @@ -201,6 +203,10 @@ struct ast_sip_contact_status { int64_t rtt; /*! Last status for a contact (default - unavailable) */ enum ast_sip_contact_status_type last_status; + /*! The name of the aor this contact_status belongs to */ + char *aor; + /*! The original contact's URI */ + char *uri; }; /*! diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c index 2e0d84b84a..16913c2c84 100644 --- a/res/res_pjsip/location.c +++ b/res/res_pjsip/location.c @@ -92,6 +92,7 @@ static void contact_destroy(void *obj) struct ast_sip_contact *contact = obj; ast_string_field_free_memory(contact); + ast_free(contact->aor); ao2_cleanup(contact->endpoint); } @@ -99,6 +100,9 @@ static void contact_destroy(void *obj) static void *contact_alloc(const char *name) { struct ast_sip_contact *contact = ast_sorcery_generic_alloc(sizeof(*contact), contact_destroy); + char *id = ast_strdupa(name); + char *aor = id; + char *aor_separator = NULL; if (!contact) { return NULL; @@ -109,6 +113,18 @@ static void *contact_alloc(const char *name) return NULL; } + /* Dynamic contacts are delimited with ";@" and static ones with "@@" */ + if ((aor_separator = strstr(id, ";@")) || (aor_separator = strstr(id, "@@"))) { + *aor_separator = '\0'; + } + ast_assert(aor_separator != NULL); + + contact->aor = ast_strdup(aor); + if (!contact->aor) { + ao2_cleanup(contact); + return NULL; + } + return contact; } @@ -790,13 +806,14 @@ static int cli_contact_print_body(void *obj, void *arg, int flags) ast_assert(context->output_buffer != NULL); indent = CLI_INDENT_TO_SPACES(context->indent_level); - flexwidth = CLI_LAST_TABSTOP - indent - 2; + flexwidth = CLI_LAST_TABSTOP - indent - 2 - strlen(contact->aor) + 1; - ast_str_append(&context->output_buffer, 0, "%*s: %-*.*s %-12.12s %11.3f\n", + ast_str_append(&context->output_buffer, 0, "%*s: %s/%-*.*s %-12.12s %11.3f\n", indent, "Contact", + contact->aor, flexwidth, flexwidth, - wrapper->contact_id, + contact->uri, ast_sip_get_contact_short_status_label(status ? status->status : UNKNOWN), (status && (status->status != UNKNOWN) ? ((long long) status->rtt) / 1000.0 : NAN)); diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index 7e0c4b087b..04002ef948 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -56,47 +56,37 @@ static int persistent_endpoint_cmp(void *obj, void *arg, int flags) return !strcmp(ast_endpoint_get_resource(persistent1->endpoint), id) ? CMP_MATCH | CMP_STOP : 0; } -/*! \brief Structure for communicating contact status to - * persistent_endpoint_update_state from the contact/contact_status - * observers. - */ -struct sip_contact_status { - char *uri; - enum ast_sip_contact_status_type status; - int64_t rtt; -}; - /*! \brief Callback function for changing the state of an endpoint */ -static int persistent_endpoint_update_state(void *obj, void *arg, void *data, int flags) +static int persistent_endpoint_update_state(void *obj, void *arg, int flags) { struct sip_persistent_endpoint *persistent = obj; struct ast_endpoint *endpoint = persistent->endpoint; - char *aor = arg; - struct sip_contact_status *status = data; + struct ast_sip_contact_status *status = arg; struct ao2_container *contacts; struct ast_json *blob; struct ao2_iterator i; struct ast_sip_contact *contact; enum ast_endpoint_state state = AST_ENDPOINT_OFFLINE; - if (!ast_strlen_zero(aor)) { - if (!strstr(persistent->aors, aor)) { + if (status) { + char rtt[32]; + + /* If the status' aor isn't one of the endpoint's, we skip */ + if (!strstr(persistent->aors, status->aor)) { return 0; } - if (status) { - char rtt[32]; - snprintf(rtt, 31, "%" PRId64, status->rtt); - blob = ast_json_pack("{s: s, s: s, s: s, s: s, s: s}", - "contact_status", ast_sip_get_contact_status_label(status->status), - "aor", aor, - "uri", status->uri, - "roundtrip_usec", rtt, - "endpoint_name", ast_endpoint_get_resource(endpoint)); - ast_endpoint_blob_publish(endpoint, ast_endpoint_contact_state_type(), blob); - ast_json_unref(blob); - } + snprintf(rtt, sizeof(rtt), "%" PRId64, status->rtt); + blob = ast_json_pack("{s: s, s: s, s: s, s: s, s: s}", + "contact_status", ast_sip_get_contact_status_label(status->status), + "aor", status->aor, + "uri", status->uri, + "roundtrip_usec", rtt, + "endpoint_name", ast_endpoint_get_resource(endpoint)); + ast_endpoint_blob_publish(endpoint, ast_endpoint_contact_state_type(), blob); + ast_json_unref(blob); } + /* Find all the contacts for this endpoint. If ANY are available, * mark the endpoint as ONLINE. */ @@ -142,57 +132,56 @@ static int persistent_endpoint_update_state(void *obj, void *arg, void *data, in return 0; } -/*! \brief Function called when stuff relating to a contact happens (created/deleted) */ +/*! \brief Function called when a contact is created */ static void persistent_endpoint_contact_created_observer(const void *object) { const struct ast_sip_contact *contact = object; - char *id = ast_strdupa(ast_sorcery_object_get_id(contact)); - char *aor = NULL; - char *contact_uri = NULL; - struct sip_contact_status status; - - aor = id; - /* Dynamic contacts are delimited with ";@" and static ones with "@@" */ - if ((contact_uri = strstr(id, ";@")) || (contact_uri = strstr(id, "@@"))) { - *contact_uri = '\0'; - contact_uri += 2; - } else { - contact_uri = id; - } + struct ast_sip_contact_status *contact_status; - status.uri = contact_uri; - status.status = CREATED; - status.rtt = 0; + contact_status = ast_sorcery_alloc(ast_sip_get_sorcery(), CONTACT_STATUS, + ast_sorcery_object_get_id(contact)); + if (!contact_status) { + ast_log(LOG_ERROR, "Unable to create ast_sip_contact_status for contact %s/%s\n", + contact->aor, contact->uri); + return; + } + contact_status->uri = ast_strdup(contact->uri); + if (!contact_status->uri) { + ao2_cleanup(contact_status); + return; + } + contact_status->status = CREATED; - ast_verb(1, "Contact %s/%s has been created\n", aor, contact_uri); + ast_verb(1, "Contact %s/%s has been created\n",contact->aor, contact->uri); - ao2_callback_data(persistent_endpoints, OBJ_NODATA, persistent_endpoint_update_state, aor, &status); + ao2_callback(persistent_endpoints, OBJ_NODATA, persistent_endpoint_update_state, contact_status); + ao2_cleanup(contact_status); } -/*! \brief Function called when stuff relating to a contact happens (created/deleted) */ +/*! \brief Function called when a contact is deleted */ static void persistent_endpoint_contact_deleted_observer(const void *object) { - char *id = ast_strdupa(ast_sorcery_object_get_id(object)); - char *aor = NULL; - char *contact_uri = NULL; - struct sip_contact_status status; + const struct ast_sip_contact *contact = object; + struct ast_sip_contact_status *contact_status; - aor = id; - /* Dynamic contacts are delimited with ";@" and static ones with "@@" */ - if ((contact_uri = strstr(id, ";@")) || (contact_uri = strstr(id, "@@"))) { - *contact_uri = '\0'; - contact_uri += 2; - } else { - contact_uri = id; + contact_status = ast_sorcery_alloc(ast_sip_get_sorcery(), CONTACT_STATUS, + ast_sorcery_object_get_id(contact)); + if (!contact_status) { + ast_log(LOG_ERROR, "Unable to create ast_sip_contact_status for contact %s/%s\n", + contact->aor, contact->uri); + return; } + contact_status->uri = ast_strdup(contact->uri); + if (!contact_status->uri) { + ao2_cleanup(contact_status); + return; + } + contact_status->status = REMOVED; - ast_verb(1, "Contact %s/%s has been deleted\n", aor, contact_uri); - - status.uri = contact_uri; - status.status = REMOVED; - status.rtt = 0; + ast_verb(1, "Contact %s/%s has been deleted\n", contact->aor, contact->uri); - ao2_callback_data(persistent_endpoints, OBJ_NODATA, persistent_endpoint_update_state, aor, &status); + ao2_callback(persistent_endpoints, OBJ_NODATA, persistent_endpoint_update_state, contact_status); + ao2_cleanup(contact_status); } /*! \brief Observer for contacts so state can be updated on respective endpoints */ @@ -201,36 +190,23 @@ static const struct ast_sorcery_observer state_contact_observer = { .deleted = persistent_endpoint_contact_deleted_observer, }; -/*! \brief Function called when stuff relating to a contact status happens (updated) */ +/*! \brief Function called when a contact_status is updated */ static void persistent_endpoint_contact_status_observer(const void *object) { - const struct ast_sip_contact_status *contact_status = object; - char *id = ast_strdupa(ast_sorcery_object_get_id(object)); - char *aor = NULL; - char *contact_uri = NULL; - struct sip_contact_status status; + struct ast_sip_contact_status *contact_status = (struct ast_sip_contact_status *)object; /* If rtt_start is set (this is the outgoing OPTIONS), ignore. */ if (contact_status->rtt_start.tv_sec > 0) { return; } - aor = id; - /* Dynamic contacts are delimited with ";@" and static ones with "@@" */ - if ((contact_uri = strstr(id, ";@")) || (contact_uri = strstr(id, "@@"))) { - *contact_uri = '\0'; - contact_uri += 2; - } else { - contact_uri = id; - } - if (contact_status->status == contact_status->last_status) { - ast_debug(3, "Contact %s status didn't change: %s, RTT: %.3f msec\n", - contact_uri, ast_sip_get_contact_status_label(contact_status->status), + ast_debug(3, "Contact %s/%s status didn't change: %s, RTT: %.3f msec\n", + contact_status->aor, contact_status->uri, ast_sip_get_contact_status_label(contact_status->status), contact_status->rtt / 1000.0); return; } else { - ast_verb(1, "Contact %s/%s is now %s. RTT: %.3f msec\n", aor, contact_uri, + ast_verb(1, "Contact %s/%s is now %s. RTT: %.3f msec\n", contact_status->aor, contact_status->uri, ast_sip_get_contact_status_label(contact_status->status), contact_status->rtt / 1000.0); } @@ -241,11 +217,7 @@ static void persistent_endpoint_contact_status_observer(const void *object) ast_sorcery_object_get_id(contact_status), ast_sip_get_contact_status_label(contact_status->status)); - status.uri = contact_uri; - status.status = contact_status->status; - status.rtt = contact_status->rtt; - - ao2_callback_data(persistent_endpoints, OBJ_NODATA, persistent_endpoint_update_state, aor, &status); + ao2_callback(persistent_endpoints, OBJ_NODATA, persistent_endpoint_update_state, contact_status); } /*! \brief Observer for contacts so state can be updated on respective endpoints */ @@ -1085,7 +1057,7 @@ static struct ast_endpoint *persistent_endpoint_find_or_create(const struct ast_ if (ast_strlen_zero(persistent->aors)) { ast_endpoint_set_state(persistent->endpoint, AST_ENDPOINT_UNKNOWN); } else { - persistent_endpoint_update_state(persistent, NULL, NULL, 0); + persistent_endpoint_update_state(persistent, NULL, 0); } ao2_link_flags(persistent_endpoints, persistent, OBJ_NOLOCK); diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c index b1724896d7..e0557871ed 100644 --- a/res/res_pjsip/pjsip_options.c +++ b/res/res_pjsip/pjsip_options.c @@ -42,7 +42,6 @@ static const char *status_map [] = { [UNKNOWN] = "Unknown", [CREATED] = "Created", [REMOVED] = "Removed", - }; static const char *short_status_map [] = { @@ -63,20 +62,45 @@ const char *ast_sip_get_contact_short_status_label(const enum ast_sip_contact_st return short_status_map[status]; } +/*! + * \internal + * \brief Destroy a ast_sip_contact_status object. + */ +static void contact_status_destroy(void * obj) +{ + struct ast_sip_contact_status *status = obj; + + ast_free(status->aor); + ast_free(status->uri); +} + /*! * \internal * \brief Create a ast_sip_contact_status object. */ static void *contact_status_alloc(const char *name) { - struct ast_sip_contact_status *status = ast_sorcery_generic_alloc(sizeof(*status), NULL); + struct ast_sip_contact_status *status = ast_sorcery_generic_alloc(sizeof(*status), contact_status_destroy); + char *id = ast_strdupa(name); + char *aor = id; + char *aor_separator = NULL; if (!status) { ast_log(LOG_ERROR, "Unable to allocate ast_sip_contact_status\n"); return NULL; } - status->status = UNKNOWN; + /* Dynamic contacts are delimited with ";@" and static ones with "@@" */ + if ((aor_separator = strstr(id, ";@")) || (aor_separator = strstr(id, "@@"))) { + *aor_separator = '\0'; + } + ast_assert(aor_separator != NULL); + + status->aor = ast_strdup(aor); + if (!status->aor) { + ao2_cleanup(status); + return NULL; + } return status; } @@ -98,12 +122,17 @@ struct ast_sip_contact_status *ast_res_pjsip_find_or_create_contact_status(const status = ast_sorcery_alloc(ast_sip_get_sorcery(), CONTACT_STATUS, ast_sorcery_object_get_id(contact)); if (!status) { - ast_log(LOG_ERROR, "Unable to create ast_sip_contact_status for contact %s\n", - contact->uri); + ast_log(LOG_ERROR, "Unable to create ast_sip_contact_status for contact %s/%s\n", + contact->aor, contact->uri); + return NULL; + } + + status->uri = ast_strdup(contact->uri); + if (!status->uri) { + ao2_cleanup(status); return NULL; } - status->status = UNKNOWN; status->rtt_start = ast_tv(0, 0); status->rtt = 0; @@ -127,8 +156,8 @@ struct ast_sip_contact_status *ast_res_pjsip_find_or_create_contact_status(const static void update_contact_status(const struct ast_sip_contact *contact, enum ast_sip_contact_status_type value) { - struct ast_sip_contact_status *status; - struct ast_sip_contact_status *update; + RAII_VAR(struct ast_sip_contact_status *, status, NULL, ao2_cleanup); + RAII_VAR(struct ast_sip_contact_status *, update, NULL, ao2_cleanup); status = ast_res_pjsip_find_or_create_contact_status(contact); if (!status) { @@ -145,6 +174,11 @@ static void update_contact_status(const struct ast_sip_contact *contact, return; } + update->uri = ast_strdup(contact->uri); + if (!update->uri) { + return; + } + update->last_status = status->status; update->status = value; if (update->last_status != update->status) { @@ -175,9 +209,6 @@ static void update_contact_status(const struct ast_sip_contact *contact, ast_log(LOG_ERROR, "Unable to update ast_sip_contact_status for contact %s\n", contact->uri); } - - ao2_ref(status, -1); - ao2_ref(update, -1); } /*! @@ -187,8 +218,8 @@ static void update_contact_status(const struct ast_sip_contact *contact, */ static void init_start_time(const struct ast_sip_contact *contact) { - struct ast_sip_contact_status *status; - struct ast_sip_contact_status *update; + RAII_VAR(struct ast_sip_contact_status *, status, NULL, ao2_cleanup); + RAII_VAR(struct ast_sip_contact_status *, update, NULL, ao2_cleanup); status = ast_res_pjsip_find_or_create_contact_status(contact); if (!status) { @@ -205,6 +236,11 @@ static void init_start_time(const struct ast_sip_contact *contact) return; } + update->uri = ast_strdup(contact->uri); + if (!update->uri) { + return; + } + update->status = status->status; update->last_status = status->last_status; update->rtt = status->rtt; @@ -214,9 +250,6 @@ static void init_start_time(const struct ast_sip_contact *contact) ast_log(LOG_ERROR, "Unable to update ast_sip_contact_status for contact %s\n", contact->uri); } - - ao2_ref(status, -1); - ao2_ref(update, -1); } /*! @@ -993,6 +1026,9 @@ static int rtt_start_to_str(const void *obj, const intptr_t *args, char **buf) return 0; } +static char status_value_unknown[2]; +static char status_value_created[2]; + int ast_sip_initialize_sorcery_qualify(void) { struct ast_sorcery *sorcery = ast_sip_get_sorcery(); @@ -1006,10 +1042,12 @@ int ast_sip_initialize_sorcery_qualify(void) return -1; } + snprintf(status_value_unknown, sizeof(status_value_unknown), "%u", UNKNOWN); ast_sorcery_object_field_register_nodoc(sorcery, CONTACT_STATUS, "last_status", - "0", OPT_UINT_T, 1, FLDSET(struct ast_sip_contact_status, last_status)); + status_value_unknown, OPT_UINT_T, 1, FLDSET(struct ast_sip_contact_status, last_status)); + snprintf(status_value_created, sizeof(status_value_created), "%u", CREATED); ast_sorcery_object_field_register_nodoc(sorcery, CONTACT_STATUS, "status", - "0", OPT_UINT_T, 1, FLDSET(struct ast_sip_contact_status, status)); + status_value_created, OPT_UINT_T, 1, FLDSET(struct ast_sip_contact_status, status)); ast_sorcery_object_field_register_custom_nodoc(sorcery, CONTACT_STATUS, "rtt_start", "0.0", rtt_start_handler, rtt_start_to_str, NULL, 0, 0); ast_sorcery_object_field_register_nodoc(sorcery, CONTACT_STATUS, "rtt", -- GitLab