]> git.sesse.net Git - vlc/commitdiff
modules/services_discovery/sap.c: Don't trust announcement down packet, but support...
authorPierre d'Herbemont <pdherbemont@videolan.org>
Fri, 21 Dec 2007 18:52:21 +0000 (18:52 +0000)
committerPierre d'Herbemont <pdherbemont@videolan.org>
Fri, 21 Dec 2007 18:52:21 +0000 (18:52 +0000)
* As suggested in the RFC we remove the discovered media if there is no new packet after three average packet period. (implicit timeout).
* Announcement of removal packet can be used to silently replace an announce by an other.
* Add a timeout argument to net_Select.

include/vlc_network.h
modules/services_discovery/sap.c
src/network/io.c

index 4a130825b86ac00bf021e883e790c6bebfa6a2b7..c2e83ad229ab96d7f11f79c4aca371baae0e383f 100644 (file)
@@ -123,8 +123,8 @@ struct virtual_socket_t
 #define net_Read(a,b,c,d,e,f) __net_Read(VLC_OBJECT(a),b,c,d,e,f)
 VLC_EXPORT( ssize_t, __net_Read, ( vlc_object_t *p_this, int fd, const v_socket_t *, uint8_t *p_data, size_t i_data, vlc_bool_t b_retry ) );
 
-#define net_Select(a,b,c,d,e) __net_Select(VLC_OBJECT(a),b,c,d,e)
-VLC_EXPORT( ssize_t, __net_Select, ( vlc_object_t *p_this, const int *pi_fd, int i_fd, uint8_t *p_data, size_t i_data ) );
+#define net_Select(a,b,c,d,e,f) __net_Select(VLC_OBJECT(a),b,c,d,e,f)
+VLC_EXPORT( ssize_t, __net_Select, ( vlc_object_t *p_this, const int *pi_fd, int i_fd, uint8_t *p_data, size_t i_data, int i_timeout ) );
 
 #define net_Write(a,b,c,d,e) __net_Write(VLC_OBJECT(a),b,c,d,e)
 VLC_EXPORT( ssize_t, __net_Write, ( vlc_object_t *p_this, int fd, const v_socket_t *, const uint8_t *p_data, size_t i_data ) );
index d5a4562f5446388810ef6819b5adef73c9b01ca9..d6971c129f7470dab2f8ce4d65f9f8fc54619708 100644 (file)
@@ -210,6 +210,8 @@ struct attribute_t
 struct sap_announce_t
 {
     mtime_t i_last;
+    mtime_t i_period;
+    uint8_t i_period_trust;
 
     uint16_t    i_hash;
     uint32_t    i_source[4];
@@ -539,16 +541,22 @@ static void Run( services_discovery_t *p_sd )
 
         i_read = net_Select( p_sd, p_sd->p_sys->pi_fd,
                              p_sd->p_sys->i_fd, p_buffer,
-                             MAX_SAP_BUFFER );
+                             MAX_SAP_BUFFER, 500 );
 
         /* Check for items that need deletion */
         for( i = 0; i < p_sd->p_sys->i_announces; i++ )
         {
             mtime_t i_timeout = ( mtime_t ) 1000000 * p_sd->p_sys->i_timeout;
-
-            if( mdate() - p_sd->p_sys->pp_announces[i]->i_last > i_timeout )
+            sap_announce_t * p_announce = p_sd->p_sys->pp_announces[i];
+            mtime_t i_last_period = mdate() - p_announce->i_last;
+            
+            /* Remove the annoucement, if the last announcement was 1 hour ago
+             * or if the last packet emitted was 3 times the average time
+             * between two packets */
+            if( ( p_announce->i_period_trust > 5 && i_last_period > 3 * p_announce->i_period ) ||
+                i_last_period > i_timeout )
             {
-                RemoveAnnounce( p_sd, p_sd->p_sys->pp_announces[i] );
+                RemoveAnnounce( p_sd, p_announce );
             }
         }
 
@@ -737,17 +745,30 @@ static int ParseSAP( services_discovery_t *p_sd, const uint8_t *buf,
 
     for( i = 0 ; i< p_sd->p_sys->i_announces ; i++ )
     {
+        sap_announce_t * p_announce = p_sd->p_sys->pp_announces[i];
         /* FIXME: slow */
         /* FIXME: we create a new announce each time the sdp changes */
-        if( IsSameSession( p_sd->p_sys->pp_announces[i]->p_sdp, p_sdp ) )
+        if( IsSameSession( p_announce->p_sdp, p_sdp ) )
         {
-            if( b_need_delete )
-            {
-                RemoveAnnounce( p_sd, p_sd->p_sys->pp_announces[i]);
-            }
-            else
+            /* 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.
+             *
+             * if( b_need_delete )
+             *    RemoveAnnounce( p_sd, p_sd->p_sys->pp_announces[i]);
+             * else
+             */
+
+            if( !b_need_delete )
             {
-                p_sd->p_sys->pp_announces[i]->i_last = mdate();
+                /* No need to go after six, as we start to trust the
+                 * average period at six */
+                if( p_announce->i_period_trust <= 5 )
+                    p_announce->i_period_trust++;
+
+                /* Compute the average period */
+                p_announce->i_period = (p_announce->i_period + (mdate() - p_announce->i_last)) / 2;
+                p_announce->i_last = mdate();
             }
             FreeSDP( p_sdp ); p_sdp = NULL;
             return VLC_SUCCESS;
@@ -774,6 +795,8 @@ sap_announce_t *CreateAnnounce( services_discovery_t *p_sd, uint16_t i_hash,
     p_sys = p_sd->p_sys;
 
     p_sap->i_last = mdate();
+    p_sap->i_period = 0;
+    p_sap->i_period_trust = 0;
     p_sap->i_hash = i_hash;
     p_sap->p_sdp = p_sdp;
 
index ee1ba969fa11e7839ef82d55623847086f5655bb..b568cd79eeb58875e8b88777ccb608e152858986 100644 (file)
@@ -256,7 +256,8 @@ int *net_Listen (vlc_object_t *p_this, const char *psz_host,
 static ssize_t
 net_ReadInner (vlc_object_t *restrict p_this, unsigned fdc, const int *fdv,
                const v_socket_t *const *restrict vsv,
-               uint8_t *restrict p_buf, size_t i_buflen, vlc_bool_t waitall)
+               uint8_t *restrict p_buf, size_t i_buflen, vlc_bool_t waitall,
+               int timeout)
 {
     size_t i_total = 0;
 
@@ -281,12 +282,13 @@ net_ReadInner (vlc_object_t *restrict p_this, unsigned fdc, const int *fdv,
             ufd[i].revents = 0;
         }
 
-        switch (poll (ufd, fdc, 500))
+        switch (poll (ufd, fdc, timeout ? timeout : 500))
         {
             case -1:
                 goto error;
 
             case 0: // timeout
+                if( timeout ) return 0;
                 continue;
         }
 
@@ -399,7 +401,7 @@ ssize_t __net_Read( vlc_object_t *restrict p_this, int fd,
 {
     return net_ReadInner( p_this, 1, &(int){ fd },
                           &(const v_socket_t *){ p_vs },
-                          buf, len, b_retry );
+                          buf, len, b_retry, 0 );
 }
 
 
@@ -407,16 +409,19 @@ ssize_t __net_Read( vlc_object_t *restrict p_this, int fd,
  * __net_Select:
  *****************************************************************************
  * Read from several sockets. Takes data from the first socket that has some.
+ * if timeout is zero, net_Select will wait indefinitely. timeout is in
+ * millisecond.
  *****************************************************************************/
 ssize_t __net_Select( vlc_object_t *restrict p_this,
                       const int *restrict fds, int nfd,
-                      uint8_t *restrict buf, size_t len )
+                      uint8_t *restrict buf, size_t len,
+                      int timeout )
 {
     const v_socket_t *vsv[nfd];
     memset( vsv, 0, sizeof (vsv) );
 
     return net_ReadInner( p_this, nfd, fds, vsv,
-                          buf, len, VLC_FALSE );
+                          buf, len, VLC_FALSE, timeout );
 }