summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2015-07-09 14:17:53 -0500
committerMark Michelson <mmichelson@digium.com>2015-07-20 12:37:01 -0500
commit2b42264e66656f6ab6bc664eec4e93d353c58ffe (patch)
tree86f14c98fb53e3231beacb9af3670c674612daaf /res
parent4a25d55416c736431620ce357f2bd9e241d62372 (diff)
res_pjsip: Add rtp_keepalive endpoint option.
This adds an "rtp_keepalive" option for PJSIP endpoints. Similar to the chan_sip option, this specifies an interval, in seconds, at which we will send RTP comfort noise frames. This can be useful for keeping RTP sessions alive as well as keeping NAT associations alive during lulls. ASTERISK-25242 #close Reported by Mark Michelson Change-Id: I3b9903d99e35fe5d0b53ecc46df82c750776bc8d
Diffstat (limited to 'res')
-rw-r--r--res/res_pjsip.c8
-rw-r--r--res/res_pjsip/pjsip_configuration.c1
-rw-r--r--res/res_pjsip_sdp_rtp.c47
-rw-r--r--res/res_pjsip_session.c1
-rw-r--r--res/res_rtp_asterisk.c7
5 files changed, 63 insertions, 1 deletions
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 6d7e4f739..fefbff446 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -790,6 +790,14 @@
have this accountcode set on it.
</para></description>
</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 name="auth">
<synopsis>Authentication type</synopsis>
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index d4fa1521b..f20b031fc 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -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", "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", "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", "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);
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index 22c4529d9..e8654a91f 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -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 */
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 */
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;
}
@@ -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)
{
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_destroy(session_media->rtp);
}
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 84c343d3c..eaf0dc485 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -1219,6 +1219,7 @@ static int add_session_media(void *obj, void *arg, int flags)
return CMP_STOP;
}
session_media->encryption = session->endpoint->media.rtp.encryption;
+ session_media->keepalive_sched_id = -1;
/* Safe use of strcpy */
strcpy(session_media->stream_type, handler_list->stream_type);
ao2_link(session->media, session_media);
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 0a68a2db7..53e9b29c2 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -2166,6 +2166,7 @@ static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t siz
void *temp = buf;
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance);
+ int res;
*ice = 0;
@@ -2184,7 +2185,11 @@ static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t siz
}
#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)