X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fservices_discovery%2Fsap.c;h=6e61f2238ed2d67ae2b2acde5f11c119f22bebfd;hb=96db1d57943e0ffc6af5db3f119898b4d3079e1c;hp=92e89472853fa74c4167f6685c31eaea0875fa3a;hpb=4f028428053d0342c55deb6ba8b8da114c6a0caa;p=vlc diff --git a/modules/services_discovery/sap.c b/modules/services_discovery/sap.c index 92e8947285..6e61f2238e 100644 --- a/modules/services_discovery/sap.c +++ b/modules/services_discovery/sap.c @@ -26,11 +26,16 @@ /***************************************************************************** * Includes *****************************************************************************/ -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include #include -#include #include +#include #include #include @@ -97,7 +102,7 @@ #define SAP_PARSE_TEXT N_( "Try to parse the announce" ) #define SAP_PARSE_LONGTEXT N_( \ "This enables actual parsing of the announces by the SAP module. " \ - "Otherwise, all announcements are parsed by the \"livedotcom\" " \ + "Otherwise, all announcements are parsed by the \"live555\" " \ "(RTP/RTSP) module." ) #define SAP_STRICT_TEXT N_( "SAP Strict mode" ) #define SAP_STRICT_LONGTEXT N_( \ @@ -118,40 +123,40 @@ static int OpenDemux ( vlc_object_t * ); static void CloseDemux ( vlc_object_t * ); -vlc_module_begin(); - set_shortname( _("SAP")); - set_description( _("SAP Announcements") ); - set_category( CAT_PLAYLIST ); - set_subcategory( SUBCAT_PLAYLIST_SD ); +vlc_module_begin () + set_shortname( N_("SAP")) + set_description( N_("SAP Announcements") ) + set_category( CAT_PLAYLIST ) + set_subcategory( SUBCAT_PLAYLIST_SD ) add_string( "sap-addr", NULL, NULL, - SAP_ADDR_TEXT, SAP_ADDR_LONGTEXT, VLC_TRUE ); + SAP_ADDR_TEXT, SAP_ADDR_LONGTEXT, true ); add_bool( "sap-ipv4", 1 , NULL, - SAP_IPV4_TEXT,SAP_IPV4_LONGTEXT, VLC_TRUE ); + SAP_IPV4_TEXT,SAP_IPV4_LONGTEXT, true ); add_bool( "sap-ipv6", 1 , NULL, - SAP_IPV6_TEXT, SAP_IPV6_LONGTEXT, VLC_TRUE ); + SAP_IPV6_TEXT, SAP_IPV6_LONGTEXT, true ); add_integer( "sap-timeout", 1800, NULL, - SAP_TIMEOUT_TEXT, SAP_TIMEOUT_LONGTEXT, VLC_TRUE ); + SAP_TIMEOUT_TEXT, SAP_TIMEOUT_LONGTEXT, true ); add_bool( "sap-parse", 1 , NULL, - SAP_PARSE_TEXT,SAP_PARSE_LONGTEXT, VLC_TRUE ); + SAP_PARSE_TEXT,SAP_PARSE_LONGTEXT, true ); add_bool( "sap-strict", 0 , NULL, - SAP_STRICT_TEXT,SAP_STRICT_LONGTEXT, VLC_TRUE ); + SAP_STRICT_TEXT,SAP_STRICT_LONGTEXT, true ); #if 0 add_bool( "sap-cache", 0 , NULL, - SAP_CACHE_TEXT,SAP_CACHE_LONGTEXT, VLC_TRUE ); + SAP_CACHE_TEXT,SAP_CACHE_LONGTEXT, true ); #endif add_bool( "sap-timeshift", 0 , NULL, - SAP_TIMESHIFT_TEXT,SAP_TIMESHIFT_LONGTEXT, VLC_TRUE ); + SAP_TIMESHIFT_TEXT,SAP_TIMESHIFT_LONGTEXT, true ); - set_capability( "services_discovery", 0 ); - set_callbacks( Open, Close ); + set_capability( "services_discovery", 0 ) + set_callbacks( Open, Close ) - add_submodule(); - set_description( _("SDP Descriptions parser") ); - add_shortcut( "sdp" ); - set_capability( "demux2", 51 ); - set_callbacks( OpenDemux, CloseDemux ); -vlc_module_end(); + add_submodule () + set_description( N_("SDP Descriptions parser") ) + add_shortcut( "sdp" ) + set_capability( "demux", 51 ) + set_callbacks( OpenDemux, CloseDemux ) +vlc_module_end () /***************************************************************************** @@ -207,7 +212,7 @@ struct sdp_t struct attribute_t { const char *value; - char name[0]; + char name[]; }; struct sap_announce_t @@ -222,11 +227,13 @@ struct sap_announce_t /* SAP annnounces must only contain one SDP */ sdp_t *p_sdp; - int i_input_id; + input_item_t * p_item; }; struct services_discovery_sys_t { + vlc_thread_t thread; + /* Socket descriptors */ int i_fd; int *pi_fd; @@ -236,9 +243,9 @@ struct services_discovery_sys_t struct sap_announce_t **pp_announces; /* Modes */ - vlc_bool_t b_strict; - vlc_bool_t b_parse; - vlc_bool_t b_timeshift; + bool b_strict; + bool b_parse; + bool b_timeshift; int i_timeout; }; @@ -256,7 +263,7 @@ struct demux_sys_t /* Main functions */ static int Demux( demux_t *p_demux ); static int Control( demux_t *, int, va_list ); - static void Run ( services_discovery_t *p_sd ); + static void *Run ( void *p_sd ); /* Main parsing functions */ static int ParseConnection( vlc_object_t *p_obj, sdp_t *p_sdp ); @@ -272,7 +279,7 @@ struct demux_sys_t static const char *FindAttribute (const sdp_t *sdp, unsigned media, const char *name); - static vlc_bool_t IsSameSession( sdp_t *p_sdp1, sdp_t *p_sdp2 ); + static bool IsSameSession( sdp_t *p_sdp1, sdp_t *p_sdp2 ); static int InitSocket( services_discovery_t *p_sd, const char *psz_address, int i_port ); static int Decompress( const unsigned char *psz_src, unsigned char **_dst, int i_len ); static void FreeSDP( sdp_t *p_sdp ); @@ -290,10 +297,11 @@ static int Open( vlc_object_t *p_this ) services_discovery_t *p_sd = ( services_discovery_t* )p_this; services_discovery_sys_t *p_sys = (services_discovery_sys_t *) malloc( sizeof( services_discovery_sys_t ) ); + if( !p_sys ) + return VLC_ENOMEM; p_sys->i_timeout = var_CreateGetInteger( p_sd, "sap-timeout" ); - p_sd->pf_run = Run; p_sd->p_sys = p_sys; p_sys->pi_fd = NULL; @@ -317,6 +325,12 @@ static int Open( vlc_object_t *p_this ) p_sys->i_announces = 0; p_sys->pp_announces = NULL; + /* TODO: create sockets here, and fix racy sockets table */ + if (vlc_clone (&p_sys->thread, Run, p_sd, VLC_THREAD_PRIORITY_LOW)) + { + free (p_sys); + return VLC_EGENERIC; + } return VLC_SUCCESS; } @@ -387,10 +401,19 @@ static int OpenDemux( vlc_object_t *p_this ) { p_sdp->psz_uri = NULL; } - if( p_sdp->i_media_type != 33 && p_sdp->i_media_type != 32 && - p_sdp->i_media_type != 14 ) - goto error; - + switch (p_sdp->i_media_type) + { /* Should be in sync with modules/demux/rtp.c */ + case 0: /* PCMU/8000 */ + case 8: /* PCMA/8000 */ + case 10: /* L16/44100/2 */ + case 11: /* L16/44100 */ + case 14: /* MPA/90000 */ + case 32: /* MPV/90000 */ + case 33: /* MP2/90000 */ + break; + default: + goto error; + } if( p_sdp->psz_uri == NULL ) goto error; p_demux->p_sys = (demux_sys_t *)malloc( sizeof(demux_sys_t) ); @@ -415,9 +438,11 @@ static void Close( vlc_object_t *p_this ) { services_discovery_t *p_sd = ( services_discovery_t* )p_this; services_discovery_sys_t *p_sys = p_sd->p_sys; - int i; + vlc_cancel (p_sys->thread); + vlc_join (p_sys->thread, NULL); + for( i = p_sys->i_fd-1 ; i >= 0 ; i-- ) { net_Close( p_sys->pi_fd[i] ); @@ -460,11 +485,13 @@ static void CloseDemux( vlc_object_t *p_this ) *****************************************************************************/ #define MAX_SAP_BUFFER 5000 -static void Run( services_discovery_t *p_sd ) +static void *Run( void *data ) { + services_discovery_t *p_sd = data; char *psz_addr; int i; int timeout = -1; + int canc = vlc_savecancel (); /* Braindead Winsock DNS resolver will get stuck over 2 seconds per failed * DNS queries, even if the DNS server returns an error with milliseconds. @@ -531,24 +558,21 @@ static void Run( services_discovery_t *p_sd ) psz_addr = var_CreateGetString( p_sd, "sap-addr" ); if( psz_addr && *psz_addr ) - { InitSocket( p_sd, psz_addr, SAP_PORT ); - free( psz_addr ); - } + free( psz_addr ); if( p_sd->p_sys->i_fd == 0 ) { msg_Err( p_sd, "unable to listen on any address" ); - return; + return NULL; } - vlc_object_lock( p_sd ); - /* read SAP packets */ - while( vlc_object_alive( p_sd ) ) + for (;;) { + vlc_restorecancel (canc); unsigned n = p_sd->p_sys->i_fd; - struct pollfd ufd[n+1]; + struct pollfd ufd[n]; for (unsigned i = 0; i < n; i++) { @@ -557,23 +581,9 @@ static void Run( services_discovery_t *p_sd ) ufd[i].revents = 0; } - /* Make sure we track vlc_object_signal() */ - ufd[n].fd = vlc_object_waitpipe( p_sd ); - ufd[n].events = POLLIN | POLLHUP; - ufd[n].revents = 0; - - if( ufd[n].fd == -1 ) - { - /* On windows, fd will be -1, as we can't select on a pipe()-ed - * fildes. Because we have no other solution to track that - * object is killed, we make sure the timeout won't be to long. */ - if( timeout > 1000 || timeout == -1 ) - timeout = 1000; - } - - vlc_object_unlock( p_sd ); - - if (poll (ufd, n+1, timeout) > 0) + int val = poll (ufd, n, timeout); + canc = vlc_savecancel (); + if (val > 0) { for (unsigned i = 0; i < n; i++) { @@ -583,7 +593,7 @@ static void Run( services_discovery_t *p_sd ) ssize_t i_read; i_read = net_Read (p_sd, ufd[i].fd, NULL, p_buffer, - MAX_SAP_BUFFER, VLC_FALSE); + MAX_SAP_BUFFER, false); if (i_read < 0) msg_Warn (p_sd, "receive error: %m"); if (i_read > 6) @@ -630,10 +640,8 @@ static void Run( services_discovery_t *p_sd ) timeout = -1; /* We can safely poll indefinitly. */ else if( timeout < 200 ) timeout = 200; /* Don't wakeup too fast. */ - - vlc_object_lock( p_sd ); } - vlc_object_unlock( p_sd ); + assert (0); } /********************************************************************** @@ -646,7 +654,6 @@ static int Demux( demux_t *p_demux ) input_thread_t *p_input; input_item_t *p_parent_input; - playlist_t *p_playlist = pl_Yield( p_demux ); p_input = (input_thread_t *)vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT ); assert( p_input ); @@ -656,6 +663,8 @@ static int Demux( demux_t *p_demux ) return VLC_EGENERIC; } + /* This item hasn't been held by input_GetItem + * don't release it */ p_parent_input = input_GetItem( p_input ); input_item_SetURI( p_parent_input, p_sdp->psz_uri ); @@ -665,22 +674,13 @@ static int Demux( demux_t *p_demux ) p_parent_input->i_type = ITEM_TYPE_NET; - if( p_playlist->status.p_item && - p_playlist->status.p_item->p_input == p_parent_input ) - { - playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE, - p_playlist->status.p_node, p_playlist->status.p_item ); - } - vlc_mutex_unlock( &p_parent_input->lock ); - vlc_object_release( p_input ); - vlc_object_release( p_playlist ); - return VLC_SUCCESS; } static int Control( demux_t *p_demux, int i_query, va_list args ) { + VLC_UNUSED(p_demux); VLC_UNUSED(i_query); VLC_UNUSED(args); return VLC_EGENERIC; } @@ -708,8 +708,8 @@ static int ParseSAP( services_discovery_t *p_sd, const uint8_t *buf, if ((flags >> 5) != 1) return VLC_EGENERIC; - vlc_bool_t b_ipv6 = (flags & 0x10) != 0; - vlc_bool_t b_need_delete = (flags & 0x04) != 0; + bool b_ipv6 = (flags & 0x10) != 0; + bool b_need_delete = (flags & 0x04) != 0; if (flags & 0x02) { @@ -717,7 +717,7 @@ static int ParseSAP( services_discovery_t *p_sd, const uint8_t *buf, return VLC_EGENERIC; } - vlc_bool_t b_compressed = (flags & 0x01) != 0; + bool b_compressed = (flags & 0x01) != 0; uint16_t i_hash = U16_AT (buf + 2); @@ -793,14 +793,18 @@ static int ParseSAP( services_discovery_t *p_sd, const uint8_t *buf, if( ( p_sdp->i_media_type != 14 && p_sdp->i_media_type != 32 && p_sdp->i_media_type != 33) - || p_sd->p_sys->b_parse == VLC_FALSE ) + || p_sd->p_sys->b_parse == false ) { free( p_sdp->psz_uri ); if (asprintf( &p_sdp->psz_uri, "sdp://%s", p_sdp->psz_sdp ) == -1) p_sdp->psz_uri = NULL; } - if( p_sdp->psz_uri == NULL ) return VLC_EGENERIC; + if( p_sdp->psz_uri == NULL ) + { + FreeSDP( p_sdp ); + return VLC_EGENERIC; + } for( i = 0 ; i< p_sd->p_sys->i_announces ; i++ ) { @@ -826,8 +830,9 @@ static int ParseSAP( services_discovery_t *p_sd, const uint8_t *buf, 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(); + mtime_t now = mdate(); + p_announce->i_period = (p_announce->i_period + (now - p_announce->i_last)) / 2; + p_announce->i_last = now; } FreeSDP( p_sdp ); p_sdp = NULL; return VLC_SUCCESS; @@ -859,12 +864,12 @@ sap_announce_t *CreateAnnounce( services_discovery_t *p_sd, uint16_t i_hash, p_sap->i_hash = i_hash; p_sap->p_sdp = p_sdp; - /* Create the actual playlist item here */ - p_input = input_ItemNewWithType( VLC_OBJECT(p_sd), + /* Released in RemoveAnnounce */ + p_input = input_item_NewWithType( VLC_OBJECT(p_sd), p_sap->p_sdp->psz_uri, p_sdp->psz_sessionname, 0, NULL, -1, ITEM_TYPE_NET ); - p_sap->i_input_id = p_input->i_id; + p_sap->p_item = p_input; if( !p_input ) { free( p_sap ); @@ -872,17 +877,16 @@ sap_announce_t *CreateAnnounce( services_discovery_t *p_sd, uint16_t i_hash, } if( p_sys->b_timeshift ) - input_ItemAddOption( p_input, ":access-filter=timeshift" ); + input_item_AddOption( p_input, ":access-filter=timeshift" ); psz_value = GetAttribute( p_sap->p_sdp->pp_attributes, p_sap->p_sdp->i_attributes, "tool" ); if( psz_value != NULL ) { - input_ItemAddInfo( p_input, _("Session"), _("Tool"), "%s", - psz_value ); + input_item_AddInfo( p_input, _("Session"), _("Tool"), "%s", psz_value ); } if( strcmp( p_sdp->username, "-" ) ) { - input_ItemAddInfo( p_input, _("Session"), _("User"), "%s", + input_item_AddInfo( p_input, _("Session"), _("User"), "%s", p_sdp->username ); } @@ -895,7 +899,7 @@ sap_announce_t *CreateAnnounce( services_discovery_t *p_sd, uint16_t i_hash, services_discovery_AddItem( p_sd, p_input, psz_value /* category name */ ); TAB_APPEND( p_sys->i_announces, p_sys->pp_announces, p_sap ); - vlc_gc_decref( p_input ); + return p_sap; } @@ -964,15 +968,19 @@ static int ParseConnection( vlc_object_t *p_obj, sdp_t *p_sdp ) if (subtype == NULL) { msg_Dbg (p_obj, "missing SDP media subtype: %s", sdp_proto); - p_sdp->i_media_type = 0; + free (sdp_proto); + return VLC_EGENERIC; } else { *subtype++ = '\0'; - p_sdp->i_media_type = atoi (subtype); + /* FIXME: check for multiple payload types in RTP/AVP case. + * FIXME: check for "mpeg" subtype in raw udp case. */ + if (!strcasecmp (sdp_proto, "udp")) + p_sdp->i_media_type = 33; + else + p_sdp->i_media_type = atoi (subtype); } - if (p_sdp->i_media_type == 0) - p_sdp->i_media_type = 33; /* RTP protocol, nul, VLC shortcut, nul, flags byte as follow: * 0x1: Connection-Oriented media. */ @@ -1212,7 +1220,7 @@ static sdp_t *ParseSDP (vlc_object_t *p_obj, const char *psz_sdp) goto error; } - if ((sscanf (data, "%63s "I64Fu" "I64Fu" IN IP%u %1023s", + if ((sscanf (data, "%63s %"PRIu64" %"PRIu64" IN IP%u %1023s", p_sdp->username, &p_sdp->session_id, &p_sdp->session_version, &p_sdp->orig_ip_version, p_sdp->orig_host) != 5) @@ -1238,9 +1246,9 @@ static sdp_t *ParseSDP (vlc_object_t *p_obj, const char *psz_sdp) } assert (p_sdp->psz_sessionname == NULL); // no memleak here p_sdp->psz_sessionname = strdup (data); - EnsureUTF8 (p_sdp->psz_sessionname); if (p_sdp->psz_sessionname == NULL) goto error; + EnsureUTF8 (p_sdp->psz_sessionname); break; } @@ -1513,8 +1521,12 @@ static int RemoveAnnounce( services_discovery_t *p_sd, p_announce->p_sdp = NULL; } - if( p_announce->i_input_id > -1 ) - playlist_DeleteFromInput( pl_Get(p_sd), p_announce->i_input_id, VLC_FALSE ); + if( p_announce->p_item ) + { + services_discovery_RemoveItem( p_sd, p_announce->p_item ); + vlc_gc_decref( p_announce->p_item ); + p_announce->p_item = NULL; + } for( i = 0; i< p_sd->p_sys->i_announces; i++) { @@ -1531,7 +1543,7 @@ static int RemoveAnnounce( services_discovery_t *p_sd, return VLC_SUCCESS; } -static vlc_bool_t IsSameSession( sdp_t *p_sdp1, sdp_t *p_sdp2 ) +static bool IsSameSession( sdp_t *p_sdp1, sdp_t *p_sdp2 ) { /* A session is identified by * - username, @@ -1544,9 +1556,9 @@ static vlc_bool_t IsSameSession( sdp_t *p_sdp1, sdp_t *p_sdp2 ) || (p_sdp1->session_id != p_sdp2->session_id) || (p_sdp1->orig_ip_version != p_sdp2->orig_ip_version) || strcmp (p_sdp1->orig_host, p_sdp2->orig_host)) - return VLC_FALSE; + return false; - return VLC_TRUE; + return true; }