diff --git a/srtcore/channel.cpp b/srtcore/channel.cpp index 0a4e1e318..d93e90fdb 100644 --- a/srtcore/channel.cpp +++ b/srtcore/channel.cpp @@ -662,12 +662,19 @@ void srt::CChannel::getPeerAddr(sockaddr_any& w_addr) const w_addr.len = namelen; } -int srt::CChannel::sendto(const sockaddr_any& addr, CPacket& packet, const sockaddr_any& source_addr SRT_ATR_UNUSED) const +int srt::CChannel::sendto(const sockaddr_any& addr, CPacket& packet, const CNetworkInterface& source_ni SRT_ATR_UNUSED) const { #if ENABLE_HEAVY_LOGGING ostringstream dsrc; #ifdef SRT_ENABLE_PKTINFO - dsrc << " sourceIP=" << (m_bBindMasked && !source_addr.isany() ? source_addr.str() : "default"); + if (m_bBindMasked && !source_ni.address.isany()) + { + dsrc << " sourceNI=" << source_ni.str(); + } + else + { + dsrc << " sourceNI=default"; + } #endif LOGC(kslog.Debug, @@ -750,15 +757,15 @@ int srt::CChannel::sendto(const sockaddr_any& addr, CPacket& packet, const socka // Note that even if PKTINFO is desired, the first caller's packet will be sent // without ancillary info anyway because there's no "peer" yet to know where to send it. char mh_crtl_buf[sizeof(CMSGNodeIPv4) + sizeof(CMSGNodeIPv6)]; - if (m_bBindMasked && source_addr.family() != AF_UNSPEC && !source_addr.isany()) + if (m_bBindMasked && source_ni.address.family() != AF_UNSPEC && !source_ni.address.isany()) { - if (!setSourceAddress(mh, mh_crtl_buf, source_addr)) + if (!setSourceAddress(mh, mh_crtl_buf, source_ni)) { - LOGC(kslog.Error, log << "CChannel::setSourceAddress: source address invalid family #" << source_addr.family() << ", NOT setting."); + LOGC(kslog.Error, log << "CChannel::setSourceAddress: source address invalid family #" << source_ni.address.family() << ", NOT setting."); } else { - HLOGC(kslog.Debug, log << "CChannel::setSourceAddress: setting as " << source_addr.str()); + HLOGC(kslog.Debug, log << "CChannel::setSourceAddress: setting as " << source_ni.str()); have_set_src = true; } } diff --git a/srtcore/channel.h b/srtcore/channel.h index e12310001..573554cb6 100644 --- a/srtcore/channel.h +++ b/srtcore/channel.h @@ -117,7 +117,7 @@ class CChannel /// @param [in] src source address to sent on an outgoing packet (if not ANY) /// @return Actual size of data sent. - int sendto(const sockaddr_any& addr, srt::CPacket& packet, const sockaddr_any& src) const; + int sendto(const sockaddr_any& addr, srt::CPacket& packet, const CNetworkInterface& src) const; /// Receive a packet from the channel and record the source address. /// @param [in] addr pointer to the source address. @@ -205,7 +205,7 @@ class CChannel cmsghdr hdr; }; - sockaddr_any getTargetAddress(const msghdr& msg) const + CNetworkInterface getTargetAddress(const msghdr& msg) const { // Loop through IP header messages cmsghdr* cmsg; @@ -219,33 +219,33 @@ class CChannel { in_pktinfo dest_ip; memcpy(&dest_ip, CMSG_DATA(cmsg), sizeof(struct in_pktinfo)); - return sockaddr_any(dest_ip.ipi_addr, 0); + return CNetworkInterface(dest_ip.ipi_addr, dest_ip.ipi_ifindex); } if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) { in6_pktinfo dest_ip; memcpy(&dest_ip, CMSG_DATA(cmsg), sizeof(struct in6_pktinfo)); - return sockaddr_any(dest_ip.ipi6_addr, 0); + return CNetworkInterface(dest_ip.ipi6_addr, dest_ip.ipi6_ifindex); } } // Fallback for an error - return sockaddr_any(m_BindAddr.family()); + return CNetworkInterface(); } // IMPORTANT!!! This function shall be called EXCLUSIVELY just before // calling ::sendmsg function. It uses a static buffer to supply data // for the call, and it's stated that only one thread is trying to // use a CChannel object in sending mode. - bool setSourceAddress(msghdr& mh, char *buf, const sockaddr_any& adr) const + bool setSourceAddress(msghdr& mh, char *buf, const CNetworkInterface& ni) const { // In contrast to an advice followed on the net, there's no case of putting // both IPv4 and IPv6 ancillary data, case we could have them. Only one // IP version is used and it's the version as found in @a adr, which should // be the version used for binding. - if (adr.family() == AF_INET) + if (ni.address.family() == AF_INET) { mh.msg_control = (void *) buf; mh.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); @@ -254,16 +254,16 @@ class CChannel cmsg_send->cmsg_level = IPPROTO_IP; cmsg_send->cmsg_type = IP_PKTINFO; cmsg_send->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); - + in_pktinfo pktinfo; - pktinfo.ipi_ifindex = 0; - pktinfo.ipi_spec_dst = adr.sin.sin_addr; + pktinfo.ipi_ifindex = ni.interface_index; + pktinfo.ipi_spec_dst = ni.address.sin.sin_addr; memcpy(CMSG_DATA(cmsg_send), &pktinfo, sizeof(in_pktinfo)); return true; } - if (adr.family() == AF_INET6) + if (ni.address.family() == AF_INET6) { mh.msg_control = buf; mh.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); @@ -274,8 +274,8 @@ class CChannel cmsg_send->cmsg_len = CMSG_LEN(sizeof(in6_pktinfo)); in6_pktinfo* pktinfo = (in6_pktinfo*) CMSG_DATA(cmsg_send); - pktinfo->ipi6_ifindex = 0; - pktinfo->ipi6_addr = adr.sin6.sin6_addr; + pktinfo->ipi6_ifindex = ni.interface_index; + pktinfo->ipi6_addr = ni.address.sin6.sin6_addr; return true; } diff --git a/srtcore/common.h b/srtcore/common.h index 6a8912118..b72369152 100644 --- a/srtcore/common.h +++ b/srtcore/common.h @@ -54,6 +54,7 @@ modified by #define INC_SRT_COMMON_H #include +#include #include #include #ifndef _WIN32 @@ -95,7 +96,36 @@ modified by #define SRT_STATIC_ASSERT(cond, msg) #endif -#include +namespace srt +{ + +struct CNetworkInterface +{ + sockaddr_any address; + int interface_index; + + template + CNetworkInterface(const InAddrType& sa, int index) + : address(sa, 0) + , interface_index(index) + { + } + + CNetworkInterface() // blank fallback + : address(AF_UNSPEC) + , interface_index(0) + { + } + + std::string str() const + { + std::ostringstream buf; + buf << address.str() << "/" << interface_index; + return buf.str(); + } +}; + +} namespace srt_logging { diff --git a/srtcore/core.cpp b/srtcore/core.cpp index b802bdec9..8a7baf856 100644 --- a/srtcore/core.cpp +++ b/srtcore/core.cpp @@ -3651,7 +3651,7 @@ void srt::CUDT::startConnect(const sockaddr_any& serv_addr, int32_t forced_isn) EConnectStatus cst = CONN_CONTINUE; // This is a temporary place to store the DESTINATION IP from the incoming packet. // We can't record this address yet until the cookie-confirmation is done, for safety reasons. - sockaddr_any use_source_adr(serv_addr.family()); + CNetworkInterface use_source_adr; while (!m_bClosing) { @@ -9591,7 +9591,7 @@ bool srt::CUDT::isRetransmissionAllowed(const time_point& tnow SRT_ATR_UNUSED) return true; } -bool srt::CUDT::packData(CPacket& w_packet, steady_clock::time_point& w_nexttime, sockaddr_any& w_src_addr) +bool srt::CUDT::packData(CPacket& w_packet, steady_clock::time_point& w_nexttime, CNetworkInterface& w_src_addr) { int payload = 0; bool probe = false; @@ -11063,7 +11063,7 @@ int srt::CUDT::processConnectRequest(const sockaddr_any& addr, CPacket& packet) // because this happens still in the frames of the listener socket. Only // when processing switches to the newly spawned accepted socket can the // address be recorded in its m_SourceAddr field. - sockaddr_any use_source_addr = packet.udpDestAddr(); + CNetworkInterface use_source_addr = packet.udpDestAddr(); // REQUEST:INDUCTION. // Set a cookie, a target ID, and send back the same as diff --git a/srtcore/core.h b/srtcore/core.h index 3935b99d3..6bb9700a6 100644 --- a/srtcore/core.h +++ b/srtcore/core.h @@ -1124,7 +1124,7 @@ class CUDT /// /// @retval true A packet was extracted for sending, the socket should be rechecked at @a nexttime /// @retval false Nothing was extracted for sending, @a nexttime should be ignored - bool packData(CPacket& packet, time_point& nexttime, sockaddr_any& src_addr); + bool packData(CPacket& packet, time_point& nexttime, CNetworkInterface& src_addr); int processData(CUnit* unit); @@ -1220,7 +1220,7 @@ class CUDT CSndQueue* m_pSndQueue; // packet sending queue CRcvQueue* m_pRcvQueue; // packet receiving queue sockaddr_any m_PeerAddr; // peer address - sockaddr_any m_SourceAddr; // override UDP source address with this one when sending + CNetworkInterface m_SourceAddr; // override UDP source address with this one when sending uint32_t m_piSelfIP[4]; // local UDP IP address CSNode* m_pSNode; // node information for UDT list used in snd queue CRNode* m_pRNode; // node information for UDT list used in rcv queue diff --git a/srtcore/packet.h b/srtcore/packet.h index 5094247b5..d8c643781 100644 --- a/srtcore/packet.h +++ b/srtcore/packet.h @@ -307,7 +307,7 @@ class CPacket /// @return packet header field [2] (bit 0~31, bit 0-26 if SRT_DEBUG_TSBPD_WRAP). uint32_t getMsgTimeStamp() const; - sockaddr_any udpDestAddr() const { return m_DestAddr; } + CNetworkInterface udpDestAddr() const { return m_DestAddr; } #ifdef SRT_DEBUG_TSBPD_WRAP // Receiver static const uint32_t MAX_TIMESTAMP = 0x07FFFFFF; // 27 bit fast wraparound for tests (~2m15s) @@ -346,7 +346,7 @@ class CPacket int32_t m_extra_pad; bool m_data_owned; - sockaddr_any m_DestAddr; + CNetworkInterface m_DestAddr; size_t m_zCapacity; protected: diff --git a/srtcore/queue.cpp b/srtcore/queue.cpp index 98999a81f..f3f6ef93a 100644 --- a/srtcore/queue.cpp +++ b/srtcore/queue.cpp @@ -579,7 +579,7 @@ void* srt::CSndQueue::worker(void* param) // pack a packet from the socket CPacket pkt; steady_clock::time_point next_send_time; - sockaddr_any source_addr; + CNetworkInterface source_addr; const bool res = u->packData((pkt), (next_send_time), (source_addr)); // Check if extracted anything to send @@ -603,7 +603,7 @@ void* srt::CSndQueue::worker(void* param) return NULL; } -int srt::CSndQueue::sendto(const sockaddr_any& addr, CPacket& w_packet, const sockaddr_any& src) +int srt::CSndQueue::sendto(const sockaddr_any& addr, CPacket& w_packet, const CNetworkInterface& src) { // send out the packet immediately (high priority), this is a control packet // NOTE: w_packet is passed by mutable reference because this function will do diff --git a/srtcore/queue.h b/srtcore/queue.h index dd68a7721..098fa24f8 100644 --- a/srtcore/queue.h +++ b/srtcore/queue.h @@ -420,7 +420,7 @@ class CSndQueue /// @param [in,ref] packet packet to be sent out /// @param [in] src The source IP address (details above) /// @return Size of data sent out. - int sendto(const sockaddr_any& addr, CPacket& packet, const sockaddr_any& src); + int sendto(const sockaddr_any& addr, CPacket& packet, const CNetworkInterface& src); /// Get the IP TTL. /// @param [in] ttl IP Time To Live. @@ -592,6 +592,10 @@ struct CMultiplexer , m_pRcvQueue(NULL) , m_pChannel(NULL) , m_pTimer(NULL) + , m_iPort(0) + , m_iIPversion(AF_UNSPEC) + , m_iRefCount(1) + , m_iID(-1) { }