summaryrefslogtreecommitdiff
path: root/res/res_pjsip
diff options
context:
space:
mode:
authorzuul <zuul@gerrit.asterisk.org>2016-07-13 07:28:31 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2016-07-13 07:28:31 -0500
commit8cea01ab1b3e07282487d7efe1888f290cc4280a (patch)
treec55f57bdc50621a0814ca6bbedd4871b54b11939 /res/res_pjsip
parent08f5f10f8f05b34f64c22545cb34b2eabbee7f0e (diff)
parent97b4c7a5b42eb84eaeaf9ec3f524de40e1d7fd74 (diff)
Merge "res_pjsip: Fix statsd regression." into 13
Diffstat (limited to 'res/res_pjsip')
-rw-r--r--res/res_pjsip/pjsip_configuration.c64
-rw-r--r--res/res_pjsip/pjsip_options.c79
2 files changed, 100 insertions, 43 deletions
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index deddddf02..ec3851bac 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -105,6 +105,40 @@ static void endpoint_update_state(struct ast_endpoint *endpoint, enum ast_endpoi
ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "PJSIP/%s", ast_endpoint_get_resource(endpoint));
}
+static void endpoint_publish_contact_status(struct ast_endpoint *endpoint, struct ast_sip_contact_status *contact)
+{
+ struct ast_json *blob;
+ char rtt[32];
+
+ snprintf(rtt, sizeof(rtt), "%" PRId64, contact->rtt);
+ blob = ast_json_pack("{s: s, s: s, s: s, s: s, s: s}",
+ "contact_status", ast_sip_get_contact_status_label(contact->status),
+ "aor", contact->aor,
+ "uri", contact->uri,
+ "roundtrip_usec", rtt,
+ "endpoint_name", ast_endpoint_get_resource(endpoint));
+ if (blob) {
+ ast_endpoint_blob_publish(endpoint, ast_endpoint_contact_state_type(), blob);
+ ast_json_unref(blob);
+ }
+}
+
+/*! \brief Callback function for publishing the status of an endpoint */
+static int persistent_endpoint_publish_status(void *obj, void *arg, int flags)
+{
+ struct sip_persistent_endpoint *persistent = obj;
+ struct ast_endpoint *endpoint = persistent->endpoint;
+ struct ast_sip_contact_status *status = arg;
+
+ /* If the status' aor isn't one of the endpoint's, we skip */
+ if (!strstr(persistent->aors, status->aor)) {
+ return 0;
+ }
+
+ endpoint_publish_contact_status(endpoint, status);
+ return 0;
+}
+
/*! \brief Callback function for changing the state of an endpoint */
static int persistent_endpoint_update_state(void *obj, void *arg, int flags)
{
@@ -112,30 +146,17 @@ static int persistent_endpoint_update_state(void *obj, void *arg, int flags)
struct ast_endpoint *endpoint = persistent->endpoint;
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 (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;
- }
-
- 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);
+ /* If the status' aor isn't one of the endpoint's, we skip */
+ if (!strstr(persistent->aors, status->aor)) {
+ return 0;
}
+ endpoint_publish_contact_status(endpoint, status);
+
/* Find all the contacts for this endpoint. If ANY are available,
* mark the endpoint as ONLINE.
*/
@@ -225,6 +246,13 @@ static void persistent_endpoint_contact_status_observer(const void *object)
{
struct ast_sip_contact_status *contact_status = (struct ast_sip_contact_status *)object;
+ if (contact_status->refresh) {
+ /* We are only re-publishing the contact status. */
+ ao2_callback(persistent_endpoints, OBJ_NODATA,
+ persistent_endpoint_publish_status, contact_status);
+ return;
+ }
+
/* If rtt_start is set (this is the outgoing OPTIONS), ignore. */
if (contact_status->rtt_start.tv_sec > 0) {
return;
diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c
index e220f90e4..7b37a7a18 100644
--- a/res/res_pjsip/pjsip_options.c
+++ b/res/res_pjsip/pjsip_options.c
@@ -43,7 +43,6 @@ static const char *status_map [] = {
[UNKNOWN] = "Unknown",
[CREATED] = "Created",
[REMOVED] = "Removed",
- [UPDATED] = "Updated",
};
static const char *short_status_map [] = {
@@ -52,7 +51,6 @@ static const char *short_status_map [] = {
[UNKNOWN] = "Unknown",
[CREATED] = "Created",
[REMOVED] = "Removed",
- [UPDATED] = "Updated",
};
const char *ast_sip_get_contact_status_label(const enum ast_sip_contact_status_type status)
@@ -160,7 +158,7 @@ struct ast_sip_contact_status *ast_res_pjsip_find_or_create_contact_status(const
* \brief Update an ast_sip_contact_status's elements.
*/
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, int is_contact_refresh)
{
RAII_VAR(struct ast_sip_contact_status *, status, NULL, ao2_cleanup);
RAII_VAR(struct ast_sip_contact_status *, update, NULL, ao2_cleanup);
@@ -172,6 +170,26 @@ static void update_contact_status(const struct ast_sip_contact *contact,
return;
}
+ if (is_contact_refresh
+ && status->status == CREATED) {
+ /*
+ * The contact status hasn't been updated since creation
+ * and we don't want to re-send a created status.
+ */
+ if (contact->qualify_frequency
+ || status->rtt_start.tv_sec > 0) {
+ /* Ignore, the status will change soon. */
+ return;
+ }
+
+ /*
+ * Convert to a regular contact status update
+ * because the status may never change.
+ */
+ is_contact_refresh = 0;
+ value = UNKNOWN;
+ }
+
update = ast_sorcery_alloc(ast_sip_get_sorcery(), CONTACT_STATUS,
ast_sorcery_object_get_id(status));
if (!update) {
@@ -185,22 +203,34 @@ static void update_contact_status(const struct ast_sip_contact *contact,
return;
}
- update->last_status = status->status;
- update->status = value;
+ if (is_contact_refresh) {
+ /* Copy everything just to set the refresh flag. */
+ update->status = status->status;
+ update->last_status = status->last_status;
+ update->rtt = status->rtt;
+ update->rtt_start = status->rtt_start;
+ update->refresh = 1;
+ } else {
+ update->last_status = status->status;
+ update->status = value;
- /* if the contact is available calculate the rtt as
- the diff between the last start time and "now" */
- update->rtt = update->status == AVAILABLE && status->rtt_start.tv_sec > 0 ?
- ast_tvdiff_us(ast_tvnow(), status->rtt_start) : 0;
- update->rtt_start = ast_tv(0, 0);
+ /*
+ * if the contact is available calculate the rtt as
+ * the diff between the last start time and "now"
+ */
+ update->rtt = update->status == AVAILABLE && status->rtt_start.tv_sec > 0
+ ? ast_tvdiff_us(ast_tvnow(), status->rtt_start)
+ : 0;
+ update->rtt_start = ast_tv(0, 0);
- ast_test_suite_event_notify("AOR_CONTACT_QUALIFY_RESULT",
- "Contact: %s\r\n"
- "Status: %s\r\n"
- "RTT: %" PRId64,
- ast_sorcery_object_get_id(update),
- ast_sip_get_contact_status_label(update->status),
- update->rtt);
+ ast_test_suite_event_notify("AOR_CONTACT_QUALIFY_RESULT",
+ "Contact: %s\r\n"
+ "Status: %s\r\n"
+ "RTT: %" PRId64,
+ ast_sorcery_object_get_id(update),
+ ast_sip_get_contact_status_label(update->status),
+ update->rtt);
+ }
if (ast_sorcery_update(ast_sip_get_sorcery(), update)) {
ast_log(LOG_ERROR, "Unable to update ast_sip_contact_status for contact %s\n",
@@ -317,10 +347,10 @@ static void qualify_contact_cb(void *token, pjsip_event *e)
/* Fall through */
case PJSIP_EVENT_TRANSPORT_ERROR:
case PJSIP_EVENT_TIMER:
- update_contact_status(contact, UNAVAILABLE);
+ update_contact_status(contact, UNAVAILABLE, 0);
break;
case PJSIP_EVENT_RX_MSG:
- update_contact_status(contact, AVAILABLE);
+ update_contact_status(contact, AVAILABLE, 0);
break;
}
ao2_cleanup(contact);
@@ -376,7 +406,7 @@ static int qualify_contact(struct ast_sip_endpoint *endpoint, struct ast_sip_con
!= PJ_SUCCESS) {
ast_log(LOG_ERROR, "Unable to send request to qualify contact %s\n",
contact->uri);
- update_contact_status(contact, UNAVAILABLE);
+ update_contact_status(contact, UNAVAILABLE, 0);
ao2_ref(contact, -1);
return -1;
}
@@ -536,7 +566,7 @@ static void qualify_and_schedule(struct ast_sip_contact *contact)
schedule_qualify(contact, contact->qualify_frequency * 1000);
} else {
- update_contact_status(contact, UNKNOWN);
+ update_contact_status(contact, UNKNOWN, 0);
}
}
@@ -555,8 +585,7 @@ static void contact_created(const void *obj)
*/
static void contact_updated(const void *obj)
{
- update_contact_status((struct ast_sip_contact *) obj, UPDATED);
- qualify_and_schedule((struct ast_sip_contact *) obj);
+ update_contact_status(obj, AVAILABLE, 1);
}
/*!
@@ -585,8 +614,8 @@ static void contact_deleted(const void *obj)
static const struct ast_sorcery_observer contact_observer = {
.created = contact_created,
+ .updated = contact_updated,
.deleted = contact_deleted,
- .updated = contact_updated
};
static pj_bool_t options_start(void)
@@ -1062,7 +1091,7 @@ static void qualify_and_schedule_contact(struct ast_sip_contact *contact)
if (contact->qualify_frequency) {
schedule_qualify(contact, initial_interval);
} else {
- update_contact_status(contact, UNKNOWN);
+ update_contact_status(contact, UNKNOWN, 0);
}
}