From 10ae17ced17e3ec9da06a13c43b3cde12c945bf5 Mon Sep 17 00:00:00 2001 From: Henrik Eriksson Date: Wed, 21 May 2008 11:29:25 +0000 Subject: [PATCH] gst/tcp/gstmultifdsink.*: Add support for DSCP QOS. Fixes #469933. Original commit message from CVS: Patch by: Henrik Eriksson * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_class_init), (gst_multi_fd_sink_init), (setup_dscp_client), (setup_dscp), (gst_multi_fd_sink_add_full), (gst_multi_fd_sink_set_property), (gst_multi_fd_sink_get_property): * gst/tcp/gstmultifdsink.h: Add support for DSCP QOS. Fixes #469933. --- ChangeLog | 11 ++++++ gst/tcp/gstmultifdsink.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++- gst/tcp/gstmultifdsink.h | 1 + 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 55e6442..262e0e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2008-05-21 Wim Taymans + + Patch by: Henrik Eriksson + + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_class_init), + (gst_multi_fd_sink_init), (setup_dscp_client), (setup_dscp), + (gst_multi_fd_sink_add_full), (gst_multi_fd_sink_set_property), + (gst_multi_fd_sink_get_property): + * gst/tcp/gstmultifdsink.h: + Add support for DSCP QOS. Fixes #469933. + 2008-05-21 Sebastian Dröge * tests/check/elements/audioconvert.c: (GST_START_TEST): diff --git a/gst/tcp/gstmultifdsink.c b/gst/tcp/gstmultifdsink.c index 6b70e6f..50c599d 100644 --- a/gst/tcp/gstmultifdsink.c +++ b/gst/tcp/gstmultifdsink.c @@ -126,6 +126,7 @@ #include #include #include +#include #ifdef HAVE_FIONREAD_IN_SYS_FILIO #include @@ -190,6 +191,8 @@ enum #define DEFAULT_BURST_UNIT GST_UNIT_TYPE_UNDEFINED #define DEFAULT_BURST_VALUE 0 +#define DEFAULT_QOS_DSCP -1 + enum { PROP_0, @@ -218,6 +221,10 @@ enum PROP_BURST_UNIT, PROP_BURST_VALUE, + + PROP_QOS_DSCP, + + PROP_LAST }; /* For backward compat, we can't really select the poll mode anymore with @@ -490,6 +497,11 @@ gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass) "The amount of burst expressed in burst-unit", 0, G_MAXUINT64, DEFAULT_BURST_VALUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_QOS_DSCP, + g_param_spec_int ("qos_dscp", "QoS diff srv code point", + "Quality of Service, differentiated services code point (-1 default)", + -1, 63, DEFAULT_QOS_DSCP, G_PARAM_READWRITE)); + /** * GstMultiFdSink::add: * @gstmultifdsink: the multifdsink element to emit this signal on @@ -678,6 +690,8 @@ gst_multi_fd_sink_init (GstMultiFdSink * this, GstMultiFdSinkClass * klass) this->def_burst_unit = DEFAULT_BURST_UNIT; this->def_burst_value = DEFAULT_BURST_VALUE; + this->qos_dscp = DEFAULT_QOS_DSCP; + this->header_flags = 0; } @@ -695,6 +709,79 @@ gst_multi_fd_sink_finalize (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static gint +setup_dscp_client (GstMultiFdSink * sink, GstTCPClient * client) +{ + gint tos; + gint ret; + struct sockaddr_storage ssaddr; + socklen_t slen = sizeof (ssaddr); + gint af; + + /* don't touch */ + if (sink->qos_dscp < 0) + return 0; + + if ((ret = + getsockname (client->fd.fd, (struct sockaddr *) &ssaddr, + &slen)) < 0) { + GST_DEBUG_OBJECT (sink, "could not get sockname: %s", g_strerror (errno)); + return ret; + } + + af = ssaddr.ss_family; + + /* If this is a v4-mapped address then do ipv4 qos. */ + if (af == AF_INET6) { + struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) &ssaddr; + + GST_DEBUG_OBJECT (sink, "check IP6 socket"); + if (IN6_IS_ADDR_V4MAPPED (&(saddr6->sin6_addr))) + GST_DEBUG_OBJECT (sink, "mapped to IPV4"); + af = AF_INET; + } + + /* Extract and shift 6 bits of the dscp. */ + tos = (sink->qos_dscp & 0x3f) << 2; + switch (af) { + case AF_INET: + ret = setsockopt (client->fd.fd, SOL_IP, IP_TOS, &tos, sizeof (tos)); + break; + case AF_INET6: +#ifdef IPV6_TCLASS + ret = + setsockopt (client->fd.fd, SOL_IPV6, IPV6_TCLASS, &tos, sizeof (tos)); + break; +#endif + default: + ret = 0; + GST_ERROR_OBJECT (sink, "unsupported AF"); + break; + } + if (ret) + GST_DEBUG_OBJECT (sink, "could not set DSCP: %s", g_strerror (errno)); + + return ret; +} + + +static void +setup_dscp (GstMultiFdSink * sink) +{ + GList *clients, *next; + + CLIENTS_LOCK (sink); + for (clients = sink->clients; clients; clients = next) { + GstTCPClient *client; + + client = (GstTCPClient *) clients->data; + next = g_list_next (clients); + + setup_dscp_client (sink, client); + } + CLIENTS_UNLOCK (sink); +} + /* "add-full" signal implementation */ void gst_multi_fd_sink_add_full (GstMultiFdSink * sink, int fd, @@ -770,6 +857,7 @@ gst_multi_fd_sink_add_full (GstMultiFdSink * sink, int fd, res = fstat (fd, &statbuf); if (S_ISSOCK (statbuf.st_mode)) { client->is_socket = TRUE; + setup_dscp_client (sink, client); } gst_poll_restart (sink->fdset); @@ -2577,6 +2665,10 @@ gst_multi_fd_sink_set_property (GObject * object, guint prop_id, case PROP_BURST_VALUE: multifdsink->def_burst_value = g_value_get_uint64 (value); break; + case PROP_QOS_DSCP: + multifdsink->qos_dscp = g_value_get_int (value); + setup_dscp (multifdsink); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -2653,7 +2745,9 @@ gst_multi_fd_sink_get_property (GObject * object, guint prop_id, GValue * value, case PROP_BURST_VALUE: g_value_set_uint64 (value, multifdsink->def_burst_value); break; - + case PROP_QOS_DSCP: + g_value_set_int (value, multifdsink->qos_dscp); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gst/tcp/gstmultifdsink.h b/gst/tcp/gstmultifdsink.h index c8352d7..9bc67d3 100644 --- a/gst/tcp/gstmultifdsink.h +++ b/gst/tcp/gstmultifdsink.h @@ -208,6 +208,7 @@ struct _GstMultiFdSink { GstTCPProtocol protocol; guint mtu; + gint qos_dscp; GArray *bufqueue; /* global queue of buffers */ -- 2.7.4