[farsight2/master] Simplify (and correct) the multicast transmitter to always send with the max requested TTL

Olivier Crête olivier.crete at collabora.co.uk
Tue Dec 9 16:41:37 PST 2008


---
 .../multicast/fs-multicast-stream-transmitter.c    |   85 +++++------------
 transmitters/multicast/fs-multicast-transmitter.c  |  102 +++++++++++++-------
 transmitters/multicast/fs-multicast-transmitter.h  |    4 +-
 3 files changed, 90 insertions(+), 101 deletions(-)

diff --git a/transmitters/multicast/fs-multicast-stream-transmitter.c b/transmitters/multicast/fs-multicast-stream-transmitter.c
index 12ab839..f41b5b2 100644
--- a/transmitters/multicast/fs-multicast-stream-transmitter.c
+++ b/transmitters/multicast/fs-multicast-stream-transmitter.c
@@ -116,8 +116,7 @@ struct _FsMulticastStreamTransmitterPrivate
   FsCandidate **remote_candidate;
   FsCandidate **local_candidate;
 
-  UdpSock **recvudpsocks;
-  UdpSock **sendudpsocks;
+  UdpSock **udpsocks;
 
   GList *preferred_local_candidates;
 
@@ -224,31 +223,18 @@ fs_multicast_stream_transmitter_dispose (GObject *object)
     /* If dispose did already run, return. */
     return;
 
-  if (self->priv->sendudpsocks)
+  if (self->priv->udpsocks)
   {
     for (c = 1; c <= self->priv->transmitter->components; c++)
     {
-      if (self->priv->sendudpsocks[c])
+      if (self->priv->udpsocks[c])
       {
         if (self->priv->sending)
           fs_multicast_transmitter_udpsock_dec_sending (
-              self->priv->sendudpsocks[c]);
+              self->priv->udpsocks[c]);
         fs_multicast_transmitter_put_udpsock (self->priv->transmitter,
-            self->priv->sendudpsocks[c]);
-        self->priv->sendudpsocks[c] = NULL;
-      }
-    }
-  }
-
-  if (self->priv->recvudpsocks)
-  {
-    for (c = 1; c <= self->priv->transmitter->components; c++)
-    {
-      if (self->priv->recvudpsocks[c])
-      {
-        fs_multicast_transmitter_put_udpsock (self->priv->transmitter,
-            self->priv->recvudpsocks[c]);
-        self->priv->recvudpsocks[c] = NULL;
+            self->priv->udpsocks[c], self->priv->remote_candidate[c]->ttl);
+        self->priv->udpsocks[c] = NULL;
       }
     }
   }
@@ -295,11 +281,8 @@ fs_multicast_stream_transmitter_finalize (GObject *object)
     self->priv->local_candidate = NULL;
   }
 
-  g_free (self->priv->sendudpsocks);
-  self->priv->sendudpsocks = NULL;
-
-  g_free (self->priv->recvudpsocks);
-  self->priv->recvudpsocks = NULL;
+  g_free (self->priv->udpsocks);
+  self->priv->udpsocks = NULL;
 
   parent_class->finalize (object);
 }
@@ -344,14 +327,14 @@ fs_multicast_stream_transmitter_set_property (GObject *object,
 
         if (self->priv->sending != old_sending)
           for (c = 1; c <= self->priv->transmitter->components; c++)
-            if (self->priv->sendudpsocks[c])
+            if (self->priv->udpsocks[c])
             {
               if (self->priv->sending)
                 fs_multicast_transmitter_udpsock_inc_sending (
-                    self->priv->sendudpsocks[c]);
+                    self->priv->udpsocks[c]);
               else
                 fs_multicast_transmitter_udpsock_dec_sending (
-                    self->priv->sendudpsocks[c]);
+                    self->priv->udpsocks[c]);
             }
       }
       break;
@@ -371,9 +354,7 @@ fs_multicast_stream_transmitter_build (FsMulticastStreamTransmitter *self,
   GList *item;
   gint c;
 
-  self->priv->sendudpsocks = g_new0 (UdpSock *,
-      self->priv->transmitter->components + 1);
-  self->priv->recvudpsocks = g_new0 (UdpSock *,
+  self->priv->udpsocks = g_new0 (UdpSock *,
       self->priv->transmitter->components + 1);
   self->priv->local_candidate = g_new0 (FsCandidate *,
       self->priv->transmitter->components + 1);
@@ -451,8 +432,8 @@ fs_multicast_stream_transmitter_add_remote_candidate (
     FsMulticastStreamTransmitter *self, FsCandidate *candidate,
     GError **error)
 {
-  UdpSock *newrecvudpsock = NULL;
-  UdpSock *newsendudpsock = NULL;
+  UdpSock *newudpsock = NULL;
+  guint8 old_ttl = 1;
 
   if (self->priv->remote_candidate[candidate->component_id])
   {
@@ -465,6 +446,7 @@ fs_multicast_stream_transmitter_add_remote_candidate (
       GST_DEBUG ("Re-set the same candidate, ignoring");
       return TRUE;
     }
+    old_ttl = old_candidate->ttl;
     fs_candidate_destroy (old_candidate);
     self->priv->remote_candidate[candidate->component_id] = NULL;
   }
@@ -475,53 +457,32 @@ fs_multicast_stream_transmitter_add_remote_candidate (
    * We should also check if the address is in the multicast range
    */
 
-  newrecvudpsock = fs_multicast_transmitter_get_udpsock (
+  newudpsock = fs_multicast_transmitter_get_udpsock (
       self->priv->transmitter,
       candidate->component_id,
       self->priv->local_candidate[candidate->component_id]->ip,
       candidate->ip,
       candidate->port,
       candidate->ttl,
-      TRUE, error);
+      error);
 
-  if (!newrecvudpsock)
+  if (!newudpsock)
     return FALSE;
 
-  newsendudpsock = fs_multicast_transmitter_get_udpsock (
-      self->priv->transmitter,
-      candidate->component_id,
-      self->priv->local_candidate[candidate->component_id]->ip,
-      candidate->ip,
-      candidate->port,
-      candidate->ttl,
-      FALSE, error);
-
-  if (!newsendudpsock)
-  {
-    fs_multicast_transmitter_put_udpsock (self->priv->transmitter,
-        newrecvudpsock);
-    return FALSE;
-  }
-
-  if (self->priv->sendudpsocks[candidate->component_id])
+  if (self->priv->udpsocks[candidate->component_id])
   {
     if (self->priv->sending)
       fs_multicast_transmitter_udpsock_dec_sending (
-          self->priv->sendudpsocks[candidate->component_id]);
+          self->priv->udpsocks[candidate->component_id]);
     fs_multicast_transmitter_put_udpsock (self->priv->transmitter,
-        self->priv->sendudpsocks[candidate->component_id]);
+        self->priv->udpsocks[candidate->component_id], old_ttl);
   }
 
-  if (self->priv->recvudpsocks[candidate->component_id])
-    fs_multicast_transmitter_put_udpsock (self->priv->transmitter,
-        self->priv->recvudpsocks[candidate->component_id]);
-
-  self->priv->sendudpsocks[candidate->component_id] = newsendudpsock;
-  self->priv->recvudpsocks[candidate->component_id] = newrecvudpsock;
+  self->priv->udpsocks[candidate->component_id] = newudpsock;
 
   if (self->priv->sending)
     fs_multicast_transmitter_udpsock_inc_sending (
-        self->priv->sendudpsocks[candidate->component_id]);
+        self->priv->udpsocks[candidate->component_id]);
 
   self->priv->remote_candidate[candidate->component_id] =
     fs_candidate_copy (candidate);
diff --git a/transmitters/multicast/fs-multicast-transmitter.c b/transmitters/multicast/fs-multicast-transmitter.c
index 0802c35..1e93d68 100644
--- a/transmitters/multicast/fs-multicast-transmitter.c
+++ b/transmitters/multicast/fs-multicast-transmitter.c
@@ -470,13 +470,12 @@ fs_multicast_transmitter_new_stream_transmitter (FsTransmitter *transmitter,
 
 /*
  * The UdpSock structure is a ref-counted pseudo-object use to represent
- * one local_ip:port:ttl:multicast_ip quatuor on which we listen and send,
+ * one local_ip:port:multicast_ip trio on which we listen and send,
  * so it includes a udpsrc and a multiudpsink. It represents one BSD socket.
- * If two UdpSock only differ by their TTL, only the first will have
+ * The TTL used is the max TTL requested by any stream.
  */
 
 struct _UdpSock {
-  gint refcount;
 
   GstElement *udpsrc;
   GstPad *udpsrc_requested_pad;
@@ -487,17 +486,18 @@ struct _UdpSock {
   gchar *local_ip;
   gchar *multicast_ip;
   guint16 port;
-  guint8 ttl;
+  guint8 current_ttl;
 
   gint fd;
 
+  GByteArray *ttls;
+
   /* These are just convenience pointers to our parent transmitter */
   GstElement *funnel;
   GstElement *tee;
 
   guint component_id;
 
-  gboolean sendonly;
   gint sendcount;
 };
 
@@ -747,12 +747,10 @@ fs_multicast_transmitter_get_udpsock (FsMulticastTransmitter *trans,
     const gchar *multicast_ip,
     guint16 port,
     guint8 ttl,
-    gboolean recv,
     GError **error)
 {
   UdpSock *udpsock;
   GList *udpsock_e;
-  gboolean sendonly = FALSE;
 
   /* First lets check if we already have one */
   if (component_id > trans->components)
@@ -773,36 +771,34 @@ fs_multicast_transmitter_get_udpsock (FsMulticastTransmitter *trans,
         ((local_ip == NULL && udpsock->local_ip == NULL) ||
           !strcmp (local_ip, udpsock->local_ip)))
     {
-      if (recv)
-      {
-        if (!udpsock->sendonly)
-        {
-          udpsock->refcount++;
-          return udpsock;
-        }
-      }
-      else /* recv */
+      if (ttl > udpsock->current_ttl)
       {
-        if (ttl == udpsock->ttl)
+
+        if (setsockopt (udpsock->fd, IPPROTO_IP, IP_MULTICAST_TTL,
+                (const void *)&ttl, sizeof (ttl)) < 0)
         {
-          udpsock->refcount++;
-          return udpsock;
+          g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
+              "Error setting the multicast TTL: %s",
+              g_strerror (errno));
+          return NULL;
         }
-        sendonly = TRUE;
+        udpsock->current_ttl = ttl;
       }
+      g_byte_array_append (udpsock->ttls, &ttl, 1);
+      return udpsock;
     }
   }
 
   udpsock = g_slice_new0 (UdpSock);
 
-  udpsock->refcount = 1;
   udpsock->local_ip = g_strdup (local_ip);
   udpsock->multicast_ip = g_strdup (multicast_ip);
   udpsock->fd = -1;
   udpsock->component_id = component_id;
   udpsock->port = port;
-  udpsock->ttl = ttl;
-  udpsock->sendonly = sendonly;
+  udpsock->current_ttl = ttl;
+  udpsock->ttls = g_byte_array_new ();
+  g_byte_array_append (udpsock->ttls, &ttl, 1);
 
   /* Now lets bind both ports */
 
@@ -813,17 +809,13 @@ fs_multicast_transmitter_get_udpsock (FsMulticastTransmitter *trans,
   /* Now lets create the elements */
 
   udpsock->tee = trans->priv->udpsink_tees[component_id];
-  if (!udpsock->sendonly)
-    udpsock->funnel = trans->priv->udpsrc_funnels[component_id];
+  udpsock->funnel = trans->priv->udpsrc_funnels[component_id];
 
-  if (!udpsock->sendonly)
-  {
-    udpsock->udpsrc = _create_sinksource ("udpsrc",
-        GST_BIN (trans->priv->gst_src), udpsock->funnel, udpsock->fd,
-        GST_PAD_SRC, &udpsock->udpsrc_requested_pad, error);
-    if (!udpsock->udpsrc)
-      goto error;
-  }
+  udpsock->udpsrc = _create_sinksource ("udpsrc",
+      GST_BIN (trans->priv->gst_src), udpsock->funnel, udpsock->fd,
+      GST_PAD_SRC, &udpsock->udpsrc_requested_pad, error);
+  if (!udpsock->udpsrc)
+    goto error;
 
   udpsock->udpsink = _create_sinksource ("multiudpsink",
     GST_BIN (trans->priv->gst_sink), udpsock->tee, udpsock->fd, GST_PAD_SINK,
@@ -844,17 +836,53 @@ fs_multicast_transmitter_get_udpsock (FsMulticastTransmitter *trans,
  error:
 
   if (udpsock)
-    fs_multicast_transmitter_put_udpsock (trans, udpsock);
+    fs_multicast_transmitter_put_udpsock (trans, udpsock, ttl);
 
   return NULL;
 }
 
 void
 fs_multicast_transmitter_put_udpsock (FsMulticastTransmitter *trans,
-  UdpSock *udpsock)
+    UdpSock *udpsock, guint8 ttl)
 {
-  if (udpsock->refcount > 1) {
-    udpsock->refcount--;
+  guint i;
+
+  for (i = udpsock->ttls->len - 1;; i--)
+  {
+    if (udpsock->ttls->data[i] == ttl)
+    {
+      g_byte_array_remove_index_fast (udpsock->ttls, i);
+      break;
+    }
+
+    g_return_if_fail (i > 0);
+  }
+
+  if (udpsock->ttls->len > 0)
+  {
+    /* If we were the max, check if there is a new max */
+    if (udpsock->current_ttl == ttl && ttl > 1)
+    {
+      guint8 max = 1;
+      for (i = 0; i < udpsock->ttls->len; i++)
+      {
+        if (udpsock->ttls->data[i] > max)
+          max = udpsock->ttls->data[i];
+      }
+
+      if (max != udpsock->current_ttl)
+      {
+
+        if (setsockopt (udpsock->fd, IPPROTO_IP, IP_MULTICAST_TTL,
+                (const void *)&max, sizeof (max)) < 0)
+        {
+          GST_WARNING ("Error setting the multicast TTL to %u: %s", max,
+              g_strerror (errno));
+          return;
+        }
+        udpsock->current_ttl = max;
+      }
+    }
     return;
   }
 
diff --git a/transmitters/multicast/fs-multicast-transmitter.h b/transmitters/multicast/fs-multicast-transmitter.h
index 9dc52aa..9b4b9b1 100644
--- a/transmitters/multicast/fs-multicast-transmitter.h
+++ b/transmitters/multicast/fs-multicast-transmitter.h
@@ -92,11 +92,11 @@ UdpSock *fs_multicast_transmitter_get_udpsock (FsMulticastTransmitter *trans,
     const gchar *multicast_ip,
     guint16 port,
     guint8 ttl,
-    gboolean recv,
     GError **error);
 
 void fs_multicast_transmitter_put_udpsock (FsMulticastTransmitter *trans,
-    UdpSock *udpsock);
+    UdpSock *udpsock, guint8 ttl);
+
 
 void fs_multicast_transmitter_udpsock_inc_sending (UdpSock *udpsock);
 void fs_multicast_transmitter_udpsock_dec_sending (UdpSock *udpsock);
-- 
1.5.6.5




More information about the farsight-commits mailing list