diff options
author | Joshua Colp <jcolp@digium.com> | 2014-11-03 14:45:01 +0000 |
---|---|---|
committer | Joshua Colp <jcolp@digium.com> | 2014-11-03 14:45:01 +0000 |
commit | ac091d41844a9a4a0f7d539164bcd154351b6da7 (patch) | |
tree | 84ec4d1350b4e6d1d1498c4ceabd2b5484f3947d /channels | |
parent | 285be15aaf0469055d3392ecd73eb24395e49059 (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.c | 53 | ||||
-rw-r--r-- | channels/pjsip/dialplan_functions.c | 2 |
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; |