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

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu May 23 15:36:44 CDT 2013


Author: kharwell
Date: Thu May 23 15:36:40 2013
New Revision: 389616

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=389616
Log:
review issues addressed - removed horrible module reg workaround, but still need to merge in fix for that from pub/sub

Added:
    team/kharwell/pimp_sip_state/res/res_sip_exten_state.exports.in   (with props)
    team/kharwell/pimp_sip_state/res/res_sip_pidf.c
      - copied, changed from r389484, team/kharwell/pimp_sip_state/res/res_sip_providers/res_sip_pidf.c
Removed:
    team/kharwell/pimp_sip_state/res/res_sip_providers/
Modified:
    team/kharwell/pimp_sip_state/include/asterisk/res_sip_exten_state.h
    team/kharwell/pimp_sip_state/res/Makefile
    team/kharwell/pimp_sip_state/res/res_sip_exten_state.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=389616&r1=389615&r2=389616
==============================================================================
--- 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 Thu May 23 15:36:40 2013
@@ -50,8 +50,10 @@
 	const char *type;
 	/*! Subtype of the body, ex: "pidf+xml" */
 	const char *subtype;
-	/*! Type/Subtype appended together - set internally */
-	char body_type[50];
+	/*! Type/Subtype together - ex: application/pidf+xml */
+	const char *body_type;
+	/*! Subscription handler to be used and associated with provider */
+	struct ast_sip_subscription_handler *handler;
 
 	/*!
 	 * \brief Create the body text of a NOTIFY request.
@@ -63,6 +65,8 @@
 	 * \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
+	 * \retval 0 Successfully created the body's text
+	 * \retval -1 Failed to create the body's text
 	 */
 	int (*create_body)(struct ast_sip_exten_state_data *data, const char *local,
 			   const char *remote, struct ast_str **body_text);
@@ -75,6 +79,8 @@
  * \brief Registers an extension state provider.
  *
  * \param obj An extension state provider
+ * \retval 0 Successfully registered the extension state provider
+ * \retval -1 Failed to register the extension state provider
  */
 int ast_sip_register_exten_state_provider(struct ast_sip_exten_state_provider *obj);
 

Modified: team/kharwell/pimp_sip_state/res/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_state/res/Makefile?view=diff&rev=389616&r1=389615&r2=389616
==============================================================================
--- team/kharwell/pimp_sip_state/res/Makefile (original)
+++ team/kharwell/pimp_sip_state/res/Makefile Thu May 23 15:36:40 2013
@@ -46,9 +46,6 @@
 $(if $(filter res_sip,$(EMBEDDED_MODS)),modules.link,res_sip.so): $(subst .c,.o,$(wildcard res_sip/*.c))
 $(subst .c,.o,$(wildcard res_sip/*.c)): _ASTCFLAGS+=$(call MOD_ASTCFLAGS,res_sip)
 
-$(if $(filter res_sip_providers,$(EMBEDDED_MODS)),modules.link,res_sip_exten_state.so): $(subst .c,.o,$(wildcard res_sip_providers/*.c))
-$(subst .c,.o,$(wildcard res_sip_providers/*.c)): _ASTCFLAGS+=$(call MOD_ASTCFLAGS,res_sip_providers)
-
 $(if $(filter res_stasis,$(EMBEDDED_MODS)),modules.link,res_stasis.so): $(subst .c,.o,$(wildcard stasis/*.c))
 $(subst .c,.o,$(wildcard stasis/*.c)): _ASTCFLAGS+=$(call MOD_ASTCFLAGS,res_stasis)
 

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=389616&r1=389615&r2=389616
==============================================================================
--- team/kharwell/pimp_sip_state/res/res_sip_exten_state.c (original)
+++ team/kharwell/pimp_sip_state/res/res_sip_exten_state.c Thu May 23 15:36:40 2013
@@ -37,69 +37,22 @@
 #include "asterisk/astobj2.h"
 #include "asterisk/sorcery.h"
 #include "asterisk/app.h"
-#include "res_sip_providers/include/res_sip_providers.h"
 
 #define BODY_SIZE 1024
-#define BODY_TYPE_SIZE 50
 #define EVENT_TYPE_SIZE 50
 
 AST_RWLIST_HEAD_STATIC(providers, ast_sip_exten_state_provider);
 
-int ast_sip_register_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;
-	}
-	strncpy(obj->body_type, obj->type, sizeof(obj->body_type));
-	strncat(obj->body_type, "/", 1);
-	strncat(obj->body_type, obj->subtype, sizeof(obj->body_type) -
-		strlen(obj->body_type));
-
-	AST_RWLIST_INSERT_TAIL(&providers, obj, next);
-	ast_module_ref(ast_module_info->self);
-	return 0;
-}
-
-void ast_sip_unregister_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) {
-			AST_RWLIST_REMOVE_CURRENT(next);
-			ast_module_unref(ast_module_info->self);
-			break;
-		}
-	}
-	AST_RWLIST_TRAVERSE_SAFE_END;
-}
-
-/*!
- * \internal
- * \brief Find a provider based on the given accept type.
- */
-static struct ast_sip_exten_state_provider *provider_by_accept(const char *accept)
+/*!
+ * \internal
+ * \brief Find a provider based on the given accept body type.
+ */
+static struct ast_sip_exten_state_provider *provider_by_type(const char *type)
 {
 	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->body_type, accept)) {
+		if (!strcmp(i->body_type, type)) {
 			return i;
 		}
 	}
@@ -109,55 +62,21 @@
 
 /*!
  * \internal
- * \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_sip_exten_state_provider *provider_by_req(pjsip_rx_data *rdata)
+ * \brief Find a provider based on the given accept body types.
+ */
+static struct ast_sip_exten_state_provider *provider_by_types(const char *event_name,
+							      char **types, int count)
 {
 	int i;
-	pjsip_accept_hdr *hdr = (pjsip_accept_hdr*)
-		pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_ACCEPT, NULL);
-
-	if (!hdr) {
-		ast_log(LOG_WARNING, "No Accept header found in subscribe\n");
-		return NULL;
-	}
-
-	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))) {
+	struct ast_sip_exten_state_provider *res;
+	for (i = 0; i < count; ++i) {
+		if ((res = provider_by_type(types[i])) &&
+		    !strcmp(event_name, res->event_name)) {
 			return res;
 		}
 	}
 	return NULL;
 }
-
-static int sub_handler_hash(const void *obj, int flags)
-{
-	const struct ast_sip_subscription_handler *handler = obj;
-	const char *event_name = obj;
-
-	return ast_str_hash(flags & OBJ_KEY ? event_name : handler->event_name);
-}
-
-static int sub_handler_cmp(void *obj, void *arg, int flags)
-{
-	struct ast_sip_subscription_handler *handler1 = obj;
-	struct ast_sip_subscription_handler *handler2 = arg;
-	const char *event_name = arg;
-
-	return !strcmp(handler1->event_name, flags & OBJ_KEY ?
-		       event_name : handler2->event_name) ? CMP_MATCH | CMP_STOP : 0;
-}
-
-#define SUB_HANDLER_BUCKETS 5
-
-static struct ao2_container *sub_handlers;
 
 /*!
  * \brief A subscription for extension state
@@ -171,8 +90,12 @@
 	int id;
 	/*! The SIP subscription */
 	struct ast_sip_subscription *sip_sub;
-	/*! The notify data creator */
-	struct ast_sip_exten_state_provider *provider;
+	/*! The name of the event the subscribed to */
+	char event_name[EVENT_TYPE_SIZE];
+	/*! The number of body types */
+	int body_types_count;
+	/*! The subscription body types */
+	char **body_types;
 	/*! Context in which subscription looks for updates */
 	char context[AST_MAX_CONTEXT];
 	/*! Extension within the context to receive updates from */
@@ -184,32 +107,45 @@
 static void exten_state_subscription_destructor(void *obj)
 {
 	struct exten_state_subscription *sub = obj;
+	int i;
+
+	for (i = 0; i < sub->body_types_count; ++i) {
+		ast_free(sub->body_types[i]);
+	}
+
+	ast_free(sub->body_types);
 	ao2_cleanup(sub->sip_sub);
 }
 
 /*!
  * \internal
- * \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[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);
-
-	if (!hdr) {
-		ast_log(LOG_WARNING, "No Event header found in subscribe\n");
-		return NULL;
-	}
-
-	ast_copy_pj_str(type, &hdr->event_type, sizeof(type));
-
-	return ao2_find(sub_handlers, type, OBJ_KEY | OBJ_NOLOCK);
-}
+ * \brief Copies the body types the message wishes to subscribe to.
+ */
+static void copy_body_types(pjsip_rx_data *rdata,
+			    struct exten_state_subscription *exten_state_sub)
+{
+	int i;
+	pjsip_accept_hdr *hdr = (pjsip_accept_hdr*)
+		pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_ACCEPT, NULL);
+
+	exten_state_sub->body_types_count = hdr->count;
+	exten_state_sub->body_types = ast_malloc(hdr->count * sizeof(char*));
+
+	for (i = 0; i < hdr->count; ++i) {
+		exten_state_sub->body_types[i] =
+			ast_malloc(hdr->values[i].slen * sizeof(char*) + 1);
+
+		ast_copy_string(exten_state_sub->body_types[i],
+				pj_strbuf(&hdr->values[i]), hdr->values[i].slen + 1);
+	}
+}
+
+/*!
+ * \internal
+ * \brief Initialize the last extension state to something outside
+ * its usual states.
+ */
+#define INITIAL_LAST_EXTEN_STATE -3
 
 /*!
  * \internal
@@ -221,7 +157,11 @@
 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;
+	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);
+
+	struct ast_sip_exten_state_provider *provider;
 	RAII_VAR(struct exten_state_subscription *, exten_state_sub,
 		 ao2_alloc(sizeof(*exten_state_sub), exten_state_subscription_destructor), ao2_cleanup);
 
@@ -229,22 +169,25 @@
 		return NULL;
 	}
 
-	if (!(handler = sub_handler_by_req(rdata))) {
-		ast_log(LOG_WARNING, "Handler not found for subscription event\n");
-		return NULL;
-	}
-
-	if (!(exten_state_sub->provider = provider_by_req(rdata))) {
-		ast_log(LOG_WARNING, "Unable to locate subscription handler provider\n");
-		return NULL;
-	}
-
-	if (!(exten_state_sub->sip_sub = ast_sip_create_subscription(handler, role, endpoint, rdata))) {
+	ast_copy_pj_str(exten_state_sub->event_name, &hdr->event_type,
+			sizeof(exten_state_sub->event_name));
+
+	copy_body_types(rdata, exten_state_sub);
+	if (!(provider = provider_by_types(exten_state_sub->event_name,
+					   exten_state_sub->body_types,
+					   exten_state_sub->body_types_count))) {
+		ast_log(LOG_WARNING, "Unable to locate subscription handler\n");
+		return NULL;
+	}
+
+	if (!(exten_state_sub->sip_sub = ast_sip_create_subscription(
+		      provider->handler, role, endpoint, rdata))) {
 		ast_log(LOG_WARNING, "Unable to create SIP subscription for endpoint %s\n",
 			ast_sorcery_object_get_id(endpoint));
 		return NULL;
 	}
-	exten_state_sub->last_exten_state = -3;
+
+	exten_state_sub->last_exten_state = INITIAL_LAST_EXTEN_STATE;
 
 	ao2_ref(exten_state_sub, +1);
 	return exten_state_sub;
@@ -262,17 +205,26 @@
 	const pj_str_t *reason_str_ptr = NULL;
 	pjsip_tx_data *tdata;
 	pjsip_dialog *dlg;
-	char local[256], remote[256];
-	struct ast_sip_body body = {
-		.type = exten_state_sub->provider->type,
-		.subtype = exten_state_sub->provider->subtype
-	};
+	char local[PJSIP_MAX_URL_SIZE], remote[PJSIP_MAX_URL_SIZE];
+	struct ast_sip_body body;
+
+	struct ast_sip_exten_state_provider *provider = provider_by_types(
+		exten_state_sub->event_name, exten_state_sub->body_types,
+		exten_state_sub->body_types_count);
+
+	if (!provider) {
+		ast_log(LOG_ERROR, "Unable to locate provider for subscription\n");
+		return;
+	}
+
+	body.type = provider->type;
+	body.subtype = 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));
 
-	if (exten_state_sub->provider->create_body(exten_state_data, local, remote, &body_text)) {
+	if (provider->create_body(exten_state_data, local, remote, &body_text)) {
 		return;
 	}
 
@@ -343,7 +295,8 @@
 	ao2_cleanup(task_data->exten_state_data.device_state_info);
 }
 
-static struct notify_task_data *alloc_notify_task_data(struct exten_state_subscription *exten_state_sub)
+static struct notify_task_data *alloc_notify_task_data(char *exten, struct exten_state_subscription *exten_state_sub,
+						       struct ast_state_cb_info *info)
 {
 	struct notify_task_data *task_data =
 		ao2_alloc(sizeof(*task_data), notify_task_data_destructor);
@@ -355,43 +308,10 @@
 
 	task_data->evsub_state = PJSIP_EVSUB_STATE_ACTIVE;
 	task_data->exten_state_sub = exten_state_sub;
+	task_data->exten_state_sub->last_exten_state = info->exten_state;
 	ao2_ref(task_data->exten_state_sub, +1);
+
 	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->evsub_state ==
-			   PJSIP_EVSUB_STATE_TERMINATED ? "noresource" : NULL,
-			   task_data->evsub_state, &task_data->exten_state_data);
-	return 0;
-}
-
-/*!
- * \internal
- * \brief Callback for exten/device state changes.
- *
- * Upon state change, send the appropriate notification to the subscriber.
- */
-static int state_changed(char *context, char *exten,
-			 struct ast_state_cb_info *info, void *data)
-{
-	struct notify_task_data *task_data;
-	struct exten_state_subscription *exten_state_sub = data;
-
-	if (exten_state_sub->last_exten_state == info->exten_state) {
-		return 0;
-	}
-	exten_state_sub->last_exten_state = info->exten_state;
-
-	if (!(task_data = alloc_notify_task_data(exten_state_sub))) {
-		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;
@@ -405,6 +325,39 @@
 		task_data->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");
+	}
+
+	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->evsub_state ==
+			   PJSIP_EVSUB_STATE_TERMINATED ? "noresource" : NULL,
+			   task_data->evsub_state, &task_data->exten_state_data);
+	return 0;
+}
+
+/*!
+ * \internal
+ * \brief Callback for exten/device state changes.
+ *
+ * Upon state change, send the appropriate notification to the subscriber.
+ */
+static int state_changed(char *context, char *exten,
+			 struct ast_state_cb_info *info, void *data)
+{
+	struct notify_task_data *task_data;
+	struct exten_state_subscription *exten_state_sub = data;
+
+	if (exten_state_sub->last_exten_state == info->exten_state) {
+		return 0;
+	}
+
+	if (!(task_data = alloc_notify_task_data(exten, exten_state_sub, info))) {
+		return -1;
 	}
 
 	/* safe to push this async since we copy the data from info and
@@ -417,6 +370,12 @@
 	return 0;
 }
 
+static void state_changed_destroy(int id, void *data)
+{
+	struct exten_state_subscription *exten_state_sub = data;	
+	ao2_cleanup(exten_state_sub);
+}
+
 static struct ast_datastore_info ds_info = { };
 static const char ds_name[] = "exten state datastore";
 
@@ -427,7 +386,7 @@
  * 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 exten_state_subscription *sub)
+static int add_datastore(struct exten_state_subscription *exten_state_sub)
 {
 	RAII_VAR(struct ast_datastore *, datastore,
 		 ast_sip_subscription_alloc_datastore(&ds_info, ds_name), ao2_cleanup);
@@ -436,8 +395,9 @@
 		return -1;
 	}
 
-	datastore->data = sub;
-	ast_sip_subscription_add_datastore(sub->sip_sub, datastore);
+	datastore->data = exten_state_sub;
+	ast_sip_subscription_add_datastore(exten_state_sub->sip_sub, datastore);
+	ao2_ref(exten_state_sub, +1);
 	return 0;
 }
 
@@ -459,10 +419,14 @@
 {
 	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);
-	}
+	if (!exten_state_sub) {
+		return;
+	}
+
+	ast_extension_state_del(exten_state_sub->id, state_changed);
+	ast_sip_subscription_remove_datastore(exten_state_sub->sip_sub, ds_name);
+	/* remove data store reference */
+	ao2_cleanup(exten_state_sub);
 }
 
 static struct ast_sip_subscription *new_subscribe(struct ast_sip_endpoint *endpoint,
@@ -481,15 +445,19 @@
 		return NULL;
 	}
 
-	strncpy(exten_state_sub->context, endpoint->context, AST_MAX_CONTEXT);
+	ast_copy_string(exten_state_sub->context, endpoint->context, sizeof(exten_state_sub->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) {
+	if ((exten_state_sub->id = ast_extension_state_add_destroy_extended(
+		     exten_state_sub->context, exten_state_sub->exten,
+		     state_changed, state_changed_destroy, exten_state_sub)) < 0) {
 		ast_log(LOG_WARNING, "Unable to subscribe extension %s\n",
 			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");
@@ -503,8 +471,6 @@
 	}
 
 	send_notify(exten_state_sub, NULL, PJSIP_EVSUB_STATE_ACTIVE);
-	/* bump the ref since ast_extension_state_add holds a reference */
-	ao2_ref(exten_state_sub, +1);
 	return exten_state_sub->sip_sub;
 }
 
@@ -513,9 +479,11 @@
 {
 	struct exten_state_subscription *exten_state_sub = get_exten_state_sub(sub);
 
-	if (exten_state_sub) {
-		send_notify(exten_state_sub, NULL, PJSIP_EVSUB_STATE_ACTIVE);
-	}
+	if (!exten_state_sub) {
+		return;
+	}
+
+	send_notify(exten_state_sub, NULL, PJSIP_EVSUB_STATE_ACTIVE);
 }
 
 static void subscription_timeout(struct ast_sip_subscription *sub)
@@ -545,54 +513,13 @@
 
 /*!
  * \internal
- * \brief Checks to see if the given value is in the given accept array.
- * 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 */
-	for (i = 0; i < sizeof(accept) &&
-		     !ast_strlen_zero(accept[i]); ++i) {
-		if (!strcmp(accept[i], value)) {
-			return -1;
-		}
-	}
-	/* return the first empty element in the array */
-	return i;
-}
-
-/*!
- * \internal
- * \brief Add given accept to 'dest' if 'dest' does not already contain
- *        the accept type.
- */
-static void add_accept(const char* dest[], const char* accept)
-{
-	int i = in_accept_or_index(dest, accept);
-
-	if (i < 0) {
-		/* already in accept list */
-		return;
-	}
-
-	if (i == sizeof(dest)) {
-		ast_log(LOG_WARNING, "Subcription handler's accept values full\n");
-		return;
-	}
-
-	dest[i] = accept;
-}
-
-/*!
- * \internal
- * \brief Create a subscription handler.
+ * \brief Create and register a subscription handler.
  *
  * Creates a subscription handler that can be registered with the pub/sub
  * framework for the given event_name and accept value.
  */
-static struct ast_sip_subscription_handler *create_sub_handler(const char *event_name,
-							       const char *accept)
+static struct ast_sip_subscription_handler *create_and_register_handler(
+	const char *event_name, const char *accept)
 {
 	struct ast_sip_subscription_handler *handler =
 		ao2_alloc(sizeof(*handler), NULL);
@@ -602,7 +529,7 @@
 	}
 
 	handler->event_name = event_name;
-	add_accept(handler->accept, accept);
+	handler->accept[0] = accept;
 
 	handler->subscription_shutdown = subscription_shutdown;
 	handler->new_subscribe = new_subscribe;
@@ -610,125 +537,71 @@
 	handler->subscription_timeout = subscription_timeout;
 	handler->subscription_terminated = subscription_terminated;
 
-	return handler;
-}
-
-/*!
- * \internal
- * \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
- * 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.
- *
- * For every registered provider create, or re-use, a subscription handler
- * based upon the event_name. If a handler does not exist for a particular
- * event_name one will be created adding the accept value from a provider.
- * If a handler already exists for an event_name then if the accept value
- * has not been added to that handler it will be.
- */
-static void create_sub_handlers(void)
-{
-	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);
-
-		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->body_type);
-			continue;
-		}
-
-		/* 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->body_type))) {
-			ao2_link(sub_handlers, handler);
-		}
-	}
-	AST_RWLIST_TRAVERSE_SAFE_END;
-}
-
-/*!
- * \internal
- * \brief Register a subscription handlers with the pub/sub framework.
- */
-static int register_sub_handlers(void *obj, void *arg, int flags)
-{
-	struct ast_sip_subscription_handler *handler = obj;
-	int *count = arg;
-
 	if (ast_sip_register_subscription_handler(handler)) {
 		ast_log(LOG_WARNING, "Unable to register subscription handler %s\n",
 			handler->event_name);
-	} else {
-		/* if at least one handler registers we will
-		   declare load success*/
-		(*count)++;
-	}
+	}
+
+	return handler;
+}
+
+int ast_sip_register_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;
+	}
+
+	obj->handler = create_and_register_handler(obj->event_name, obj->body_type);
+
+	AST_RWLIST_INSERT_TAIL(&providers, obj, next);
+	ast_module_ref(ast_module_info->self);
+
 	return 0;
 }
 
-/*!
- * \internal
- * \brief Unregister a subscription handler with the pub/sub framework.
- */
-static int unregister_sub_handlers(void *obj, void *arg, int flags)
-{
-	ast_sip_unregister_subscription_handler(obj);
+void ast_sip_unregister_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) {
+			ast_sip_unregister_subscription_handler(i->handler);
+			ao2_cleanup(i->handler);
+			AST_RWLIST_REMOVE_CURRENT(next);
+			ast_module_unref(ast_module_info->self);
+			break;
+		}
+	}
+	AST_RWLIST_TRAVERSE_SAFE_END;
+}
+
+static int load_module(void)
+{
+	return AST_MODULE_LOAD_SUCCESS;
+}
+
+static int unload_module(void)
+{
 	return 0;
 }
 
-static int load_module(void)
-{
-	int count = 0;
-
-	if (!(sub_handlers = ao2_container_alloc(SUB_HANDLER_BUCKETS,
-						 sub_handler_hash, sub_handler_cmp))) {
-		return AST_MODULE_LOAD_FAILURE;
-	}
-
-	/* register providers - for now they have to be specifically added here
-	   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 */
-	ast_sip_register_pidf_xml_provider();
-	ast_sip_register_xpidf_xml_provider();
-	ast_sip_register_cpim_pidf_xml_provider();
-
-	/* create the subscription handlers based upon the providers */
-	create_sub_handlers();
-
-	/* register each subscription handler declaring success if
-	   at least one registers */
-	ao2_callback(sub_handlers, OBJ_NODATA | OBJ_NOLOCK,
-		     register_sub_handlers, &count);
-
-	return count ? AST_MODULE_LOAD_SUCCESS : AST_MODULE_LOAD_FAILURE;
-}
-
-static int unload_module(void)
-{
-	ao2_callback(sub_handlers, OBJ_NODATA | OBJ_NOLOCK,
-		     unregister_sub_handlers, NULL);
-
-	/* unregister providers here, again due to pjsip limitation mentioned above */
-	ast_sip_unregister_pidf_xml_provider();
-	ast_sip_unregister_xpidf_xml_provider();
-	ast_sip_unregister_cpim_pidf_xml_provider();
-
-	ao2_cleanup(sub_handlers);
-
-	return 0;
-}
-
-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SIP Extension State Notifications",
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "SIP Extension State Notifications",
 		.load = load_module,
 		.unload = unload_module,
 		.load_pri = AST_MODPRI_CHANNEL_DEPEND,

Added: team/kharwell/pimp_sip_state/res/res_sip_exten_state.exports.in
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/pimp_sip_state/res/res_sip_exten_state.exports.in?view=auto&rev=389616
==============================================================================
--- team/kharwell/pimp_sip_state/res/res_sip_exten_state.exports.in (added)
+++ team/kharwell/pimp_sip_state/res/res_sip_exten_state.exports.in Thu May 23 15:36:40 2013
@@ -1,0 +1,7 @@
+{
+	global:
+		LINKER_SYMBOL_PREFIXast_sip_register_exten_state_provider;
+		LINKER_SYMBOL_PREFIXast_sip_unregister_exten_state_provider;
+	local:
+		*;
+};

Propchange: team/kharwell/pimp_sip_state/res/res_sip_exten_state.exports.in
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/kharwell/pimp_sip_state/res/res_sip_exten_state.exports.in
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: team/kharwell/pimp_sip_state/res/res_sip_exten_state.exports.in
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Copied: team/kharwell/pimp_sip_state/res/res_sip_pidf.c (from r389484, 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_pidf.c?view=diff&rev=389616&p1=team/kharwell/pimp_sip_state/res/res_sip_providers/res_sip_pidf.c&r1=389484&p2=team/kharwell/pimp_sip_state/res/res_sip_pidf.c&r2=389616
==============================================================================
--- team/kharwell/pimp_sip_state/res/res_sip_providers/res_sip_pidf.c (original)
+++ team/kharwell/pimp_sip_state/res/res_sip_pidf.c Thu May 23 15:36:40 2013
@@ -30,10 +30,9 @@
 #include <pjsip_simple.h>
 #include <pjlib.h>
 
+#include "asterisk/module.h"
 #include "asterisk/res_sip.h"
 #include "asterisk/res_sip_exten_state.h"
-#include "include/res_sip_providers.h"
-
 
 enum state {
 	NOTIFY_OPEN,
@@ -229,25 +228,17 @@
 	.event_name = "presence",
 	.type = "application",
 	.subtype = "pidf+xml",
+	.body_type = "application/pidf+xml",
 	.create_body = pidf_xml_create_body
 };
 
-void ast_sip_register_pidf_xml_provider(void)
-{
-	ast_sip_register_exten_state_provider(&pidf_xml_provider);
-}
-
-void ast_sip_unregister_pidf_xml_provider(void)
-{
-	ast_sip_unregister_exten_state_provider(&pidf_xml_provider);
-}
-
 static int xpidf_xml_create_body(struct ast_sip_exten_state_data *data, const char *local,
 				 const char *remote, struct ast_str **body_text)
 {
+	static pj_str_t STR_ADDR_PARAM = { ";user=ip", 8 };
 	pjxpidf_pres *pres;
 	pj_xml_attr *attr;
-	pj_str_t name;
+	pj_str_t name, uri;
 	char *statestring = NULL, *pidfstate = NULL, *pidfnote = NULL;
 	int local_state, size;
 
@@ -267,8 +258,12 @@
 	pj_strdup2(pool, &attr->value, data->exten);
 
 	attr = find_node_attr(pool, pres, "address", "uri");
-	pj_strdup2(pool, &attr->value, remote);
-	pj_strcat2(&attr->value, ";user=ip");
+
+	uri.ptr = (char*) pj_pool_alloc(pool, strlen(remote) + STR_ADDR_PARAM.slen);
+	pj_strcpy2( &uri, remote);
+	pj_strcat( &uri, &STR_ADDR_PARAM);
+	pj_strdup(pool, &attr->value, &uri);
+
 	create_attr(pool, pj_xml_find_node(pres, pj_cstr(&name, "address")),
 		    "priority", "0.80000");
 
@@ -298,32 +293,49 @@
 	.event_name = "presence",
 	.type = "application",
 	.subtype = "xpidf+xml",
+	.body_type = "application/xpidf+xml",
 	.create_body = xpidf_xml_create_body
 };
-
-void ast_sip_register_xpidf_xml_provider(void)
-{
-	ast_sip_register_exten_state_provider(&xpidf_xml_provider);
-}
-
-void ast_sip_unregister_xpidf_xml_provider(void)
-{
-	ast_sip_unregister_exten_state_provider(&xpidf_xml_provider);
-}
 
 static struct ast_sip_exten_state_provider cpim_pidf_xml_provider = {
 	.event_name = "presence",
 	.type = "application",
 	.subtype = "cpim-pidf+xml",
-	.create_body = xpidf_xml_create_body
+	.body_type = "application/cpim-pidf+xml",
+	.create_body = xpidf_xml_create_body,
 };
 
-void ast_sip_register_cpim_pidf_xml_provider(void)
-{
-	ast_sip_register_exten_state_provider(&cpim_pidf_xml_provider);
-}
-
-void ast_sip_unregister_cpim_pidf_xml_provider(void)
+static int load_module(void)
+{
+	if (ast_sip_register_exten_state_provider(&pidf_xml_provider)) {
+		ast_log(LOG_WARNING, "Unable to load provider event_name=%s, body_type=%s",
+			pidf_xml_provider.event_name, pidf_xml_provider.body_type);
+	}
+
+	if (ast_sip_register_exten_state_provider(&xpidf_xml_provider)) {
+		ast_log(LOG_WARNING, "Unable to load provider event_name=%s, body_type=%s",
+			xpidf_xml_provider.event_name, xpidf_xml_provider.body_type);
+	}
+
+	if (ast_sip_register_exten_state_provider(&cpim_pidf_xml_provider)) {
+		ast_log(LOG_WARNING, "Unable to load provider event_name=%s, body_type=%s",
+			cpim_pidf_xml_provider.event_name, cpim_pidf_xml_provider.body_type);
+	}
+
+	return AST_MODULE_LOAD_SUCCESS;
+}
+
+static int unload_module(void)
 {
 	ast_sip_unregister_exten_state_provider(&cpim_pidf_xml_provider);
-}
+	ast_sip_unregister_exten_state_provider(&xpidf_xml_provider);
+	ast_sip_unregister_exten_state_provider(&pidf_xml_provider);
+
+	return 0;
+}
+
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SIP Extension State PIDF Provider",
+		.load = load_module,
+		.unload = unload_module,
+		.load_pri = AST_MODPRI_CHANNEL_DEPEND,
+);




More information about the asterisk-commits mailing list