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

📄 sap.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 4 页
字号:
    }    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: we create a new announce each time the sdp changes */        if( IsSameSession( p_announce->p_sdp, p_sdp ) )        {            /* We don't support delete announcement as they can easily             * Be used to highjack an announcement by a third party.             * Intead we cleverly implement Implicit Announcement removal.             *             * if( b_need_delete )             *    RemoveAnnounce( p_sd, p_sd->p_sys->pp_announces[i]);             * else             */            if( !b_need_delete )            {                /* 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 */                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;        }    }    CreateAnnounce( p_sd, i_hash, p_sdp );    FREENULL (decomp);    return VLC_SUCCESS;}sap_announce_t *CreateAnnounce( services_discovery_t *p_sd, uint16_t i_hash,                                sdp_t *p_sdp ){    input_item_t *p_input;    const 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;    p_sap->i_last = mdate();    p_sap->i_period = 0;    p_sap->i_period_trust = 0;    p_sap->i_hash = i_hash;    p_sap->p_sdp = p_sdp;    /* 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->p_item = p_input;    if( !p_input )    {        free( p_sap );        return NULL;    }    if( p_sys->b_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_item_AddInfo( p_input, _("Session"), _("Tool"), "%s", psz_value );    }    if( strcmp( p_sdp->username, "-" ) )    {        input_item_AddInfo( p_input, _("Session"), _("User"), "%s",                           p_sdp->username );    }    /* Handle group */    if (p_sap->p_sdp->mediac >= 1)        psz_value = FindAttribute (p_sap->p_sdp, 0, "x-plgroup");    else        psz_value = GetAttribute( p_sap->p_sdp->pp_attributes, p_sap->p_sdp->i_attributes, "x-plgroup" );    services_discovery_AddItem( p_sd, p_input, psz_value /* category name */ );    TAB_APPEND( p_sys->i_announces, p_sys->pp_announces, p_sap );    return p_sap;}static const char *FindAttribute (const sdp_t *sdp, unsigned media,                                  const char *name){    /* Look for media attribute, and fallback to session */    return GetAttribute (sdp->mediav[media].pp_attributes,                         sdp->mediav[media].i_attributes, name)        ?: GetAttribute (sdp->pp_attributes, sdp->i_attributes, name);}/* Fill p_sdp->psz_uri */static int ParseConnection( vlc_object_t *p_obj, sdp_t *p_sdp ){    if (p_sdp->mediac == 0)    {        msg_Dbg (p_obj, "Ignoring SDP with no media");        return VLC_EGENERIC;    }    for (unsigned i = 1; i < p_sdp->mediac; i++)    {        if ((p_sdp->mediav[i].n_addr != p_sdp->mediav->n_addr)         || (p_sdp->mediav[i].addrlen != p_sdp->mediav->addrlen)         || memcmp (&p_sdp->mediav[i].addr, &p_sdp->mediav->addr,                    p_sdp->mediav->addrlen))        {            msg_Dbg (p_obj, "Multiple media ports not supported -> live555");            return VLC_EGENERIC;        }    }    if (p_sdp->mediav->n_addr != 1)    {        msg_Dbg (p_obj, "Layered encoding not supported -> live555");        return VLC_EGENERIC;    }    char psz_uri[1026];    const char *host;    int port;    psz_uri[0] = '[';    if (vlc_getnameinfo ((struct sockaddr *)&(p_sdp->mediav->addr),                         p_sdp->mediav->addrlen, psz_uri + 1,                         sizeof (psz_uri) - 2, &port, NI_NUMERICHOST))        return VLC_EGENERIC;    if (strchr (psz_uri + 1, ':'))    {        host = psz_uri;        strcat (psz_uri, "]");    }    else        host = psz_uri + 1;    /* Parse m= field */    char *sdp_proto = strdup (p_sdp->mediav[0].fmt);    if (sdp_proto == NULL)        return VLC_ENOMEM;    char *subtype = strchr (sdp_proto, ' ');    if (subtype == NULL)    {        msg_Dbg (p_obj, "missing SDP media subtype: %s", sdp_proto);        free (sdp_proto);        return VLC_EGENERIC;    }    else    {        *subtype++ = '\0';        /* 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);    }    /* RTP protocol, nul, VLC shortcut, nul, flags byte as follow:     * 0x1: Connection-Oriented media. */    static const char proto_match[] =        "udp\0"             "udp\0\0"        "RTP/AVP\0"         "rtp\0\0"        "UDPLite/RTP/AVP\0" "udplite\0\0"        "DCCP/RTP/AVP\0"    "dccp\0\1"        "TCP/RTP/AVP\0"     "rtptcp\0\1"        "\0";    const char *vlc_proto = NULL;    uint8_t flags = 0;    for (const char *proto = proto_match; *proto;)    {        if (strcasecmp (proto, sdp_proto) == 0)        {            vlc_proto = proto + strlen (proto) + 1;            flags = vlc_proto[strlen (vlc_proto) + 1];            break;        }        proto += strlen (proto) + 1;        proto += strlen (proto) + 2;    }    free (sdp_proto);    if (vlc_proto == NULL)    {        msg_Dbg (p_obj, "unknown SDP media protocol: %s",                 p_sdp->mediav[0].fmt);        return VLC_EGENERIC;    }    if (flags & 1)    {        /* Connection-oriented media */        const char *setup = FindAttribute (p_sdp, 0, "setup");        if (setup == NULL)            setup = "active"; /* default value */        if (strcmp (setup, "actpass") && strcmp (setup, "passive"))        {            msg_Dbg (p_obj, "unsupported COMEDIA mode: %s", setup);            return VLC_EGENERIC;        }        if (asprintf (&p_sdp->psz_uri, "%s://%s:%d", vlc_proto,                      host, port) == -1)            return VLC_ENOMEM;    }    else    {        /* Non-connected (normally multicast) media */        char psz_source[258] = "";        const char *sfilter = FindAttribute (p_sdp, 0, "source-filter");        if (sfilter != NULL)        {            char psz_source_ip[256];            unsigned ipv;            if (sscanf (sfilter, " incl IN IP%u %*s %255s ", &ipv,                        psz_source_ip) == 2)            {                /* According to RFC4570, FQDNs can be used for source-filters,                 * but -seriously- this is impractical */                switch (ipv)                {#ifdef AF_INET6                    case 6:                    {                        struct in6_addr addr;                        if ((inet_pton (AF_INET6, psz_source_ip, &addr) > 0)                        && (inet_ntop (AF_INET6, &addr, psz_source + 1,                                        sizeof (psz_source) - 2) != NULL))                        {                            psz_source[0] = '[';                            psz_source[strlen (psz_source)] = ']';                        }                        break;                    }#endif                    case 4:                    {                        struct in_addr addr;                        if ((inet_pton (AF_INET, psz_source_ip, &addr) > 0)                        && (inet_ntop (AF_INET, &addr, psz_source,                                        sizeof (psz_source)) == NULL))                            *psz_source = '\0';                        break;                    }                }            }        }        if (asprintf (&p_sdp->psz_uri, "%s://%s@%s:%i", vlc_proto, psz_source,                     host, port) == -1)            return VLC_ENOMEM;    }    return VLC_SUCCESS;}static int ParseSDPConnection (const char *str, struct sockaddr_storage *addr,                               socklen_t *addrlen, unsigned *number){    char host[60];    unsigned fam, n1, n2;    int res = sscanf (str, "IN IP%u %59[^/]/%u/%u", &fam, host, &n1, &n2);    if (res < 2)        return -1;    switch (fam)    {#ifdef AF_INET6        case 6:            addr->ss_family = AF_INET6;# ifdef HAVE_SA_LEN            addr->ss_len =# endif           *addrlen = sizeof (struct sockaddr_in6);            if (inet_pton (AF_INET6, host,                           &((struct sockaddr_in6 *)addr)->sin6_addr) <= 0)                return -1;            *number = (res >= 3) ? n1 : 1;            break;#endif        case 4:            addr->ss_family = AF_INET;# ifdef HAVE_SA_LEN            addr->ss_len =# endif           *addrlen = sizeof (struct sockaddr_in);            if (inet_pton (AF_INET, host,                           &((struct sockaddr_in *)addr)->sin_addr) <= 0)                return -1;            *number = (res >= 4) ? n2 : 1;            break;        default:            return -1;    }    return 0;}/*********************************************************************** * ParseSDP : SDP parsing * ********************************************************************* * Validate SDP and parse all fields ***********************************************************************/static sdp_t *ParseSDP (vlc_object_t *p_obj, const char *psz_sdp){    if( psz_sdp == NULL )        return NULL;    sdp_t *p_sdp = calloc (1, sizeof (*p_sdp));    if (p_sdp == NULL)        return NULL;    char expect = 'V';    struct sockaddr_storage glob_addr;    memset (&glob_addr, 0, sizeof (glob_addr));    socklen_t glob_len = 0;    unsigned glob_count = 1;    int port = 0;    /* TODO: use iconv and charset attribute instead of EnsureUTF8 */    while (*psz_sdp)    {        /* Extract one line */        char *eol = strchr (psz_sdp, '\n');        size_t linelen = eol ? (size_t)(eol - psz_sdp) : strlen (psz_sdp);        char line[linelen + 1];        memcpy (line, psz_sdp, linelen);        line[linelen] = '\0';        psz_sdp += linelen + 1;        /* Remove carriage return if present */        eol = strchr (line, '\r');        if (eol != NULL)        {            linelen = eol - line;            line[linelen] = '\0';        }        /* Validate line */        char cat = line[0], *data = line + 2;        if (!cat || (strchr ("vosiuepcbtrzkam", cat) == NULL))        {            /* MUST ignore SDP with unknown line type */            msg_Dbg (p_obj, "unknown SDP line type: 0x%02x", (int)cat);            goto error;        }        if (line[1] != '=')        {            msg_Dbg (p_obj, "invalid SDP line: %s", line);            goto error;        }        assert (linelen >= 2);        /* SDP parsing state machine         * We INTERNALLY use uppercase for session, lowercase for media         */        switch (expect)        {            /* Session description */            case 'V':                expect = 'O';                if (cat != 'v')                {                    msg_Dbg (p_obj, "missing SDP version");

⌨️ 快捷键说明

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