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

📄 udp.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** * udp.c: ***************************************************************************** * Copyright (C) 2004-2006 the VideoLAN team * Copyright © 2006-2007 Rémi Denis-Courmont * * $Id$ * * Authors: Laurent Aimar <fenrir@videolan.org> *          Rémi Denis-Courmont <rem # videolan.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <errno.h>#ifdef HAVE_SYS_TIME_H#    include <sys/time.h>#endif#include <vlc_network.h>#ifdef WIN32#   if defined(UNDER_CE)#       undef IP_MULTICAST_TTL#       define IP_MULTICAST_TTL 3#       undef IP_ADD_MEMBERSHIP#       define IP_ADD_MEMBERSHIP 5#   endif#   define EAFNOSUPPORT WSAEAFNOSUPPORT#   define if_nametoindex( str ) atoi( str )#else#   include <unistd.h>#   ifdef HAVE_NET_IF_H#       include <net/if.h>#   endif#endif#ifdef HAVE_LINUX_DCCP_H# include <linux/dccp.h># ifndef SOCK_DCCP /* provisional API */#  define SOCK_DCCP 6# endif#endif#ifndef SOL_IP# define SOL_IP IPPROTO_IP#endif#ifndef SOL_IPV6# define SOL_IPV6 IPPROTO_IPV6#endif#ifndef IPPROTO_IPV6# define IPPROTO_IPV6 41 /* IANA */#endif#ifndef SOL_DCCP# define SOL_DCCP IPPROTO_DCCP#endif#ifndef IPPROTO_DCCP# define IPPROTO_DCCP 33 /* IANA */#endif#ifndef SOL_UDPLITE# define SOL_UDPLITE IPPROTO_UDPLITE#endif#ifndef IPPROTO_UDPLITE# define IPPROTO_UDPLITE 136 /* IANA */#endif#if defined (HAVE_NETINET_UDPLITE_H)# include <netinet/udplite.h>#elif defined (__linux__)/* still missing from glibc 2.6 */# define UDPLITE_SEND_CSCOV     10# define UDPLITE_RECV_CSCOV     11#endifextern int net_Socket( vlc_object_t *p_this, int i_family, int i_socktype,                       int i_protocol );/* */static int net_SetupDgramSocket( vlc_object_t *p_obj, int fd, const struct addrinfo *ptr ){#ifdef SO_REUSEPORT    setsockopt (fd, SOL_SOCKET, SO_REUSEPORT, &(int){ 1 }, sizeof (int));#endif#ifdef SO_RCVBUF    /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s)     * to avoid packet loss caused in case of scheduling hiccups */    setsockopt (fd, SOL_SOCKET, SO_RCVBUF,                (void *)&(int){ 0x80000 }, sizeof (int));    setsockopt (fd, SOL_SOCKET, SO_SNDBUF,                (void *)&(int){ 0x80000 }, sizeof (int));#endif#if defined (WIN32) || defined (UNDER_CE)    if (net_SockAddrIsMulticast (ptr->ai_addr, ptr->ai_addrlen)     && (sizeof (struct sockaddr_storage) >= ptr->ai_addrlen))    {        // This works for IPv4 too - don't worry!        struct sockaddr_in6 dumb =        {            .sin6_family = ptr->ai_addr->sa_family,            .sin6_port =  ((struct sockaddr_in *)(ptr->ai_addr))->sin_port        };        bind (fd, (struct sockaddr *)&dumb, ptr->ai_addrlen);    }    else#endif    if (bind (fd, ptr->ai_addr, ptr->ai_addrlen))    {        msg_Err( p_obj, "socket bind error (%m)" );        net_Close (fd);        return -1;    }    return fd;}/* */static int net_ListenSingle (vlc_object_t *obj, const char *host, int port,                             int family, int protocol){    struct addrinfo hints, *res;    memset (&hints, 0, sizeof( hints ));    hints.ai_family = family;    hints.ai_socktype = SOCK_DGRAM;    hints.ai_flags = AI_PASSIVE;    if (host && !*host)        host = NULL;    msg_Dbg (obj, "net: opening %s datagram port %d", host ?: "any", port);    int val = vlc_getaddrinfo (obj, host, port, &hints, &res);    if (val)    {        msg_Err (obj, "Cannot resolve %s port %d : %s", host, port,                 vlc_gai_strerror (val));        return -1;    }    val = -1;    for (const struct addrinfo *ptr = res; ptr != NULL; ptr = ptr->ai_next)    {        int fd = net_Socket (obj, ptr->ai_family, ptr->ai_socktype,                             protocol ?: ptr->ai_protocol);        if (fd == -1)        {            msg_Dbg (obj, "socket error: %m");            continue;        }        if (ptr->ai_next != NULL)        {#ifdef IPV6_V6ONLY            if ((ptr->ai_family != AF_INET6)             || setsockopt (fd, SOL_IPV6, IPV6_V6ONLY, &(int){ 0 },                            sizeof (int)))#endif            {                msg_Err (obj, "Multiple network protocols present");                msg_Err (obj, "Please select network protocol manually");            }        }        fd = net_SetupDgramSocket( obj, fd, ptr );        if( fd == -1 )            continue;        if (net_SockAddrIsMulticast (ptr->ai_addr, ptr->ai_addrlen)         && net_Subscribe (obj, fd, ptr->ai_addr, ptr->ai_addrlen))        {            net_Close (fd);            continue;        }        val = fd;        break;    }    vlc_freeaddrinfo (res);    return val;}static int net_SetMcastHopLimit( vlc_object_t *p_this,                                 int fd, int family, int hlim ){    int proto, cmd;    /* There is some confusion in the world whether IP_MULTICAST_TTL     * takes a byte or an int as an argument.     * BSD seems to indicate byte so we are going with that and use     * int as a fallback to be safe */    switch( family )    {#ifdef IP_MULTICAST_TTL        case AF_INET:            proto = SOL_IP;            cmd = IP_MULTICAST_TTL;            break;#endif#ifdef IPV6_MULTICAST_HOPS        case AF_INET6:            proto = SOL_IPV6;            cmd = IPV6_MULTICAST_HOPS;            break;#endif        default:            errno = EAFNOSUPPORT;            msg_Warn( p_this, "%m" );            return VLC_EGENERIC;    }    if( setsockopt( fd, proto, cmd, &hlim, sizeof( hlim ) ) < 0 )    {        /* BSD compatibility */        unsigned char buf;        buf = (unsigned char)(( hlim > 255 ) ? 255 : hlim);        if( setsockopt( fd, proto, cmd, &buf, sizeof( buf ) ) )            return VLC_EGENERIC;    }    return VLC_SUCCESS;}static int net_SetMcastOutIface (int fd, int family, int scope){    switch (family)    {#ifdef IPV6_MULTICAST_IF        case AF_INET6:            return setsockopt (fd, SOL_IPV6, IPV6_MULTICAST_IF,                               &scope, sizeof (scope));#endif#ifdef __linux__        case AF_INET:        {            struct ip_mreqn req = { .imr_ifindex = scope };            return setsockopt (fd, SOL_IP, IP_MULTICAST_IF, &req,                               sizeof (req));        }#endif    }    errno = EAFNOSUPPORT;    return -1;}static inline int net_SetMcastOutIPv4 (int fd, struct in_addr ipv4){#ifdef IP_MULTICAST_IF    return setsockopt( fd, SOL_IP, IP_MULTICAST_IF, &ipv4, sizeof (ipv4));#else    errno = EAFNOSUPPORT;    return -1;#endif}static int net_SetMcastOut (vlc_object_t *p_this, int fd, int family,                            const char *iface, const char *addr){    if (iface != NULL)    {        int scope = if_nametoindex (iface);        if (scope == 0)        {            msg_Err (p_this, "invalid multicast interface: %s", iface);            return -1;        }        if (net_SetMcastOutIface (fd, family, scope) == 0)            return 0;        msg_Err (p_this, "%s: %m", iface);    }    if (addr != NULL)    {        if (family == AF_INET)        {            struct in_addr ipv4;            if (inet_pton (AF_INET, addr, &ipv4) <= 0)            {                msg_Err (p_this, "invalid IPv4 address for multicast: %s",                         addr);                return -1;            }            if (net_SetMcastOutIPv4 (fd, ipv4) == 0)                return 0;            msg_Err (p_this, "%s: %m", addr);        }    }    return -1;}/** * Old-style any-source multicast join. * In use on Windows XP/2003 and older. */static intnet_IPv4Join (vlc_object_t *obj, int fd,              const struct sockaddr_in *src, const struct sockaddr_in *grp){#ifdef IP_ADD_MEMBERSHIP    union    {        struct ip_mreq gr4;# ifdef IP_ADD_SOURCE_MEMBERSHIP        struct ip_mreq_source gsr4;# endif    } opt;    int cmd;    struct in_addr id = { .s_addr = INADDR_ANY };    socklen_t optlen;    /* Multicast interface IPv4 address */    char *iface = var_CreateGetNonEmptyString (obj, "miface-addr");    if ((iface != NULL)     && (inet_pton (AF_INET, iface, &id) <= 0))    {        msg_Err (obj, "invalid multicast interface address %s", iface);        free (iface);        goto error;    }    free (iface);    memset (&opt, 0, sizeof (opt));    if (src != NULL)    {# ifdef IP_ADD_SOURCE_MEMBERSHIP        cmd = IP_ADD_SOURCE_MEMBERSHIP;        opt.gsr4.imr_multiaddr = grp->sin_addr;        opt.gsr4.imr_sourceaddr = src->sin_addr;        opt.gsr4.imr_interface = id;        optlen = sizeof (opt.gsr4);# else        errno = ENOSYS;        goto error;# endif    }    else    {        cmd = IP_ADD_MEMBERSHIP;        opt.gr4.imr_multiaddr = grp->sin_addr;        opt.gr4.imr_interface = id;        optlen = sizeof (opt.gr4);    }    msg_Dbg (obj, "IP_ADD_%sMEMBERSHIP multicast request",             (src != NULL) ? "SOURCE_" : "");    if (setsockopt (fd, SOL_IP, cmd, &opt, optlen) == 0)        return 0;error:#endif    msg_Err (obj, "cannot join IPv4 multicast group (%m)");    return -1;}static intnet_IPv6Join (vlc_object_t *obj, int fd, const struct sockaddr_in6 *src){#ifdef IPV6_JOIN_GROUP    struct ipv6_mreq gr6;    memset (&gr6, 0, sizeof (gr6));    gr6.ipv6mr_interface = src->sin6_scope_id;    memcpy (&gr6.ipv6mr_multiaddr, &src->sin6_addr, 16);    msg_Dbg (obj, "IPV6_JOIN_GROUP multicast request");    if (!setsockopt (fd, SOL_IPV6, IPV6_JOIN_GROUP, &gr6, sizeof (gr6)))        return 0;#else    errno = ENOSYS;#endif    msg_Err (obj, "cannot join IPv6 any-source multicast group (%m)");    return -1;}#if defined (WIN32) && !defined (MCAST_JOIN_SOURCE_GROUP)/* * I hate manual definitions: Error-prone. Portability hell. * Developers shall use UP-TO-DATE compilers. Full point. * If you remove the warning, you remove the whole ifndef. */#  warning Your C headers are out-of-date. Please update.#  define MCAST_JOIN_GROUP 41struct group_req{    ULONG gr_interface;    struct sockaddr_storage gr_group;};#  define MCAST_JOIN_SOURCE_GROUP 45 /* from <ws2ipdef.h> */struct group_source_req{    uint32_t gsr_interface;    struct sockaddr_storage gsr_group;    struct sockaddr_storage gsr_source;};

⌨️ 快捷键说明

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