Commit be03b19f authored by Youness Alaoui's avatar Youness Alaoui

Add support for tcp turn in the agent's code. Thanks to Olivier Crete

parent d34c720b
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
#include "debug.h" #include "debug.h"
#include "socket.h" #include "socket.h"
#include "udp-turn.h" #include "stun/usages/turn.h"
#include "candidate.h" #include "candidate.h"
#include "component.h" #include "component.h"
#include "conncheck.h" #include "conncheck.h"
...@@ -102,7 +102,6 @@ enum ...@@ -102,7 +102,6 @@ enum
N_SIGNALS, N_SIGNALS,
}; };
static guint signals[N_SIGNALS]; static guint signals[N_SIGNALS];
static gboolean priv_attach_stream_component (NiceAgent *agent, static gboolean priv_attach_stream_component (NiceAgent *agent,
...@@ -110,6 +109,16 @@ static gboolean priv_attach_stream_component (NiceAgent *agent, ...@@ -110,6 +109,16 @@ static gboolean priv_attach_stream_component (NiceAgent *agent,
Component *component); Component *component);
static void priv_detach_stream_component (Stream *stream, Component *component); static void priv_detach_stream_component (Stream *stream, Component *component);
static StunUsageTurnCompatibility
priv_agent_to_turn_compatibility (NiceAgent *agent) {
return agent->compatibility == NICE_COMPATIBILITY_DRAFT19 ?
STUN_USAGE_TURN_COMPATIBILITY_DRAFT9 :
agent->compatibility == NICE_COMPATIBILITY_GOOGLE ?
STUN_USAGE_TURN_COMPATIBILITY_GOOGLE :
agent->compatibility == NICE_COMPATIBILITY_MSN ?
STUN_USAGE_TURN_COMPATIBILITY_MSN : STUN_USAGE_TURN_COMPATIBILITY_DRAFT9;
}
Stream *agent_find_stream (NiceAgent *agent, guint stream_id) Stream *agent_find_stream (NiceAgent *agent, guint stream_id)
{ {
GSList *i; GSList *i;
...@@ -646,8 +655,7 @@ agent_candidate_pair_priority (NiceAgent *agent, NiceCandidate *local, NiceCandi ...@@ -646,8 +655,7 @@ agent_candidate_pair_priority (NiceAgent *agent, NiceCandidate *local, NiceCandi
static gboolean static gboolean
priv_add_new_candidate_discovery_stun (NiceAgent *agent, priv_add_new_candidate_discovery_stun (NiceAgent *agent,
NiceCandidate *host_candidate, NiceAddress server, NiceCandidate *host_candidate, NiceAddress server,
Stream *stream, guint component_id, Stream *stream, guint component_id)
NiceAddress *addr)
{ {
CandidateDiscovery *cdisco; CandidateDiscovery *cdisco;
GSList *modified_list; GSList *modified_list;
...@@ -679,9 +687,8 @@ priv_add_new_candidate_discovery_stun (NiceAgent *agent, ...@@ -679,9 +687,8 @@ priv_add_new_candidate_discovery_stun (NiceAgent *agent,
static gboolean static gboolean
priv_add_new_candidate_discovery_turn (NiceAgent *agent, priv_add_new_candidate_discovery_turn (NiceAgent *agent,
NiceCandidate *host_candidate, NiceAddress server, NiceCandidate *host_candidate, TurnServer *turn,
Stream *stream, guint component_id, Stream *stream, guint component_id)
NiceAddress *addr)
{ {
CandidateDiscovery *cdisco; CandidateDiscovery *cdisco;
GSList *modified_list; GSList *modified_list;
...@@ -692,11 +699,25 @@ priv_add_new_candidate_discovery_turn (NiceAgent *agent, ...@@ -692,11 +699,25 @@ priv_add_new_candidate_discovery_turn (NiceAgent *agent,
cdisco = g_slice_new0 (CandidateDiscovery); cdisco = g_slice_new0 (CandidateDiscovery);
if (cdisco) { if (cdisco) {
modified_list = g_slist_append (agent->discovery_list, cdisco); modified_list = g_slist_append (agent->discovery_list, cdisco);
priv_agent_to_turn_compatibility (agent);
if (modified_list) { if (modified_list) {
cdisco->type = NICE_CANDIDATE_TYPE_RELAYED; cdisco->type = NICE_CANDIDATE_TYPE_RELAYED;
cdisco->nicesock = host_candidate->sockptr; if (turn->type == NICE_RELAY_TYPE_UDP) {
cdisco->server = server; cdisco->nicesock = host_candidate->sockptr;
} else {
cdisco->nicesock = nice_tcp_turn_socket_new (agent,
&turn->server,
priv_agent_to_turn_compatibility (agent));
if (!cdisco->nicesock) {
agent->discovery_list = g_slist_remove (modified_list, cdisco);
g_slice_free (CandidateDiscovery, cdisco);
return FALSE;
}
}
cdisco->turn = turn;
cdisco->server = turn->server;
cdisco->stream = stream; cdisco->stream = stream;
cdisco->component = stream_find_component_by_id (stream, component_id); cdisco->component = stream_find_component_by_id (stream, component_id);
cdisco->agent = agent; cdisco->agent = agent;
...@@ -779,10 +800,12 @@ nice_agent_add_stream ( ...@@ -779,10 +800,12 @@ nice_agent_add_stream (
} }
NICEAPI_EXPORT void nice_agent_set_relay_info(NiceAgent *agent, NICEAPI_EXPORT gboolean
nice_agent_set_relay_info(NiceAgent *agent,
guint stream_id, guint component_id, guint stream_id, guint component_id,
const gchar *server_ip, guint server_port, const gchar *server_ip, guint server_port,
const gchar *username, const gchar *password) const gchar *username, const gchar *password,
NiceRelayType type)
{ {
Component *component = NULL; Component *component = NULL;
...@@ -790,21 +813,27 @@ NICEAPI_EXPORT void nice_agent_set_relay_info(NiceAgent *agent, ...@@ -790,21 +813,27 @@ NICEAPI_EXPORT void nice_agent_set_relay_info(NiceAgent *agent,
g_static_rec_mutex_lock (&agent->mutex); g_static_rec_mutex_lock (&agent->mutex);
if (agent_find_component (agent, stream_id, component_id, NULL, &component)) { if (agent_find_component (agent, stream_id, component_id, NULL, &component)) {
nice_address_init (&component->turn_server); TurnServer *turn = g_slice_new0 (TurnServer);
nice_address_init (&turn->server);
if (nice_address_set_from_string (&component->turn_server, server_ip)) {
nice_address_set_port (&component->turn_server, server_port); if (nice_address_set_from_string (&turn->server, server_ip)) {
nice_address_set_port (&turn->server, server_port);
} else {
g_slice_free (TurnServer, turn);
g_static_rec_mutex_unlock (&agent->mutex);
return FALSE;
} }
g_free (component->turn_username); turn->username = g_strdup (username);
component->turn_username = g_strdup (username); turn->password = g_strdup (password);
turn->type = type;
g_free (component->turn_password);
component->turn_password = g_strdup (password);
component->turn_servers = g_list_append (component->turn_servers, turn);
} }
g_static_rec_mutex_unlock (&agent->mutex); g_static_rec_mutex_unlock (&agent->mutex);
return TRUE;
} }
...@@ -860,8 +889,7 @@ nice_agent_gather_candidates ( ...@@ -860,8 +889,7 @@ nice_agent_gather_candidates (
host_candidate, host_candidate,
stun_server, stun_server,
stream, stream,
n + 1 /* component-id */, n + 1);
addr);
if (res != TRUE) { if (res != TRUE) {
/* note: memory allocation failure, return error */ /* note: memory allocation failure, return error */
...@@ -870,22 +898,25 @@ nice_agent_gather_candidates ( ...@@ -870,22 +898,25 @@ nice_agent_gather_candidates (
} }
} }
if (agent->full_mode && if (agent->full_mode && component) {
component && nice_address_is_valid (&component->turn_server)) { GList *item;
gboolean res = for (item = component->turn_servers; item; item = item->next) {
priv_add_new_candidate_discovery_turn (agent, TurnServer *turn = item->data;
host_candidate,
component->turn_server, gboolean res =
stream, priv_add_new_candidate_discovery_turn (agent,
n + 1 /* component-id */, host_candidate,
addr); turn,
stream,
if (res != TRUE) { n + 1);
/* note: memory allocation failure, return error */
g_error ("Memory allocation failure?"); if (res != TRUE) {
} /* note: memory allocation failure, return error */
} g_error ("Memory allocation failure?");
}
}
}
} }
} }
...@@ -1307,6 +1338,7 @@ _nice_agent_recv ( ...@@ -1307,6 +1338,7 @@ _nice_agent_recv (
{ {
NiceAddress from; NiceAddress from;
gint len; gint len;
GList *item;
len = nice_socket_recv (socket, &from, buf_len, buf); len = nice_socket_recv (socket, &from, buf_len, buf);
...@@ -1329,18 +1361,24 @@ _nice_agent_recv ( ...@@ -1329,18 +1361,24 @@ _nice_agent_recv (
return 0; return 0;
} }
if (nice_address_equal (&from, &component->turn_server)) { for (item = component->turn_servers; item; item = g_list_next (item)) {
GSList * i = NULL; TurnServer *turn = item->data;
if (nice_address_equal (&from, &turn->server)) {
GSList * i = NULL;
#ifndef NDEBUG #ifndef NDEBUG
nice_debug ("Agent %p : Packet received from TURN server candidate.", agent); nice_debug ("Agent %p : Packet received from TURN server candidate.",
agent);
#endif #endif
for (i = component->local_candidates; i; i = i->next) { for (i = component->local_candidates; i; i = i->next) {
NiceCandidate *cand = i->data; NiceCandidate *cand = i->data;
if (cand->type == NICE_CANDIDATE_TYPE_RELAYED && if (cand->type == NICE_CANDIDATE_TYPE_RELAYED &&
cand->stream_id == stream->id && cand->component_id == component->id) { cand->stream_id == stream->id &&
len = nice_udp_turn_socket_parse_recv (cand->sockptr, &socket, cand->component_id == component->id) {
&from, len, buf, &from, buf, len); len = nice_udp_turn_socket_parse_recv (cand->sockptr, &socket,
&from, len, buf, &from, buf, len);
}
} }
break;
} }
} }
......
...@@ -98,6 +98,7 @@ typedef enum ...@@ -98,6 +98,7 @@ typedef enum
NICE_COMPONENT_TYPE_RTCP = 2 NICE_COMPONENT_TYPE_RTCP = 2
} NiceComponentType; } NiceComponentType;
typedef enum typedef enum
{ {
NICE_COMPATIBILITY_DRAFT19 = 0, NICE_COMPATIBILITY_DRAFT19 = 0,
...@@ -139,14 +140,15 @@ nice_agent_remove_stream ( ...@@ -139,14 +140,15 @@ nice_agent_remove_stream (
guint stream_id); guint stream_id);
void nice_agent_set_relay_info( gboolean nice_agent_set_relay_info(
NiceAgent *agent, NiceAgent *agent,
guint stream_id, guint stream_id,
guint component_id, guint component_id,
const gchar *server_ip, const gchar *server_ip,
guint server_port, guint server_port,
const gchar *username, const gchar *username,
const gchar *password); const gchar *password,
NiceRelayType type);
void void
nice_agent_gather_candidates ( nice_agent_gather_candidates (
......
...@@ -64,8 +64,25 @@ typedef enum ...@@ -64,8 +64,25 @@ typedef enum
NICE_CANDIDATE_TRANSPORT_UDP, NICE_CANDIDATE_TRANSPORT_UDP,
} NiceCandidateTransport; } NiceCandidateTransport;
typedef enum {
NICE_RELAY_TYPE_UDP,
NICE_RELAY_TYPE_TCP,
NICE_RELAY_TYPE_TLS
} NiceRelayType;
typedef struct _NiceCandidate NiceCandidate; typedef struct _NiceCandidate NiceCandidate;
typedef struct _TurnServer TurnServer;
struct _TurnServer
{
NiceAddress server; /**< TURN server address */
gchar *username; /**< TURN username */
gchar *password; /**< TURN password */
NiceRelayType type; /**< TURN type */
};
struct _NiceCandidate struct _NiceCandidate
{ {
NiceCandidateType type; NiceCandidateType type;
...@@ -79,6 +96,7 @@ struct _NiceCandidate ...@@ -79,6 +96,7 @@ struct _NiceCandidate
NiceSocket *sockptr; NiceSocket *sockptr;
gchar *username; /* pointer to a NULL-terminated username string */ gchar *username; /* pointer to a NULL-terminated username string */
gchar *password; /* pointer to a NULL-terminated password string */ gchar *password; /* pointer to a NULL-terminated password string */
TurnServer *turn;
}; };
......
...@@ -71,6 +71,7 @@ void ...@@ -71,6 +71,7 @@ void
component_free (Component *cmp) component_free (Component *cmp)
{ {
GSList *i; GSList *i;
GList *item;
for (i = cmp->local_candidates; i; i = i->next) { for (i = cmp->local_candidates; i; i = i->next) {
NiceCandidate *candidate = i->data; NiceCandidate *candidate = i->data;
...@@ -107,8 +108,13 @@ component_free (Component *cmp) ...@@ -107,8 +108,13 @@ component_free (Component *cmp)
g_slist_free (cmp->gsources); g_slist_free (cmp->gsources);
g_slist_free (cmp->incoming_checks); g_slist_free (cmp->incoming_checks);
g_free (cmp->turn_username); for (item = cmp->turn_servers; item; item = g_list_next (item)) {
g_free (cmp->turn_password); TurnServer *turn = item->data;
g_free (turn->username);
g_free (turn->password);
g_slice_free (TurnServer, turn);
}
g_list_free (cmp->turn_servers);
g_slice_free (Component, cmp); g_slice_free (Component, cmp);
} }
......
...@@ -82,9 +82,7 @@ struct _Component ...@@ -82,9 +82,7 @@ struct _Component
GSList *sockets; /**< list of NiceSocket objs */ GSList *sockets; /**< list of NiceSocket objs */
GSList *gsources; /**< list of GSource objs */ GSList *gsources; /**< list of GSource objs */
GSList *incoming_checks; /**< list of IncomingCheck objs */ GSList *incoming_checks; /**< list of IncomingCheck objs */
NiceAddress turn_server; /**< TURN server address */ GList *turn_servers; /**< List of TURN servers */
gchar *turn_username; /**< TURN username */
gchar *turn_password; /**< TURN password */
CandidatePair selected_pair; /**< independent from checklists, CandidatePair selected_pair; /**< independent from checklists,
see ICE 11.1. "Sending Media" (ID-19) */ see ICE 11.1. "Sending Media" (ID-19) */
gboolean media_after_tick; /**< true if media received since last gboolean media_after_tick; /**< true if media received since last
......
...@@ -560,10 +560,10 @@ static void priv_turn_allocate_refresh_tick_unlocked (CandidateRefresh *cand) ...@@ -560,10 +560,10 @@ static void priv_turn_allocate_refresh_tick_unlocked (CandidateRefresh *cand)
size_t password_len; size_t password_len;
size_t buffer_len = 0; size_t buffer_len = 0;
username = (uint8_t *)cand->component->turn_username; username = (uint8_t *)cand->turn->username;
username_len = (size_t) strlen (cand->component->turn_username); username_len = (size_t) strlen (cand->turn->username);
password = (uint8_t *)cand->component->turn_password; password = (uint8_t *)cand->turn->password;
password_len = (size_t) strlen (cand->component->turn_password); password_len = (size_t) strlen (cand->turn->password);
if (cand->agent->compatibility == NICE_COMPATIBILITY_MSN) { if (cand->agent->compatibility == NICE_COMPATIBILITY_MSN) {
username = g_base64_decode ((gchar *)username, &username_len); username = g_base64_decode ((gchar *)username, &username_len);
...@@ -1856,6 +1856,7 @@ priv_add_new_turn_refresh (CandidateDiscovery *cdisco, NiceCandidate *relay_cand ...@@ -1856,6 +1856,7 @@ priv_add_new_turn_refresh (CandidateDiscovery *cdisco, NiceCandidate *relay_cand
cand->nicesock = cdisco->nicesock; cand->nicesock = cdisco->nicesock;
cand->relay_socket = relay_cand->sockptr; cand->relay_socket = relay_cand->sockptr;
cand->server = cdisco->server; cand->server = cdisco->server;
cand->turn = cdisco->turn;
cand->stream = cdisco->stream; cand->stream = cdisco->stream;
cand->component = cdisco->component; cand->component = cdisco->component;
cand->agent = cdisco->agent; cand->agent = cdisco->agent;
...@@ -1917,7 +1918,7 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage * ...@@ -1917,7 +1918,7 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage *
if (res == STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER) { if (res == STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER) {
/* handle alternate server */ /* handle alternate server */
nice_address_set_from_sockaddr (&d->server, &alternate); nice_address_set_from_sockaddr (&d->server, &alternate);
nice_address_set_from_sockaddr (&d->component->turn_server, &alternate); nice_address_set_from_sockaddr (&d->turn->server, &alternate);
d->pending = FALSE; d->pending = FALSE;
} else if (res == STUN_USAGE_TURN_RETURN_RELAY_SUCCESS || } else if (res == STUN_USAGE_TURN_RETURN_RELAY_SUCCESS ||
...@@ -1944,7 +1945,8 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage * ...@@ -1944,7 +1945,8 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage *
d->stream->id, d->stream->id,
d->component->id, d->component->id,
&niceaddr, &niceaddr,
d->nicesock); d->nicesock,
d->turn);
priv_add_new_turn_refresh (d, relay_cand, lifetime); priv_add_new_turn_refresh (d, relay_cand, lifetime);
......
...@@ -179,10 +179,10 @@ void refresh_free_item (gpointer data, gpointer user_data) ...@@ -179,10 +179,10 @@ void refresh_free_item (gpointer data, gpointer user_data)
cand->tick_source = NULL; cand->tick_source = NULL;
} }
username = (uint8_t *)cand->component->turn_username; username = (uint8_t *)cand->turn->username;
username_len = (size_t) strlen (cand->component->turn_username); username_len = (size_t) strlen (cand->turn->username);
password = (uint8_t *)cand->component->turn_password; password = (uint8_t *)cand->turn->password;
password_len = (size_t) strlen (cand->component->turn_password); password_len = (size_t) strlen (cand->turn->password);
if (agent->compatibility == NICE_COMPATIBILITY_MSN) { if (agent->compatibility == NICE_COMPATIBILITY_MSN) {
username = g_base64_decode ((gchar *)username, &username_len); username = g_base64_decode ((gchar *)username, &username_len);
...@@ -524,7 +524,8 @@ discovery_add_relay_candidate ( ...@@ -524,7 +524,8 @@ discovery_add_relay_candidate (
guint stream_id, guint stream_id,
guint component_id, guint component_id,
NiceAddress *address, NiceAddress *address,
NiceSocket *base_socket) NiceSocket *base_socket,
TurnServer *turn)
{ {
NiceCandidate *candidate; NiceCandidate *candidate;
Component *component; Component *component;
...@@ -549,11 +550,12 @@ discovery_add_relay_candidate ( ...@@ -549,11 +550,12 @@ discovery_add_relay_candidate (
candidate->stream_id = stream_id; candidate->stream_id = stream_id;
candidate->component_id = component_id; candidate->component_id = component_id;
candidate->addr = *address; candidate->addr = *address;
candidate->turn = turn;
/* step: link to the base candidate+socket */ /* step: link to the base candidate+socket */
relay_socket = nice_udp_turn_socket_new (agent, address, relay_socket = nice_udp_turn_socket_new (agent, address,
base_socket, &component->turn_server, base_socket, &turn->server,
component->turn_username, component->turn_password, turn->username, turn->password,
priv_agent_to_udp_turn_compatibility (agent)); priv_agent_to_udp_turn_compatibility (agent));
if (relay_socket) { if (relay_socket) {
candidate->sockptr = relay_socket; candidate->sockptr = relay_socket;
...@@ -564,7 +566,7 @@ discovery_add_relay_candidate ( ...@@ -564,7 +566,7 @@ discovery_add_relay_candidate (
/* Google uses the turn username as the candidate username */ /* Google uses the turn username as the candidate username */
if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) { if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
g_free (candidate->username); g_free (candidate->username);
candidate->username = g_strdup (component->turn_username); candidate->username = g_strdup (turn->username);
} }
priv_assign_foundation (agent, candidate); priv_assign_foundation (agent, candidate);
...@@ -826,10 +828,10 @@ static gboolean priv_discovery_tick_unlocked (gpointer pointer) ...@@ -826,10 +828,10 @@ static gboolean priv_discovery_tick_unlocked (gpointer pointer)
buffer_len = stun_usage_bind_create (&agent->stun_agent, buffer_len = stun_usage_bind_create (&agent->stun_agent,
&cand->stun_message, cand->stun_buffer, sizeof(cand->stun_buffer)); &cand->stun_message, cand->stun_buffer, sizeof(cand->stun_buffer));
} else if (cand->type == NICE_CANDIDATE_TYPE_RELAYED) { } else if (cand->type == NICE_CANDIDATE_TYPE_RELAYED) {
uint8_t *username = (uint8_t *)cand->component->turn_username; uint8_t *username = (uint8_t *)cand->turn->username;
size_t username_len = (size_t) strlen (cand->component->turn_username); size_t username_len = (size_t) strlen (cand->turn->username);
uint8_t *password = (uint8_t *)cand->component->turn_password; uint8_t *password = (uint8_t *)cand->turn->password;
size_t password_len = (size_t) strlen (cand->component->turn_password); size_t password_len = (size_t) strlen (cand->turn->password);
if (agent->compatibility == NICE_COMPATIBILITY_MSN) { if (agent->compatibility == NICE_COMPATIBILITY_MSN) {
username = g_base64_decode ((gchar *)username, &username_len); username = g_base64_decode ((gchar *)username, &username_len);
...@@ -846,6 +848,8 @@ static gboolean priv_discovery_tick_unlocked (gpointer pointer) ...@@ -846,6 +848,8 @@ static gboolean priv_discovery_tick_unlocked (gpointer pointer)
priv_agent_to_turn_compatibility (agent)); priv_agent_to_turn_compatibility (agent));
if (agent->compatibility == NICE_COMPATIBILITY_MSN) { if (agent->compatibility == NICE_COMPATIBILITY_MSN) {
g_free (cand->msn_turn_username);
g_free (cand->msn_turn_password);
cand->msn_turn_username = username; cand->msn_turn_username = username;
cand->msn_turn_password = password; cand->msn_turn_password = password;
} }
......
...@@ -52,6 +52,7 @@ typedef struct ...@@ -52,6 +52,7 @@ typedef struct
gboolean done; /**< is discovery complete? */ gboolean done; /**< is discovery complete? */
Stream *stream; Stream *stream;
Component *component; Component *component;
TurnServer *turn;
StunAgent turn_agent; StunAgent turn_agent;
uint8_t *msn_turn_username; uint8_t *msn_turn_username;
uint8_t *msn_turn_password; uint8_t *msn_turn_password;
...@@ -70,6 +71,7 @@ typedef struct ...@@ -70,6 +71,7 @@ typedef struct
NiceAddress server; /**< STUN/TURN server address */ NiceAddress server; /**< STUN/TURN server address */
Stream *stream; Stream *stream;
Component *component; Component *component;
TurnServer *turn;
StunAgent turn_agent; StunAgent turn_agent;
GSource *timer_source; GSource *timer_source;
GSource *tick_source; GSource *tick_source;
...@@ -106,7 +108,8 @@ discovery_add_relay_candidate ( ...@@ -106,7 +108,8 @@ discovery_add_relay_candidate (
guint stream_id, guint stream_id,
guint component_id, guint component_id,
NiceAddress *address, NiceAddress *address,
NiceSocket *base_socket); NiceSocket *base_socket,
TurnServer *turn);
NiceCandidate* NiceCandidate*
discovery_add_server_reflexive_candidate ( discovery_add_server_reflexive_candidate (
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment