summaryrefslogtreecommitdiff
path: root/main/channel.c
diff options
context:
space:
mode:
authorDavid M. Lee <dlee@digium.com>2013-03-25 16:19:55 +0000
committerDavid M. Lee <dlee@digium.com>2013-03-25 16:19:55 +0000
commit4a6237b231df34494e420b577be320cde00d2619 (patch)
tree835d1fa72267de7face0d602c945b21ff59639ac /main/channel.c
parentd484f366f5e2f4a54d760cb39a10391f9ab94f52 (diff)
Move NewCallerid, HangupRequest and SoftHangupRequest to Stasis
HangupRequest and SoftHangupRequest are now ast_channel_blob Stasis messages, with the cause code as an optional field in the blob. NewCallerid now simply watches for changes in the callerid information in channel snapshots, and creates the AMI event appropriately. Since the original NewCallerid event honored the channelvars setting in manager.conf, the channel variables configured there had to become a part of the channel snapshot. These are now a part of every snapshot based event, making the configuration description "every time a channel-oriented event is emitted" less of a lie. There a a few other changes wrapped up in here as well. * When ast_channel_topic() is given NULL for a channel, it returns the ast_channel_topic_all() topic instead of NULL. This can clean up a lot of NULL checking we're doing currently. * The fields Cause and Cause-txt were removed from the base channel information and put only on the Hangup events, since those fields are meaningless outside of a Hangup event. * Removed the pipe-delimiter processing of the channelvars field, since that's been deprecated forever. (closes issue ASTERISK-21096) Review: https://reviewboard.asterisk.org/r/2405/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@383726 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/channel.c')
-rw-r--r--main/channel.c240
1 files changed, 136 insertions, 104 deletions
diff --git a/main/channel.c b/main/channel.c
index 5318e6667..56752f852 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -243,6 +243,18 @@ static void publish_channel_state(struct ast_channel *chan)
stasis_publish(ast_channel_topic(chan), message);
}
+static void publish_channel_blob(struct ast_channel *chan, struct ast_json *blob)
+{
+ RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+ if (blob) {
+ message = ast_channel_blob_create(chan, blob);
+ }
+ if (message) {
+ stasis_publish(ast_channel_topic(chan), message);
+ }
+}
+
+
static void channel_blob_dtor(void *obj)
{
struct ast_channel_blob *event = obj;
@@ -309,22 +321,7 @@ void ast_channel_publish_varset(struct ast_channel *chan, const char *name, cons
"type", "varset",
"variable", name,
"value", value);
- if (!blob) {
- ast_log(LOG_ERROR, "Error creating message\n");
- return;
- }
-
- msg = ast_channel_blob_create(chan, ast_json_ref(blob));
-
- if (!msg) {
- return;
- }
-
- if (chan) {
- stasis_publish(ast_channel_topic(chan), msg);
- } else {
- stasis_publish(ast_channel_topic_all(), msg);
- }
+ publish_channel_blob(chan, blob);
}
@@ -1463,22 +1460,16 @@ int ast_queue_frame_head(struct ast_channel *chan, struct ast_frame *fin)
/*! \brief Queue a hangup frame for channel */
int ast_queue_hangup(struct ast_channel *chan)
{
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+ RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP };
int res;
/* Yeah, let's not change a lock-critical value without locking */
ast_channel_lock(chan);
ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV);
- /*** DOCUMENTATION
- <managerEventInstance>
- <synopsis>Raised when a hangup is requested with no set cause.</synopsis>
- </managerEventInstance>
- ***/
- manager_event(EVENT_FLAG_CALL, "HangupRequest",
- "Channel: %s\r\n"
- "Uniqueid: %s\r\n",
- ast_channel_name(chan),
- ast_channel_uniqueid(chan));
+ blob = ast_json_pack("{s: s}", "type", "hangup_request");
+ publish_channel_blob(chan, blob);
res = ast_queue_frame(chan, &f);
ast_channel_unlock(chan);
@@ -1488,6 +1479,8 @@ int ast_queue_hangup(struct ast_channel *chan)
/*! \brief Queue a hangup frame for channel */
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
{
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+ RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP };
int res;
@@ -1501,21 +1494,10 @@ int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
if (cause < 0) {
f.data.uint32 = ast_channel_hangupcause(chan);
}
- /*** DOCUMENTATION
- <managerEventInstance>
- <synopsis>Raised when a hangup is requested with a specific cause code.</synopsis>
- <syntax>
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='Hangup']/managerEventInstance/syntax/parameter[@name='Cause'])" />
- </syntax>
- </managerEventInstance>
- ***/
- manager_event(EVENT_FLAG_CALL, "HangupRequest",
- "Channel: %s\r\n"
- "Uniqueid: %s\r\n"
- "Cause: %d\r\n",
- ast_channel_name(chan),
- ast_channel_uniqueid(chan),
- cause);
+ blob = ast_json_pack("{s: s, s: i}",
+ "type", "hangup_request",
+ "cause", cause);
+ publish_channel_blob(chan, blob);
res = ast_queue_frame(chan, &f);
ast_channel_unlock(chan);
@@ -2818,25 +2800,16 @@ int ast_softhangup_nolock(struct ast_channel *chan, int cause)
/*! \brief Softly hangup a channel, lock */
int ast_softhangup(struct ast_channel *chan, int cause)
{
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
int res;
ast_channel_lock(chan);
res = ast_softhangup_nolock(chan, cause);
- /*** DOCUMENTATION
- <managerEventInstance>
- <synopsis>Raised when a soft hangup is requested with a specific cause code.</synopsis>
- <syntax>
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='Hangup']/managerEventInstance/syntax/parameter[@name='Cause'])" />
- </syntax>
- </managerEventInstance>
- ***/
- manager_event(EVENT_FLAG_CALL, "SoftHangupRequest",
- "Channel: %s\r\n"
- "Uniqueid: %s\r\n"
- "Cause: %d\r\n",
- ast_channel_name(chan),
- ast_channel_uniqueid(chan),
- cause);
+ blob = ast_json_pack("{s: s, s: i, s: b}",
+ "type", "hangup_request",
+ "cause", cause,
+ "soft", 1);
+ publish_channel_blob(chan, blob);
ast_channel_unlock(chan);
return res;
@@ -6837,39 +6810,6 @@ static void ast_set_owners_and_peers(struct ast_channel *chan1,
}
/*!
- * \pre chan is locked
- */
-static void report_new_callerid(struct ast_channel *chan)
-{
- int pres;
-
- pres = ast_party_id_presentation(&ast_channel_caller(chan)->id);
- /*** DOCUMENTATION
- <managerEventInstance>
- <synopsis>Raised when a channel receives new Caller ID information.</synopsis>
- <syntax>
- <parameter name="CID-CallingPres">
- <para>A description of the Caller ID presentation.</para>
- </parameter>
- </syntax>
- </managerEventInstance>
- ***/
- ast_manager_event(chan, EVENT_FLAG_CALL, "NewCallerid",
- "Channel: %s\r\n"
- "CallerIDNum: %s\r\n"
- "CallerIDName: %s\r\n"
- "Uniqueid: %s\r\n"
- "CID-CallingPres: %d (%s)\r\n",
- ast_channel_name(chan),
- S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""),
- S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""),
- ast_channel_uniqueid(chan),
- pres,
- ast_describe_caller_presentation(pres)
- );
-}
-
-/*!
* \internal
* \brief Transfer COLP between target and transferee channels.
* \since 1.8
@@ -7273,7 +7213,7 @@ void ast_do_masquerade(struct ast_channel *original)
ast_channel_redirecting_set(original, ast_channel_redirecting(clonechan));
ast_channel_redirecting_set(clonechan, &exchange.redirecting);
- report_new_callerid(original);
+ publish_channel_state(original);
/* Restore original timing file descriptor */
ast_channel_set_fd(original, AST_TIMING_FD, ast_channel_timingfd(original));
@@ -7439,7 +7379,7 @@ void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char
ast_cdr_setcid(ast_channel_cdr(chan), chan);
}
- report_new_callerid(chan);
+ publish_channel_state(chan);
ast_channel_unlock(chan);
}
@@ -7458,26 +7398,14 @@ void ast_channel_set_caller(struct ast_channel *chan, const struct ast_party_cal
void ast_channel_set_caller_event(struct ast_channel *chan, const struct ast_party_caller *caller, const struct ast_set_party_caller *update)
{
- const char *pre_set_number;
- const char *pre_set_name;
-
if (ast_channel_caller(chan) == caller) {
/* Don't set to self */
return;
}
ast_channel_lock(chan);
- pre_set_number =
- S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL);
- pre_set_name = S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL);
ast_party_caller_set(ast_channel_caller(chan), caller, update);
- if (S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)
- != pre_set_number
- || S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, NULL)
- != pre_set_name) {
- /* The caller id name or number changed. */
- report_new_callerid(chan);
- }
+ publish_channel_state(chan);
if (ast_channel_cdr(chan)) {
ast_cdr_setcid(ast_channel_cdr(chan), chan);
}
@@ -8671,8 +8599,108 @@ static void prnt_channel_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
prnt(where, "%s", ast_channel_name(chan));
}
+/*!
+ * \brief List of channel variables to append to all channel-related events.
+ */
+struct manager_channel_variable {
+ AST_LIST_ENTRY(manager_channel_variable) entry;
+ unsigned int isfunc:1;
+ char name[];
+};
+
+static AST_RWLIST_HEAD_STATIC(channelvars, manager_channel_variable);
+
+static void free_channelvars(void)
+{
+ struct manager_channel_variable *var;
+ AST_RWLIST_WRLOCK(&channelvars);
+ while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) {
+ ast_free(var);
+ }
+ AST_RWLIST_UNLOCK(&channelvars);
+}
+
+void ast_channel_set_manager_vars(size_t varc, char **vars)
+{
+ size_t i;
+
+ free_channelvars();
+ AST_RWLIST_WRLOCK(&channelvars);
+ for (i = 0; i < varc; ++i) {
+ const char *var = vars[i];
+ struct manager_channel_variable *mcv;
+ if (!(mcv = ast_calloc(1, sizeof(*mcv) + strlen(var) + 1))) {
+ break;
+ }
+ strcpy(mcv->name, var); /* SAFE */
+ if (strchr(var, '(')) {
+ mcv->isfunc = 1;
+ }
+ AST_RWLIST_INSERT_TAIL(&channelvars, mcv, entry);
+ }
+ AST_RWLIST_UNLOCK(&channelvars);
+}
+
+/*!
+ * \brief Destructor for the return value from ast_channel_get_manager_vars().
+ * \param obj AO2 object.
+ */
+static void varshead_dtor(void *obj)
+{
+ struct varshead *head = obj;
+ struct ast_var_t *var;
+
+ while ((var = AST_RWLIST_REMOVE_HEAD(head, entries))) {
+ ast_var_delete(var);
+ }
+}
+
+struct varshead *ast_channel_get_manager_vars(struct ast_channel *chan)
+{
+ RAII_VAR(struct varshead *, ret, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_str *, tmp, NULL, ast_free);
+ struct manager_channel_variable *mcv;
+
+ ret = ao2_alloc(sizeof(*ret), varshead_dtor);
+ tmp = ast_str_create(16);
+
+ if (!ret || !tmp) {
+ return NULL;
+ }
+
+ AST_RWLIST_RDLOCK(&channelvars);
+ AST_LIST_TRAVERSE(&channelvars, mcv, entry) {
+ const char *val = NULL;
+ struct ast_var_t *var;
+
+ if (mcv->isfunc) {
+ if (ast_func_read2(chan, mcv->name, &tmp, 0) == 0) {
+ val = ast_str_buffer(tmp);
+ } else {
+ ast_log(LOG_ERROR,
+ "Error invoking function %s\n", mcv->name);
+ }
+ } else {
+ val = pbx_builtin_getvar_helper(chan, mcv->name);
+ }
+
+ var = ast_var_assign(mcv->name, val ? val : "");
+ if (!var) {
+ AST_RWLIST_UNLOCK(&channelvars);
+ return NULL;
+ }
+
+ AST_RWLIST_INSERT_TAIL(ret, var, entries);
+ }
+ AST_RWLIST_UNLOCK(&channelvars);
+
+ ao2_ref(ret, +1);
+ return ret;
+}
+
static void channels_shutdown(void)
{
+ free_channelvars();
ao2_cleanup(__channel_snapshot);
__channel_snapshot = NULL;
ao2_cleanup(__channel_blob);
@@ -11298,6 +11326,7 @@ static void ast_channel_snapshot_dtor(void *obj)
{
struct ast_channel_snapshot *snapshot = obj;
ast_string_field_free_memory(snapshot);
+ ao2_cleanup(snapshot->manager_vars);
}
struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan)
@@ -11342,6 +11371,9 @@ struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *cha
snapshot->amaflags = ast_channel_amaflags(chan);
snapshot->hangupcause = ast_channel_hangupcause(chan);
snapshot->flags = *ast_channel_flags(chan);
+ snapshot->caller_pres = ast_party_id_presentation(&ast_channel_caller(chan)->id);
+
+ snapshot->manager_vars = ast_channel_get_manager_vars(chan);
ao2_ref(snapshot, +1);
return snapshot;