From dfd51e44f3117a4c1572d3335f819b198b6826e0 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Thu, 19 Aug 2021 06:03:34 +0000 Subject: [PATCH] added Socket::setRecvPktinfo() --- qse/include/qse/si/Socket.hpp | 2 + qse/lib/si/Socket.cpp | 99 +++++++++++++++++++++++++++++++++-- 2 files changed, 98 insertions(+), 3 deletions(-) diff --git a/qse/include/qse/si/Socket.hpp b/qse/include/qse/si/Socket.hpp index 363ebf5d..444c4e4a 100644 --- a/qse/include/qse/si/Socket.hpp +++ b/qse/include/qse/si/Socket.hpp @@ -83,6 +83,7 @@ public: int setTcpNodelay (int n) QSE_CPP_NOEXCEPT; int setOobInline (int n) QSE_CPP_NOEXCEPT; int setIpv6Only (int n) QSE_CPP_NOEXCEPT; + int setRecvPktinfo (int n) QSE_CPP_NOEXCEPT; int setNonBlock (int n) QSE_CPP_NOEXCEPT; // -------------------------------------------------------------------- @@ -130,6 +131,7 @@ public: qse_ssize_t receive (void* buf, qse_size_t len) QSE_CPP_NOEXCEPT; qse_ssize_t receive (void* buf, qse_size_t len, SocketAddress& srcaddr) QSE_CPP_NOEXCEPT; + qse_ssize_t receive (void* buf, qse_size_t len, SocketAddress& srcaddr, int& ifindex) QSE_CPP_NOEXCEPT; // -------------------------------------------------------------------- diff --git a/qse/lib/si/Socket.cpp b/qse/lib/si/Socket.cpp index e5d83b23..c9f010b0 100644 --- a/qse/lib/si/Socket.cpp +++ b/qse/lib/si/Socket.cpp @@ -291,13 +291,38 @@ int Socket::setOobInline (int n) QSE_CPP_NOEXCEPT int Socket::setIpv6Only (int n) QSE_CPP_NOEXCEPT { #if defined(IPV6_V6ONLY) - return this->setOption(IPPROTO_IPV6, IPV6_V6ONLY, (char*)&n, QSE_SIZEOF(n)); -#else + if (this->getDomain() == AF_INET6) + return this->setOption(IPPROTO_IPV6, IPV6_V6ONLY, (char*)&n, QSE_SIZEOF(n)); +#endif + this->setErrorNumber (E_ENOIMPL); return -1; -#endif } +int Socket::setRecvPktinfo (int n) QSE_CPP_NOEXCEPT +{ + switch (this->getDomain()) + { + #if defined(IP_PKTINFO) + case AF_INET: + return this->setOption(IPPROTO_IP, IP_PKTINFO, (char*)&n, QSE_SIZEOF(n)); + #endif + + #if defined(AF_INET6) && defined(IPV6_RECVPKTINFO) + case AF_INET6: + return this->setOption(IPPROTO_IPV6, IPV6_RECVPKTINFO, (char*)&n, QSE_SIZEOF(n)); + break; + #endif + + default: + break; + } + + this->setErrorNumber (E_ENOIMPL); + return -1; +} + + int Socket::setNonBlock (int n) QSE_CPP_NOEXCEPT { QSE_ASSERT (qse_is_sck_valid(this->handle)); @@ -984,6 +1009,74 @@ qse_ssize_t Socket::receive (void* buf, qse_size_t len, SocketAddress& srcaddr) return n; } +qse_ssize_t Socket::receive (void* buf, qse_size_t len, SocketAddress& srcaddr, int& ifindex) QSE_CPP_NOEXCEPT +{ + QSE_ASSERT (qse_is_sck_valid(this->handle)); + + switch (this->getDomain()) + { + case AF_INET: + { + break; + } + + #if defined(AF_INET6) + case AF_INET6: + { + ssize_t n; + struct msghdr msg; + struct cmsghdr* cmsg; + union + { + struct cmsghdr cmsg; + qse_uint8_t buf[CMSG_SPACE(QSE_SIZEOF(struct in6_pktinfo))]; + } c; + struct iovec iov; + struct sockaddr_in6 from; + + QSE_MEMSET (&msg, 0, QSE_SIZEOF(msg)); + msg.msg_control = c.buf; + msg.msg_controllen = QSE_SIZEOF(c); + msg.msg_flags = 0; + msg.msg_name = &from; + msg.msg_namelen = QSE_SIZEOF(from); + + iov.iov_base = buf; + iov.iov_len = len; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + n = ::recvmsg(this->handle, &msg, 0); + if (n == -1) + { + this->setErrorFmt (syserr_to_errnum(errno), QSE_T("%hs"), strerror(errno)); + return -1; + } + + ifindex = 0; // not known yet + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) + { + if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) + { + struct in6_pktinfo* pi; + + pi = (struct in6_pktinfo*)CMSG_DATA(cmsg); + ifindex = pi->ipi6_ifindex; + break; + } + } + + srcaddr.set ((const qse_skad_t*)&from); + return n; + } + #endif + } + + this->setErrorFmt (E_ENOIMPL, QSE_T("unsupported socket domain"), strerror(errno)); + return -1; +} + + int Socket::joinMulticastGroup (const SocketAddress& mcaddr, const SocketAddress& ifaddr) QSE_CPP_NOEXCEPT { int family = mcaddr.getFamily(); // ((struct sockaddr*)mcaddr.getAddrPtr())->sa_family