mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-19 19:52:48 +00:00
Merged revisions 332756 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/10 ........ r332756 | mnicholson | 2011-08-22 11:29:45 -0500 (Mon, 22 Aug 2011) | 4 lines add a way to disable and/or modify the gateway timeout ASTERISK-18219 ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@332757 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -172,6 +172,8 @@ struct ast_fax_session_details {
|
|||||||
struct ast_fax_t38_parameters their_t38_parameters;
|
struct ast_fax_t38_parameters their_t38_parameters;
|
||||||
/*! the id of the t.38 gateway framehook for this channel */
|
/*! the id of the t.38 gateway framehook for this channel */
|
||||||
int gateway_id;
|
int gateway_id;
|
||||||
|
/*! the timeout for this gateway in seconds */
|
||||||
|
int gateway_timeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ast_fax_tech;
|
struct ast_fax_tech;
|
||||||
|
@@ -192,6 +192,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||||||
<enum name="gateway">
|
<enum name="gateway">
|
||||||
<para>R/W T38 Gateway Enabled (yes/no)</para>
|
<para>R/W T38 Gateway Enabled (yes/no)</para>
|
||||||
</enum>
|
</enum>
|
||||||
|
<enum name="timeout">
|
||||||
|
<para>R/W Gateway fax activity timeout in seconds (yes/no/seconds)</para>
|
||||||
|
</enum>
|
||||||
<enum name="pages">
|
<enum name="pages">
|
||||||
<para>R/O Number of pages transferred.</para>
|
<para>R/O Number of pages transferred.</para>
|
||||||
</enum>
|
</enum>
|
||||||
@@ -452,6 +455,7 @@ static struct ast_fax_session_details *session_details_new(void)
|
|||||||
d->minrate = general_options.minrate;
|
d->minrate = general_options.minrate;
|
||||||
d->maxrate = general_options.maxrate;
|
d->maxrate = general_options.maxrate;
|
||||||
d->gateway_id = -1;
|
d->gateway_id = -1;
|
||||||
|
d->gateway_timeout = FAX_GATEWAY_TIMEOUT;
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
@@ -2419,7 +2423,7 @@ static struct fax_gateway *fax_gateway_new(struct ast_fax_session_details *detai
|
|||||||
ast_dsp_set_faxmode(gateway->peer_dsp, DSP_FAXMODE_DETECT_V21);
|
ast_dsp_set_faxmode(gateway->peer_dsp, DSP_FAXMODE_DETECT_V21);
|
||||||
|
|
||||||
details->caps = AST_FAX_TECH_GATEWAY;
|
details->caps = AST_FAX_TECH_GATEWAY;
|
||||||
if (!(gateway->s = fax_session_reserve(details, &gateway->token))) {
|
if (details->gateway_timeout && !(gateway->s = fax_session_reserve(details, &gateway->token))) {
|
||||||
details->caps |= ~AST_FAX_TECH_GATEWAY;
|
details->caps |= ~AST_FAX_TECH_GATEWAY;
|
||||||
ast_log(LOG_ERROR, "Can't reserve a FAX session, gateway attempt failed.\n");
|
ast_log(LOG_ERROR, "Can't reserve a FAX session, gateway attempt failed.\n");
|
||||||
ao2_ref(gateway, -1);
|
ao2_ref(gateway, -1);
|
||||||
@@ -2503,6 +2507,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->gateway_timeout = FAX_GATEWAY_TIMEOUT;
|
||||||
|
|
||||||
ast_debug(1, "requesting T.38 for gateway session for %s\n", chan->name);
|
ast_debug(1, "requesting T.38 for gateway session for %s\n", chan->name);
|
||||||
return fp;
|
return fp;
|
||||||
@@ -2595,6 +2600,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->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 == T38_STATE_UNAVAILABLE || state == T38_STATE_REJECTED) {
|
||||||
@@ -2632,6 +2638,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->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", active->name);
|
ast_debug(1, "%s is attempting to negotiate T.38 after we already sent a negotiation request based on v21 preamble detection\n", active->name);
|
||||||
ao2_ref(details, -1);
|
ao2_ref(details, -1);
|
||||||
@@ -2810,10 +2817,23 @@ static void fax_gateway_framehook_destroy(void *data) {
|
|||||||
static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data) {
|
static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data) {
|
||||||
struct fax_gateway *gateway = data;
|
struct fax_gateway *gateway = data;
|
||||||
struct ast_channel *peer, *active;
|
struct ast_channel *peer, *active;
|
||||||
|
struct ast_fax_session_details *details;
|
||||||
|
|
||||||
|
if (gateway->s) {
|
||||||
|
details = gateway->s->details;
|
||||||
|
ao2_ref(details, 1);
|
||||||
|
} else {
|
||||||
|
if (!(details = find_details(chan))) {
|
||||||
|
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);
|
||||||
|
details->gateway_id = -1;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* restore audio formats when we are detached */
|
/* restore audio formats when we are detached */
|
||||||
if (event == AST_FRAMEHOOK_EVENT_DETACHED) {
|
if (event == AST_FRAMEHOOK_EVENT_DETACHED) {
|
||||||
set_channel_variables(chan, gateway->s->details);
|
set_channel_variables(chan, details);
|
||||||
|
|
||||||
if (gateway->bridged) {
|
if (gateway->bridged) {
|
||||||
ast_set_read_format(chan, &gateway->chan_read_format);
|
ast_set_read_format(chan, &gateway->chan_read_format);
|
||||||
@@ -2826,20 +2846,24 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ao2_ref(details, -1);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!f || (event == AST_FRAMEHOOK_EVENT_ATTACHED)) {
|
if (!f || (event == AST_FRAMEHOOK_EVENT_ATTACHED)) {
|
||||||
|
ao2_ref(details, -1);
|
||||||
return NULL;
|
return NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* this frame was generated by the fax gateway, pass it on */
|
/* this frame was generated by the fax gateway, pass it on */
|
||||||
if (ast_test_flag(f, AST_FAX_FRFLAG_GATEWAY)) {
|
if (ast_test_flag(f, AST_FAX_FRFLAG_GATEWAY)) {
|
||||||
|
ao2_ref(details, -1);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(peer = ast_bridged_channel(chan))) {
|
if (!(peer = ast_bridged_channel(chan))) {
|
||||||
/* not bridged, don't do anything */
|
/* not bridged, don't do anything */
|
||||||
|
ao2_ref(details, -1);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2848,16 +2872,19 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
|
|||||||
if (ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE && ast_channel_get_t38_state(peer) == T38_STATE_UNAVAILABLE) {
|
if (ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE && ast_channel_get_t38_state(peer) == T38_STATE_UNAVAILABLE) {
|
||||||
ast_debug(1, "not starting gateway for %s and %s; neither channel supports T.38\n", chan->name, peer->name);
|
ast_debug(1, "not starting gateway for %s and %s; neither channel supports T.38\n", chan->name, peer->name);
|
||||||
ast_framehook_detach(chan, gateway->framehook);
|
ast_framehook_detach(chan, gateway->framehook);
|
||||||
gateway->s->details->gateway_id = -1;
|
details->gateway_id = -1;
|
||||||
|
|
||||||
ast_string_field_set(gateway->s->details, result, "FAILED");
|
ast_string_field_set(details, result, "FAILED");
|
||||||
ast_string_field_set(gateway->s->details, resultstr, "neither channel supports T.38");
|
ast_string_field_set(details, resultstr, "neither channel supports T.38");
|
||||||
ast_string_field_set(gateway->s->details, error, "T38_NEG_ERROR");
|
ast_string_field_set(details, error, "T38_NEG_ERROR");
|
||||||
set_channel_variables(chan, gateway->s->details);
|
set_channel_variables(chan, details);
|
||||||
|
ao2_ref(details, -1);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
gateway->timeout_start = ast_tvnow();
|
if (details->gateway_timeout) {
|
||||||
|
gateway->timeout_start = ast_tvnow();
|
||||||
|
}
|
||||||
|
|
||||||
/* we are bridged, change r/w formats to SLIN for v21 preamble
|
/* we are bridged, change r/w formats to SLIN for v21 preamble
|
||||||
* detection and T.30 */
|
* detection and T.30 */
|
||||||
@@ -2878,15 +2905,16 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (gateway->bridged && !ast_tvzero(gateway->timeout_start)) {
|
if (gateway->bridged && !ast_tvzero(gateway->timeout_start)) {
|
||||||
if (ast_tvdiff_ms(ast_tvnow(), gateway->timeout_start) > FAX_GATEWAY_TIMEOUT) {
|
if (ast_tvdiff_ms(ast_tvnow(), gateway->timeout_start) > details->gateway_timeout) {
|
||||||
ast_debug(1, "no fax activity between %s and %s after %d ms, disabling gateway\n", chan->name, peer->name, FAX_GATEWAY_TIMEOUT);
|
ast_debug(1, "no fax activity between %s and %s after %d ms, disabling gateway\n", chan->name, peer->name, FAX_GATEWAY_TIMEOUT);
|
||||||
ast_framehook_detach(chan, gateway->framehook);
|
ast_framehook_detach(chan, gateway->framehook);
|
||||||
gateway->s->details->gateway_id = -1;
|
details->gateway_id = -1;
|
||||||
|
|
||||||
ast_string_field_set(gateway->s->details, result, "FAILED");
|
ast_string_field_set(details, result, "FAILED");
|
||||||
ast_string_field_build(gateway->s->details, resultstr, "no fax activity after %d ms", FAX_GATEWAY_TIMEOUT);
|
ast_string_field_build(details, resultstr, "no fax activity after %d ms", FAX_GATEWAY_TIMEOUT);
|
||||||
ast_string_field_set(gateway->s->details, error, "TIMEOUT");
|
ast_string_field_set(details, error, "TIMEOUT");
|
||||||
set_channel_variables(chan, gateway->s->details);
|
set_channel_variables(chan, details);
|
||||||
|
ao2_ref(details, -1);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2900,6 +2928,7 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
|
|||||||
case AST_FORMAT_ULAW:
|
case AST_FORMAT_ULAW:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
ao2_ref(details, -1);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2907,13 +2936,16 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
|
|||||||
if (f->subclass.integer == AST_MODEM_T38) {
|
if (f->subclass.integer == AST_MODEM_T38) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
ao2_ref(details, -1);
|
||||||
return f;
|
return f;
|
||||||
case AST_FRAME_CONTROL:
|
case AST_FRAME_CONTROL:
|
||||||
if (f->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
|
if (f->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
ao2_ref(details, -1);
|
||||||
return f;
|
return f;
|
||||||
default:
|
default:
|
||||||
|
ao2_ref(details, -1);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2927,17 +2959,20 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ast_log(LOG_WARNING, "unhandled framehook event %i\n", event);
|
ast_log(LOG_WARNING, "unhandled framehook event %i\n", event);
|
||||||
|
ao2_ref(details, -1);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle control frames */
|
/* handle control frames */
|
||||||
if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
|
if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
|
||||||
|
ao2_ref(details, -1);
|
||||||
return fax_gateway_detect_t38(gateway, chan, peer, active, f);
|
return fax_gateway_detect_t38(gateway, chan, peer, active, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gateway->detected_v21 && gateway->t38_state == T38_STATE_UNAVAILABLE && f->frametype == AST_FRAME_VOICE) {
|
if (!gateway->detected_v21 && gateway->t38_state == T38_STATE_UNAVAILABLE && f->frametype == AST_FRAME_VOICE) {
|
||||||
/* not in gateway mode and have not detected v21 yet, listen
|
/* not in gateway mode and have not detected v21 yet, listen
|
||||||
* for v21 */
|
* for v21 */
|
||||||
|
ao2_ref(details, -1);
|
||||||
return fax_gateway_detect_v21(gateway, chan, peer, active, f);
|
return fax_gateway_detect_v21(gateway, chan, peer, active, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2948,6 +2983,7 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
|
|||||||
if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id != AST_FORMAT_SLINEAR)) {
|
if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id != AST_FORMAT_SLINEAR)) {
|
||||||
if (active->readtrans && (f = ast_translate(active->readtrans, f, 1)) == NULL) {
|
if (active->readtrans && (f = ast_translate(active->readtrans, f, 1)) == NULL) {
|
||||||
f = &ast_null_frame;
|
f = &ast_null_frame;
|
||||||
|
ao2_ref(details, -1);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2958,6 +2994,7 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
|
|||||||
* now we'll just ignore the return value. */
|
* now we'll just ignore the return value. */
|
||||||
gateway->s->tech->write(gateway->s, f);
|
gateway->s->tech->write(gateway->s, f);
|
||||||
f = &ast_null_frame;
|
f = &ast_null_frame;
|
||||||
|
ao2_ref(details, -1);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2974,12 +3011,15 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
|
|||||||
ast_format_set(&silence_frame.subclass.format, AST_FORMAT_SLINEAR, 0);
|
ast_format_set(&silence_frame.subclass.format, AST_FORMAT_SLINEAR, 0);
|
||||||
memset(silence_buf, 0, sizeof(silence_buf));
|
memset(silence_buf, 0, sizeof(silence_buf));
|
||||||
|
|
||||||
|
ao2_ref(details, -1);
|
||||||
return ast_frisolate(&silence_frame);
|
return ast_frisolate(&silence_frame);
|
||||||
} else {
|
} else {
|
||||||
|
ao2_ref(details, -1);
|
||||||
return &ast_null_frame;
|
return &ast_null_frame;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ao2_ref(details, -1);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3432,6 +3472,8 @@ static int acf_faxopt_read(struct ast_channel *chan, const char *cmd, char *data
|
|||||||
} else if (!strcasecmp(data, "t38gateway") || !strcasecmp(data, "gateway") ||
|
} else if (!strcasecmp(data, "t38gateway") || !strcasecmp(data, "gateway") ||
|
||||||
!strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
|
!strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
|
||||||
ast_copy_string(buf, details->gateway_id != -1 ? "yes" : "no", len);
|
ast_copy_string(buf, details->gateway_id != -1 ? "yes" : "no", len);
|
||||||
|
} else if (!strcasecmp(data, "timeout")) {
|
||||||
|
snprintf(buf, len, "%d", details->gateway_timeout / 1000);
|
||||||
} else if (!strcasecmp(data, "error")) {
|
} else if (!strcasecmp(data, "error")) {
|
||||||
ast_copy_string(buf, details->error, len);
|
ast_copy_string(buf, details->error, len);
|
||||||
} else if (!strcasecmp(data, "filename")) {
|
} else if (!strcasecmp(data, "filename")) {
|
||||||
@@ -3527,6 +3569,18 @@ static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *dat
|
|||||||
} else {
|
} else {
|
||||||
ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
|
ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
|
||||||
}
|
}
|
||||||
|
} else if (!strcasecmp(data, "timeout")) {
|
||||||
|
const char *val = ast_skip_blanks(value);
|
||||||
|
int timeout;
|
||||||
|
if (ast_true(val)) {
|
||||||
|
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
|
||||||
|
} else if (ast_false(val)) {
|
||||||
|
details->gateway_timeout = 0;
|
||||||
|
} else if (sscanf(val, "%d", &timeout) == 1 && timeout > 0) {
|
||||||
|
details->gateway_timeout = timeout * 1000;
|
||||||
|
} else {
|
||||||
|
ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
|
||||||
|
}
|
||||||
} else if (!strcasecmp(data, "headerinfo")) {
|
} else if (!strcasecmp(data, "headerinfo")) {
|
||||||
ast_string_field_set(details, headerinfo, value);
|
ast_string_field_set(details, headerinfo, value);
|
||||||
} else if (!strcasecmp(data, "localstationid")) {
|
} else if (!strcasecmp(data, "localstationid")) {
|
||||||
|
Reference in New Issue
Block a user