aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortwilson <twilson@f38db490-d61c-443f-a65b-d21fe96a405b>2010-03-13 00:11:41 +0000
committertwilson <twilson@f38db490-d61c-443f-a65b-d21fe96a405b>2010-03-13 00:11:41 +0000
commit39c22b7f5eaad981c8c8c3af12ccbf2616eff657 (patch)
treedb7227b0d8a950fd5d9cc9e48970e3e4af8d2932
parentbe449d51e904665430df45dd79351099c989820b (diff)
Merged revisions 252089 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ........ r252089 | twilson | 2010-03-12 16:04:51 -0600 (Fri, 12 Mar 2010) | 20 lines Only change the RTP ssrc when we see that it has changed This change basically reverts the change reviewed in https://reviewboard.asterisk.org/r/374/ and instead limits the updating of the RTP synchronization source to only those times when we detect that the other side of the conversation has changed the ssrc. The problem is that SRCUPDATE control frames are sent many times where we don't want a new ssrc, including whenever Asterisk has to send DTMF in a normal bridge. This is also not the first time that this mistake has been made. The initial implementation of the ast_rtp_new_source function also changed the ssrc--and then it was removed because of this same issue. Then, we put it back in again to fix a different issue. This patch attempts to only change the ssrc when we see that the other side of the conversation has changed the ssrc. It also renames some functions to make their purpose more clear. Review: https://reviewboard.asterisk.org/r/540/ ........ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.2@252137 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--channels/chan_h323.c6
-rw-r--r--channels/chan_mgcp.c5
-rw-r--r--channels/chan_sip.c35
-rw-r--r--channels/chan_skinny.c5
-rw-r--r--configs/sip.conf.sample3
-rw-r--r--include/asterisk/frame.h4
-rw-r--r--include/asterisk/rtp.h7
-rw-r--r--main/channel.c5
-rw-r--r--main/rtp.c52
9 files changed, 72 insertions, 50 deletions
diff --git a/channels/chan_h323.c b/channels/chan_h323.c
index be8c78d90..5734fbb58 100644
--- a/channels/chan_h323.c
+++ b/channels/chan_h323.c
@@ -914,7 +914,11 @@ static int oh323_indicate(struct ast_channel *c, int condition, const void *data
res = 0;
break;
case AST_CONTROL_SRCUPDATE:
- ast_rtp_new_source(pvt->rtp);
+ ast_rtp_update_source(pvt->rtp);
+ res = 0;
+ break;
+ case AST_CONTROL_SRCCHANGE:
+ ast_rtp_change_source(pvt->rtp);
res = 0;
break;
case AST_CONTROL_PROCEEDING:
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index 771286da7..319ce9101 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -1454,7 +1454,10 @@ static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, siz
ast_moh_stop(ast);
break;
case AST_CONTROL_SRCUPDATE:
- ast_rtp_new_source(sub->rtp);
+ ast_rtp_update_source(sub->rtp);
+ break;
+ case AST_CONTROL_SRCCHANGE:
+ ast_rtp_change_source(sub->rtp);
break;
case -1:
transmit_notify_request(sub, "");
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 6ab697768..52dd81dac 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1373,7 +1373,6 @@ struct sip_auth {
#define SIP_PAGE2_RTCACHEFRIENDS (1 << 0) /*!< GP: Should we keep RT objects in memory for extended time? */
#define SIP_PAGE2_RTAUTOCLEAR (1 << 2) /*!< GP: Should we clean memory from peers after expiry? */
/* Space for addition of other realtime flags in the future */
-#define SIP_PAGE2_CONSTANT_SSRC (1 << 8) /*!< GDP: Don't change SSRC on reinvite */
#define SIP_PAGE2_STATECHANGEQUEUE (1 << 9) /*!< D: Unsent state pending change exists */
#define SIP_PAGE2_RPORT_PRESENT (1 << 10) /*!< Was rport received in the Via header? */
@@ -1406,7 +1405,7 @@ struct sip_auth {
(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_FAX_DETECT | \
- SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_VIDEOSUPPORT_ALWAYS | SIP_PAGE2_CONSTANT_SSRC)
+ SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_VIDEOSUPPORT_ALWAYS)
/*@}*/
@@ -5150,9 +5149,6 @@ 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;
@@ -5163,9 +5159,6 @@ 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);
@@ -6195,7 +6188,7 @@ static int sip_answer(struct ast_channel *ast)
ast_setstate(ast, AST_STATE_UP);
ast_debug(1, "SIP answering channel: %s\n", ast->name);
- ast_rtp_new_source(p->rtp);
+ ast_rtp_update_source(p->rtp);
res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, FALSE);
ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
}
@@ -6230,7 +6223,7 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame)
if ((ast->_state != AST_STATE_UP) &&
!ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
!ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
- ast_rtp_new_source(p->rtp);
+ ast_rtp_update_source(p->rtp);
if (!global_prematuremediafilter) {
p->invitestate = INV_EARLY_MEDIA;
transmit_provisional_response(p, "183 Session Progress", &p->initreq, TRUE);
@@ -6553,11 +6546,11 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
res = -1;
break;
case AST_CONTROL_HOLD:
- ast_rtp_new_source(p->rtp);
+ ast_rtp_update_source(p->rtp);
ast_moh_start(ast, data, p->mohinterpret);
break;
case AST_CONTROL_UNHOLD:
- ast_rtp_new_source(p->rtp);
+ ast_rtp_update_source(p->rtp);
ast_moh_stop(ast);
break;
case AST_CONTROL_VIDUPDATE: /* Request a video frame update */
@@ -6576,7 +6569,10 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data
}
break;
case AST_CONTROL_SRCUPDATE:
- ast_rtp_new_source(p->rtp);
+ ast_rtp_update_source(p->rtp);
+ break;
+ case AST_CONTROL_SRCCHANGE:
+ ast_rtp_change_source(p->rtp);
break;
case -1:
res = -1;
@@ -20002,14 +19998,6 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
res = -1;
goto request_invite_cleanup;
}
- 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");
@@ -23406,9 +23394,6 @@ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask
} else if (!strcasecmp(v->name, "buggymwi")) {
ast_set_flag(&mask[1], SIP_PAGE2_BUGGY_MWI);
ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_BUGGY_MWI);
- } 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;
@@ -24877,8 +24862,6 @@ static int reload_config(enum channelreloadreason reason)
default_maxcallbitrate = DEFAULT_MAX_CALL_BITRATE;
} else if (!strcasecmp(v->name, "matchexterniplocally")) {
sip_cfg.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/channels/chan_skinny.c b/channels/chan_skinny.c
index 4753e08e8..c7341376a 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -4256,7 +4256,10 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s
case AST_CONTROL_PROCEEDING:
break;
case AST_CONTROL_SRCUPDATE:
- ast_rtp_new_source(sub->rtp);
+ ast_rtp_update_source(sub->rtp);
+ break;
+ case AST_CONTROL_SRCCHANGE:
+ ast_rtp_change_source(sub->rtp);
break;
default:
ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample
index e4e62ecb7..662ccc5f0 100644
--- a/configs/sip.conf.sample
+++ b/configs/sip.conf.sample
@@ -696,8 +696,6 @@ 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
@@ -910,7 +908,6 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; timerb
; qualifyfreq
; t38pt_usertpsource
-; constantssrc
; contactpermit ; Limit what a host may register as (a neat trick
; contactdeny ; is to register at the same IP as a SIP provider,
; ; then call oneself, and get redirected to that
diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h
index 221548c97..57760f162 100644
--- a/include/asterisk/frame.h
+++ b/include/asterisk/frame.h
@@ -83,7 +83,8 @@ struct ast_codec_pref {
\arg \b HOLD Call is placed on hold
\arg \b UNHOLD Call is back from hold
\arg \b VIDUPDATE Video update requested
- \arg \b SRCUPDATE The source of media has changed
+ \arg \b SRCUPDATE The source of media has changed (RTP marker bit must change)
+ \arg \b SRCCHANGE Media source has changed (RTP marker bit and SSRC must change)
*/
@@ -316,6 +317,7 @@ enum ast_control_frame_type {
_XXX_AST_CONTROL_T38 = 19, /*!< T38 state change request/notification \deprecated This is no longer supported. Use AST_CONTROL_T38_PARAMETERS instead. */
AST_CONTROL_SRCUPDATE = 20, /*!< Indicate source of media has changed */
AST_CONTROL_T38_PARAMETERS = 24, /*!< T38 state change request/notification with parameters */
+ AST_CONTROL_SRCCHANGE = 25, /*!< Media source has changed and requires a new RTP SSRC */
};
enum ast_control_t38 {
diff --git a/include/asterisk/rtp.h b/include/asterisk/rtp.h
index da842e1f9..e7c80c58a 100644
--- a/include/asterisk/rtp.h
+++ b/include/asterisk/rtp.h
@@ -216,10 +216,11 @@ 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);
+/*! \brief Indicate that we need to set the marker bit */
+void ast_rtp_update_source(struct ast_rtp *rtp);
-void ast_rtp_new_source(struct ast_rtp *rtp);
+/*! \brief Indicate that we need to set the marker bit and change the ssrc */
+void ast_rtp_change_source(struct ast_rtp *rtp);
/*! \brief Setting RTP payload types from lines in a SDP description: */
void ast_rtp_pt_clear(struct ast_rtp* rtp);
diff --git a/main/channel.c b/main/channel.c
index cf2e7ff28..f63063c62 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -2487,6 +2487,7 @@ int ast_waitfordigit_full(struct ast_channel *c, int ms, int audiofd, int cmdfd)
case AST_CONTROL_RINGING:
case AST_CONTROL_ANSWER:
case AST_CONTROL_SRCUPDATE:
+ case AST_CONTROL_SRCCHANGE:
/* Unimportant */
break;
default:
@@ -3122,6 +3123,7 @@ static int attribute_const is_visible_indication(enum ast_control_frame_type con
case AST_CONTROL_PROCEEDING:
case AST_CONTROL_VIDUPDATE:
case AST_CONTROL_SRCUPDATE:
+ case AST_CONTROL_SRCCHANGE:
case AST_CONTROL_RADIO_KEY:
case AST_CONTROL_RADIO_UNKEY:
case AST_CONTROL_OPTION:
@@ -3227,6 +3229,7 @@ int ast_indicate_data(struct ast_channel *chan, int _condition,
case AST_CONTROL_PROCEEDING:
case AST_CONTROL_VIDUPDATE:
case AST_CONTROL_SRCUPDATE:
+ case AST_CONTROL_SRCCHANGE:
case AST_CONTROL_RADIO_KEY:
case AST_CONTROL_RADIO_UNKEY:
case AST_CONTROL_OPTION:
@@ -3932,6 +3935,7 @@ struct ast_channel *__ast_request_and_dial(const char *type, int format, void *d
case AST_CONTROL_UNHOLD:
case AST_CONTROL_VIDUPDATE:
case AST_CONTROL_SRCUPDATE:
+ case AST_CONTROL_SRCCHANGE:
case -1: /* Ignore -- just stopping indications */
break;
@@ -4891,6 +4895,7 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct
case AST_CONTROL_UNHOLD:
case AST_CONTROL_VIDUPDATE:
case AST_CONTROL_SRCUPDATE:
+ case AST_CONTROL_SRCCHANGE:
case AST_CONTROL_T38_PARAMETERS:
ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
if (jb_in_use) {
diff --git a/main/rtp.c b/main/rtp.c
index d463873f7..c8e89d9a0 100644
--- a/main/rtp.c
+++ b/main/rtp.c
@@ -1578,6 +1578,7 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
struct rtpPayloadType rtpPT;
struct ast_rtp *bridged = NULL;
int prev_seqno;
+ AST_LIST_HEAD_NOLOCK(, ast_frame) frames;
/* If time is up, kill it */
if (rtp->sending_digit)
@@ -1679,10 +1680,22 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
timestamp = ntohl(rtpheader[1]);
ssrc = ntohl(rtpheader[2]);
- if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
- if (option_debug || rtpdebug)
- ast_debug(0, "Forcing Marker bit, because SSRC has changed\n");
- mark = 1;
+ AST_LIST_HEAD_INIT_NOLOCK(&frames);
+ /* Force a marker bit and change SSRC if the SSRC changes */
+ if (rtp->rxssrc && rtp->rxssrc != ssrc) {
+ struct ast_frame *f, srcupdate = {
+ AST_FRAME_CONTROL,
+ .subclass = AST_CONTROL_SRCCHANGE,
+ };
+
+ if (!mark) {
+ if (option_debug || rtpdebug) {
+ ast_debug(0, "Forcing Marker bit, because SSRC has changed\n");
+ }
+ mark = 1;
+ }
+ f = ast_frisolate(&srcupdate);
+ AST_LIST_INSERT_TAIL(&frames, f, frame_list);
}
rtp->rxssrc = ssrc;
@@ -1713,7 +1726,7 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
if (res < hdrlen) {
ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
- return &ast_null_frame;
+ return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;
}
rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */
@@ -1777,7 +1790,11 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
} else {
ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr));
}
- return f ? f : &ast_null_frame;
+ if (f) {
+ AST_LIST_INSERT_TAIL(&frames, f, frame_list);
+ return AST_LIST_FIRST(&frames);
+ }
+ return &ast_null_frame;
}
rtp->lastrxformat = rtp->f.subclass = rtpPT.code;
rtp->f.frametype = (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
@@ -1793,7 +1810,8 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0));
rtp->resp = 0;
rtp->dtmf_timeout = rtp->dtmf_duration = 0;
- return f;
+ AST_LIST_INSERT_TAIL(&frames, f, frame_list);
+ return AST_LIST_FIRST(&frames);
}
}
@@ -1897,7 +1915,9 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
rtp->f.delivery.tv_usec = 0;
}
rtp->f.src = "RTP";
- return &rtp->f;
+
+ AST_LIST_INSERT_TAIL(&frames, &rtp->f, frame_list);
+ return AST_LIST_FIRST(&frames);
}
/* The following array defines the MIME Media type (and subtype) for each
@@ -2638,18 +2658,22 @@ int ast_rtp_setqos(struct ast_rtp *rtp, int type_of_service, int class_of_servic
return ast_netsock_set_qos(rtp->s, type_of_service, class_of_service, desc);
}
-void ast_rtp_set_constantssrc(struct ast_rtp *rtp)
+void ast_rtp_update_source(struct ast_rtp *rtp)
{
- rtp->constantssrc = 1;
+ if (rtp) {
+ rtp->set_marker_bit = 1;
+ ast_debug(3, "Setting the marker bit due to a source update\n");
+ }
}
-void ast_rtp_new_source(struct ast_rtp *rtp)
+void ast_rtp_change_source(struct ast_rtp *rtp)
{
if (rtp) {
+ unsigned int ssrc = ast_random();
+
rtp->set_marker_bit = 1;
- if (!rtp->constantssrc) {
- rtp->ssrc = ast_random();
- }
+ ast_debug(3, "Changing ssrc from %u to %u due to a source change\n", rtp->ssrc, ssrc);
+ rtp->ssrc = ssrc;
}
}