diff options
-rw-r--r-- | agent/agent-priv.h | 6 | ||||
-rw-r--r-- | agent/agent.c | 477 | ||||
-rw-r--r-- | agent/component.c | 10 | ||||
-rw-r--r-- | agent/component.h | 3 | ||||
-rw-r--r-- | agent/stream.c | 2 | ||||
-rw-r--r-- | agent/stream.h | 6 |
6 files changed, 301 insertions, 203 deletions
diff --git a/agent/agent-priv.h b/agent/agent-priv.h index d6c488c..8c08b28 100644 --- a/agent/agent-priv.h +++ b/agent/agent-priv.h @@ -166,12 +166,10 @@ struct _NiceAgent "Determining Role" ID-19) */ NiceCompatibility compatibility; /* property: Compatibility mode */ gboolean media_after_tick; /* Received media after keepalive tick */ + gboolean upnp_enabled; /* whether UPnP discovery is enabled */ #ifdef HAVE_GUPNP GUPnPSimpleIgdThread* upnp; /* GUPnP Single IGD agent */ - gboolean upnp_enabled; /* whether UPnP discovery is enabled */ guint upnp_timeout; /* UPnP discovery timeout */ - GSList *upnp_mapping; /* NiceAddresses of cands being mapped */ - GSource *upnp_timer_source; /* source of upnp timeout timer */ #endif gchar *software_attribute; /* SOFTWARE attribute */ gboolean reliable; /* property: reliable */ @@ -246,7 +244,7 @@ StunUsageIceCompatibility agent_to_ice_compatibility (NiceAgent *agent); StunUsageTurnCompatibility agent_to_turn_compatibility (NiceAgent *agent); NiceTurnSocketCompatibility agent_to_turn_socket_compatibility (NiceAgent *agent); -void agent_remove_local_candidate (NiceAgent *agent, +void agent_remove_local_candidate (NiceAgent *agent, NiceStream *stream, NiceCandidate *candidate); void nice_agent_init_stun_agent (NiceAgent *agent, StunAgent *stun_agent); diff --git a/agent/agent.c b/agent/agent.c index e642b63..c9c9313 100644 --- a/agent/agent.c +++ b/agent/agent.c @@ -145,8 +145,6 @@ enum static guint signals[N_SIGNALS]; -static void priv_stop_upnp (NiceAgent *agent); - static void pseudo_tcp_socket_opened (PseudoTcpSocket *sock, gpointer user_data); static void pseudo_tcp_socket_readable (PseudoTcpSocket *sock, gpointer user_data); static void pseudo_tcp_socket_writable (PseudoTcpSocket *sock, gpointer user_data); @@ -1630,9 +1628,7 @@ nice_agent_set_property ( break; case PROP_UPNP: -#ifdef HAVE_GUPNP agent->upnp_enabled = g_value_get_boolean (value); -#endif break; case PROP_RELIABLE: @@ -2218,7 +2214,7 @@ _transport_to_string (NiceCandidateTransport type) { void agent_gathering_done (NiceAgent *agent) { - + gboolean upnp_running = FALSE; GSList *i, *j, *k, *l, *m; for (i = agent->streams; i; i = i->next) { @@ -2234,6 +2230,11 @@ void agent_gathering_done (NiceAgent *agent) if (!stream->gathering) continue; +#ifdef HAVE_GUPNP + if (stream->upnp_timer_source != NULL) + upnp_running = TRUE; +#endif + for (j = stream->components; j; j = j->next) { NiceComponent *component = j->data; @@ -2280,7 +2281,7 @@ void agent_gathering_done (NiceAgent *agent) "for OC2007R2 compatibility", agent); component->local_candidates = g_slist_remove (component->local_candidates, local_candidate); - agent_remove_local_candidate (agent, local_candidate); + agent_remove_local_candidate (agent, stream, local_candidate); nice_candidate_free (local_candidate); goto next_cand; } @@ -2305,15 +2306,8 @@ next_cand: } } -#ifdef HAVE_GUPNP - if (agent->discovery_timer_source == NULL && - agent->upnp_timer_source == NULL) { - agent_signal_gathering_done (agent); - } -#else - if (agent->discovery_timer_source == NULL) + if (agent->discovery_timer_source == NULL && !upnp_running) agent_signal_gathering_done (agent); -#endif } void agent_signal_gathering_done (NiceAgent *agent) @@ -2908,23 +2902,6 @@ nice_agent_set_relay_info(NiceAgent *agent, #ifdef HAVE_GUPNP -static void agent_check_upnp_gathering_done (NiceAgent *agent); - -static gboolean priv_upnp_timeout_cb_agent_locked (NiceAgent *agent, - gpointer user_data) -{ - nice_debug ("Agent %p : UPnP port mapping timed out", agent); - - /* We cannot free priv->upnp here as it may be holding mappings open which - * we are using (e.g. if some mappings were successful and others errored). */ - g_slist_free_full (agent->upnp_mapping, (GDestroyNotify) nice_address_free); - agent->upnp_mapping = NULL; - - agent_check_upnp_gathering_done (agent); - - return FALSE; -} - /* Check whether UPnP gathering is done, which is true when the list of pending * mappings (upnp_mapping) is empty. When it is empty, we have heard back from * gupnp-igd about each of the mappings we added, either successfully or not. @@ -2932,88 +2909,139 @@ static gboolean priv_upnp_timeout_cb_agent_locked (NiceAgent *agent, * Note that upnp_mapping has to be a list, rather than a counter, as the * mapped-external-port and error-mapping-port signals could be emitted multiple * times for each mapping. */ -static void agent_check_upnp_gathering_done (NiceAgent *agent) +static void check_upnp_gathering_done (NiceAgent *agent, + NiceStream *stream) { - if (agent->upnp_mapping != NULL) + if (stream->upnp_mapping != NULL) return; - if (agent->upnp_timer_source != NULL) { - g_source_destroy (agent->upnp_timer_source); - g_source_unref (agent->upnp_timer_source); - agent->upnp_timer_source = NULL; + if (stream->upnp_timer_source != NULL) { + g_source_destroy (stream->upnp_timer_source); + g_source_unref (stream->upnp_timer_source); + stream->upnp_timer_source = NULL; } agent_gathering_done (agent); } -static void _upnp_mapped_external_port (GUPnPSimpleIgd *self, gchar *proto, - gchar *external_ip, gchar *replaces_external_ip, guint external_port, - gchar *local_ip, guint local_port, gchar *description, gpointer user_data) +static gboolean priv_upnp_timeout_cb_agent_locked (NiceAgent *agent, + gpointer user_data) { - NiceAgent *agent = (NiceAgent*)user_data; - NiceAddress localaddr; - NiceAddress externaddr; - NiceCandidateTransport transport; - GSList *i, *j, *k; + NiceStream *stream = user_data; - agent_lock (agent); + nice_debug ("Agent %p s:%d : UPnP port mapping timed out", agent, + stream->id); - if (agent->upnp_timer_source == NULL) - goto end; + /* Force it to be done */ + stream->upnp_mapped = g_slist_concat (stream->upnp_mapped, + stream->upnp_mapping); + stream->upnp_mapping = NULL; - nice_debug ("Agent %p : Successfully mapped %s:%d to %s:%d", agent, local_ip, - local_port, external_ip, external_port); + check_upnp_gathering_done (agent, stream); - if (!nice_address_set_from_string (&localaddr, local_ip)) - goto end; - nice_address_set_port (&localaddr, local_port); + return G_SOURCE_REMOVE; +} + + +static GSList * +priv_find_upnp_candidate (GSList *upnp_list, NiceCandidate *host_candidate) +{ + GSList *item; + + for (item = upnp_list; item; item = item->next) { + NiceCandidate *c = item->data; + + if (!nice_candidate_equal_target (host_candidate, c)) + continue; - if (g_strcmp0 (proto, "TCP") == 0) - transport = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE; + if ((host_candidate->transport == NICE_CANDIDATE_TRANSPORT_UDP) != + (c->transport == NICE_CANDIDATE_TRANSPORT_UDP)) + continue; + + return item; + } + + return NULL; +} + +static NiceStream * +priv_find_candidate_for_upnp_mapping (NiceAgent *agent, gchar *proto, + gchar *local_ip, guint local_port, gboolean only_mapping, + gboolean *was_mapping, GSList **item) +{ + GSList *i; + NiceCandidate upnp_candidate = { .type = NICE_CANDIDATE_TYPE_HOST }; + + if (!nice_address_set_from_string (&upnp_candidate.addr, local_ip)) + return NULL; + + nice_address_set_port (&upnp_candidate.addr, local_port); + if (!g_strcmp0 (proto, "UDP")) + upnp_candidate.transport = NICE_CANDIDATE_TRANSPORT_UDP; else - transport = NICE_CANDIDATE_TRANSPORT_UDP; + upnp_candidate.transport = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE; - for (i = agent->upnp_mapping; i; i = i->next) { - NiceAddress *addr = i->data; - if (nice_address_equal (&localaddr, addr)) { - agent->upnp_mapping = g_slist_remove (agent->upnp_mapping, addr); - nice_address_free (addr); - break; + for (i = agent->streams; i; i = i->next) { + NiceStream *stream = i->data; + GSList *j; + + j = priv_find_upnp_candidate (stream->upnp_mapping, &upnp_candidate); + if (was_mapping) + *was_mapping = (j != NULL); + + if (j == NULL && !only_mapping) + j = priv_find_upnp_candidate (stream->upnp_mapped, &upnp_candidate); + + if (j) { + *item = j; + return stream; } } + return NULL; +} + + +static void _upnp_mapped_external_port (GUPnPSimpleIgd *self, gchar *proto, + gchar *external_ip, gchar *replaces_external_ip, guint external_port, + gchar *local_ip, guint local_port, gchar *description, gpointer user_data) +{ + NiceAgent *agent = (NiceAgent*)user_data; + NiceStream *stream = NULL; + GSList *item; + gboolean was_mapping = FALSE; + NiceAddress externaddr; + + nice_debug ("Agent %p : Successfully mapped %s:%d to %s:%d", agent, local_ip, + local_port, external_ip, external_port); + if (!nice_address_set_from_string (&externaddr, external_ip)) - goto end; + return; nice_address_set_port (&externaddr, external_port); - for (i = agent->streams; i; i = i->next) { - NiceStream *stream = i->data; - for (j = stream->components; j; j = j->next) { - NiceComponent *component = j->data; - for (k = component->local_candidates; k; k = k->next) { - NiceCandidateImpl *local_candidate = k->data; + agent_lock (agent); - if (agent->force_relay && - local_candidate->c.type != NICE_CANDIDATE_TYPE_RELAYED) - continue; + stream = priv_find_candidate_for_upnp_mapping (agent, proto, + local_ip, local_port, FALSE, &was_mapping, &item); - if (nice_address_equal (&localaddr, &local_candidate->c.base_addr)) { - discovery_add_server_reflexive_candidate ( - agent, - stream->id, - component->id, - &externaddr, - transport, - local_candidate->sockptr, - TRUE); - goto end; - } - } + if (stream && stream->upnp_timer_source) { + NiceCandidateImpl *host_candidate = item->data; + + if (was_mapping) { + stream->upnp_mapping = g_slist_delete_link (stream->upnp_mapping, item); + stream->upnp_mapped = g_slist_prepend (stream->upnp_mapped, + host_candidate); } - } - end: - agent_check_upnp_gathering_done (agent); + discovery_add_server_reflexive_candidate (agent, + host_candidate->c.stream_id, host_candidate->c.component_id, + &externaddr, + host_candidate->c.transport, + host_candidate->sockptr, + TRUE); + + check_upnp_gathering_done (agent, stream); + } agent_unlock_and_emit (agent); } @@ -3022,32 +3050,180 @@ static void _upnp_error_mapping_port (GUPnPSimpleIgd *self, GError *error, gchar *proto, guint external_port, gchar *local_ip, guint local_port, gchar *description, gpointer user_data) { - NiceAgent *agent = (NiceAgent*)user_data; - NiceAddress localaddr; - GSList *i; + NiceAgent *agent = (NiceAgent *) user_data; + NiceStream *stream; + GSList *item; agent_lock (agent); nice_debug ("Agent %p : Error mapping %s:%d to %d (%d) : %s", agent, local_ip, local_port, external_port, error->domain, error->message); - if (nice_address_set_from_string (&localaddr, local_ip)) { - nice_address_set_port (&localaddr, local_port); - for (i = agent->upnp_mapping; i; i = i->next) { - NiceAddress *addr = i->data; - if (nice_address_equal (&localaddr, addr)) { - agent->upnp_mapping = g_slist_remove (agent->upnp_mapping, addr); - nice_address_free (addr); - break; - } - } + stream = priv_find_candidate_for_upnp_mapping (agent, proto, + local_ip, local_port, TRUE, NULL, &item); - agent_check_upnp_gathering_done (agent); + if (stream) { + NiceCandidate *host_candidate = item->data; + + stream->upnp_mapping = g_slist_delete_link (stream->upnp_mapping, item); + stream->upnp_mapped = + g_slist_prepend (stream->upnp_mapped, host_candidate); + check_upnp_gathering_done (agent, stream); } agent_unlock_and_emit (agent); } +static void +priv_add_upnp_discovery (NiceAgent *agent, NiceStream *stream, + NiceCandidate *host_candidate) +{ + gchar local_ip[NICE_ADDRESS_STRING_LEN]; + + if (!agent->upnp_enabled || agent->force_relay) + return; + + if (agent->upnp == NULL) { + agent->upnp = gupnp_simple_igd_thread_new (); + + if (agent->upnp == NULL) { + nice_debug ("Agent %p : Could not initialize GUPnP library", agent); + agent->upnp_enabled = FALSE; + return; + } + + g_signal_connect (agent->upnp, "mapped-external-port", + G_CALLBACK (_upnp_mapped_external_port), agent); + g_signal_connect (agent->upnp, "error-mapping-port", + G_CALLBACK (_upnp_error_mapping_port), agent); + } + + if (host_candidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE) + return; + + if (priv_find_upnp_candidate (stream->upnp_mapping, host_candidate)) + return; + if (priv_find_upnp_candidate (stream->upnp_mapped, host_candidate)) + return; + + nice_address_to_string (&host_candidate->addr, local_ip); + + gupnp_simple_igd_add_port (GUPNP_SIMPLE_IGD (agent->upnp), + host_candidate->transport == NICE_CANDIDATE_TRANSPORT_UDP ? "UDP" : "TCP", + 0, local_ip, nice_address_get_port (&host_candidate->addr), + 0, PACKAGE_STRING); + stream->upnp_mapping = g_slist_prepend (stream->upnp_mapping, + nice_candidate_copy (host_candidate)); + + if (stream->upnp_timer_source == NULL) + agent_timeout_add_with_context (agent, &stream->upnp_timer_source, + "UPnP timeout", agent->upnp_timeout, + priv_upnp_timeout_cb_agent_locked, stream); +} + +static void +priv_remove_upnp_mapping (NiceAgent *agent, NiceCandidate *host_candidate) +{ + gchar local_ip[NICE_ADDRESS_STRING_LEN] = ""; + + nice_address_to_string (&host_candidate->addr, local_ip); + + g_print ("REMOVING %s: %d\n", local_ip, nice_address_get_port (&host_candidate->addr)); + + gupnp_simple_igd_remove_port_local (GUPNP_SIMPLE_IGD (agent->upnp), + host_candidate->transport == NICE_CANDIDATE_TRANSPORT_UDP ? "UDP" : + "TCP", + local_ip, nice_address_get_port (&host_candidate->addr)); +} + +void +agent_remove_local_candidate (NiceAgent *agent, NiceStream *stream, + NiceCandidate *local_candidate) +{ + GSList *item; + + if (agent->upnp == NULL) + return; + + if (local_candidate->type != NICE_CANDIDATE_TYPE_HOST) + return; + + if (local_candidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE) + return; + + item = priv_find_upnp_candidate (stream->upnp_mapping, local_candidate); + if (item) { + nice_candidate_free (item->data); + stream->upnp_mapping = g_slist_delete_link (stream->upnp_mapping, item); + } + + item = priv_find_upnp_candidate (stream->upnp_mapped, local_candidate); + if (item) { + nice_candidate_free (item->data); + stream->upnp_mapped = g_slist_delete_link (stream->upnp_mapped, item); + } + + priv_remove_upnp_mapping (agent, local_candidate); +} + +static void +priv_stop_upnp (NiceAgent *agent, NiceStream *stream) +{ + if (agent->upnp == NULL) + return; + + if (stream->upnp_timer_source != NULL) { + g_source_destroy (stream->upnp_timer_source); + g_source_unref (stream->upnp_timer_source); + stream->upnp_timer_source = NULL; + } + + while (stream->upnp_mapping) { + NiceCandidate *host_candidate = stream->upnp_mapping->data; + + priv_remove_upnp_mapping (agent, host_candidate); + + nice_candidate_free (host_candidate); + stream->upnp_mapping = g_slist_delete_link (stream->upnp_mapping, + stream->upnp_mapping); + } + + while (stream->upnp_mapped) { + NiceCandidate *host_candidate = stream->upnp_mapped->data; + + priv_remove_upnp_mapping (agent, host_candidate); + + nice_candidate_free (host_candidate); + stream->upnp_mapped = g_slist_delete_link (stream->upnp_mapped, + stream->upnp_mapped); + } +} + +#else /* HAVE_GUPNP */ + +static inline void +priv_add_upnp_discovery (NiceAgent *agent, NiceStream *stream, + NiceCandidate *host_candidate) +{ + /* Use the upnp_enabled to print this only once */ + if (agent->upnp_enabled) { + nice_debug ("Agent %p : libnice compiled without GUPnP support", agent); + agent->upnp_enabled = FALSE; + } +} + +static void +priv_stop_upnp (NiceAgent *agent, NiceStream *stream) { + /* Do nothing */ +} + +void +agent_remove_local_candidate (NiceAgent *agent, NiceStream *stream, + NiceCandidate *local_candidate) +{ + /* Do nothing */ +} + #endif NICEAPI_EXPORT gboolean @@ -3082,25 +3258,6 @@ nice_agent_gather_candidates ( nice_debug ("Agent %p : In %s mode, starting candidate gathering.", agent, agent->full_mode ? "ICE-FULL" : "ICE-LITE"); -#ifdef HAVE_GUPNP - if (agent->upnp_enabled && agent->upnp == NULL && !agent->force_relay) { - agent->upnp = gupnp_simple_igd_thread_new (); - - if (agent->upnp) { - g_signal_connect (agent->upnp, "mapped-external-port", - G_CALLBACK (_upnp_mapped_external_port), agent); - g_signal_connect (agent->upnp, "error-mapping-port", - G_CALLBACK (_upnp_error_mapping_port), agent); - } else { - nice_debug ("Agent %p : Error creating UPnP Simple IGD agent", agent); - } - } else { - nice_debug ("Agent %p : UPnP property Disabled", agent); - } -#else - nice_debug ("Agent %p : libnice compiled without UPnP support", agent); -#endif - /* if no local addresses added, generate them ourselves */ if (agent->local_addresses == NULL) { GList *addresses = nice_interfaces_get_local_ips (FALSE); @@ -3156,11 +3313,6 @@ nice_agent_gather_candidates ( NiceAddress *addr = i->data; NiceCandidateImpl *host_candidate; -#ifdef HAVE_GUPNP - gchar local_ip[NICE_ADDRESS_STRING_LEN]; - nice_address_to_string (addr, local_ip); -#endif - for (add_type = ADD_HOST_MIN; add_type <= ADD_HOST_MAX; add_type++) { NiceCandidateTransport transport; guint current_port; @@ -3252,23 +3404,7 @@ nice_agent_gather_candidates ( nice_socket_set_writable_callback (host_candidate->sockptr, _tcp_sock_is_writable, component); -#ifdef HAVE_GUPNP - if (agent->upnp_enabled && agent->upnp && - transport != NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE) { - NiceAddress *base_addr = nice_address_dup (&host_candidate->c.base_addr); - nice_debug ("Agent %p: Adding UPnP port %s:%d", agent, local_ip, - nice_address_get_port (base_addr)); - gupnp_simple_igd_add_port (GUPNP_SIMPLE_IGD (agent->upnp), - transport == NICE_CANDIDATE_TRANSPORT_UDP ? "UDP" : "TCP", - 0, local_ip, nice_address_get_port (base_addr), - 0, PACKAGE_STRING); - agent->upnp_mapping = g_slist_prepend (agent->upnp_mapping, base_addr); - - agent_timeout_add_with_context (agent, &agent->upnp_timer_source, - "UPnP timeout", agent->upnp_timeout, - priv_upnp_timeout_cb_agent_locked, agent); - } -#endif + priv_add_upnp_discovery (agent, stream, (NiceCandidate *) host_candidate); /* TODO: Add server-reflexive support for TCP candidates */ if (agent->full_mode && agent->stun_server_ip && !agent->force_relay && @@ -3338,7 +3474,7 @@ nice_agent_gather_candidates ( /* note: no async discoveries pending, signal that we are ready */ if (agent->discovery_unsched_items == 0 && #ifdef HAVE_GUPNP - agent->upnp_mapping == NULL) { + stream->upnp_mapping == NULL) { #else TRUE) { #endif @@ -3355,20 +3491,14 @@ nice_agent_gather_candidates ( g_slist_free (local_addresses); if (ret == FALSE) { - priv_stop_upnp (agent); + priv_stop_upnp (agent, stream); for (cid = 1; cid <= stream->n_components; cid++) { NiceComponent *component = nice_stream_find_component_by_id (stream, cid); nice_component_free_socket_sources (component); - for (i = component->local_candidates; i; i = i->next) { - NiceCandidate *candidate = i->data; - - agent_remove_local_candidate (agent, candidate); - - nice_candidate_free (candidate); - } - g_slist_free (component->local_candidates); + g_slist_free_full (component->local_candidates, + (GDestroyNotify) nice_candidate_free); component->local_candidates = NULL; } discovery_prune_stream (agent, stream_id); @@ -3379,44 +3509,6 @@ nice_agent_gather_candidates ( return ret; } -void agent_remove_local_candidate (NiceAgent *agent, NiceCandidate *candidate) -{ -#ifdef HAVE_GUPNP - gchar local_ip[NICE_ADDRESS_STRING_LEN]; - - if (agent->upnp == NULL) - return; - - if (candidate->type != NICE_CANDIDATE_TYPE_HOST) - return; - - if (nice_address_get_port (&candidate->addr) == 0) - return; - - nice_address_to_string (&candidate->addr, local_ip); - - gupnp_simple_igd_remove_port_local (GUPNP_SIMPLE_IGD (agent->upnp), "UDP", - local_ip, nice_address_get_port (&candidate->addr)); -#endif -} - -static void priv_stop_upnp (NiceAgent *agent) -{ -#ifdef HAVE_GUPNP - if (!agent->upnp) - return; - - g_slist_free_full (agent->upnp_mapping, (GDestroyNotify) nice_address_free); - agent->upnp_mapping = NULL; - - if (agent->upnp_timer_source != NULL) { - g_source_destroy (agent->upnp_timer_source); - g_source_unref (agent->upnp_timer_source); - agent->upnp_timer_source = NULL; - } -#endif -} - static void priv_remove_keepalive_timer (NiceAgent *agent) { if (agent->keepalive_timer_source != NULL) { @@ -3469,6 +3561,8 @@ nice_agent_remove_stream ( return; } + priv_stop_upnp (agent, stream); + /* note: remove items with matching stream_ids from both lists */ conn_check_prune_stream (agent, stream); discovery_prune_stream (agent, stream_id); @@ -5458,6 +5552,7 @@ nice_agent_dispose (GObject *object) while (agent->streams) { NiceStream *s = agent->streams->data; + priv_stop_upnp (agent, s); nice_stream_close (agent, s); g_object_unref (s); @@ -5491,8 +5586,6 @@ nice_agent_dispose (GObject *object) nice_rng_free (agent->rng); agent->rng = NULL; - priv_stop_upnp (agent); - #ifdef HAVE_GUPNP if (agent->upnp) { g_object_unref (agent->upnp); diff --git a/agent/component.c b/agent/component.c index b0e9fe0..1854779 100644 --- a/agent/component.c +++ b/agent/component.c @@ -197,8 +197,8 @@ nice_component_remove_socket (NiceAgent *agent, NiceComponent *cmp, conn_check_prune_socket (agent, stream, cmp, candidate->sockptr); nice_component_detach_socket (cmp, candidate->sockptr); } - agent_remove_local_candidate (agent, (NiceCandidate *) candidate); - nice_candidate_free ((NiceCandidate *) candidate); + agent_remove_local_candidate (agent, stream, (NiceCandidate *) candidate); + nice_candidate_free ((NiceCandidate *)candidate); cmp->local_candidates = g_slist_delete_link (cmp->local_candidates, i); i = next; @@ -289,7 +289,7 @@ nice_component_clean_turn_servers (NiceAgent *agent, NiceComponent *cmp) cmp->selected_pair.priority = 0; cmp->turn_candidate = candidate; } else { - agent_remove_local_candidate (agent, (NiceCandidate *) candidate); + agent_remove_local_candidate (agent, stream, (NiceCandidate *) candidate); relay_candidates = g_slist_append(relay_candidates, candidate); } cmp->local_candidates = g_slist_delete_link (cmp->local_candidates, i); @@ -324,7 +324,7 @@ nice_component_clear_selected_pair (NiceComponent *component) /* Must be called with the agent lock held as it touches internal Component * state. */ void -nice_component_close (NiceAgent *agent, NiceComponent *cmp) +nice_component_close (NiceAgent *agent, NiceStream *stream, NiceComponent *cmp) { IOCallbackData *data; GOutputVector *vec; @@ -353,7 +353,7 @@ nice_component_close (NiceAgent *agent, NiceComponent *cmp) cmp->turn_candidate = NULL; while (cmp->local_candidates) { - agent_remove_local_candidate (agent, cmp->local_candidates->data); + agent_remove_local_candidate (agent, stream, cmp->local_candidates->data); nice_candidate_free (cmp->local_candidates->data); cmp->local_candidates = g_slist_delete_link (cmp->local_candidates, cmp->local_candidates); diff --git a/agent/component.h b/agent/component.h index a36cc94..2e6c496 100644 --- a/agent/component.h +++ b/agent/component.h @@ -236,7 +236,8 @@ NiceComponent * nice_component_new (guint component_id, NiceAgent *agent, NiceStream *stream); void -nice_component_close (NiceAgent *agent, NiceComponent *component); +nice_component_close (NiceAgent *agent, NiceStream *stream, + NiceComponent *component); gboolean nice_component_find_pair (NiceComponent *component, NiceAgent *agent, diff --git a/agent/stream.c b/agent/stream.c index b8f42dc..2ec4feb 100644 --- a/agent/stream.c +++ b/agent/stream.c @@ -89,7 +89,7 @@ nice_stream_close (NiceAgent *agent, NiceStream *stream) for (i = stream->components; i; i = i->next) { NiceComponent *component = i->data; - nice_component_close (agent, component); + nice_component_close (agent, stream, component); } } diff --git a/agent/stream.h b/agent/stream.h index de1d456..b41f67a 100644 --- a/agent/stream.h +++ b/agent/stream.h @@ -90,6 +90,12 @@ struct _NiceStream { gboolean peer_gathering_done; gint tos; guint tick_counter; + +#ifdef HAVE_GUPNP + GSList *upnp_mapping; /* NiceCandidate being mapped */ + GSList *upnp_mapped; /* NiceCandidate mapped with UPnP */ + GSource *upnp_timer_source; /* source of upnp timeout timer */ +#endif }; typedef struct { |