[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