aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormnicholson <mnicholson@f38db490-d61c-443f-a65b-d21fe96a405b>2011-07-11 13:29:13 +0000
committermnicholson <mnicholson@f38db490-d61c-443f-a65b-d21fe96a405b>2011-07-11 13:29:13 +0000
commit30177298c63c914a1180aef905305b2a570453b1 (patch)
tree86dc43ca297a23da2115acbc4d825cf0287246eb
parentfdee0340a69817e159e22a01f5ce9a3590f0313a (diff)
Delay sending an CED tone generated T.38 reinvite to give the CED tone
generating party time to send its own T.38 reinvite. Also don't forward frames through the gateway if we are negotiating T.38. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@327511 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--res/res_fax.c105
1 files changed, 72 insertions, 33 deletions
diff --git a/res/res_fax.c b/res/res_fax.c
index 06b39e05c..5202e6323 100644
--- a/res/res_fax.c
+++ b/res/res_fax.c
@@ -246,6 +246,8 @@ struct fax_gateway {
struct ast_fax_tech_token *token;
/*! \brief the start of our timeout counter */
struct timeval timeout_start;
+ /*! \brief the start of our ced timeout */
+ struct timeval ced_timeout_start;
/*! \brief DSP Processor */
struct ast_dsp *chan_dsp;
struct ast_dsp *peer_dsp;
@@ -253,6 +255,8 @@ struct fax_gateway {
int framehook;
/*! \brief bridged */
int bridged:1;
+ /*! \brief 1 if the ced tone came from chan, 0 if it came from peer */
+ int ced_chan:1;
/*! \brief a flag to track the state of our negotiation */
enum ast_t38_state t38_state;
/*! \brief original audio formats */
@@ -269,6 +273,7 @@ static int fax_logger_level = -1;
#define RES_FAX_TIMEOUT 10000
#define FAX_GATEWAY_TIMEOUT RES_FAX_TIMEOUT
+#define FAX_GATEWAY_CED_TIMEOUT 3000
/*! \brief The faxregistry is used to manage information and statistics for all FAX sessions. */
static struct {
@@ -2465,6 +2470,46 @@ static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session
return 0;
}
+static struct ast_frame *fax_gateway_send_ced(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_frame *f)
+{
+ struct ast_frame *fp;
+ struct ast_control_t38_parameters t38_parameters = {
+ .request_response = AST_T38_REQUEST_NEGOTIATE,
+ };
+ struct ast_frame control_frame = {
+ .src = "res_fax",
+ .frametype = AST_FRAME_CONTROL,
+ .datalen = sizeof(t38_parameters),
+ .subclass.integer = AST_CONTROL_T38_PARAMETERS,
+ .data.ptr = &t38_parameters,
+ };
+
+ struct ast_fax_session_details *details = find_details(chan);
+
+ if (!details) {
+ ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", chan->name);
+ ast_framehook_detach(chan, gateway->framehook);
+ return f;
+ }
+
+ t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
+ ao2_ref(details, -1);
+
+ if (!(fp = ast_frisolate(&control_frame))) {
+ ast_log(LOG_ERROR, "error generating T.38 request control frame on chan %s for T.38 gateway session\n", chan->name);
+ return f;
+ }
+
+ gateway->t38_state = T38_STATE_NEGOTIATING;
+ gateway->timeout_start = ast_tvnow();
+
+ gateway->ced_timeout_start.tv_sec = 0;
+ gateway->ced_timeout_start.tv_usec = 0;
+
+ ast_debug(1, "detected CED tone; requesting T.38 for gateway session for %s\n", chan->name);
+ return fp;
+}
+
static struct ast_frame *fax_gateway_detect_ced(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
{
struct ast_frame *dfr = ast_frdup(f);
@@ -2480,40 +2525,13 @@ static struct ast_frame *fax_gateway_detect_ced(struct fax_gateway *gateway, str
}
if (dfr->frametype == AST_FRAME_DTMF && dfr->subclass.integer == 'e') {
- if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) {
- struct ast_control_t38_parameters t38_parameters = {
- .request_response = AST_T38_REQUEST_NEGOTIATE,
- };
- struct ast_frame control_frame = {
- .src = "res_fax",
- .frametype = AST_FRAME_CONTROL,
- .datalen = sizeof(t38_parameters),
- .subclass.integer = AST_CONTROL_T38_PARAMETERS,
- .data.ptr = &t38_parameters,
- };
-
- struct ast_fax_session_details *details = find_details(chan);
- ast_frfree(dfr);
-
- if (!details) {
- ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", chan->name);
- ast_framehook_detach(chan, gateway->framehook);
- return f;
- }
-
- t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
- ao2_ref(details, -1);
-
- if (!(dfr = ast_frisolate(&control_frame))) {
- ast_log(LOG_ERROR, "error generating T.38 request control frame on chan %s for T.38 gateway session\n", chan->name);
- return f;
+ if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN && ast_tvzero(gateway->ced_timeout_start)) {
+ if (ast_channel_get_t38_state(active) == T38_STATE_UNKNOWN) {
+ gateway->ced_timeout_start = ast_tvnow();
+ gateway->ced_chan = (active == chan);
+ } else {
+ return fax_gateway_send_ced(gateway, chan, f);
}
-
- gateway->t38_state = T38_STATE_NEGOTIATING;
- gateway->timeout_start = ast_tvnow();
-
- ast_debug(1, "detected CED tone on %s, requesting T.38 on %s for T.38 gateway session\n", active->name, other->name);
- return dfr;
} else {
ast_debug(1, "detected CED tone on %s, but %s does not support T.38 for T.38 gateway session\n", active->name, other->name);
}
@@ -2568,6 +2586,10 @@ 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);
+
+ gateway->ced_timeout_start.tv_sec = 0;
+ gateway->ced_timeout_start.tv_usec = 0;
+
if (state == T38_STATE_UNKNOWN) {
/* we detected a request to negotiate T.38 and the
* other channel appears to support T.38, we'll pass
@@ -2922,6 +2944,17 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
return fax_gateway_detect_ced(gateway, chan, peer, active, f);
}
+ /* handle the ced timeout delay */
+ if (!ast_tvzero(gateway->ced_timeout_start)) {
+ if (ast_tvdiff_ms(ast_tvnow(), gateway->ced_timeout_start) > FAX_GATEWAY_CED_TIMEOUT) {
+ if (gateway->ced_chan && chan == active) {
+ return fax_gateway_send_ced(gateway, chan, f);
+ } else if (!gateway->ced_chan && peer == active) {
+ return fax_gateway_send_ced(gateway, chan, f);
+ }
+ }
+ }
+
/* in gateway mode, gateway some packets */
if (gateway->t38_state == T38_STATE_NEGOTIATED) {
/* framehooks are called in __ast_read() before frame format
@@ -2942,6 +2975,12 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
return f;
}
+ /* force silence on the line if T.38 negotiation might be taking place */
+ if (!ast_tvzero(gateway->ced_timeout_start) || (gateway->t38_state != T38_STATE_UNAVAILABLE && gateway->t38_state != T38_STATE_REJECTED)) {
+ /* XXX may need to return a silence frame here */
+ return &ast_null_frame;
+ }
+
return f;
}