[farsight2/master] The Multicast transmitter now binds to the multicast address, not the local address. So we really have to have one socket per multicast group we join.

Olivier Crête olivier.crete at collabora.co.uk
Tue Dec 23 15:21:10 PST 2008


---
 .../multicast/fs-multicast-stream-transmitter.c    |  105 +++---
 transmitters/multicast/fs-multicast-transmitter.c  |  439 +++++++-------------
 transmitters/multicast/fs-multicast-transmitter.h  |   18 +-
 3 files changed, 223 insertions(+), 339 deletions(-)

diff --git a/transmitters/multicast/fs-multicast-stream-transmitter.c b/transmitters/multicast/fs-multicast-stream-transmitter.c
index 04656ba..a9ee72f 100644
--- a/transmitters/multicast/fs-multicast-stream-transmitter.c
+++ b/transmitters/multicast/fs-multicast-stream-transmitter.c
@@ -117,8 +117,8 @@ struct _FsMulticastStreamTransmitterPrivate
   FsCandidate **remote_candidate;
   FsCandidate **local_candidate;
 
-  UdpMulticastGroup **recvmcasts;
-  UdpMulticastGroup **sendmcasts;
+  UdpSock **recvudpsocks;
+  UdpSock **sendudpsocks;
 
   GList *preferred_local_candidates;
 
@@ -225,31 +225,31 @@ fs_multicast_stream_transmitter_dispose (GObject *object)
     /* If dispose did already run, return. */
     return;
 
-  if (self->priv->sendmcasts)
+  if (self->priv->sendudpsocks)
   {
     for (c = 1; c <= self->priv->transmitter->components; c++)
     {
-      if (self->priv->sendmcasts[c])
+      if (self->priv->sendudpsocks[c])
       {
         if (self->priv->sending)
-          fs_multicast_transmitter_group_dec_sending (
-              self->priv->sendmcasts[c]);
-        fs_multicast_transmitter_put_group (self->priv->transmitter,
-            self->priv->sendmcasts[c]);
-        self->priv->sendmcasts[c] = NULL;
+          fs_multicast_transmitter_udpsock_dec_sending (
+              self->priv->sendudpsocks[c]);
+        fs_multicast_transmitter_put_udpsock (self->priv->transmitter,
+            self->priv->sendudpsocks[c]);
+        self->priv->sendudpsocks[c] = NULL;
       }
     }
   }
 
-  if (self->priv->recvmcasts)
+  if (self->priv->recvudpsocks)
   {
     for (c = 1; c <= self->priv->transmitter->components; c++)
     {
-      if (self->priv->recvmcasts[c])
+      if (self->priv->recvudpsocks[c])
       {
-        fs_multicast_transmitter_put_group (self->priv->transmitter,
-            self->priv->recvmcasts[c]);
-        self->priv->recvmcasts[c] = NULL;
+        fs_multicast_transmitter_put_udpsock (self->priv->transmitter,
+            self->priv->recvudpsocks[c]);
+        self->priv->recvudpsocks[c] = NULL;
       }
     }
   }
@@ -296,11 +296,11 @@ fs_multicast_stream_transmitter_finalize (GObject *object)
     self->priv->local_candidate = NULL;
   }
 
-  g_free (self->priv->sendmcasts);
-  self->priv->sendmcasts = NULL;
+  g_free (self->priv->sendudpsocks);
+  self->priv->sendudpsocks = NULL;
 
-  g_free (self->priv->recvmcasts);
-  self->priv->recvmcasts = NULL;
+  g_free (self->priv->recvudpsocks);
+  self->priv->recvudpsocks = NULL;
 
   parent_class->finalize (object);
 }
@@ -345,14 +345,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->sendmcasts[c])
+            if (self->priv->sendudpsocks[c])
             {
               if (self->priv->sending)
-                fs_multicast_transmitter_group_inc_sending (
-                    self->priv->sendmcasts[c]);
+                fs_multicast_transmitter_udpsock_inc_sending (
+                    self->priv->sendudpsocks[c]);
               else
-                fs_multicast_transmitter_group_dec_sending (
-                    self->priv->sendmcasts[c]);
+                fs_multicast_transmitter_udpsock_dec_sending (
+                    self->priv->sendudpsocks[c]);
             }
       }
       break;
@@ -372,9 +372,9 @@ fs_multicast_stream_transmitter_build (FsMulticastStreamTransmitter *self,
   GList *item;
   gint c;
 
-  self->priv->sendmcasts = g_new0 (UdpMulticastGroup *,
+  self->priv->sendudpsocks = g_new0 (UdpSock *,
       self->priv->transmitter->components + 1);
-  self->priv->recvmcasts = g_new0 (UdpMulticastGroup *,
+  self->priv->recvudpsocks = g_new0 (UdpSock *,
       self->priv->transmitter->components + 1);
   self->priv->local_candidate = g_new0 (FsCandidate *,
       self->priv->transmitter->components + 1);
@@ -465,8 +465,8 @@ fs_multicast_stream_transmitter_add_remote_candidate (
 {
   FsMulticastStreamTransmitter *self =
     FS_MULTICAST_STREAM_TRANSMITTER (streamtransmitter);
-  UdpMulticastGroup *newrecvmcast = NULL;
-  UdpMulticastGroup *newsendmcast = NULL;
+  UdpSock *newrecvudpsock = NULL;
+  UdpSock *newsendudpsock = NULL;
 
   if (candidate->proto != FS_NETWORK_PROTOCOL_UDP) {
     g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
@@ -525,44 +525,53 @@ fs_multicast_stream_transmitter_add_remote_candidate (
    * We should also check if the address is in the multicast range
    */
 
-  newrecvmcast = fs_multicast_transmitter_get_group (self->priv->transmitter,
-      candidate->component_id, candidate->ip, candidate->port,
+  newrecvudpsock = fs_multicast_transmitter_get_udpsock (
+      self->priv->transmitter,
+      candidate->component_id,
       self->priv->local_candidate[candidate->component_id]->ip,
-      candidate->ttl, TRUE, error);
+      candidate->ip,
+      candidate->port,
+      candidate->ttl,
+      TRUE, error);
 
-  if (!newrecvmcast)
+  if (!newrecvudpsock)
     return FALSE;
 
-  newsendmcast = fs_multicast_transmitter_get_group (self->priv->transmitter,
-      candidate->component_id, candidate->ip, candidate->port,
+  newsendudpsock = fs_multicast_transmitter_get_udpsock (
+      self->priv->transmitter,
+      candidate->component_id,
       self->priv->local_candidate[candidate->component_id]->ip,
-      candidate->ttl, FALSE, error);
+      candidate->ip,
+      candidate->port,
+      candidate->ttl,
+      FALSE, error);
 
-  if (!newsendmcast)
+  if (!newsendudpsock)
   {
-    fs_multicast_transmitter_put_group (self->priv->transmitter, newrecvmcast);
+    fs_multicast_transmitter_put_udpsock (self->priv->transmitter,
+        newrecvudpsock);
     return FALSE;
   }
 
-  if (self->priv->sendmcasts[candidate->component_id])
+  if (self->priv->sendudpsocks[candidate->component_id])
   {
     if (self->priv->sending)
-      fs_multicast_transmitter_group_dec_sending (
-          self->priv->sendmcasts[candidate->component_id]);
-    fs_multicast_transmitter_put_group (self->priv->transmitter,
-        self->priv->sendmcasts[candidate->component_id]);
+      fs_multicast_transmitter_udpsock_dec_sending (
+          self->priv->sendudpsocks[candidate->component_id]);
+    fs_multicast_transmitter_put_udpsock (self->priv->transmitter,
+        self->priv->sendudpsocks[candidate->component_id]);
   }
 
-  if (self->priv->recvmcasts[candidate->component_id])
-    fs_multicast_transmitter_put_group (self->priv->transmitter,
-        self->priv->recvmcasts[candidate->component_id]);
+  if (self->priv->recvudpsocks[candidate->component_id])
+    fs_multicast_transmitter_put_udpsock (self->priv->transmitter,
+        self->priv->recvudpsocks[candidate->component_id]);
 
-  self->priv->sendmcasts[candidate->component_id] = newsendmcast;
-  self->priv->recvmcasts[candidate->component_id] = newrecvmcast;
+  self->priv->sendudpsocks[candidate->component_id] = newsendudpsock;
+  self->priv->recvudpsocks[candidate->component_id] = newrecvudpsock;
 
   if (self->priv->sending)
-    fs_multicast_transmitter_group_inc_sending (
-        self->priv->sendmcasts[candidate->component_id]);
+    fs_multicast_transmitter_udpsock_inc_sending (
+        self->priv->sendudpsocks[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 32d235c..ed6593c 100644
--- a/transmitters/multicast/fs-multicast-transmitter.c
+++ b/transmitters/multicast/fs-multicast-transmitter.c
@@ -78,7 +78,7 @@ struct _FsMulticastTransmitterPrivate
   GstElement **udpsrc_funnels;
   GstElement **udpsink_tees;
 
-  GList **udpports;
+  GList **udpsocks;
 
   gboolean disposed;
 };
@@ -110,21 +110,6 @@ static GType fs_multicast_transmitter_get_stream_transmitter_type (
     FsTransmitter *transmitter,
     GError **error);
 
-
-typedef struct _UdpPort UdpPort;
-
-static UdpPort *fs_multicast_transmitter_get_udpport (
-    FsMulticastTransmitter *trans,
-    guint component_id,
-    const gchar *local_ip,
-    guint16 port,
-    guint8 ttl,
-    gboolean recv,
-    GError **error);
-static void fs_multicast_transmitter_put_udpport (FsMulticastTransmitter *trans,
-    UdpPort *udpport);
-
-
 static GObjectClass *parent_class = NULL;
 //static guint signals[LAST_SIGNAL] = { 0 };
 
@@ -238,7 +223,7 @@ fs_multicast_transmitter_constructed (GObject *object)
   /* We waste one space in order to have the index be the component_id */
   self->priv->udpsrc_funnels = g_new0 (GstElement *, self->components+1);
   self->priv->udpsink_tees = g_new0 (GstElement *, self->components+1);
-  self->priv->udpports = g_new0 (GList *, self->components+1);
+  self->priv->udpsocks = g_new0 (GList *, self->components+1);
 
   /* First we need the src elemnet */
 
@@ -406,9 +391,9 @@ fs_multicast_transmitter_finalize (GObject *object)
     self->priv->udpsink_tees = NULL;
   }
 
-  if (self->priv->udpports) {
-    g_free (self->priv->udpports);
-    self->priv->udpports = NULL;
+  if (self->priv->udpsocks) {
+    g_free (self->priv->udpsocks);
+    self->priv->udpsocks = NULL;
   }
 
   parent_class->finalize (object);
@@ -479,12 +464,13 @@ fs_multicast_transmitter_new_stream_transmitter (FsTransmitter *transmitter,
 
 
 /*
- * The UdpPort structure is a ref-counted pseudo-object use to represent
- * one ip:port:ttl trio on which we listen and send, so it includes a udpsrc
- * and a multiudpsink. It represents one BSD socket.
+ * 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,
+ * 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 
  */
 
-struct _UdpPort {
+struct _UdpSock {
   gint refcount;
 
   GstElement *udpsrc;
@@ -494,6 +480,7 @@ struct _UdpPort {
   GstPad *udpsink_requested_pad;
 
   gchar *local_ip;
+  gchar *multicast_ip;
   guint16 port;
   guint8 ttl;
 
@@ -506,13 +493,37 @@ struct _UdpPort {
   guint component_id;
 
   gboolean sendonly;
-
-  GList *multicast_groups;
+  gint sendcount;
 };
 
+static gboolean
+_ip_string_into_sockaddr_in (const gchar *ip_as_string,
+    struct sockaddr_in *sockaddr_in, GError **error)
+{
+  struct addrinfo hints;
+  struct addrinfo *result = NULL;
+  int retval;
+
+  memset (&hints, 0, sizeof (struct addrinfo));
+  hints.ai_family = AF_INET;
+  hints.ai_flags = AI_NUMERICHOST;
+  retval = getaddrinfo (ip_as_string, NULL, &hints, &result);
+  if (retval != 0) {
+    g_set_error (error, FS_ERROR, FS_ERROR_NETWORK,
+        "Invalid IP address %s passed: %s", ip_as_string,
+        gai_strerror (retval));
+    return FALSE;
+  }
+  memcpy (sockaddr_in, result->ai_addr, sizeof(struct sockaddr_in));
+  freeaddrinfo (result);
+
+  return TRUE;
+}
+
 static gint
 _bind_port (
-    const gchar *ip,
+    const gchar *local_ip,
+    const gchar *multicast_ip,
     guint16 port,
     guchar ttl,
     GError **error)
@@ -522,26 +533,29 @@ _bind_port (
   int retval;
   guchar loop = 1;
   int reuseaddr = 1;
+  struct ip_mreqn mreqn;
 
   address.sin_family = AF_INET;
   address.sin_addr.s_addr = INADDR_ANY;
 
-  if (ip) {
-    struct addrinfo hints;
-    struct addrinfo *result = NULL;
-
-    memset (&hints, 0, sizeof (struct addrinfo));
-    hints.ai_family = AF_INET;
-    hints.ai_flags = AI_NUMERICHOST;
-    retval = getaddrinfo (ip, NULL, &hints, &result);
-    if (retval != 0) {
-      g_set_error (error, FS_ERROR, FS_ERROR_NETWORK,
-        "Invalid IP address %s passed: %s", ip, gai_strerror (retval));
-      return -1;
-    }
-    memcpy (&address, result->ai_addr, sizeof(struct sockaddr_in));
-    freeaddrinfo (result);
+  g_assert (multicast_ip);
+
+  if (!_ip_string_into_sockaddr_in (multicast_ip, &address, error))
+    goto error;
+  memcpy (&mreqn.imr_multiaddr, &address.sin_addr, sizeof(mreqn.imr_multiaddr));
+
+  if (local_ip)
+  {
+    struct sockaddr_in tmpaddr;
+    if (!_ip_string_into_sockaddr_in (local_ip, &tmpaddr, error))
+      goto error;
+    memcpy (&mreqn.imr_address, &tmpaddr.sin_addr, sizeof(mreqn.imr_address));
   }
+  else
+  {
+    mreqn.imr_address.s_addr = INADDR_ANY;
+  }
+  mreqn.imr_ifindex = 0;
 
   if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) <= 0) {
     g_set_error (error, FS_ERROR, FS_ERROR_NETWORK,
@@ -587,6 +601,15 @@ _bind_port (
   }
 #endif
 
+  if (setsockopt (sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+          &(mreqn), sizeof (mreqn)) < 0)
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
+        "Could not join the socket to the multicast group: %s",
+        g_strerror (errno));
+    goto error;
+  }
+
   address.sin_port = htons (port);
   retval = bind (sock, (struct sockaddr *) &address, sizeof (address));
   if (retval != 0)
@@ -697,18 +720,18 @@ _create_sinksource (gchar *elementname, GstBin *bin,
   return NULL;
 }
 
-
-static UdpPort *
-fs_multicast_transmitter_get_udpport (FsMulticastTransmitter *trans,
+UdpSock *
+fs_multicast_transmitter_get_udpsock (FsMulticastTransmitter *trans,
     guint component_id,
     const gchar *local_ip,
+    const gchar *multicast_ip,
     guint16 port,
     guint8 ttl,
     gboolean recv,
     GError **error)
 {
-  UdpPort *udpport;
-  GList *udpport_e;
+  UdpSock *udpsock;
+  GList *udpsock_e;
   gboolean sendonly = FALSE;
 
   /* First lets check if we already have one */
@@ -719,163 +742,166 @@ fs_multicast_transmitter_get_udpport (FsMulticastTransmitter *trans,
     return NULL;
   }
 
-  for (udpport_e = g_list_first (trans->priv->udpports[component_id]);
-       udpport_e;
-       udpport_e = g_list_next (udpport_e))
+  for (udpsock_e = g_list_first (trans->priv->udpsocks[component_id]);
+       udpsock_e;
+       udpsock_e = g_list_next (udpsock_e))
   {
-    udpport = udpport_e->data;
+    udpsock = udpsock_e->data;
 
-    if (port == udpport->port &&
-        ((local_ip == NULL && udpport->local_ip == NULL) ||
-          !strcmp (local_ip, udpport->local_ip)))
+    if (port == udpsock->port &&
+        !strcmp (multicast_ip, udpsock->multicast_ip) &&
+        ((local_ip == NULL && udpsock->local_ip == NULL) ||
+          !strcmp (local_ip, udpsock->local_ip)))
     {
       if (recv)
       {
-        if (!udpport->sendonly)
+        if (!udpsock->sendonly)
         {
-          udpport->refcount++;
-          return udpport;
+          udpsock->refcount++;
+          return udpsock;
         }
       }
       else /* recv */
       {
-        if (ttl == udpport->ttl)
+        if (ttl == udpsock->ttl)
         {
-          udpport->refcount++;
-          return udpport;
+          udpsock->refcount++;
+          return udpsock;
         }
         sendonly = TRUE;
       }
     }
   }
 
-  udpport = g_new0 (UdpPort, 1);
+  udpsock = g_new0 (UdpSock, 1);
 
-  udpport->refcount = 1;
-  udpport->local_ip = g_strdup (local_ip);
-  udpport->fd = -1;
-  udpport->component_id = component_id;
-  udpport->port = port;
-  udpport->ttl = ttl;
-  udpport->sendonly = sendonly;
+  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;
 
   /* Now lets bind both ports */
 
-  udpport->fd = _bind_port (local_ip, port, ttl, error);
-  if (udpport->fd < 0)
+  udpsock->fd = _bind_port (local_ip, multicast_ip, port, ttl, error);
+  if (udpsock->fd < 0)
     goto error;
 
   /* Now lets create the elements */
 
-  udpport->tee = trans->priv->udpsink_tees[component_id];
-  if (!udpport->sendonly)
-    udpport->funnel = trans->priv->udpsrc_funnels[component_id];
+  udpsock->tee = trans->priv->udpsink_tees[component_id];
+  if (!udpsock->sendonly)
+    udpsock->funnel = trans->priv->udpsrc_funnels[component_id];
 
-  if (!udpport->sendonly)
+  if (!udpsock->sendonly)
   {
-    udpport->udpsrc = _create_sinksource ("udpsrc",
-        GST_BIN (trans->priv->gst_src), udpport->funnel, udpport->fd, GST_PAD_SRC,
-        &udpport->udpsrc_requested_pad, error);
-    if (!udpport->udpsrc)
+    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;
   }
 
-  udpport->udpsink = _create_sinksource ("multiudpsink",
-    GST_BIN (trans->priv->gst_sink), udpport->tee, udpport->fd, GST_PAD_SINK,
-    &udpport->udpsink_requested_pad, error);
-  if (!udpport->udpsink)
+  udpsock->udpsink = _create_sinksource ("multiudpsink",
+    GST_BIN (trans->priv->gst_sink), udpsock->tee, udpsock->fd, GST_PAD_SINK,
+    &udpsock->udpsink_requested_pad, error);
+  if (!udpsock->udpsink)
     goto error;
 
-  g_object_set (udpport->udpsink, "async", FALSE, NULL);
+  g_object_set (udpsock->udpsink, "async", FALSE, NULL);
 
-  trans->priv->udpports[component_id] =
-    g_list_prepend (trans->priv->udpports[component_id], udpport);
+  trans->priv->udpsocks[component_id] =
+    g_list_prepend (trans->priv->udpsocks[component_id], udpsock);
 
-  return udpport;
+  return udpsock;
 
  error:
 
-  if (udpport)
-    fs_multicast_transmitter_put_udpport (trans, udpport);
+  if (udpsock)
+    fs_multicast_transmitter_put_udpsock (trans, udpsock);
 
   return NULL;
 }
 
-static void
-fs_multicast_transmitter_put_udpport (FsMulticastTransmitter *trans,
-  UdpPort *udpport)
+void
+fs_multicast_transmitter_put_udpsock (FsMulticastTransmitter *trans,
+  UdpSock *udpsock)
 {
-  if (udpport->refcount > 1) {
-    udpport->refcount--;
+  if (udpsock->refcount > 1) {
+    udpsock->refcount--;
     return;
   }
 
-  g_assert (udpport->multicast_groups == NULL);
+  trans->priv->udpsocks[udpsock->component_id] =
+    g_list_remove (trans->priv->udpsocks[udpsock->component_id], udpsock);
 
-  trans->priv->udpports[udpport->component_id] =
-    g_list_remove (trans->priv->udpports[udpport->component_id], udpport);
-
-  if (udpport->udpsrc) {
+  if (udpsock->udpsrc) {
     GstStateChangeReturn ret;
-    gst_object_ref (udpport->udpsrc);
-    gst_element_set_state (udpport->udpsrc, GST_STATE_NULL);
-    gst_bin_remove (GST_BIN (trans->priv->gst_src), udpport->udpsrc);
-    ret = gst_element_set_state (udpport->udpsrc, GST_STATE_NULL);
+    gst_object_ref (udpsock->udpsrc);
+    gst_element_set_state (udpsock->udpsrc, GST_STATE_NULL);
+    gst_bin_remove (GST_BIN (trans->priv->gst_src), udpsock->udpsrc);
+    ret = gst_element_set_state (udpsock->udpsrc, GST_STATE_NULL);
     if (ret != GST_STATE_CHANGE_SUCCESS) {
       GST_ERROR ("Error changing state of udpsrc: %s",
         gst_element_state_change_return_get_name (ret));
     }
-    gst_object_unref (udpport->udpsrc);
+    gst_object_unref (udpsock->udpsrc);
   }
 
-  if (udpport->udpsrc_requested_pad) {
-    gst_element_release_request_pad (udpport->funnel,
-      udpport->udpsrc_requested_pad);
-    gst_object_unref (udpport->udpsrc_requested_pad);
+  if (udpsock->udpsrc_requested_pad) {
+    gst_element_release_request_pad (udpsock->funnel,
+      udpsock->udpsrc_requested_pad);
+    gst_object_unref (udpsock->udpsrc_requested_pad);
   }
 
-  if (udpport->udpsink) {
+  if (udpsock->udpsink) {
     GstStateChangeReturn ret;
-    gst_object_ref (udpport->udpsink);
-    gst_element_set_state (udpport->udpsink, GST_STATE_NULL);
-    gst_bin_remove (GST_BIN (trans->priv->gst_sink), udpport->udpsink);
-    ret = gst_element_set_state (udpport->udpsink, GST_STATE_NULL);
+    gst_object_ref (udpsock->udpsink);
+    gst_element_set_state (udpsock->udpsink, GST_STATE_NULL);
+    gst_bin_remove (GST_BIN (trans->priv->gst_sink), udpsock->udpsink);
+    ret = gst_element_set_state (udpsock->udpsink, GST_STATE_NULL);
     if (ret != GST_STATE_CHANGE_SUCCESS) {
       GST_ERROR ("Error changing state of udpsink: %s",
         gst_element_state_change_return_get_name (ret));
     }
-    gst_object_unref (udpport->udpsink);
+    gst_object_unref (udpsock->udpsink);
   }
 
-  if (udpport->udpsink_requested_pad) {
-    gst_element_release_request_pad (udpport->tee,
-      udpport->udpsink_requested_pad);
-    gst_object_unref (udpport->udpsink_requested_pad);
+  if (udpsock->udpsink_requested_pad) {
+    gst_element_release_request_pad (udpsock->tee,
+      udpsock->udpsink_requested_pad);
+    gst_object_unref (udpsock->udpsink_requested_pad);
   }
 
-  if (udpport->fd >= 0)
-    close (udpport->fd);
+  if (udpsock->fd >= 0)
+    close (udpsock->fd);
 
-  g_free (udpport->local_ip);
-  g_free (udpport);
+  g_free (udpsock->local_ip);
+  g_free (udpsock);
 }
 
-static void
-fs_multicast_transmitter_udpport_add_dest (UdpPort *udpport,
-  const gchar *ip, gint port)
+void
+fs_multicast_transmitter_udpsock_inc_sending (UdpSock *udpsock)
 {
-  GST_DEBUG ("Adding dest %s:%d", ip, port);
-  g_signal_emit_by_name (udpport->udpsink, "add", ip, port);
-}
+  if (udpsock->sendcount == 0)
+    g_signal_emit_by_name (udpsock->udpsink, "add", udpsock->multicast_ip,
+        udpsock->port);
 
+  udpsock->sendcount++;
+}
 
-static void
-fs_multicast_transmitter_udpport_remove_dest (UdpPort *udpport,
-  const gchar *ip, gint port)
+void
+fs_multicast_transmitter_udpsock_dec_sending (UdpSock *udpsock)
 {
-  g_signal_emit_by_name (udpport->udpsink, "remove", ip, port);
-}
+  udpsock->sendcount--;
 
+  if (udpsock->sendcount == 0)
+    g_signal_emit_by_name (udpsock->udpsink, "remove", udpsock->multicast_ip,
+        udpsock->port);
+}
 
 static GType
 fs_multicast_transmitter_get_stream_transmitter_type (
@@ -884,152 +910,3 @@ fs_multicast_transmitter_get_stream_transmitter_type (
 {
   return FS_TYPE_MULTICAST_STREAM_TRANSMITTER;
 }
-
-/*
- * The following functions are for counting the use of Multicast
- * Each struct represents a quatuor of local_ip:port:ttl:multicast_ip
- */
-
-struct _UdpMulticastGroup
-{
-  UdpPort *udpport;
-
-  gint refcount;
-  gint sendcount;
-
-  gchar *multicast_ip;
-
-  struct ip_mreqn mreqn;
-};
-
-UdpMulticastGroup *
-fs_multicast_transmitter_get_group (FsMulticastTransmitter *trans,
-    guint component_id,
-    const gchar *multicast_ip,
-    guint port,
-    const gchar *local_ip,
-    guint8 ttl,
-    gboolean recv,
-    GError **error)
-{
-  UdpPort *udpport;
-  UdpMulticastGroup *mcast = NULL;
-  GList *item = NULL;
-
-  udpport = fs_multicast_transmitter_get_udpport (trans, component_id,
-      local_ip, port, ttl, recv, error);
-  if (!udpport)
-    return NULL;
-
-  for (item = g_list_first (udpport->multicast_groups);
-       item;
-       item = g_list_next (item))
-  {
-    mcast = item->data;
-
-    if (!strcmp (mcast->multicast_ip, multicast_ip))
-    {
-      fs_multicast_transmitter_put_udpport (trans, mcast->udpport);
-      mcast->refcount++;
-      return mcast;
-    }
-  }
-
-  mcast = g_new0 (UdpMulticastGroup, 1);
-
-  mcast->refcount = 1;
-  mcast->sendcount = 0;
-  mcast->udpport = udpport;
-  mcast->multicast_ip = g_strdup (multicast_ip);
-
-  if (!inet_aton (multicast_ip, &mcast->mreqn.imr_multiaddr))
-  {
-    g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
-        "Invalid multicast IP");
-    goto error;
-  }
-
-  if (udpport->local_ip &&
-      !inet_aton (udpport->local_ip, &mcast->mreqn.imr_address))
-  {
-    g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
-        "UdpPort address invalid");
-    goto error;
-  }
-  else
-  {
-    mcast->mreqn.imr_address.s_addr = INADDR_ANY;
-  }
-  mcast->mreqn.imr_ifindex = 0;
-
-  if (setsockopt (udpport->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
-          &(mcast->mreqn), sizeof (mcast->mreqn)) < 0)
-  {
-    g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
-        "Could not join the socket to the multicast group2: %s",
-        g_strerror (errno));
-    goto error;
-  }
-
-  udpport->multicast_groups = g_list_prepend (udpport->multicast_groups,
-      mcast);
-
-  return mcast;
-
- error:
-
-  if (mcast)
-  {
-    fs_multicast_transmitter_put_udpport (trans, mcast->udpport);
-    g_free (mcast->multicast_ip);
-    g_free (mcast);
-  }
-
-  return NULL;
-}
-
-void
-fs_multicast_transmitter_put_group (FsMulticastTransmitter *trans,
-    UdpMulticastGroup *mcast)
-{
-
-  mcast->refcount--;
-
-  if (mcast->refcount > 0)
-    return;
-
-  if (setsockopt (mcast->udpport->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
-          &(mcast->mreqn), sizeof (mcast->mreqn)) < 0)
-    GST_ERROR ("Could not remove the socket from the multicast group: %s",
-        g_strerror (errno));
-
-  mcast->udpport->multicast_groups = g_list_remove (
-      mcast->udpport->multicast_groups,
-      mcast);
-
-  fs_multicast_transmitter_put_udpport (trans, mcast->udpport);
-
-  g_free (mcast->multicast_ip);
-  g_free (mcast);
-}
-
-void
-fs_multicast_transmitter_group_inc_sending (UdpMulticastGroup *mcast)
-{
-  if (mcast->sendcount == 0)
-    fs_multicast_transmitter_udpport_add_dest (mcast->udpport,
-        mcast->multicast_ip, mcast->udpport->port);
-
-  mcast->sendcount++;
-}
-
-
-void
-fs_multicast_transmitter_group_dec_sending (UdpMulticastGroup *mcast)
-{
-  mcast->sendcount--;
-
-  if (mcast->sendcount == 0)
-    fs_multicast_transmitter_udpport_remove_dest (mcast->udpport,
-        mcast->multicast_ip, mcast->udpport->port);
-}
diff --git a/transmitters/multicast/fs-multicast-transmitter.h b/transmitters/multicast/fs-multicast-transmitter.h
index 2100682..27c2709 100644
--- a/transmitters/multicast/fs-multicast-transmitter.h
+++ b/transmitters/multicast/fs-multicast-transmitter.h
@@ -84,26 +84,24 @@ struct _FsMulticastTransmitter
 };
 
 /* Private declarations */
-typedef struct _UdpMulticastGroup UdpMulticastGroup;
+typedef struct _UdpSock UdpSock;
 
 GType fs_multicast_transmitter_get_type (void);
 
-
-UdpMulticastGroup *fs_multicast_transmitter_get_group (
-    FsMulticastTransmitter *trans,
+UdpSock *fs_multicast_transmitter_get_udpsock (FsMulticastTransmitter *trans,
     guint component_id,
-    const gchar *multicast_ip,
-    guint port,
     const gchar *local_ip,
+    const gchar *multicast_ip,
+    guint16 port,
     guint8 ttl,
     gboolean recv,
     GError **error);
-void fs_multicast_transmitter_put_group (FsMulticastTransmitter *trans,
-    UdpMulticastGroup *mcast);
 
-void fs_multicast_transmitter_group_inc_sending (UdpMulticastGroup *mcast);
-void fs_multicast_transmitter_group_dec_sending (UdpMulticastGroup *mcast);
+void fs_multicast_transmitter_put_udpsock (FsMulticastTransmitter *trans,
+    UdpSock *udpsock);
 
+void fs_multicast_transmitter_udpsock_inc_sending (UdpSock *udpsock);
+void fs_multicast_transmitter_udpsock_dec_sending (UdpSock *udpsock);
 
 
 G_END_DECLS
-- 
1.5.6.5




More information about the farsight-commits mailing list