[asterisk-commits] kharwell: branch kharwell/pimp_sip_state r388428 - in /team/kharwell/pimp_sip...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri May 10 17:16:16 CDT 2013


Author: kharwell
Date: Fri May 10 17:16:14 2013
New Revision: 388428

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=388428
Log:
addressed review issues. still need to look into suggestion about using pjsip for creating pidf body

Modified:
    team/kharwell/pimp_sip_state/include/asterisk/res_sip_exten_state.h
    team/kharwell/pimp_sip_state/include/asterisk/res_sip_pubsub.h
    team/kharwell/pimp_sip_state/res/res_sip_exten_state.c
    team/kharwell/pimp_sip_state/res/res_sip_providers/include/res_sip_providers.h
    team/kharwell/pimp_sip_state/res/res_sip_providers/res_sip_pidf.c

Modified: team/kharwell/pimp_sip_state/include/asterisk/res_sip_exten_state.h
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_state/include/asterisk/res_sip_exten_state.h?view=diff&rev=388428&r1=388427&r2=388428
==============================================================================
--- team/kharwell/pimp_sip_state/include/asterisk/res_sip_exten_state.h (original)
+++ team/kharwell/pimp_sip_state/include/asterisk/res_sip_exten_state.h Fri May 10 17:16:14 2013
@@ -21,39 +21,51 @@
 
 #include "asterisk/stringfields.h"
 #include "asterisk/linkedlists.h"
+
+#include "asterisk/pbx.h"
 #include "asterisk/presencestate.h"
 
-struct ast_exten_state {
+/*!
+ * \brief Contains information pertaining to extension/device state changes.
+ */
+struct ast_sip_exten_state_data {
 	/*! The extension of the current state change */
 	const char *exten;
 	/*! The extension state of the change */
-	int exten_state;
+	enum ast_extension_states exten_state;
 	/*! The presence state of the change */
 	enum ast_presence_state presence_state;
 	/*! Current device state information */
-	struct ao2_container *device_state;
+	struct ao2_container *device_state_info;
 };
 
 /*!
  * \brief Extension state provider.
  */
-struct ast_exten_state_provider {
+struct ast_sip_exten_state_provider {
 	/*! The name of the event this provider registers for */
 	const char *event_name;
-	/*! The type of body this provider accepts */
-	const char *accept;
+	/*! Type of the body, ex: "application" */
+	const char *type;
+	/*! Subtype of the body, ex: "pidf+xml" */
+	const char *subtype;
 
 	/*!
 	 * \brief Create the body text of a NOTIFY request.
 	 *
 	 * Implementors use this to create body information within the given
 	 * ast_str.  That information is then added to the NOTIFY request.
+	 *
+	 * \param data Current extension state changes
+	 * \param local URI of the dialog's local party, e.g. 'from'
+	 * \param remote URI of the dialog's remote party, e.g. 'to'
+	 * \param body_text Out parameter used to populate the NOTIFY msg body
 	 */
-	void (*create_body)(struct ast_exten_state *data, const char *local,
-			    const char *remote,struct ast_str **body_text);
+	int (*create_body)(struct ast_sip_exten_state_data *data, const char *local,
+			   const char *remote, struct ast_str **body_text);
 
 	/*! Next item in the list */
-	AST_LIST_ENTRY(ast_exten_state_provider) next;
+	AST_LIST_ENTRY(ast_sip_exten_state_provider) next;
 };
 
 #endif

Modified: team/kharwell/pimp_sip_state/include/asterisk/res_sip_pubsub.h
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_state/include/asterisk/res_sip_pubsub.h?view=diff&rev=388428&r1=388427&r2=388428
==============================================================================
--- team/kharwell/pimp_sip_state/include/asterisk/res_sip_pubsub.h (original)
+++ team/kharwell/pimp_sip_state/include/asterisk/res_sip_pubsub.h Fri May 10 17:16:14 2013
@@ -276,7 +276,7 @@
  * \retval non-NULL The underlying pjsip_dialog
  */
 pjsip_dialog *ast_sip_subscription_get_dlg(struct ast_sip_subscription *sub);
- 
+
 /*!
  * \brief Send a request created via a PJSIP evsub method
  *

Modified: team/kharwell/pimp_sip_state/res/res_sip_exten_state.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_state/res/res_sip_exten_state.c?view=diff&rev=388428&r1=388427&r2=388428
==============================================================================
--- team/kharwell/pimp_sip_state/res/res_sip_exten_state.c (original)
+++ team/kharwell/pimp_sip_state/res/res_sip_exten_state.c Fri May 10 17:16:14 2013
@@ -37,22 +37,44 @@
 #include "asterisk/astobj2.h"
 #include "asterisk/sorcery.h"
 #include "asterisk/app.h"
-#include "asterisk/pbx.h"
 #include "res_sip_providers/include/res_sip_providers.h"
 
-AST_RWLIST_HEAD_STATIC(providers, ast_exten_state_provider);
-
-static int register_exten_state_provider(struct ast_exten_state_provider *obj)
+#define BODY_SIZE 1024
+#define BODY_TYPE_SIZE 50
+#define EVENT_TYPE_SIZE 50
+
+AST_RWLIST_HEAD_STATIC(providers, ast_sip_exten_state_provider);
+
+static int register_sip_exten_state_provider(struct ast_sip_exten_state_provider *obj)
 {
 	SCOPED_LOCK(lock, &providers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
+
+	if (ast_strlen_zero(obj->type)) {
+		ast_log(LOG_WARNING, "Type not specified on provider for event %s\n",
+			obj->event_name);
+		return -1;
+	}
+
+	if (ast_strlen_zero(obj->subtype)) {
+		ast_log(LOG_WARNING, "Subtype not specified on provider for event %s\n",
+			obj->event_name);
+		return -1;
+	}
+
+	if (!obj->create_body) {
+		ast_log(LOG_WARNING, "Body handler not specified on provide for event %s\n",
+		    obj->event_name);
+		return -1;
+	}
+	
 	AST_RWLIST_INSERT_TAIL(&providers, obj, next);
 	ast_module_ref(ast_module_info->self);
 	return 0;
 }
 
-static void unregister_exten_state_provider(struct ast_exten_state_provider *obj)
-{
-	struct ast_exten_state_provider *i;
+static void unregister_sip_exten_state_provider(struct ast_sip_exten_state_provider *obj)
+{
+	struct ast_sip_exten_state_provider *i;
 	SCOPED_LOCK(lock, &providers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
 	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&providers, i, next) {
 		if (i == obj) {
@@ -68,12 +90,14 @@
  * \internal
  * \brief Find a provider based on the given accept type.
  */
-static struct ast_exten_state_provider *provider_by_accept(const char *accept)
-{
-	struct ast_exten_state_provider *i;
-	SCOPED_LOCK(lock, &providers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
+static struct ast_sip_exten_state_provider *provider_by_accept(const char *accept)
+{
+	struct ast_str *type = ast_str_alloca(BODY_TYPE_SIZE);
+	struct ast_sip_exten_state_provider *i;
+	SCOPED_LOCK(lock, &providers, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
 	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&providers, i, next) {
-		if (!strcmp(i->accept, accept)) {
+		ast_str_set(&type, -1, "%s/%s", i->type, i->subtype);
+		if (!strcmp(ast_str_buffer(type), accept)) {
 			return i;
 		}
 	}
@@ -83,18 +107,16 @@
 
 /*!
  * \internal
- * \brief Find a provider based on a given message accept type.
+ * \brief Find a provider based on a given message body's type/subtype.
  *
  * Attempts to locate accept headers in the given request data. If found
  * tries to find a provider for the accept type.
  */
-static struct ast_exten_state_provider *provider_by_req(pjsip_rx_data *rdata)
+static struct ast_sip_exten_state_provider *provider_by_req(pjsip_rx_data *rdata)
 {
 	int i;
-	char type[50];
 	pjsip_accept_hdr *hdr = (pjsip_accept_hdr*)
 		pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_ACCEPT, NULL);
-	struct ast_exten_state_provider *res;
 
 	if (!hdr) {
 		ast_log(LOG_WARNING, "No Accept header found in subscribe\n");
@@ -102,6 +124,9 @@
 	}
 
 	for (i = 0; i < hdr->count; ++i) {
+		struct ast_sip_exten_state_provider *res;
+		char type[BODY_TYPE_SIZE];
+
 		ast_copy_pj_str(type, &hdr->values[i], sizeof(type));
 		if ((res = provider_by_accept(type))) {
 			return res;
@@ -139,38 +164,38 @@
  * also keeps a pointer to an associated "provider" so when a state changes
  * a notify data creator is quickly accessible.
  */
-struct state_sub {
+struct exten_state_subscription {
 	/*! Watcher id when registering for extension state changes */
 	int id;
 	/*! The SIP subscription */
 	struct ast_sip_subscription *sip_sub;
 	/*! The notify data creator */
-	struct ast_exten_state_provider *provider;
+	struct ast_sip_exten_state_provider *provider;
 	/*! Context in which subscription looks for updates */
-	const char *context;
+	char context[AST_MAX_CONTEXT];
 	/*! Extension within the context to receive updates from */
 	char exten[AST_MAX_EXTENSION];
 	/*! pjsip state for NOTIFY request */
-	pjsip_evsub_state state;
+	pjsip_evsub_state evsub_state;
 };
 
-static void state_sub_destructor(void *obj)
-{
-	struct state_sub *sub = obj;
+static void exten_state_subscription_destructor(void *obj)
+{
+	struct exten_state_subscription *sub = obj;
 	ao2_cleanup(sub->sip_sub);
 }
 
 /*!
  * \internal
- * \brief Find a subscription handler based on a given event type.
+ * \brief Find a subscription handler based on a given message's event type.
  *
  * Attempts to locate an event header in the given request data. If found
  * tries to find a subscription handler for the event type.
  */
 static struct ast_sip_subscription_handler *sub_handler_by_req(pjsip_rx_data *rdata)
 {
-	char type[25];
-	pj_str_t event_name = { "Event", 5 };
+	char type[EVENT_TYPE_SIZE];
+	static const pj_str_t event_name = { "Event", 5 };
 	pjsip_event_hdr *hdr = (pjsip_event_hdr*)
 		pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &event_name, NULL);
 
@@ -181,83 +206,73 @@
 
 	ast_copy_pj_str(type, &hdr->event_type, sizeof(type));
 
-	return (struct ast_sip_subscription_handler*)
-		ao2_find(sub_handlers, type, OBJ_KEY | OBJ_NOLOCK);
-}
-
-/*!
- * \internal
- * \brief Allocates an state_sub object.
+	return ao2_find(sub_handlers, type, OBJ_KEY | OBJ_NOLOCK);
+}
+
+/*!
+ * \internal
+ * \brief Allocates a exten_state_subscription object.
  *
  * Creates the underlying SIP subscription for the given request. First makes
  * sure that there are registered handler and provider objects available.
  */
-static struct state_sub *state_sub_alloc(struct ast_sip_endpoint *endpoint,
-		enum ast_sip_subscription_role role, pjsip_rx_data *rdata)
+static struct exten_state_subscription *exten_state_subscription_alloc(
+	struct ast_sip_endpoint *endpoint, enum ast_sip_subscription_role role, pjsip_rx_data *rdata)
 {
 	struct ast_sip_subscription_handler *handler;
-	struct state_sub *ssub;
-
-	if (!(ssub = ao2_alloc(sizeof(*ssub), state_sub_destructor))) {
+	RAII_VAR(struct exten_state_subscription *, exten_state_sub,
+		 ao2_alloc(sizeof(*exten_state_sub), exten_state_subscription_destructor), ao2_cleanup);
+
+	if (!exten_state_sub) {
 		return NULL;
 	}
 
 	if (!(handler = sub_handler_by_req(rdata))) {
 		ast_log(LOG_WARNING, "Handler not found for subscription event\n");
-		ao2_cleanup(ssub);
-		return NULL;
-	}
-
-	if (!(ssub->provider = provider_by_req(rdata))) {
+		return NULL;
+	}
+
+	if (!(exten_state_sub->provider = provider_by_req(rdata))) {
 		ast_log(LOG_WARNING, "Unable to locate subscription handler provider\n");
-		ao2_cleanup(ssub);
-		return NULL;
-	}
-
-	if (!(ssub->sip_sub = ast_sip_create_subscription(handler, role, endpoint, rdata))) {
+		return NULL;
+	}
+
+	if (!(exten_state_sub->sip_sub = ast_sip_create_subscription(handler, role, endpoint, rdata))) {
 		ast_log(LOG_WARNING, "Unable to create SIP subscription for endpoint %s\n",
 			ast_sorcery_object_get_id(endpoint));
-		ao2_cleanup(ssub);
-		return NULL;
-	}
-
-	return ssub;
+		return NULL;
+	}
+
+	ao2_ref(exten_state_sub, +1);
+	return exten_state_sub;
 }
 
 /*!
  * \internal
  * \brief Create and send a NOTIFY request to the subscriber.
  */
-static void create_send_notify(struct state_sub *ssub, const char *reason,
-			       struct ast_exten_state *data)
-{
-	RAII_VAR(struct ast_str *, body_text, ast_str_create(1024), ast_free_ptr);
+static void create_send_notify(struct exten_state_subscription *exten_state_sub, const char *reason,
+			       struct ast_sip_exten_state_data *exten_state_data)
+{
+	RAII_VAR(struct ast_str *, body_text, ast_str_create(BODY_SIZE), ast_free_ptr);
 	pj_str_t reason_str;
 	const pj_str_t *reason_str_ptr = NULL;
 	pjsip_tx_data *tdata;
 	pjsip_dialog *dlg;
-	struct ast_sip_body body;
-	char type[50], local[256], remote[256];
-
-	if (!(body.subtype = strchr(ssub->provider->accept, '/'))) {
-		ast_log(LOG_WARNING, "Subtype not specified for provider\n");
-		return;
-	}
-
-	ast_copy_string(type, ssub->provider->accept,
-			++body.subtype - ssub->provider->accept);
-	body.type = type;
-
-	if (!ssub->provider->create_body) {
-		ast_log(LOG_WARNING, "Body handler not specified for provider\n");
-		return;
-	}
-
-	dlg = ast_sip_subscription_get_dlg(ssub->sip_sub);
+	char local[256], remote[256];
+	struct ast_sip_body body = {
+		.type = exten_state_sub->provider->type,
+		.subtype = exten_state_sub->provider->subtype
+	};
+
+	dlg = ast_sip_subscription_get_dlg(exten_state_sub->sip_sub);
 	ast_copy_pj_str(local, &dlg->local.info_str, sizeof(local));
 	ast_copy_pj_str(remote, &dlg->remote.info_str, sizeof(remote));
 
-	ssub->provider->create_body(data, local, remote, &body_text);
+	if (exten_state_sub->provider->create_body(exten_state_data, local, remote, &body_text)) {
+		return;
+	}
+
 	body.body_text = ast_str_buffer(body_text);
 
 	if (reason) {
@@ -265,8 +280,8 @@
 		reason_str_ptr = &reason_str;
 	}
 
-	if (pjsip_evsub_notify(ast_sip_subscription_get_evsub(ssub->sip_sub), ssub->state,
-			       NULL, reason_str_ptr, &tdata) != PJ_SUCCESS) {
+	if (pjsip_evsub_notify(ast_sip_subscription_get_evsub(exten_state_sub->sip_sub),
+			       exten_state_sub->evsub_state, NULL, reason_str_ptr, &tdata) != PJ_SUCCESS) {
 		ast_log(LOG_WARNING, "Unable to create NOTIFY request\n");
 		return;
 	}
@@ -277,7 +292,7 @@
 		return;
 	}
 
-	if (ast_sip_subscription_send_request(ssub->sip_sub, tdata) != PJ_SUCCESS) {
+	if (ast_sip_subscription_send_request(exten_state_sub->sip_sub, tdata) != PJ_SUCCESS) {
 		ast_log(LOG_WARNING, "Unable to send NOTIFY request\n");
 		pjsip_tx_data_dec_ref(tdata);
 	}
@@ -287,47 +302,67 @@
  * \internal
  * \brief Get device state information and send notification to the subscriber.
  */
-static void send_notify(struct state_sub *ssub, const char *reason)
+static void send_notify(struct exten_state_subscription *exten_state_sub, const char *reason)
 {
 	RAII_VAR(struct ao2_container*, info, NULL, ao2_cleanup);
 	char *subtype = NULL, *message = NULL;
 
-	struct ast_exten_state sdata = {
-		.exten = ssub->exten,
-		.presence_state = ast_hint_presence_state(NULL, ssub->context,
-							  ssub->exten, &subtype, &message),
+	struct ast_sip_exten_state_data exten_state_data = {
+		.exten = exten_state_sub->exten,
+		.presence_state = ast_hint_presence_state(NULL, exten_state_sub->context,
+							  exten_state_sub->exten, &subtype, &message),
 	};
 
-	if ((sdata.exten_state = ast_extension_state_extended(
-		     NULL, ssub->context, ssub->exten, &info)) < 0) {
+	if ((exten_state_data.exten_state = ast_extension_state_extended(
+		     NULL, exten_state_sub->context, exten_state_sub->exten, &info)) < 0) {
 
 		ast_log(LOG_WARNING, "Unable to get device hint/info for extension %s\n",
-			ssub->exten);
+			exten_state_sub->exten);
 		return;
 	}
 
-	sdata.device_state = info;
-	create_send_notify(ssub, reason, &sdata);
-}
-
-struct serialized_userdata {
-	struct ast_exten_state *sdata;
-	struct state_sub *ssub;
+	exten_state_data.device_state_info = info;
+	create_send_notify(exten_state_sub, reason, &exten_state_data);
+}
+
+struct notify_task_data {
+	struct ast_sip_exten_state_data exten_state_data;
+	struct exten_state_subscription *exten_state_sub;
 };
 
-static int serialized_notify(void *userdata)
-{
-	struct serialized_userdata *udata = userdata;
-
-	create_send_notify(udata->ssub, udata->ssub->state == PJSIP_EVSUB_STATE_TERMINATED ?
-			   "noresource" : NULL, udata->sdata);
-
-	ao2_ref(udata->ssub, -1);
-	if (udata->sdata->device_state) {
-		ao2_ref(udata->sdata->device_state, -1);
-	}
-
-	ast_free(udata->sdata);
+static void notify_task_data_destructor(void *obj)
+{
+	struct notify_task_data *task_data = obj;
+
+	ao2_ref(task_data->exten_state_sub, -1);
+	if (task_data->exten_state_data.device_state_info) {
+		ao2_ref(task_data->exten_state_data.device_state_info, -1);
+	}
+}
+
+static struct notify_task_data *alloc_notify_task_data(struct exten_state_subscription *exten_state_sub)
+{
+	struct notify_task_data *task_data =
+		ao2_alloc(sizeof(*task_data), notify_task_data_destructor);
+
+	if (!task_data) {
+		ast_log(LOG_WARNING, "Unable to create notify task data\n");
+		return NULL;
+	}
+
+	task_data->exten_state_sub = exten_state_sub;
+	task_data->exten_state_sub->evsub_state = PJSIP_EVSUB_STATE_ACTIVE;
+	task_data->exten_state_data.exten = exten_state_sub->exten;
+
+	return task_data;
+}
+
+static int notify_task(void *obj)
+{
+	RAII_VAR(struct notify_task_data *, task_data, obj, ao2_cleanup);
+
+	create_send_notify(task_data->exten_state_sub, task_data->exten_state_sub->evsub_state == 
+			   PJSIP_EVSUB_STATE_TERMINATED ? "noresource" : NULL, &task_data->exten_state_data);
 	return 0;
 }
 
@@ -337,34 +372,32 @@
  *
  * Upon state change, send the appropriate notification to the subscriber.
  */
-static int state_changed(char *context, char *exten, 
+static int state_changed(char *context, char *exten,
 			 struct ast_state_cb_info *info, void *data)
 {
-	struct serialized_userdata *udata = ast_malloc(sizeof(*udata));
-	struct ast_exten_state *sdata = ast_malloc(sizeof(*sdata));
-
-	udata->ssub = data;
-	ao2_ref(udata->ssub, +1);
-
-	sdata->exten = udata->ssub->exten;
-	sdata->exten_state = info->exten_state;
-	sdata->presence_state = info->presence_state;
-	sdata->device_state = info->device_state_info;
-	if (sdata->device_state) {
-		ao2_ref(sdata->device_state, +1);
-	}
-	udata->sdata = sdata;
-
-	udata->ssub->state = PJSIP_EVSUB_STATE_ACTIVE;
+	struct notify_task_data *task_data = alloc_notify_task_data(data);
+
+	if (!task_data) {
+		return -1;
+	}
+
+	task_data->exten_state_data.exten_state = info->exten_state;
+	task_data->exten_state_data.presence_state = info->presence_state;
+	task_data->exten_state_data.device_state_info = info->device_state_info;
+
+	if (task_data->exten_state_data.device_state_info) {
+		ao2_ref(task_data->exten_state_data.device_state_info, +1);
+	}
+
 	if ((info->exten_state == AST_EXTENSION_DEACTIVATED) ||
 	    (info->exten_state == AST_EXTENSION_REMOVED)) {
-		udata->ssub->state = PJSIP_EVSUB_STATE_TERMINATED;
-		ast_log(LOG_NOTICE, "Watcher for hint %s %s\n", exten, info->exten_state
+		task_data->exten_state_sub->evsub_state = PJSIP_EVSUB_STATE_TERMINATED;
+		ast_log(LOG_WARNING, "Watcher for hint %s %s\n", exten, info->exten_state
 			 == AST_EXTENSION_REMOVED ? "removed" : "deactivated");
 	}
 
-	ast_sip_push_task(ast_sip_subscription_get_serializer(udata->ssub->sip_sub),
-			  serialized_notify, udata);
+	ast_sip_push_task(ast_sip_subscription_get_serializer(task_data->exten_state_sub->sip_sub),
+			  notify_task, task_data);
 	return 0;
 }
 
@@ -373,14 +406,14 @@
 
 /*!
  * \internal
- * \brief Add a datastore for exten state_sub.
- *
- * Adds the state_sub wrapper object to a datastore so it can be retrieved
+ * \brief Add a datastore for exten exten_state_subscription.
+ *
+ * Adds the exten_state_subscription wrapper object to a datastore so it can be retrieved
  * later based upon its association with the ast_sip_subscription.
  */
-static int add_datastore(struct state_sub *sub)
-{
-	RAII_VAR(struct ast_datastore *, datastore, 
+static int add_datastore(struct exten_state_subscription *sub)
+{
+	RAII_VAR(struct ast_datastore *, datastore,
 		 ast_sip_subscription_alloc_datastore(&ds_info, ds_name), ao2_cleanup);
 
 	if (!datastore) {
@@ -394,10 +427,11 @@
 
 /*!
  * \internal
- * \brief Get the state_sub object associated with the given
+ * \brief Get the exten_state_subscription object associated with the given
  * ast_sip_subscription in the datastore.
  */
-static struct state_sub *from_datastore(struct ast_sip_subscription *sub)
+static struct exten_state_subscription *get_exten_state_sub(
+	struct ast_sip_subscription *sub)
 {
 	RAII_VAR(struct ast_datastore *, datastore,
 		 ast_sip_subscription_get_datastore(sub, ds_name), ao2_cleanup);
@@ -407,11 +441,11 @@
 
 static void subscription_shutdown(struct ast_sip_subscription *sub)
 {
-	struct state_sub *ssub = from_datastore(sub);
-
-	if (ssub) {
-		ast_extension_state_del(ssub->id, state_changed);
-		ao2_cleanup(ssub);
+	struct exten_state_subscription *exten_state_sub = get_exten_state_sub(sub);
+
+	if (exten_state_sub) {
+		ast_extension_state_del(exten_state_sub->id, state_changed);
+		ao2_cleanup(exten_state_sub);
 	}
 }
 
@@ -420,85 +454,90 @@
 {
 	pjsip_uri *uri = rdata->msg_info.msg->line.req.uri;
 	pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri);
-	struct state_sub *ssub;
+	RAII_VAR(struct exten_state_subscription *, exten_state_sub, NULL, ao2_cleanup);
 
 	if (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri)) {
 		ast_log(LOG_WARNING, "Attempt to SUBSCRIBE to a non-SIP URI\n");
 		return NULL;
 	}
 
-	if (!(ssub = state_sub_alloc(endpoint, AST_SIP_NOTIFIER, rdata))) {
-		return NULL;
-	}
-
-	ssub->context = endpoint->context;
-	ast_copy_pj_str(ssub->exten, &sip_uri->user, sizeof(ssub->exten));
-
-	if ((ssub->id = ast_extension_state_add(ssub->context, ssub->exten,
-						state_changed, ssub)) < 0) {
+	if (!(exten_state_sub = exten_state_subscription_alloc(endpoint, AST_SIP_NOTIFIER, rdata))) {
+		return NULL;
+	}
+
+	strncpy(exten_state_sub->context, endpoint->context, AST_MAX_CONTEXT);
+	ast_copy_pj_str(exten_state_sub->exten, &sip_uri->user, sizeof(exten_state_sub->exten));
+
+	if ((exten_state_sub->id = ast_extension_state_add(exten_state_sub->context, exten_state_sub->exten,
+						state_changed, exten_state_sub)) < 0) {
 		ast_log(LOG_WARNING, "Unable to subscribe extension %s\n",
-			ssub->exten);
-		ao2_cleanup(ssub);
-		return NULL;
-	}
-
-	if (add_datastore(ssub)) {
+			exten_state_sub->exten);
+		return NULL;
+	}
+
+	/* bump the ref since ast_extension_state_add holds a reference */
+	ao2_ref(exten_state_sub, +1);
+
+	if (add_datastore(exten_state_sub)) {
 		ast_log(LOG_WARNING, "Unable to add to subscription datastore.\n");
-		ao2_cleanup(ssub);
-		return NULL;
-	}
-
-	pjsip_evsub_accept(ast_sip_subscription_get_evsub(ssub->sip_sub),
-			   rdata, 200, NULL);
-
-	ssub->state = PJSIP_EVSUB_STATE_ACTIVE;
-	send_notify(ssub, NULL);
-	return ssub->sip_sub;
+		return NULL;
+	}
+
+	if (pjsip_evsub_accept(ast_sip_subscription_get_evsub(exten_state_sub->sip_sub),
+			       rdata, 200, NULL) != PJ_SUCCESS) {
+		ast_log(LOG_WARNING, "Unable to accept the incoming extension state subscription.\n");
+		return NULL;
+	}
+
+	exten_state_sub->evsub_state = PJSIP_EVSUB_STATE_ACTIVE;
+	send_notify(exten_state_sub, NULL);
+	return exten_state_sub->sip_sub;
 }
 
 static void resubscribe(struct ast_sip_subscription *sub, pjsip_rx_data *rdata,
 			struct ast_sip_subscription_response_data *response_data)
 {
-	struct state_sub *ssub = from_datastore(sub);
-
-	if (ssub) {
-		ssub->state = PJSIP_EVSUB_STATE_ACTIVE;
-		send_notify(ssub, NULL);
+	struct exten_state_subscription *exten_state_sub = get_exten_state_sub(sub);
+
+	if (exten_state_sub) {
+		exten_state_sub->evsub_state = PJSIP_EVSUB_STATE_ACTIVE;
+		send_notify(exten_state_sub, NULL);
 	}
 }
 
 static void subscription_timeout(struct ast_sip_subscription *sub)
 {
-	struct state_sub *ssub = from_datastore(sub);
-
-	if (!ssub) {
+	struct exten_state_subscription *exten_state_sub = get_exten_state_sub(sub);
+
+	if (!exten_state_sub) {
 		return;
 	}
 
-	ast_log(LOG_NOTICE, "Subscription for has timed out.\n");
-	ssub->state = PJSIP_EVSUB_STATE_TERMINATED;
-	send_notify(ssub, "timeout");
+	ast_verbose(VERBOSE_PREFIX_3 "Subscription for has timed out.\n");
+	exten_state_sub->evsub_state = PJSIP_EVSUB_STATE_TERMINATED;
+	send_notify(exten_state_sub, "timeout");
 }
 
 static void subscription_terminated(struct ast_sip_subscription *sub,
 				    pjsip_rx_data *rdata)
 {
-	struct state_sub *ssub = from_datastore(sub);
-
-	if (!ssub) {
+	struct exten_state_subscription *exten_state_sub = get_exten_state_sub(sub);
+
+	if (!exten_state_sub) {
 		return;
 	}
 
-	ast_log(LOG_NOTICE, "Subscription has been terminated\n");
-	ssub->state = PJSIP_EVSUB_STATE_TERMINATED;
-	send_notify(ssub, NULL);
+	ast_verbose(VERBOSE_PREFIX_3 "Subscription has been terminated.\n");
+	exten_state_sub->evsub_state = PJSIP_EVSUB_STATE_TERMINATED;
+	send_notify(exten_state_sub, NULL);
 }
 
 /*!
  * \internal
  * \brief Checks to see if the given value is in the given accept array.
- */
-static int has_accept(const char *accept[], const char *value)
+ * If it isn't return the index to the next usable space in the array.
+ */
+static int in_accept_or_index(const char *accept[], const char *value)
 {
 	int i;
 	/* search all items or until we find a null/empty element */
@@ -519,10 +558,10 @@
  */
 static void add_accept(const char* dest[], const char* accept)
 {
-	int i = has_accept(dest, accept);
+	int i = in_accept_or_index(dest, accept);
 
 	if (i < 0) {
-		/* already in list */
+		/* already in accept list */
 		return;
 	}
 
@@ -544,9 +583,9 @@
 static struct ast_sip_subscription_handler *create_sub_handler(const char *event_name,
 							       const char *accept)
 {
-	struct ast_sip_subscription_handler *handler = 
+	struct ast_sip_subscription_handler *handler =
 		ao2_alloc(sizeof(*handler), NULL);
-	
+
 	if (!handler) {
 		return NULL;
 	}
@@ -568,7 +607,7 @@
  * \brief Create a collection of subscription handlers.
  *
  * Currently pjsip only allows one event_name to be registered for a given
- * list of body type/application (accept) values. This list of values 
+ * list of body type/application (accept) values. This list of values
  * cannot be modified once a particular event_name has been registered.
  * This means all accept values must be specified before registering a
  * subcription handler for an event_name with the pub/sub framework.
@@ -581,23 +620,25 @@
  */
 static void create_sub_handlers(void)
 {
-	struct ast_exten_state_provider *i;
-	SCOPED_LOCK(lock, &providers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
-
+	struct ast_sip_exten_state_provider *i;
+	SCOPED_LOCK(lock, &providers, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
 	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&providers, i, next) {
 		struct ast_sip_subscription_handler *handler =
 			ao2_find(sub_handlers, i->event_name, OBJ_NOLOCK | OBJ_KEY);
 
+		struct ast_str *type = ast_str_alloca(BODY_TYPE_SIZE);
+		ast_str_set(&type, -1, "%s/%s", i->type, i->subtype);
+
 		if (handler) {
 			/* if handler exists just assign those accept values to
 			   it from the provider that have not already been set */
-			add_accept(handler->accept, i->accept);
+			add_accept(handler->accept, ast_str_buffer(type));
 			continue;
 		}
 
-		/* if handler does not exist yet, create it and add to 
+		/* if handler does not exist yet, create it and add to
 		   container - note accept values assigned in create */
-		if ((handler = create_sub_handler(i->event_name, i->accept))) {
+		if ((handler = create_sub_handler(i->event_name, ast_str_buffer(type)))) {
 			ao2_link(sub_handlers, handler);
 		}
 	}
@@ -644,11 +685,14 @@
 	}
 
 	/* register providers - for now they have to be specifically added here
-	   because of a limitation in pjsip. if pjsip ever gets modified these
+	   because pjsip requires a registered event type and all associated
+	   body types be done once (i.e. you can't register 'presence' with
+	   'application/pidf+xml' and then later try to re-register 'presence'
+	   along with 'application/xpidf'). if pjsip ever gets modified these
 	   can be moved to their respective module files */
-	register_exten_state_provider(ast_sip_pidf_xml_provider());
-	register_exten_state_provider(ast_sip_xml_pidf_provider());
-	register_exten_state_provider(ast_sip_cpim_pidf_xml_provider());
+	register_sip_exten_state_provider(ast_sip_pidf_xml_provider());
+	register_sip_exten_state_provider(ast_sip_xpidf_xml_provider());
+	register_sip_exten_state_provider(ast_sip_cpim_pidf_xml_provider());
 
 	/* create the subscription handlers based upon the providers */
 	create_sub_handlers();
@@ -666,10 +710,10 @@
 	ao2_callback(sub_handlers, OBJ_NODATA | OBJ_NOLOCK,
 		     unregister_sub_handlers, NULL);
 
-	/* unregister providers here, again due to pjsip limitation */
-	unregister_exten_state_provider(ast_sip_cpim_pidf_xml_provider());
-	unregister_exten_state_provider(ast_sip_xml_pidf_provider());
-	unregister_exten_state_provider(ast_sip_pidf_xml_provider());
+	/* unregister providers here, again due to pjsip limitation mentioned above */
+	unregister_sip_exten_state_provider(ast_sip_cpim_pidf_xml_provider());
+	unregister_sip_exten_state_provider(ast_sip_xpidf_xml_provider());
+	unregister_sip_exten_state_provider(ast_sip_pidf_xml_provider());
 
 	ao2_cleanup(sub_handlers);
 

Modified: team/kharwell/pimp_sip_state/res/res_sip_providers/include/res_sip_providers.h
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_state/res/res_sip_providers/include/res_sip_providers.h?view=diff&rev=388428&r1=388427&r2=388428
==============================================================================
--- team/kharwell/pimp_sip_state/res/res_sip_providers/include/res_sip_providers.h (original)
+++ team/kharwell/pimp_sip_state/res/res_sip_providers/include/res_sip_providers.h Fri May 10 17:16:14 2013
@@ -35,8 +35,8 @@
    added here in order to be accessible by res_sip_extern_state.
 */
 
-struct ast_exten_state_provider *ast_sip_pidf_xml_provider(void);
-struct ast_exten_state_provider *ast_sip_xml_pidf_provider(void);
-struct ast_exten_state_provider *ast_sip_cpim_pidf_xml_provider(void);
+struct ast_sip_exten_state_provider *ast_sip_pidf_xml_provider(void);
+struct ast_sip_exten_state_provider *ast_sip_xpidf_xml_provider(void);
+struct ast_sip_exten_state_provider *ast_sip_cpim_pidf_xml_provider(void);
 
 #endif

Modified: team/kharwell/pimp_sip_state/res/res_sip_providers/res_sip_pidf.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_state/res/res_sip_providers/res_sip_pidf.c?view=diff&rev=388428&r1=388427&r2=388428
==============================================================================
--- team/kharwell/pimp_sip_state/res/res_sip_providers/res_sip_pidf.c (original)
+++ team/kharwell/pimp_sip_state/res/res_sip_providers/res_sip_pidf.c Fri May 10 17:16:14 2013
@@ -25,7 +25,6 @@
  ***/
 
 #include "asterisk.h"
-#include "asterisk/pbx.h"
 #include "asterisk/res_sip_exten_state.h"
 #include "include/res_sip_providers.h"
 
@@ -81,8 +80,8 @@
 	}
 }
 
-static void pidf_xml_create_body(struct ast_exten_state *data, const char *local,
-					 const char *remote, struct ast_str **body_text)
+static int pidf_xml_create_body(struct ast_sip_exten_state_data *data, const char *local,
+				const char *remote, struct ast_str **body_text)
 {
 	char *statestring = NULL, *pidfstate = NULL, *pidfnote = NULL;
 	int local_state;
@@ -112,20 +111,23 @@
 		ast_str_append(body_text, 0, "<status><basic>%s</basic></status>\n", (local_state != NOTIFY_CLOSED) ? "open" : "closed");
 	}
 	ast_str_append(body_text, 0, "</tuple>\n</presence>\n");
+
+	return 0;
 }
 
-static struct ast_exten_state_provider _pidf_xml_provider = {
+static struct ast_sip_exten_state_provider _pidf_xml_provider = {
 	.event_name = "presence",
-	.accept = "application/pidf+xml",
+	.type = "application",
+	.subtype = "pidf+xml",
 	.create_body = pidf_xml_create_body
 };
 
-struct ast_exten_state_provider *ast_sip_pidf_xml_provider(void)
+struct ast_sip_exten_state_provider *ast_sip_pidf_xml_provider(void)
 {
 	return &_pidf_xml_provider;
 }
 
-static void xml_pidf_create_body(struct ast_exten_state *data, const char *local,
+static int xpidf_xml_create_body(struct ast_sip_exten_state_data *data, const char *local,
 				 const char *remote, struct ast_str **body_text)
 {
 	char *statestring = NULL, *pidfstate = NULL, *pidfnote = NULL;
@@ -148,24 +150,28 @@
 		       (local_state == NOTIFY_OPEN) ? "online" :
 		       (local_state == NOTIFY_INUSE) ? "onthephone" : "offline");
 	ast_str_append(body_text, 0, "</address>\n</atom>\n</presence>\n");
+
+	return 0;
 }
 
-static struct ast_exten_state_provider _xml_pidf_provider = {
+static struct ast_sip_exten_state_provider _xpidf_xml_provider = {
 	.event_name = "presence",
-	.accept = "application/xml+pidf",
-	.create_body = xml_pidf_create_body
+	.type = "application",
+	.subtype = "xpidf+xml",
+	.create_body = xpidf_xml_create_body
 };
 
-struct ast_exten_state_provider *ast_sip_xml_pidf_provider(void) {
-	return &_xml_pidf_provider;
+struct ast_sip_exten_state_provider *ast_sip_xpidf_xml_provider(void) {
+	return &_xpidf_xml_provider;
 }
 
-static struct ast_exten_state_provider _cpim_pidf_xml_provider = {
+static struct ast_sip_exten_state_provider _cpim_pidf_xml_provider = {
 	.event_name = "presence",
-	.accept = "application/cpim+pidf+xml",
-	.create_body = xml_pidf_create_body
+	.type = "application",
+	.subtype = "cpim-pidf+xml",
+	.create_body = xpidf_xml_create_body
 };
 
-struct ast_exten_state_provider *ast_sip_cpim_pidf_xml_provider(void) {
+struct ast_sip_exten_state_provider *ast_sip_cpim_pidf_xml_provider(void) {
 	return &_cpim_pidf_xml_provider;
 }




More information about the asterisk-commits mailing list