[asterisk-commits] kharwell: branch kharwell/gulp_notify r392782 - in /team/kharwell/gulp_notify...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Jun 24 17:17:02 CDT 2013


Author: kharwell
Date: Mon Jun 24 17:17:00 2013
New Revision: 392782

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=392782
Log:
addressed some review issues

Modified:
    team/kharwell/gulp_notify/include/asterisk/res_sip.h
    team/kharwell/gulp_notify/res/res_sip_notify.c

Modified: team/kharwell/gulp_notify/include/asterisk/res_sip.h
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/gulp_notify/include/asterisk/res_sip.h?view=diff&rev=392782&r1=392781&r2=392782
==============================================================================
--- team/kharwell/gulp_notify/include/asterisk/res_sip.h (original)
+++ team/kharwell/gulp_notify/include/asterisk/res_sip.h Mon Jun 24 17:17:00 2013
@@ -1181,9 +1181,9 @@
 struct ast_sip_endpoint *ast_pjsip_rdata_get_endpoint(pjsip_rx_data *rdata);
 
 /*!
- * \brief Get the current defined endpoints
- *
- * \retval The current endpoints loaded by res_sip
+ * \brief Retrieve any endpoints currently loaded by sorcery.
+ *
+ * \retval Endpoints loaded by sorcery, NULL if no endpoints found.
  */
 struct ao2_container *ast_sip_get_endpoints(void);
 

Modified: team/kharwell/gulp_notify/res/res_sip_notify.c
URL: http://svnview.digium.com/svn/asterisk/team/kharwell/gulp_notify/res/res_sip_notify.c?view=diff&rev=392782&r1=392781&r2=392782
==============================================================================
--- team/kharwell/gulp_notify/res/res_sip_notify.c (original)
+++ team/kharwell/gulp_notify/res/res_sip_notify.c Mon Jun 24 17:17:00 2013
@@ -23,7 +23,7 @@
 
 #include "asterisk.h"
 
-#include "pjsua-lib/pjsua.h"
+#include <pjsip.h>
 
 #include "asterisk/cli.h"
 #include "asterisk/config.h"
@@ -42,11 +42,151 @@
  */
 static const char notify_config[] = "sip_notify.conf";
 
-/*!
- * \internal
- * \brief A list of configured NOTIFY payload types to send.
- */
-static struct ast_config *notify_types = NULL;
+struct notify_option_item {
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(name);
+		AST_STRING_FIELD(value);
+	);
+};
+
+static void notify_option_item_destroy(void *obj)
+{
+	struct notify_option_item *item = obj;
+
+	ast_string_field_free_memory(item);
+}
+
+struct notify_option {
+	/*! The name of the notify option */
+	const char *name;
+	/*! Contains header and/or content information */
+	struct ao2_container *items;
+};
+
+static int notify_option_hash(const void *obj, int flags)
+{
+	const struct notify_option *option = obj;
+	return ast_str_case_hash(flags & OBJ_KEY ? obj : option->name);
+}
+
+static int notify_option_cmp(void *obj, void *arg, int flags)
+{
+	struct notify_option *option1 = obj;
+	struct notify_option *option2 = arg;
+	const char *key = flags & OBJ_KEY ? arg : option2->name;
+
+	return strcasecmp(option1->name, key) ? 0 : CMP_MATCH;
+}
+
+static void notify_option_destroy(void *obj)
+{
+	struct notify_option *option = obj;
+
+	ast_free((char *) option->name);
+	ao2_cleanup(option->items);
+}
+
+static void *notify_option_alloc(const char *category)
+{
+	struct notify_option *option = ao2_alloc(
+		sizeof(*option), notify_option_destroy);
+
+	if (!option) {
+		return NULL;
+	}
+
+	if (!(option->name = ast_strdup(category))) {
+		ao2_cleanup(option);
+		return NULL;
+	}
+
+	if (!(option->items = ao2_container_alloc_list(
+		      AO2_ALLOC_OPT_LOCK_NOLOCK,
+		      AO2_CONTAINER_ALLOC_OPT_DUPS_ALLOW, NULL, NULL))) {
+		ao2_cleanup(option);
+		return NULL;
+	}
+
+	return option;
+}
+
+static void *notify_option_find(struct ao2_container *container, const char *category)
+{
+	return ao2_find(container, category, OBJ_KEY);
+}
+
+static int notify_option_handler(const struct aco_option *opt,
+				 struct ast_variable *var, void *obj)
+{
+	struct notify_option *option = obj;
+
+	RAII_VAR(struct notify_option_item *, item,
+		 ao2_alloc(sizeof(*item), notify_option_item_destroy), ao2_cleanup);
+
+	if (!item || ast_string_field_init(item, 32)) {
+		return -1;
+	}
+
+	ast_string_field_set(item, name, var->name);
+	ast_string_field_set(item, value, var->value);
+
+	if (!ao2_link(option->items, item)) {
+		return -1;
+	}
+
+	return 0;
+}
+
+struct notify_cfg {
+	struct ao2_container *notify_options;
+};
+
+static void notify_cfg_destroy(void *obj)
+{
+	struct notify_cfg *cfg = obj;
+	ao2_cleanup(cfg->notify_options);
+}
+
+static void *notify_cfg_alloc(void)
+{
+	struct notify_cfg *cfg;
+
+	if (!(cfg = ao2_alloc(sizeof(*cfg), notify_cfg_destroy))) {
+		return NULL;
+	}
+
+	if (!(cfg->notify_options = ao2_container_alloc_options(
+		      AO2_ALLOC_OPT_LOCK_NOLOCK, 20, notify_option_hash,
+		      notify_option_cmp))) {
+		ao2_cleanup(cfg);
+		return NULL;
+	}
+
+	return cfg;
+}
+
+static struct aco_type notify_option = {
+	.type = ACO_ITEM,
+	.name = "notify",
+	.category_match = ACO_BLACKLIST,
+	.category = "^general$",
+	.item_offset = offsetof(struct notify_cfg, notify_options),
+	.item_alloc = notify_option_alloc,
+	.item_find = notify_option_find
+};
+
+static struct aco_type *notify_options[] = ACO_TYPES(&notify_option);
+
+static struct aco_file module_conf = {
+	.filename = notify_config,
+	.types = ACO_TYPES(&notify_option),
+};
+
+AO2_GLOBAL_OBJ_STATIC(globals);
+
+CONFIG_INFO_STANDARD(notify_cfg, globals, notify_cfg_alloc,
+	.files = ACO_FILES(&module_conf)
+);
 
 /*!
  * \internal
@@ -55,37 +195,35 @@
 struct notify_data {
 	/*! The endpoint being notified */
 	struct ast_sip_endpoint *endpoint;
-	/*! The variable data of headers, types and content */
-	struct ast_variable *vars;
-	/*! If true destroy vars on destruction of this object */
-	char destroy_vars;
+	/*! The info of headers, types and content */
+	void *info;
+	/*! Function to help build notify request */
+	void (*build_notify)(pjsip_tx_data *, void *);
 };
 
 /*!
  * \internal
- * \brief Destroy the notify data releasing any resources.
- */
-static void notify_data_destroy(void *obj)
+ * \brief Destroy the notify CLI data releasing any resources.
+ */
+static void notify_cli_data_destroy(void *obj)
 {
 	struct notify_data *data = obj;
 
 	ao2_cleanup(data->endpoint);
-
-	if (data->destroy_vars) {
-		ast_variables_destroy(data->vars);
-	}
-}
-
-/*!
- * \internal
- * \brief Construct a notify data object.
- */
-static struct notify_data* notify_data_create(struct ast_sip_endpoint *endpoint,
-					      struct ast_variable *vars,
-					      char destroy_vars)
-{
-	struct notify_data *data = ao2_alloc(sizeof(*data), notify_data_destroy);
-
+	ao2_cleanup(data->info);
+}
+
+static void build_cli_notify(pjsip_tx_data *tdata, void *info);
+
+/*!
+ * \internal
+ * \brief Construct a notify data object for CLI.
+ */
+static struct notify_data* notify_cli_data_create(
+	struct ast_sip_endpoint *endpoint, void *info)
+{
+	struct notify_data *data = ao2_alloc(sizeof(*data),
+					     notify_cli_data_destroy);
 	if (!data) {
 		return NULL;
 	}
@@ -93,8 +231,47 @@
 	data->endpoint = endpoint;
 	ao2_ref(data->endpoint, +1);
 
-	data->vars = vars;
-	data->destroy_vars = destroy_vars;
+	data->info = info;
+	ao2_ref(data->info, +1);
+
+	data->build_notify = build_cli_notify;
+
+	return data;
+}
+
+/*!
+ * \internal
+ * \brief Destroy the notify AMI data releasing any resources.
+ */
+static void notify_ami_data_destroy(void *obj)
+{
+	struct notify_data *data = obj;
+	struct ast_variable *info = data->info;
+
+	ao2_cleanup(data->endpoint);
+	ast_variables_destroy(info);
+}
+
+static void build_ami_notify(pjsip_tx_data *tdata, void *info);
+
+/*!
+ * \internal
+ * \brief Construct a notify data object for AMI.
+ */
+static struct notify_data* notify_ami_data_create(
+	struct ast_sip_endpoint *endpoint, void *info)
+{
+	struct notify_data *data = ao2_alloc(sizeof(*data),
+					     notify_ami_data_destroy);
+	if (!data) {
+		return NULL;
+	}
+
+	data->endpoint = endpoint;
+	ao2_ref(data->endpoint, +1);
+
+	data->info = info;
+	data->build_notify = build_ami_notify;
 
 	return data;
 }
@@ -132,45 +309,16 @@
 
 /*!
  * \internal
- * \brief Build the NOTIFY request adding header and content when specified.
- */
-static void build_notify(pjsip_tx_data *tdata, struct ast_variable *vars)
-{
-	RAII_VAR(struct ast_str *, content_type, NULL, ast_free);
-	RAII_VAR(struct ast_str *, content, NULL, ast_free);
-	struct ast_sip_body body;
-	struct ast_variable *i;
-
-	ast_sip_add_header(tdata, "Subscription-State", "terminated");
-
-	for (i = vars; i; i = i->next) {
-		if (not_allowed(i->name)) {
-			ast_log(LOG_WARNING, "Cannot specify %s header, "
-				"ignoring\n", i->name);
-			continue;
-		}
-
-		if (!strcasecmp(i->name, "Content-type")) {
-			if (!content_type) {
-				content_type = ast_str_create(CONTENT_TYPE_SIZE);
-			}
-			ast_str_set(&content_type, 0,"%s", i->value);
-		} else if (!strcasecmp(i->name, "Content")) {
-			if (!content) {
-				content = ast_str_create(CONTENT_SIZE);
-			}
-
-			if (ast_str_strlen(content)) {
-				ast_str_append(&content, 0, "\r\n");
-			}
-			ast_str_append(&content, 0, "%s", i->value);
-		} else {
-			ast_sip_add_header(tdata, i->name, i->value);
-		}
-	}
-
+ * \brief If a content type was specified add it and the content body to the
+ *        NOTIFY request.
+ */
+static void build_notify_body(pjsip_tx_data *tdata, struct ast_str *content_type,
+			      struct ast_str *content)
+{
 	if (content_type) {
 		char *p;
+		struct ast_sip_body body;
+
 		if (content) {
 			body.body_text = ast_str_buffer(content);
 		}
@@ -182,6 +330,82 @@
 		}
 		ast_sip_add_body(tdata, &body);
 	}
+}
+
+/*!
+ * \internal
+ * \brief Build the NOTIFY request adding content or header info.
+ */
+static void build_notify(pjsip_tx_data *tdata, const char *name, const char *value,
+			 struct ast_str **content_type, struct ast_str **content)
+{
+	if (not_allowed(name)) {
+		ast_log(LOG_WARNING, "Cannot specify %s header, "
+			"ignoring\n", name);
+		return;
+	}
+
+	if (!strcasecmp(name, "Content-type")) {
+		if (!(*content_type)) {
+			*content_type = ast_str_create(CONTENT_TYPE_SIZE);
+		}
+		ast_str_set(content_type, 0,"%s", value);
+	} else if (!strcasecmp(name, "Content")) {
+		if (!(*content)) {
+			*content = ast_str_create(CONTENT_SIZE);
+		}
+
+		if (ast_str_strlen(*content)) {
+			ast_str_append(content, 0, "\r\n");
+		}
+		ast_str_append(content, 0, "%s", value);
+	} else {
+		ast_sip_add_header(tdata, name, value);
+	}
+}
+
+/*!
+ * \internal
+ * \brief Build the NOTIFY request from CLI info adding header and content
+ *        when specified.
+ */
+static void build_cli_notify(pjsip_tx_data *tdata, void *info)
+{
+	struct notify_option *option = info;
+	RAII_VAR(struct ast_str *, content_type, NULL, ast_free);
+	RAII_VAR(struct ast_str *, content, NULL, ast_free);
+
+	struct notify_option_item *item;
+	struct ao2_iterator i = ao2_iterator_init(option->items, 0);
+
+	while ((item = ao2_iterator_next(&i))) {
+		build_notify(tdata, item->name, item->value,
+			     &content_type, &content);
+		ao2_cleanup(item);
+	}
+	ao2_iterator_destroy(&i);
+
+	build_notify_body(tdata, content_type, content);
+}
+
+/*!
+ * \internal
+ * \brief Build the NOTIFY request from AMI info adding header and content
+ *        when specified.
+ */
+static void build_ami_notify(pjsip_tx_data *tdata, void *info)
+{
+	struct ast_variable *vars = info;
+	RAII_VAR(struct ast_str *, content_type, NULL, ast_free);
+	RAII_VAR(struct ast_str *, content, NULL, ast_free);
+	struct ast_variable *i;
+
+	for (i = vars; i; i = i->next) {
+		build_notify(tdata, i->name, i->value,
+			     &content_type, &content);
+	}
+
+	build_notify_body(tdata, content_type, content);
 }
 
 /*!
@@ -201,7 +425,8 @@
 		return -1;
 	}
 
-	build_notify(tdata, data->vars);
+	ast_sip_add_header(tdata, "Subscription-State", "terminated");
+	data->build_notify(tdata, data->info);
 
 	if (ast_sip_send_request(tdata, NULL, data->endpoint)) {
 		pjsip_tx_data_dec_ref(tdata);
@@ -255,13 +480,14 @@
 	TASK_PUSH_ERROR
 };
 
+typedef struct notify_data *(*task_data_create)(
+	struct ast_sip_endpoint *, void *info);
 /*!
  * \internal
  * \brief Send a NOTIFY request to the endpoint within a threaded task.
  */
-static enum notify_result push_notify(const char *endpoint_name,
-				      struct ast_variable *vars,
-				      char destroy_vars)
+static enum notify_result push_notify(const char *endpoint_name, void *info,
+				      task_data_create data_create)
 {
 	RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
 	struct notify_data *data;
@@ -271,7 +497,7 @@
 		return INVALID_ENDPOINT;
 	}
 
-	if (!(data = notify_data_create(endpoint, vars, destroy_vars))) {
+	if (!(data = data_create(endpoint, info))) {
 		return ALLOC_ERROR;
 	}
 
@@ -324,20 +550,25 @@
 
 	if (pos == 2) {
 		int which = 0;
-		char *cat = NULL;
 		int wordlen = strlen(word);
 
+		RAII_VAR(struct notify_cfg *, cfg,
+			 ao2_global_obj_ref(globals), ao2_cleanup);
+		struct notify_option *option;
+
 		/* do completion for notify type */
-
-		if (!notify_types)
-			return NULL;
-
-		while ((cat = ast_category_browse(notify_types, cat))) {
-			if (!strncasecmp(word, cat, wordlen) && ++which > state) {
-				c = ast_strdup(cat);
+		struct ao2_iterator i = ao2_iterator_init(cfg->notify_options, 0);
+		while ((option = ao2_iterator_next(&i))) {
+			if (!strncasecmp(word, option->name, wordlen) && ++which > state) {
+				c = ast_strdup(option->name);
+			}
+
+			ao2_cleanup(option);
+			if (c) {
 				break;
 			}
 		}
+		ao2_iterator_destroy(&i);
 		return c;
 	}
 	return pos > 2 ? cli_complete_endpoint(word, state) : NULL;
@@ -353,7 +584,9 @@
  */
 static char *cli_notify(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	struct ast_variable *vars;
+	RAII_VAR(struct notify_cfg *, cfg, NULL, ao2_cleanup);
+	RAII_VAR(struct notify_option *, option, NULL, ao2_cleanup);
+
 	int i;
 
 	switch (cmd) {
@@ -361,7 +594,7 @@
 		e->command = "gulp notify";
 		e->usage =
 			"Usage: gulp notify <type> <peer> [<peer>...]\n"
-			"       Send a NOTIFY message to a SIP peer or peers\n"
+			"       Send a NOTIFY request to an endpoint\n"
 			"       Message types are defined in sip_notify.conf\n";
 		return NULL;
 	case CLI_GENERATE:
@@ -372,13 +605,10 @@
 		return CLI_SHOWUSAGE;
 	}
 
-	if (!notify_types) {
-		ast_cli(a->fd, "%s not found, or no types listed there\n",
-			notify_config);
-		return CLI_FAILURE;
-	}
-
-	if (!(vars = ast_variable_browse(notify_types, a->argv[2]))) {
+	cfg = ao2_global_obj_ref(globals);
+
+	if (!(option = notify_option_find(cfg->notify_options, a->argv[2])))
+	{
 		ast_cli(a->fd, "Unable to find notify type '%s'\n",
 			a->argv[2]);
 		return CLI_FAILURE;
@@ -388,9 +618,10 @@
 		ast_cli(a->fd, "Sending NOTIFY of type '%s' to '%s'\n",
 			a->argv[2], a->argv[i]);
 
-		switch (push_notify(a->argv[i], vars, 0)) {
+		switch (push_notify(a->argv[i], option,
+				    notify_cli_data_create)) {
 		case INVALID_ENDPOINT:
-			ast_log(LOG_WARNING, "Unable to retrieve endpoint %s\n",
+			ast_cli(a->fd, "Unable to retrieve endpoint %s\n",
 				a->argv[i]);
 			break;
 		case ALLOC_ERROR:
@@ -408,7 +639,7 @@
 }
 
 static struct ast_cli_entry cli_options[] = {
-	AST_CLI_DEFINE(cli_notify, "Send an OPTIONS request to a SIP endpoint")
+	AST_CLI_DEFINE(cli_notify, "Send a NOTIFY request to a SIP endpoint")
 };
 
 /*!
@@ -429,7 +660,7 @@
 		endpoint_name += 4;
 	}
 
-	switch (push_notify(endpoint_name, vars, 1)) {
+	switch (push_notify(endpoint_name, vars, notify_ami_data_create)) {
 	case INVALID_ENDPOINT:
 		astman_send_error_va(s, m, "Unable to retrieve endpoint %s\n",
 			endpoint_name);
@@ -448,33 +679,17 @@
 	return 0;
 }
 
-/*!
- * \internal
- * \brief [Re]Load data from the configuration file.
- */
-static int load_config(int reload)
-{
-	struct ast_flags flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
-
-	if (notify_types) {
-		ast_config_destroy(notify_types);
-	}
-
-	if ((notify_types = ast_config_load(
-		     notify_config, flags)) == CONFIG_STATUS_FILEINVALID) {
-
-		ast_log(LOG_ERROR, "Unable to parse %s - invalid content.\n",
-			notify_config);
-		notify_types = NULL;
-		return -1;
-	}
-
-	return 0;
-}
-
 static int load_module(void)
 {
-	if (load_config(0)) {
+	if (aco_info_init(&notify_cfg)) {
+		return AST_MODULE_LOAD_DECLINE;
+	}
+
+	aco_option_register_custom(&notify_cfg, "^.*$", ACO_REGEX, notify_options,
+				   "", notify_option_handler, 0);
+
+	if (aco_process_config(&notify_cfg, 0)) {
+		aco_info_destroy(&notify_cfg);
 		return AST_MODULE_LOAD_DECLINE;
 	}
 
@@ -486,13 +701,15 @@
 
 static int reload_module(void)
 {
-	return load_config(1) ? AST_MODULE_LOAD_DECLINE :
-		AST_MODULE_LOAD_SUCCESS;
+	return aco_process_config(&notify_cfg, 1) ?
+		AST_MODULE_LOAD_DECLINE : 0;
 }
 
 static int unload_module(void)
 {
 	ast_manager_unregister("GulpNotify");
+	aco_info_destroy(&notify_cfg);
+
 	return 0;
 }
 




More information about the asterisk-commits mailing list