Commit 3c325913 authored by Pierre d'Herbemont's avatar Pierre d'Herbemont

modules/services_discovery/sap.c: Don't trust announcement down packet, but...

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.
parent 54b8548a
...@@ -123,8 +123,8 @@ struct virtual_socket_t ...@@ -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) #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 ) ); 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) #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 ) ); 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) #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 ) ); 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 ) );
......
...@@ -210,6 +210,8 @@ struct attribute_t ...@@ -210,6 +210,8 @@ struct attribute_t
struct sap_announce_t struct sap_announce_t
{ {
mtime_t i_last; mtime_t i_last;
mtime_t i_period;
uint8_t i_period_trust;
uint16_t i_hash; uint16_t i_hash;
uint32_t i_source[4]; uint32_t i_source[4];
...@@ -539,16 +541,22 @@ static void Run( services_discovery_t *p_sd ) ...@@ -539,16 +541,22 @@ static void Run( services_discovery_t *p_sd )
i_read = net_Select( p_sd, p_sd->p_sys->pi_fd, i_read = net_Select( p_sd, p_sd->p_sys->pi_fd,
p_sd->p_sys->i_fd, p_buffer, p_sd->p_sys->i_fd, p_buffer,
MAX_SAP_BUFFER ); MAX_SAP_BUFFER, 500 );
/* Check for items that need deletion */ /* Check for items that need deletion */
for( i = 0; i < p_sd->p_sys->i_announces; i++ ) for( i = 0; i < p_sd->p_sys->i_announces; i++ )
{ {
mtime_t i_timeout = ( mtime_t ) 1000000 * p_sd->p_sys->i_timeout; mtime_t i_timeout = ( mtime_t ) 1000000 * p_sd->p_sys->i_timeout;
sap_announce_t * p_announce = p_sd->p_sys->pp_announces[i];
mtime_t i_last_period = mdate() - p_announce->i_last;
if( mdate() - p_sd->p_sys->pp_announces[i]->i_last > i_timeout ) /* 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, ...@@ -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++ ) 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: slow */
/* FIXME: we create a new announce each time the sdp changes */ /* 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 ) /* We don't support delete announcement as they can easily
{ * Be used to highjack an announcement by a third party.
RemoveAnnounce( p_sd, p_sd->p_sys->pp_announces[i]); * Intead we cleverly implement Implicit Announcement removal.
} *
else * 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; FreeSDP( p_sdp ); p_sdp = NULL;
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -774,6 +795,8 @@ sap_announce_t *CreateAnnounce( services_discovery_t *p_sd, uint16_t i_hash, ...@@ -774,6 +795,8 @@ sap_announce_t *CreateAnnounce( services_discovery_t *p_sd, uint16_t i_hash,
p_sys = p_sd->p_sys; p_sys = p_sd->p_sys;
p_sap->i_last = mdate(); p_sap->i_last = mdate();
p_sap->i_period = 0;
p_sap->i_period_trust = 0;
p_sap->i_hash = i_hash; p_sap->i_hash = i_hash;
p_sap->p_sdp = p_sdp; p_sap->p_sdp = p_sdp;
......
...@@ -256,7 +256,8 @@ int *net_Listen (vlc_object_t *p_this, const char *psz_host, ...@@ -256,7 +256,8 @@ int *net_Listen (vlc_object_t *p_this, const char *psz_host,
static ssize_t static ssize_t
net_ReadInner (vlc_object_t *restrict p_this, unsigned fdc, const int *fdv, net_ReadInner (vlc_object_t *restrict p_this, unsigned fdc, const int *fdv,
const v_socket_t *const *restrict vsv, 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; size_t i_total = 0;
...@@ -281,12 +282,13 @@ net_ReadInner (vlc_object_t *restrict p_this, unsigned fdc, const int *fdv, ...@@ -281,12 +282,13 @@ net_ReadInner (vlc_object_t *restrict p_this, unsigned fdc, const int *fdv,
ufd[i].revents = 0; ufd[i].revents = 0;
} }
switch (poll (ufd, fdc, 500)) switch (poll (ufd, fdc, timeout ? timeout : 500))
{ {
case -1: case -1:
goto error; goto error;
case 0: // timeout case 0: // timeout
if( timeout ) return 0;
continue; continue;
} }
...@@ -399,7 +401,7 @@ ssize_t __net_Read( vlc_object_t *restrict p_this, int fd, ...@@ -399,7 +401,7 @@ ssize_t __net_Read( vlc_object_t *restrict p_this, int fd,
{ {
return net_ReadInner( p_this, 1, &(int){ fd }, return net_ReadInner( p_this, 1, &(int){ fd },
&(const v_socket_t *){ p_vs }, &(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, ...@@ -407,16 +409,19 @@ ssize_t __net_Read( vlc_object_t *restrict p_this, int fd,
* __net_Select: * __net_Select:
***************************************************************************** *****************************************************************************
* Read from several sockets. Takes data from the first socket that has some. * 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, ssize_t __net_Select( vlc_object_t *restrict p_this,
const int *restrict fds, int nfd, 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]; const v_socket_t *vsv[nfd];
memset( vsv, 0, sizeof (vsv) ); memset( vsv, 0, sizeof (vsv) );
return net_ReadInner( p_this, nfd, fds, vsv, return net_ReadInner( p_this, nfd, fds, vsv,
buf, len, VLC_FALSE ); buf, len, VLC_FALSE, timeout );
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment