summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2013-12-14 17:19:41 +0000
committerJoshua Colp <jcolp@digium.com>2013-12-14 17:19:41 +0000
commit3a5cc054ed3efb0733a70a6945880b71506b5757 (patch)
tree2435f375316c92c0009d51bb9ee1bc12e7ea0810 /main
parent661ac149115dd23c421c1445a1d07f92249db243 (diff)
res_stasis: Expose event for call forwarding and follow forwarded channel.
This change adds an event for when an originated call is redirected to another target. This event contains the original channel and the newly created channel. If a stasis subscription exists on the original originated channel for a stasis application then a new subscription will also be created on the stasis application to the redirected channel. This allows the application to follow the call path completely. (closes issue ASTERISK-22719) Reported by: Joshua Colp Review: https://reviewboard.asterisk.org/r/3054/ ........ Merged revisions 403808 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@403810 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r--main/dial.c7
-rw-r--r--main/stasis_channels.c73
2 files changed, 74 insertions, 6 deletions
diff --git a/main/dial.c b/main/dial.c
index 134386735..ca0b9c8d1 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -465,14 +465,17 @@ static int handle_call_forward(struct ast_dial *dial, struct ast_dial_channel *c
channel->device = ast_strdup(device);
AST_LIST_UNLOCK(&dial->channels);
-
/* Drop the original channel */
- ast_hangup(original);
channel->owner = NULL;
/* Finally give it a go... send it out into the world */
begin_dial_channel(channel, chan, chan ? 0 : 1, predial_string);
+ ast_channel_publish_dial_forward(chan, original, channel->owner, NULL, "CANCEL",
+ ast_channel_call_forward(original));
+
+ ast_hangup(original);
+
return 0;
}
diff --git a/main/stasis_channels.c b/main/stasis_channels.c
index 38aac982e..8a39bdfcb 100644
--- a/main/stasis_channels.c
+++ b/main/stasis_channels.c
@@ -287,14 +287,21 @@ static void channel_blob_dtor(void *obj)
ast_json_unref(event->blob);
}
+/*! \brief Dummy callback for receiving events */
+static void dummy_event_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
+{
+}
+
void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_channel *peer,
- const char *dialstring, const char *dialstatus, const char *forward)
+ struct ast_channel *forwarded, const char *dialstring, const char *dialstatus,
+ const char *forward)
{
RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
RAII_VAR(struct ast_channel_snapshot *, peer_snapshot, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_channel_snapshot *, forwarded_snapshot, NULL, ao2_cleanup);
ast_assert(peer != NULL);
blob = ast_json_pack("{s: s, s: s, s: s}",
@@ -323,18 +330,33 @@ void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_cha
}
ast_multi_channel_blob_add_channel(payload, "peer", peer_snapshot);
+ if (forwarded) {
+ forwarded_snapshot = ast_channel_snapshot_create(forwarded);
+ if (!forwarded_snapshot) {
+ return;
+ }
+ ast_multi_channel_blob_add_channel(payload, "forwarded", forwarded_snapshot);
+ }
+
msg = stasis_message_create(ast_channel_dial_type(), payload);
if (!msg) {
return;
}
- publish_message_for_channel_topics(msg, caller);
+ if (forwarded) {
+ struct stasis_subscription *subscription = stasis_subscribe(ast_channel_topic(peer), dummy_event_cb, NULL);
+
+ stasis_publish(ast_channel_topic(peer), msg);
+ stasis_unsubscribe_and_join(subscription);
+ } else {
+ publish_message_for_channel_topics(msg, caller);
+ }
}
void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer,
const char *dialstring, const char *dialstatus)
{
- ast_channel_publish_dial_forward(caller, peer, dialstring, dialstatus, NULL);
+ ast_channel_publish_dial_forward(caller, peer, NULL, dialstring, dialstatus, NULL);
}
static struct stasis_message *create_channel_blob_message(struct ast_channel_snapshot *snapshot,
@@ -931,11 +953,54 @@ static struct ast_json *hangup_request_to_json(
return channel_blob_to_json(message, "ChannelHangupRequest", sanitize);
}
+static struct ast_json *dial_to_json(
+ struct stasis_message *message,
+ const struct stasis_message_sanitizer *sanitize)
+{
+ struct ast_multi_channel_blob *payload = stasis_message_data(message);
+ struct ast_json *blob = ast_multi_channel_blob_get_json(payload);
+ struct ast_json *caller_json = ast_channel_snapshot_to_json(ast_multi_channel_blob_get_channel(payload, "caller"), sanitize);
+ struct ast_json *peer_json = ast_channel_snapshot_to_json(ast_multi_channel_blob_get_channel(payload, "peer"), sanitize);
+ struct ast_json *forwarded_json = ast_channel_snapshot_to_json(ast_multi_channel_blob_get_channel(payload, "forwarded"), sanitize);
+ struct ast_json *json;
+ const struct timeval *tv = stasis_message_timestamp(message);
+ int res = 0;
+
+ json = ast_json_pack("{s: s, s: o, s: O, s: O, s: O}",
+ "type", "Dial",
+ "timestamp", ast_json_timeval(*tv, NULL),
+ "dialstatus", ast_json_object_get(blob, "dialstatus"),
+ "forward", ast_json_object_get(blob, "forward"),
+ "dialstring", ast_json_object_get(blob, "dialstring"));
+ if (!json) {
+ return NULL;
+ }
+
+ if (caller_json) {
+ res |= ast_json_object_set(json, "caller", caller_json);
+ }
+ if (peer_json) {
+ res |= ast_json_object_set(json, "peer", peer_json);
+ }
+ if (forwarded_json) {
+ res |= ast_json_object_set(json, "forwarded", forwarded_json);
+ }
+
+ if (res) {
+ ast_json_unref(json);
+ return NULL;
+ }
+
+ return json;
+}
+
/*!
* @{ \brief Define channel message types.
*/
STASIS_MESSAGE_TYPE_DEFN(ast_channel_snapshot_type);
-STASIS_MESSAGE_TYPE_DEFN(ast_channel_dial_type);
+STASIS_MESSAGE_TYPE_DEFN(ast_channel_dial_type,
+ .to_json = dial_to_json,
+ );
STASIS_MESSAGE_TYPE_DEFN(ast_channel_varset_type,
.to_ami = varset_to_ami,
.to_json = varset_to_json,