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

📄 sap.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 4 页
字号:
        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) );    p_demux->p_sys->p_sdp = p_sdp;    p_demux->pf_control = Control;    p_demux->pf_demux = Demux;    FREENULL( psz_sdp );    return VLC_SUCCESS;error:    FREENULL( psz_sdp );    if( p_sdp ) FreeSDP( p_sdp ); p_sdp = NULL;    stream_Seek( p_demux->s, 0 );    return errval;}/***************************************************************************** * Close: *****************************************************************************/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;    for( i = p_sys->i_fd-1 ; i >= 0 ; i-- )    {        net_Close( p_sys->pi_fd[i] );    }    FREENULL( p_sys->pi_fd );#if 0    if( config_GetInt( p_sd, "sap-cache" ) )    {        CacheSave( p_sd );    }#endif    for( i = p_sys->i_announces  - 1;  i>= 0; i-- )    {        RemoveAnnounce( p_sd, p_sys->pp_announces[i] );    }    FREENULL( p_sys->pp_announces );    free( p_sys );}/***************************************************************************** * CloseDemux: Close the demuxer *****************************************************************************/static void CloseDemux( vlc_object_t *p_this ){    demux_t *p_demux = (demux_t *)p_this;    if( p_demux->p_sys )    {        if( p_demux->p_sys->p_sdp ) { FreeSDP( p_demux->p_sys->p_sdp ); p_demux->p_sys->p_sdp = NULL; }        free( p_demux->p_sys );    }}/***************************************************************************** * 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 ){    char *psz_addr;    int i;    int timeout = -1;    /* 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[NI_MAXNUMERICHOST] = "ff02::2:7ffe%";#ifndef WIN32        struct if_nameindex *l = if_nameindex ();        if (l != NULL)        {            char *ptr = strchr (psz_address, '%') + 1;            for (unsigned i = 0; l[i].if_index; i++)            {                strcpy (ptr, l[i].if_name);                InitSocket (p_sd, psz_address, SAP_PORT);            }            if_freenameindex (l);        }#else        /* this is the Winsock2 equivalant of SIOCGIFCONF on BSD stacks,           which if_nameindex uses internally anyway */        // first create a dummy socket to pin down the protocol family        SOCKET s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);        if( s != INVALID_SOCKET )        {            INTERFACE_INFO ifaces[10]; // Assume there will be no more than 10 IP interfaces            size_t len = sizeof(ifaces);            if( SOCKET_ERROR != WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0, &ifaces, len, &len, NULL, NULL) )            {                unsigned ifcount = len/sizeof(INTERFACE_INFO);                char *ptr = strchr (psz_address, '%') + 1;                for(unsigned i = 1; i<=ifcount; ++i )                {                    // append link-local zone identifier                    sprintf(ptr, "%d", i);                }            }            closesocket(s);        }#endif        *strchr (psz_address, '%') = '\0';        static const char ipv6_scopes[] = "1456789ABCDE";        for (const char *c_scope = ipv6_scopes; *c_scope; c_scope++)        {            psz_address[3] = *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( vlc_object_alive( p_sd ) )    {        unsigned n = p_sd->p_sys->i_fd;        struct pollfd ufd[n+1];        for (unsigned i = 0; i < n; i++)        {            ufd[i].fd = p_sd->p_sys->pi_fd[i];            ufd[i].events = POLLIN;            ufd[i].revents = 0;        }        /* Make sure we track vlc_object_signal() */        ufd[n].fd = vlc_object_waitpipe( p_sd );        ufd[n].events = POLLIN;        ufd[n].revents = 0;        if (poll (ufd, n+1, timeout) > 0)        {            for (unsigned i = 0; i < n; i++)            {                if (ufd[i].revents)                {                    uint8_t p_buffer[MAX_SAP_BUFFER+1];                    ssize_t i_read;                    i_read = net_Read (p_sd, ufd[i].fd, NULL, p_buffer,                                       MAX_SAP_BUFFER, false);                    if (i_read < 0)                        msg_Warn (p_sd, "receive error: %m");                    if (i_read > 6)                    {                        /* Parse the packet */                        p_buffer[i_read] = '\0';                        ParseSAP (p_sd, p_buffer, i_read);                    }                }            }        }        mtime_t now = mdate();        /* A 1 hour timeout correspong to the RFC Implicit timeout.         * This timeout is tuned in the following loop. */        timeout = 1000 * 60 * 60;        /* 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;            sap_announce_t * p_announce = p_sd->p_sys->pp_announces[i];            mtime_t i_last_period = now - 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_announce );            }            else            {                /* Compute next timeout */                if( p_announce->i_period_trust > 5 )                    timeout = min_int((3 * p_announce->i_period - i_last_period) / 1000, timeout);                timeout = min_int((i_timeout - i_last_period)/1000, timeout);            }        }        if( !p_sd->p_sys->i_announces )            timeout = -1; /* We can safely poll indefinitly. */        else if( timeout < 200 )            timeout = 200; /* Don't wakeup too fast. */    }}/********************************************************************** * 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;    input_thread_t *p_input;    input_item_t *p_parent_input;    p_input = (input_thread_t *)vlc_object_find( p_demux, VLC_OBJECT_INPUT,                                                 FIND_PARENT );    assert( p_input );    if( !p_input )    {        msg_Err( p_demux, "parent input could not be found" );        return VLC_EGENERIC;    }    /* This item hasn't been yield by input_GetItem     * don't release it */    p_parent_input = input_GetItem( p_input );    input_item_SetURI( p_parent_input, p_sdp->psz_uri );    input_item_SetName( p_parent_input, p_sdp->psz_sessionname );    vlc_mutex_lock( &p_parent_input->lock );    p_parent_input->i_type = ITEM_TYPE_NET;    vlc_mutex_unlock( &p_parent_input->lock );    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;}/************************************************************** * Local functions **************************************************************//* i_read is at least > 6 */static int ParseSAP( services_discovery_t *p_sd, const uint8_t *buf,                     size_t len ){    int i;    const char          *psz_sdp;    const uint8_t *end = buf + len;    sdp_t               *p_sdp;    assert (buf[len] == '\0');    if (len < 4)        return VLC_EGENERIC;    uint8_t flags = buf[0];    /* First, check the sap announce is correct */    if ((flags >> 5) != 1)        return VLC_EGENERIC;    bool b_ipv6 = (flags & 0x10) != 0;    bool b_need_delete = (flags & 0x04) != 0;    if (flags & 0x02)    {        msg_Dbg( p_sd, "encrypted packet, unsupported" );        return VLC_EGENERIC;    }    bool b_compressed = (flags & 0x01) != 0;    uint16_t i_hash = U16_AT (buf + 2);    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;    }    // Skips source address and auth data    buf += 4 + (b_ipv6 ? 16 : 4) + buf[1];    if (buf > end)        return VLC_EGENERIC;    uint8_t *decomp = NULL;    if( b_compressed )    {        int newsize = Decompress (buf, &decomp, end - buf);        if (newsize < 0)        {            msg_Dbg( p_sd, "decompression of SAP packet failed" );            return VLC_EGENERIC;        }        decomp = realloc (decomp, newsize + 1);        decomp[newsize] = '\0';        psz_sdp = (const char *)decomp;        len = newsize;    }    else    {        psz_sdp = (const char *)buf;        len = end - buf;    }    /* len is a strlen here here. both buf and decomp are len+1 where the 1 should be a \0 */    assert( psz_sdp[len] == '\0');    /* Skip payload type */    /* SAPv1 has implicit "application/sdp" payload type: first line is v=0 */    if (strncmp (psz_sdp, "v=0", 3))    {        size_t clen = strlen (psz_sdp) + 1;        if (strcmp (psz_sdp, "application/sdp"))        {            msg_Dbg (p_sd, "unsupported content type: %s", psz_sdp);            return VLC_EGENERIC;        }        // skips content type        if (len <= clen)            return VLC_EGENERIC;        len -= clen;        psz_sdp += clen;    }    /* Parse SDP info */    p_sdp = ParseSDP( VLC_OBJECT(p_sd), psz_sdp );    if( p_sdp == NULL )        return VLC_EGENERIC;    p_sdp->psz_sdp = psz_sdp;    /* 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_type != 14       && p_sdp->i_media_type != 32       && p_sdp->i_media_type != 33)     || 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 )    {        FreeSDP( p_sdp );        return VLC_EGENERIC;

⌨️ 快捷键说明

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