Merge "res_pjsip: Handle deferred SDP hold/unhold properly."

changes/38/2538/1
Joshua Colp 9 years ago committed by Gerrit Code Review
commit 97db0ca884

@ -1125,7 +1125,54 @@ static pj_bool_t session_reinvite_on_rx_request(pjsip_rx_data *rdata)
}
if (!sdp_info->sdp) {
const pjmedia_sdp_session *local;
int i;
ast_queue_unhold(session->channel);
pjmedia_sdp_neg_get_active_local(session->inv_session->neg, &local);
if (!local) {
return PJ_FALSE;
}
/*
* Some devices indicate hold with deferred SDP reinvites (i.e. no SDP in the reinvite).
* When hold is initially indicated, we
* - Receive an INVITE with no SDP
* - Send a 200 OK with SDP, indicating sendrecv in the media streams
* - Receive an ACK with SDP, indicating sendonly in the media streams
*
* At this point, the pjmedia negotiator saves the state of the media direction so that
* if we are to send any offers, we'll offer recvonly in the media streams. This is
* problematic if the device is attempting to unhold, though. If the device unholds
* by sending a reinvite with no SDP, then we will respond with a 200 OK with recvonly.
* According to RFC 3264, if an offerer offers recvonly, then the answerer MUST respond
* with sendonly or inactive. The result of this is that the stream is not off hold.
*
* Therefore, in this case, when we receive a reinvite while the stream is on hold, we
* need to be sure to offer sendrecv. This way, the answerer can respond with sendrecv
* in order to get the stream off hold. If this is actually a different purpose reinvite
* (like a session timer refresh), then the answerer can respond to our sendrecv with
* sendonly, keeping the stream on hold.
*/
for (i = 0; i < local->media_count; ++i) {
pjmedia_sdp_media *m = local->media[i];
pjmedia_sdp_attr *recvonly;
pjmedia_sdp_attr *inactive;
recvonly = pjmedia_sdp_attr_find2(m->attr_count, m->attr, "recvonly", NULL);
inactive = pjmedia_sdp_attr_find2(m->attr_count, m->attr, "inactive", NULL);
if (recvonly || inactive) {
pjmedia_sdp_attr *to_remove = recvonly ?: inactive;
pjmedia_sdp_attr *sendrecv;
pjmedia_sdp_attr_remove(&m->attr_count, m->attr, to_remove);
sendrecv = pjmedia_sdp_attr_create(session->inv_session->pool, "sendrecv", NULL);
pjmedia_sdp_media_add_attr(m, sendrecv);
}
}
return PJ_FALSE;
}

Loading…
Cancel
Save