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

📄 sap.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************** * CloseDemux: Close the demuxer *****************************************************************************/static void CloseDemux( vlc_object_t *p_this ){}/***************************************************************************** * Run: main SAP thread ***************************************************************************** * Listens to SAP packets, and sends them to packet_handle *****************************************************************************/#define MAX_SAP_BUFFER 5000static void Run( services_discovery_t *p_sd ){    int i;    /* 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 )            {                struct sap_announce_t *p_announce;                p_announce = p_sd->p_sys->pp_announces[i];                /* Remove the playlist item */                playlist_LockDelete( p_sd->p_sys->p_playlist,                                     p_announce->i_item_id );                /* Remove the sap_announce from the array */                REMOVE_ELEM( p_sd->p_sys->pp_announces,                           p_sd->p_sys->i_announces, i );                free( p_announce );            }        }        /* 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;    p_playlist = (playlist_t *)vlc_object_find( p_demux, VLC_OBJECT_PLAYLIST,                                               FIND_ANYWHERE );    p_playlist->status.p_item->i_flags |= PLAYLIST_DEL_FLAG;    playlist_Add( p_playlist, p_sdp->psz_uri, p_sdp->psz_sessionname,                 PLAYLIST_APPEND, PLAYLIST_END );    vlc_object_release( p_playlist );    if( p_sdp ) FreeSDP( p_sdp );    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;    uint8_t             *psz_sdp;    uint8_t             *psz_initial_sdp;    sdp_t               *p_sdp;    vlc_bool_t          b_compressed;    vlc_bool_t          b_need_delete = VLC_FALSE;#ifdef HAVE_ZLIB_H    int                 i_decompressed_size;    uint8_t             *p_decompressed_buffer;#endif    uint8_t             *psz_foo;    /* 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] & 0x08) != 0 )    {        msg_Dbg( p_sd, "reserved bit incorrectly set" );        return VLC_EGENERIC;    }    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  = &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\n" );            return VLC_EGENERIC;        }    }    else /* ipv6 source address */    {        psz_sdp += 16;        if( i_read <= 21 )        {            msg_Warn( p_sd, "too short SAP packet\n" );            return VLC_EGENERIC;        }    }    if( b_compressed )    {#ifdef HAVE_ZLIB_H        i_decompressed_size = Decompress( psz_sdp,                   &p_decompressed_buffer,i_read - ( psz_sdp - p_buffer ) );        if( i_decompressed_size > 0 && i_decompressed_size < MAX_SAP_BUFFER )        {            memcpy( psz_sdp, p_decompressed_buffer, i_decompressed_size );            psz_sdp[i_decompressed_size] = '\0';            free( p_decompressed_buffer );        }#else        msg_Warn( p_sd, "Ignoring compressed sap packet" );        return VLC_EGENERIC;#endif    }    /* 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\n");        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 -p_buffer >= i_read )    {        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]);                return VLC_SUCCESS;            }            else            {                p_sd->p_sys->pp_announces[i]->i_last = mdate();                FreeSDP( p_sdp );                return VLC_SUCCESS;            }        }    }    /* Add item */    if( p_sdp->i_media > 1 )    {        msg_Dbg( p_sd, "passing to LIVE.COM" );    }    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 ) );    psz_value = convert_from_utf8( p_sd, p_sdp->psz_sessionname );    if( p_sap == NULL || psz_value == NULL )    {        FREE( p_sap );        FREE( psz_value );        return NULL;    }    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 playlist item here */    p_item = playlist_ItemNew( p_sd, p_sap->p_sdp->psz_uri, psz_value );    free( psz_value );    if( !p_item )    {        free( p_sap );        return NULL;    }    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" );    }    if( psz_value != NULL )    {        char *psz_grp = convert_from_utf8( p_sd, psz_value );        if( psz_grp != NULL )        {            p_child = playlist_ChildSearchName( p_sd->p_sys->p_node,                                                psz_grp );            if( p_child == NULL )            {                p_child = playlist_NodeCreate( p_sd->p_sys->p_playlist,                                               VIEW_CATEGORY, psz_grp,                                               p_sd->p_sys->p_node );                p_child->i_flags =~ PLAYLIST_SKIP_FLAG;            }            free( psz_grp );        }        else        {            msg_Err( p_sd, "out of memory");            free( p_sap );            return NULL;        }    }    else    {        p_child = p_sd->p_sys->p_node;    }    p_item->i_flags &= ~PLAYLIST_SKIP_FLAG;    p_item->i_flags &= ~PLAYLIST_SAVE_FLAG;    playlist_NodeAddItem( p_sd->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_sd->p_sys->i_announces,                p_sd->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;    char *psz_parse;    char *psz_uri = NULL;    char *psz_proto = NULL;    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;        }        else        {            msg_Dbg( p_obj, "incorrect c field, %s", p_sdp->psz_connection );        }        psz_uri = strdup( psz_parse );    }    /* Parse m= field */    if( p_sdp->psz_media )    {        psz_parse = p_sdp->psz_media;        psz_eof = strchr( psz_parse, ' ' );        if( psz_eof )        {            *psz_eof = '\0';            if( strncmp( psz_parse, "audio", 5 )  &&                strncmp( psz_parse, "video",5 ) )            {                msg_Warn( p_obj, "unhandled media type -%s-", psz_parse );                FREE( psz_uri );                return VLC_EGENERIC;            }            psz_parse = psz_eof + 1;        }        else        {            msg_Warn( p_obj, "unable to parse m field (1)");            FREE( psz_uri );            return VLC_EGENERIC;        }        psz_eof = strchr( psz_parse, ' ' );        if( psz_eof )        {            *psz_eof = '\0';            /* FIXME : multiple port ! */            i_port = atoi( psz_parse );            if( i_port <= 0 || i_port >= 65536 )            {                msg_Warn( p_obj, "invalid transport port %i", i_port );            }            psz_parse = psz_eof + 1;

⌨️ 快捷键说明

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