]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Make apps send PROGRESS control frame for early media and fix too early media issue...
authorOlle Johansson <oej@edvina.net>
Fri, 4 Sep 2009 13:45:48 +0000 (13:45 +0000)
committerOlle Johansson <oej@edvina.net>
Fri, 4 Sep 2009 13:45:48 +0000 (13:45 +0000)
The issue at hand is that some legacy (dying) PBX systems send empty media frames on PRI
links *before* any call progress. The SIP channel receives these frames and by default
signals 183 Session progress and starts sending media. This will cause phones to
play silence and ignore the later 180 ringing message. A bad user experience.

The fix is twofold:
- We discovered that asterisk apps that support early media ("noanswer") did not send
  any PROGRESS frame to indicate early media. Fixed.
- We introduce a setting in chan_sip so that users can disable any relay of media frames
  before the outbound channel actually indicates any sort of call progress.
  In 1.4, 1.6.0 and 1.6.1, this will be disabled for backward compatibility. In later versions
  of Asterisk, this will be enabled. We don't assume that it will change your Asterisk
  phone experience - only for the better.

We encourage third-party application developers to make sure that if they have applications
that wants to send early media, add a PROGRESS control frame transmission to make sure that
all channel drivers actually will start sending early media. This has not been the default
in Asterisk previous to this patch, so if you got inspiration from our code, you need to
update accordingly. Sorry for the trouble and thanks for your support.

This code has been running for a few months in a large scale installation (over 250
servers with PRI and/or BRI links to old PBX systems).
That's no proof that this is an excellent patch, but, well, it's tested :-)

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@216430 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_disa.c
apps/app_playback.c
channels/chan_sip.c
configs/sip.conf.sample
main/pbx.c

index 3c8bad9d4a7130b4dadc20db8a1e957e67f599e9..038274057936f404023718834f2549e6ea4e8ff5 100644 (file)
@@ -176,7 +176,12 @@ static int disa_exec(struct ast_channel *chan, void *data)
                        /* answer */
                        ast_answer(chan);
                }
-       } else special_noanswer = 1;
+       } else {
+               special_noanswer = 1;
+               if (chan->_state != AST_STATE_UP) {
+                       ast_indicate(chan, AST_CONTROL_PROGRESS);
+               }
+       }
        i = k = x = 0; /* k is 0 for pswd entry, 1 for ext entry */
        did_ignore = 0;
        exten[0] = 0;
index 6763bd917f50f7a6b29980f386228b2c48d049b6..972435f18cfdfd2410454a1aaaf232fe85b96a6b 100644 (file)
@@ -418,9 +418,13 @@ static int playback_exec(struct ast_channel *chan, void *data)
                if (option_skip) {
                        /* At the user's option, skip if the line is not up */
                        goto done;
-               } else if (!option_noanswer)
+               } else if (!option_noanswer) {
                        /* Otherwise answer unless we're supposed to send this while on-hook */
                        res = ast_answer(chan);
+               } else {
+                       ast_indicate(chan, AST_CONTROL_PROGRESS);
+               }
+
        }
        if (!res) {
                char *back = args.filenames;
index 684bff098a1bf32f2d6d37a63888911fc2a150a8..30243e45a7fdea562d0dca2408311dfd455abbf1 100644 (file)
@@ -539,6 +539,7 @@ static struct ast_codec_pref default_prefs;         /*!< Default codec prefs */
 
 /* Global settings only apply to the channel */
 static int global_directrtpsetup;      /*!< Enable support for Direct RTP setup (no re-invites) */
+static int global_prematuremediafilter;        /*!< Enable/disable premature frames in a call (causing 183 early media) */
 static int global_limitonpeers;                /*!< Match call limit on peers only */
 static int global_rtautoclear;
 static int global_notifyringing;       /*!< Send notifications on ringing */
@@ -3894,9 +3895,11 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame)
                                    !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
                                    !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
                                        ast_rtp_new_source(p->rtp);
-                                       p->invitestate = INV_EARLY_MEDIA;
-                                       transmit_provisional_response(p, "183 Session Progress", &p->initreq, 1);
-                                       ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
+                                       if (!global_prematuremediafilter) {
+                                               p->invitestate = INV_EARLY_MEDIA;
+                                               transmit_provisional_response(p, "183 Session Progress", &p->initreq, 1);
+                                               ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
+                                       }
                                } else if (p->t38.state == T38_ENABLED && !p->t38.direct) {
                                        p->t38.state = T38_DISABLED;
                                        transmit_reinvite_with_sdp(p);
@@ -11317,6 +11320,7 @@ static int sip_show_settings(int fd, int argc, char *argv[])
        print_codec_to_cli(fd, &default_prefs);
        ast_cli(fd, "\n");
        ast_cli(fd, "  T1 minimum:             %d\n", global_t1min);
+       ast_cli(fd, "  No premature media:     %s\n", global_prematuremediafilter ? "Yes" : "No");
        ast_cli(fd, "  Relax DTMF:             %s\n", global_relaxdtmf ? "Yes" : "No");
        ast_cli(fd, "  Compact SIP headers:    %s\n", compactheaders ? "Yes" : "No");
        ast_cli(fd, "  RTP Keepalive:          %d %s\n", global_rtpkeepalive, global_rtpkeepalive ? "" : "(Disabled)" );
@@ -18127,6 +18131,7 @@ static int reload_config(enum channelreloadreason reason)
        expiry = DEFAULT_EXPIRY;
        global_notifyringing = DEFAULT_NOTIFYRINGING;
        global_limitonpeers = FALSE;
+       global_prematuremediafilter = FALSE;
        global_directrtpsetup = FALSE;          /* Experimental feature, disabled by default */
        global_notifyhold = FALSE;
        global_alwaysauthreject = 0;
@@ -18232,6 +18237,8 @@ static int reload_config(enum channelreloadreason reason)
                        ast_set2_flag(&global_flags[1], i || ast_true(v->value), SIP_PAGE2_RTAUTOCLEAR);
                } else if (!strcasecmp(v->name, "usereqphone")) {
                        ast_set2_flag(&global_flags[0], ast_true(v->value), SIP_USEREQPHONE);   
+               } else if (!strcasecmp(v->name, "prematuremedia")) {
+                       global_prematuremediafilter = ast_true(v->value);
                } else if (!strcasecmp(v->name, "relaxdtmf")) {
                        global_relaxdtmf = ast_true(v->value);
                } else if (!strcasecmp(v->name, "checkmwi")) {
index 966d9abf599121c3117fc6f5f190a949bab9a2e6..741ae7570fcdabb9f14b9cfb98b30248f8114796 100644 (file)
@@ -115,6 +115,12 @@ srvlookup=yes                   ; Enable DNS SRV lookups on outbound calls
                                  ; use 'never' to never use in-band signalling, even in cases
                                  ; where some buggy devices might not render it
                                  ; Valid values: yes, no, never Default: never
+;prematuremedia=no              ; Some ISDN links send empty media frames before 
+                                ; the call is in ringing or progress state. The SIP 
+                                ; channel will then send 183 indicating early media
+                                ; which will be empty - thus users get no ring signal.
+                                ; Setting this to "no" will stop any media before we have
+                                ; call progress. Default is "yes".
 ;useragent=Asterisk PBX          ; Allows you to change the user agent string
 ;promiscredir = no               ; If yes, allows 302 or REDIR to non-local SIP address
                                  ; Note that promiscredir when redirects are made to the
index 1672b533208e8ecba8dec13227f109ecaa49c775..acf2da9cf861f356118ab936379ef9f81e6af007 100644 (file)
@@ -5710,6 +5710,8 @@ static int pbx_builtin_background(struct ast_channel *chan, void *data)
                } else if (!ast_test_flag(&flags, BACKGROUND_NOANSWER)) {
                        res = ast_answer(chan);
                }
+               /* Send progress control frame to start early media */
+               ast_indicate(chan, AST_CONTROL_PROGRESS);
        }
 
        if (!res) {