summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
Diffstat (limited to 'res')
-rw-r--r--res/res_fax.c109
-rw-r--r--res/res_pjsip_refer.c7
-rw-r--r--res/res_pjsip_t38.c14
3 files changed, 104 insertions, 26 deletions
diff --git a/res/res_fax.c b/res/res_fax.c
index 86260d10e..e37091b31 100644
--- a/res/res_fax.c
+++ b/res/res_fax.c
@@ -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);
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);
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)
{
char buf[10];
+
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, "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, "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");
} else {
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, resultstr, "");
ast_string_field_set(details, error, "");
+ details->is_t38_negotiated = t38negotiated;
set_channel_variables(chan, details);
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
*/
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));
break;
case AST_T38_NEGOTIATED:
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
t38negotiated = 1;
+ details->is_t38_negotiated = 1;
break;
default:
break;
@@ -2880,11 +2889,17 @@ static struct fax_gateway *fax_gateway_new(struct ast_channel *chan, struct ast_
return gateway;
}
-/*! \brief Create a fax session and start T.30<->T.38 gateway mode
+/*!
+ * \brief Create a fax session and start T.30<->T.38 gateway mode
+ *
* \param gateway a fax gateway object
* \param details fax session details
* \param chan active channel
- * \return 0 on error 1 on success*/
+ *
+ * \pre chan is locked on entry
+ *
+ * \return 0 on error 1 on success
+ */
static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session_details *details, struct ast_channel *chan)
{
struct ast_fax_session *s;
@@ -2896,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, resultstr, "error starting gateway session");
ast_string_field_set(details, error, "INIT_ERROR");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
report_fax_status(chan, details, "No Available Resource");
ast_log(LOG_ERROR, "Can't create a FAX session, gateway attempt failed.\n");
@@ -2916,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, resultstr, "error starting gateway session");
ast_string_field_set(details, error, "INIT_ERROR");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
return -1;
}
@@ -2928,6 +2945,7 @@ static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session
return 0;
}
+/*! \pre chan is locked on entry */
static struct ast_frame *fax_gateway_request_t38(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_frame *f)
{
struct ast_frame *fp;
@@ -2960,12 +2978,14 @@ static struct ast_frame *fax_gateway_request_t38(struct fax_gateway *gateway, st
gateway->t38_state = T38_STATE_NEGOTIATING;
gateway->timeout_start = ast_tvnow();
+ details->is_t38_negotiated = 0;
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
ast_debug(1, "requesting T.38 for gateway session for %s\n", ast_channel_name(chan));
return fp;
}
+/*! \pre chan is locked on entry */
static struct ast_frame *fax_gateway_detect_v21(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
{
struct ast_channel *other = (active == chan) ? peer : chan;
@@ -2981,8 +3001,14 @@ static struct ast_frame *fax_gateway_detect_v21(struct fax_gateway *gateway, str
}
if (gateway->detected_v21) {
+ enum ast_t38_state state_other;
+
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));
return fax_gateway_request_t38(gateway, chan, f);
} else {
@@ -2993,21 +3019,29 @@ static struct ast_frame *fax_gateway_detect_v21(struct fax_gateway *gateway, str
return f;
}
-static int fax_gateway_indicate_t38(struct ast_channel *chan, struct ast_channel *active, struct ast_control_t38_parameters *control_params)
+/*! \pre chan is locked on entry */
+static void fax_gateway_indicate_t38(struct ast_channel *chan, struct ast_channel *active, struct ast_control_t38_parameters *control_params)
{
if (active == chan) {
- return ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
+ ast_channel_unlock(chan);
+ ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
+ ast_channel_lock(chan);
} else {
- return ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
+ ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
}
}
-/*! \brief T38 Gateway Negotiate t38 parameters
+/*!
+ * \brief T38 Gateway Negotiate t38 parameters
+ *
* \param gateway gateway object
* \param chan channel running the gateway
* \param peer channel im bridged too
* \param active channel the frame originated on
* \param f the control frame to process
+ *
+ * \pre chan is locked on entry
+ *
* \return processed control frame or null frame
*/
static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
@@ -3015,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_channel *other = (active == chan) ? peer : chan;
struct ast_fax_session_details *details;
+ enum ast_t38_state state_other;
if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
/* invalaid AST_CONTROL_T38_PARAMETERS frame, we can't
@@ -3037,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) {
- 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
* other channel appears to support T.38, we'll pass
* the request through and only step in if the other
@@ -3048,10 +3085,11 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
gateway->t38_state = T38_STATE_UNKNOWN;
gateway->timeout_start = ast_tvnow();
+ details->is_t38_negotiated = 0;
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
ao2_ref(details, -1);
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
* 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));
@@ -3063,12 +3101,14 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
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));
gateway->t38_state = T38_STATE_REJECTED;
+ details->is_t38_negotiated = 0;
control_params->request_response = AST_T38_REFUSED;
ast_framehook_detach(chan, details->gateway_id);
details->gateway_id = -1;
} else {
gateway->t38_state = T38_STATE_NEGOTIATED;
+ details->is_t38_negotiated = chan == active;
control_params->request_response = AST_T38_NEGOTIATED;
report_fax_status(chan, details, "T.38 Negotiated");
}
@@ -3086,6 +3126,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);
gateway->t38_state = T38_STATE_UNKNOWN;
gateway->timeout_start = ast_tvnow();
+ details->is_t38_negotiated = 0;
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));
@@ -3108,6 +3149,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, resultstr, "no gateway necessary");
ast_string_field_set(details, error, "NATIVE_T38");
+ details->is_t38_negotiated = 1;
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));
@@ -3122,11 +3164,15 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
&& 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));
+ details->is_t38_negotiated = 0;
/* our request to negotiate T.38 was refused, if the other
* channel supports T.38, they might still reinvite and save
* 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;
} else {
ast_framehook_detach(chan, details->gateway_id);
@@ -3150,11 +3196,13 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
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));
gateway->t38_state = T38_STATE_NEGOTIATING;
+ details->is_t38_negotiated = 0;
control_params->request_response = AST_T38_REQUEST_TERMINATE;
fax_gateway_indicate_t38(chan, active, control_params);
} else {
gateway->t38_state = T38_STATE_NEGOTIATED;
+ details->is_t38_negotiated = chan == active;
report_fax_status(chan, details, "T.38 Negotiated");
}
@@ -3170,14 +3218,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);
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;
+ details->is_t38_negotiated = 0;
control_params->request_response = AST_T38_REFUSED;
ast_framehook_detach(chan, details->gateway_id);
details->gateway_id = -1;
} else {
gateway->t38_state = T38_STATE_NEGOTIATED;
+ details->is_t38_negotiated = chan == other;
control_params->request_response = AST_T38_NEGOTIATED;
}
@@ -3193,6 +3243,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
details->gateway_id = -1;
gateway->t38_state = T38_STATE_REJECTED;
+ details->is_t38_negotiated = 0;
control_params->request_response = AST_T38_TERMINATED;
fax_gateway_indicate_t38(chan, active, control_params);
@@ -3208,6 +3259,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, resultstr, "no gateway necessary");
ast_string_field_set(details, error, "NATIVE_T38");
+ details->is_t38_negotiated = 1;
set_channel_variables(chan, details);
ao2_ref(details, -1);
@@ -3250,7 +3302,8 @@ static void fax_gateway_framehook_destroy(void *data)
ao2_ref(gateway, -1);
}
-/*! \brief T.30<->T.38 gateway framehook.
+/*!
+ * \brief T.30<->T.38 gateway framehook.
*
* Intercept packets on bridged channels and determine if a T.38 gateway is
* required. If a gateway is required, start a gateway and handle T.38
@@ -3261,6 +3314,8 @@ static void fax_gateway_framehook_destroy(void *data)
* \param event framehook event
* \param data framehook data (struct fax_gateway *)
*
+ * \pre chan is locked on entry
+ *
* \return processed frame or NULL when f is NULL or a null frame
*/
static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
@@ -3323,8 +3378,16 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
}
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 */
- 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_framehook_detach(chan, gateway->framehook);
details->gateway_id = -1;
@@ -3332,6 +3395,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, resultstr, "neither channel supports T.38");
ast_string_field_set(details, error, "T38_NEG_ERROR");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
return f;
}
@@ -3376,6 +3440,7 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
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_set(details, error, "TIMEOUT");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
return f;
}
@@ -3491,9 +3556,9 @@ static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_d
.disable_inheritance = 1, /* Masquerade inheritance is handled through the datastore fixup */
};
- if (global_fax_debug) {
- details->option.debug = AST_FAX_OPTFLAG_TRUE;
- }
+ if (global_fax_debug) {
+ details->option.debug = AST_FAX_OPTFLAG_TRUE;
+ }
ast_string_field_set(details, result, "SUCCESS");
ast_string_field_set(details, resultstr, "gateway operation started successfully");
@@ -3506,6 +3571,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, resultstr, "error initializing gateway session");
ast_string_field_set(details, error, "INIT_ERROR");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
report_fax_status(chan, details, "No Available Resource");
return -1;
@@ -3521,6 +3587,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, resultstr, "error attaching gateway to channel");
ast_string_field_set(details, error, "INIT_ERROR");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
return -1;
}
@@ -4509,7 +4576,9 @@ static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *dat
ast_log(LOG_WARNING, "Attempt to attach a T.38 gateway on channel (%s) with gateway already running.\n", ast_channel_name(chan));
}
} else if (ast_false(val)) {
+ ast_channel_lock(chan);
ast_framehook_detach(chan, details->gateway_id);
+ ast_channel_unlock(chan);
details->gateway_id = -1;
} else {
ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
@@ -4561,7 +4630,9 @@ static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *dat
ast_log(LOG_WARNING, "Attempt to attach a FAX detect on channel (%s) with FAX detect already running.\n", ast_channel_name(chan));
}
} else if (ast_false(val)) {
+ ast_channel_lock(chan);
ast_framehook_detach(chan, details->faxdetect_id);
+ ast_channel_unlock(chan);
details->faxdetect_id = -1;
} else {
ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c
index e5bb90e5c..8fe4e8477 100644
--- a/res/res_pjsip_refer.c
+++ b/res/res_pjsip_refer.c
@@ -607,7 +607,10 @@ static void refer_blind_callback(struct ast_channel *chan, struct transfer_chann
ao2_ref(refer->progress, +1);
/* If we can't attach a frame hook for whatever reason send a notification of success immediately */
- if ((refer->progress->framehook = ast_framehook_attach(chan, &hook)) < 0) {
+ ast_channel_lock(chan);
+ refer->progress->framehook = ast_framehook_attach(chan, &hook);
+ ast_channel_unlock(chan);
+ if (refer->progress->framehook < 0) {
struct refer_progress_notification *notification = refer_progress_notification_alloc(refer->progress, 200,
PJSIP_EVSUB_STATE_TERMINATED);
@@ -638,7 +641,9 @@ static void refer_blind_callback(struct ast_channel *chan, struct transfer_chann
refer_progress_notify(notification);
}
+ ast_channel_lock(chan);
ast_framehook_detach(chan, refer->progress->framehook);
+ ast_channel_unlock(chan);
ao2_cleanup(refer->progress);
}
diff --git a/res/res_pjsip_t38.c b/res/res_pjsip_t38.c
index 992902af2..01bfefdd9 100644
--- a/res/res_pjsip_t38.c
+++ b/res/res_pjsip_t38.c
@@ -501,25 +501,27 @@ static void t38_attach_framehook(struct ast_sip_session *session)
return;
}
- /* Skip attaching the framehook if the T.38 datastore already exists for the channel */
ast_channel_lock(session->channel);
- if ((datastore = ast_channel_datastore_find(session->channel, &t38_framehook_datastore, NULL))) {
+
+ /* Skip attaching the framehook if the T.38 datastore already exists for the channel */
+ datastore = ast_channel_datastore_find(session->channel, &t38_framehook_datastore,
+ NULL);
+ if (datastore) {
ast_channel_unlock(session->channel);
return;
}
- ast_channel_unlock(session->channel);
framehook_id = ast_framehook_attach(session->channel, &hook);
if (framehook_id < 0) {
- ast_log(LOG_WARNING, "Could not attach T.38 Frame hook to channel, T.38 will be unavailable on '%s'\n",
+ ast_log(LOG_WARNING, "Could not attach T.38 Frame hook, T.38 will be unavailable on '%s'\n",
ast_channel_name(session->channel));
+ ast_channel_unlock(session->channel);
return;
}
- ast_channel_lock(session->channel);
datastore = ast_datastore_alloc(&t38_framehook_datastore, NULL);
if (!datastore) {
- ast_log(LOG_ERROR, "Could not attach T.38 Frame hook to channel, T.38 will be unavailable on '%s'\n",
+ ast_log(LOG_ERROR, "Could not alloc T.38 Frame hook datastore, T.38 will be unavailable on '%s'\n",
ast_channel_name(session->channel));
ast_framehook_detach(session->channel, framehook_id);
ast_channel_unlock(session->channel);