mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-16 17:53:15 +00:00
Merge "chan_pjsip: transfers with direct media reinvite has wrong address/port"
This commit is contained in:
@@ -223,17 +223,6 @@ static void chan_pjsip_get_codec(struct ast_channel *chan, struct ast_format_cap
|
||||
ast_format_cap_append_from_cap(result, channel->session->endpoint->media.codecs, AST_MEDIA_TYPE_UNKNOWN);
|
||||
}
|
||||
|
||||
static int send_direct_media_request(void *data)
|
||||
{
|
||||
struct ast_sip_session *session = data;
|
||||
int res;
|
||||
|
||||
res = ast_sip_session_refresh(session, NULL, NULL, NULL,
|
||||
session->endpoint->media.direct_media.method, 1);
|
||||
ao2_ref(session, -1);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*! \brief Destructor function for \ref transport_info_data */
|
||||
static void transport_info_destroy(void *obj)
|
||||
{
|
||||
@@ -302,6 +291,83 @@ static int check_for_rtp_changes(struct ast_channel *chan, struct ast_rtp_instan
|
||||
return changed;
|
||||
}
|
||||
|
||||
struct rtp_direct_media_data {
|
||||
struct ast_channel *chan;
|
||||
struct ast_rtp_instance *rtp;
|
||||
struct ast_rtp_instance *vrtp;
|
||||
struct ast_format_cap *cap;
|
||||
struct ast_sip_session *session;
|
||||
};
|
||||
|
||||
static void rtp_direct_media_data_destroy(void *data)
|
||||
{
|
||||
struct rtp_direct_media_data *cdata = data;
|
||||
|
||||
ao2_cleanup(cdata->session);
|
||||
ao2_cleanup(cdata->cap);
|
||||
ao2_cleanup(cdata->vrtp);
|
||||
ao2_cleanup(cdata->rtp);
|
||||
ao2_cleanup(cdata->chan);
|
||||
}
|
||||
|
||||
static struct rtp_direct_media_data *rtp_direct_media_data_create(
|
||||
struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp,
|
||||
const struct ast_format_cap *cap, struct ast_sip_session *session)
|
||||
{
|
||||
struct rtp_direct_media_data *cdata = ao2_alloc(sizeof(*cdata), rtp_direct_media_data_destroy);
|
||||
|
||||
if (!cdata) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cdata->chan = ao2_bump(chan);
|
||||
cdata->rtp = ao2_bump(rtp);
|
||||
cdata->vrtp = ao2_bump(vrtp);
|
||||
cdata->cap = ao2_bump((struct ast_format_cap *)cap);
|
||||
cdata->session = ao2_bump(session);
|
||||
|
||||
return cdata;
|
||||
}
|
||||
|
||||
static int send_direct_media_request(void *data)
|
||||
{
|
||||
struct rtp_direct_media_data *cdata = data;
|
||||
struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(cdata->chan);
|
||||
struct chan_pjsip_pvt *pvt = channel->pvt;
|
||||
int changed = 0;
|
||||
int res = 0;
|
||||
|
||||
if (pvt->media[SIP_MEDIA_AUDIO]) {
|
||||
changed |= check_for_rtp_changes(
|
||||
cdata->chan, cdata->rtp, pvt->media[SIP_MEDIA_AUDIO], 1);
|
||||
}
|
||||
if (pvt->media[SIP_MEDIA_VIDEO]) {
|
||||
changed |= check_for_rtp_changes(
|
||||
cdata->chan, cdata->vrtp, pvt->media[SIP_MEDIA_VIDEO], 3);
|
||||
}
|
||||
|
||||
if (direct_media_mitigate_glare(cdata->session)) {
|
||||
ast_debug(4, "Disregarding setting RTP on %s: mitigating re-INVITE glare\n", ast_channel_name(cdata->chan));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cdata->cap && ast_format_cap_count(cdata->cap) &&
|
||||
!ast_format_cap_identical(cdata->session->direct_media_cap, cdata->cap)) {
|
||||
ast_format_cap_remove_by_type(cdata->session->direct_media_cap, AST_MEDIA_TYPE_UNKNOWN);
|
||||
ast_format_cap_append_from_cap(cdata->session->direct_media_cap, cdata->cap, AST_MEDIA_TYPE_UNKNOWN);
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
ast_debug(4, "RTP changed on %s; initiating direct media update\n", ast_channel_name(cdata->chan));
|
||||
res = ast_sip_session_refresh(cdata->session, NULL, NULL, NULL,
|
||||
cdata->session->endpoint->media.direct_media.method, 1);
|
||||
}
|
||||
|
||||
ao2_ref(cdata, -1);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*! \brief Function called by RTP engine to change where the remote party should send media */
|
||||
static int chan_pjsip_set_rtp_peer(struct ast_channel *chan,
|
||||
struct ast_rtp_instance *rtp,
|
||||
@@ -311,9 +377,8 @@ static int chan_pjsip_set_rtp_peer(struct ast_channel *chan,
|
||||
int nat_active)
|
||||
{
|
||||
struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
|
||||
struct chan_pjsip_pvt *pvt = channel->pvt;
|
||||
struct ast_sip_session *session = channel->session;
|
||||
int changed = 0;
|
||||
struct rtp_direct_media_data *cdata;
|
||||
|
||||
/* Don't try to do any direct media shenanigans on early bridges */
|
||||
if ((rtp || vrtp || tpeer) && !ast_channel_is_bridged(chan)) {
|
||||
@@ -326,31 +391,14 @@ static int chan_pjsip_set_rtp_peer(struct ast_channel *chan,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pvt->media[SIP_MEDIA_AUDIO]) {
|
||||
changed |= check_for_rtp_changes(chan, rtp, pvt->media[SIP_MEDIA_AUDIO], 1);
|
||||
}
|
||||
if (pvt->media[SIP_MEDIA_VIDEO]) {
|
||||
changed |= check_for_rtp_changes(chan, vrtp, pvt->media[SIP_MEDIA_VIDEO], 3);
|
||||
}
|
||||
|
||||
if (direct_media_mitigate_glare(session)) {
|
||||
ast_debug(4, "Disregarding setting RTP on %s: mitigating re-INVITE glare\n", ast_channel_name(chan));
|
||||
cdata = rtp_direct_media_data_create(chan, rtp, vrtp, cap, session);
|
||||
if (!cdata) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cap && ast_format_cap_count(cap) && !ast_format_cap_identical(session->direct_media_cap, cap)) {
|
||||
ast_format_cap_remove_by_type(session->direct_media_cap, AST_MEDIA_TYPE_UNKNOWN);
|
||||
ast_format_cap_append_from_cap(session->direct_media_cap, cap, AST_MEDIA_TYPE_UNKNOWN);
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
ao2_ref(session, +1);
|
||||
|
||||
ast_debug(4, "RTP changed on %s; initiating direct media update\n", ast_channel_name(chan));
|
||||
if (ast_sip_push_task(session->serializer, send_direct_media_request, session)) {
|
||||
ao2_cleanup(session);
|
||||
}
|
||||
if (ast_sip_push_task(session->serializer, send_direct_media_request, cdata)) {
|
||||
ast_log(LOG_ERROR, "Unable to send direct media request for channel %s\n", ast_channel_name(chan));
|
||||
ao2_ref(cdata, -1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user