mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-18 07:48:14 +00:00
Merge "res_pjsip: Add rtp_keepalive endpoint option."
This commit is contained in:
4
CHANGES
4
CHANGES
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user