Commit 7f6ddac8 authored by Olivier Crête's avatar Olivier Crête

agent: Add force-relay property to force messages through the relay

This allows implementing WebRTC privacy mode.
parent c69d479e
...@@ -130,6 +130,7 @@ struct _NiceAgent ...@@ -130,6 +130,7 @@ struct _NiceAgent
gboolean controlling_mode; /* property: controlling-mode */ gboolean controlling_mode; /* property: controlling-mode */
guint timer_ta; /* property: timer Ta */ guint timer_ta; /* property: timer Ta */
guint max_conn_checks; /* property: max connectivity checks */ guint max_conn_checks; /* property: max connectivity checks */
gboolean force_relay; /* property: force relay */
GSList *local_addresses; /* list of NiceAddresses for local GSList *local_addresses; /* list of NiceAddresses for local
interfaces */ interfaces */
......
...@@ -111,7 +111,8 @@ enum ...@@ -111,7 +111,8 @@ enum
PROP_ICE_UDP, PROP_ICE_UDP,
PROP_ICE_TCP, PROP_ICE_TCP,
PROP_BYTESTREAM_TCP, PROP_BYTESTREAM_TCP,
PROP_KEEPALIVE_CONNCHECK PROP_KEEPALIVE_CONNCHECK,
PROP_FORCE_RELAY,
}; };
...@@ -689,6 +690,24 @@ nice_agent_class_init (NiceAgentClass *klass) ...@@ -689,6 +690,24 @@ nice_agent_class_init (NiceAgentClass *klass)
FALSE, FALSE,
G_PARAM_READWRITE)); G_PARAM_READWRITE));
/**
* NiceAgent:force-relay
*
* Force all traffic to go through a relay for added privacy, this
* allows hiding the local IP address. When this is enabled, so
* local candidates are available before relay servers have been set
* with nice_agent_set_relay_info().
*
* Since: UNRELEASED
*/
g_object_class_install_property (gobject_class, PROP_FORCE_RELAY,
g_param_spec_boolean (
"force-relay",
"Force Relay",
"Force all traffic to go through a relay for added privacy.",
FALSE,
G_PARAM_READWRITE));
/* install signals */ /* install signals */
/** /**
...@@ -1164,6 +1183,10 @@ nice_agent_get_property ( ...@@ -1164,6 +1183,10 @@ nice_agent_get_property (
g_value_set_boolean (value, agent->keepalive_conncheck); g_value_set_boolean (value, agent->keepalive_conncheck);
break; break;
case PROP_FORCE_RELAY:
g_value_set_boolean (value, agent->force_relay);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
} }
...@@ -1347,6 +1370,10 @@ nice_agent_set_property ( ...@@ -1347,6 +1370,10 @@ nice_agent_set_property (
agent->keepalive_conncheck = g_value_get_boolean (value); agent->keepalive_conncheck = g_value_get_boolean (value);
break; break;
case PROP_FORCE_RELAY:
agent->force_relay = g_value_get_boolean (value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
} }
...@@ -1868,6 +1895,11 @@ void agent_gathering_done (NiceAgent *agent) ...@@ -1868,6 +1895,11 @@ void agent_gathering_done (NiceAgent *agent)
for (k = component->local_candidates; k; k = k->next) { for (k = component->local_candidates; k; k = k->next) {
NiceCandidate *local_candidate = k->data; NiceCandidate *local_candidate = k->data;
if (agent->force_relay &&
local_candidate->type != NICE_CANDIDATE_TYPE_RELAYED)
continue;
if (nice_debug_is_enabled ()) { if (nice_debug_is_enabled ()) {
gchar tmpbuf[INET6_ADDRSTRLEN]; gchar tmpbuf[INET6_ADDRSTRLEN];
nice_address_to_string (&local_candidate->addr, tmpbuf); nice_address_to_string (&local_candidate->addr, tmpbuf);
...@@ -2575,6 +2607,10 @@ static void _upnp_mapped_external_port (GUPnPSimpleIgd *self, gchar *proto, ...@@ -2575,6 +2607,10 @@ static void _upnp_mapped_external_port (GUPnPSimpleIgd *self, gchar *proto,
for (k = component->local_candidates; k; k = k->next) { for (k = component->local_candidates; k; k = k->next) {
NiceCandidate *local_candidate = k->data; NiceCandidate *local_candidate = k->data;
if (agent->force_relay &&
local_candidate->type != NICE_CANDIDATE_TYPE_RELAYED)
continue;
if (nice_address_equal (&localaddr, &local_candidate->base_addr)) { if (nice_address_equal (&localaddr, &local_candidate->base_addr)) {
discovery_add_server_reflexive_candidate ( discovery_add_server_reflexive_candidate (
agent, agent,
...@@ -2660,7 +2696,7 @@ nice_agent_gather_candidates ( ...@@ -2660,7 +2696,7 @@ nice_agent_gather_candidates (
agent->full_mode ? "ICE-FULL" : "ICE-LITE"); agent->full_mode ? "ICE-FULL" : "ICE-LITE");
#ifdef HAVE_GUPNP #ifdef HAVE_GUPNP
if (agent->upnp_enabled && agent->upnp == NULL) { if (agent->upnp_enabled && agent->upnp == NULL && !agent->force_relay) {
agent->upnp = gupnp_simple_igd_thread_new (); agent->upnp = gupnp_simple_igd_thread_new ();
if (agent->upnp) { if (agent->upnp) {
...@@ -2821,7 +2857,7 @@ nice_agent_gather_candidates ( ...@@ -2821,7 +2857,7 @@ nice_agent_gather_candidates (
#endif #endif
/* TODO: Add server-reflexive support for TCP candidates */ /* TODO: Add server-reflexive support for TCP candidates */
if (agent->full_mode && agent->stun_server_ip && if (agent->full_mode && agent->stun_server_ip && !agent->force_relay &&
transport == NICE_CANDIDATE_TRANSPORT_UDP) { transport == NICE_CANDIDATE_TRANSPORT_UDP) {
NiceAddress stun_server; NiceAddress stun_server;
if (nice_address_set_from_string (&stun_server, agent->stun_server_ip)) { if (nice_address_set_from_string (&stun_server, agent->stun_server_ip)) {
...@@ -2863,6 +2899,10 @@ nice_agent_gather_candidates ( ...@@ -2863,6 +2899,10 @@ nice_agent_gather_candidates (
NiceComponent *component = nice_stream_find_component_by_id (stream, cid); NiceComponent *component = nice_stream_find_component_by_id (stream, cid);
for (i = component->local_candidates; i; i = i->next) { for (i = component->local_candidates; i; i = i->next) {
NiceCandidate *candidate = i->data; NiceCandidate *candidate = i->data;
if (agent->force_relay && candidate->type != NICE_CANDIDATE_TYPE_RELAYED)
continue;
agent_signal_new_candidate (agent, candidate); agent_signal_new_candidate (agent, candidate);
} }
} }
...@@ -3373,6 +3413,7 @@ agent_recv_message_unlocked ( ...@@ -3373,6 +3413,7 @@ agent_recv_message_unlocked (
NiceAddress from; NiceAddress from;
GList *item; GList *item;
gint retval; gint retval;
gboolean is_turn = FALSE;
/* We need an address for packet parsing, below. */ /* We need an address for packet parsing, below. */
if (message->from == NULL) { if (message->from == NULL) {
...@@ -3577,7 +3618,19 @@ agent_recv_message_unlocked ( ...@@ -3577,7 +3618,19 @@ agent_recv_message_unlocked (
nice_address_get_port (message->from), message->length); nice_address_get_port (message->from), message->length);
} }
for (item = component->turn_servers; item; item = g_list_next (item)) { if (nicesock->type == NICE_SOCKET_TYPE_UDP_TURN ||
nicesock->type == NICE_SOCKET_TYPE_UDP_TURN_OVER_TCP)
is_turn = TRUE;
if (!is_turn && component->turn_candidate &&
nice_address_equal (message->from,
&component->turn_candidate->turn->server)) {
is_turn = TRUE;
retval = nice_udp_turn_socket_parse_recv_message (
component->turn_candidate->sockptr, &nicesock, message);
}
for (item = component->turn_servers; item && !is_turn;
item = g_list_next (item)) {
TurnServer *turn = item->data; TurnServer *turn = item->data;
GSList *i = NULL; GSList *i = NULL;
...@@ -3586,14 +3639,13 @@ agent_recv_message_unlocked ( ...@@ -3586,14 +3639,13 @@ agent_recv_message_unlocked (
nice_debug_verbose ("Agent %p : Packet received from TURN server candidate.", nice_debug_verbose ("Agent %p : Packet received from TURN server candidate.",
agent); agent);
is_turn = TRUE;
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->stream_id == stream->id) {
cand->component_id == component->id &&
nice_socket_is_based_on (cand->sockptr, nicesock)) {
retval = nice_udp_turn_socket_parse_recv_message (cand->sockptr, &nicesock, retval = nice_udp_turn_socket_parse_recv_message (cand->sockptr, &nicesock,
message); message);
break; break;
...@@ -3602,6 +3654,12 @@ agent_recv_message_unlocked ( ...@@ -3602,6 +3654,12 @@ agent_recv_message_unlocked (
break; break;
} }
if (agent->force_relay && !is_turn) {
/* Ignore messages not from TURN if TURN is required */
retval = RECV_WOULD_BLOCK; /* EWOULDBLOCK */
goto done;
}
if (retval == RECV_OOB) if (retval == RECV_OOB)
goto done; goto done;
...@@ -4607,8 +4665,14 @@ nice_agent_get_local_candidates ( ...@@ -4607,8 +4665,14 @@ nice_agent_get_local_candidates (
goto done; goto done;
} }
for (item = component->local_candidates; item; item = item->next) for (item = component->local_candidates; item; item = item->next) {
ret = g_slist_append (ret, nice_candidate_copy (item->data)); NiceCandidate *cand = item->data;
if (agent->force_relay && cand->type != NICE_CANDIDATE_TYPE_RELAYED)
continue;
ret = g_slist_append (ret, nice_candidate_copy (cand));
}
done: done:
agent_unlock_and_emit (agent); agent_unlock_and_emit (agent);
...@@ -5460,6 +5524,10 @@ _get_default_local_candidate_locked (NiceAgent *agent, ...@@ -5460,6 +5524,10 @@ _get_default_local_candidate_locked (NiceAgent *agent,
for (i = component->local_candidates; i; i = i->next) { for (i = component->local_candidates; i; i = i->next) {
NiceCandidate *local_candidate = i->data; NiceCandidate *local_candidate = i->data;
if (agent->force_relay &&
local_candidate->type != NICE_CANDIDATE_TYPE_RELAYED)
continue;
/* Only check for ipv4 candidates */ /* Only check for ipv4 candidates */
if (nice_address_ip_version (&local_candidate->addr) != 4) if (nice_address_ip_version (&local_candidate->addr) != 4)
continue; continue;
...@@ -5634,6 +5702,9 @@ _generate_stream_sdp (NiceAgent *agent, NiceStream *stream, ...@@ -5634,6 +5702,9 @@ _generate_stream_sdp (NiceAgent *agent, NiceStream *stream,
for (j = component->local_candidates; j; j = j->next) { for (j = component->local_candidates; j; j = j->next) {
NiceCandidate *candidate = j->data; NiceCandidate *candidate = j->data;
if (agent->force_relay && candidate->type != NICE_CANDIDATE_TYPE_RELAYED)
continue;
_generate_candidate_sdp (agent, candidate, sdp); _generate_candidate_sdp (agent, candidate, sdp);
g_string_append (sdp, "\n"); g_string_append (sdp, "\n");
} }
......
...@@ -1730,8 +1730,11 @@ int conn_check_add_for_candidate (NiceAgent *agent, guint stream_id, NiceCompone ...@@ -1730,8 +1730,11 @@ int conn_check_add_for_candidate (NiceAgent *agent, guint stream_id, NiceCompone
g_assert (remote != NULL); g_assert (remote != NULL);
for (i = component->local_candidates; i ; i = i->next) { for (i = component->local_candidates; i ; i = i->next) {
NiceCandidate *local = i->data; NiceCandidate *local = i->data;
if (agent->force_relay && local->type != NICE_CANDIDATE_TYPE_RELAYED)
continue;
ret = conn_check_add_for_candidate_pair (agent, stream_id, component, local, remote); ret = conn_check_add_for_candidate_pair (agent, stream_id, component, local, remote);
if (ret) { if (ret) {
...@@ -2561,21 +2564,23 @@ static CandidateCheckPair *priv_process_response_check_for_reflexive(NiceAgent * ...@@ -2561,21 +2564,23 @@ static CandidateCheckPair *priv_process_response_check_for_reflexive(NiceAgent *
} }
else { else {
if (!local_cand) { if (!local_cand) {
local_cand = discovery_add_peer_reflexive_candidate (agent, if (!agent->force_relay)
stream->id, local_cand = discovery_add_peer_reflexive_candidate (agent,
component->id, stream->id,
&mapped, component->id,
sockptr, &mapped,
local_candidate, sockptr,
remote_candidate); local_candidate,
remote_candidate);
p->state = NICE_CHECK_FAILED; p->state = NICE_CHECK_FAILED;
nice_debug ("Agent %p : pair %p state FAILED", agent, p); nice_debug ("Agent %p : pair %p state FAILED", agent, p);
} }
/* step: add a new discovered pair (see RFC 5245 7.1.3.2.2 /* step: add a new discovered pair (see RFC 5245 7.1.3.2.2
"Constructing a Valid Pair") */ "Constructing a Valid Pair") */
new_pair = priv_add_peer_reflexive_pair (agent, stream->id, component, if (local_cand)
local_cand, p); new_pair = priv_add_peer_reflexive_pair (agent, stream->id, component,
local_cand, p);
nice_debug ("Agent %p : conncheck %p FAILED, %p DISCOVERED.", agent, p, new_pair); nice_debug ("Agent %p : conncheck %p FAILED, %p DISCOVERED.", agent, p, new_pair);
} }
...@@ -2780,25 +2785,27 @@ static gboolean priv_map_reply_to_discovery_request (NiceAgent *agent, StunMessa ...@@ -2780,25 +2785,27 @@ static gboolean priv_map_reply_to_discovery_request (NiceAgent *agent, StunMessa
d->pending = FALSE; d->pending = FALSE;
} else if (res == STUN_USAGE_BIND_RETURN_SUCCESS) { } else if (res == STUN_USAGE_BIND_RETURN_SUCCESS) {
/* case: successful binding discovery, create a new local candidate */ /* case: successful binding discovery, create a new local candidate */
NiceAddress niceaddr;
nice_address_set_from_sockaddr (&niceaddr, &sockaddr.addr); if (!agent->force_relay) {
NiceAddress niceaddr;
discovery_add_server_reflexive_candidate (
d->agent, nice_address_set_from_sockaddr (&niceaddr, &sockaddr.addr);
d->stream->id, discovery_add_server_reflexive_candidate (
d->component->id,
&niceaddr,
NICE_CANDIDATE_TRANSPORT_UDP,
d->nicesock,
FALSE);
if (d->agent->use_ice_tcp)
discovery_discover_tcp_server_reflexive_candidates (
d->agent, d->agent,
d->stream->id, d->stream->id,
d->component->id, d->component->id,
&niceaddr, &niceaddr,
d->nicesock); NICE_CANDIDATE_TRANSPORT_UDP,
d->nicesock,
FALSE);
if (d->agent->use_ice_tcp)
discovery_discover_tcp_server_reflexive_candidates (
d->agent,
d->stream->id,
d->component->id,
&niceaddr,
d->nicesock);
}
d->stun_message.buffer = NULL; d->stun_message.buffer = NULL;
d->stun_message.buffer_len = 0; d->stun_message.buffer_len = 0;
d->done = TRUE; d->done = TRUE;
...@@ -2931,7 +2938,8 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage * ...@@ -2931,7 +2938,8 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage *
* on a TCP connection, which cannot be used for server-reflexive * on a TCP connection, which cannot be used for server-reflexive
* discovery of candidates. * discovery of candidates.
*/ */
if (d->turn->type == NICE_RELAY_TYPE_TURN_UDP) { if (d->turn->type == NICE_RELAY_TYPE_TURN_UDP &&
!agent->force_relay) {
discovery_add_server_reflexive_candidate ( discovery_add_server_reflexive_candidate (
d->agent, d->agent,
d->stream->id, d->stream->id,
......
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