[vlc-devel] [PATCH] Fix for SAP mishandling of duplicates via different addresses

Alexander Clouter alex at digriz.org.uk
Wed Oct 19 15:21:56 CEST 2011

We broadcast a number of IPTV channels at my organisation and want the
channels available to internal and nearby external users. As a result
we announce these channels via SAP on *both*
does not like this too much.

The function modules/services_discovery/sap.c::ParseSAP() has an
IsSameSession() check that overlooks the possibility that the same session
could arrive via different SAP listener sockets and as a result rewrites the
entire SAP playlist once every 30 seconds (we announce at a period of five
seconds and your 'trust' cycle of six leads to 30 seconds). Once rewritten,
any channel being viewed is terminated. This repeats every thirty seconds,
getting annoying, real quickly. :)

The solution is to additionally track the SAP listener socket that the
packet arrived on, and only go through the 'trust' codepath if it comes in
on the same socket; ignoring duplicates (packets that match the conditions
of IsSameSession) arriving via different sockets.

I am pretty sure this is a safe fix as nothing in RFC2974 (section 5,
'Session Modification') implies that broadcasting the same SDP payload on
different SAP addresses is incorrect; hopefully I have not missed any
clauses ;)

This is detailed in Trac bug #5462[1].

[1] http://trac.videolan.org/vlc/ticket/5462

Signed-off-by: Alexander Clouter <alex at digriz.org.uk>
 modules/services_discovery/sap.c |   13 ++++++++++---
 1 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/modules/services_discovery/sap.c b/modules/services_discovery/sap.c
index a44cd6d..775fa5e 100644
--- a/modules/services_discovery/sap.c
+++ b/modules/services_discovery/sap.c
@@ -157,6 +157,8 @@ struct sdp_media_t
 /* The structure that contains sdp information */
 struct  sdp_t
+    int origin_fd;
     const char *psz_sdp;
     /* o field */
@@ -241,7 +243,7 @@ struct demux_sys_t
 /* Main parsing functions */
     static int ParseConnection( vlc_object_t *p_obj, sdp_t *p_sdp );
-    static int ParseSAP( services_discovery_t *p_sd, const uint8_t *p_buffer, size_t i_read );
+    static int ParseSAP( services_discovery_t *p_sd, const uint8_t *p_buffer, size_t i_read, int fd );
     static sdp_t *ParseSDP (vlc_object_t *p_sd, const char *psz_sdp);
     static sap_announce_t *CreateAnnounce( services_discovery_t *, uint16_t, sdp_t * );
     static int RemoveAnnounce( services_discovery_t *p_sd, sap_announce_t *p_announce );
@@ -556,7 +558,7 @@ static void *Run( void *data )
                         /* Parse the packet */
                         p_buffer[i_read] = '\0';
-                        ParseSAP (p_sd, p_buffer, i_read);
+                        ParseSAP (p_sd, p_buffer, i_read, ufd[i].fd);
@@ -655,7 +657,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
 /* i_read is at least > 6 */
 static int ParseSAP( services_discovery_t *p_sd, const uint8_t *buf,
-                     size_t len )
+                     size_t len, int fd )
     int i;
     const char          *psz_sdp;
@@ -747,6 +749,7 @@ static int ParseSAP( services_discovery_t *p_sd, const uint8_t *buf,
     if( p_sdp == NULL )
         return VLC_EGENERIC;
+    p_sdp->origin_fd = fd;
     p_sdp->psz_sdp = psz_sdp;
     /* Decide whether we should add a playlist item for this SDP */
@@ -775,6 +778,10 @@ static int ParseSAP( services_discovery_t *p_sd, const uint8_t *buf,
         /* FIXME: we create a new announce each time the sdp changes */
         if( IsSameSession( p_announce->p_sdp, p_sdp ) )
+            /* ignore duplicates that appear via a different socket */
+            if (p_announce->p_sdp->origin_fd != p_sdp->origin_fd)
+		return VLC_SUCCESS;
             /* We don't support delete announcement as they can easily
              * Be used to highjack an announcement by a third party.
              * Intead we cleverly implement Implicit Announcement removal.

More information about the vlc-devel mailing list