agent: add nice_agent_close_async() API
authorJakub Adam <jakub.adam@collabora.com>
Mon, 25 Feb 2019 10:30:10 +0000 (11:30 +0100)
committerOlivier CrĂȘte <olivier.crete@ocrete.ca>
Thu, 9 May 2019 01:14:37 +0000 (01:14 +0000)
Asynchronously closes resources the agent has allocated on remote
servers.

agent/agent.c
agent/agent.h
docs/reference/libnice/libnice-sections.txt
nice/libnice.sym
tests/test-fullmode.c
tests/test-turn.c

index 30684bb..dc47ba0 100644 (file)
@@ -6685,3 +6685,22 @@ nice_agent_peer_candidate_gathering_done (NiceAgent *agent, guint stream_id)
   return result;
 }
 
+static gboolean
+on_agent_refreshes_pruned (NiceAgent *agent, gpointer user_data)
+{
+  // This is called from a timeout cb with agent lock held
+
+  agent_queue_signal (agent, signals[SIGNAL_CLOSED]);
+
+  return G_SOURCE_REMOVE;
+}
+
+void
+nice_agent_close_async (NiceAgent *agent)
+{
+  agent_lock (agent);
+
+  refresh_prune_agent_async (agent, on_agent_refreshes_pruned);
+
+  agent_unlock (agent);
+}
index 688d784..c85ee5e 100644 (file)
@@ -1659,6 +1659,21 @@ nice_agent_peer_candidate_gathering_done (
     NiceAgent *agent,
     guint stream_id);
 
+/**
+ * nice_agent_close_async:
+ * @agent: The #NiceAgent object
+ *
+ * Asynchronously closes resources the agent has allocated on remote servers.
+ * The agent will emit "closed" signal when the operation finishes.
+ *
+ * Calling this function before freeing the agent makes sure the allocated relay
+ * ports aren't left behind on TURN server but properly removed.
+ *
+ * Since: 0.1.16
+ */
+void
+nice_agent_close_async (NiceAgent *agent);
+
 G_END_DECLS
 
 #endif /* __LIBNICE_AGENT_H__ */
index fa0dd10..bff9c96 100644 (file)
@@ -55,6 +55,7 @@ nice_agent_parse_remote_candidate_sdp
 nice_agent_get_io_stream
 nice_agent_get_selected_socket
 nice_agent_get_component_state
+nice_agent_close_async
 nice_component_state_to_string
 <SUBSECTION Standard>
 NICE_AGENT
index f005603..1e6d127 100644 (file)
@@ -17,6 +17,7 @@ nice_address_set_port
 nice_address_to_string
 nice_agent_add_local_address
 nice_agent_add_stream
+nice_agent_close_async
 nice_agent_recv
 nice_agent_recv_messages
 nice_agent_recv_nonblocking
index 71d14fe..d5aedb5 100644 (file)
@@ -130,6 +130,8 @@ static gboolean global_lagent_gathering_done = FALSE;
 static gboolean global_ragent_gathering_done = FALSE;
 static gboolean global_lagent_ibr_received = FALSE;
 static gboolean global_ragent_ibr_received = FALSE;
+static gboolean global_lagent_closed = FALSE;
+static gboolean global_ragent_closed = FALSE;
 static int global_lagent_cands = 0;
 static int global_ragent_cands = 0;
 static gint global_ragent_read = 0;
@@ -296,6 +298,13 @@ static void cb_initial_binding_request_received(NiceAgent *agent, guint stream_i
   (void)agent; (void)stream_id; (void)data;
 }
 
+static void cb_closed (NiceAgent *agent, gpointer data)
+{
+  g_debug ("test-fullmode:%s: %p", G_STRFUNC, agent);
+
+  *((gboolean *)data) = TRUE;
+}
+
 static void set_candidates (NiceAgent *from, guint from_stream,
     NiceAgent *to, guint to_stream, guint component, gboolean remove_non_relay)
 {
@@ -924,6 +933,10 @@ int main (void)
   g_signal_connect (G_OBJECT (ragent), "initial-binding-request-received",
       G_CALLBACK (cb_initial_binding_request_received),
       GUINT_TO_POINTER (2));
+  g_signal_connect (G_OBJECT (lagent), "closed",
+      G_CALLBACK (cb_closed), &global_lagent_closed);
+  g_signal_connect (G_OBJECT (ragent), "closed",
+      G_CALLBACK (cb_closed), &global_ragent_closed);
 
   stun_server = getenv ("NICE_STUN_SERVER");
   stun_server_port = getenv ("NICE_STUN_SERVER_PORT");
@@ -1099,6 +1112,13 @@ int main (void)
   g_assert (global_ragent_state[0] == NICE_COMPONENT_STATE_READY);
   g_assert (global_ragent_state[1] == NICE_COMPONENT_STATE_READY);
 
+  nice_agent_close_async (lagent);
+  nice_agent_close_async (ragent);
+
+  while (!global_lagent_closed || !global_ragent_closed) {
+    g_main_context_iteration (NULL, TRUE);
+  }
+
   g_object_unref (lagent);
   g_object_unref (ragent);
 
index c466261..9a1e63f 100644 (file)
@@ -10,6 +10,8 @@ static NiceComponentState global_ragent_state[2] = { NICE_COMPONENT_STATE_LAST,
 static guint global_components_ready = 0;
 static gboolean global_lagent_gathering_done = FALSE;
 static gboolean global_ragent_gathering_done = FALSE;
+static gboolean global_lagent_closed = FALSE;
+static gboolean global_ragent_closed = FALSE;
 static int global_lagent_cands = 0;
 static int global_ragent_cands = 0;
 
@@ -101,6 +103,13 @@ static void cb_new_selected_pair(NiceAgent *agent, guint stream_id,
     ++global_ragent_cands;
 }
 
+static void cb_closed (NiceAgent *agent, gpointer data)
+{
+  g_debug ("test-turn:%s: %p", G_STRFUNC, agent);
+
+  *((gboolean *)data) = TRUE;
+}
+
 static void set_candidates (NiceAgent *from, guint from_stream,
     NiceAgent *to, guint to_stream, guint component, gboolean remove_non_relay,
     gboolean force_relay)
@@ -164,6 +173,8 @@ run_test(guint turn_port, gboolean is_ipv6,
   global_components_ready = 0;
   global_lagent_gathering_done = FALSE;
   global_ragent_gathering_done = FALSE;
+  global_lagent_closed = FALSE;
+  global_ragent_closed = FALSE;
   global_lagent_cands = global_ragent_cands = 0;
 
   lagent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245);
@@ -199,6 +210,10 @@ run_test(guint turn_port, gboolean is_ipv6,
       G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER(1));
   g_signal_connect (G_OBJECT (ragent), "new-selected-pair",
       G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER (2));
+  g_signal_connect (G_OBJECT (lagent), "closed",
+      G_CALLBACK (cb_closed), &global_lagent_closed);
+  g_signal_connect (G_OBJECT (ragent), "closed",
+      G_CALLBACK (cb_closed), &global_ragent_closed);
 
   g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
   g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
@@ -247,6 +262,13 @@ run_test(guint turn_port, gboolean is_ipv6,
   nice_agent_remove_stream (lagent, ls_id);
   nice_agent_remove_stream (ragent, rs_id);
 
+  nice_agent_close_async (lagent);
+  nice_agent_close_async (ragent);
+
+  while (!global_lagent_closed || !global_ragent_closed) {
+    g_main_context_iteration (NULL, TRUE);
+  }
+
   g_source_remove (timer_id);
 
   g_clear_object(&lagent);