Skip to content

Commit

Permalink
Add support for ICE consent freshness (requires libnice >= 0.1.19) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
lminiero committed Jun 28, 2023
1 parent e3a2aea commit cdfc0e0
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 4 deletions.
8 changes: 6 additions & 2 deletions conf/janus.jcfg.sample.in
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,11 @@ media: {
# it should work in ICE-Lite mode (by default it doesn't). If libnice is
# at least 0.1.15, you can choose which ICE nomination mode to use: valid
# values are "regular" and "aggressive" (the default depends on the libnice
# version itself; if we can set it, we set aggressive nomination). You can
# also configure whether to use connectivity checks as keep-alives, which
# version itself; if we can set it, we set aggressive nomination). If
# libnice is at least 0.1.19, you can enable consent freshness checks for
# PeerConnections as well: this will issue regular checks to check whether
# or not the WebRTC peer isn't available anymore. Enabling consent freshness
# will automatically also enable using connectivity checks as keep-alives, which
# might help detecting when a peer is no longer available (notice that
# current libnice master is breaking connections after 50 seconds when
# keepalive-conncheck is being used, so if you want to use it, better
Expand All @@ -286,6 +289,7 @@ nat: {
nice_debug = false
#full_trickle = true
#ice_nomination = "regular"
#ice_consent_freshness = true
#ice_keepalive_conncheck = true
#ice_lite = true
#ice_tcp = true
Expand Down
6 changes: 6 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,12 @@ AC_CHECK_LIB([nice],
[AC_MSG_NOTICE([libnice version does not have nice_agent_new_full])]
)

AC_CHECK_LIB([nice],
[nice_agent_consent_lost],
[AC_DEFINE(HAVE_CONSENT_FRESHNESS)],
[AC_MSG_NOTICE([libnice version does not have nice_agent_consent_lost])]
)

AC_CHECK_LIB([dl],
[dlopen],
[JANUS_MANUAL_LIBS="${JANUS_MANUAL_LIBS} -ldl"],
Expand Down
54 changes: 52 additions & 2 deletions src/ice.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,35 @@ const char *janus_ice_get_nomination_mode(void) {
}
#endif

/* ICE consent freshness */
static gboolean janus_ice_consent_freshness = FALSE;
void janus_ice_set_consent_freshness_enabled(gboolean enabled) {
#ifndef HAVE_CONSENT_FRESHNESS
if(enabled) {
JANUS_LOG(LOG_WARN, "libnice version doesn't support consent freshness\n");
return;
}
#endif
janus_ice_consent_freshness = enabled;
if(janus_ice_consent_freshness) {
JANUS_LOG(LOG_INFO, "Using content freshness checks in PeerConnection\n");
janus_ice_set_keepalive_conncheck_enabled(TRUE);
}
}
gboolean janus_ice_is_consent_freshness_enabled(void) {
return janus_ice_consent_freshness;
}

/* Keepalive via connectivity checks */
static gboolean janus_ice_keepalive_connchecks = FALSE;
void janus_ice_set_keepalive_conncheck_enabled(gboolean enabled) {
if(janus_ice_consent_freshness && !enabled) {
JANUS_LOG(LOG_WARN, "Can't disable connectivity checks as PeerConnection keep-alives, consent freshness is enabled\n");
return;
}
janus_ice_keepalive_connchecks = enabled;
if(janus_ice_keepalive_connchecks) {
JANUS_LOG(LOG_INFO, "Using connectivity checks as PeerConnection keep-alives\n");
JANUS_LOG(LOG_WARN, "Notice that the current libnice master is breaking connections after 50s when keepalive-conncheck enabled. As such, better to stick to 0.1.18 until the issue is addressed upstream\n");
}
}
gboolean janus_ice_is_keepalive_conncheck_enabled(void) {
Expand Down Expand Up @@ -862,6 +884,25 @@ static void janus_ice_notify_media(janus_ice_handle *handle, char *mid, gboolean
}
}

static void janus_ice_notify_ice_failed(janus_ice_handle *handle) {
if(handle == NULL)
return;
/* Prepare JSON event to notify user/application */
JANUS_LOG(LOG_VERB, "[%"SCNu64"] Notifying WebRTC ICE failure; %p\n", handle->handle_id, handle);
janus_session *session = (janus_session *)handle->session;
if(session == NULL)
return;
json_t *event = json_object();
json_object_set_new(event, "janus", json_string("ice-failed"));
json_object_set_new(event, "session_id", json_integer(session->session_id));
json_object_set_new(event, "sender", json_integer(handle->handle_id));
if(opaqueid_in_api && handle->opaque_id != NULL)
json_object_set_new(event, "opaque_id", json_string(handle->opaque_id));
/* Send the event */
JANUS_LOG(LOG_VERB, "[%"SCNu64"] Sending event to transport...; %p\n", handle->handle_id, handle);
janus_session_notify_event(session, event);
}

void janus_ice_notify_hangup(janus_ice_handle *handle, const char *reason) {
if(handle == NULL)
return;
Expand Down Expand Up @@ -2076,6 +2117,7 @@ static void janus_ice_cb_component_state_changed(NiceAgent *agent, guint stream_
JANUS_LOG(LOG_ERR, "[%"SCNu64"] No stream %d??\n", handle->handle_id, stream_id);
return;
}
guint prev_state = pc->state;
pc->state = state;
/* Notify event handlers */
if(janus_events_is_enabled()) {
Expand All @@ -2093,6 +2135,11 @@ static void janus_ice_cb_component_state_changed(NiceAgent *agent, guint stream_
gboolean alert_set = janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_ALERT);
if(alert_set)
return;
if(prev_state == NICE_COMPONENT_STATE_CONNECTED || prev_state == NICE_COMPONENT_STATE_READY) {
/* Failed after connected/ready means consent freshness detected something broken:
* notify the user via a Janus API event and then fire the 'failed' timer as sual */
janus_ice_notify_ice_failed(handle);
}
gboolean trickle_recv = (!janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_TRICKLE) || janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_ALL_TRICKLES));
gboolean answer_recv = janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_GOT_ANSWER);
JANUS_LOG(LOG_WARN, "[%"SCNu64"] ICE failed for component %d in stream %d, but let's give it some time... (trickle %s, answer %s, alert %s)\n",
Expand Down Expand Up @@ -3527,12 +3574,15 @@ int janus_ice_setup_local(janus_ice_handle *handle, gboolean offer, gboolean tri
JANUS_LOG(LOG_INFO, "[%"SCNu64"] Creating ICE agent (ICE %s mode, %s)\n", handle->handle_id,
janus_ice_lite_enabled ? "Lite" : "Full", handle->controlling ? "controlling" : "controlled");
handle->agent = g_object_new(NICE_TYPE_AGENT,
"compatibility", NICE_COMPATIBILITY_DRAFT19,
"compatibility", NICE_COMPATIBILITY_RFC5245,
"main-context", handle->mainctx,
"reliable", FALSE,
"full-mode", janus_ice_lite_enabled ? FALSE : TRUE,
#ifdef HAVE_ICE_NOMINATION
"nomination-mode", janus_ice_nomination,
#endif
#ifdef HAVE_CONSENT_FRESHNESS
"consent-freshness", janus_ice_consent_freshness ? TRUE : FALSE,
#endif
"keepalive-conncheck", janus_ice_keepalive_connchecks ? TRUE : FALSE,
#ifdef HAVE_LIBNICE_TCP
Expand Down
9 changes: 9 additions & 0 deletions src/ice.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@ void janus_ice_set_nomination_mode(const char *nomination);
* @returns "regular" or "aggressive" */
const char *janus_ice_get_nomination_mode(void);
#endif
/*! \brief Method to enable/disable consent freshness in PeerConnections.
* \note This is only available on libnice >= 0.1.19, and automatically enables
* keepalive connectivity checks too. Documentation for the setting:
* https://libnice.freedesktop.org/libnice/NiceAgent.html#NiceAgent--consent-freshness
* @param[in] enabled Whether the functionality should be enabled or disabled */
void janus_ice_set_consent_freshness_enabled(gboolean enabled);
/*! \brief Method to check whether consent fresnhess will be enabled in ICE
* @returns true if enabled, false (default) otherwise */
gboolean janus_ice_is_consent_freshness_enabled(void);
/*! \brief Method to enable/disable connectivity checks as keepalives for PeerConnections.
* \note The main rationale behind this setting is provided in the libnice documentation:
* https://libnice.freedesktop.org/libnice/NiceAgent.html#NiceAgent--keepalive-conncheck
Expand Down
4 changes: 4 additions & 0 deletions src/janus.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ static json_t *janus_info(const char *transaction) {
#ifdef HAVE_ICE_NOMINATION
json_object_set_new(info, "ice-nomination", json_string(janus_ice_get_nomination_mode()));
#endif
json_object_set_new(info, "ice-consent-freshness", janus_ice_is_consent_freshness_enabled() ? json_true() : json_false());
json_object_set_new(info, "ice-keepalive-conncheck", janus_ice_is_keepalive_conncheck_enabled() ? json_true() : json_false());
json_object_set_new(info, "full-trickle", janus_ice_is_full_trickle_enabled() ? json_true() : json_false());
json_object_set_new(info, "mdns-enabled", janus_ice_is_mdns_enabled() ? json_true() : json_false());
Expand Down Expand Up @@ -5201,6 +5202,9 @@ gint main(int argc, char *argv[]) {
janus_ice_set_nomination_mode(item->value);
#endif
}
item = janus_config_get(config, config_nat, janus_config_type_item, "ice_consent_freshness");
if(item && item->value)
janus_ice_set_consent_freshness_enabled(janus_is_true(item->value));
item = janus_config_get(config, config_nat, janus_config_type_item, "ice_keepalive_conncheck");
if(item && item->value)
janus_ice_set_keepalive_conncheck_enabled(janus_is_true(item->value));
Expand Down

0 comments on commit cdfc0e0

Please sign in to comment.