[Asterisk-code-review] res pjsip: Add AMI events for chan pjsip contact lifecycle c... (asterisk[13])
George Joseph
asteriskteam at digium.com
Thu May 21 17:27:29 CDT 2015
George Joseph has uploaded a new change for review.
https://gerrit.asterisk.org/510
Change subject: res_pjsip: Add AMI events for chan_pjsip contact lifecycle changes
......................................................................
res_pjsip: Add AMI events for chan_pjsip contact lifecycle changes
Add a new ContactStatus AMI event.
Publish the following status/state changes:
Created
Removed
Reachable
Unreachable
Unknown
Contact URI, new status/state, aor and endpoint names, and the
last qualify rtt result are included in the event.
ASTERISK-25224 #close
Change-Id: I6d3e288f89bc55e9adbaa7b2c9f9feed4701e2e7
Reported-by: George Joseph <george.joseph at fairview5.com>
Tested-by: George Joseph <george.joseph at fairview5.com>
---
M include/asterisk/res_pjsip.h
M include/asterisk/stasis_endpoints.h
M main/manager_endpoints.c
M main/stasis_endpoints.c
M res/res_pjsip/pjsip_configuration.c
M res/res_pjsip/pjsip_options.c
6 files changed, 147 insertions(+), 16 deletions(-)
git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/10/510/1
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index cbae595..d91fe18 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -178,7 +178,9 @@
enum ast_sip_contact_status_type {
UNAVAILABLE,
AVAILABLE,
- UNKNOWN
+ UNKNOWN,
+ CREATED,
+ REMOVED,
};
/*!
diff --git a/include/asterisk/stasis_endpoints.h b/include/asterisk/stasis_endpoints.h
index 1d56a8f..539f270 100644
--- a/include/asterisk/stasis_endpoints.h
+++ b/include/asterisk/stasis_endpoints.h
@@ -119,6 +119,12 @@
struct stasis_message_type *ast_endpoint_state_type(void);
/*!
+ * \brief Message type for endpoint contact state changes.
+ * \since 13.5
+ */
+struct stasis_message_type *ast_endpoint_contact_state_type(void);
+
+/*!
* \brief Message type for \ref ast_endpoint_snapshot.
* \since 12
*/
diff --git a/main/manager_endpoints.c b/main/manager_endpoints.c
index 0d08660..b2a4573 100644
--- a/main/manager_endpoints.c
+++ b/main/manager_endpoints.c
@@ -75,6 +75,7 @@
}
ret |= stasis_message_router_add(endpoint_router, ast_endpoint_state_type(), endpoint_state_cb, NULL);
+ ret |= stasis_message_router_add(endpoint_router, ast_endpoint_contact_state_type(), endpoint_state_cb, NULL);
/* If somehow we failed to add any routes, just shut down the whole
* thing and fail it.
diff --git a/main/stasis_endpoints.c b/main/stasis_endpoints.c
index 7374681..e0d0878 100644
--- a/main/stasis_endpoints.c
+++ b/main/stasis_endpoints.c
@@ -71,6 +71,35 @@
</syntax>
</managerEventInstance>
</managerEvent>
+ <managerEvent language="en_US" name="ContactStatus">
+ <managerEventInstance class="EVENT_FLAG_SYSTEM">
+ <synopsis>Raised when the state of a contact changes.</synopsis>
+ <syntax>
+ <parameter name="URI">
+ <para>This contact's URI.</para>
+ </parameter>
+ <parameter name="ContactStatus">
+ <para>New status of the contact.</para>
+ <enumlist>
+ <enum name="Unknown"/>
+ <enum name="Unreachable"/>
+ <enum name="Reachable"/>
+ <enum name="Created"/>
+ <enum name="Removed"/>
+ </enumlist>
+ </parameter>
+ <parameter name="AOR">
+ <para>The name of the associated aor.</para>
+ </parameter>
+ <parameter name="EndpointName">
+ <para>The name of the associated endpoint.</para>
+ </parameter>
+ <parameter name="RoundtripUsec">
+ <para>The RTT measured during the last qualify.</para>
+ </parameter>
+ </syntax>
+ </managerEventInstance>
+ </managerEvent>
***/
static struct stasis_cp_all *endpoint_cache_all;
@@ -135,6 +164,46 @@
obj->snapshot->tech,
obj->snapshot->resource,
ast_str_buffer(peerstatus_event_string));
+}
+
+static struct ast_manager_event_blob *contactstatus_to_ami(struct stasis_message *msg);
+
+STASIS_MESSAGE_TYPE_DEFN(ast_endpoint_contact_state_type,
+ .to_ami = contactstatus_to_ami,
+);
+
+static struct ast_manager_event_blob *contactstatus_to_ami(struct stasis_message *msg)
+{
+ struct ast_endpoint_blob *obj = stasis_message_data(msg);
+ RAII_VAR(struct ast_str *, contactstatus_event_string, ast_str_create(64), ast_free);
+ const char *value;
+
+ if (!(value = ast_json_string_get(ast_json_object_get(obj->blob, "uri")))) {
+ return NULL;
+ }
+ ast_str_append(&contactstatus_event_string, 0, "URI: %s\r\n", value);
+
+ if (!(value = ast_json_string_get(ast_json_object_get(obj->blob, "contact_status")))) {
+ return NULL;
+ }
+ ast_str_append(&contactstatus_event_string, 0, "ContactStatus: %s\r\n", value);
+
+ if (!(value = ast_json_string_get(ast_json_object_get(obj->blob, "aor")))) {
+ return NULL;
+ }
+ ast_str_append(&contactstatus_event_string, 0, "AOR: %s\r\n", value);
+
+ if (!(value = ast_json_string_get(ast_json_object_get(obj->blob, "endpoint_name")))) {
+ return NULL;
+ }
+ ast_str_append(&contactstatus_event_string, 0, "EndpointName: %s\r\n", value);
+
+ if ((value = ast_json_string_get(ast_json_object_get(obj->blob, "roundtrip_usec")))) {
+ ast_str_append(&contactstatus_event_string, 0, "RoundtripUsec: %s\r\n", value);
+ }
+
+ return ast_manager_event_blob_create(EVENT_FLAG_SYSTEM, "ContactStatus",
+ "%s", ast_str_buffer(contactstatus_event_string));
}
static void endpoint_blob_dtor(void *obj)
@@ -294,6 +363,7 @@
{
STASIS_MESSAGE_TYPE_CLEANUP(ast_endpoint_snapshot_type);
STASIS_MESSAGE_TYPE_CLEANUP(ast_endpoint_state_type);
+ STASIS_MESSAGE_TYPE_CLEANUP(ast_endpoint_contact_state_type);
ao2_cleanup(endpoint_cache_all);
endpoint_cache_all = NULL;
@@ -312,6 +382,7 @@
res |= STASIS_MESSAGE_TYPE_INIT(ast_endpoint_snapshot_type);
res |= STASIS_MESSAGE_TYPE_INIT(ast_endpoint_state_type);
+ res |= STASIS_MESSAGE_TYPE_INIT(ast_endpoint_contact_state_type);
return res;
}
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 42f16d2..8ffe221 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -56,22 +56,48 @@
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;
+ int no_process;
+};
+
/*! \brief Callback function for changing the state of an endpoint */
-static int persistent_endpoint_update_state(void *obj, void *arg, int flags)
+static int persistent_endpoint_update_state(void *obj, void *arg, void *data, int flags)
{
struct sip_persistent_endpoint *persistent = obj;
struct ast_endpoint *endpoint = persistent->endpoint;
char *aor = arg;
+ struct sip_contact_status *status = data;
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) && !strstr(persistent->aors, aor)) {
- return 0;
- }
+ if (!ast_strlen_zero(aor)) {
+ if (!strstr(persistent->aors, aor)) {
+ return 0;
+ }
+ if (status) {
+ char rtt[32];
+ snprintf(rtt, 31, "%ld", 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);
+ }
+ }
/* Find all the contacts for this endpoint. If ANY are available,
* mark the endpoint as ONLINE.
*/
@@ -122,10 +148,14 @@
static void persistent_endpoint_contact_created_observer(const void *object)
{
char *id = ast_strdupa(ast_sorcery_object_get_id(object)), *aor = NULL;
+ struct sip_contact_status status;
aor = strsep(&id, ";@");
+ status.uri = strsep(&id, ";@");
+ status.status = CREATED;
+ status.rtt = 0;
- ao2_callback(persistent_endpoints, OBJ_NODATA, persistent_endpoint_update_state, aor);
+ ao2_callback_data(persistent_endpoints, OBJ_NODATA, persistent_endpoint_update_state, aor, &status);
}
/*! \brief Function called when stuff relating to a contact happens (created/deleted) */
@@ -134,6 +164,7 @@
char *id = ast_strdupa(ast_sorcery_object_get_id(object));
char *aor = NULL;
char *contact = NULL;
+ struct sip_contact_status status;
aor = id;
/* Dynamic contacts are delimited with ";@" and static ones with "@@" */
@@ -146,7 +177,11 @@
ast_verb(1, "Contact %s/%s is now Unavailable\n", aor, contact);
- ao2_callback(persistent_endpoints, OBJ_NODATA, persistent_endpoint_update_state, aor);
+ status.uri = contact;
+ status.status = REMOVED;
+ status.rtt = 0;
+
+ 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 */
@@ -162,12 +197,11 @@
char *id = ast_strdupa(ast_sorcery_object_get_id(object));
char *aor = NULL;
char *contact = NULL;
+ struct sip_contact_status status;
+ status.no_process = 0;
- /* If rtt_start is set (this is the outgoing OPTIONS) or
- * there's no status change, ignore.
- */
- if (contact_status->rtt_start.tv_sec > 0
- || contact_status->status == contact_status->last_status) {
+ /* If rtt_start is set (this is the outgoing OPTIONS), ignore. */
+ if (contact_status->rtt_start.tv_sec > 0) {
return;
}
@@ -180,16 +214,28 @@
contact = id;
}
+ if (contact_status->status == contact_status->last_status) {
+ ast_debug(3, "Contact %s status didn't change: %s, RTT: %.3f msec\n",
+ contact, 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,
+ ast_sip_get_contact_status_label(contact_status->status),
+ contact_status->rtt / 1000.0);
+ }
+
ast_test_suite_event_notify("AOR_CONTACT_UPDATE",
"Contact: %s\r\n"
"Status: %s",
ast_sorcery_object_get_id(contact_status),
ast_sip_get_contact_status_label(contact_status->status));
- ast_verb(1, "Contact %s/%s is now %s\n", aor, contact,
- ast_sip_get_contact_status_label(contact_status->status));
+ status.uri = contact;
+ status.status = contact_status->status;
+ status.rtt = contact_status->rtt;
- ao2_callback(persistent_endpoints, OBJ_NODATA, persistent_endpoint_update_state, aor);
+ 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 */
@@ -1014,7 +1060,7 @@
if (ast_strlen_zero(persistent->aors)) {
ast_endpoint_set_state(persistent->endpoint, AST_ENDPOINT_UNKNOWN);
} else {
- persistent_endpoint_update_state(persistent, NULL, 0);
+ persistent_endpoint_update_state(persistent, NULL, 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 8ffb88c..bc1e1ec 100644
--- a/res/res_pjsip/pjsip_options.c
+++ b/res/res_pjsip/pjsip_options.c
@@ -39,12 +39,17 @@
[UNAVAILABLE] = "Unreachable",
[AVAILABLE] = "Reachable",
[UNKNOWN] = "Unknown",
+ [CREATED] = "Created",
+ [REMOVED] = "Removed",
+
};
static const char *short_status_map [] = {
[UNAVAILABLE] = "Unavail",
[AVAILABLE] = "Avail",
[UNKNOWN] = "Unknown",
+ [CREATED] = "Created",
+ [REMOVED] = "Removed",
};
const char *ast_sip_get_contact_status_label(const enum ast_sip_contact_status_type status)
--
To view, visit https://gerrit.asterisk.org/510
To unsubscribe, visit https://gerrit.asterisk.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I6d3e288f89bc55e9adbaa7b2c9f9feed4701e2e7
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: 13
Gerrit-Owner: George Joseph <george.joseph at fairview5.com>
More information about the asterisk-code-review
mailing list