summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2016-07-15 20:44:52 -0500
committerRichard Mudgett <rmudgett@digium.com>2016-07-19 10:32:14 -0500
commit851b1c3a177e06660aeeb92b29a0d3e267ddb61b (patch)
tree50a081207f283aaab365c3d3f6b41bb9c430e4f1
parent962c7ef5d91c546794313e01b4c264efdf3d1ead (diff)
res_pjsip: Add fax_detect_timeout endpoint option.
The new endpoint option allows the PJSIP channel driver's fax_detect endpoint option to timeout on a call after the specified number of seconds into a call. The new feature is disabled if the timeout is set to zero. The option is disabled by default. ASTERISK-26214 Reported by: Richard Mudgett Change-Id: Id5a87375fb2c4f9dc1d4b44c78ec8735ba65453d
-rw-r--r--CHANGES4
-rw-r--r--channels/chan_pjsip.c41
-rw-r--r--configs/samples/pjsip.conf.sample4
-rw-r--r--contrib/ast-db-manage/config/versions/4a6c67fa9b7a_add_fax_detect_timeout_option.py23
-rw-r--r--include/asterisk/res_pjsip.h2
-rw-r--r--include/asterisk/res_pjsip_session.h2
-rw-r--r--main/channel.c33
-rw-r--r--res/res_pjsip.c8
-rw-r--r--res/res_pjsip/pjsip_configuration.c1
9 files changed, 105 insertions, 13 deletions
diff --git a/CHANGES b/CHANGES
index c95ab494b..2c5c86474 100644
--- a/CHANGES
+++ b/CHANGES
@@ -14,6 +14,10 @@
res_pjsip
------------------
+ * Added "fax_detect_timeout" to endpoint.
+ The option determines how many seconds into a call before fax_detect
+ is disabled for the call. Setting the value to zero disables the timeout.
+
* Added "subscribe_context" to endpoint.
If specified, incoming SUBSCRIBE requests will be searched for the matching
extension in the indicated context. If no "subscribe_context" is specified,
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index bbccb53a9..3c2860edd 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -612,10 +612,12 @@ static struct ast_frame *chan_pjsip_cng_tone_detected(struct ast_sip_session *se
{
const char *target_context;
int exists;
+ int dsp_features;
- /* If we only needed this DSP for fax detection purposes we can just drop it now */
- if (session->endpoint->dtmf == AST_SIP_DTMF_INBAND || session->endpoint->dtmf == AST_SIP_DTMF_AUTO) {
- ast_dsp_set_features(session->dsp, DSP_FEATURE_DIGIT_DETECT);
+ dsp_features = ast_dsp_get_features(session->dsp);
+ dsp_features &= ~DSP_FEATURE_FAX_DETECT;
+ if (dsp_features) {
+ ast_dsp_set_features(session->dsp, dsp_features);
} else {
ast_dsp_free(session->dsp);
session->dsp = NULL;
@@ -660,6 +662,7 @@ static struct ast_frame *chan_pjsip_cng_tone_detected(struct ast_sip_session *se
static struct ast_frame *chan_pjsip_read(struct ast_channel *ast)
{
struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
+ struct ast_sip_session *session;
struct chan_pjsip_pvt *pvt = channel->pvt;
struct ast_frame *f;
struct ast_sip_session_media *media = NULL;
@@ -697,22 +700,42 @@ static struct ast_frame *chan_pjsip_read(struct ast_channel *ast)
return f;
}
- if (ast_format_cap_iscompatible_format(channel->session->endpoint->media.codecs, f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ session = channel->session;
+
+ if (ast_format_cap_iscompatible_format(session->endpoint->media.codecs, f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
ast_debug(1, "Oooh, got a frame with format of %s on channel '%s' when endpoint '%s' is not configured for it\n",
ast_format_get_name(f->subclass.format), ast_channel_name(ast),
- ast_sorcery_object_get_id(channel->session->endpoint));
+ ast_sorcery_object_get_id(session->endpoint));
ast_frfree(f);
return &ast_null_frame;
}
- if (channel->session->dsp) {
- f = ast_dsp_process(ast, channel->session->dsp, f);
+ if (session->dsp) {
+ int dsp_features;
+ dsp_features = ast_dsp_get_features(session->dsp);
+ if ((dsp_features & DSP_FEATURE_FAX_DETECT)
+ && session->endpoint->faxdetect_timeout
+ && session->endpoint->faxdetect_timeout <= ast_channel_get_up_time(ast)) {
+ dsp_features &= ~DSP_FEATURE_FAX_DETECT;
+ if (dsp_features) {
+ ast_dsp_set_features(session->dsp, dsp_features);
+ } else {
+ ast_dsp_free(session->dsp);
+ session->dsp = NULL;
+ }
+ ast_debug(3, "Channel driver fax CNG detection timeout on %s\n",
+ ast_channel_name(ast));
+ }
+ }
+ if (session->dsp) {
+ f = ast_dsp_process(ast, session->dsp, f);
if (f && (f->frametype == AST_FRAME_DTMF)) {
if (f->subclass.integer == 'f') {
- ast_debug(3, "Fax CNG detected on %s\n", ast_channel_name(ast));
- f = chan_pjsip_cng_tone_detected(channel->session, f);
+ ast_debug(3, "Channel driver fax CNG detected on %s\n",
+ ast_channel_name(ast));
+ f = chan_pjsip_cng_tone_detected(session, f);
} else {
ast_debug(3, "* Detected inband DTMF '%c' on '%s'\n", f->subclass.integer,
ast_channel_name(ast));
diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index 3e007e48c..767948df6 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -691,6 +691,10 @@
;t38_udptl_maxdatagram=0 ; T 38 UDPTL maximum datagram size (default:
; "0")
;fax_detect=no ; Whether CNG tone detection is enabled (default: "no")
+;fax_detect_timeout=30 ; How many seconds into a call before fax_detect is
+ ; disabled for the call.
+ ; Zero disables the timeout.
+ ; (default: "0")
;t38_udptl_nat=no ; Whether NAT support is enabled on UDPTL sessions
; (default: "no")
;t38_udptl_ipv6=no ; Whether IPv6 is used for UDPTL Sessions (default:
diff --git a/contrib/ast-db-manage/config/versions/4a6c67fa9b7a_add_fax_detect_timeout_option.py b/contrib/ast-db-manage/config/versions/4a6c67fa9b7a_add_fax_detect_timeout_option.py
new file mode 100644
index 000000000..91774c447
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/4a6c67fa9b7a_add_fax_detect_timeout_option.py
@@ -0,0 +1,23 @@
+"""add fax_detect_timeout option
+
+Revision ID: 4a6c67fa9b7a
+Revises: 9deac0ae4717
+Create Date: 2016-07-18 18:20:44.249491
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '4a6c67fa9b7a'
+down_revision = '9deac0ae4717'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+ op.add_column('ps_endpoints', sa.Column('fax_detect_timeout', sa.Integer))
+
+
+def downgrade():
+ op.drop_column('ps_endpoints', 'fax_detect_timeout')
+
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 962ddb11b..4d60d1dab 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -749,6 +749,8 @@ struct ast_sip_endpoint {
struct ast_acl_list *acl;
/* Restrict what IPs are allowed in the Contact header (for registration) */
struct ast_acl_list *contact_acl;
+ /*! The number of seconds into call to disable fax detection. (0 = disabled) */
+ unsigned int faxdetect_timeout;
};
/*!
diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h
index e4c54a173..7e65e6d7c 100644
--- a/include/asterisk/res_pjsip_session.h
+++ b/include/asterisk/res_pjsip_session.h
@@ -137,7 +137,7 @@ struct ast_sip_session {
struct ast_party_id id;
/*! Requested capabilities */
struct ast_format_cap *req_caps;
- /*! Optional DSP, used only for inband DTMF detection if configured */
+ /*! Optional DSP, used only for inband DTMF/Fax-CNG detection if configured */
struct ast_dsp *dsp;
/*! Whether the termination of the session should be deferred */
unsigned int defer_terminate:1;
diff --git a/main/channel.c b/main/channel.c
index 327ec64a6..73f795ffa 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -2692,10 +2692,28 @@ void ast_hangup(struct ast_channel *chan)
ast_channel_unref(chan);
}
+/*!
+ * \internal
+ * \brief Set channel answered time if not already set.
+ * \since 13.11.0
+ *
+ * \param chan Channel to set answered time.
+ *
+ * \return Nothing
+ */
+static void set_channel_answer_time(struct ast_channel *chan)
+{
+ if (ast_tvzero(ast_channel_answertime(chan))) {
+ struct timeval answertime;
+
+ answertime = ast_tvnow();
+ ast_channel_answertime_set(chan, &answertime);
+ }
+}
+
int ast_raw_answer(struct ast_channel *chan)
{
int res = 0;
- struct timeval answertime;
ast_channel_lock(chan);
@@ -2711,8 +2729,11 @@ int ast_raw_answer(struct ast_channel *chan)
return -1;
}
- answertime = ast_tvnow();
- ast_channel_answertime_set(chan, &answertime);
+ /*
+ * Mark when incoming channel answered so we can know how
+ * long the channel has been up.
+ */
+ set_channel_answer_time(chan);
ast_channel_unlock(chan);
@@ -3911,6 +3932,12 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
ast_frfree(f);
f = &ast_null_frame;
} else {
+ /*
+ * Mark when outgoing channel answered so we can know how
+ * long the channel has been up.
+ */
+ set_channel_answer_time(chan);
+
ast_setstate(chan, AST_STATE_UP);
}
} else if (f->subclass.integer == AST_CONTROL_READ_ACTION) {
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index de8eb3e8a..52ace6443 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -600,6 +600,14 @@
detected.
</para></description>
</configOption>
+ <configOption name="fax_detect_timeout">
+ <synopsis>How long into a call before fax_detect is disabled for the call</synopsis>
+ <description><para>
+ The option determines how many seconds into a call before the
+ fax_detect option is disabled for the call. Setting the value
+ to zero disables the timeout.
+ </para></description>
+ </configOption>
<configOption name="t38_udptl_nat" default="no">
<synopsis>Whether NAT support is enabled on UDPTL sessions</synopsis>
<description><para>
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index b44512589..48d011067 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -1852,6 +1852,7 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "t38_udptl_ec", "none", t38udptl_ec_handler, t38udptl_ec_to_str, NULL, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_maxdatagram", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.t38.maxdatagram));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "fax_detect", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, faxdetect));
+ ast_sorcery_object_field_register(sip_sorcery, "endpoint", "fax_detect_timeout", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, faxdetect_timeout));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_nat", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.nat));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.ipv6));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "tone_zone", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, zone));