diff options
-rw-r--r-- | agent/agent-priv.h | 1 | ||||
-rw-r--r-- | agent/agent.c | 89 | ||||
-rw-r--r-- | agent/conncheck.c | 60 |
3 files changed, 115 insertions, 35 deletions
diff --git a/agent/agent-priv.h b/agent/agent-priv.h index 9b7bdba..d66a9ef 100644 --- a/agent/agent-priv.h +++ b/agent/agent-priv.h @@ -130,6 +130,7 @@ struct _NiceAgent gboolean controlling_mode; /* property: controlling-mode */ guint timer_ta; /* property: timer Ta */ guint max_conn_checks; /* property: max connectivity checks */ + gboolean force_relay; /* property: force relay */ GSList *local_addresses; /* list of NiceAddresses for local interfaces */ diff --git a/agent/agent.c b/agent/agent.c index 108e87c..0f6a189 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -111,7 +111,8 @@ enum PROP_ICE_UDP, PROP_ICE_TCP, PROP_BYTESTREAM_TCP, - PROP_KEEPALIVE_CONNCHECK + PROP_KEEPALIVE_CONNCHECK, + PROP_FORCE_RELAY, }; @@ -689,6 +690,24 @@ nice_agent_class_init (NiceAgentClass *klass) FALSE, 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 */ /** @@ -1164,6 +1183,10 @@ nice_agent_get_property ( g_value_set_boolean (value, agent->keepalive_conncheck); break; + case PROP_FORCE_RELAY: + g_value_set_boolean (value, agent->force_relay); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -1347,6 +1370,10 @@ nice_agent_set_property ( agent->keepalive_conncheck = g_value_get_boolean (value); break; + case PROP_FORCE_RELAY: + agent->force_relay = g_value_get_boolean (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -1868,6 +1895,11 @@ void agent_gathering_done (NiceAgent *agent) for (k = component->local_candidates; k; k = k->next) { NiceCandidate *local_candidate = k->data; + + if (agent->force_relay && + local_candidate->type != NICE_CANDIDATE_TYPE_RELAYED) + continue; + if (nice_debug_is_enabled ()) { gchar tmpbuf[INET6_ADDRSTRLEN]; nice_address_to_string (&local_candidate->addr, tmpbuf); @@ -2575,6 +2607,10 @@ static void _upnp_mapped_external_port (GUPnPSimpleIgd *self, gchar *proto, for (k = component->local_candidates; k; k = k->next) { 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)) { discovery_add_server_reflexive_candidate ( agent, @@ -2660,7 +2696,7 @@ nice_agent_gather_candidates ( agent->full_mode ? "ICE-FULL" : "ICE-LITE"); #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 (); if (agent->upnp) { @@ -2821,7 +2857,7 @@ nice_agent_gather_candidates ( #endif /* 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) { NiceAddress stun_server; if (nice_address_set_from_string (&stun_server, agent->stun_server_ip)) { @@ -2863,6 +2899,10 @@ nice_agent_gather_candidates ( NiceComponent *component = nice_stream_find_component_by_id (stream, cid); for (i = component->local_candidates; i; i = i->next) { NiceCandidate *candidate = i->data; + + if (agent->force_relay && candidate->type != NICE_CANDIDATE_TYPE_RELAYED) + continue; + agent_signal_new_candidate (agent, candidate); } } @@ -3373,6 +3413,7 @@ agent_recv_message_unlocked ( NiceAddress from; GList *item; gint retval; + gboolean is_turn = FALSE; /* We need an address for packet parsing, below. */ if (message->from == NULL) { @@ -3577,7 +3618,19 @@ agent_recv_message_unlocked ( 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; GSList *i = NULL; @@ -3586,14 +3639,13 @@ agent_recv_message_unlocked ( nice_debug_verbose ("Agent %p : Packet received from TURN server candidate.", agent); + is_turn = TRUE; for (i = component->local_candidates; i; i = i->next) { NiceCandidate *cand = i->data; if (cand->type == NICE_CANDIDATE_TYPE_RELAYED && - cand->stream_id == stream->id && - cand->component_id == component->id && - nice_socket_is_based_on (cand->sockptr, nicesock)) { + cand->stream_id == stream->id) { retval = nice_udp_turn_socket_parse_recv_message (cand->sockptr, &nicesock, message); break; @@ -3602,6 +3654,12 @@ agent_recv_message_unlocked ( 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) goto done; @@ -4607,8 +4665,14 @@ nice_agent_get_local_candidates ( goto done; } - for (item = component->local_candidates; item; item = item->next) - ret = g_slist_append (ret, nice_candidate_copy (item->data)); + for (item = component->local_candidates; item; item = item->next) { + 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: agent_unlock_and_emit (agent); @@ -5460,6 +5524,10 @@ _get_default_local_candidate_locked (NiceAgent *agent, for (i = component->local_candidates; i; i = i->next) { NiceCandidate *local_candidate = i->data; + if (agent->force_relay && + local_candidate->type != NICE_CANDIDATE_TYPE_RELAYED) + continue; + /* Only check for ipv4 candidates */ if (nice_address_ip_version (&local_candidate->addr) != 4) continue; @@ -5634,6 +5702,9 @@ _generate_stream_sdp (NiceAgent *agent, NiceStream *stream, for (j = component->local_candidates; j; j = j->next) { NiceCandidate *candidate = j->data; + if (agent->force_relay && candidate->type != NICE_CANDIDATE_TYPE_RELAYED) + continue; + _generate_candidate_sdp (agent, candidate, sdp); g_string_append (sdp, "\n"); } diff --git a/agent/conncheck.c b/agent/conncheck.c index a71fc60..70e35c5 100644 --- a/agent/conncheck.c +++ b/agent/conncheck.c @@ -1730,8 +1730,11 @@ int conn_check_add_for_candidate (NiceAgent *agent, guint stream_id, NiceCompone g_assert (remote != NULL); for (i = component->local_candidates; i ; i = i->next) { - 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); if (ret) { @@ -2561,21 +2564,23 @@ static CandidateCheckPair *priv_process_response_check_for_reflexive(NiceAgent * } else { if (!local_cand) { - local_cand = discovery_add_peer_reflexive_candidate (agent, - stream->id, - component->id, - &mapped, - sockptr, - local_candidate, - remote_candidate); + if (!agent->force_relay) + local_cand = discovery_add_peer_reflexive_candidate (agent, + stream->id, + component->id, + &mapped, + sockptr, + local_candidate, + remote_candidate); p->state = NICE_CHECK_FAILED; nice_debug ("Agent %p : pair %p state FAILED", agent, p); } /* step: add a new discovered pair (see RFC 5245 7.1.3.2.2 "Constructing a Valid Pair") */ - new_pair = priv_add_peer_reflexive_pair (agent, stream->id, component, - local_cand, p); + if (local_cand) + 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); } @@ -2780,25 +2785,27 @@ static gboolean priv_map_reply_to_discovery_request (NiceAgent *agent, StunMessa d->pending = FALSE; } else if (res == STUN_USAGE_BIND_RETURN_SUCCESS) { /* case: successful binding discovery, create a new local candidate */ - NiceAddress niceaddr; - nice_address_set_from_sockaddr (&niceaddr, &sockaddr.addr); - - discovery_add_server_reflexive_candidate ( - d->agent, - d->stream->id, - d->component->id, - &niceaddr, - NICE_CANDIDATE_TRANSPORT_UDP, - d->nicesock, - FALSE); - if (d->agent->use_ice_tcp) - discovery_discover_tcp_server_reflexive_candidates ( + + if (!agent->force_relay) { + NiceAddress niceaddr; + + nice_address_set_from_sockaddr (&niceaddr, &sockaddr.addr); + discovery_add_server_reflexive_candidate ( d->agent, d->stream->id, d->component->id, &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_len = 0; d->done = TRUE; @@ -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 * 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 ( d->agent, d->stream->id, |