]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Change the SSRC by default when our media stream changes
authorTerry Wilson <twilson@digium.com>
Wed, 30 Sep 2009 14:49:11 +0000 (14:49 +0000)
committerTerry Wilson <twilson@digium.com>
Wed, 30 Sep 2009 14:49:11 +0000 (14:49 +0000)
Be default, change SSRC when doing an audio stream changes Asterisk doesn't
honor marker bit when reinvited to already-bridged RTP streams,resulting in
far-end stack discarding packets with "old" timestamps that areactually part of
a new stream.  This patch sends AST_CONTROL_SRCUPDATE whenever there is a
reinvite, unless the 'constantssrc' is set to true in sip.conf.

The original issue reported to Digium support detailed the following situation:
ITSP <-> Asterisk 1.4.26.2 <-> SIP-based Application Server Call comes in
fromITSP, Asterisk dials the app server which sends a re-invite back
toAsterisk--not to negotiate to send media directly to the ITSP, but to
indicatethat it's changing the stream it's sending to Asterisk.  The app
servergenerates a new SSRC, sequence numbers, timestamps, and sets the marker
bit on the new stream.  Asterisk passes through the teimstamp of the new stream,
butdoes not reset the SSRC, sequence numbers, or set the marker bit.

When the timestamp on the new stream is older than the timestamp on the
originalstream, the ITSP (which doesn't know there has been any change) discards
the newframes because it thinks they are too old.  This patch addresses this by
changing the SSRC on a stream update unless constantssrc=true is set in
sip.conf.

Review: https://reviewboard.asterisk.org/r/374/

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

channels/chan_sip.c
configs/sip.conf.sample
include/asterisk/rtp.h
main/rtp.c

index 15984fb0e2276a69f2612bdb3e1aeb3c95dbd29c..0e8c24a01686b06c8a46ff40a6f79ba3e2681d3c 100644 (file)
@@ -807,10 +807,12 @@ struct sip_auth {
 #define SIP_PAGE2_UDPTL_DESTINATION     (1 << 28)       /*!< 28: Use source IP of RTP as destination if NAT is enabled */
 #define SIP_PAGE2_DIALOG_ESTABLISHED    (1 << 29)       /*!< 29: Has a dialog been established? */
 #define SIP_PAGE2_RPORT_PRESENT         (1 << 30)       /*!< 30: Was rport received in the Via header? */
+#define SIP_PAGE2_CONSTANT_SSRC         (1 << 31)       /*!< 31: Don't change SSRC on reinvite */
 
 #define SIP_PAGE2_FLAGS_TO_COPY \
        (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | \
-       SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | SIP_PAGE2_BUGGY_MWI | SIP_PAGE2_UDPTL_DESTINATION)
+       SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | SIP_PAGE2_BUGGY_MWI | \
+       SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_CONSTANT_SSRC)
 
 /* SIP packet flags */
 #define SIP_PKT_DEBUG          (1 << 0)        /*!< Debug this packet */
@@ -2939,6 +2941,9 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
                ast_rtp_set_rtptimeout(dialog->rtp, peer->rtptimeout);
                ast_rtp_set_rtpholdtimeout(dialog->rtp, peer->rtpholdtimeout);
                ast_rtp_set_rtpkeepalive(dialog->rtp, peer->rtpkeepalive);
+               if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_CONSTANT_SSRC)) {
+                       ast_rtp_set_constantssrc(dialog->rtp);
+               }
                /* Set Frame packetization */
                ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs);
                dialog->autoframing = peer->autoframing;
@@ -2949,6 +2954,9 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
                ast_rtp_set_rtptimeout(dialog->vrtp, peer->rtptimeout);
                ast_rtp_set_rtpholdtimeout(dialog->vrtp, peer->rtpholdtimeout);
                ast_rtp_set_rtpkeepalive(dialog->vrtp, peer->rtpkeepalive);
+               if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_CONSTANT_SSRC)) {
+                       ast_rtp_set_constantssrc(dialog->vrtp);
+               }
        }
 
        ast_string_field_set(dialog, peername, peer->name);
@@ -14854,6 +14862,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                                                sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
                                        return -1;
                                }
+                               ast_queue_control(p->owner, AST_CONTROL_SRCUPDATE);
                        } else {
                                p->jointcapability = p->capability;
                                if (option_debug > 2)
@@ -14908,6 +14917,14 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                                        ast_log(LOG_DEBUG, "No compatible codecs for this SIP call.\n");
                                return -1;
                        }
+                       if (ast_test_flag(&p->flags[1], SIP_PAGE2_CONSTANT_SSRC)) {
+                               if (p->rtp) {
+                                       ast_rtp_set_constantssrc(p->rtp);
+                               }
+                               if (p->vrtp) {
+                                       ast_rtp_set_constantssrc(p->vrtp);
+                               }
+                       }
                } else {        /* No SDP in invite, call control session */
                        p->jointcapability = p->capability;
                        if (option_debug > 1)
@@ -17366,6 +17383,9 @@ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask
        } else if (!strcasecmp(v->name, "t38pt_usertpsource")) {
                ast_set_flag(&mask[1], SIP_PAGE2_UDPTL_DESTINATION);
                ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_UDPTL_DESTINATION);
+       } else if (!strcasecmp(v->name, "constantssrc")) {
+               ast_set_flag(&mask[1], SIP_PAGE2_CONSTANT_SSRC);
+               ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_CONSTANT_SSRC);
        } else
                res = 0;
 
@@ -18422,6 +18442,8 @@ static int reload_config(enum channelreloadreason reason)
                                default_maxcallbitrate = DEFAULT_MAX_CALL_BITRATE;
                } else if (!strcasecmp(v->name, "matchexterniplocally")) {
                        global_matchexterniplocally = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "constantssrc")) {
+                       ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_CONSTANT_SSRC);
                }
        }
 
index 741ae7570fcdabb9f14b9cfb98b30248f8114796..57d96550356d56cf6a913a7147481dd0e189eb23 100644 (file)
@@ -365,6 +365,8 @@ srvlookup=yes                   ; Enable DNS SRV lookups on outbound calls
                                 ; instead of INVITE. This can be combined with 'nonat', as
                                 ; 'canreinvite=update,nonat'. It implies 'yes'.
 
+;constantssrc=yes               ; Don't change the RTP SSRC when our media stream changes
+
 ;----------------------------------------- REALTIME SUPPORT ------------------------
 ; For additional information on ARA, the Asterisk Realtime Architecture,
 ; please read realtime.txt and extconfig.txt in the /doc directory of the
@@ -524,7 +526,7 @@ srvlookup=yes                   ; Enable DNS SRV lookups on outbound calls
 ; maxcallbitrate              maxcallbitrate
 ; rfc2833compensate           mailbox
 ; t38pt_usertpsource          username
-;                             template
+; constantssrc                template
 ;                             fromdomain
 ;                             regexten
 ;                             fromuser
@@ -537,6 +539,7 @@ srvlookup=yes                   ; Enable DNS SRV lookups on outbound calls
 ;                             sendrpid
 ;                             outboundproxy
 ;                             rfc2833compensate
+;                             constantssrc
 ;                             t38pt_usertpsource
 ;                             contactpermit         ; Limit what a host may register as (a neat trick
 ;                             contactdeny           ; is to register at the same IP as a SIP provider,
index f9da4bdac5079bdcc590ceeb4bd648aa0d59aee1..fada0bcb473a2048fc6767afc7b04504a85b3a90 100644 (file)
@@ -179,6 +179,9 @@ int ast_rtp_sendcng(struct ast_rtp *rtp, int level);
 
 int ast_rtp_settos(struct ast_rtp *rtp, int tos);
 
+/*! \brief When changing sources, don't generate a new SSRC */
+void ast_rtp_set_constantssrc(struct ast_rtp *rtp);
+
 void ast_rtp_new_source(struct ast_rtp *rtp);
 
 /*! \brief  Setting RTP payload types from lines in a SDP description: */
index c1dc445b71815ad6060d7dd13e7d6c0b05e8d0c0..770292a4f9e9e3bbe4d1a4871d44d04ab034a834 100644 (file)
@@ -174,6 +174,7 @@ struct ast_rtp {
        struct ast_codec_pref pref;
        struct ast_rtp *bridged;        /*!< Who we are Packet bridged to */
        int set_marker_bit:1;           /*!< Whether to set the marker bit or not */
+       unsigned int constantssrc:1;
 };
 
 /* Forward declarations */
@@ -2054,12 +2055,19 @@ int ast_rtp_settos(struct ast_rtp *rtp, int tos)
        return res;
 }
 
+void ast_rtp_set_constantssrc(struct ast_rtp *rtp)
+{
+       rtp->constantssrc = 1;
+}
+
 void ast_rtp_new_source(struct ast_rtp *rtp)
 {
        if (rtp) {
                rtp->set_marker_bit = 1;
+               if (!rtp->constantssrc) {
+                       rtp->ssrc = ast_random();
+               }
        }
-       return;
 }
 
 void ast_rtp_set_peer(struct ast_rtp *rtp, struct sockaddr_in *them)