From 3c3259132706c07bf0046e922945974c0993f469 Mon Sep 17 00:00:00 2001 From: Pierre d'Herbemont Date: Fri, 21 Dec 2007 18:52:21 +0000 Subject: [PATCH] modules/services_discovery/sap.c: Don't trust announcement down packet, but support implicit timeout. * 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 | 4 +-- modules/services_discovery/sap.c | 45 ++++++++++++++++++++++++-------- src/network/io.c | 15 +++++++---- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/include/vlc_network.h b/include/vlc_network.h index 4a130825b8..c2e83ad229 100644 --- a/include/vlc_network.h +++ b/include/vlc_network.h @@ -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 ) ); diff --git a/modules/services_discovery/sap.c b/modules/services_discovery/sap.c index d5a4562f54..d6971c129f 100644 --- a/modules/services_discovery/sap.c +++ b/modules/services_discovery/sap.c @@ -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; diff --git a/src/network/io.c b/src/network/io.c index ee1ba969fa..b568cd79ee 100644 --- a/src/network/io.c +++ b/src/network/io.c @@ -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 ); } -- 2.39.2