Skip to content

Commit

Permalink
Added support for the TURN REST API (draft-uberti-behave-turn-rest-00…
Browse files Browse the repository at this point in the history
…) to dynamically get TURN servers and credentials to use within Janus
  • Loading branch information
meetecho committed Apr 9, 2015
1 parent 10d71c9 commit 355bacc
Show file tree
Hide file tree
Showing 8 changed files with 637 additions and 28 deletions.
4 changes: 3 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ bin_PROGRAMS = janus
headerdir = $(includedir)/janus
header_HEADERS = \
plugins/plugin.h apierror.h config.h debug.h dtls.h ice.h mutex.h record.h \
rtcp.h rtp.h sctp.h sdp.h utils.h
rtcp.h rtp.h sctp.h sdp.h turnrest.h utils.h

confdir = $(sysconfdir)/janus
conf_DATA = conf/janus.cfg.sample
Expand Down Expand Up @@ -91,6 +91,8 @@ janus_SOURCES = \
sctp.h \
sdp.c \
sdp.h \
turnrest.c \
turnrest.h \
utils.c \
utils.h \
plugins/plugin.c \
Expand Down
22 changes: 22 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ AC_ARG_ENABLE([rabbitmq],
[],
[enable_rabbitmq=yes])

AC_ARG_ENABLE([libcurl],
[AS_HELP_STRING([--disable-libcurl],
[Disable TURN REST API client (via libcurl)])],
[],
[enable_libcurl=yes])

PKG_CHECK_MODULES([JANUS],
[
glib-2.0 >= glib_version
Expand Down Expand Up @@ -134,6 +140,19 @@ AC_CHECK_LIB([rabbitmq],
])
AM_CONDITIONAL([ENABLE_RABBITMQ], [test "x$enable_rabbitmq" = "xyes"])

PKG_CHECK_MODULES([LIBCURL],
[libcurl],
[
AC_DEFINE(HAVE_LIBCURL)
JANUS_MANUAL_LIBS+=" -lcurl"
enable_turn_rest_api=yes
],
[
AC_MSG_NOTICE(libcurl not found. The TURN REST API client will not be built.)
enable_turn_rest_api=no
])
AM_CONDITIONAL([ENABLE_TURN_REST_API], [test "x$enable_turn_rest_api" = "xyes"])

AC_CHECK_PROG([DOXYGEN],
[doxygen],
[doxygen])
Expand Down Expand Up @@ -289,6 +308,9 @@ AM_COND_IF([ENABLE_SCTP],
AM_COND_IF([ENABLE_POST_PROCESSING],
[echo "Recordings post-processor: yes"],
[echo "Recordings post-processor: no"])
AM_COND_IF([ENABLE_TURN_REST_API],
[echo "TURN REST API client: yes"],
[echo "TURN REST API client: no"])
AM_COND_IF([ENABLE_DOCS],
[echo "Doxygen documentation: yes"],
[echo "Doxygen documentation: no"])
Expand Down
231 changes: 210 additions & 21 deletions ice.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "janus.h"
#include "debug.h"
#include "ice.h"
#include "turnrest.h"
#include "dtls.h"
#include "rtp.h"
#include "rtcp.h"
Expand All @@ -42,7 +43,7 @@ uint16_t janus_ice_get_stun_port(void) {
}


/* TURN server/portand credentials, if any */
/* TURN server/port and credentials, if any */
static char *janus_turn_server = NULL;
static uint16_t janus_turn_port = 0;
static char *janus_turn_user = NULL, *janus_turn_pwd = NULL;
Expand All @@ -56,6 +57,16 @@ uint16_t janus_ice_get_turn_port(void) {
}


/* TURN REST API support, if any */
char *janus_ice_get_turn_rest_api(void) {
#ifndef HAVE_LIBCURL
return NULL;
#else
return (char *)janus_turnrest_get_backend();
#endif
}


/* ICE-Lite status */
static gboolean janus_ice_lite_enabled;
gboolean janus_ice_is_ice_lite_enabled(void) {
Expand Down Expand Up @@ -360,6 +371,11 @@ void janus_ice_init(gboolean ice_lite, gboolean ice_tcp, gboolean ipv6, uint16_t
JANUS_LOG(LOG_FATAL, "Got error %d (%s) trying to start handles watchdog...\n", error->code, error->message ? error->message : "??");
exit(1);
}

#ifdef HAVE_LIBCURL
/* Initialize the TURN REST API client stack, whether we're going to use it or not */
janus_turnrest_init();
#endif

}

Expand All @@ -375,6 +391,9 @@ void janus_ice_deinit(void) {
g_hash_table_destroy(old_handles);
old_handles = NULL;
janus_mutex_unlock(&old_handles_mutex);
#ifdef HAVE_LIBCURL
janus_turnrest_deinit();
#endif
}

int janus_ice_set_stun_server(gchar *stun_server, uint16_t stun_port) {
Expand Down Expand Up @@ -496,20 +515,45 @@ int janus_ice_set_turn_server(gchar *turn_server, uint16_t turn_port, gchar *tur
JANUS_LOG(LOG_ERR, "Unsupported relay type '%s'...\n", turn_type);
return -1;
}
if(janus_turn_server != NULL)
g_free(janus_turn_server);
janus_turn_server = g_strdup(inet_ntoa(*addr_list[0]));
if(janus_turn_server == NULL) {
JANUS_LOG(LOG_FATAL, "Memory error!\n");
return -1;
}
janus_turn_port = turn_port;
JANUS_LOG(LOG_VERB, " >> %s:%u\n", janus_turn_server, janus_turn_port);
if(janus_turn_user != NULL)
g_free(janus_turn_user);
janus_turn_user = NULL;
if(turn_user)
janus_turn_user = g_strdup(turn_user);
if(janus_turn_pwd != NULL)
g_free(janus_turn_pwd);
janus_turn_pwd = NULL;
if(turn_pwd)
janus_turn_pwd = g_strdup(turn_pwd);
return 0;
}

int janus_ice_set_turn_rest_api(gchar *api_server, gchar *api_key) {
#ifndef HAVE_LIBCURL
JANUS_LOG(LOG_ERR, "Janus has been nuilt with no libcurl support, TURN REST API unavailable\n");
return -1;
#else
if(api_server != NULL &&
(strstr(api_server, "http://") != api_server && strstr(api_server, "https://") != api_server)) {
JANUS_LOG(LOG_ERR, "Invalid TURN REST API backend: not an HTTP address\n");
return -1;
}
janus_turnrest_set_backend(api_server, api_key);
JANUS_LOG(LOG_INFO, "TURN REST API backend: %s\n", api_server ? api_server : "(disabled)");
#endif
return 0;
}


/* ICE stuff */
static const gchar *janus_ice_state_name[] =
{
Expand Down Expand Up @@ -1830,6 +1874,25 @@ int janus_ice_setup_local(janus_ice_handle *handle, int offer, int audio, int vi
"stun-server-port", janus_stun_port,
NULL);
}
/* Any dynamic TURN credentials to retrieve via REST API? */
gboolean have_turnrest_credentials = FALSE;
#ifdef HAVE_LIBCURL
janus_turnrest_response *turnrest_credentials = janus_turnrest_request();
if(turnrest_credentials != NULL) {
have_turnrest_credentials = TRUE;
JANUS_LOG(LOG_VERB, "[%"SCNu64"] Got credentials from the TURN REST API backend!\n", handle->handle_id);
JANUS_LOG(LOG_HUGE, " -- Username: %s\n", turnrest_credentials->username);
JANUS_LOG(LOG_HUGE, " -- Password: %s\n", turnrest_credentials->password);
JANUS_LOG(LOG_HUGE, " -- TTL: %"SCNu32"\n", turnrest_credentials->ttl);
JANUS_LOG(LOG_HUGE, " -- Servers: %d\n", g_list_length(turnrest_credentials->servers));
GList *server = turnrest_credentials->servers;
while(server != NULL) {
janus_turnrest_instance *instance = (janus_turnrest_instance *)server->data;
JANUS_LOG(LOG_HUGE, " -- -- URI: %s:%"SCNu16" (%d)\n", instance->server, instance->port, instance->transport);
server = server->next;
}
}
#endif
g_object_set(G_OBJECT(handle->agent), "upnp", FALSE, NULL);
g_object_set(G_OBJECT(handle->agent), "controlling-mode", !offer, NULL);
g_signal_connect (G_OBJECT (handle->agent), "candidate-gathering-done",
Expand Down Expand Up @@ -1925,10 +1988,34 @@ int janus_ice_setup_local(janus_ice_handle *handle, int offer, int audio, int vi
janus_mutex_init(&audio_stream->mutex);
audio_stream->components = g_hash_table_new(NULL, NULL);
g_hash_table_insert(handle->streams, GUINT_TO_POINTER(handle->audio_id), audio_stream);
if(janus_turn_server != NULL) {
/* We need relay candidates as well */
nice_agent_set_relay_info(handle->agent, handle->audio_id, 1,
janus_turn_server, janus_turn_port, janus_turn_user, janus_turn_pwd, janus_turn_type);
if(!have_turnrest_credentials) {
/* No TURN REST API server and credentials, any static ones? */
if(janus_turn_server != NULL) {
/* We need relay candidates as well */
gboolean ok = nice_agent_set_relay_info(handle->agent, handle->audio_id, 1,
janus_turn_server, janus_turn_port, janus_turn_user, janus_turn_pwd, janus_turn_type);
if(!ok) {
JANUS_LOG(LOG_WARN, "Could not set TURN server, is the address correct? (%s:%"SCNu16")\n",
janus_turn_server, janus_turn_port);
}
}
#ifdef HAVE_LIBCURL
} else {
/* We need relay candidates as well: add all those we got */
GList *server = turnrest_credentials->servers;
while(server != NULL) {
janus_turnrest_instance *instance = (janus_turnrest_instance *)server->data;
gboolean ok = nice_agent_set_relay_info(handle->agent, handle->audio_id, 1,
instance->server, instance->port,
turnrest_credentials->username, turnrest_credentials->password,
instance->transport);
if(!ok) {
JANUS_LOG(LOG_WARN, "Could not set TURN server, is the address correct? (%s:%"SCNu16")\n",
instance->server, instance->port);
}
server = server->next;
}
#endif
}
handle->audio_stream = audio_stream;
janus_ice_component *audio_rtp = (janus_ice_component *)calloc(1, sizeof(janus_ice_component));
Expand Down Expand Up @@ -1964,10 +2051,34 @@ int janus_ice_setup_local(janus_ice_handle *handle, int offer, int audio, int vi
JANUS_LOG(LOG_FATAL, "Memory error!\n");
return -1;
}
if(janus_turn_server != NULL) {
/* We need relay candidates as well */
nice_agent_set_relay_info(handle->agent, handle->audio_id, 2,
janus_turn_server, janus_turn_port, janus_turn_user, janus_turn_pwd, janus_turn_type);
if(!have_turnrest_credentials) {
/* No TURN REST API server and credentials, any static ones? */
if(janus_turn_server != NULL) {
/* We need relay candidates as well */
gboolean ok = nice_agent_set_relay_info(handle->agent, handle->audio_id, 2,
janus_turn_server, janus_turn_port, janus_turn_user, janus_turn_pwd, janus_turn_type);
if(!ok) {
JANUS_LOG(LOG_WARN, "Could not set TURN server, is the address correct? (%s:%"SCNu16")\n",
janus_turn_server, janus_turn_port);
}
}
#ifdef HAVE_LIBCURL
} else {
/* We need relay candidates as well: add all those we got */
GList *server = turnrest_credentials->servers;
while(server != NULL) {
janus_turnrest_instance *instance = (janus_turnrest_instance *)server->data;
gboolean ok = nice_agent_set_relay_info(handle->agent, handle->audio_id, 2,
instance->server, instance->port,
turnrest_credentials->username, turnrest_credentials->password,
instance->transport);
if(!ok) {
JANUS_LOG(LOG_WARN, "Could not set TURN server, is the address correct? (%s:%"SCNu16")\n",
instance->server, instance->port);
}
server = server->next;
}
#endif
}
audio_rtcp->stream = audio_stream;
audio_rtcp->candidates = NULL;
Expand Down Expand Up @@ -2026,10 +2137,34 @@ int janus_ice_setup_local(janus_ice_handle *handle, int offer, int audio, int vi
JANUS_LOG(LOG_FATAL, "Memory error!\n");
return -1;
}
if(janus_turn_server != NULL) {
/* We need relay candidates as well */
nice_agent_set_relay_info(handle->agent, handle->video_id, 1,
janus_turn_server, janus_turn_port, janus_turn_user, janus_turn_pwd, janus_turn_type);
if(!have_turnrest_credentials) {
/* No TURN REST API server and credentials, any static ones? */
if(janus_turn_server != NULL) {
/* We need relay candidates as well */
gboolean ok = nice_agent_set_relay_info(handle->agent, handle->video_id, 1,
janus_turn_server, janus_turn_port, janus_turn_user, janus_turn_pwd, janus_turn_type);
if(!ok) {
JANUS_LOG(LOG_WARN, "Could not set TURN server, is the address correct? (%s:%"SCNu16")\n",
janus_turn_server, janus_turn_port);
}
}
#ifdef HAVE_LIBCURL
} else {
/* We need relay candidates as well: add all those we got */
GList *server = turnrest_credentials->servers;
while(server != NULL) {
janus_turnrest_instance *instance = (janus_turnrest_instance *)server->data;
gboolean ok = nice_agent_set_relay_info(handle->agent, handle->video_id, 1,
instance->server, instance->port,
turnrest_credentials->username, turnrest_credentials->password,
instance->transport);
if(!ok) {
JANUS_LOG(LOG_WARN, "Could not set TURN server, is the address correct? (%s:%"SCNu16")\n",
instance->server, instance->port);
}
server = server->next;
}
#endif
}
video_rtp->stream = video_stream;
video_rtp->candidates = NULL;
Expand Down Expand Up @@ -2059,10 +2194,34 @@ int janus_ice_setup_local(janus_ice_handle *handle, int offer, int audio, int vi
JANUS_LOG(LOG_FATAL, "Memory error!\n");
return -1;
}
if(janus_turn_server != NULL) {
/* We need relay candidates as well */
nice_agent_set_relay_info(handle->agent, handle->audio_id, 2,
janus_turn_server, janus_turn_port, janus_turn_user, janus_turn_pwd, janus_turn_type);
if(!have_turnrest_credentials) {
/* No TURN REST API server and credentials, any static ones? */
if(janus_turn_server != NULL) {
/* We need relay candidates as well */
gboolean ok = nice_agent_set_relay_info(handle->agent, handle->video_id, 2,
janus_turn_server, janus_turn_port, janus_turn_user, janus_turn_pwd, janus_turn_type);
if(!ok) {
JANUS_LOG(LOG_WARN, "Could not set TURN server, is the address correct? (%s:%"SCNu16")\n",
janus_turn_server, janus_turn_port);
}
}
#ifdef HAVE_LIBCURL
} else {
/* We need relay candidates as well: add all those we got */
GList *server = turnrest_credentials->servers;
while(server != NULL) {
janus_turnrest_instance *instance = (janus_turnrest_instance *)server->data;
gboolean ok = nice_agent_set_relay_info(handle->agent, handle->video_id, 2,
instance->server, instance->port,
turnrest_credentials->username, turnrest_credentials->password,
instance->transport);
if(!ok) {
JANUS_LOG(LOG_WARN, "Could not set TURN server, is the address correct? (%s:%"SCNu16")\n",
instance->server, instance->port);
}
server = server->next;
}
#endif
}
video_rtcp->stream = video_stream;
video_rtcp->candidates = NULL;
Expand Down Expand Up @@ -2105,10 +2264,34 @@ int janus_ice_setup_local(janus_ice_handle *handle, int offer, int audio, int vi
return -1;
}
handle->data_mid = NULL;
if(janus_turn_server != NULL) {
/* We need relay candidates as well */
nice_agent_set_relay_info(handle->agent, handle->data_id, 1,
janus_turn_server, janus_turn_port, janus_turn_user, janus_turn_pwd, janus_turn_type);
if(!have_turnrest_credentials) {
/* No TURN REST API server and credentials, any static ones? */
if(janus_turn_server != NULL) {
/* We need relay candidates as well */
gboolean ok = nice_agent_set_relay_info(handle->agent, handle->data_id, 1,
janus_turn_server, janus_turn_port, janus_turn_user, janus_turn_pwd, janus_turn_type);
if(!ok) {
JANUS_LOG(LOG_WARN, "Could not set TURN server, is the address correct? (%s:%"SCNu16")\n",
janus_turn_server, janus_turn_port);
}
}
#ifdef HAVE_LIBCURL
} else {
/* We need relay candidates as well: add all those we got */
GList *server = turnrest_credentials->servers;
while(server != NULL) {
janus_turnrest_instance *instance = (janus_turnrest_instance *)server->data;
gboolean ok = nice_agent_set_relay_info(handle->agent, handle->data_id, 1,
instance->server, instance->port,
turnrest_credentials->username, turnrest_credentials->password,
instance->transport);
if(!ok) {
JANUS_LOG(LOG_WARN, "Could not set TURN server, is the address correct? (%s:%"SCNu16")\n",
instance->server, instance->port);
}
server = server->next;
}
#endif
}
data_stream->handle = handle;
data_stream->stream_id = handle->data_id;
Expand Down Expand Up @@ -2150,6 +2333,12 @@ int janus_ice_setup_local(janus_ice_handle *handle, int offer, int audio, int vi
nice_agent_gather_candidates (handle->agent, handle->data_id);
nice_agent_attach_recv (handle->agent, handle->data_id, 1, g_main_loop_get_context (handle->iceloop), janus_ice_cb_nice_recv, data_component);
}
#endif
#ifdef HAVE_LIBCURL
if(turnrest_credentials != NULL) {
janus_turnrest_response_destroy(turnrest_credentials);
turnrest_credentials = NULL;
}
#endif
return 0;
}
Expand Down
Loading

0 comments on commit 355bacc

Please sign in to comment.