]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjsip: Add fax_detect_timeout endpoint option. 41/3241/1
authorRichard Mudgett <rmudgett@digium.com>
Sat, 16 Jul 2016 01:44:52 +0000 (20:44 -0500)
committerRichard Mudgett <rmudgett@digium.com>
Tue, 19 Jul 2016 15:54:52 +0000 (10:54 -0500)
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

CHANGES
channels/chan_pjsip.c
configs/samples/pjsip.conf.sample
contrib/ast-db-manage/config/versions/4a6c67fa9b7a_add_fax_detect_timeout_option.py [new file with mode: 0644]
include/asterisk/res_pjsip.h
include/asterisk/res_pjsip_session.h
main/channel.c
res/res_pjsip.c
res/res_pjsip/pjsip_configuration.c

diff --git a/CHANGES b/CHANGES
index 921cd3f519974b1393144b0e0dba6bb618d612e8..377fb8ea769c2a4cdc977c7a53f92116517d6acc 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -8,6 +8,16 @@
 ===
 ==============================================================================
 
+------------------------------------------------------------------------------
+--- Functionality changes from Asterisk 13.8-cert1 to Asterisk 13.8-cert2 ----
+------------------------------------------------------------------------------
+
+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.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 13.8.0 to Asterisk 13.8-cert1 --------
 ------------------------------------------------------------------------------
index 07887afd856dd229166fb9ead0ce405467080d0c..6f7010a690a5bb3ce668b31c7b27764a7cdf8dd8 100644 (file)
@@ -602,10 +602,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;
@@ -650,6 +652,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;
@@ -687,22 +690,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));
index f87a671a8f778948bb8d63963b2cddcfb24f5cf3..163de651d0715934c1979aefb482691bd38cbc39 100644 (file)
 ;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 (file)
index 0000000..921ef06
--- /dev/null
@@ -0,0 +1,23 @@
+"""add fax_detect_timeout option
+
+Revision ID: 4a6c67fa9b7a
+Revises: 8d478ab86e29
+Create Date: 2016-07-18 18:20:44.249491
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '4a6c67fa9b7a'
+down_revision = '8d478ab86e29'
+
+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')
+
index 586178b31128f938ba1cbe5a0e5111d27e9c754c..5cdc42a09921468db67f531c19d819474dc8613d 100644 (file)
@@ -713,6 +713,8 @@ struct ast_sip_endpoint {
        unsigned int usereqphone;
        /*! Do we send messages for connected line updates for unanswered incoming calls immediately to this endpoint? */
        unsigned int rpid_immediate;
+       /*! The number of seconds into call to disable fax detection.  (0 = disabled) */
+       unsigned int faxdetect_timeout;
 };
 
 /*!
index e4c54a173ef9f2a7259111480cc4b296613ba3c5..7e65e6d7cf5a381f7f5794494adface0ee823887 100644 (file)
@@ -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;
index 4ed1f8b8a262189d8cdcee55a578aeb5eddae683..6e2bc0978f8e120605d906c900f145265281fd65 100644 (file)
@@ -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) {
index 37d52df0a805e98d4e318114ec49d4eecaac11c8..17f3f83eeec7815fc3b69319eee6caa42e98211f 100644 (file)
                                                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>
index ebd621261beaf18eef1c4f3057abb064fccac985..f694b30d5a2553201174f2d52c1a13d3fa8d2916 100644 (file)
@@ -1913,6 +1913,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));