[Pkg-telepathy-commits] [libnice] 238/265: component: Make is possible to remove a socket

Simon McVittie smcv at debian.org
Wed May 14 12:05:12 UTC 2014


This is an automated email from the git hooks/post-receive script.

smcv pushed a commit to branch debian
in repository libnice.

commit 6628ed59a25fa07b5573b2848a77856882f6e050
Author: Olivier Crête <olivier.crete at collabora.com>
Date:   Tue Apr 15 22:21:07 2014 -0400

    component: Make is possible to remove a socket
    
    Change the SocketSource handling to make it possible
    to remove a source, not only to add one.
---
 agent/component.c | 122 +++++++++++++++++++++++++++++++++---------------------
 1 file changed, 75 insertions(+), 47 deletions(-)

diff --git a/agent/component.c b/agent/component.c
index fa323e2..4e9384e 100644
--- a/agent/component.c
+++ b/agent/component.c
@@ -451,16 +451,9 @@ component_attach_socket (Component *component, NiceSocket *nicesock)
   /* Find an existing SocketSource in the component which contains @socket, or
    * create a new one.
    *
-   * In order for socket_sources_age to work properly, socket_sources must only
-   * grow monotonically, or be entirely cleared. i.e. New SocketSources must be
-   * prepended to socket_sources, and all other existing SocketSource must be
-   * left untouched; *or* the whole of socket_sources must be cleared. If
-   * socket_sources is cleared, age is reset to 0 and *must not* be incremented
-   * again or the new sockets will not be picked up by ComponentSocket. This is
-   * guaranteed by the fact that socket_sources is only cleared on disconnection
-   * or discovery failure, which are both unrecoverable states.
-   *
-   * An empty socket_sources corresponds to age 0. */
+   * Whenever a source is added or remove to socket_sources, socket_sources_age
+   * must be incremented.
+   */
   l = g_slist_find_custom (component->socket_sources, nicesock,
           _find_socket_source);
   if (l != NULL) {
@@ -554,7 +547,7 @@ component_free_socket_sources (Component *component)
   g_slist_free_full (component->socket_sources,
       (GDestroyNotify) socket_source_free);
   component->socket_sources = NULL;
-  component->socket_sources_age = 0;
+  component->socket_sources_age++;
 }
 
 GMainContext *
@@ -830,7 +823,6 @@ component_deschedule_io_callback (Component *component)
   component->io_callback_id = 0;
 }
 
-
 /**
  * ComponentSource:
  *
@@ -861,15 +853,20 @@ typedef struct {
   guint stream_id;
   guint component_id;
   guint component_socket_sources_age;
+
+  /* SocketSource, free with free_child_socket_source() */
+  GSList *socket_sources;
+
+  GIOCondition condition;
 } ComponentSource;
 
 static gboolean
 component_source_prepare (GSource *source, gint *timeout_)
 {
   ComponentSource *component_source = (ComponentSource *) source;
-  gint age_diff;
   NiceAgent *agent;
   Component *component;
+  GSList *parentl, *childl;
 
   agent = g_weak_ref_get (&component_source->agent_ref);
   if (!agent)
@@ -884,44 +881,67 @@ component_source_prepare (GSource *source, gint *timeout_)
     goto done;
 
 
-  age_diff =
-      component->socket_sources_age -
-      component_source->component_socket_sources_age;
+  if (component->socket_sources_age ==
+      component_source->component_socket_sources_age)
+    goto done;
 
-  /* If the age has changed, either:
-   *  • a new socket has been *prepended* to component->socket_sources (and
-   *    age_diff > 0); or
-   *  • component->socket_sources has been emptied (and age_diff < 0).
-   * We can’t remove any child sources without destroying them, so must
-   * monotonically add new ones, or remove everything.
-   *
-   * Removing everything only happens on shutdown or failure, in which case
-   * the ComponentSource itself can be destroyed, automatically destroying all
-   * the child sources. */
-  if (age_diff < 0) {
-    g_source_destroy (source);
-  } else if (age_diff > 0) {
-    /* Add the new child sources. The difference between the two ages gives
-     * the number of new child sources. */
-    guint i;
-    GSList *l;
-
-    for (i = 0, l = component->socket_sources;
-         i < (guint) age_diff && l != NULL;
-         i++, l = l->next) {
-      GSource *child_source;
-      SocketSource *socket_source;
-
-      socket_source = l->data;
-
-      child_source = g_socket_create_source (socket_source->socket->fileno,
-          G_IO_IN, NULL);
-      g_source_set_dummy_callback (child_source);
-      g_source_add_child_source (source, child_source);
-      g_source_unref (child_source);
+  /* If the age has changed, either
+   *  - one or more new socket has been prepended
+   *  - old sockets have been removed
+   */
+
+  /* Add the new child sources. */
+
+  for (parentl = component->socket_sources; parentl; parentl = parentl->next) {
+    SocketSource *parent_socket_source = parentl->data;
+    SocketSource *child_socket_source;
+
+    /* Iterating the list of socket sources every time isn't a big problem
+     * because the number of pairs is limited ~100 normally, so there will
+     * rarely be more than 10.
+     */
+    childl = g_slist_find_custom (component_source->socket_sources,
+        parent_socket_source->socket, _find_socket_source);
+
+    /* If we have reached this state, then all sources new sources have been
+     * added, because they are always prepended.
+     */
+    if (childl)
+      break;
+
+    child_socket_source = g_slice_new0 (SocketSource);
+    child_socket_source->socket = parent_socket_source->socket;
+    child_socket_source->source =
+        g_socket_create_source (child_socket_source->socket->fileno, G_IO_IN,
+            NULL);
+    g_source_set_dummy_callback (child_socket_source->source);
+    g_source_add_child_source (source, child_socket_source->source);
+    g_source_unref (child_socket_source->source);
+    component_source->socket_sources =
+        g_slist_prepend (component_source->socket_sources, child_socket_source);
+  }
+
+
+  for (childl = component_source->socket_sources;
+       childl;) {
+    SocketSource *child_socket_source = childl->data;
+    GSList *next = childl->next;
+
+    parentl = g_slist_find_custom (component->socket_sources,
+      child_socket_source->socket, _find_socket_source);
+
+    /* If this is not a currently used socket, remove the relevant source */
+    if (!parentl) {
+      g_source_remove_child_source (source, child_socket_source->source);
+      g_slice_free (SocketSource, child_socket_source);
+      component_source->socket_sources =
+          g_slist_delete_link (component_source->socket_sources, childl);
     }
+
+    childl = next;
   }
 
+
   /* Update the age. */
   component_source->component_socket_sources_age = component->socket_sources_age;
 
@@ -945,10 +965,18 @@ component_source_dispatch (GSource *source, GSourceFunc callback,
 }
 
 static void
+free_child_socket_source (gpointer data)
+{
+  g_slice_free (SocketSource, data);
+}
+
+static void
 component_source_finalize (GSource *source)
 {
   ComponentSource *component_source = (ComponentSource *) source;
 
+  g_slist_free_full (component_source->socket_sources, free_child_socket_source);
+
   g_weak_ref_clear (&component_source->agent_ref);
   g_object_unref (component_source->pollable_stream);
   component_source->pollable_stream = NULL;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-telepathy/libnice.git



More information about the Pkg-telepathy-commits mailing list