#include "asterisk/channel.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
+#include "asterisk/stasis.h"
/*** DOCUMENTATION
<application name="NoCDR" language="en_US">
AST_APP_OPTION('e', AST_CDR_FLAG_DISABLE_ALL),
});
+STASIS_MESSAGE_TYPE_DEFN_LOCAL(appcdr_message_type);
+
+/*! \internal \brief Payload for the Stasis message sent to manipulate a CDR */
+struct app_cdr_message_payload {
+ /*! The name of the channel to be manipulated */
+ const char *channel_name;
+ /*! Disable the CDR for this channel */
+ int disable:1;
+ /*! Re-enable the CDR for this channel */
+ int reenable:1;
+ /*! Reset the CDR */
+ int reset:1;
+ /*! If reseting the CDR, keep the variables */
+ int keep_variables:1;
+};
+
+static void appcdr_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
+{
+ struct app_cdr_message_payload *payload;
+
+ if (stasis_message_type(message) != appcdr_message_type()) {
+ return;
+ }
+
+ payload = stasis_message_data(message);
+ if (!payload) {
+ return;
+ }
+
+ if (payload->disable) {
+ if (ast_cdr_set_property(payload->channel_name, AST_CDR_FLAG_DISABLE_ALL)) {
+ ast_log(AST_LOG_WARNING, "Failed to disable CDRs on channel %s\n",
+ payload->channel_name);
+ }
+ }
+
+ if (payload->reenable) {
+ if (ast_cdr_clear_property(payload->channel_name, AST_CDR_FLAG_DISABLE_ALL)) {
+ ast_log(AST_LOG_WARNING, "Failed to enable CDRs on channel %s\n",
+ payload->channel_name);
+ }
+ }
+
+ if (payload->reset) {
+ if (ast_cdr_reset(payload->channel_name, payload->keep_variables)) {
+ ast_log(AST_LOG_WARNING, "Failed to reset CDRs on channel %s\n",
+ payload->channel_name);
+ }
+ }
+}
+
+static int publish_app_cdr_message(struct ast_channel *chan, struct app_cdr_message_payload *payload)
+{
+ RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+ RAII_VAR(struct stasis_subscription *, subscription, NULL, ao2_cleanup);
+
+ message = stasis_message_create(appcdr_message_type(), payload);
+ if (!message) {
+ ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",
+ payload->channel_name);
+ return -1;
+ }
+
+ subscription = stasis_subscribe(ast_channel_topic(chan), appcdr_callback, NULL);
+ if (!subscription) {
+ ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create subscription\n",
+ payload->channel_name);
+ return -1;
+ }
+
+ stasis_publish(ast_channel_topic(chan), message);
+
+ subscription = stasis_unsubscribe_and_join(subscription);
+ return 0;
+}
+
static int resetcdr_exec(struct ast_channel *chan, const char *data)
{
+ RAII_VAR(struct app_cdr_message_payload *, payload,
+ ao2_alloc(sizeof(*payload), NULL), ao2_cleanup);
char *args;
struct ast_flags flags = { 0 };
- int res = 0;
+
+ if (!payload) {
+ return -1;
+ }
if (!ast_strlen_zero(data)) {
args = ast_strdupa(data);
ast_app_parse_options(resetcdr_opts, &flags, NULL, args);
}
+ payload->channel_name = ast_channel_name(chan);
+ payload->reset = 1;
+
if (ast_test_flag(&flags, AST_CDR_FLAG_DISABLE_ALL)) {
- if (ast_cdr_clear_property(ast_channel_name(chan), AST_CDR_FLAG_DISABLE_ALL)) {
- res = 1;
- }
- }
- if (ast_cdr_reset(ast_channel_name(chan), &flags)) {
- res = 1;
+ payload->reenable = 1;
}
- if (res) {
- ast_log(AST_LOG_WARNING, "Failed to reset CDR for channel %s\n", ast_channel_name(chan));
+ if (ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) {
+ payload->keep_variables = 1;
}
- return res;
+
+ return publish_app_cdr_message(chan, payload);
}
static int nocdr_exec(struct ast_channel *chan, const char *data)
{
- if (ast_cdr_set_property(ast_channel_name(chan), AST_CDR_FLAG_DISABLE_ALL)) {
- ast_log(AST_LOG_WARNING, "Failed to disable CDR for channel %s\n", ast_channel_name(chan));
+ RAII_VAR(struct app_cdr_message_payload *, payload,
+ ao2_alloc(sizeof(*payload), NULL), ao2_cleanup);
+
+ if (!payload) {
+ return -1;
}
- return 0;
+ payload->channel_name = ast_channel_name(chan);
+ payload->disable = 1;
+
+ return publish_app_cdr_message(chan, payload);
}
static int unload_module(void)
{
+ STASIS_MESSAGE_TYPE_CLEANUP(appcdr_message_type);
ast_unregister_application(nocdr_app);
ast_unregister_application(resetcdr_app);
return 0;
{
int res = 0;
+ res |= STASIS_MESSAGE_TYPE_INIT(appcdr_message_type);
res |= ast_register_application_xml(nocdr_app, nocdr_exec);
res |= ast_register_application_xml(resetcdr_app, resetcdr_exec);
#include "asterisk/cdr.h"
#include "asterisk/app.h"
#include "asterisk/module.h"
+#include "asterisk/stasis.h"
/*** DOCUMENTATION
<application name="ForkCDR" language="en_US">
AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS),
});
+STASIS_MESSAGE_TYPE_DEFN_LOCAL(forkcdr_message_type);
+
+/*! \internal \brief Message payload for the Stasis message sent to fork the CDR */
+struct fork_cdr_message_payload {
+ /*! The name of the channel whose CDR will be forked */
+ const char *channel_name;
+ /*! Option flags that control how the CDR will be forked */
+ struct ast_flags *flags;
+};
+
+static void forkcdr_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
+{
+ struct fork_cdr_message_payload *payload;
+
+ if (stasis_message_type(message) != forkcdr_message_type()) {
+ return;
+ }
+
+ payload = stasis_message_data(message);
+ if (!payload) {
+ return;
+ }
+
+ if (ast_cdr_fork(payload->channel_name, payload->flags)) {
+ ast_log(AST_LOG_WARNING, "Failed to fork CDR for channel %s\n",
+ payload->channel_name);
+ }
+}
+
static int forkcdr_exec(struct ast_channel *chan, const char *data)
{
+ RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+ RAII_VAR(struct fork_cdr_message_payload *, payload, ao2_alloc(sizeof(*payload), NULL), ao2_cleanup);
+ RAII_VAR(struct stasis_subscription *, subscription, NULL, ao2_cleanup);
+
char *parse;
struct ast_flags flags = { 0, };
AST_DECLARE_APP_ARGS(args,
ast_app_parse_options(forkcdr_exec_options, &flags, NULL, args.options);
}
- if (ast_cdr_fork(ast_channel_name(chan), &flags)) {
- ast_log(AST_LOG_WARNING, "Failed to fork CDR for channel %s\n", ast_channel_name(chan));
+ if (!payload) {
+ return -1;
+ }
+
+ payload->channel_name = ast_channel_name(chan);
+ payload->flags = &flags;
+ message = stasis_message_create(forkcdr_message_type(), payload);
+ if (!message) {
+ ast_log(AST_LOG_WARNING, "Failed to fork CDR for channel %s: unable to create message\n",
+ ast_channel_name(chan));
+ return -1;
+ }
+
+ subscription = stasis_subscribe(ast_channel_topic(chan), forkcdr_callback, NULL);
+ if (!subscription) {
+ ast_log(AST_LOG_WARNING, "Failed to fork CDR for channel %s: unable to create subscription\n",
+ payload->channel_name);
+ return -1;
}
+ stasis_publish(ast_channel_topic(chan), message);
+
+ subscription = stasis_unsubscribe_and_join(subscription);
+
return 0;
}
static int unload_module(void)
{
+ STASIS_MESSAGE_TYPE_CLEANUP(forkcdr_message_type);
+
return ast_unregister_application(app);
}
static int load_module(void)
{
- return ast_register_application_xml(app, forkcdr_exec);
+ int res = 0;
+
+ res |= STASIS_MESSAGE_TYPE_INIT(forkcdr_message_type);
+ res |= ast_register_application_xml(app, forkcdr_exec);
+
+ return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Fork The CDR into 2 separate entities");
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/cdr.h"
+#include "asterisk/stasis.h"
/*** DOCUMENTATION
<function name="CDR" language="en_US">
AST_APP_OPTION('u', OPT_UNPARSED),
});
-static int cdr_read(struct ast_channel *chan, const char *cmd, char *parse,
- char *buf, size_t len)
+struct cdr_func_payload {
+ struct ast_channel *chan;
+ const char *cmd;
+ const char *arguments;
+ const char *value;
+};
+
+struct cdr_func_data {
+ char *buf;
+ size_t len;
+};
+
+STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_read_message_type);
+STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_write_message_type);
+STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_prop_write_message_type);
+
+static void cdr_read_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
{
+ struct cdr_func_data *output = data;
+ struct cdr_func_payload *payload = stasis_message_data(message);
+ char *info;
char *value = NULL;
struct ast_flags flags = { 0 };
char tempbuf[512];
- char *info;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(variable);
AST_APP_ARG(options);
);
- buf[0] = '\0';/* Ensure the buffer is initialized. */
+ if (cdr_read_message_type() != stasis_message_type(message)) {
+ return;
+ }
- if (!chan) {
- return -1;
+ if (!payload || !output) {
+ return;
}
- if (ast_strlen_zero(parse)) {
- ast_log(AST_LOG_WARNING, "FUNC_CDR requires a variable (FUNC_CDR(variable[,option]))\n)");
- return -1;
+ if (ast_strlen_zero(payload->arguments)) {
+ ast_log(AST_LOG_WARNING, "%s requires a variable (%s(variable[,option]))\n)",
+ payload->cmd, payload->cmd);
+ return;
}
- info = ast_strdupa(parse);
+ info = ast_strdupa(payload->arguments);
AST_STANDARD_APP_ARGS(args, info);
if (!ast_strlen_zero(args.options)) {
ast_app_parse_options(cdr_func_options, &flags, NULL, args.options);
}
- if (ast_strlen_zero(ast_channel_name(chan))) {
+ if (ast_strlen_zero(ast_channel_name(payload->chan))) {
/* Format request on a dummy channel */
- ast_cdr_format_var(ast_channel_cdr(chan), args.variable, &value, tempbuf, sizeof(tempbuf), 0);
+ ast_cdr_format_var(ast_channel_cdr(payload->chan), args.variable, &value, tempbuf, sizeof(tempbuf), 0);
if (ast_strlen_zero(value)) {
- return 0;
+ return;
}
ast_copy_string(tempbuf, value, sizeof(tempbuf));
ast_set_flag(&flags, OPT_UNPARSED);
- } else if (ast_cdr_getvar(ast_channel_name(chan), args.variable, tempbuf, sizeof(tempbuf))) {
- return 0;
+ } else if (ast_cdr_getvar(ast_channel_name(payload->chan), args.variable, tempbuf, sizeof(tempbuf))) {
+ return;
}
if (ast_test_flag(&flags, OPT_FLOAT)
if (sscanf(tempbuf, "%30ld", &ms) != 1) {
ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n",
- args.variable, tempbuf, ast_channel_name(chan));
- return 0;
+ args.variable, tempbuf, ast_channel_name(payload->chan));
+ return;
}
dtime = (double)(ms / 1000.0);
snprintf(tempbuf, sizeof(tempbuf), "%lf", dtime);
if (sscanf(tempbuf, "%ld.%ld", &fmt_time.tv_sec, &tv_usec) != 2) {
ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n",
- args.variable, tempbuf, ast_channel_name(chan));
- return 0;
+ args.variable, tempbuf, ast_channel_name(payload->chan));
+ return;
}
fmt_time.tv_usec = tv_usec;
ast_localtime(&fmt_time, &tm, NULL);
if (sscanf(tempbuf, "%8d", &disposition) != 1) {
ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n",
- args.variable, tempbuf, ast_channel_name(chan));
- return 0;
+ args.variable, tempbuf, ast_channel_name(payload->chan));
+ return;
}
snprintf(tempbuf, sizeof(tempbuf), "%s", ast_cdr_disp2str(disposition));
} else if (!strcasecmp("amaflags", args.variable)) {
if (sscanf(tempbuf, "%8d", &amaflags) != 1) {
ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n",
- args.variable, tempbuf, ast_channel_name(chan));
- return 0;
+ args.variable, tempbuf, ast_channel_name(payload->chan));
+ return;
}
snprintf(tempbuf, sizeof(tempbuf), "%s", ast_channel_amaflags2string(amaflags));
}
}
- ast_copy_string(buf, tempbuf, len);
- return 0;
+ ast_copy_string(output->buf, tempbuf, output->len);
}
-static int cdr_write(struct ast_channel *chan, const char *cmd, char *parse,
- const char *value)
+static void cdr_write_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
{
+ struct cdr_func_payload *payload = stasis_message_data(message);
struct ast_flags flags = { 0 };
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(variable);
AST_APP_ARG(options);
);
+ char *parse;
- if (ast_strlen_zero(parse) || !value || !chan) {
- return -1;
+ if (cdr_write_message_type() != stasis_message_type(message)) {
+ return;
}
+ if (!payload) {
+ return;
+ }
+
+ if (ast_strlen_zero(payload->arguments)) {
+ ast_log(AST_LOG_WARNING, "%s requires a variable (%s(variable)=value)\n)",
+ payload->cmd, payload->cmd);
+ return;
+ }
+ if (ast_strlen_zero(payload->value)) {
+ ast_log(AST_LOG_WARNING, "%s requires a value (%s(variable)=value)\n)",
+ payload->cmd, payload->cmd);
+ return;
+ }
+ parse = ast_strdupa(payload->arguments);
AST_STANDARD_APP_ARGS(args, parse);
if (!ast_strlen_zero(args.options)) {
if (!strcasecmp(args.variable, "accountcode")) {
ast_log(AST_LOG_WARNING, "Using the CDR function to set 'accountcode' is deprecated. Please use the CHANNEL function instead.\n");
- ast_channel_lock(chan);
- ast_channel_accountcode_set(chan, value);
- ast_channel_unlock(chan);
+ ast_channel_lock(payload->chan);
+ ast_channel_accountcode_set(payload->chan, payload->value);
+ ast_channel_unlock(payload->chan);
} else if (!strcasecmp(args.variable, "peeraccount")) {
ast_log(AST_LOG_WARNING, "The 'peeraccount' setting is not supported. Please set the 'accountcode' on the appropriate channel using the CHANNEL function.\n");
} else if (!strcasecmp(args.variable, "userfield")) {
- ast_cdr_setuserfield(ast_channel_name(chan), value);
+ ast_cdr_setuserfield(ast_channel_name(payload->chan), payload->value);
} else if (!strcasecmp(args.variable, "amaflags")) {
ast_log(AST_LOG_WARNING, "Using the CDR function to set 'amaflags' is deprecated. Please use the CHANNEL function instead.\n");
- if (isdigit(*value)) {
+ if (isdigit(*payload->value)) {
int amaflags;
- sscanf(value, "%30d", &amaflags);
- ast_channel_lock(chan);
- ast_channel_amaflags_set(chan, amaflags);
- ast_channel_unlock(chan);
+ sscanf(payload->value, "%30d", &amaflags);
+ ast_channel_lock(payload->chan);
+ ast_channel_amaflags_set(payload->chan, amaflags);
+ ast_channel_unlock(payload->chan);
} else {
- ast_channel_lock(chan);
- ast_channel_amaflags_set(chan, ast_channel_string2amaflag(value));
- ast_channel_unlock(chan);
+ ast_channel_lock(payload->chan);
+ ast_channel_amaflags_set(payload->chan, ast_channel_string2amaflag(payload->value));
+ ast_channel_unlock(payload->chan);
}
} else {
- ast_cdr_setvar(ast_channel_name(chan), args.variable, value);
+ ast_cdr_setvar(ast_channel_name(payload->chan), args.variable, payload->value);
}
-
- return 0;
+ return;
}
-static int cdr_prop_write(struct ast_channel *chan, const char *cmd, char *parse,
- const char *value)
+static void cdr_prop_write_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
{
+ struct cdr_func_payload *payload = stasis_message_data(message);
enum ast_cdr_options option;
-
+ char *parse;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(variable);
AST_APP_ARG(options);
);
- if (ast_strlen_zero(parse) || !value || !chan) {
- return -1;
+ if (cdr_prop_write_message_type() != stasis_message_type(message)) {
+ return;
}
+ if (!payload) {
+ return;
+ }
+
+ if (ast_strlen_zero(payload->arguments)) {
+ ast_log(AST_LOG_WARNING, "%s requires a variable (%s(variable)=value)\n)",
+ payload->cmd, payload->cmd);
+ return;
+ }
+ if (ast_strlen_zero(payload->value)) {
+ ast_log(AST_LOG_WARNING, "%s requires a value (%s(variable)=value)\n)",
+ payload->cmd, payload->cmd);
+ return;
+ }
+ parse = ast_strdupa(payload->arguments);
AST_STANDARD_APP_ARGS(args, parse);
if (!strcasecmp("party_a", args.variable)) {
} else if (!strcasecmp("disable", args.variable)) {
option = AST_CDR_FLAG_DISABLE_ALL;
} else {
- ast_log(AST_LOG_WARNING, "Unknown option %s used with CDR_PROP\n", args.variable);
- return 0;
+ ast_log(AST_LOG_WARNING, "Unknown option %s used with %s\n", args.variable, payload->cmd);
+ return;
}
- if (ast_true(value)) {
- ast_cdr_set_property(ast_channel_name(chan), option);
+ if (ast_true(payload->value)) {
+ ast_cdr_set_property(ast_channel_name(payload->chan), option);
} else {
- ast_cdr_clear_property(ast_channel_name(chan), option);
+ ast_cdr_clear_property(ast_channel_name(payload->chan), option);
+ }
+}
+
+
+static int cdr_read(struct ast_channel *chan, const char *cmd, char *parse,
+ char *buf, size_t len)
+{
+ RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+ RAII_VAR(struct cdr_func_payload *, payload,
+ ao2_alloc(sizeof(*payload), NULL), ao2_cleanup);
+ struct cdr_func_data output = { 0, };
+
+ if (!payload) {
+ return -1;
}
+ payload->chan = chan;
+ payload->cmd = cmd;
+ payload->arguments = parse;
+
+ buf[0] = '\0';/* Ensure the buffer is initialized. */
+ output.buf = buf;
+ output.len = len;
+
+ message = stasis_message_create(cdr_read_message_type(), payload);
+ if (!message) {
+ ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",
+ ast_channel_name(chan));
+ return -1;
+ }
+
+ /* If this is a request on a dummy channel, we're doing post-processing on an
+ * already dispatched CDR. Simply call the callback to calculate the value and
+ * return, instead of posting to Stasis as we would for a running channel.
+ */
+ if (ast_strlen_zero(ast_channel_name(chan))) {
+ cdr_read_callback(NULL, NULL, message);
+ } else {
+ RAII_VAR(struct stasis_subscription *, subscription, NULL, ao2_cleanup);
+
+ subscription = stasis_subscribe(ast_channel_topic(chan), cdr_read_callback, &output);
+ if (!subscription) {
+ ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create subscription\n",
+ ast_channel_name(chan));
+ return -1;
+ }
+
+ stasis_publish(ast_channel_topic(chan), message);
+
+ subscription = stasis_unsubscribe_and_join(subscription);
+ }
+
+ return 0;
+}
+
+static int cdr_write(struct ast_channel *chan, const char *cmd, char *parse,
+ const char *value)
+{
+ RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+ RAII_VAR(struct cdr_func_payload *, payload,
+ ao2_alloc(sizeof(*payload), NULL), ao2_cleanup);
+ RAII_VAR(struct stasis_subscription *, subscription, NULL, ao2_cleanup);
+
+ if (!payload) {
+ return -1;
+ }
+ payload->chan = chan;
+ payload->cmd = cmd;
+ payload->arguments = parse;
+ payload->value = value;
+
+ message = stasis_message_create(cdr_write_message_type(), payload);
+ if (!message) {
+ ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",
+ ast_channel_name(chan));
+ return -1;
+ }
+
+ subscription = stasis_subscribe(ast_channel_topic(chan), cdr_write_callback, NULL);
+ if (!subscription) {
+ ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create subscription\n",
+ ast_channel_name(chan));
+ return -1;
+ }
+
+ stasis_publish(ast_channel_topic(chan), message);
+
+ subscription = stasis_unsubscribe_and_join(subscription);
+
+ return 0;
+}
+
+static int cdr_prop_write(struct ast_channel *chan, const char *cmd, char *parse,
+ const char *value)
+{
+ RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+ RAII_VAR(struct cdr_func_payload *, payload,
+ ao2_alloc(sizeof(*payload), NULL), ao2_cleanup);
+ RAII_VAR(struct stasis_subscription *, subscription, NULL, ao2_cleanup);
+
+ if (!payload) {
+ return -1;
+ }
+ payload->chan = chan;
+ payload->cmd = cmd;
+ payload->arguments = parse;
+ payload->value = value;
+
+ message = stasis_message_create(cdr_prop_write_message_type(), payload);
+ if (!message) {
+ ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",
+ ast_channel_name(chan));
+ return -1;
+ }
+
+ subscription = stasis_subscribe(ast_channel_topic(chan), cdr_prop_write_callback, NULL);
+ if (!subscription) {
+ ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create subscription\n",
+ ast_channel_name(chan));
+ return -1;
+ }
+
+ stasis_publish(ast_channel_topic(chan), message);
+
+ subscription = stasis_unsubscribe_and_join(subscription);
+
return 0;
}
{
int res = 0;
+ STASIS_MESSAGE_TYPE_CLEANUP(cdr_read_message_type);
+ STASIS_MESSAGE_TYPE_CLEANUP(cdr_write_message_type);
+ STASIS_MESSAGE_TYPE_CLEANUP(cdr_prop_write_message_type);
res |= ast_custom_function_unregister(&cdr_function);
res |= ast_custom_function_unregister(&cdr_prop_function);
{
int res = 0;
+ res |= STASIS_MESSAGE_TYPE_INIT(cdr_read_message_type);
+ res |= STASIS_MESSAGE_TYPE_INIT(cdr_write_message_type);
+ res |= STASIS_MESSAGE_TYPE_INIT(cdr_prop_write_message_type);
res |= ast_custom_function_register(&cdr_function);
res |= ast_custom_function_register(&cdr_prop_function);