From 225d7ebd1233e31b39e9f94a466cf9f3e3350411 Mon Sep 17 00:00:00 2001 From: Terry Wilson Date: Wed, 30 Sep 2009 18:50:50 +0000 Subject: [PATCH] Merged revisions 221266 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r221266 | twilson | 2009-09-30 12:52:30 -0500 (Wed, 30 Sep 2009) | 32 lines Merged revisions 221086 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r221086 | twilson | 2009-09-30 09:49:11 -0500 (Wed, 30 Sep 2009) | 25 lines Change the SSRC by default when our media stream changes 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.6.0@221301 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 24 +++++++++++++++++++++++- configs/sip.conf.sample | 2 ++ include/asterisk/rtp.h | 3 +++ main/rtp.c | 10 +++++++++- 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index f14dc16fab..23fee34964 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -1003,11 +1003,13 @@ struct sip_auth { #define SIP_PAGE2_DIALOG_ESTABLISHED (1 << 27) /*!< 29: Has a dialog been established? */ #define SIP_PAGE2_REGISTERTRYING (1 << 29) /*!< DP: Send 100 Trying on REGISTER attempts */ #define SIP_PAGE2_UDPTL_DESTINATION (1 << 30) /*!< DP: Use source IP of RTP as destination if NAT is enabled */ +#define SIP_PAGE2_CONSTANT_SSRC (1 << 31) /*!< GDP: Don't change SSRC on reinvite */ #define SIP_PAGE2_FLAGS_TO_COPY \ (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_IGNORESDPVERSION | \ SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | \ - SIP_PAGE2_BUGGY_MWI | SIP_PAGE2_TEXTSUPPORT | SIP_PAGE2_UDPTL_DESTINATION) + SIP_PAGE2_BUGGY_MWI | SIP_PAGE2_TEXTSUPPORT | SIP_PAGE2_UDPTL_DESTINATION | \ + SIP_PAGE2_CONSTANT_SSRC) /*@}*/ @@ -4300,6 +4302,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; @@ -4310,6 +4315,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); + } } if (dialog->trtp) { /* Realtime text */ ast_rtp_setdtmf(dialog->trtp, 0); @@ -17648,6 +17656,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; ast_debug(1, "Hm.... No sdp for the moment\n"); @@ -17696,6 +17705,14 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int ast_debug(1, "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; ast_debug(2, "No SDP in Invite, third party call control\n"); @@ -20833,6 +20850,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; @@ -22365,6 +22385,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); } else if (!strcasecmp(v->name, "session-timers")) { int i = (int) str2stmode(v->value); if (i < 0) { diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample index 01f4ae5846..05b4fca969 100644 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -588,6 +588,8 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; (observed with Microsoft OCS). By default this option is ; off. +;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 diff --git a/include/asterisk/rtp.h b/include/asterisk/rtp.h index 98b6b1ffca..62af529c08 100644 --- a/include/asterisk/rtp.h +++ b/include/asterisk/rtp.h @@ -187,6 +187,9 @@ int ast_rtp_sendcng(struct ast_rtp *rtp, int level); int ast_rtp_setqos(struct ast_rtp *rtp, int tos, int cos, char *desc); +/*! \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: */ diff --git a/main/rtp.c b/main/rtp.c index 33a2211c91..5ee8ecae6e 100644 --- a/main/rtp.c +++ b/main/rtp.c @@ -179,6 +179,7 @@ struct ast_rtp { struct sockaddr_in strict_rtp_address; /*!< Remote address information for strict RTP purposes */ int set_marker_bit:1; /*!< Whether to set the marker bit or not */ + unsigned int constantssrc:1; }; /* Forward declarations */ @@ -2389,12 +2390,19 @@ int ast_rtp_setqos(struct ast_rtp *rtp, int tos, int cos, char *desc) return ast_netsock_set_qos(rtp->s, tos, cos, desc); } +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)