-
Notifications
You must be signed in to change notification settings - Fork 851
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added extraction of IP_PKTINFO when reading and setting it when sending back #456
Changes from all commits
e825aa6
6eea9f7
5a1e508
95af2e3
828b403
2ac3a99
f57ca6f
be0afb8
76ad98a
fec4909
c1b4466
bcce38f
e2a1426
bdd7ee2
ec349dc
f37b21b
b8be09f
58cd006
21e7740
af2870b
5d8dae1
7d9eee0
7f8a55b
39f9565
f1b2db8
ba63b76
b379292
c9cd6f6
4742039
39c430a
52f820d
f6ed44f
c25f2d7
d44d96f
cbae059
3ac8c18
660a126
b2c8e9a
d5d84f3
41ad2c0
a087907
a6f01ed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -139,7 +139,24 @@ static int set_cloexec(int fd, int set) | |
|
||
srt::CChannel::CChannel() | ||
: m_iSocket(INVALID_SOCKET) | ||
#ifdef SRT_ENABLE_PKTINFO | ||
, m_bBindMasked(true) | ||
#endif | ||
{ | ||
#ifdef SRT_ENABLE_PKTINFO | ||
// Do the check for ancillary data buffer size, kinda assertion | ||
static const size_t CMSG_MAX_SPACE = sizeof (CMSGNodeAlike); | ||
|
||
if (CMSG_MAX_SPACE < CMSG_SPACE(sizeof(in_pktinfo)) | ||
|| CMSG_MAX_SPACE < CMSG_SPACE(sizeof(in6_pktinfo))) | ||
{ | ||
LOGC(kmlog.Fatal, log << "Size of CMSG_MAX_SPACE=" | ||
<< CMSG_MAX_SPACE << " too short for cmsg " | ||
<< CMSG_SPACE(sizeof(in_pktinfo)) << ", " | ||
<< CMSG_SPACE(sizeof(in6_pktinfo)) << " - PLEASE FIX"); | ||
throw CUDTException(MJ_SETUP, MN_NONE, 0); | ||
} | ||
#endif | ||
} | ||
|
||
srt::CChannel::~CChannel() {} | ||
|
@@ -207,6 +224,9 @@ void srt::CChannel::open(const sockaddr_any& addr) | |
throw CUDTException(MJ_SETUP, MN_NORES, NET_ERROR); | ||
|
||
m_BindAddr = addr; | ||
#ifdef SRT_ENABLE_PKTINFO | ||
m_bBindMasked = m_BindAddr.isany(); | ||
#endif | ||
LOGC(kmlog.Debug, log << "CHANNEL: Bound to local address: " << m_BindAddr.str()); | ||
|
||
setUDPSockOpt(); | ||
|
@@ -247,6 +267,12 @@ void srt::CChannel::open(int family) | |
} | ||
m_BindAddr = sockaddr_any(res->ai_addr, (sockaddr_any::len_t)res->ai_addrlen); | ||
|
||
#ifdef SRT_ENABLE_PKTINFO | ||
// We know that this is intentionally bound now to "any", | ||
// so the requester-destination address must be remembered and passed. | ||
m_bBindMasked = true; | ||
#endif | ||
|
||
::freeaddrinfo(res); | ||
|
||
HLOGC(kmlog.Debug, log << "CHANNEL: Bound to local address: " << m_BindAddr.str()); | ||
|
@@ -472,6 +498,19 @@ void srt::CChannel::setUDPSockOpt() | |
if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(timeval))) | ||
throw CUDTException(MJ_SETUP, MN_NORES, NET_ERROR); | ||
#endif | ||
|
||
#ifdef SRT_ENABLE_PKTINFO | ||
if (m_bBindMasked) | ||
{ | ||
HLOGP(kmlog.Debug, "Socket bound to ANY - setting PKTINFO for address retrieval"); | ||
const int on = 1, off SRT_ATR_UNUSED = 0; | ||
::setsockopt(m_iSocket, IPPROTO_IP, IP_PKTINFO, (char*)&on, sizeof(on)); | ||
::setsockopt(m_iSocket, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)); | ||
|
||
// XXX Unknown why this has to be off. RETEST. | ||
//::setsockopt(m_iSocket, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)); | ||
Comment on lines
+510
to
+511
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I found this line in the old implementation that was there years ago. Unsure what this was about. Left for a case when someone finds a problem on IPv6 using it. |
||
} | ||
#endif | ||
} | ||
|
||
void srt::CChannel::close() const | ||
|
@@ -610,11 +649,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 | ||
int srt::CChannel::sendto(const sockaddr_any& addr, CPacket& packet, const sockaddr_any& source_addr SRT_ATR_UNUSED) const | ||
{ | ||
HLOGC(kslog.Debug, | ||
log << "CChannel::sendto: SENDING NOW DST=" << addr.str() << " target=@" << packet.m_iID | ||
<< " size=" << packet.getLength() << " pkt.ts=" << packet.m_iTimeStamp << " " << packet.Info()); | ||
#if ENABLE_HEAVY_LOGGING | ||
ostringstream dsrc; | ||
#ifdef SRT_ENABLE_PKTINFO | ||
dsrc << " sourceIP=" << (m_bBindMasked && !source_addr.isany() ? source_addr.str() : "default"); | ||
#endif | ||
|
||
LOGC(kslog.Debug, | ||
log << "CChannel::sendto: SENDING NOW DST=" << addr.str() << " target=@" << packet.m_iID | ||
<< " size=" << packet.getLength() << " pkt.ts=" << packet.m_iTimeStamp | ||
<< dsrc.str() << " " << packet.Info()); | ||
#endif | ||
|
||
#ifdef SRT_TEST_FAKE_LOSS | ||
|
||
|
@@ -683,8 +730,28 @@ int srt::CChannel::sendto(const sockaddr_any& addr, CPacket& packet) const | |
mh.msg_namelen = addr.size(); | ||
mh.msg_iov = (iovec*)packet.m_PacketVector; | ||
mh.msg_iovlen = 2; | ||
mh.msg_control = NULL; | ||
mh.msg_controllen = 0; | ||
bool have_set_src = false; | ||
|
||
#ifdef SRT_ENABLE_PKTINFO | ||
if (m_bBindMasked && !source_addr.isany()) | ||
{ | ||
if (!setSourceAddress(mh, source_addr)) | ||
{ | ||
LOGC(kslog.Error, log << "CChannel::setSourceAddress: source address invalid family #" << source_addr.family() << ", NOT setting."); | ||
} | ||
else | ||
{ | ||
HLOGC(kslog.Debug, log << "CChannel::setSourceAddress: setting as " << source_addr.str()); | ||
have_set_src = true; | ||
} | ||
} | ||
#endif | ||
|
||
if (!have_set_src) | ||
{ | ||
mh.msg_control = NULL; | ||
mh.msg_controllen = 0; | ||
} | ||
mh.msg_flags = 0; | ||
|
||
const int res = ::sendmsg(m_iSocket, &mh, 0); | ||
|
@@ -725,15 +792,33 @@ srt::EReadStatus srt::CChannel::recvfrom(sockaddr_any& w_addr, CPacket& w_packet | |
} | ||
|
||
#ifndef _WIN32 | ||
msghdr mh; // will not be used on failure | ||
|
||
if (select_ret > 0) | ||
{ | ||
msghdr mh; | ||
mh.msg_name = (w_addr.get()); | ||
mh.msg_namelen = w_addr.size(); | ||
mh.msg_iov = (w_packet.m_PacketVector); | ||
mh.msg_iovlen = 2; | ||
|
||
// Default | ||
mh.msg_control = NULL; | ||
mh.msg_controllen = 0; | ||
|
||
#ifdef SRT_ENABLE_PKTINFO | ||
// Without m_bBindMasked, we don't need ancillary data - the source | ||
// address will always be the bound address. | ||
if (m_bBindMasked) | ||
{ | ||
// Extract the destination IP address from the ancillary | ||
// data. This might be interesting for the connection to | ||
// know to which address the packet should be sent back during | ||
// the handshake and then addressed when sending during connection. | ||
mh.msg_control = (m_acCmsgRecvBuffer); | ||
mh.msg_controllen = sizeof m_acCmsgRecvBuffer; | ||
} | ||
#endif | ||
|
||
mh.msg_flags = 0; | ||
|
||
recv_size = ::recvmsg(m_iSocket, (&mh), 0); | ||
|
@@ -779,6 +864,17 @@ srt::EReadStatus srt::CChannel::recvfrom(sockaddr_any& w_addr, CPacket& w_packet | |
goto Return_error; | ||
} | ||
|
||
#ifdef SRT_ENABLE_PKTINFO | ||
if (m_bBindMasked) | ||
{ | ||
// Extract the address. Set it explicitly; if this returns address that isany(), | ||
// it will simply set this on the packet so that it behaves as if nothing was | ||
// extracted (it will "fail the old way"). | ||
w_packet.m_DestAddr = getTargetAddress(mh); | ||
HLOGC(krlog.Debug, log << CONID() << "(sys)recvmsg: ANY BOUND, retrieved DEST ADDR: " << w_packet.m_DestAddr.str()); | ||
} | ||
#endif | ||
|
||
#else | ||
// XXX REFACTORING NEEDED! | ||
// This procedure uses the WSARecvFrom function that just reads | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By treating these systems differently in the description I wanted to highlight the fact that in BSD systems this feature really isn't implemented and there's no known way to implement it, while in case of Windows it is possible, but the API used currently for sending and receiving UDP packets does not allow the use of CMSG messages. Such an API exists, so for Windows this would only require changing the API functions used for sending/receiving (use
WSASendMsg
instead ofWSASendTo
etc.).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I wouldn't go into such details - maybe this way:
Note that this feature is not supported on BSD systems (not possible due to lacking IP_PKTINFO feature). On Windows it is theoretically possible, but currently not implemented.