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 | 34 | ||||
-rw-r--r-- | channels/chan_skinny.c | 5 | ||||
-rw-r--r-- | configs/sip.conf.sample | 4 | ||||
-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 | 57 |
9 files changed, 76 insertions, 51 deletions
diff --git a/channels/chan_h323.c b/channels/chan_h323.c index 700fdd174..f8a929d6e 100644 --- a/channels/chan_h323.c +++ b/channels/chan_h323.c @@ -918,7 +918,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 159657b85..3f8b49e0d 100644 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -1442,7 +1442,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 618fdd7ca..6d80d466f 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -811,12 +811,11 @@ 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_CONSTANT_SSRC) + SIP_PAGE2_UDPTL_DESTINATION) /* SIP packet flags */ #define SIP_PKT_DEBUG (1 << 0) /*!< Debug this packet */ @@ -2952,9 +2951,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; @@ -2965,9 +2961,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); - } } ast_string_field_set(dialog, peername, peer->name); @@ -3871,6 +3864,7 @@ static int sip_answer(struct ast_channel *ast) if (option_debug) ast_log(LOG_DEBUG, "SIP answering channel: %s\n", ast->name); + ast_rtp_update_source(p->rtp); res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL); ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); } @@ -3905,7 +3899,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, 1); @@ -4153,11 +4147,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 */ @@ -4168,7 +4162,10 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data res = -1; 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; @@ -15085,14 +15082,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; if (option_debug > 1) @@ -17574,9 +17563,6 @@ 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; @@ -18650,8 +18636,6 @@ 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, "shrinkcallerid")) { if (ast_true(v->value)) { global_shrinkcallerid = 1; diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index 812aa16fb..48be77b9c 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -2868,7 +2868,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 914ccb775..838196d80 100644 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -385,8 +385,6 @@ 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 @@ -546,7 +544,6 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; maxcallbitrate maxcallbitrate ; rfc2833compensate mailbox ; t38pt_usertpsource username -; constantssrc template ; fromdomain ; regexten ; fromuser @@ -559,7 +556,6 @@ 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, diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h index 5cfe0eb0a..7f45d91f0 100644 --- a/include/asterisk/frame.h +++ b/include/asterisk/frame.h @@ -85,7 +85,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) */ @@ -290,6 +291,7 @@ enum ast_control_frame_type { AST_CONTROL_UNHOLD = 17, /*!< Indicate call is left from hold */ AST_CONTROL_VIDUPDATE = 18, /*!< Indicate video frame update */ AST_CONTROL_SRCUPDATE = 20, /*!< Indicate source of media has changed */ + AST_CONTROL_SRCCHANGE = 21, /*!< Media has changed and requires a new RTP SSRC */ }; #define AST_SMOOTHER_FLAG_G729 (1 << 0) diff --git a/include/asterisk/rtp.h b/include/asterisk/rtp.h index fada0bcb4..955e8bf99 100644 --- a/include/asterisk/rtp.h +++ b/include/asterisk/rtp.h @@ -179,10 +179,11 @@ 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); +/*! \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 a4ffd629d..4141d51bf 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1972,6 +1972,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: @@ -2571,6 +2572,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: @@ -2663,6 +2665,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: @@ -3367,6 +3370,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; @@ -4316,6 +4320,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: ast_indicate_data(other, f->subclass, f->data, f->datalen); if (jb_in_use) { ast_jb_empty_and_reset(c0, c1); diff --git a/main/rtp.c b/main/rtp.c index 4f54b71a5..76deb3c69 100644 --- a/main/rtp.c +++ b/main/rtp.c @@ -174,7 +174,6 @@ 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 */ @@ -1175,6 +1174,7 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp) unsigned int *rtpheader; struct rtpPayloadType rtpPT; struct ast_rtp *bridged = NULL; + AST_LIST_HEAD_NOLOCK(, ast_frame) frames; /* If time is up, kill it */ if (rtp->sending_digit) @@ -1253,11 +1253,23 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp) seqno &= 0xffff; timestamp = ntohl(rtpheader[1]); ssrc = ntohl(rtpheader[2]); - - if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) { - if (option_debug || rtpdebug) - ast_log(LOG_DEBUG, "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_log(LOG_DEBUG, "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; @@ -1280,7 +1292,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 */ @@ -1342,7 +1354,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_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO; @@ -1358,7 +1374,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); } } @@ -1391,7 +1408,9 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp) rtp->f.subclass |= 0x1; } 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 @@ -2063,18 +2082,26 @@ int ast_rtp_settos(struct ast_rtp *rtp, int tos) return res; } -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; + if (option_debug > 2) { + ast_log(LOG_DEBUG, "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(); + if (option_debug > 2) { + ast_log(LOG_DEBUG, "Changing ssrc from %u to %u due to a source change\n", rtp->ssrc, ssrc); } + rtp->ssrc = ssrc; } } |