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

📄 udp.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
#endif/** * IP-agnostic multicast join, * with fallback to old APIs, and fallback from SSM to ASM. */static intnet_SourceSubscribe (vlc_object_t *obj, int fd,                     const struct sockaddr *src, socklen_t srclen,                     const struct sockaddr *grp, socklen_t grplen){    int level, iid = 0;    char *iface = var_CreateGetNonEmptyString (obj, "miface");    if (iface != NULL)    {        iid = if_nametoindex (iface);        if (iid == 0)        {            msg_Err (obj, "invalid multicast interface: %s", iface);            free (iface);            return -1;        }        free (iface);    }    switch (grp->sa_family)    {#ifdef AF_INET6        case AF_INET6:            level = SOL_IPV6;            if (((const struct sockaddr_in6 *)grp)->sin6_scope_id)                iid = ((const struct sockaddr_in6 *)grp)->sin6_scope_id;            break;#endif        case AF_INET:            level = SOL_IP;            break;        default:            errno = EAFNOSUPPORT;            return -1;    }    if (src != NULL)        switch (src->sa_family)        {#ifdef AF_INET6            case AF_INET6:                if (memcmp (&((const struct sockaddr_in6 *)src)->sin6_addr,                            &in6addr_any, sizeof (in6addr_any)) == 0)                    src = NULL;            break;#endif            case AF_INET:                if (((const struct sockaddr_in *)src)->sin_addr.s_addr                     == INADDR_ANY)                    src = NULL;                break;        }    /* Agnostic ASM/SSM multicast join */#ifdef MCAST_JOIN_SOURCE_GROUP    union    {        struct group_req gr;        struct group_source_req gsr;    } opt;    socklen_t optlen;    memset (&opt, 0, sizeof (opt));    if (src != NULL)    {        if ((grplen > sizeof (opt.gsr.gsr_group))         || (srclen > sizeof (opt.gsr.gsr_source)))            return -1;        opt.gsr.gsr_interface = iid;        memcpy (&opt.gsr.gsr_source, src, srclen);        memcpy (&opt.gsr.gsr_group,  grp, grplen);        optlen = sizeof (opt.gsr);    }    else    {        if (grplen > sizeof (opt.gr.gr_group))            return -1;        opt.gr.gr_interface = iid;        memcpy (&opt.gr.gr_group, grp, grplen);        optlen = sizeof (opt.gr);    }    msg_Dbg (obj, "Multicast %sgroup join request", src ? "source " : "");    if (setsockopt (fd, level,                    src ? MCAST_JOIN_SOURCE_GROUP : MCAST_JOIN_GROUP,                    (void *)&opt, optlen) == 0)        return 0;#endif    /* Fallback to IPv-specific APIs */    if ((src != NULL) && (src->sa_family != grp->sa_family))        return -1;    switch (grp->sa_family)    {        case AF_INET:            if ((grplen < sizeof (struct sockaddr_in))             || ((src != NULL) && (srclen < sizeof (struct sockaddr_in))))                return -1;            if (net_IPv4Join (obj, fd, (const struct sockaddr_in *)src,                              (const struct sockaddr_in *)grp) == 0)                return 0;            break;#ifdef AF_INET6        case AF_INET6:            if ((grplen < sizeof (struct sockaddr_in6))             || ((src != NULL) && (srclen < sizeof (struct sockaddr_in6))))                return -1;            /* IPv6-specific SSM API does not exist. So if we're here             * it means IPv6 SSM is not supported on this OS and we             * directly fallback to ASM */            if (net_IPv6Join (obj, fd, (const struct sockaddr_in6 *)grp) == 0)                return 0;            break;#endif    }    msg_Err (obj, "Multicast group join error (%m)");    if (src != NULL)    {        msg_Warn (obj, "Trying ASM instead of SSM...");        return net_Subscribe (obj, fd, grp, grplen);    }    msg_Err (obj, "Multicast not supported");    return -1;}int net_Subscribe (vlc_object_t *obj, int fd,                   const struct sockaddr *addr, socklen_t addrlen){    return net_SourceSubscribe (obj, fd, NULL, 0, addr, addrlen);}static int net_SetDSCP( int fd, uint8_t dscp ){    struct sockaddr_storage addr;    if( getsockname( fd, (struct sockaddr *)&addr, &(socklen_t){ sizeof (addr) }) )        return -1;    int level, cmd;    switch( addr.ss_family )    {#ifdef IPV6_TCLASS        case AF_INET6:            level = SOL_IPV6;            cmd = IPV6_TCLASS;            break;#endif        case AF_INET:            level = SOL_IP;            cmd = IP_TOS;            break;        default:#ifdef ENOPROTOOPT            errno = ENOPROTOOPT;#endif            return -1;    }    return setsockopt( fd, level, cmd, &(int){ dscp }, sizeof (int));}/***************************************************************************** * __net_ConnectDgram: ***************************************************************************** * Open a datagram socket to send data to a defined destination, with an * optional hop limit. *****************************************************************************/int __net_ConnectDgram( vlc_object_t *p_this, const char *psz_host, int i_port,                        int i_hlim, int proto ){    struct addrinfo hints, *res, *ptr;    int             i_val, i_handle = -1;    bool      b_unreach = false;    if( i_hlim < 1 )        i_hlim = var_CreateGetInteger( p_this, "ttl" );    memset( &hints, 0, sizeof( hints ) );    hints.ai_socktype = SOCK_DGRAM;    msg_Dbg( p_this, "net: connecting to [%s]:%d", psz_host, i_port );    i_val = vlc_getaddrinfo( p_this, psz_host, i_port, &hints, &res );    if( i_val )    {        msg_Err( p_this, "cannot resolve [%s]:%d : %s", psz_host, i_port,                 vlc_gai_strerror( i_val ) );        return -1;    }    for( ptr = res; ptr != NULL; ptr = ptr->ai_next )    {        char *str;        int fd = net_Socket (p_this, ptr->ai_family, ptr->ai_socktype,                             proto ?: ptr->ai_protocol);        if (fd == -1)            continue;#if !defined( SYS_BEOS )        /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s)        * to avoid packet loss caused by scheduling problems */        setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &(int){ 0x80000 }, sizeof (int));        setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &(int){ 0x80000 }, sizeof (int));        /* Allow broadcast sending */        setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &(int){ 1 }, sizeof (int));#endif        if( i_hlim > 0 )            net_SetMcastHopLimit( p_this, fd, ptr->ai_family, i_hlim );        str = var_CreateGetNonEmptyString (p_this, "miface");        if (str != NULL)        {            net_SetMcastOut (p_this, fd, ptr->ai_family, str, NULL);            free (str);        }        str = var_CreateGetNonEmptyString (p_this, "miface-addr");        if (str != NULL)        {            net_SetMcastOut (p_this, fd, ptr->ai_family, NULL, str);            free (str);        }        net_SetDSCP (fd, var_CreateGetInteger (p_this, "dscp"));        if( connect( fd, ptr->ai_addr, ptr->ai_addrlen ) == 0 )        {            /* success */            i_handle = fd;            break;        }#if defined( WIN32 ) || defined( UNDER_CE )        if( WSAGetLastError () == WSAENETUNREACH )#else        if( errno == ENETUNREACH )#endif            b_unreach = true;        else        {            msg_Warn( p_this, "%s port %d : %m", psz_host, i_port);            net_Close( fd );            continue;        }    }    vlc_freeaddrinfo( res );    if( i_handle == -1 )    {        if( b_unreach )            msg_Err( p_this, "Host %s port %d is unreachable", psz_host,                     i_port );        return -1;    }    return i_handle;}/***************************************************************************** * __net_OpenDgram: ***************************************************************************** * OpenDgram a datagram socket and return a handle *****************************************************************************/int __net_OpenDgram( vlc_object_t *obj, const char *psz_bind, int i_bind,                     const char *psz_server, int i_server,                     int family, int protocol ){    if ((psz_server == NULL) || (psz_server[0] == '\0'))        return net_ListenSingle (obj, psz_bind, i_bind, family, protocol);    msg_Dbg (obj, "net: connecting to [%s]:%d from [%s]:%d",             psz_server, i_server, psz_bind, i_bind);    struct addrinfo hints, *loc, *rem;    int val;    memset (&hints, 0, sizeof (hints));    hints.ai_family = family;    hints.ai_socktype = SOCK_DGRAM;    val = vlc_getaddrinfo (obj, psz_server, i_server, &hints, &rem);    if (val)    {        msg_Err (obj, "cannot resolve %s port %d : %s", psz_bind, i_bind,                 vlc_gai_strerror (val));        return -1;    }    hints.ai_flags = AI_PASSIVE;    val = vlc_getaddrinfo (obj, psz_bind, i_bind, &hints, &loc);    if (val)    {        msg_Err (obj, "cannot resolve %s port %d : %s", psz_bind, i_bind,                 vlc_gai_strerror (val));        vlc_freeaddrinfo (rem);        return -1;    }    for (struct addrinfo *ptr = loc; ptr != NULL; ptr = ptr->ai_next)    {        int fd = net_Socket (obj, ptr->ai_family, ptr->ai_socktype,                             protocol ?: ptr->ai_protocol);        if (fd == -1)            continue; // usually, address family not supported        fd = net_SetupDgramSocket( obj, fd, ptr );        if( fd == -1 )            continue;        val = -1;        for (struct addrinfo *ptr2 = rem; ptr2 != NULL; ptr2 = ptr2->ai_next)        {            if ((ptr2->ai_family != ptr->ai_family)             || (ptr2->ai_socktype != ptr->ai_socktype)             || (ptr2->ai_protocol != ptr->ai_protocol))                continue;            if (net_SockAddrIsMulticast (ptr->ai_addr, ptr->ai_addrlen)              ? net_SourceSubscribe (obj, fd,                                     ptr2->ai_addr, ptr2->ai_addrlen,                                     ptr->ai_addr, ptr->ai_addrlen)              : connect (fd, ptr2->ai_addr, ptr2->ai_addrlen))            {                msg_Err (obj, "cannot connect to %s port %d: %m",                         psz_server, i_server);                continue;            }            val = fd;            break;        }        if (val != -1)            break;        net_Close (fd);    }    vlc_freeaddrinfo (rem);    vlc_freeaddrinfo (loc);    return val;}/** * net_SetCSCov: * Sets the send and receive checksum coverage of a socket: * @param fd socket * @param sendcov payload coverage of sent packets (bytes), -1 for full * @param recvcov minimum payload coverage of received packets, -1 for full */int net_SetCSCov (int fd, int sendcov, int recvcov){    int type;    if (getsockopt (fd, SOL_SOCKET, SO_TYPE,                    &type, &(socklen_t){ sizeof (type) }))        return VLC_EGENERIC;    switch (type)    {#ifdef UDPLITE_RECV_CSCOV        case SOCK_DGRAM: /* UDP-Lite */            if (sendcov == -1)                sendcov = 0;            else                sendcov += 8; /* partial */            if (setsockopt (fd, SOL_UDPLITE, UDPLITE_SEND_CSCOV, &sendcov,                            sizeof (sendcov)))                return VLC_EGENERIC;            if (recvcov == -1)                recvcov = 0;            else                recvcov += 8;            if (setsockopt (fd, SOL_UDPLITE, UDPLITE_RECV_CSCOV,                            &recvcov, sizeof (recvcov)))                return VLC_EGENERIC;            return VLC_SUCCESS;#endif#ifdef DCCP_SOCKOPT_SEND_CSCOV        case SOCK_DCCP: /* DCCP and its ill-named socket type */            if ((sendcov == -1) || (sendcov > 56))                sendcov = 0;            else                sendcov = (sendcov + 3) / 4;            if (setsockopt (fd, SOL_DCCP, DCCP_SOCKOPT_SEND_CSCOV,                            &sendcov, sizeof (sendcov)))                return VLC_EGENERIC;            if ((recvcov == -1) || (recvcov > 56))                recvcov = 0;            else                recvcov = (recvcov + 3) / 4;            if (setsockopt (fd, SOL_DCCP, DCCP_SOCKOPT_RECV_CSCOV,                            &recvcov, sizeof (recvcov)))                return VLC_EGENERIC;            return VLC_SUCCESS;#endif    }#if !defined( UDPLITE_RECV_CSCOV ) && !defined( DCCP_SOCKOPT_SEND_CSCOV )    VLC_UNUSED(sendcov);    VLC_UNUSED(recvcov);#endif    return VLC_EGENERIC;}

⌨️ 快捷键说明

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