Merge "res_pjsip: Update logging to show contact->uri in messages"

changes/61/1761/1
Joshua Colp 10 years ago committed by Gerrit Code Review
commit 268d21dee5

@ -159,6 +159,8 @@ struct ast_sip_contact {
AST_STRING_FIELD(path); AST_STRING_FIELD(path);
/*! Content of the User-Agent header in REGISTER request */ /*! Content of the User-Agent header in REGISTER request */
AST_STRING_FIELD(user_agent); AST_STRING_FIELD(user_agent);
/*! The name of the aor this contact belongs to */
AST_STRING_FIELD(aor);
); );
/*! Absolute time that this contact is no longer valid after */ /*! Absolute time that this contact is no longer valid after */
struct timeval expiration_time; struct timeval expiration_time;
@ -193,6 +195,12 @@ enum ast_sip_contact_status_type {
*/ */
struct ast_sip_contact_status { struct ast_sip_contact_status {
SORCERY_OBJECT(details); SORCERY_OBJECT(details);
AST_DECLARE_STRING_FIELDS(
/*! The original contact's URI */
AST_STRING_FIELD(uri);
/*! The name of the aor this contact_status belongs to */
AST_STRING_FIELD(aor);
);
/*! Current status for a contact (default - unavailable) */ /*! Current status for a contact (default - unavailable) */
enum ast_sip_contact_status_type status; enum ast_sip_contact_status_type status;
/*! The round trip start time set before sending a qualify request */ /*! The round trip start time set before sending a qualify request */

@ -99,6 +99,9 @@ static void contact_destroy(void *obj)
static void *contact_alloc(const char *name) static void *contact_alloc(const char *name)
{ {
struct ast_sip_contact *contact = ast_sorcery_generic_alloc(sizeof(*contact), contact_destroy); 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) { if (!contact) {
return NULL; return NULL;
@ -109,6 +112,14 @@ static void *contact_alloc(const char *name)
return NULL; 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);
ast_string_field_set(contact, aor, aor);
return contact; return contact;
} }
@ -790,13 +801,14 @@ static int cli_contact_print_body(void *obj, void *arg, int flags)
ast_assert(context->output_buffer != NULL); ast_assert(context->output_buffer != NULL);
indent = CLI_INDENT_TO_SPACES(context->indent_level); 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, indent,
"Contact", "Contact",
contact->aor,
flexwidth, flexwidth, flexwidth, flexwidth,
wrapper->contact_id, contact->uri,
ast_sip_get_contact_short_status_label(status ? status->status : UNKNOWN), ast_sip_get_contact_short_status_label(status ? status->status : UNKNOWN),
(status && (status->status != UNKNOWN) ? ((long long) status->rtt) / 1000.0 : NAN)); (status && (status->status != UNKNOWN) ? ((long long) status->rtt) / 1000.0 : NAN));

@ -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; 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 */ /*! \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 sip_persistent_endpoint *persistent = obj;
struct ast_endpoint *endpoint = persistent->endpoint; struct ast_endpoint *endpoint = persistent->endpoint;
char *aor = arg; struct ast_sip_contact_status *status = arg;
struct sip_contact_status *status = data;
struct ao2_container *contacts; struct ao2_container *contacts;
struct ast_json *blob; struct ast_json *blob;
struct ao2_iterator i; struct ao2_iterator i;
struct ast_sip_contact *contact; struct ast_sip_contact *contact;
enum ast_endpoint_state state = AST_ENDPOINT_OFFLINE; enum ast_endpoint_state state = AST_ENDPOINT_OFFLINE;
if (!ast_strlen_zero(aor)) { if (status) {
if (!strstr(persistent->aors, aor)) { char rtt[32];
/* If the status' aor isn't one of the endpoint's, we skip */
if (!strstr(persistent->aors, status->aor)) {
return 0; return 0;
} }
if (status) { snprintf(rtt, sizeof(rtt), "%" PRId64, status->rtt);
char rtt[32]; blob = ast_json_pack("{s: s, s: s, s: s, s: s, s: s}",
snprintf(rtt, 31, "%" PRId64, status->rtt); "contact_status", ast_sip_get_contact_status_label(status->status),
blob = ast_json_pack("{s: s, s: s, s: s, s: s, s: s}", "aor", status->aor,
"contact_status", ast_sip_get_contact_status_label(status->status), "uri", status->uri,
"aor", aor, "roundtrip_usec", rtt,
"uri", status->uri, "endpoint_name", ast_endpoint_get_resource(endpoint));
"roundtrip_usec", rtt, ast_endpoint_blob_publish(endpoint, ast_endpoint_contact_state_type(), blob);
"endpoint_name", ast_endpoint_get_resource(endpoint)); ast_json_unref(blob);
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, /* Find all the contacts for this endpoint. If ANY are available,
* mark the endpoint as ONLINE. * mark the endpoint as ONLINE.
*/ */
@ -142,57 +132,50 @@ static int persistent_endpoint_update_state(void *obj, void *arg, void *data, in
return 0; 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) static void persistent_endpoint_contact_created_observer(const void *object)
{ {
const struct ast_sip_contact *contact = object; const struct ast_sip_contact *contact = object;
char *id = ast_strdupa(ast_sorcery_object_get_id(contact)); struct ast_sip_contact_status *contact_status;
char *aor = NULL;
char *contact_uri = NULL; contact_status = ast_sorcery_alloc(ast_sip_get_sorcery(), CONTACT_STATUS,
struct sip_contact_status status; ast_sorcery_object_get_id(contact));
if (!contact_status) {
aor = id; ast_log(LOG_ERROR, "Unable to create ast_sip_contact_status for contact %s/%s\n",
/* Dynamic contacts are delimited with ";@" and static ones with "@@" */ contact->aor, contact->uri);
if ((contact_uri = strstr(id, ";@")) || (contact_uri = strstr(id, "@@"))) { return;
*contact_uri = '\0';
contact_uri += 2;
} else {
contact_uri = id;
} }
ast_string_field_set(contact_status, uri, contact->uri);
status.uri = contact_uri; contact_status->status = CREATED;
status.status = CREATED;
status.rtt = 0;
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) static void persistent_endpoint_contact_deleted_observer(const void *object)
{ {
char *id = ast_strdupa(ast_sorcery_object_get_id(object)); const struct ast_sip_contact *contact = object;
char *aor = NULL; struct ast_sip_contact_status *contact_status;
char *contact_uri = NULL;
struct sip_contact_status status;
aor = id; contact_status = ast_sorcery_alloc(ast_sip_get_sorcery(), CONTACT_STATUS,
/* Dynamic contacts are delimited with ";@" and static ones with "@@" */ ast_sorcery_object_get_id(contact));
if ((contact_uri = strstr(id, ";@")) || (contact_uri = strstr(id, "@@"))) { if (!contact_status) {
*contact_uri = '\0'; ast_log(LOG_ERROR, "Unable to create ast_sip_contact_status for contact %s/%s\n",
contact_uri += 2; contact->aor, contact->uri);
} else { return;
contact_uri = id;
} }
ast_string_field_set(contact_status, uri, contact->uri);
ast_verb(1, "Contact %s/%s has been deleted\n", aor, contact_uri); contact_status->status = REMOVED;
status.uri = contact_uri; ast_verb(1, "Contact %s/%s has been deleted\n", contact->aor, contact->uri);
status.status = REMOVED;
status.rtt = 0;
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 */ /*! \brief Observer for contacts so state can be updated on respective endpoints */
@ -201,36 +184,23 @@ static const struct ast_sorcery_observer state_contact_observer = {
.deleted = persistent_endpoint_contact_deleted_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) static void persistent_endpoint_contact_status_observer(const void *object)
{ {
const struct ast_sip_contact_status *contact_status = object; struct ast_sip_contact_status *contact_status = (struct ast_sip_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;
/* If rtt_start is set (this is the outgoing OPTIONS), ignore. */ /* If rtt_start is set (this is the outgoing OPTIONS), ignore. */
if (contact_status->rtt_start.tv_sec > 0) { if (contact_status->rtt_start.tv_sec > 0) {
return; 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) { if (contact_status->status == contact_status->last_status) {
ast_debug(3, "Contact %s status didn't change: %s, RTT: %.3f msec\n", ast_debug(3, "Contact %s/%s status didn't change: %s, RTT: %.3f msec\n",
contact_uri, ast_sip_get_contact_status_label(contact_status->status), contact_status->aor, contact_status->uri, ast_sip_get_contact_status_label(contact_status->status),
contact_status->rtt / 1000.0); contact_status->rtt / 1000.0);
return; return;
} else { } 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), ast_sip_get_contact_status_label(contact_status->status),
contact_status->rtt / 1000.0); contact_status->rtt / 1000.0);
} }
@ -241,11 +211,7 @@ static void persistent_endpoint_contact_status_observer(const void *object)
ast_sorcery_object_get_id(contact_status), ast_sorcery_object_get_id(contact_status),
ast_sip_get_contact_status_label(contact_status->status)); ast_sip_get_contact_status_label(contact_status->status));
status.uri = contact_uri; ao2_callback(persistent_endpoints, OBJ_NODATA, persistent_endpoint_update_state, contact_status);
status.status = contact_status->status;
status.rtt = contact_status->rtt;
ao2_callback_data(persistent_endpoints, OBJ_NODATA, persistent_endpoint_update_state, aor, &status);
} }
/*! \brief Observer for contacts so state can be updated on respective endpoints */ /*! \brief Observer for contacts so state can be updated on respective endpoints */
@ -1085,7 +1051,7 @@ static struct ast_endpoint *persistent_endpoint_find_or_create(const struct ast_
if (ast_strlen_zero(persistent->aors)) { if (ast_strlen_zero(persistent->aors)) {
ast_endpoint_set_state(persistent->endpoint, AST_ENDPOINT_UNKNOWN); ast_endpoint_set_state(persistent->endpoint, AST_ENDPOINT_UNKNOWN);
} else { } else {
persistent_endpoint_update_state(persistent, NULL, NULL, 0); persistent_endpoint_update_state(persistent, NULL, 0);
} }
ao2_link_flags(persistent_endpoints, persistent, OBJ_NOLOCK); ao2_link_flags(persistent_endpoints, persistent, OBJ_NOLOCK);

@ -42,7 +42,6 @@ static const char *status_map [] = {
[UNKNOWN] = "Unknown", [UNKNOWN] = "Unknown",
[CREATED] = "Created", [CREATED] = "Created",
[REMOVED] = "Removed", [REMOVED] = "Removed",
}; };
static const char *short_status_map [] = { static const char *short_status_map [] = {
@ -63,20 +62,47 @@ const char *ast_sip_get_contact_short_status_label(const enum ast_sip_contact_st
return short_status_map[status]; 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_string_field_free_memory(status);
}
/*! /*!
* \internal * \internal
* \brief Create a ast_sip_contact_status object. * \brief Create a ast_sip_contact_status object.
*/ */
static void *contact_status_alloc(const char *name) 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) { if (!status) {
ast_log(LOG_ERROR, "Unable to allocate ast_sip_contact_status\n"); ast_log(LOG_ERROR, "Unable to allocate ast_sip_contact_status\n");
return NULL; return NULL;
} }
status->status = UNKNOWN; if (ast_string_field_init(status, 256)) {
ast_log(LOG_ERROR, "Unable to allocate ast_sip_contact_status stringfields\n");
ao2_cleanup(status);
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);
ast_string_field_set(status, aor, aor);
status->status = CREATED;
return status; return status;
} }
@ -98,12 +124,12 @@ struct ast_sip_contact_status *ast_res_pjsip_find_or_create_contact_status(const
status = ast_sorcery_alloc(ast_sip_get_sorcery(), CONTACT_STATUS, status = ast_sorcery_alloc(ast_sip_get_sorcery(), CONTACT_STATUS,
ast_sorcery_object_get_id(contact)); ast_sorcery_object_get_id(contact));
if (!status) { if (!status) {
ast_log(LOG_ERROR, "Unable to create ast_sip_contact_status for contact %s\n", ast_log(LOG_ERROR, "Unable to create ast_sip_contact_status for contact %s/%s\n",
contact->uri); contact->aor, contact->uri);
return NULL; return NULL;
} }
status->status = UNKNOWN; ast_string_field_set(status, uri, contact->uri);
status->rtt_start = ast_tv(0, 0); status->rtt_start = ast_tv(0, 0);
status->rtt = 0; status->rtt = 0;
@ -127,8 +153,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, static void update_contact_status(const struct ast_sip_contact *contact,
enum ast_sip_contact_status_type value) enum ast_sip_contact_status_type value)
{ {
struct ast_sip_contact_status *status; RAII_VAR(struct ast_sip_contact_status *, status, NULL, ao2_cleanup);
struct ast_sip_contact_status *update; RAII_VAR(struct ast_sip_contact_status *, update, NULL, ao2_cleanup);
status = ast_res_pjsip_find_or_create_contact_status(contact); status = ast_res_pjsip_find_or_create_contact_status(contact);
if (!status) { if (!status) {
@ -145,6 +171,7 @@ static void update_contact_status(const struct ast_sip_contact *contact,
return; return;
} }
ast_string_field_set(update, uri, contact->uri);
update->last_status = status->status; update->last_status = status->status;
update->status = value; update->status = value;
if (update->last_status != update->status) { if (update->last_status != update->status) {
@ -175,9 +202,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", ast_log(LOG_ERROR, "Unable to update ast_sip_contact_status for contact %s\n",
contact->uri); contact->uri);
} }
ao2_ref(status, -1);
ao2_ref(update, -1);
} }
/*! /*!
@ -187,8 +211,8 @@ static void update_contact_status(const struct ast_sip_contact *contact,
*/ */
static void init_start_time(const struct ast_sip_contact *contact) static void init_start_time(const struct ast_sip_contact *contact)
{ {
struct ast_sip_contact_status *status; RAII_VAR(struct ast_sip_contact_status *, status, NULL, ao2_cleanup);
struct ast_sip_contact_status *update; RAII_VAR(struct ast_sip_contact_status *, update, NULL, ao2_cleanup);
status = ast_res_pjsip_find_or_create_contact_status(contact); status = ast_res_pjsip_find_or_create_contact_status(contact);
if (!status) { if (!status) {
@ -205,6 +229,7 @@ static void init_start_time(const struct ast_sip_contact *contact)
return; return;
} }
ast_string_field_set(status, uri, contact->uri);
update->status = status->status; update->status = status->status;
update->last_status = status->last_status; update->last_status = status->last_status;
update->rtt = status->rtt; update->rtt = status->rtt;
@ -214,9 +239,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", ast_log(LOG_ERROR, "Unable to update ast_sip_contact_status for contact %s\n",
contact->uri); contact->uri);
} }
ao2_ref(status, -1);
ao2_ref(update, -1);
} }
/*! /*!
@ -993,6 +1015,9 @@ static int rtt_start_to_str(const void *obj, const intptr_t *args, char **buf)
return 0; return 0;
} }
static char status_value_unknown[2];
static char status_value_created[2];
int ast_sip_initialize_sorcery_qualify(void) int ast_sip_initialize_sorcery_qualify(void)
{ {
struct ast_sorcery *sorcery = ast_sip_get_sorcery(); struct ast_sorcery *sorcery = ast_sip_get_sorcery();
@ -1006,10 +1031,12 @@ int ast_sip_initialize_sorcery_qualify(void)
return -1; return -1;
} }
snprintf(status_value_unknown, sizeof(status_value_unknown), "%u", UNKNOWN);
ast_sorcery_object_field_register_nodoc(sorcery, CONTACT_STATUS, "last_status", 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", 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", ast_sorcery_object_field_register_custom_nodoc(sorcery, CONTACT_STATUS, "rtt_start",
"0.0", rtt_start_handler, rtt_start_to_str, NULL, 0, 0); "0.0", rtt_start_handler, rtt_start_to_str, NULL, 0, 0);
ast_sorcery_object_field_register_nodoc(sorcery, CONTACT_STATUS, "rtt", ast_sorcery_object_field_register_nodoc(sorcery, CONTACT_STATUS, "rtt",

Loading…
Cancel
Save