⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sap.c

📁 uclinux 下的vlc播放器源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 *****************************************************************************/#define MAX_SAP_BUFFER 5000static void Run( services_discovery_t *p_sd ){    char *psz_addr;    int i;    /* Braindead Winsock DNS resolver will get stuck over 2 seconds per failed     * DNS queries, even if the DNS server returns an error with milliseconds.     * You don't want to know why the bug (as of XP SP2) wasn't fixed since     * Winsock 1.1 from Windows 95, if not Windows 3.1.     * Anyway, to avoid a 30 seconds delay for failed IPv6 socket creation,     * we have to open sockets in Run() rather than Open(). */    if( var_CreateGetInteger( p_sd, "sap-ipv4" ) )    {        InitSocket( p_sd, SAP_V4_GLOBAL_ADDRESS, SAP_PORT );        InitSocket( p_sd, SAP_V4_ORG_ADDRESS, SAP_PORT );        InitSocket( p_sd, SAP_V4_LOCAL_ADDRESS, SAP_PORT );        InitSocket( p_sd, SAP_V4_LINK_ADDRESS, SAP_PORT );    }    if( var_CreateGetInteger( p_sd, "sap-ipv6" ) )    {        char psz_address[] = SAP_V6_1"0"SAP_V6_2;        const char *c_scope;        for( c_scope = ipv6_scopes; *c_scope; c_scope++ )        {            psz_address[sizeof(SAP_V6_1) - 1] = *c_scope;            InitSocket( p_sd, psz_address, SAP_PORT );        }    }    psz_addr = var_CreateGetString( p_sd, "sap-addr" );    if( psz_addr && *psz_addr )    {        InitSocket( p_sd, psz_addr, SAP_PORT );        free( psz_addr );    }    if( p_sd->p_sys->i_fd == 0 )    {        msg_Err( p_sd, "unable to listen on any address" );        return;    }    /* read SAP packets */    while( !p_sd->b_die )    {        int i_read;        uint8_t p_buffer[MAX_SAP_BUFFER+1];        i_read = net_Select( p_sd, p_sd->p_sys->pi_fd, NULL,                             p_sd->p_sys->i_fd, p_buffer,                             MAX_SAP_BUFFER, 500000 );        /* 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 )            {                RemoveAnnounce( p_sd, p_sd->p_sys->pp_announces[i] );            }        }        /* Minimum length is > 6 */        if( i_read <= 6 )        {            if( i_read < 0 )            {                msg_Warn( p_sd, "socket read error" );            }            continue;        }        p_buffer[i_read] = '\0';        /* Parse the packet */        ParseSAP( p_sd, p_buffer, i_read );    }}/********************************************************************** * Demux: reads and demuxes data packets * Return -1 if error, 0 if EOF, 1 else **********************************************************************/static int Demux( demux_t *p_demux ){    sdp_t *p_sdp = p_demux->p_sys->p_sdp;    playlist_t *p_playlist;    input_thread_t *p_input;    input_item_t *p_parent_input;    p_playlist = (playlist_t *)vlc_object_find( p_demux, VLC_OBJECT_PLAYLIST,                                               FIND_ANYWHERE );    if( !p_playlist )    {        msg_Err( p_demux, "playlist could not be found" );        return VLC_EGENERIC;    }    p_input = (input_thread_t *)vlc_object_find( p_demux, VLC_OBJECT_INPUT,                                               FIND_PARENT );    if( !p_input )    {        msg_Err( p_demux, "parent input could not be found" );        return VLC_EGENERIC;    }    p_parent_input = p_input->input.p_item;    vlc_mutex_lock( &p_parent_input->lock );    FREE( p_parent_input->psz_uri );    p_parent_input->psz_uri = strdup( p_sdp->psz_uri );    FREE( p_parent_input->psz_name );    p_parent_input->psz_name = strdup( EnsureUTF8( p_sdp->psz_sessionname ) );    p_parent_input->i_type = ITEM_TYPE_NET;    if( p_playlist->status.p_item &&             &p_playlist->status.p_item->input == p_parent_input )    {        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,                          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 ){    return VLC_EGENERIC;}/************************************************************** * Local functions **************************************************************//* i_read is at least > 6 */static int ParseSAP( services_discovery_t *p_sd, uint8_t *p_buffer, int i_read ){    int                 i_version, i_address_type, i_hash, i;    char                *psz_sdp, *psz_foo, *psz_initial_sdp, *psz_end;    uint8_t             *p_decompressed_buffer = NULL;    sdp_t               *p_sdp;    vlc_bool_t          b_compressed;    vlc_bool_t          b_need_delete = VLC_FALSE;    /* First, check the sap announce is correct */    i_version = p_buffer[0] >> 5;    if( i_version != 1 )    {       msg_Dbg( p_sd, "strange sap version %d found", i_version );    }    i_address_type = p_buffer[0] & 0x10;    if( (p_buffer[0] & 0x04) != 0 )    {        msg_Dbg( p_sd, "session deletion packet" );        b_need_delete = VLC_TRUE;    }    if( p_buffer[0] & 0x02  )    {        msg_Dbg( p_sd, "encrypted packet, unsupported" );        return VLC_EGENERIC;    }    b_compressed = p_buffer[0] & 0x01;    i_hash = ( p_buffer[2] << 8 ) + p_buffer[3];    if( p_sd->p_sys->b_strict && i_hash == 0 )    {        msg_Dbg( p_sd, "strict mode, discarding announce with null id hash");        return VLC_EGENERIC;    }    psz_sdp  = (char *)p_buffer + 4;    psz_initial_sdp = psz_sdp;    if( i_address_type == 0 ) /* ipv4 source address */    {        psz_sdp += 4;        if( i_read <= 9 )        {            msg_Warn( p_sd, "too short SAP packet" );            return VLC_EGENERIC;        }    }    else /* ipv6 source address */    {        psz_sdp += 16;        if( i_read <= 21 )        {            msg_Warn( p_sd, "too short SAP packet" );            return VLC_EGENERIC;        }    }    if( b_compressed )    {#ifdef HAVE_ZLIB_H        int      i_decompressed_size;        i_decompressed_size = Decompress( (uint8_t *)psz_sdp,                   &p_decompressed_buffer, i_read - ( psz_sdp - (char *)p_buffer ) );        if( i_decompressed_size > 0 &&                 i_decompressed_size < ( MAX_SAP_BUFFER - 20 ) )        {            memcpy( psz_sdp, p_decompressed_buffer, i_decompressed_size );            psz_sdp[i_decompressed_size] = '\0';            psz_end = psz_sdp + i_decompressed_size;            FREE( p_decompressed_buffer );        }        else        {            msg_Warn( p_sd, "error in decompression of sap packet" );            FREE( p_decompressed_buffer );            return VLC_EGENERIC;        }#else        msg_Warn( p_sd, "ignoring compressed sap packet" );        return VLC_EGENERIC;#endif    }    else        psz_end = ((const char *)p_buffer) + i_read;    /* Add the size of authentification info */    if( i_read < p_buffer[1] + (psz_sdp - psz_initial_sdp ) )    {        msg_Warn( p_sd, "too short SAP packet");        return VLC_EGENERIC;    }    psz_sdp += p_buffer[1];    psz_foo = psz_sdp;    /* Skip payload type */    /* Handle announces without \0 between SAP and SDP */    while( *psz_sdp != '\0' && ( psz_sdp[0] != 'v' && psz_sdp[1] != '=' ) )    {        if( psz_sdp - psz_initial_sdp >= i_read - 5 )        {            msg_Warn( p_sd, "empty SDP ?");        }        psz_sdp++;    }    if( *psz_sdp == '\0' )    {        psz_sdp++;    }    if( ( psz_sdp != psz_foo ) && strcasecmp( psz_foo, "application/sdp" ) )    {        msg_Dbg( p_sd, "unhandled content type: %s", psz_foo );    }    if( psz_sdp >= psz_end )    {        msg_Warn( p_sd, "package without content" );        return VLC_EGENERIC;    }    /* Parse SDP info */    p_sdp = ParseSDP( VLC_OBJECT(p_sd), psz_sdp );    if( p_sdp == NULL )    {        return VLC_EGENERIC;    }    /* Decide whether we should add a playlist item for this SDP */    /* Parse connection information (c= & m= ) */    if( ParseConnection( VLC_OBJECT(p_sd), p_sdp ) )    {        p_sdp->psz_uri = NULL;    }    /* Multi-media or no-parse -> pass to LIVE.COM */    if( p_sdp->i_media > 1 || ( 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 )    {        if( p_sdp->psz_uri ) free( p_sdp->psz_uri );        asprintf( &p_sdp->psz_uri, "sdp://%s", p_sdp->psz_sdp );    }    if( p_sdp->psz_uri == NULL ) return VLC_EGENERIC;    for( i = 0 ; i< p_sd->p_sys->i_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( b_need_delete )            {                RemoveAnnounce( p_sd, p_sd->p_sys->pp_announces[i]);            }            else            {                p_sd->p_sys->pp_announces[i]->i_last = mdate();            }            FreeSDP( p_sdp ); p_sdp = NULL;            return VLC_SUCCESS;        }    }    /* Add item */    if( p_sdp->i_media > 1 )    {        msg_Dbg( p_sd, "passing to liveMedia" );    }    CreateAnnounce( p_sd, i_hash, p_sdp );    return VLC_SUCCESS;}sap_announce_t *CreateAnnounce( services_discovery_t *p_sd, uint16_t i_hash,                                sdp_t *p_sdp ){    playlist_item_t     *p_item, *p_child;    char *psz_value;    sap_announce_t *p_sap = (sap_announce_t *)malloc(                                        sizeof(sap_announce_t ) );    services_discovery_sys_t *p_sys;    if( p_sap == NULL )        return NULL;    p_sys = p_sd->p_sys;    EnsureUTF8( p_sdp->psz_sessionname );    p_sap->i_last = mdate();    p_sap->i_hash = i_hash;    p_sap->p_sdp = p_sdp;    p_sap->i_item_id = -1;    /* Create the actual playlist item here */    p_item = playlist_ItemNew( p_sd, p_sap->p_sdp->psz_uri, p_sdp->psz_sessionname );    if( !p_item )    {        free( p_sap );        return NULL;    }    if( p_sys->b_timeshift )        playlist_ItemAddOption( p_item, ":access-filter=timeshift" );    psz_value = GetAttribute( p_sap->p_sdp, "tool" );    if( psz_value != NULL )    {        vlc_input_item_AddInfo( &p_item->input, _("Session"),                                _("Tool"), psz_value );    }    if( strcmp( p_sdp->psz_username, "-" ) )    {        vlc_input_item_AddInfo( &p_item->input, _("Session"),                                _("User"), p_sdp->psz_username );    }    psz_value = GetAttribute( p_sap->p_sdp, "x-plgroup" );    if( psz_value == NULL )    {        psz_value = GetAttribute( p_sap->p_sdp, "plgroup" );    }    /* Find or Create the group playlist non-playable item */    if( psz_value != NULL )    {        EnsureUTF8( psz_value );        p_child = playlist_ChildSearchName( p_sys->p_node, psz_value );        if( p_child == NULL )        {            p_child = playlist_NodeCreate( p_sys->p_playlist,                                           VIEW_CATEGORY, psz_value,                                           p_sys->p_node );            p_child->i_flags &= ~PLAYLIST_SKIP_FLAG;        }    }    else    {        p_child = p_sys->p_node;    }    p_item->i_flags &= ~PLAYLIST_SKIP_FLAG;    p_item->i_flags &= ~PLAYLIST_SAVE_FLAG;    playlist_NodeAddItem( p_sys->p_playlist, p_item, VIEW_CATEGORY, p_child,                          PLAYLIST_APPEND, PLAYLIST_END );    p_sap->i_item_id = p_item->input.i_id;    TAB_APPEND( p_sys->i_announces, p_sys->pp_announces, p_sap );    return p_sap;}static char *GetAttribute( sdp_t *p_sdp, const char *psz_search ){    int i;    for( i = 0 ; i< p_sdp->i_attributes; i++ )    {        if( !strncmp( p_sdp->pp_attributes[i]->psz_field, psz_search,                      strlen( p_sdp->pp_attributes[i]->psz_field ) ) )        {            return p_sdp->pp_attributes[i]->psz_value;        }    }    return NULL;}/* Fill p_sdp->psz_uri */static int ParseConnection( vlc_object_t *p_obj, sdp_t *p_sdp ){    char *psz_eof = NULL;    char *psz_parse = NULL;    char *psz_uri = NULL;    char *psz_proto = NULL;    char psz_source[258] = "";    int i_port = 0;    /* Parse c= field */    if( p_sdp->psz_connection )    {        psz_parse = p_sdp->psz_connection;        psz_eof = strchr( psz_parse, ' ' );        if( psz_eof )        {            *psz_eof = '\0';            psz_parse = psz_eof + 1;        }        else        {            msg_Warn( p_obj, "unable to parse c field (1)");            return VLC_EGENERIC;        }        psz_eof = strchr( psz_parse, ' ' );        if( psz_eof )        {            *psz_eof = '\0';            if( !strncmp( psz_parse, "IP4", 3 ) )            {                p_sdp->i_in = 4;            }            else if( !strncmp( psz_parse, "IP6", 3 ) )            {                p_sdp->i_in = 6;            }            else            {                p_sdp->i_in = 0;            }            psz_parse = psz_eof + 1;        }        else        {            msg_Warn( p_obj, "unable to parse c field (2)");            return VLC_EGENERIC;        }        psz_eof = strchr( psz_parse, '/' );        if( psz_eof )        {            *psz_eof = '\0';

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -