summaryrefslogtreecommitdiff
path: root/channels
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2014-11-03 14:45:01 +0000
committerJoshua Colp <jcolp@digium.com>2014-11-03 14:45:01 +0000
commitac091d41844a9a4a0f7d539164bcd154351b6da7 (patch)
tree84ec4d1350b4e6d1d1498c4ceabd2b5484f3947d /channels
parent285be15aaf0469055d3392ecd73eb24395e49059 (diff)
chan_pjsip: Add support for passing hold and unhold requests through.
This change adds an option, moh_passthrough, that when enabled will pass hold and unhold requests through using a SIP re-invite. When placing on hold a re-invite with sendonly will be sent and when taking off hold a re-invite with sendrecv will be sent. This allows remote servers to handle the musiconhold instead of the local Asterisk instance being responsible. Review: https://reviewboard.asterisk.org/r/4103/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@427112 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_pjsip.c53
-rw-r--r--channels/pjsip/dialplan_functions.c2
2 files changed, 52 insertions, 3 deletions
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index f200a05d3..a37258a69 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -1097,6 +1097,39 @@ static int update_connected_line_information(void *data)
return 0;
}
+/*! \brief Callback which changes the value of locally held on the media stream */
+static int local_hold_set_state(void *obj, void *arg, int flags)
+{
+ struct ast_sip_session_media *session_media = obj;
+ unsigned int *held = arg;
+
+ session_media->locally_held = *held;
+
+ return 0;
+}
+
+/*! \brief Update local hold state and send a re-INVITE with the new SDP */
+static int remote_send_hold_refresh(struct ast_sip_session *session, unsigned int held)
+{
+ ao2_callback(session->media, OBJ_NODATA, local_hold_set_state, &held);
+ ast_sip_session_refresh(session, NULL, NULL, NULL, AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1);
+ ao2_ref(session, -1);
+
+ return 0;
+}
+
+/*! \brief Update local hold state to be held */
+static int remote_send_hold(void *data)
+{
+ return remote_send_hold_refresh(data, 1);
+}
+
+/*! \brief Update local hold state to be unheld */
+static int remote_send_unhold(void *data)
+{
+ return remote_send_hold_refresh(data, 0);
+}
+
/*! \brief Function called by core to ask the channel to indicate some sort of condition */
static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
{
@@ -1219,7 +1252,15 @@ static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const voi
device_buf = alloca(device_buf_size);
ast_channel_get_device_name(ast, device_buf, device_buf_size);
ast_devstate_changed_literal(AST_DEVICE_ONHOLD, 1, device_buf);
- ast_moh_start(ast, data, NULL);
+ if (!channel->session->endpoint->moh_passthrough) {
+ ast_moh_start(ast, data, NULL);
+ } else {
+ if (ast_sip_push_task(channel->session->serializer, remote_send_hold, ao2_bump(channel->session))) {
+ ast_log(LOG_WARNING, "Could not queue task to remotely put session '%s' on hold with endpoint '%s'\n",
+ ast_sorcery_object_get_id(channel->session), ast_sorcery_object_get_id(channel->session->endpoint));
+ ao2_ref(channel->session, -1);
+ }
+ }
break;
case AST_CONTROL_UNHOLD:
chan_pjsip_remove_hold(ast_channel_uniqueid(ast));
@@ -1227,7 +1268,15 @@ static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const voi
device_buf = alloca(device_buf_size);
ast_channel_get_device_name(ast, device_buf, device_buf_size);
ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, 1, device_buf);
- ast_moh_stop(ast);
+ if (!channel->session->endpoint->moh_passthrough) {
+ ast_moh_stop(ast);
+ } else {
+ if (ast_sip_push_task(channel->session->serializer, remote_send_unhold, ao2_bump(channel->session))) {
+ ast_log(LOG_WARNING, "Could not queue task to remotely take session '%s' off hold with endpoint '%s'\n",
+ ast_sorcery_object_get_id(channel->session), ast_sorcery_object_get_id(channel->session->endpoint));
+ ao2_ref(channel->session, -1);
+ }
+ }
break;
case AST_CONTROL_SRCUPDATE:
break;
diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c
index 6c0aff30b..6cc88017a 100644
--- a/channels/pjsip/dialplan_functions.c
+++ b/channels/pjsip/dialplan_functions.c
@@ -434,7 +434,7 @@ static int channel_read_rtp(struct ast_channel *chan, const char *type, const ch
} else if (!strcmp(type, "secure")) {
snprintf(buf, buflen, "%d", media->srtp ? 1 : 0);
} else if (!strcmp(type, "hold")) {
- snprintf(buf, buflen, "%d", media->held ? 1 : 0);
+ snprintf(buf, buflen, "%d", media->remotely_held ? 1 : 0);
} else {
ast_log(AST_LOG_WARNING, "Unknown type field '%s' specified for 'rtp' information\n", type);
return -1;