Merge "res_pjsip: Add rtp_keepalive endpoint option."

changes/42/942/1
Joshua Colp 10 years ago committed by Gerrit Code Review
commit f7f3ae1815

@ -209,6 +209,10 @@ res_pjsip
'yes' and g.726 audio is negotiated, forces the codec to be treated as if it 'yes' and g.726 audio is negotiated, forces the codec to be treated as if it
is AAL2 packed on the channel. is AAL2 packed on the channel.
* A new 'rtp_keepalive' endpoint option has been added. This option specifies
an interval, in seconds, at which we will send RTP comfort noise packets to
the endpoint. This functions identically to chan_sip's "rtpkeepalive" option.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
--- Functionality changes from Asterisk 13.3.0 to Asterisk 13.4.0 ------------ --- Functionality changes from Asterisk 13.3.0 to Asterisk 13.4.0 ------------
------------------------------------------------------------------------------ ------------------------------------------------------------------------------

@ -0,0 +1,22 @@
"""Add RTP keepalive
Revision ID: 498357a710ae
Revises: 28b8e71e541f
Create Date: 2015-07-10 16:42:12.244421
"""
# revision identifiers, used by Alembic.
revision = '498357a710ae'
down_revision = '28b8e71e541f'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.add_column('ps_endpoints', sa.Column('rtp_keepalive', sa.Integer))
def downgrade():
op.drop_column('ps_endpoints', 'rtp_keepalive')

@ -502,6 +502,8 @@ struct ast_sip_media_rtp_configuration {
enum ast_sip_session_media_encryption encryption; enum ast_sip_session_media_encryption encryption;
/*! Do we want to optimistically support encryption if possible? */ /*! Do we want to optimistically support encryption if possible? */
unsigned int encryption_optimistic; unsigned int encryption_optimistic;
/*! Number of seconds between RTP keepalive packets */
unsigned int keepalive;
}; };
/*! /*!

@ -77,6 +77,8 @@ struct ast_sip_session_media {
enum ast_sip_session_media_encryption encryption; enum ast_sip_session_media_encryption encryption;
/*! \brief The media transport in use for this stream */ /*! \brief The media transport in use for this stream */
pj_str_t transport; pj_str_t transport;
/*! \brief Scheduler ID for RTP keepalive */
int keepalive_sched_id;
/*! \brief Stream is on hold by remote side */ /*! \brief Stream is on hold by remote side */
unsigned int remotely_held:1; unsigned int remotely_held:1;
/*! \brief Stream is on hold by local side */ /*! \brief Stream is on hold by local side */

@ -2288,6 +2288,22 @@ void ast_rtp_publish_rtcp_message(struct ast_rtp_instance *rtp,
struct ast_rtp_rtcp_report *report, struct ast_rtp_rtcp_report *report,
struct ast_json *blob); struct ast_json *blob);
/*!
* \brief Get the last RTP transmission time
*
* \param rtp The instance from which to get the last transmission time
* \return The last RTP transmission time
*/
time_t ast_rtp_instance_get_last_tx(const struct ast_rtp_instance *rtp);
/*!
* \brief Set the last RTP transmission time
*
* \param rtp The instance on which to set the last transmission time
* \param time The last transmission time
*/
void ast_rtp_instance_set_last_tx(struct ast_rtp_instance *rtp, time_t time);
/*! \addtogroup StasisTopicsAndMessages /*! \addtogroup StasisTopicsAndMessages
* @{ * @{
*/ */

@ -190,6 +190,8 @@ struct ast_rtp_instance {
struct ast_srtp *srtp; struct ast_srtp *srtp;
/*! Channel unique ID */ /*! Channel unique ID */
char channel_uniqueid[AST_MAX_UNIQUEID]; char channel_uniqueid[AST_MAX_UNIQUEID];
/*! Time of last packet sent */
time_t last_tx;
}; };
/*! List of RTP engines that are currently registered */ /*! List of RTP engines that are currently registered */
@ -2206,3 +2208,14 @@ int ast_rtp_engine_init()
return 0; return 0;
} }
time_t ast_rtp_instance_get_last_tx(const struct ast_rtp_instance *rtp)
{
return rtp->last_tx;
}
void ast_rtp_instance_set_last_tx(struct ast_rtp_instance *rtp, time_t time)
{
rtp->last_tx = time;
}

@ -790,6 +790,14 @@
have this accountcode set on it. have this accountcode set on it.
</para></description> </para></description>
</configOption> </configOption>
<configOption name="rtp_keepalive">
<synopsis>Number of seconds between RTP comfort noise keepalive packets.</synopsis>
<description><para>
At the specified interval, Asterisk will send an RTP comfort noise frame. This may
be useful for situations where Asterisk is behind a NAT or firewall and must keep
a hole open in order to allow for media to arrive at Asterisk.
</para></description>
</configOption>
</configObject> </configObject>
<configObject name="auth"> <configObject name="auth">
<synopsis>Authentication type</synopsis> <synopsis>Authentication type</synopsis>

@ -1880,6 +1880,7 @@ int ast_res_pjsip_initialize_configuration(void)
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "use_avpf", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_avpf)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "use_avpf", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_avpf));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "force_avp", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.force_avp)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "force_avp", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.force_avp));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_use_received_transport", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_received_transport)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "media_use_received_transport", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.use_received_transport));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtp_keepalive", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.rtp.keepalive));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "one_touch_recording", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, info.recording.enabled)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "one_touch_recording", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, info.recording.enabled));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "inband_progress", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, inband_progress)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "inband_progress", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, inband_progress));
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "call_group", "", group_handler, callgroup_to_str, NULL, 0, 0); ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "call_group", "", group_handler, callgroup_to_str, NULL, 0, 0);

@ -107,6 +107,39 @@ static void format_cap_only_type(struct ast_format_cap *caps, enum ast_media_typ
} }
} }
static int send_keepalive(const void *data)
{
struct ast_sip_session_media *session_media = (struct ast_sip_session_media *) data;
struct ast_rtp_instance *rtp = session_media->rtp;
int keepalive;
time_t interval;
int send_keepalive;
if (!rtp) {
return 0;
}
keepalive = ast_rtp_instance_get_keepalive(rtp);
if (!ast_sockaddr_isnull(&session_media->direct_media_addr)) {
ast_debug(3, "Not sending RTP keepalive on RTP instance %p since direct media is in use\n", rtp);
return keepalive * 1000;
}
interval = time(NULL) - ast_rtp_instance_get_last_tx(rtp);
send_keepalive = interval >= keepalive;
ast_debug(3, "It has been %d seconds since RTP was last sent on instance %p. %sending keepalive\n",
(int) interval, rtp, send_keepalive ? "S" : "Not s");
if (send_keepalive) {
ast_rtp_instance_sendcng(rtp, 0);
return keepalive * 1000;
}
return (keepalive - interval) * 1000;
}
/*! \brief Internal function which creates an RTP instance */ /*! \brief Internal function which creates an RTP instance */
static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_media *session_media, unsigned int ipv6) static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_media *session_media, unsigned int ipv6)
{ {
@ -1228,6 +1261,17 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
/* This purposely resets the encryption to the configured in case it gets added later */ /* This purposely resets the encryption to the configured in case it gets added later */
session_media->encryption = session->endpoint->media.rtp.encryption; session_media->encryption = session->endpoint->media.rtp.encryption;
if (session->endpoint->media.rtp.keepalive > 0 &&
stream_to_media_type(session_media->stream_type) == AST_MEDIA_TYPE_AUDIO) {
ast_rtp_instance_set_keepalive(session_media->rtp, session->endpoint->media.rtp.keepalive);
/* Schedule the initial keepalive early in case this is being used to punch holes through
* a NAT. This way there won't be an awkward delay before media starts flowing in some
* scenarios.
*/
session_media->keepalive_sched_id = ast_sched_add_variable(sched, 500, send_keepalive,
session_media, 1);
}
return 1; return 1;
} }
@ -1257,6 +1301,9 @@ static void change_outgoing_sdp_stream_media_address(pjsip_tx_data *tdata, struc
static void stream_destroy(struct ast_sip_session_media *session_media) static void stream_destroy(struct ast_sip_session_media *session_media)
{ {
if (session_media->rtp) { if (session_media->rtp) {
if (session_media->keepalive_sched_id != -1) {
AST_SCHED_DEL(sched, session_media->keepalive_sched_id);
}
ast_rtp_instance_stop(session_media->rtp); ast_rtp_instance_stop(session_media->rtp);
ast_rtp_instance_destroy(session_media->rtp); ast_rtp_instance_destroy(session_media->rtp);
} }

@ -1220,6 +1220,7 @@ static int add_session_media(void *obj, void *arg, int flags)
return CMP_STOP; return CMP_STOP;
} }
session_media->encryption = session->endpoint->media.rtp.encryption; session_media->encryption = session->endpoint->media.rtp.encryption;
session_media->keepalive_sched_id = -1;
/* Safe use of strcpy */ /* Safe use of strcpy */
strcpy(session_media->stream_type, handler_list->stream_type); strcpy(session_media->stream_type, handler_list->stream_type);
ao2_link(session->media, session_media); ao2_link(session->media, session_media);

@ -2166,6 +2166,7 @@ static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t siz
void *temp = buf; void *temp = buf;
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance); struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance);
int res;
*ice = 0; *ice = 0;
@ -2184,7 +2185,11 @@ static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t siz
} }
#endif #endif
return ast_sendto(rtcp ? rtp->rtcp->s : rtp->s, temp, len, flags, sa); res = ast_sendto(rtcp ? rtp->rtcp->s : rtp->s, temp, len, flags, sa);
if (res > 0) {
ast_rtp_instance_set_last_tx(instance, time(NULL));
}
return res;
} }
static int rtcp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice) static int rtcp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)

Loading…
Cancel
Save