[farsight2/master] multicast: Implement ToS field

Olivier Crête olivier.crete at collabora.co.uk
Wed Jul 22 13:57:49 PDT 2009


---
 transmitters/multicast/fs-multicast-transmitter.c |   78 ++++++++++++++++++---
 1 files changed, 69 insertions(+), 9 deletions(-)

diff --git a/transmitters/multicast/fs-multicast-transmitter.c b/transmitters/multicast/fs-multicast-transmitter.c
index 00475cd..a643931 100644
--- a/transmitters/multicast/fs-multicast-transmitter.c
+++ b/transmitters/multicast/fs-multicast-transmitter.c
@@ -72,7 +72,8 @@ enum
   PROP_0,
   PROP_GST_SINK,
   PROP_GST_SRC,
-  PROP_COMPONENTS
+  PROP_COMPONENTS,
+  PROP_TYPE_OF_SERVICE
 };
 
 struct _FsMulticastTransmitterPrivate
@@ -90,6 +91,8 @@ struct _FsMulticastTransmitterPrivate
   GMutex *mutex;
   GList **udpsocks;
 
+  gint type_of_service;
+
   gboolean disposed;
 };
 
@@ -119,6 +122,11 @@ static FsStreamTransmitter *fs_multicast_transmitter_new_stream_transmitter (
 static GType fs_multicast_transmitter_get_stream_transmitter_type (
     FsTransmitter *transmitter);
 
+static void fs_multicast_transmitter_set_type_of_service (
+    FsMulticastTransmitter *self,
+    gint tos);
+
+
 static GObjectClass *parent_class = NULL;
 //static guint signals[LAST_SIGNAL] = { 0 };
 
@@ -182,6 +190,8 @@ fs_multicast_transmitter_class_init (FsMulticastTransmitterClass *klass)
   g_object_class_override_property (gobject_class, PROP_GST_SINK, "gst-sink");
   g_object_class_override_property (gobject_class, PROP_COMPONENTS,
     "components");
+  g_object_class_override_property (gobject_class, PROP_TYPE_OF_SERVICE,
+    "tos");
 
   transmitter_class->new_stream_transmitter =
     fs_multicast_transmitter_new_stream_transmitter;
@@ -423,6 +433,11 @@ fs_multicast_transmitter_get_property (GObject *object,
     case PROP_COMPONENTS:
       g_value_set_uint (value, self->components);
       break;
+    case PROP_TYPE_OF_SERVICE:
+      g_mutex_lock (self->priv->mutex);
+      g_value_set_uint (value, self->priv->type_of_service);
+      g_mutex_unlock (self->priv->mutex);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -441,6 +456,10 @@ fs_multicast_transmitter_set_property (GObject *object,
     case PROP_COMPONENTS:
       self->components = g_value_get_uint (value);
       break;
+    case PROP_TYPE_OF_SERVICE:
+      fs_multicast_transmitter_set_type_of_service (self,
+          g_value_get_uint (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -538,6 +557,7 @@ _bind_port (
     const gchar *multicast_ip,
     guint16 port,
     guchar ttl,
+    int type_of_service,
     GError **error)
 {
   int sock = -1;
@@ -550,7 +570,6 @@ _bind_port (
 #else
   struct ip_mreq mreq;
 #endif
-  int tos, prio;
 
   address.sin_family = AF_INET;
   address.sin_addr.s_addr = INADDR_ANY;
@@ -639,13 +658,15 @@ _bind_port (
     goto error;
   }
 
-  tos = IPTOS_LOWDELAY;
-  if (setsockopt (sock, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)) < 0)
-    GST_WARNING ("could not set TOS: %s", g_strerror (errno));
+  if (setsockopt (sock, IPPROTO_IP, IP_TOS,
+          &type_of_service, sizeof (type_of_service)) < 0)
+    GST_WARNING ("could not set socket ToS: %s", g_strerror (errno));
 
-  prio = 6;
-  if (setsockopt (sock, SOL_SOCKET, SO_PRIORITY, &prio, sizeof (tos)) < 0)
-    GST_WARNING ( "could not set socket priority: %s", g_strerror (errno));
+#ifdef IPV6_TCLASS
+  if (setsockopt (sock, IPPROTO_IPV6, IPV6_TCLASS,
+          &type_of_service, sizeof (type_of_service)) < 0)
+    GST_WARNING ("could not set TCLASS: %s", g_strerror (errno));
+#endif
 
   address.sin_port = htons (port);
   retval = bind (sock, (struct sockaddr *) &address, sizeof (address));
@@ -871,6 +892,7 @@ fs_multicast_transmitter_get_udpsock (FsMulticastTransmitter *trans,
   UdpSock *udpsock;
   UdpSock *tmpudpsock;
   GError *local_error = NULL;
+  int tos;
 
   /* First lets check if we already have one */
   if (component_id > trans->components)
@@ -883,6 +905,7 @@ fs_multicast_transmitter_get_udpsock (FsMulticastTransmitter *trans,
   g_mutex_lock (trans->priv->mutex);
   udpsock = fs_multicast_transmitter_get_udpsock_locked (trans, component_id,
       local_ip, multicast_ip, port, ttl, sending, &local_error);
+  tos = trans->priv->type_of_service;
   g_mutex_unlock (trans->priv->mutex);
 
   if (local_error)
@@ -911,7 +934,7 @@ fs_multicast_transmitter_get_udpsock (FsMulticastTransmitter *trans,
 
   /* Now lets bind both ports */
 
-  udpsock->fd = _bind_port (local_ip, multicast_ip, port, ttl, error);
+  udpsock->fd = _bind_port (local_ip, multicast_ip, port, ttl, tos, error);
   if (udpsock->fd < 0)
     goto error;
 
@@ -1143,3 +1166,40 @@ fs_multicast_transmitter_udpsock_ref (FsMulticastTransmitter *trans,
   g_byte_array_append (udpsock->ttls, &ttl, 1);
   g_mutex_unlock (trans->priv->mutex);
 }
+
+
+static void
+fs_multicast_transmitter_set_type_of_service (FsMulticastTransmitter *self,
+    gint tos)
+{
+  gint i;
+
+  g_mutex_lock (self->priv->mutex);
+  if (self->priv->type_of_service == tos)
+    goto out;
+
+  self->priv->type_of_service = tos;
+
+  for (i = 0; i < self->components; i++)
+  {
+    GList *item;
+
+    for (item = self->priv->udpsocks[i]; item; item = item->next)
+    {
+      UdpSock *udpsock = item->data;
+
+      if (setsockopt (udpsock->fd, IPPROTO_IP, IP_TOS,
+              &tos, sizeof (tos)) < 0)
+        GST_WARNING ( "could not set socket tos: %s", g_strerror (errno));
+
+#ifdef IPV6_TCLASS
+      if (setsockopt (udpsock->fd, IPPROTO_IPV6, IPV6_TCLASS,
+              &tos, sizeof (tos)) < 0)
+        GST_WARNING ("could not set TCLASS: %s", g_strerror (errno));
+#endif
+    }
+  }
+
+ out:
+  g_mutex_unlock (self->priv->mutex);
+}
-- 
1.5.6.5




More information about the farsight-commits mailing list