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

📄 multicast.c

📁 log4cxx 0.10 unix下编译包
💻 C
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include "apr_arch_networkio.h"#include "apr_network_io.h"#include "apr_support.h"#include "apr_portable.h"#include "apr_arch_inherit.h"#ifdef HAVE_GETIFADDRS#include <net/if.h>#include <ifaddrs.h>#endif#ifdef HAVE_STRUCT_IPMREQ/* Only UDP and Raw Sockets can be used for Multicast */static apr_status_t mcast_check_type(apr_socket_t *sock){    int type;    apr_status_t rv;    rv = apr_socket_type_get(sock, &type);    if (rv != APR_SUCCESS) {        return rv;    }    else if (type == SOCK_DGRAM || type == SOCK_RAW) {        return APR_SUCCESS;    }    else {        return APR_ENOTIMPL;    }}static void fill_mip_v4(struct ip_mreq *mip, apr_sockaddr_t *mcast,                        apr_sockaddr_t *iface){    mip->imr_multiaddr = mcast->sa.sin.sin_addr;    if (iface == NULL) {        mip->imr_interface.s_addr = INADDR_ANY;    }    else {        mip->imr_interface = iface->sa.sin.sin_addr;    }}#if APR_HAVE_IPV6static unsigned int find_if_index(const apr_sockaddr_t *iface){    unsigned int index = 0;#ifdef HAVE_GETIFADDRS    struct ifaddrs *ifp, *ifs;    /**     * TODO: getifaddrs is only portable to *BSD and OS X. Using ioctl      *       and SIOCGIFCONF is needed for Linux/Solaris support.     *            *       There is a wrapper that takes the messy ioctl interface into      *       getifaddrs. The license is acceptable, but, It is a fairly large      *       chunk of code.     */    if (getifaddrs(&ifs) != 0) {        return 0;    }    for (ifp = ifs; ifp; ifp = ifp->ifa_next) {        if (ifp->ifa_addr != NULL && ifp->ifa_addr->sa_family == AF_INET6) {            if (memcmp(&iface->sa.sin6.sin6_addr,                       &ifp->ifa_addr->sa_data[0],                       sizeof(iface->sa.sin6.sin6_addr)) == 0) {                index = if_nametoindex(ifp->ifa_name);                break;            }        }    }    freeifaddrs(ifs);#endif    return index;}static void fill_mip_v6(struct ipv6_mreq *mip, const apr_sockaddr_t *mcast,                        const apr_sockaddr_t *iface){    memcpy(&mip->ipv6mr_multiaddr, mcast->ipaddr_ptr,           sizeof(mip->ipv6mr_multiaddr));    if (iface == NULL) {        mip->ipv6mr_interface = 0;    }    else {        mip->ipv6mr_interface = find_if_index(iface);    }}#endifstatic int sock_is_ipv4(apr_socket_t *sock){    if (sock->local_addr->family == APR_INET)        return 1;    return 0;}#if APR_HAVE_IPV6static int sock_is_ipv6(apr_socket_t *sock){    if (sock->local_addr->family == APR_INET6)        return 1;    return 0;}#endifstatic apr_status_t do_mcast(int type, apr_socket_t *sock,                             apr_sockaddr_t *mcast, apr_sockaddr_t *iface,                             apr_sockaddr_t *source){    struct ip_mreq mip4;    apr_status_t rv = APR_SUCCESS;#if APR_HAVE_IPV6    struct ipv6_mreq mip6;#endif#if MCAST_JOIN_SOURCE_GROUP    struct group_source_req mip;    int ip_proto;#endif    rv = mcast_check_type(sock);    if (rv != APR_SUCCESS) {        return rv;    }    if (source != NULL) {#if MCAST_JOIN_SOURCE_GROUP        if (sock_is_ipv4(sock)) {            ip_proto = IPPROTO_IP;        } #if APR_HAVE_IPV6        else if (sock_is_ipv6(sock)) {            ip_proto = IPPROTO_IPV6;        }#endif        else {            return APR_ENOTIMPL;        }        if (type == IP_ADD_MEMBERSHIP)            type = MCAST_JOIN_SOURCE_GROUP;        else if (type == IP_DROP_MEMBERSHIP)            type = MCAST_LEAVE_SOURCE_GROUP;        else            return APR_ENOTIMPL;        mip.gsr_interface = find_if_index(iface);        memcpy(&mip.gsr_group, mcast->ipaddr_ptr, sizeof(mip.gsr_group));        memcpy(&mip.gsr_source, source->ipaddr_ptr, sizeof(mip.gsr_source));        if (setsockopt(sock->socketdes, ip_proto, type, (const void *) &mip,                       sizeof(mip)) == -1) {            rv = errno;        }#else        /* We do not support Source-Specific Multicast. */        return APR_ENOTIMPL;#endif    }    else {        if (sock_is_ipv4(sock)) {            fill_mip_v4(&mip4, mcast, iface);            if (setsockopt(sock->socketdes, IPPROTO_IP, type,                           (const void *) &mip4, sizeof(mip4)) == -1) {                rv = errno;            }        }#if APR_HAVE_IPV6 && defined(IPV6_JOIN_GROUP) && defined(IPV6_LEAVE_GROUP)        else if (sock_is_ipv6(sock)) {            if (type == IP_ADD_MEMBERSHIP) {                type = IPV6_JOIN_GROUP;            }            else if (type == IP_DROP_MEMBERSHIP) {                type = IPV6_LEAVE_GROUP;            }            else {                return APR_ENOTIMPL;            }            fill_mip_v6(&mip6, mcast, iface);            if (setsockopt(sock->socketdes, IPPROTO_IPV6, type,                           &mip6, sizeof(mip6)) == -1) {                rv = errno;            }        }#endif        else {            rv = APR_ENOTIMPL;        }    }    return rv;}static apr_status_t do_mcast_opt(int type, apr_socket_t *sock,                                 apr_byte_t value){    apr_status_t rv = APR_SUCCESS;    rv = mcast_check_type(sock);    if (rv != APR_SUCCESS) {        return rv;    }    if (sock_is_ipv4(sock)) {        if (setsockopt(sock->socketdes, IPPROTO_IP, type,                       (const void *) &value, sizeof(value)) == -1) {            rv = errno;        }    }#if APR_HAVE_IPV6    else if (sock_is_ipv6(sock) && type == IP_MULTICAST_LOOP) {        unsigned int loopopt = value;        type = IPV6_MULTICAST_LOOP;        if (setsockopt(sock->socketdes, IPPROTO_IPV6, type,                       &loopopt, sizeof(loopopt)) == -1) {            rv = errno;        }    }    else if (sock_is_ipv6(sock)) {        if (type == IP_MULTICAST_TTL) {            type = IPV6_MULTICAST_HOPS;        }        else {            return APR_ENOTIMPL;        }        if (setsockopt(sock->socketdes, IPPROTO_IPV6, type,                       &value, sizeof(value)) == -1) {            rv = errno;        }    }#endif    else {        rv = APR_ENOTIMPL;    }    return rv;}#endifAPR_DECLARE(apr_status_t) apr_mcast_join(apr_socket_t *sock,                                         apr_sockaddr_t *join,                                         apr_sockaddr_t *iface,                                         apr_sockaddr_t *source){#if defined(IP_ADD_MEMBERSHIP) && defined(HAVE_STRUCT_IPMREQ)    return do_mcast(IP_ADD_MEMBERSHIP, sock, join, iface, source);#else    return APR_ENOTIMPL;#endif}APR_DECLARE(apr_status_t) apr_mcast_leave(apr_socket_t *sock,                                          apr_sockaddr_t *addr,                                          apr_sockaddr_t *iface,                                          apr_sockaddr_t *source){#if defined(IP_DROP_MEMBERSHIP) && defined(HAVE_STRUCT_IPMREQ)    return do_mcast(IP_DROP_MEMBERSHIP, sock, addr, iface, source);#else    return APR_ENOTIMPL;#endif}APR_DECLARE(apr_status_t) apr_mcast_hops(apr_socket_t *sock, apr_byte_t ttl){#if defined(IP_MULTICAST_TTL) && defined(HAVE_STRUCT_IPMREQ)    return do_mcast_opt(IP_MULTICAST_TTL, sock, ttl);#else    return APR_ENOTIMPL;#endif}APR_DECLARE(apr_status_t) apr_mcast_loopback(apr_socket_t *sock,                                             apr_byte_t opt){#if defined(IP_MULTICAST_LOOP) && defined(HAVE_STRUCT_IPMREQ)    return do_mcast_opt(IP_MULTICAST_LOOP, sock, opt);#else    return APR_ENOTIMPL;#endif}APR_DECLARE(apr_status_t) apr_mcast_interface(apr_socket_t *sock,                                              apr_sockaddr_t *iface){#if defined(IP_MULTICAST_IF) && defined(HAVE_STRUCT_IPMREQ)    apr_status_t rv = APR_SUCCESS;    if (sock_is_ipv4(sock)) {        if (setsockopt(sock->socketdes, IPPROTO_IP, IP_MULTICAST_IF,                       (const void *) &iface->sa.sin.sin_addr,                       sizeof(iface->sa.sin.sin_addr)) == -1) {            rv = errno;        }    }#if APR_HAVE_IPV6    else if (sock_is_ipv6(sock)) {        unsigned int idx = find_if_index(iface);        if (setsockopt(sock->socketdes, IPPROTO_IPV6, IPV6_MULTICAST_IF,                       &idx, sizeof(idx)) == -1) {            rv = errno;        }    }#endif    else {        rv = APR_ENOTIMPL;    }    return rv;#else    return APR_ENOTIMPL;#endif}

⌨️ 快捷键说明

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