added Socket::joinMulticastGroup() and Socket::leaveMulticastGroup()

This commit is contained in:
hyung-hwan 2018-10-18 07:30:25 +00:00
parent 72345c7280
commit 05c2905a0a
4 changed files with 118 additions and 6 deletions

View File

@ -95,6 +95,8 @@ public:
qse_ssize_t receive (void* buf, qse_size_t len, SocketAddress& srcaddr) QSE_CPP_NOEXCEPT;
/* TODO: sendmsg, recvmsg */
int joinMulticastGroup (const SocketAddress& mcaddr, const SocketAddress& ifaddr);
int leaveMulticastGroup (const SocketAddress& mcaddr, const SocketAddress& ifaddr);
// utility functions to retrieve network configuration information.
int getIfceIndex (const qse_mchar_t* name);

View File

@ -67,10 +67,13 @@ public:
void setIpaddr (const qse_ip4ad_t* ipaddr) QSE_CPP_NOEXCEPT;
void setIpaddr (const qse_ip6ad_t* ipaddr) QSE_CPP_NOEXCEPT;
const qse_ip4ad_t* getIp4addr () const QSE_CPP_NOEXCEPT;
const qse_ip6ad_t* getIp6addr () const QSE_CPP_NOEXCEPT;
qse_uint16_t getPort() const QSE_CPP_NOEXCEPT; // in network-byte order
void setPort (qse_uint16_t port) QSE_CPP_NOEXCEPT; // in network-byte order
qse_uint32_t getScopeId () QSE_CPP_NOEXCEPT; // in network-byte order
qse_uint32_t getScopeId () const QSE_CPP_NOEXCEPT; // in network-byte order
void setScopeId (qse_uint32_t scope_id) QSE_CPP_NOEXCEPT; // in network-byte order
int set (const qse_skad_t* skad) QSE_CPP_NOEXCEPT;

View File

@ -35,6 +35,7 @@
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>
#if defined(HAVE_NET_IF_H)
# include <net/if.h>
@ -590,6 +591,88 @@ qse_ssize_t Socket::receive (void* buf, qse_size_t len, SocketAddress& srcaddr)
return n;
}
int Socket::joinMulticastGroup (const SocketAddress& mcaddr, const SocketAddress& ifaddr)
{
int family = mcaddr.getFamily(); // ((struct sockaddr*)mcaddr.getAddrPtr())->sa_family
if (family != ifaddr.getFamily())
{
this->setErrorCode (E_EINVAL);
return -1;
}
switch (family)
{
#if defined(AF_INET)
case AF_INET:
{
struct ip_mreq mreq;
QSE_MEMSET (&mreq, 0, QSE_SIZEOF(mreq));
mreq.imr_multiaddr = *(struct in_addr*)mcaddr.getIp4addr();
mreq.imr_interface = *(struct in_addr*)ifaddr.getIp4addr();
return ::setsockopt(this->handle, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, QSE_SIZEOF(mreq));
}
#endif
#if defined(AF_INET6)
case AF_INET6:
{
struct ipv6_mreq mreq;
QSE_MEMSET (&mreq, 0, QSE_SIZEOF(mreq));
mreq.ipv6mr_multiaddr = *(struct in6_addr*)mcaddr.getIp6addr();
mreq.ipv6mr_interface = ifaddr.getScopeId();
return ::setsockopt(this->handle, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, QSE_SIZEOF(mreq));
}
#endif
}
this->setErrorCode (E_ENOIMPL);
return -1;
}
int Socket::leaveMulticastGroup (const SocketAddress& mcaddr, const SocketAddress& ifaddr)
{
int family = mcaddr.getFamily(); // ((struct sockaddr*)mcaddr.getAddrPtr())->sa_family
if (family != ifaddr.getFamily())
{
this->setErrorCode (E_EINVAL);
return -1;
}
switch (family)
{
#if defined(AF_INET)
case AF_INET:
{
struct ip_mreq mreq;
QSE_MEMSET (&mreq, 0, QSE_SIZEOF(mreq));
mreq.imr_multiaddr = *(struct in_addr*)mcaddr.getIp4addr();
mreq.imr_interface = *(struct in_addr*)ifaddr.getIp4addr();
return ::setsockopt(this->handle, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, QSE_SIZEOF(mreq));
}
#endif
#if defined(AF_INET6)
case AF_INET6:
{
struct ipv6_mreq mreq;
QSE_MEMSET (&mreq, 0, QSE_SIZEOF(mreq));
mreq.ipv6mr_multiaddr = *(struct in6_addr*)mcaddr.getIp6addr();
mreq.ipv6mr_interface = ifaddr.getScopeId();
return ::setsockopt(this->handle, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, QSE_SIZEOF(mreq));
}
#endif
}
this->setErrorCode (E_ENOIMPL);
return -1;
}
int Socket::getIfceIndex (const qse_mchar_t* name)
{
@ -674,7 +757,7 @@ int Socket::getIfceAddress (const qse_wchar_t* name, SocketAddress* addr)
int Socket::getIfceNetmask(const qse_mchar_t* name, SocketAddress* addr)
{
#if defined(SIOCGIFADDR)
#if defined(SIOCGIFNETMASK)
return this->get_ifce_address(SIOCGIFNETMASK, name, false, addr);
#else
this->setErrorCode (E_ENOIMPL);
@ -684,7 +767,7 @@ int Socket::getIfceNetmask(const qse_mchar_t* name, SocketAddress* addr)
int Socket::getIfceNetmask (const qse_wchar_t* name, SocketAddress* addr)
{
#if defined(SIOCGIFADDR)
#if defined(SIOCGIFNETMASK)
return this->get_ifce_address(SIOCGIFNETMASK, name, true, addr);
#else
this->setErrorCode (E_ENOIMPL);
@ -694,7 +777,7 @@ int Socket::getIfceNetmask (const qse_wchar_t* name, SocketAddress* addr)
int Socket::getIfceBroadcast(const qse_mchar_t* name, SocketAddress* addr)
{
#if defined(SIOCGIFADDR)
#if defined(SIOCGIFBRDADDR)
return this->get_ifce_address(SIOCGIFBRDADDR, name, false, addr);
#else
this->setErrorCode (E_ENOIMPL);
@ -704,7 +787,7 @@ int Socket::getIfceBroadcast(const qse_mchar_t* name, SocketAddress* addr)
int Socket::getIfceBroadcast (const qse_wchar_t* name, SocketAddress* addr)
{
#if defined(SIOCGIFADDR)
#if defined(SIOCGIFBRDADDR)
return this->get_ifce_address(SIOCGIFBRDADDR, name, true, addr);
#else
this->setErrorCode (E_ENOIMPL);

View File

@ -139,6 +139,30 @@ void SocketAddress::setIpaddr (const qse_ip6ad_t* ipaddr) QSE_CPP_NOEXCEPT
#endif
}
const qse_ip4ad_t* SocketAddress::getIp4addr () const QSE_CPP_NOEXCEPT
{
#if defined(AF_INET)
if (FAMILY(&this->skad) == AF_INET)
{
struct sockaddr_in* v4 = (struct sockaddr_in*)&this->skad;
return (const qse_ip4ad_t*)&v4->sin_addr;
}
#endif
return QSE_NULL;
}
const qse_ip6ad_t* SocketAddress::getIp6addr () const QSE_CPP_NOEXCEPT
{
#if defined(AF_INET6)
if (FAMILY(&this->skad) == AF_INET6)
{
struct sockaddr_in6* v6 = (struct sockaddr_in6*)&this->skad;
return (const qse_ip6ad_t*)&v6->sin6_addr;
}
#endif
return QSE_NULL;
}
qse_uint16_t SocketAddress::getPort () const QSE_CPP_NOEXCEPT
{
switch (FAMILY(&this->skad))
@ -187,7 +211,7 @@ void SocketAddress::setPort (qse_uint16_t port) QSE_CPP_NOEXCEPT
}
}
qse_uint32_t SocketAddress::getScopeId () QSE_CPP_NOEXCEPT
qse_uint32_t SocketAddress::getScopeId () const QSE_CPP_NOEXCEPT
{
switch (FAMILY(&this->skad))
{