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 | 2 | ||||
-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, 49 deletions
diff --git a/channels/chan_h323.c b/channels/chan_h323.c index 68b64d979..32ba5060e 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 7536ea0e0..f30ddd15c 100644 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -1480,7 +1480,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 0d24aa8c2..7bd17a3ad 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -1064,7 +1064,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? */ @@ -1097,7 +1096,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_UDPTL_DESTINATION | SIP_PAGE2_VIDEOSUPPORT_ALWAYS | SIP_PAGE2_CONSTANT_SSRC | SIP_PAGE2_FAX_DETECT) + SIP_PAGE2_UDPTL_DESTINATION | SIP_PAGE2_VIDEOSUPPORT_ALWAYS | SIP_PAGE2_FAX_DETECT) /*@}*/ @@ -4773,9 +4772,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; @@ -4786,9 +4782,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); @@ -5792,7 +5785,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); } @@ -5827,7 +5820,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); @@ -6150,11 +6143,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 */ @@ -6173,7 +6166,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; @@ -19092,14 +19088,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"); @@ -22458,9 +22446,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 if (!strcasecmp(v->name, "faxdetect")) { ast_set_flag(&mask[1], SIP_PAGE2_FAX_DETECT); ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_FAX_DETECT); @@ -23860,8 +23845,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, "session-timers")) { int i = (int) str2stmode(v->value); if (i < 0) { diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index b9fe51548..9839ee2eb 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -3918,7 +3918,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 52265ba10..c8359e8c5 100644 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -673,8 +673,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 diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h index 05e3710fd..74df85739 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) */ @@ -306,6 +307,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 3037c5e32..07491024a 100644 --- a/include/asterisk/rtp.h +++ b/include/asterisk/rtp.h @@ -210,10 +210,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 5f1a9b3f7..0a6beb315 100644 --- a/main/channel.c +++ b/main/channel.c @@ -2460,6 +2460,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: @@ -3095,6 +3096,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: @@ -3200,6 +3202,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: @@ -3904,6 +3907,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; @@ -4863,6 +4867,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 2ee77cd21..2ff0aacbd 100644 --- a/main/rtp.c +++ b/main/rtp.c @@ -1584,6 +1584,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) @@ -1685,10 +1686,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; @@ -1719,7 +1732,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 */ @@ -1783,7 +1796,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; @@ -1799,7 +1816,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); } } @@ -1903,7 +1921,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 @@ -2597,18 +2617,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; } } |