diff options
-rw-r--r-- | channels/chan_sip.c | 53 | ||||
-rw-r--r-- | configs/sip.conf.sample | 26 | ||||
-rw-r--r-- | include/asterisk/rtp.h | 15 | ||||
-rw-r--r-- | main/rtp.c | 52 |
4 files changed, 117 insertions, 29 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 6b3be234c..80b009157 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -948,8 +948,6 @@ static struct sip_pvt { time_t lastrtprx; /*!< Last RTP received */ time_t lastrtptx; /*!< Last RTP sent */ int rtptimeout; /*!< RTP timeout time */ - int rtpholdtimeout; /*!< RTP timeout when on hold */ - int rtpkeepalive; /*!< Send RTP packets for keepalive */ struct sockaddr_in recv; /*!< Received as */ struct in_addr ourip; /*!< Our IP */ struct ast_channel *owner; /*!< Who owns us (if we have an owner) */ @@ -2593,17 +2591,21 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer) if (dialog->rtp) { ast_rtp_setdtmf(dialog->rtp, ast_test_flag(&dialog->flags[0], SIP_DTMF) != SIP_DTMF_INFO); ast_rtp_setdtmfcompensate(dialog->rtp, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); + ast_rtp_set_rtptimeout(dialog->rtp, peer->rtptimeout); + ast_rtp_set_rtpholdtimeout(dialog->rtp, peer->rtpholdtimeout); + ast_rtp_set_rtpkeepalive(dialog->rtp, peer->rtpkeepalive); + /* Set Frame packetization */ + ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs); + dialog->autoframing = peer->autoframing; } if (dialog->vrtp) { ast_rtp_setdtmf(dialog->vrtp, 0); ast_rtp_setdtmfcompensate(dialog->vrtp, 0); + ast_rtp_set_rtptimeout(dialog->vrtp, peer->rtptimeout); + ast_rtp_set_rtpholdtimeout(dialog->vrtp, peer->rtpholdtimeout); + ast_rtp_set_rtpkeepalive(dialog->vrtp, peer->rtpkeepalive); } - /* Set Frame packetization */ - if (dialog->rtp) { - ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs); - dialog->autoframing = peer->autoframing; - } ast_string_field_set(dialog, peername, peer->username); ast_string_field_set(dialog, authname, peer->username); ast_string_field_set(dialog, username, peer->username); @@ -2642,8 +2644,6 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer) dialog->noncodeccapability &= ~AST_RTP_DTMF; ast_string_field_set(dialog, context, peer->context); dialog->rtptimeout = peer->rtptimeout; - dialog->rtpholdtimeout = peer->rtpholdtimeout; - dialog->rtpkeepalive = peer->rtpkeepalive; if (peer->call_limit) ast_set_flag(&dialog->flags[0], SIP_CALL_LIMIT); dialog->maxcallbitrate = peer->maxcallbitrate; @@ -4171,16 +4171,19 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) != SIP_DTMF_INFO); ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); ast_rtp_settos(p->rtp, global_tos_audio); + ast_rtp_set_rtptimeout(p->rtp, global_rtptimeout); + ast_rtp_set_rtpholdtimeout(p->rtp, global_rtpholdtimeout); + ast_rtp_set_rtpkeepalive(p->rtp, global_rtpkeepalive); if (p->vrtp) { ast_rtp_settos(p->vrtp, global_tos_video); ast_rtp_setdtmf(p->vrtp, 0); ast_rtp_setdtmfcompensate(p->vrtp, 0); + ast_rtp_set_rtptimeout(p->vrtp, global_rtptimeout); + ast_rtp_set_rtpholdtimeout(p->vrtp, global_rtpholdtimeout); + ast_rtp_set_rtpkeepalive(p->vrtp, global_rtpkeepalive); } if (p->udptl) ast_udptl_settos(p->udptl, global_tos_audio); - p->rtptimeout = global_rtptimeout; - p->rtpholdtimeout = global_rtpholdtimeout; - p->rtpkeepalive = global_rtpkeepalive; p->maxcallbitrate = default_maxcallbitrate; } @@ -10184,6 +10187,7 @@ static int sip_show_settings(int fd, int argc, char *argv[]) ast_cli(fd, " T1 minimum: %d\n", global_t1min); ast_cli(fd, " Relax DTMF: %s\n", global_relaxdtmf ? "Yes" : "No"); ast_cli(fd, " Compact SIP headers: %s\n", compactheaders ? "Yes" : "No"); + ast_cli(fd, " RTP Keepalive: %d %s\n", global_rtpkeepalive, global_rtpkeepalive ? "" : "(Disabled)" ); ast_cli(fd, " RTP Timeout: %d %s\n", global_rtptimeout, global_rtptimeout ? "" : "(Disabled)" ); ast_cli(fd, " RTP Hold Timeout: %d %s\n", global_rtpholdtimeout, global_rtpholdtimeout ? "" : "(Disabled)"); ast_cli(fd, " MWI NOTIFY mime type: %s\n", default_notifymime); @@ -11598,6 +11602,9 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru if (bridgepvt->udptl) { if (p->t38.state == T38_PEER_REINVITE) { sip_handle_t38_reinvite(bridgepeer, p, 0); + ast_rtp_set_rtptimers_onhold(p->rtp); + if (p->vrtp) + ast_rtp_set_rtptimers_onhold(p->vrtp); /* Turn off RTP timers while we send fax */ } else if (p->t38.state == T38_DISABLED && bridgepeer && (bridgepvt->t38.state == T38_ENABLED)) { ast_log(LOG_WARNING, "RTP re-inivte after T38 session not handled yet !\n"); /* Insted of this we should somehow re-invite the other side of the bridge to RTP */ @@ -14714,23 +14721,23 @@ restartsearch: (sip->owner->_state == AST_STATE_UP) && !sip->redirip.sin_addr.s_addr) { if (sip->lastrtptx && - sip->rtpkeepalive && - (t > sip->lastrtptx + sip->rtpkeepalive)) { + ast_rtp_get_rtpkeepalive(sip->rtp) && + (t > sip->lastrtptx + ast_rtp_get_rtpkeepalive(sip->rtp))) { /* Need to send an empty RTP packet */ sip->lastrtptx = time(NULL); ast_rtp_sendcng(sip->rtp, 0); } if (sip->lastrtprx && - (sip->rtptimeout || sip->rtpholdtimeout) && - (t > sip->lastrtprx + sip->rtptimeout)) { + (ast_rtp_get_rtptimeout(sip->rtp) || ast_rtp_get_rtpholdtimeout(sip->rtp)) && + (t > sip->lastrtprx + ast_rtp_get_rtptimeout(sip->rtp))) { /* Might be a timeout now -- see if we're on hold */ struct sockaddr_in sin; ast_rtp_get_peer(sip->rtp, &sin); if (sin.sin_addr.s_addr || - (sip->rtpholdtimeout && - (t > sip->lastrtprx + sip->rtpholdtimeout))) { + (ast_rtp_get_rtpholdtimeout(sip->rtp) && + (t > sip->lastrtprx + ast_rtp_get_rtpholdtimeout(sip->rtp)))) { /* Needs a hangup */ - if (sip->rtptimeout) { + if (ast_rtp_get_rtptimeout(sip->rtp)) { while (sip->owner && ast_channel_trylock(sip->owner)) { ast_mutex_unlock(&sip->lock); usleep(1); @@ -14751,8 +14758,12 @@ restartsearch: has already been requested and we don't want to repeatedly request hangups */ - sip->rtptimeout = 0; - sip->rtpholdtimeout = 0; + ast_rtp_set_rtptimeout(sip->rtp, 0); + ast_rtp_set_rtpholdtimeout(sip->rtp, 0); + if (sip->vrtp) { + ast_rtp_set_rtptimeout(sip->vrtp, 0); + ast_rtp_set_rtpholdtimeout(sip->vrtp, 0); + } } } } diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample index 37e3ebba3..33959eff4 100644 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -91,12 +91,6 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ;language=en ; Default language setting for all users/peers ; This may also be set for individual users/peers ;relaxdtmf=yes ; Relax dtmf handling -;rtptimeout=60 ; Terminate call if 60 seconds of no RTP or RTCP activity - ; when we're not on hold. This is to be able to hangup - ; a call in the case of a phone disappearing from the net, - ; like a powerloss or grandma tripping over a cable. -;rtpholdtimeout=300 ; Terminate call if 300 seconds of no RTP or RTCP activity - ; when we're on hold (must be > rtptimeout) ;trustrpid = no ; If Remote-Party-ID should be trusted ;sendrpid = yes ; If Remote-Party-ID should be sent ;progressinband=never ; If we should generate in-band ringing always @@ -152,6 +146,21 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; ;regcontext=sipregistrations ; +;--------------------------- RTP timers ---------------------------------------------------- +; These timers are currently used for both audio and video streams. The RTP timeouts +; are only applied to the audio channel. +; The settings are settable in the global section as well as per device +; +;rtptimeout=60 ; Terminate call if 60 seconds of no RTP or RTCP activity + ; on the audio channel + ; when we're not on hold. This is to be able to hangup + ; a call in the case of a phone disappearing from the net, + ; like a powerloss or grandma tripping over a cable. +;rtpholdtimeout=300 ; Terminate call if 300 seconds of no RTP or RTCP activity + ; on the audio channel + ; when we're on hold (must be > rtptimeout) +;rtpkeepalive=<secs> ; Send keepalives in the RTP stream to keep NAT open + ; (default is off - zero) ;--------------------------- SIP DEBUGGING --------------------------------------------------- ;sipdebug = yes ; Turn on SIP debugging by default, from ; the moment the channel loads this configuration @@ -196,8 +205,9 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; ; This setting is available in the [general] section as well as in device configurations. ; Setting this to yes, enables T.38 fax (UDPTL) passthrough on SIP to SIP calls, provided -; both parties have T38 support enabled in their Asterisk configuration (either general or -; peer/user/friend sections) +; both parties have T38 support enabled in their Asterisk configuration +; This has to be enabled in the general section for all devices to work. You can then +; disable it on a per device basis. ; ; t38pt_udptl = yes ; Default false ; diff --git a/include/asterisk/rtp.h b/include/asterisk/rtp.h index d7738b345..839648878 100644 --- a/include/asterisk/rtp.h +++ b/include/asterisk/rtp.h @@ -219,6 +219,21 @@ struct ast_codec_pref *ast_rtp_codec_getpref(struct ast_rtp *rtp); int ast_rtp_codec_getformat(int pt); +/*! \brief Set rtp timeout */ +void ast_rtp_set_rtptimeout(struct ast_rtp *rtp, int timeout); +/*! \brief Set rtp hold timeout */ +void ast_rtp_set_rtpholdtimeout(struct ast_rtp *rtp, int timeout); +/*! \brief set RTP keepalive interval */ +void ast_rtp_set_rtpkeepalive(struct ast_rtp *rtp, int period); +/*! \brief Get RTP keepalive interval */ +int ast_rtp_get_rtpkeepalive(struct ast_rtp *rtp); +/*! \brief Get rtp hold timeout */ +int ast_rtp_get_rtpholdtimeout(struct ast_rtp *rtp); +/*! \brief Get rtp timeout */ +int ast_rtp_get_rtptimeout(struct ast_rtp *rtp); +/* \brief Put RTP timeout timers on hold during another transaction, like T.38 */ +void ast_rtp_set_rtptimers_onhold(struct ast_rtp *rtp); + #if defined(__cplusplus) || defined(c_plusplus) } #endif diff --git a/main/rtp.c b/main/rtp.c index 53ef9f1c0..8761f5d5b 100644 --- a/main/rtp.c +++ b/main/rtp.c @@ -128,6 +128,11 @@ struct ast_rtp { double rxtransit; /*!< Relative transit time for previous packet */ int lasttxformat; int lastrxformat; + + int rtptimeout; /*!< RTP timeout time (negative or zero means disabled, negative value means temporarily disabled) */ + int rtpholdtimeout; /*!< RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */ + int rtpkeepalive; /*!< Send RTP comfort noice packets for keepalive */ + /* DTMF Reception Variables */ char resp; unsigned int lasteventendseqn; @@ -521,6 +526,53 @@ unsigned int ast_rtcp_calc_interval(struct ast_rtp *rtp) return interval; } +/* \brief Put RTP timeout timers on hold during another transaction, like T.38 */ +void ast_rtp_set_rtptimers_onhold(struct ast_rtp *rtp) +{ + rtp->rtptimeout = (-1) * rtp->rtptimeout; + rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout; +} + +/*! \brief Set rtp timeout */ +void ast_rtp_set_rtptimeout(struct ast_rtp *rtp, int timeout) +{ + rtp->rtptimeout = timeout; +} + +/*! \brief Set rtp hold timeout */ +void ast_rtp_set_rtpholdtimeout(struct ast_rtp *rtp, int timeout) +{ + rtp->rtpholdtimeout = timeout; +} + +/*! \brief set RTP keepalive interval */ +void ast_rtp_set_rtpkeepalive(struct ast_rtp *rtp, int period) +{ + rtp->rtpkeepalive = period; +} + +/*! \brief Get rtp timeout */ +int ast_rtp_get_rtptimeout(struct ast_rtp *rtp) +{ + if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ + return 0; + return rtp->rtptimeout; +} + +/*! \brief Get rtp hold timeout */ +int ast_rtp_get_rtpholdtimeout(struct ast_rtp *rtp) +{ + if (rtp->rtptimeout < 0) /* We're not checking, but remembering the setting (during T.38 transmission) */ + return 0; + return rtp->rtpholdtimeout; +} + +/*! \brief Get RTP keepalive interval */ +int ast_rtp_get_rtpkeepalive(struct ast_rtp *rtp) +{ + return rtp->rtpkeepalive; +} + void ast_rtp_set_data(struct ast_rtp *rtp, void *data) { rtp->data = data; |