mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-26 22:30:28 +00:00
Merge "res_fax: Fix deadlock setting FAXMODE channel variable."
This commit is contained in:
@@ -20,16 +20,16 @@
|
|||||||
#ifndef _ASTERISK_RES_FAX_H
|
#ifndef _ASTERISK_RES_FAX_H
|
||||||
#define _ASTERISK_RES_FAX_H
|
#define _ASTERISK_RES_FAX_H
|
||||||
|
|
||||||
#include <asterisk.h>
|
#include "asterisk.h"
|
||||||
#include <asterisk/lock.h>
|
#include "asterisk/lock.h"
|
||||||
#include <asterisk/linkedlists.h>
|
#include "asterisk/linkedlists.h"
|
||||||
#include <asterisk/module.h>
|
#include "asterisk/module.h"
|
||||||
#include <asterisk/utils.h>
|
#include "asterisk/utils.h"
|
||||||
#include <asterisk/options.h>
|
#include "asterisk/options.h"
|
||||||
#include <asterisk/frame.h>
|
#include "asterisk/frame.h"
|
||||||
#include <asterisk/cli.h>
|
#include "asterisk/cli.h"
|
||||||
#include <asterisk/stringfields.h>
|
#include "asterisk/stringfields.h"
|
||||||
#include <asterisk/manager.h>
|
#include "asterisk/manager.h"
|
||||||
|
|
||||||
/*! \brief capabilities for res_fax to locate a fax technology module */
|
/*! \brief capabilities for res_fax to locate a fax technology module */
|
||||||
enum ast_fax_capabilities {
|
enum ast_fax_capabilities {
|
||||||
@@ -187,6 +187,8 @@ struct ast_fax_session_details {
|
|||||||
int faxdetect_timeout;
|
int faxdetect_timeout;
|
||||||
/*! flags used for fax detection */
|
/*! flags used for fax detection */
|
||||||
int faxdetect_flags;
|
int faxdetect_flags;
|
||||||
|
/*! Non-zero if T.38 is negotiated */
|
||||||
|
int is_t38_negotiated;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ast_fax_tech;
|
struct ast_fax_tech;
|
||||||
|
|||||||
@@ -641,6 +641,7 @@ static void fixup_callback(void *data, struct ast_channel *old_chan, struct ast_
|
|||||||
struct ast_fax_session_details *new_details = find_or_create_details(new_chan);
|
struct ast_fax_session_details *new_details = find_or_create_details(new_chan);
|
||||||
|
|
||||||
ast_framehook_detach(old_chan, old_details->gateway_id);
|
ast_framehook_detach(old_chan, old_details->gateway_id);
|
||||||
|
new_details->is_t38_negotiated = old_details->is_t38_negotiated;
|
||||||
fax_gateway_attach(new_chan, new_details);
|
fax_gateway_attach(new_chan, new_details);
|
||||||
ao2_cleanup(new_details);
|
ao2_cleanup(new_details);
|
||||||
}
|
}
|
||||||
@@ -1439,6 +1440,7 @@ static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_de
|
|||||||
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
|
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
|
||||||
{
|
{
|
||||||
char buf[10];
|
char buf[10];
|
||||||
|
|
||||||
pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
|
pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
|
||||||
pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
|
pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
|
||||||
pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
|
pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
|
||||||
@@ -1447,7 +1449,7 @@ static void set_channel_variables(struct ast_channel *chan, struct ast_fax_sessi
|
|||||||
pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
|
pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
|
||||||
pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
|
pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
|
||||||
|
|
||||||
if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
|
if (details->is_t38_negotiated) {
|
||||||
pbx_builtin_setvar_helper(chan, "FAXMODE", "T38");
|
pbx_builtin_setvar_helper(chan, "FAXMODE", "T38");
|
||||||
} else {
|
} else {
|
||||||
pbx_builtin_setvar_helper(chan, "FAXMODE", "audio");
|
pbx_builtin_setvar_helper(chan, "FAXMODE", "audio");
|
||||||
@@ -1656,6 +1658,7 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
|
|||||||
ast_string_field_set(details, result, "");
|
ast_string_field_set(details, result, "");
|
||||||
ast_string_field_set(details, resultstr, "");
|
ast_string_field_set(details, resultstr, "");
|
||||||
ast_string_field_set(details, error, "");
|
ast_string_field_set(details, error, "");
|
||||||
|
details->is_t38_negotiated = t38negotiated;
|
||||||
set_channel_variables(chan, details);
|
set_channel_variables(chan, details);
|
||||||
|
|
||||||
if (fax->tech->start_session(fax) < 0) {
|
if (fax->tech->start_session(fax) < 0) {
|
||||||
@@ -1706,12 +1709,18 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
|
|||||||
* do T.38 as well
|
* do T.38 as well
|
||||||
*/
|
*/
|
||||||
t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
|
t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
|
||||||
t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
|
if (details->caps & AST_FAX_TECH_T38) {
|
||||||
|
details->is_t38_negotiated = 1;
|
||||||
|
t38_parameters.request_response = AST_T38_NEGOTIATED;
|
||||||
|
} else {
|
||||||
|
t38_parameters.request_response = AST_T38_REFUSED;
|
||||||
|
}
|
||||||
ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
|
ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
|
||||||
break;
|
break;
|
||||||
case AST_T38_NEGOTIATED:
|
case AST_T38_NEGOTIATED:
|
||||||
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
|
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
|
||||||
t38negotiated = 1;
|
t38negotiated = 1;
|
||||||
|
details->is_t38_negotiated = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -2902,6 +2911,7 @@ static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session
|
|||||||
ast_string_field_set(details, result, "FAILED");
|
ast_string_field_set(details, result, "FAILED");
|
||||||
ast_string_field_set(details, resultstr, "error starting gateway session");
|
ast_string_field_set(details, resultstr, "error starting gateway session");
|
||||||
ast_string_field_set(details, error, "INIT_ERROR");
|
ast_string_field_set(details, error, "INIT_ERROR");
|
||||||
|
details->is_t38_negotiated = 0;
|
||||||
set_channel_variables(chan, details);
|
set_channel_variables(chan, details);
|
||||||
report_fax_status(chan, details, "No Available Resource");
|
report_fax_status(chan, details, "No Available Resource");
|
||||||
ast_log(LOG_ERROR, "Can't create a FAX session, gateway attempt failed.\n");
|
ast_log(LOG_ERROR, "Can't create a FAX session, gateway attempt failed.\n");
|
||||||
@@ -2922,6 +2932,7 @@ static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session
|
|||||||
ast_string_field_set(details, result, "FAILED");
|
ast_string_field_set(details, result, "FAILED");
|
||||||
ast_string_field_set(details, resultstr, "error starting gateway session");
|
ast_string_field_set(details, resultstr, "error starting gateway session");
|
||||||
ast_string_field_set(details, error, "INIT_ERROR");
|
ast_string_field_set(details, error, "INIT_ERROR");
|
||||||
|
details->is_t38_negotiated = 0;
|
||||||
set_channel_variables(chan, details);
|
set_channel_variables(chan, details);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -2967,6 +2978,7 @@ static struct ast_frame *fax_gateway_request_t38(struct fax_gateway *gateway, st
|
|||||||
|
|
||||||
gateway->t38_state = T38_STATE_NEGOTIATING;
|
gateway->t38_state = T38_STATE_NEGOTIATING;
|
||||||
gateway->timeout_start = ast_tvnow();
|
gateway->timeout_start = ast_tvnow();
|
||||||
|
details->is_t38_negotiated = 0;
|
||||||
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
|
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
|
||||||
|
|
||||||
ast_debug(1, "requesting T.38 for gateway session for %s\n", ast_channel_name(chan));
|
ast_debug(1, "requesting T.38 for gateway session for %s\n", ast_channel_name(chan));
|
||||||
@@ -3064,6 +3076,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
|
|||||||
t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
|
t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
|
||||||
gateway->t38_state = T38_STATE_UNKNOWN;
|
gateway->t38_state = T38_STATE_UNKNOWN;
|
||||||
gateway->timeout_start = ast_tvnow();
|
gateway->timeout_start = ast_tvnow();
|
||||||
|
details->is_t38_negotiated = 0;
|
||||||
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
|
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
|
||||||
ao2_ref(details, -1);
|
ao2_ref(details, -1);
|
||||||
return f;
|
return f;
|
||||||
@@ -3079,12 +3092,14 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
|
|||||||
if (fax_gateway_start(gateway, details, chan)) {
|
if (fax_gateway_start(gateway, details, chan)) {
|
||||||
ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
|
ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
|
||||||
gateway->t38_state = T38_STATE_REJECTED;
|
gateway->t38_state = T38_STATE_REJECTED;
|
||||||
|
details->is_t38_negotiated = 0;
|
||||||
control_params->request_response = AST_T38_REFUSED;
|
control_params->request_response = AST_T38_REFUSED;
|
||||||
|
|
||||||
ast_framehook_detach(chan, details->gateway_id);
|
ast_framehook_detach(chan, details->gateway_id);
|
||||||
details->gateway_id = -1;
|
details->gateway_id = -1;
|
||||||
} else {
|
} else {
|
||||||
gateway->t38_state = T38_STATE_NEGOTIATED;
|
gateway->t38_state = T38_STATE_NEGOTIATED;
|
||||||
|
details->is_t38_negotiated = chan == active;
|
||||||
control_params->request_response = AST_T38_NEGOTIATED;
|
control_params->request_response = AST_T38_NEGOTIATED;
|
||||||
report_fax_status(chan, details, "T.38 Negotiated");
|
report_fax_status(chan, details, "T.38 Negotiated");
|
||||||
}
|
}
|
||||||
@@ -3102,6 +3117,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
|
|||||||
t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
|
t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
|
||||||
gateway->t38_state = T38_STATE_UNKNOWN;
|
gateway->t38_state = T38_STATE_UNKNOWN;
|
||||||
gateway->timeout_start = ast_tvnow();
|
gateway->timeout_start = ast_tvnow();
|
||||||
|
details->is_t38_negotiated = 0;
|
||||||
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
|
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
|
||||||
|
|
||||||
ast_debug(1, "%s is attempting to negotiate T.38 after we already sent a negotiation request based on v21 preamble detection\n", ast_channel_name(active));
|
ast_debug(1, "%s is attempting to negotiate T.38 after we already sent a negotiation request based on v21 preamble detection\n", ast_channel_name(active));
|
||||||
@@ -3124,6 +3140,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
|
|||||||
ast_string_field_set(details, result, "SUCCESS");
|
ast_string_field_set(details, result, "SUCCESS");
|
||||||
ast_string_field_set(details, resultstr, "no gateway necessary");
|
ast_string_field_set(details, resultstr, "no gateway necessary");
|
||||||
ast_string_field_set(details, error, "NATIVE_T38");
|
ast_string_field_set(details, error, "NATIVE_T38");
|
||||||
|
details->is_t38_negotiated = 1;
|
||||||
set_channel_variables(chan, details);
|
set_channel_variables(chan, details);
|
||||||
|
|
||||||
ast_debug(1, "%s is attempting to negotiate T.38 after we already negotiated T.38 with %s, disabling the gateway\n", ast_channel_name(active), ast_channel_name(other));
|
ast_debug(1, "%s is attempting to negotiate T.38 after we already negotiated T.38 with %s, disabling the gateway\n", ast_channel_name(active), ast_channel_name(other));
|
||||||
@@ -3138,6 +3155,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
|
|||||||
&& control_params->request_response == AST_T38_REFUSED) {
|
&& control_params->request_response == AST_T38_REFUSED) {
|
||||||
|
|
||||||
ast_debug(1, "unable to negotiate T.38 on %s for fax gateway\n", ast_channel_name(active));
|
ast_debug(1, "unable to negotiate T.38 on %s for fax gateway\n", ast_channel_name(active));
|
||||||
|
details->is_t38_negotiated = 0;
|
||||||
|
|
||||||
/* 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
|
||||||
@@ -3166,11 +3184,13 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
|
|||||||
if (fax_gateway_start(gateway, details, chan)) {
|
if (fax_gateway_start(gateway, details, chan)) {
|
||||||
ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
|
ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
|
||||||
gateway->t38_state = T38_STATE_NEGOTIATING;
|
gateway->t38_state = T38_STATE_NEGOTIATING;
|
||||||
|
details->is_t38_negotiated = 0;
|
||||||
control_params->request_response = AST_T38_REQUEST_TERMINATE;
|
control_params->request_response = AST_T38_REQUEST_TERMINATE;
|
||||||
|
|
||||||
fax_gateway_indicate_t38(chan, active, control_params);
|
fax_gateway_indicate_t38(chan, active, control_params);
|
||||||
} else {
|
} else {
|
||||||
gateway->t38_state = T38_STATE_NEGOTIATED;
|
gateway->t38_state = T38_STATE_NEGOTIATED;
|
||||||
|
details->is_t38_negotiated = chan == active;
|
||||||
report_fax_status(chan, details, "T.38 Negotiated");
|
report_fax_status(chan, details, "T.38 Negotiated");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3186,14 +3206,16 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
|
|||||||
t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
|
t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
|
||||||
|
|
||||||
if (fax_gateway_start(gateway, details, chan)) {
|
if (fax_gateway_start(gateway, details, chan)) {
|
||||||
ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
|
ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(other), ast_channel_name(active));
|
||||||
gateway->t38_state = T38_STATE_REJECTED;
|
gateway->t38_state = T38_STATE_REJECTED;
|
||||||
|
details->is_t38_negotiated = 0;
|
||||||
control_params->request_response = AST_T38_REFUSED;
|
control_params->request_response = AST_T38_REFUSED;
|
||||||
|
|
||||||
ast_framehook_detach(chan, details->gateway_id);
|
ast_framehook_detach(chan, details->gateway_id);
|
||||||
details->gateway_id = -1;
|
details->gateway_id = -1;
|
||||||
} else {
|
} else {
|
||||||
gateway->t38_state = T38_STATE_NEGOTIATED;
|
gateway->t38_state = T38_STATE_NEGOTIATED;
|
||||||
|
details->is_t38_negotiated = chan == other;
|
||||||
control_params->request_response = AST_T38_NEGOTIATED;
|
control_params->request_response = AST_T38_NEGOTIATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3209,6 +3231,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
|
|||||||
details->gateway_id = -1;
|
details->gateway_id = -1;
|
||||||
|
|
||||||
gateway->t38_state = T38_STATE_REJECTED;
|
gateway->t38_state = T38_STATE_REJECTED;
|
||||||
|
details->is_t38_negotiated = 0;
|
||||||
control_params->request_response = AST_T38_TERMINATED;
|
control_params->request_response = AST_T38_TERMINATED;
|
||||||
|
|
||||||
fax_gateway_indicate_t38(chan, active, control_params);
|
fax_gateway_indicate_t38(chan, active, control_params);
|
||||||
@@ -3224,6 +3247,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
|
|||||||
ast_string_field_set(details, result, "SUCCESS");
|
ast_string_field_set(details, result, "SUCCESS");
|
||||||
ast_string_field_set(details, resultstr, "no gateway necessary");
|
ast_string_field_set(details, resultstr, "no gateway necessary");
|
||||||
ast_string_field_set(details, error, "NATIVE_T38");
|
ast_string_field_set(details, error, "NATIVE_T38");
|
||||||
|
details->is_t38_negotiated = 1;
|
||||||
set_channel_variables(chan, details);
|
set_channel_variables(chan, details);
|
||||||
|
|
||||||
ao2_ref(details, -1);
|
ao2_ref(details, -1);
|
||||||
@@ -3351,6 +3375,7 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
|
|||||||
ast_string_field_set(details, result, "FAILED");
|
ast_string_field_set(details, result, "FAILED");
|
||||||
ast_string_field_set(details, resultstr, "neither channel supports T.38");
|
ast_string_field_set(details, resultstr, "neither channel supports T.38");
|
||||||
ast_string_field_set(details, error, "T38_NEG_ERROR");
|
ast_string_field_set(details, error, "T38_NEG_ERROR");
|
||||||
|
details->is_t38_negotiated = 0;
|
||||||
set_channel_variables(chan, details);
|
set_channel_variables(chan, details);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
@@ -3395,6 +3420,7 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
|
|||||||
ast_string_field_set(details, result, "FAILED");
|
ast_string_field_set(details, result, "FAILED");
|
||||||
ast_string_field_build(details, resultstr, "no fax activity after %d ms", details->gateway_timeout);
|
ast_string_field_build(details, resultstr, "no fax activity after %d ms", details->gateway_timeout);
|
||||||
ast_string_field_set(details, error, "TIMEOUT");
|
ast_string_field_set(details, error, "TIMEOUT");
|
||||||
|
details->is_t38_negotiated = 0;
|
||||||
set_channel_variables(chan, details);
|
set_channel_variables(chan, details);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
@@ -3525,6 +3551,7 @@ static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_d
|
|||||||
ast_string_field_set(details, result, "FAILED");
|
ast_string_field_set(details, result, "FAILED");
|
||||||
ast_string_field_set(details, resultstr, "error initializing gateway session");
|
ast_string_field_set(details, resultstr, "error initializing gateway session");
|
||||||
ast_string_field_set(details, error, "INIT_ERROR");
|
ast_string_field_set(details, error, "INIT_ERROR");
|
||||||
|
details->is_t38_negotiated = 0;
|
||||||
set_channel_variables(chan, details);
|
set_channel_variables(chan, details);
|
||||||
report_fax_status(chan, details, "No Available Resource");
|
report_fax_status(chan, details, "No Available Resource");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -3540,6 +3567,7 @@ static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_d
|
|||||||
ast_string_field_set(details, result, "FAILED");
|
ast_string_field_set(details, result, "FAILED");
|
||||||
ast_string_field_set(details, resultstr, "error attaching gateway to channel");
|
ast_string_field_set(details, resultstr, "error attaching gateway to channel");
|
||||||
ast_string_field_set(details, error, "INIT_ERROR");
|
ast_string_field_set(details, error, "INIT_ERROR");
|
||||||
|
details->is_t38_negotiated = 0;
|
||||||
set_channel_variables(chan, details);
|
set_channel_variables(chan, details);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user