diff options
-rw-r--r-- | channels/chan_h323.c | 6 | ||||
-rw-r--r-- | channels/chan_mgcp.c | 5 | ||||
-rw-r--r-- | channels/chan_sip.c | 35 | ||||
-rw-r--r-- | channels/chan_skinny.c | 5 | ||||
-rw-r--r-- | configs/sip.conf.sample | 3 | ||||
-rw-r--r-- | include/asterisk/frame.h | 4 | ||||
-rw-r--r-- | include/asterisk/rtp.h | 7 | ||||
-rw-r--r-- | main/channel.c | 5 | ||||
-rw-r--r-- | main/rtp.c | 52 |
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; } } |