mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 20:20:07 +00:00
Merge "res_pjsip_session: segfault on already disconnected session"
This commit is contained in:
123
configure
vendored
123
configure
vendored
@@ -936,6 +936,10 @@ PBX_POPT
|
|||||||
POPT_DIR
|
POPT_DIR
|
||||||
POPT_INCLUDE
|
POPT_INCLUDE
|
||||||
POPT_LIB
|
POPT_LIB
|
||||||
|
PBX_PJSIP_INV_SESSION_REF
|
||||||
|
PJSIP_INV_SESSION_REF_DIR
|
||||||
|
PJSIP_INV_SESSION_REF_INCLUDE
|
||||||
|
PJSIP_INV_SESSION_REF_LIB
|
||||||
PBX_PJSIP_EVSUB_GRP_LOCK
|
PBX_PJSIP_EVSUB_GRP_LOCK
|
||||||
PJSIP_EVSUB_GRP_LOCK_DIR
|
PJSIP_EVSUB_GRP_LOCK_DIR
|
||||||
PJSIP_EVSUB_GRP_LOCK_INCLUDE
|
PJSIP_EVSUB_GRP_LOCK_INCLUDE
|
||||||
@@ -11063,6 +11067,18 @@ PBX_PJSIP_EVSUB_GRP_LOCK=0
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PJSIP_INV_SESSION_REF_DESCRIP="PJSIP INVITE Session Reference Count support"
|
||||||
|
PJSIP_INV_SESSION_REF_OPTION=pjsip
|
||||||
|
PJSIP_INV_SESSION_REF_DIR=${PJPROJECT_DIR}
|
||||||
|
|
||||||
|
PBX_PJSIP_INV_SESSION_REF=0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
POPT_DESCRIP="popt"
|
POPT_DESCRIP="popt"
|
||||||
POPT_OPTION="popt"
|
POPT_OPTION="popt"
|
||||||
@@ -25355,6 +25371,9 @@ $as_echo "#define HAVE_PJSIP_TLS_TRANSPORT_PROTO 1" >>confdefs.h
|
|||||||
$as_echo "#define HAVE_PJSIP_EVSUB_GRP_LOCK 1" >>confdefs.h
|
$as_echo "#define HAVE_PJSIP_EVSUB_GRP_LOCK 1" >>confdefs.h
|
||||||
|
|
||||||
|
|
||||||
|
$as_echo "#define HAVE_PJSIP_INV_SESSION_REF 1" >>confdefs.h
|
||||||
|
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
if test "x${PBX_PJPROJECT}" != "x1" -a "${USE_PJPROJECT}" != "no"; then
|
if test "x${PBX_PJPROJECT}" != "x1" -a "${USE_PJPROJECT}" != "no"; then
|
||||||
@@ -26175,6 +26194,110 @@ _ACEOF
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if test "x${PBX_PJSIP_INV_SESSION_REF}" != "x1" -a "${USE_PJSIP_INV_SESSION_REF}" != "no"; then
|
||||||
|
pbxlibdir=""
|
||||||
|
# if --with-PJSIP_INV_SESSION_REF=DIR has been specified, use it.
|
||||||
|
if test "x${PJSIP_INV_SESSION_REF_DIR}" != "x"; then
|
||||||
|
if test -d ${PJSIP_INV_SESSION_REF_DIR}/lib; then
|
||||||
|
pbxlibdir="-L${PJSIP_INV_SESSION_REF_DIR}/lib"
|
||||||
|
else
|
||||||
|
pbxlibdir="-L${PJSIP_INV_SESSION_REF_DIR}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
pbxfuncname="pjsip_inv_add_ref"
|
||||||
|
if test "x${pbxfuncname}" = "x" ; then # empty lib, assume only headers
|
||||||
|
AST_PJSIP_INV_SESSION_REF_FOUND=yes
|
||||||
|
else
|
||||||
|
ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
|
||||||
|
CFLAGS="${CFLAGS} $PJPROJECT_CFLAGS"
|
||||||
|
as_ac_Lib=`$as_echo "ac_cv_lib_pjsip_${pbxfuncname}" | $as_tr_sh`
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lpjsip" >&5
|
||||||
|
$as_echo_n "checking for ${pbxfuncname} in -lpjsip... " >&6; }
|
||||||
|
if eval \${$as_ac_Lib+:} false; then :
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
ac_check_lib_save_LIBS=$LIBS
|
||||||
|
LIBS="-lpjsip ${pbxlibdir} $PJPROJECT_LIB $LIBS"
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
/* Override any GCC internal prototype to avoid an error.
|
||||||
|
Use char because int might match the return type of a GCC
|
||||||
|
builtin and then its argument prototype would still apply. */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
#endif
|
||||||
|
char ${pbxfuncname} ();
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
return ${pbxfuncname} ();
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_c_try_link "$LINENO"; then :
|
||||||
|
eval "$as_ac_Lib=yes"
|
||||||
|
else
|
||||||
|
eval "$as_ac_Lib=no"
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
LIBS=$ac_check_lib_save_LIBS
|
||||||
|
fi
|
||||||
|
eval ac_res=\$$as_ac_Lib
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||||
|
$as_echo "$ac_res" >&6; }
|
||||||
|
if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then :
|
||||||
|
AST_PJSIP_INV_SESSION_REF_FOUND=yes
|
||||||
|
else
|
||||||
|
AST_PJSIP_INV_SESSION_REF_FOUND=no
|
||||||
|
fi
|
||||||
|
|
||||||
|
CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# now check for the header.
|
||||||
|
if test "${AST_PJSIP_INV_SESSION_REF_FOUND}" = "yes"; then
|
||||||
|
PJSIP_INV_SESSION_REF_LIB="${pbxlibdir} -lpjsip $PJPROJECT_LIB"
|
||||||
|
# if --with-PJSIP_INV_SESSION_REF=DIR has been specified, use it.
|
||||||
|
if test "x${PJSIP_INV_SESSION_REF_DIR}" != "x"; then
|
||||||
|
PJSIP_INV_SESSION_REF_INCLUDE="-I${PJSIP_INV_SESSION_REF_DIR}/include"
|
||||||
|
fi
|
||||||
|
PJSIP_INV_SESSION_REF_INCLUDE="${PJSIP_INV_SESSION_REF_INCLUDE} $PJPROJECT_CFLAGS"
|
||||||
|
if test "xpjsip.h" = "x" ; then # no header, assume found
|
||||||
|
PJSIP_INV_SESSION_REF_HEADER_FOUND="1"
|
||||||
|
else # check for the header
|
||||||
|
ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
|
||||||
|
CPPFLAGS="${CPPFLAGS} ${PJSIP_INV_SESSION_REF_INCLUDE}"
|
||||||
|
ac_fn_c_check_header_mongrel "$LINENO" "pjsip.h" "ac_cv_header_pjsip_h" "$ac_includes_default"
|
||||||
|
if test "x$ac_cv_header_pjsip_h" = xyes; then :
|
||||||
|
PJSIP_INV_SESSION_REF_HEADER_FOUND=1
|
||||||
|
else
|
||||||
|
PJSIP_INV_SESSION_REF_HEADER_FOUND=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"
|
||||||
|
fi
|
||||||
|
if test "x${PJSIP_INV_SESSION_REF_HEADER_FOUND}" = "x0" ; then
|
||||||
|
PJSIP_INV_SESSION_REF_LIB=""
|
||||||
|
PJSIP_INV_SESSION_REF_INCLUDE=""
|
||||||
|
else
|
||||||
|
if test "x${pbxfuncname}" = "x" ; then # only checking headers -> no library
|
||||||
|
PJSIP_INV_SESSION_REF_LIB=""
|
||||||
|
fi
|
||||||
|
PBX_PJSIP_INV_SESSION_REF=1
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
#define HAVE_PJSIP_INV_SESSION_REF 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@@ -502,6 +502,7 @@ AST_EXT_LIB_SETUP_OPTIONAL([PJ_SSL_CERT_LOAD_FROM_FILES2], [pj_ssl_cert_load_fro
|
|||||||
AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_EXTERNAL_RESOLVER], [PJSIP External Resolver Support], [PJPROJECT], [pjsip])
|
AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_EXTERNAL_RESOLVER], [PJSIP External Resolver Support], [PJPROJECT], [pjsip])
|
||||||
AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_TLS_TRANSPORT_PROTO], [PJSIP TLS Transport proto field support], [PJPROJECT], [pjsip])
|
AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_TLS_TRANSPORT_PROTO], [PJSIP TLS Transport proto field support], [PJPROJECT], [pjsip])
|
||||||
AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_EVSUB_GRP_LOCK], [PJSIP EVSUB Group Lock support], [PJPROJECT], [pjsip])
|
AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_EVSUB_GRP_LOCK], [PJSIP EVSUB Group Lock support], [PJPROJECT], [pjsip])
|
||||||
|
AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_INV_SESSION_REF], [PJSIP INVITE Session Reference Count support], [PJPROJECT], [pjsip])
|
||||||
|
|
||||||
AST_EXT_LIB_SETUP([POPT], [popt], [popt])
|
AST_EXT_LIB_SETUP([POPT], [popt], [popt])
|
||||||
AST_EXT_LIB_SETUP([PORTAUDIO], [PortAudio], [portaudio])
|
AST_EXT_LIB_SETUP([PORTAUDIO], [PortAudio], [portaudio])
|
||||||
@@ -2226,6 +2227,7 @@ if test "$USE_PJPROJECT" != "no" ; then
|
|||||||
CPPFLAGS="${saved_cppflags}"
|
CPPFLAGS="${saved_cppflags}"
|
||||||
|
|
||||||
AST_EXT_LIB_CHECK([PJSIP_EVSUB_GRP_LOCK], [pjsip], [pjsip_evsub_add_ref], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
|
AST_EXT_LIB_CHECK([PJSIP_EVSUB_GRP_LOCK], [pjsip], [pjsip_evsub_add_ref], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
|
||||||
|
AST_EXT_LIB_CHECK([PJSIP_INV_SESSION_REF], [pjsip], [pjsip_inv_add_ref], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@@ -598,6 +598,9 @@
|
|||||||
/* Define if your system has pjsip_get_dest_info declared. */
|
/* Define if your system has pjsip_get_dest_info declared. */
|
||||||
#undef HAVE_PJSIP_GET_DEST_INFO
|
#undef HAVE_PJSIP_GET_DEST_INFO
|
||||||
|
|
||||||
|
/* Define if your system has PJSIP_INV_SESSION_REF */
|
||||||
|
#undef HAVE_PJSIP_INV_SESSION_REF
|
||||||
|
|
||||||
/* Define if your system has the PJSIP_REPLACE_MEDIA_STREAM headers. */
|
/* Define if your system has the PJSIP_REPLACE_MEDIA_STREAM headers. */
|
||||||
#undef HAVE_PJSIP_REPLACE_MEDIA_STREAM
|
#undef HAVE_PJSIP_REPLACE_MEDIA_STREAM
|
||||||
|
|
||||||
|
@@ -213,6 +213,11 @@ static int handle_incoming_sdp(struct ast_sip_session *session, const pjmedia_sd
|
|||||||
int i;
|
int i;
|
||||||
int handled = 0;
|
int handled = 0;
|
||||||
|
|
||||||
|
if (session->inv_session && session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
|
||||||
|
ast_log(LOG_ERROR, "Failed to handle incoming SDP. Session has been already disconnected\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < sdp->media_count; ++i) {
|
for (i = 0; i < sdp->media_count; ++i) {
|
||||||
/* See if there are registered handlers for this media stream type */
|
/* See if there are registered handlers for this media stream type */
|
||||||
char media[20];
|
char media[20];
|
||||||
@@ -2087,6 +2092,16 @@ static int new_invite(void *data)
|
|||||||
* so that we will be notified so we can destroy the session properly
|
* so that we will be notified so we can destroy the session properly
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (invite->session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
|
||||||
|
ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
|
||||||
|
invite->session->inv_session->cause,
|
||||||
|
pjsip_get_status_text(invite->session->inv_session->cause)->ptr);
|
||||||
|
#ifdef HAVE_PJSIP_INV_SESSION_REF
|
||||||
|
pjsip_inv_dec_ref(invite->session->inv_session);
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
switch (get_destination(invite->session, invite->rdata)) {
|
switch (get_destination(invite->session, invite->rdata)) {
|
||||||
case SIP_GET_DEST_EXTEN_FOUND:
|
case SIP_GET_DEST_EXTEN_FOUND:
|
||||||
/* Things worked. Keep going */
|
/* Things worked. Keep going */
|
||||||
@@ -2097,7 +2112,7 @@ static int new_invite(void *data)
|
|||||||
} else {
|
} else {
|
||||||
pjsip_inv_terminate(invite->session->inv_session, 416, PJ_TRUE);
|
pjsip_inv_terminate(invite->session->inv_session, 416, PJ_TRUE);
|
||||||
}
|
}
|
||||||
return 0;
|
goto end;
|
||||||
case SIP_GET_DEST_EXTEN_NOT_FOUND:
|
case SIP_GET_DEST_EXTEN_NOT_FOUND:
|
||||||
case SIP_GET_DEST_EXTEN_PARTIAL:
|
case SIP_GET_DEST_EXTEN_PARTIAL:
|
||||||
default:
|
default:
|
||||||
@@ -2110,7 +2125,7 @@ static int new_invite(void *data)
|
|||||||
} else {
|
} else {
|
||||||
pjsip_inv_terminate(invite->session->inv_session, 404, PJ_TRUE);
|
pjsip_inv_terminate(invite->session->inv_session, 404, PJ_TRUE);
|
||||||
}
|
}
|
||||||
return 0;
|
goto end;
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((sdp_info = pjsip_rdata_get_sdp_info(invite->rdata)) && (sdp_info->sdp_err == PJ_SUCCESS) && sdp_info->sdp) {
|
if ((sdp_info = pjsip_rdata_get_sdp_info(invite->rdata)) && (sdp_info->sdp_err == PJ_SUCCESS) && sdp_info->sdp) {
|
||||||
@@ -2120,7 +2135,7 @@ static int new_invite(void *data)
|
|||||||
} else {
|
} else {
|
||||||
pjsip_inv_terminate(invite->session->inv_session, 488, PJ_TRUE);
|
pjsip_inv_terminate(invite->session->inv_session, 488, PJ_TRUE);
|
||||||
}
|
}
|
||||||
return 0;
|
goto end;
|
||||||
}
|
}
|
||||||
/* We are creating a local SDP which is an answer to their offer */
|
/* We are creating a local SDP which is an answer to their offer */
|
||||||
local = create_local_sdp(invite->session->inv_session, invite->session, sdp_info->sdp);
|
local = create_local_sdp(invite->session->inv_session, invite->session, sdp_info->sdp);
|
||||||
@@ -2136,7 +2151,7 @@ static int new_invite(void *data)
|
|||||||
} else {
|
} else {
|
||||||
pjsip_inv_terminate(invite->session->inv_session, 500, PJ_TRUE);
|
pjsip_inv_terminate(invite->session->inv_session, 500, PJ_TRUE);
|
||||||
}
|
}
|
||||||
return 0;
|
goto end;
|
||||||
} else {
|
} else {
|
||||||
pjsip_inv_set_local_sdp(invite->session->inv_session, local);
|
pjsip_inv_set_local_sdp(invite->session->inv_session, local);
|
||||||
pjmedia_sdp_neg_set_prefer_remote_codec_order(invite->session->inv_session->neg, PJ_FALSE);
|
pjmedia_sdp_neg_set_prefer_remote_codec_order(invite->session->inv_session->neg, PJ_FALSE);
|
||||||
@@ -2153,12 +2168,16 @@ static int new_invite(void *data)
|
|||||||
/* At this point, we've verified what we can, so let's go ahead and send a 100 Trying out */
|
/* At this point, we've verified what we can, so let's go ahead and send a 100 Trying out */
|
||||||
if (pjsip_inv_initial_answer(invite->session->inv_session, invite->rdata, 100, NULL, NULL, &tdata) != PJ_SUCCESS) {
|
if (pjsip_inv_initial_answer(invite->session->inv_session, invite->rdata, 100, NULL, NULL, &tdata) != PJ_SUCCESS) {
|
||||||
pjsip_inv_terminate(invite->session->inv_session, 500, PJ_TRUE);
|
pjsip_inv_terminate(invite->session->inv_session, 500, PJ_TRUE);
|
||||||
return 0;
|
goto end;
|
||||||
}
|
}
|
||||||
ast_sip_session_send_response(invite->session, tdata);
|
ast_sip_session_send_response(invite->session, tdata);
|
||||||
|
|
||||||
handle_incoming_request(invite->session, invite->rdata);
|
handle_incoming_request(invite->session, invite->rdata);
|
||||||
|
|
||||||
|
end:
|
||||||
|
#ifdef HAVE_PJSIP_INV_SESSION_REF
|
||||||
|
pjsip_inv_dec_ref(invite->session->inv_session);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2179,6 +2198,20 @@ static void handle_new_invite_request(pjsip_rx_data *rdata)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PJSIP_INV_SESSION_REF
|
||||||
|
if (pjsip_inv_add_ref(inv_session) != PJ_SUCCESS) {
|
||||||
|
ast_log(LOG_ERROR, "Can't increase the session reference counter\n");
|
||||||
|
if (inv_session->state != PJSIP_INV_STATE_DISCONNECTED) {
|
||||||
|
if (pjsip_inv_initial_answer(inv_session, rdata, 500, NULL, NULL, &tdata) == PJ_SUCCESS) {
|
||||||
|
pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
|
||||||
|
} else {
|
||||||
|
internal_pjsip_inv_send_msg(inv_session, endpoint->transport, tdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
session = ast_sip_session_alloc(endpoint, NULL, inv_session, rdata);
|
session = ast_sip_session_alloc(endpoint, NULL, inv_session, rdata);
|
||||||
if (!session) {
|
if (!session) {
|
||||||
if (pjsip_inv_initial_answer(inv_session, rdata, 500, NULL, NULL, &tdata) == PJ_SUCCESS) {
|
if (pjsip_inv_initial_answer(inv_session, rdata, 500, NULL, NULL, &tdata) == PJ_SUCCESS) {
|
||||||
@@ -2186,6 +2219,9 @@ static void handle_new_invite_request(pjsip_rx_data *rdata)
|
|||||||
} else {
|
} else {
|
||||||
internal_pjsip_inv_send_msg(inv_session, endpoint->transport, tdata);
|
internal_pjsip_inv_send_msg(inv_session, endpoint->transport, tdata);
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_PJSIP_INV_SESSION_REF
|
||||||
|
pjsip_inv_dec_ref(inv_session);
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2196,6 +2232,9 @@ static void handle_new_invite_request(pjsip_rx_data *rdata)
|
|||||||
} else {
|
} else {
|
||||||
internal_pjsip_inv_send_msg(inv_session, endpoint->transport, tdata);
|
internal_pjsip_inv_send_msg(inv_session, endpoint->transport, tdata);
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_PJSIP_INV_SESSION_REF
|
||||||
|
pjsip_inv_dec_ref(inv_session);
|
||||||
|
#endif
|
||||||
ao2_cleanup(invite);
|
ao2_cleanup(invite);
|
||||||
}
|
}
|
||||||
ao2_ref(session, -1);
|
ao2_ref(session, -1);
|
||||||
@@ -2467,8 +2506,9 @@ static void handle_outgoing(struct ast_sip_session *session, pjsip_tx_data *tdat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void session_end(struct ast_sip_session *session)
|
static int session_end(void *vsession)
|
||||||
{
|
{
|
||||||
|
struct ast_sip_session *session = vsession;
|
||||||
struct ast_sip_session_supplement *iter;
|
struct ast_sip_session_supplement *iter;
|
||||||
|
|
||||||
/* Stop the scheduled termination */
|
/* Stop the scheduled termination */
|
||||||
@@ -2480,6 +2520,7 @@ static void session_end(struct ast_sip_session *session)
|
|||||||
iter->session_end(session);
|
iter->session_end(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -2617,9 +2658,12 @@ static void session_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
|
if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
|
||||||
|
if (ast_sip_push_task(session->serializer, session_end, session)) {
|
||||||
|
/* Do it anyway even though this is not the right thread. */
|
||||||
session_end(session);
|
session_end(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void session_inv_on_new_session(pjsip_inv_session *inv, pjsip_event *e)
|
static void session_inv_on_new_session(pjsip_inv_session *inv, pjsip_event *e)
|
||||||
{
|
{
|
||||||
@@ -2784,7 +2828,11 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
|
|||||||
* Pass the session ref held by session->inv_session to
|
* Pass the session ref held by session->inv_session to
|
||||||
* session_end_completion().
|
* session_end_completion().
|
||||||
*/
|
*/
|
||||||
|
if (session
|
||||||
|
&& ast_sip_push_task(session->serializer, session_end_completion, session)) {
|
||||||
|
/* Do it anyway even though this is not the right thread. */
|
||||||
session_end_completion(session);
|
session_end_completion(session);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2909,7 +2957,12 @@ static struct pjmedia_sdp_session *create_local_sdp(pjsip_inv_session *inv, stru
|
|||||||
static const pj_str_t STR_IP6 = { "IP6", 3 };
|
static const pj_str_t STR_IP6 = { "IP6", 3 };
|
||||||
pjmedia_sdp_session *local;
|
pjmedia_sdp_session *local;
|
||||||
|
|
||||||
if (!(local = PJ_POOL_ZALLOC_T(inv->pool_prov, pjmedia_sdp_session))) {
|
if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
|
||||||
|
ast_log(LOG_ERROR, "Failed to create session SDP. Session has been already disconnected\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inv->pool_prov || !(local = PJ_POOL_ZALLOC_T(inv->pool_prov, pjmedia_sdp_session))) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
third-party/pjproject/configure.m4
vendored
1
third-party/pjproject/configure.m4
vendored
@@ -45,4 +45,5 @@ AC_DEFUN([PJPROJECT_CONFIGURE],
|
|||||||
PJPROJECT_SYMBOL_CHECK([PJSIP_EXTERNAL_RESOLVER], [pjsip_endpt_set_ext_resolver], [pjsip.h])
|
PJPROJECT_SYMBOL_CHECK([PJSIP_EXTERNAL_RESOLVER], [pjsip_endpt_set_ext_resolver], [pjsip.h])
|
||||||
AC_DEFINE([HAVE_PJSIP_TLS_TRANSPORT_PROTO], 1, [Define if your system has PJSIP_TLS_TRANSPORT_PROTO])
|
AC_DEFINE([HAVE_PJSIP_TLS_TRANSPORT_PROTO], 1, [Define if your system has PJSIP_TLS_TRANSPORT_PROTO])
|
||||||
AC_DEFINE([HAVE_PJSIP_EVSUB_GRP_LOCK], 1, [Define if your system has PJSIP_EVSUB_GRP_LOCK])
|
AC_DEFINE([HAVE_PJSIP_EVSUB_GRP_LOCK], 1, [Define if your system has PJSIP_EVSUB_GRP_LOCK])
|
||||||
|
AC_DEFINE([HAVE_PJSIP_INV_SESSION_REF], 1, [Define if your system has PJSIP_INV_SESSION_REF])
|
||||||
])
|
])
|
||||||
|
212
third-party/pjproject/patches/0002-r5435-add-pjsip_inv_session-ref_cnt.patch
vendored
Normal file
212
third-party/pjproject/patches/0002-r5435-add-pjsip_inv_session-ref_cnt.patch
vendored
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
When a transport error occured on an INVITE session
|
||||||
|
the stack calls on_tsx_state_changed with new state
|
||||||
|
PJSIP_INV_STATE_DISCONNECTED and immediately destroys
|
||||||
|
the INVITE session.
|
||||||
|
At the same time this INVITE session could being processed
|
||||||
|
on another thread. This thread could use the session's
|
||||||
|
memory pools which were already freed, so we get segfault.
|
||||||
|
|
||||||
|
This patch adds a reference counter and new functions:
|
||||||
|
pjsip_inv_add_ref and pjsip_inv_dec_ref.
|
||||||
|
The INVITE session is destroyed only when the reference
|
||||||
|
counter has reached zero.
|
||||||
|
|
||||||
|
To avoid race condition an application should call
|
||||||
|
pjsip_inv_add_ref/pjsip_inv_dec_ref.
|
||||||
|
|
||||||
|
Index: pjsip/include/pjsip-ua/sip_inv.h
|
||||||
|
===================================================================
|
||||||
|
--- a/pjsip/include/pjsip-ua/sip_inv.h (revision 5434)
|
||||||
|
+++ b/pjsip/include/pjsip-ua/sip_inv.h (revision 5435)
|
||||||
|
@@ -383,6 +383,11 @@
|
||||||
|
* Other applications that want to use these pools must understand
|
||||||
|
* that the flip-flop pool's lifetimes are synchronized to the
|
||||||
|
* SDP offer-answer negotiation.
|
||||||
|
+ *
|
||||||
|
+ * The lifetime of this session is controlled by the reference counter in this
|
||||||
|
+ * structure, which is manipulated by calling #pjsip_inv_add_ref and
|
||||||
|
+ * #pjsip_inv_dec_ref. When the reference counter has reached zero, then
|
||||||
|
+ * this session will be destroyed.
|
||||||
|
*/
|
||||||
|
struct pjsip_inv_session
|
||||||
|
{
|
||||||
|
@@ -412,6 +417,7 @@
|
||||||
|
struct pjsip_timer *timer; /**< Session Timers. */
|
||||||
|
pj_bool_t following_fork; /**< Internal, following
|
||||||
|
forked media? */
|
||||||
|
+ pj_atomic_t *ref_cnt; /**< Reference counter. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -631,6 +637,30 @@
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
+ * Add reference counter to the INVITE session. The reference counter controls
|
||||||
|
+ * the life time of the session, ie. when the counter reaches zero, then it
|
||||||
|
+ * will be destroyed.
|
||||||
|
+ *
|
||||||
|
+ * @param inv The INVITE session.
|
||||||
|
+ * @return PJ_SUCCESS if the INVITE session reference counter
|
||||||
|
+ * was increased.
|
||||||
|
+ */
|
||||||
|
+PJ_DECL(pj_status_t) pjsip_inv_add_ref( pjsip_inv_session *inv );
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Decrement reference counter of the INVITE session.
|
||||||
|
+ * When the session is no longer used, it will be destroyed and
|
||||||
|
+ * caller is informed with PJ_EGONE return status.
|
||||||
|
+ *
|
||||||
|
+ * @param inv The INVITE session.
|
||||||
|
+ * @return PJ_SUCCESS if the INVITE session reference counter
|
||||||
|
+ * was decreased. A status PJ_EGONE will be returned to
|
||||||
|
+ * inform that session is destroyed.
|
||||||
|
+ */
|
||||||
|
+PJ_DECL(pj_status_t) pjsip_inv_dec_ref( pjsip_inv_session *inv );
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
* Forcefully terminate and destroy INVITE session, regardless of
|
||||||
|
* the state of the session. Note that this function should only be used
|
||||||
|
* when there is failure in the INVITE session creation. After the
|
||||||
|
Index: pjsip/src/pjsip-ua/sip_inv.c
|
||||||
|
===================================================================
|
||||||
|
--- a/pjsip/src/pjsip-ua/sip_inv.c (revision 5434)
|
||||||
|
+++ b/pjsip/src/pjsip-ua/sip_inv.c (revision 5435)
|
||||||
|
@@ -195,6 +195,65 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
+ * Add reference to INVITE session.
|
||||||
|
+ */
|
||||||
|
+PJ_DEF(pj_status_t) pjsip_inv_add_ref( pjsip_inv_session *inv )
|
||||||
|
+{
|
||||||
|
+ PJ_ASSERT_RETURN(inv && inv->ref_cnt, PJ_EINVAL);
|
||||||
|
+
|
||||||
|
+ pj_atomic_inc(inv->ref_cnt);
|
||||||
|
+
|
||||||
|
+ return PJ_SUCCESS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void inv_session_destroy(pjsip_inv_session *inv)
|
||||||
|
+{
|
||||||
|
+ if (inv->last_ack) {
|
||||||
|
+ pjsip_tx_data_dec_ref(inv->last_ack);
|
||||||
|
+ inv->last_ack = NULL;
|
||||||
|
+ }
|
||||||
|
+ if (inv->invite_req) {
|
||||||
|
+ pjsip_tx_data_dec_ref(inv->invite_req);
|
||||||
|
+ inv->invite_req = NULL;
|
||||||
|
+ }
|
||||||
|
+ if (inv->pending_bye) {
|
||||||
|
+ pjsip_tx_data_dec_ref(inv->pending_bye);
|
||||||
|
+ inv->pending_bye = NULL;
|
||||||
|
+ }
|
||||||
|
+ pjsip_100rel_end_session(inv);
|
||||||
|
+ pjsip_timer_end_session(inv);
|
||||||
|
+ pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod);
|
||||||
|
+
|
||||||
|
+ /* Release the flip-flop pools */
|
||||||
|
+ pj_pool_release(inv->pool_prov);
|
||||||
|
+ inv->pool_prov = NULL;
|
||||||
|
+ pj_pool_release(inv->pool_active);
|
||||||
|
+ inv->pool_active = NULL;
|
||||||
|
+
|
||||||
|
+ pj_atomic_destroy(inv->ref_cnt);
|
||||||
|
+ inv->ref_cnt = NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Decrease INVITE session reference, destroy it when the reference count
|
||||||
|
+ * reaches zero.
|
||||||
|
+ */
|
||||||
|
+PJ_DEF(pj_status_t) pjsip_inv_dec_ref( pjsip_inv_session *inv )
|
||||||
|
+{
|
||||||
|
+ pj_atomic_value_t ref_cnt;
|
||||||
|
+
|
||||||
|
+ PJ_ASSERT_RETURN(inv && inv->ref_cnt, PJ_EINVAL);
|
||||||
|
+
|
||||||
|
+ ref_cnt = pj_atomic_dec_and_get(inv->ref_cnt);
|
||||||
|
+ pj_assert( ref_cnt >= 0);
|
||||||
|
+ if (ref_cnt == 0) {
|
||||||
|
+ inv_session_destroy(inv);
|
||||||
|
+ return PJ_EGONE;
|
||||||
|
+ }
|
||||||
|
+ return PJ_SUCCESS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
* Set session state.
|
||||||
|
*/
|
||||||
|
static void inv_set_state(pjsip_inv_session *inv, pjsip_inv_state state,
|
||||||
|
@@ -261,27 +320,7 @@
|
||||||
|
if (inv->state == PJSIP_INV_STATE_DISCONNECTED &&
|
||||||
|
prev_state != PJSIP_INV_STATE_DISCONNECTED)
|
||||||
|
{
|
||||||
|
- if (inv->last_ack) {
|
||||||
|
- pjsip_tx_data_dec_ref(inv->last_ack);
|
||||||
|
- inv->last_ack = NULL;
|
||||||
|
- }
|
||||||
|
- if (inv->invite_req) {
|
||||||
|
- pjsip_tx_data_dec_ref(inv->invite_req);
|
||||||
|
- inv->invite_req = NULL;
|
||||||
|
- }
|
||||||
|
- if (inv->pending_bye) {
|
||||||
|
- pjsip_tx_data_dec_ref(inv->pending_bye);
|
||||||
|
- inv->pending_bye = NULL;
|
||||||
|
- }
|
||||||
|
- pjsip_100rel_end_session(inv);
|
||||||
|
- pjsip_timer_end_session(inv);
|
||||||
|
- pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod);
|
||||||
|
-
|
||||||
|
- /* Release the flip-flop pools */
|
||||||
|
- pj_pool_release(inv->pool_prov);
|
||||||
|
- inv->pool_prov = NULL;
|
||||||
|
- pj_pool_release(inv->pool_active);
|
||||||
|
- inv->pool_active = NULL;
|
||||||
|
+ pjsip_inv_dec_ref(inv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -838,6 +877,12 @@
|
||||||
|
inv = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_inv_session);
|
||||||
|
pj_assert(inv != NULL);
|
||||||
|
|
||||||
|
+ status = pj_atomic_create(dlg->pool, 0, &inv->ref_cnt);
|
||||||
|
+ if (status != PJ_SUCCESS) {
|
||||||
|
+ pjsip_dlg_dec_lock(dlg);
|
||||||
|
+ return status;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
inv->pool = dlg->pool;
|
||||||
|
inv->role = PJSIP_ROLE_UAC;
|
||||||
|
inv->state = PJSIP_INV_STATE_NULL;
|
||||||
|
@@ -881,6 +926,7 @@
|
||||||
|
pjsip_100rel_attach(inv);
|
||||||
|
|
||||||
|
/* Done */
|
||||||
|
+ pjsip_inv_add_ref(inv);
|
||||||
|
*p_inv = inv;
|
||||||
|
|
||||||
|
pjsip_dlg_dec_lock(dlg);
|
||||||
|
@@ -1471,6 +1517,12 @@
|
||||||
|
inv = PJ_POOL_ZALLOC_T(dlg->pool, pjsip_inv_session);
|
||||||
|
pj_assert(inv != NULL);
|
||||||
|
|
||||||
|
+ status = pj_atomic_create(dlg->pool, 0, &inv->ref_cnt);
|
||||||
|
+ if (status != PJ_SUCCESS) {
|
||||||
|
+ pjsip_dlg_dec_lock(dlg);
|
||||||
|
+ return status;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
inv->pool = dlg->pool;
|
||||||
|
inv->role = PJSIP_ROLE_UAS;
|
||||||
|
inv->state = PJSIP_INV_STATE_NULL;
|
||||||
|
@@ -1540,6 +1592,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Done */
|
||||||
|
+ pjsip_inv_add_ref(inv);
|
||||||
|
pjsip_dlg_dec_lock(dlg);
|
||||||
|
*p_inv = inv;
|
||||||
|
|
Reference in New Issue
Block a user