aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;
}
}