Merge "res_pjsip_session: Fix off-nominal session refreshes." into 16
This commit is contained in:
commit
0d0f2b4569
|
@ -69,6 +69,13 @@ static int handle_incoming(struct ast_sip_session *session, pjsip_rx_data *rdata
|
|||
enum ast_sip_session_response_priority response_priority);
|
||||
static void handle_outgoing_request(struct ast_sip_session *session, pjsip_tx_data *tdata);
|
||||
static void handle_outgoing_response(struct ast_sip_session *session, pjsip_tx_data *tdata);
|
||||
static int sip_session_refresh(struct ast_sip_session *session,
|
||||
ast_sip_session_request_creation_cb on_request_creation,
|
||||
ast_sip_session_sdp_creation_cb on_sdp_creation,
|
||||
ast_sip_session_response_cb on_response,
|
||||
enum ast_sip_session_refresh_method method, int generate_new_sdp,
|
||||
struct ast_sip_session_media_state *media_state,
|
||||
int queued);
|
||||
|
||||
/*! \brief NAT hook for modifying outgoing messages with SDP */
|
||||
static struct ast_sip_nat_hook *nat_hook;
|
||||
|
@ -1244,8 +1251,18 @@ static void delayed_request_free(struct ast_sip_session_delayed_request *delay)
|
|||
ast_free(delay);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Send a delayed request
|
||||
*
|
||||
* \retval -1 failure
|
||||
* \retval 0 success
|
||||
* \retval 1 refresh request not sent as no change would occur
|
||||
*/
|
||||
static int send_delayed_request(struct ast_sip_session *session, struct ast_sip_session_delayed_request *delay)
|
||||
{
|
||||
int res;
|
||||
|
||||
ast_debug(3, "Endpoint '%s(%s)' sending delayed %s request.\n",
|
||||
ast_sorcery_object_get_id(session->endpoint),
|
||||
session->channel ? ast_channel_name(session->channel) : "",
|
||||
|
@ -1253,19 +1270,19 @@ static int send_delayed_request(struct ast_sip_session *session, struct ast_sip_
|
|||
|
||||
switch (delay->method) {
|
||||
case DELAYED_METHOD_INVITE:
|
||||
ast_sip_session_refresh(session, delay->on_request_creation,
|
||||
res = sip_session_refresh(session, delay->on_request_creation,
|
||||
delay->on_sdp_creation, delay->on_response,
|
||||
AST_SIP_SESSION_REFRESH_METHOD_INVITE, delay->generate_new_sdp, delay->media_state);
|
||||
AST_SIP_SESSION_REFRESH_METHOD_INVITE, delay->generate_new_sdp, delay->media_state, 1);
|
||||
/* Ownership of media state transitions to ast_sip_session_refresh */
|
||||
delay->media_state = NULL;
|
||||
return 0;
|
||||
return res;
|
||||
case DELAYED_METHOD_UPDATE:
|
||||
ast_sip_session_refresh(session, delay->on_request_creation,
|
||||
res = sip_session_refresh(session, delay->on_request_creation,
|
||||
delay->on_sdp_creation, delay->on_response,
|
||||
AST_SIP_SESSION_REFRESH_METHOD_UPDATE, delay->generate_new_sdp, delay->media_state);
|
||||
AST_SIP_SESSION_REFRESH_METHOD_UPDATE, delay->generate_new_sdp, delay->media_state, 1);
|
||||
/* Ownership of media state transitions to ast_sip_session_refresh */
|
||||
delay->media_state = NULL;
|
||||
return 0;
|
||||
return res;
|
||||
case DELAYED_METHOD_BYE:
|
||||
ast_sip_session_terminate(session, 0);
|
||||
return 0;
|
||||
|
@ -1300,7 +1317,9 @@ static int invite_proceeding(void *vsession)
|
|||
AST_LIST_REMOVE_CURRENT(next);
|
||||
res = send_delayed_request(session, delay);
|
||||
delayed_request_free(delay);
|
||||
found = 1;
|
||||
if (!res) {
|
||||
found = 1;
|
||||
}
|
||||
break;
|
||||
case DELAYED_METHOD_BYE:
|
||||
/* A BYE is pending so don't bother anymore. */
|
||||
|
@ -1354,7 +1373,9 @@ static int invite_terminated(void *vsession)
|
|||
AST_LIST_REMOVE_CURRENT(next);
|
||||
res = send_delayed_request(session, delay);
|
||||
delayed_request_free(delay);
|
||||
break;
|
||||
if (!res) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
AST_LIST_TRAVERSE_SAFE_END;
|
||||
|
@ -1558,12 +1579,13 @@ static void set_from_header(struct ast_sip_session *session)
|
|||
}
|
||||
}
|
||||
|
||||
int ast_sip_session_refresh(struct ast_sip_session *session,
|
||||
static int sip_session_refresh(struct ast_sip_session *session,
|
||||
ast_sip_session_request_creation_cb on_request_creation,
|
||||
ast_sip_session_sdp_creation_cb on_sdp_creation,
|
||||
ast_sip_session_response_cb on_response,
|
||||
enum ast_sip_session_refresh_method method, int generate_new_sdp,
|
||||
struct ast_sip_session_media_state *media_state)
|
||||
struct ast_sip_session_media_state *media_state,
|
||||
int queued)
|
||||
{
|
||||
pjsip_inv_session *inv_session = session->inv_session;
|
||||
pjmedia_sdp_session *new_sdp = NULL;
|
||||
|
@ -1630,6 +1652,20 @@ int ast_sip_session_refresh(struct ast_sip_session *session,
|
|||
int type_streams[AST_MEDIA_TYPE_END] = {0};
|
||||
struct ast_stream *stream;
|
||||
|
||||
/* Media state conveys a desired media state, so if there are outstanding
|
||||
* delayed requests we need to ensure we go into the queue and not jump
|
||||
* ahead. If we sent this media state now then updates could go out of
|
||||
* order.
|
||||
*/
|
||||
if (!queued && !AST_LIST_EMPTY(&session->delayed_requests)) {
|
||||
ast_debug(3, "Delay sending reinvite to %s because of outstanding requests...\n",
|
||||
ast_sorcery_object_get_id(session->endpoint));
|
||||
return delay_request(session, on_request_creation, on_sdp_creation,
|
||||
on_response, generate_new_sdp,
|
||||
method == AST_SIP_SESSION_REFRESH_METHOD_INVITE
|
||||
? DELAYED_METHOD_INVITE : DELAYED_METHOD_UPDATE, media_state);
|
||||
}
|
||||
|
||||
/* Prune the media state so the number of streams fit within the configured limits - we do it here
|
||||
* so that the index of the resulting streams in the SDP match. If we simply left the streams out
|
||||
* of the SDP when producing it we'd be in trouble. We also enforce formats here for media types that
|
||||
|
@ -1742,7 +1778,11 @@ int ast_sip_session_refresh(struct ast_sip_session *session,
|
|||
/* If the resulting media state matches the existing active state don't bother doing a session refresh */
|
||||
if (ast_stream_topology_equal(session->active_media_state->topology, media_state->topology)) {
|
||||
ast_sip_session_media_state_free(media_state);
|
||||
return 0;
|
||||
/* For external consumers we return 0 to say success, but internally for
|
||||
* send_delayed_request we return a separate value to indicate that this
|
||||
* session refresh would be redundant so we didn't send it
|
||||
*/
|
||||
return queued ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1794,6 +1834,17 @@ int ast_sip_session_refresh(struct ast_sip_session *session,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ast_sip_session_refresh(struct ast_sip_session *session,
|
||||
ast_sip_session_request_creation_cb on_request_creation,
|
||||
ast_sip_session_sdp_creation_cb on_sdp_creation,
|
||||
ast_sip_session_response_cb on_response,
|
||||
enum ast_sip_session_refresh_method method, int generate_new_sdp,
|
||||
struct ast_sip_session_media_state *media_state)
|
||||
{
|
||||
return sip_session_refresh(session, on_request_creation, on_sdp_creation,
|
||||
on_response, method, generate_new_sdp, media_state, 0);
|
||||
}
|
||||
|
||||
int ast_sip_session_regenerate_answer(struct ast_sip_session *session,
|
||||
ast_sip_session_sdp_creation_cb on_sdp_creation)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue