mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-21 09:10:36 +00:00
Merge "res_fax: Fix deadlock in ast_channel_get_t38_state()."
This commit is contained in:
@@ -2549,7 +2549,11 @@ static inline int ast_fdisset(struct pollfd *pfds, int fd, int maximum, int *sta
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Retrieves the current T38 state of a channel */
|
/*!
|
||||||
|
* \brief Retrieves the current T38 state of a channel
|
||||||
|
*
|
||||||
|
* \note Absolutely _NO_ channel locks should be held before calling this function.
|
||||||
|
*/
|
||||||
static inline enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
|
static inline enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
|
||||||
{
|
{
|
||||||
enum ast_t38_state state = T38_STATE_UNAVAILABLE;
|
enum ast_t38_state state = T38_STATE_UNAVAILABLE;
|
||||||
|
|||||||
@@ -3001,8 +3001,14 @@ static struct ast_frame *fax_gateway_detect_v21(struct fax_gateway *gateway, str
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (gateway->detected_v21) {
|
if (gateway->detected_v21) {
|
||||||
|
enum ast_t38_state state_other;
|
||||||
|
|
||||||
destroy_v21_sessions(gateway);
|
destroy_v21_sessions(gateway);
|
||||||
if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) {
|
|
||||||
|
ast_channel_unlock(chan);
|
||||||
|
state_other = ast_channel_get_t38_state(other);
|
||||||
|
ast_channel_lock(chan);
|
||||||
|
if (state_other == T38_STATE_UNKNOWN) {
|
||||||
ast_debug(1, "detected v21 preamble from %s\n", ast_channel_name(active));
|
ast_debug(1, "detected v21 preamble from %s\n", ast_channel_name(active));
|
||||||
return fax_gateway_request_t38(gateway, chan, f);
|
return fax_gateway_request_t38(gateway, chan, f);
|
||||||
} else {
|
} else {
|
||||||
@@ -3043,6 +3049,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
|
|||||||
struct ast_control_t38_parameters *control_params = f->data.ptr;
|
struct ast_control_t38_parameters *control_params = f->data.ptr;
|
||||||
struct ast_channel *other = (active == chan) ? peer : chan;
|
struct ast_channel *other = (active == chan) ? peer : chan;
|
||||||
struct ast_fax_session_details *details;
|
struct ast_fax_session_details *details;
|
||||||
|
enum ast_t38_state state_other;
|
||||||
|
|
||||||
if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
|
if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
|
||||||
/* invalaid AST_CONTROL_T38_PARAMETERS frame, we can't
|
/* invalaid AST_CONTROL_T38_PARAMETERS frame, we can't
|
||||||
@@ -3065,9 +3072,11 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (control_params->request_response == AST_T38_REQUEST_NEGOTIATE) {
|
if (control_params->request_response == AST_T38_REQUEST_NEGOTIATE) {
|
||||||
enum ast_t38_state state = ast_channel_get_t38_state(other);
|
ast_channel_unlock(chan);
|
||||||
|
state_other = ast_channel_get_t38_state(other);
|
||||||
|
ast_channel_lock(chan);
|
||||||
|
|
||||||
if (state == T38_STATE_UNKNOWN) {
|
if (state_other == T38_STATE_UNKNOWN) {
|
||||||
/* we detected a request to negotiate T.38 and the
|
/* we detected a request to negotiate T.38 and the
|
||||||
* other channel appears to support T.38, we'll pass
|
* other channel appears to support T.38, we'll pass
|
||||||
* the request through and only step in if the other
|
* the request through and only step in if the other
|
||||||
@@ -3080,7 +3089,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
|
|||||||
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
|
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
|
||||||
ao2_ref(details, -1);
|
ao2_ref(details, -1);
|
||||||
return f;
|
return f;
|
||||||
} else if (state == T38_STATE_UNAVAILABLE || state == T38_STATE_REJECTED) {
|
} else if (state_other == T38_STATE_UNAVAILABLE || state_other == T38_STATE_REJECTED) {
|
||||||
/* the other channel does not support T.38, we need to
|
/* the other channel does not support T.38, we need to
|
||||||
* step in here */
|
* step in here */
|
||||||
ast_debug(1, "%s is attempting to negotiate T.38 but %s does not support it\n", ast_channel_name(active), ast_channel_name(other));
|
ast_debug(1, "%s is attempting to negotiate T.38 but %s does not support it\n", ast_channel_name(active), ast_channel_name(other));
|
||||||
@@ -3160,7 +3169,10 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
|
|||||||
/* our request to negotiate T.38 was refused, if the other
|
/* our request to negotiate T.38 was refused, if the other
|
||||||
* channel supports T.38, they might still reinvite and save
|
* channel supports T.38, they might still reinvite and save
|
||||||
* the day. Otherwise disable the gateway. */
|
* the day. Otherwise disable the gateway. */
|
||||||
if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) {
|
ast_channel_unlock(chan);
|
||||||
|
state_other = ast_channel_get_t38_state(other);
|
||||||
|
ast_channel_lock(chan);
|
||||||
|
if (state_other == T38_STATE_UNKNOWN) {
|
||||||
gateway->t38_state = T38_STATE_UNAVAILABLE;
|
gateway->t38_state = T38_STATE_UNAVAILABLE;
|
||||||
} else {
|
} else {
|
||||||
ast_framehook_detach(chan, details->gateway_id);
|
ast_framehook_detach(chan, details->gateway_id);
|
||||||
@@ -3366,8 +3378,16 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!gateway->bridged) {
|
if (!gateway->bridged) {
|
||||||
|
enum ast_t38_state state_chan;
|
||||||
|
enum ast_t38_state state_peer;
|
||||||
|
|
||||||
|
ast_channel_unlock(chan);
|
||||||
|
state_chan = ast_channel_get_t38_state(chan);
|
||||||
|
state_peer = ast_channel_get_t38_state(peer);
|
||||||
|
ast_channel_lock(chan);
|
||||||
|
|
||||||
/* don't start a gateway if neither channel can handle T.38 */
|
/* don't start a gateway if neither channel can handle T.38 */
|
||||||
if (ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE && ast_channel_get_t38_state(peer) == T38_STATE_UNAVAILABLE) {
|
if (state_chan == T38_STATE_UNAVAILABLE && state_peer == T38_STATE_UNAVAILABLE) {
|
||||||
ast_debug(1, "not starting gateway for %s and %s; neither channel supports T.38\n", ast_channel_name(chan), ast_channel_name(peer));
|
ast_debug(1, "not starting gateway for %s and %s; neither channel supports T.38\n", ast_channel_name(chan), ast_channel_name(peer));
|
||||||
ast_framehook_detach(chan, gateway->framehook);
|
ast_framehook_detach(chan, gateway->framehook);
|
||||||
details->gateway_id = -1;
|
details->gateway_id = -1;
|
||||||
|
|||||||
Reference in New Issue
Block a user