1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Upgrade libsrt to v1.5.3. v5.0.183 v6.0.81 (#3808)

fix https://github.com/ossrs/srs/issues/3155
Build srt-1-fit fails with `standard attributes in middle of
decl-specifiers` on GCC 12,Arch Linux.

See https://github.com/Haivision/srt/releases/tag/v1.5.3
This commit is contained in:
Haibo Chen 2023-09-21 22:23:56 +08:00 committed by GitHub
parent f9bba0a9b0
commit c5e067fb0b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
94 changed files with 5974 additions and 6273 deletions

View file

@ -326,6 +326,7 @@ SRTSOCKET srt::CUDTUnited::generateSocketID(bool for_group)
// We have a rollover on the socket value, so
// definitely we haven't made the Columbus mistake yet.
m_SocketIDGenerator = MAX_SOCKET_VAL;
sockval = MAX_SOCKET_VAL;
}
// Check all sockets if any of them has this value.
@ -459,10 +460,8 @@ SRTSOCKET srt::CUDTUnited::newSocket(CUDTSocket** pps)
// failure and rollback
delete ns;
ns = NULL;
}
if (!ns)
throw CUDTException(MJ_SYSTEMRES, MN_MEMORY, 0);
}
if (pps)
*pps = ns;
@ -563,7 +562,7 @@ int srt::CUDTUnited::newConnection(const SRTSOCKET listen,
}
catch (const CUDTException&)
{
LOGF(cnlog.Fatal, "newConnection: IPE: all sockets occupied? Last gen=%d", m_SocketIDGenerator);
LOGC(cnlog.Fatal, log << "newConnection: IPE: all sockets occupied? Last gen=" << m_SocketIDGenerator);
// generateSocketID throws exception, which can be naturally handled
// when the call is derived from the API call, but here it's called
// internally in response to receiving a handshake. It must be handled
@ -600,7 +599,8 @@ int srt::CUDTUnited::newConnection(const SRTSOCKET listen,
// this call causes sending the SRT Handshake through this socket.
// Without this mapping the socket cannot be found and therefore
// the SRT Handshake message would fail.
HLOGF(cnlog.Debug, "newConnection: incoming %s, mapping socket %d", peer.str().c_str(), ns->m_SocketID);
HLOGC(cnlog.Debug, log <<
"newConnection: incoming " << peer.str() << ", mapping socket " << ns->m_SocketID);
{
ScopedLock cg(m_GlobControlLock);
m_Sockets[ns->m_SocketID] = ns;
@ -619,7 +619,14 @@ int srt::CUDTUnited::newConnection(const SRTSOCKET listen,
// bind to the same addr of listening socket
ns->core().open();
updateListenerMux(ns, ls);
if (!updateListenerMux(ns, ls))
{
// This is highly unlikely if not impossible, but there's
// a theoretical runtime chance of failure so it should be
// handled
ns->core().m_RejectReason = SRT_REJ_IPE;
throw false; // let it jump directly into the omni exception handler
}
ns->core().acceptAndRespond(ls->m_SelfAddr, peer, hspkt, (w_hs));
}
@ -647,7 +654,8 @@ int srt::CUDTUnited::newConnection(const SRTSOCKET listen,
ScopedLock glock(m_GlobControlLock);
try
{
HLOGF(cnlog.Debug, "newConnection: mapping peer %d to that socket (%d)\n", ns->m_PeerID, ns->m_SocketID);
HLOGC(cnlog.Debug, log << "newConnection: mapping peer " << ns->m_PeerID
<< " to that socket (" << ns->m_SocketID << ")");
m_PeerRec[ns->getPeerSpec()].insert(ns->m_SocketID);
}
catch (...)
@ -666,7 +674,7 @@ int srt::CUDTUnited::newConnection(const SRTSOCKET listen,
// XXX this might require another check of group type.
// For redundancy group, at least, update the status in the group
CUDTGroup* g = ns->m_GroupOf;
ScopedLock glock(g->m_GroupLock);
ScopedLock grlock(g->m_GroupLock);
if (g->m_bClosing)
{
error = 1; // "INTERNAL REJECTION"
@ -911,6 +919,15 @@ int srt::CUDTUnited::bind(CUDTSocket* s, const sockaddr_any& name)
if (s->m_Status != SRTS_INIT)
throw CUDTException(MJ_NOTSUP, MN_NONE, 0);
if (s->core().m_config.iIpV6Only == -1 && name.family() == AF_INET6 && name.isany())
{
// V6ONLY option must be set explicitly if you want to bind to a wildcard address in IPv6
HLOGP(smlog.Error,
"bind: when binding to :: (IPv6 wildcard), SRTO_IPV6ONLY option must be set explicitly to 0 or 1");
throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
}
s->core().open();
updateMux(s, name);
s->m_Status = SRTS_OPENED;
@ -1078,7 +1095,7 @@ SRTSOCKET srt::CUDTUnited::accept(const SRTSOCKET listen, sockaddr* pw_addr, int
SRTSOCKET u = CUDT::INVALID_SOCK;
bool accepted = false;
// !!only one conection can be set up each time!!
// !!only one connection can be set up each time!!
while (!accepted)
{
UniqueLock accept_lock(ls->m_AcceptLock);
@ -1179,7 +1196,7 @@ SRTSOCKET srt::CUDTUnited::accept(const SRTSOCKET listen, sockaddr* pw_addr, int
int srt::CUDTUnited::connect(SRTSOCKET u, const sockaddr* srcname, const sockaddr* tarname, int namelen)
{
// Here both srcname and tarname must be specified
if (!srcname || !tarname || size_t(namelen) < sizeof(sockaddr_in))
if (!srcname || !tarname || namelen < int(sizeof(sockaddr_in)))
{
LOGC(aclog.Error,
log << "connect(with source): invalid call: srcname=" << srcname << " tarname=" << tarname
@ -1224,6 +1241,12 @@ int srt::CUDTUnited::connect(SRTSOCKET u, const sockaddr* srcname, const sockadd
int srt::CUDTUnited::connect(const SRTSOCKET u, const sockaddr* name, int namelen, int32_t forced_isn)
{
if (!name || namelen < int(sizeof(sockaddr_in)))
{
LOGC(aclog.Error, log << "connect(): invalid call: name=" << name << " namelen=" << namelen);
throw CUDTException(MJ_NOTSUP, MN_INVAL);
}
sockaddr_any target_addr(name, namelen);
if (target_addr.len == 0)
throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
@ -1458,7 +1481,7 @@ int srt::CUDTUnited::groupConnect(CUDTGroup* pg, SRT_SOCKGROUPCONFIG* targets, i
ns->m_GroupMemberData = f;
ns->m_GroupOf = &g;
f->weight = targets[tii].weight;
LOGC(aclog.Note, log << "srt_connect_group: socket @" << sid << " added to group $" << g.m_GroupID);
HLOGC(aclog.Debug, log << "srt_connect_group: socket @" << sid << " added to group $" << g.m_GroupID);
}
else
{
@ -1474,21 +1497,13 @@ int srt::CUDTUnited::groupConnect(CUDTGroup* pg, SRT_SOCKGROUPCONFIG* targets, i
// XXX This should be reenabled later, this should
// be probably still in use to exchange information about
// packets assymetrically lost. But for no other purpose.
// packets asymmetrically lost. But for no other purpose.
/*
ns->core().m_cbPacketArrival.set(ns->m_pUDT, &CUDT::groupPacketArrival);
*/
int isn = g.currentSchedSequence();
// Don't synchronize ISN in case of synch on msgno. Every link
// may send their own payloads independently.
if (g.synconmsgno())
{
HLOGC(aclog.Debug, log << "groupConnect: NOT synchronizing sequence numbers: will sync on msgno");
isn = -1;
}
// Set it the groupconnect option, as all in-group sockets should have.
ns->core().m_config.iGroupConnect = 1;
@ -1867,6 +1882,8 @@ int srt::CUDTUnited::connectIn(CUDTSocket* s, const sockaddr_any& target_addr, i
*/
try
{
// record peer address
s->m_PeerAddr = target_addr;
s->core().startConnect(target_addr, forced_isn);
}
catch (const CUDTException&) // Interceptor, just to change the state.
@ -1946,9 +1963,9 @@ void srt::CUDTUnited::deleteGroup_LOCKED(CUDTGroup* g)
int srt::CUDTUnited::close(CUDTSocket* s)
{
HLOGC(smlog.Debug, log << s->core().CONID() << " CLOSE. Acquiring control lock");
HLOGC(smlog.Debug, log << s->core().CONID() << "CLOSE. Acquiring control lock");
ScopedLock socket_cg(s->m_ControlLock);
HLOGC(smlog.Debug, log << s->core().CONID() << " CLOSING (removing from listening, closing CUDT)");
HLOGC(smlog.Debug, log << s->core().CONID() << "CLOSING (removing from listening, closing CUDT)");
const bool synch_close_snd = s->core().m_config.bSynSending;
@ -1971,14 +1988,16 @@ int srt::CUDTUnited::close(CUDTSocket* s)
// be unable to bind to this port that the about-to-delete listener
// is currently occupying (due to blocked slot in the RcvQueue).
HLOGC(smlog.Debug, log << s->core().CONID() << " CLOSING (removing listener immediately)");
HLOGC(smlog.Debug, log << s->core().CONID() << "CLOSING (removing listener immediately)");
s->core().notListening();
s->m_Status = SRTS_CLOSING;
// broadcast all "accept" waiting
CSync::lock_notify_all(s->m_AcceptCond, s->m_AcceptLock);
}
else
{
s->m_Status = SRTS_CLOSING;
// Note: this call may be done on a socket that hasn't finished
// sending all packets scheduled for sending, which means, this call
// may block INDEFINITELY. As long as it's acceptable to block the
@ -1989,7 +2008,7 @@ int srt::CUDTUnited::close(CUDTSocket* s)
// synchronize with garbage collection.
HLOGC(smlog.Debug,
log << "@" << u << "U::close done. GLOBAL CLOSE: " << s->core().CONID()
<< ". Acquiring GLOBAL control lock");
<< "Acquiring GLOBAL control lock");
ScopedLock manager_cg(m_GlobControlLock);
// since "s" is located before m_GlobControlLock, locate it again in case
// it became invalid
@ -2101,6 +2120,7 @@ int srt::CUDTUnited::close(CUDTSocket* s)
...
}
*/
CSync::notify_one_relaxed(m_GCStopCond);
return 0;
}
@ -2597,11 +2617,7 @@ void srt::CUDTUnited::checkBrokenSockets()
// NOT WHETHER THEY ARE ALSO READY TO PLAY at the time when
// this function is called (isRcvDataReady also checks if the
// available data is "ready to play").
#if ENABLE_NEW_RCVBUFFER
&& s->core().m_pRcvBuffer->hasAvailablePackets())
#else
&& s->core().m_pRcvBuffer->isRcvDataAvailable())
#endif
{
const int bc = s->core().m_iBrokenCounter.load();
if (bc > 0)
@ -2615,7 +2631,7 @@ void srt::CUDTUnited::checkBrokenSockets()
#if ENABLE_BONDING
if (s->m_GroupOf)
{
LOGC(smlog.Note,
HLOGC(smlog.Debug,
log << "@" << s->m_SocketID << " IS MEMBER OF $" << s->m_GroupOf->id() << " - REMOVING FROM GROUP");
s->removeFromGroup(true);
}
@ -2644,7 +2660,7 @@ void srt::CUDTUnited::checkBrokenSockets()
for (sockets_t::iterator j = m_ClosedSockets.begin(); j != m_ClosedSockets.end(); ++j)
{
// HLOGF(smlog.Debug, "checking CLOSED socket: %d\n", j->first);
// HLOGC(smlog.Debug, log << "checking CLOSED socket: " << j->first);
if (!is_zero(j->second->core().m_tsLingerExpiration))
{
// asynchronous close:
@ -2671,7 +2687,7 @@ void srt::CUDTUnited::checkBrokenSockets()
log << "checkBrokenSockets: @" << j->second->m_SocketID << " closed "
<< FormatDuration(closed_ago) << " ago and removed from RcvQ - will remove");
// HLOGF(smlog.Debug, "will unref socket: %d\n", j->first);
// HLOGC(smlog.Debug, log << "will unref socket: " << j->first);
tbr.push_back(j->first);
}
}
@ -2826,12 +2842,41 @@ uint16_t srt::CUDTUnited::installMuxer(CUDTSocket* w_s, CMultiplexer& fw_sm)
return sa.hport();
}
bool srt::CUDTUnited::channelSettingsMatch(const CSrtMuxerConfig& cfgMuxer, const CSrtConfig& cfgSocket)
bool srt::CUDTUnited::inet6SettingsCompat(const sockaddr_any& muxaddr, const CSrtMuxerConfig& cfgMuxer,
const sockaddr_any& reqaddr, const CSrtMuxerConfig& cfgSocket)
{
return cfgMuxer.bReuseAddr && cfgMuxer == cfgSocket;
if (muxaddr.family() != AF_INET6)
return true; // Don't check - the family has been checked already
if (reqaddr.isany())
{
if (cfgSocket.iIpV6Only == -1) // Treat as "adaptive"
return true;
// If set explicitly, then it must be equal to the one of found muxer.
return cfgSocket.iIpV6Only == cfgMuxer.iIpV6Only;
}
// If binding to the certain IPv6 address, then this setting doesn't matter.
return true;
}
void srt::CUDTUnited::updateMux(CUDTSocket* s, const sockaddr_any& addr, const UDPSOCKET* udpsock /*[[nullable]]*/)
bool srt::CUDTUnited::channelSettingsMatch(const CSrtMuxerConfig& cfgMuxer, const CSrtConfig& cfgSocket)
{
if (!cfgMuxer.bReuseAddr)
{
HLOGP(smlog.Debug, "channelSettingsMatch: fail: the multiplexer is not reusable");
return false;
}
if (cfgMuxer.isCompatWith(cfgSocket))
return true;
HLOGP(smlog.Debug, "channelSettingsMatch: fail: some options have different values");
return false;
}
void srt::CUDTUnited::updateMux(CUDTSocket* s, const sockaddr_any& reqaddr, const UDPSOCKET* udpsock /*[[nullable]]*/)
{
ScopedLock cg(m_GlobControlLock);
@ -2844,9 +2889,23 @@ void srt::CUDTUnited::updateMux(CUDTSocket* s, const sockaddr_any& addr, const U
{
// If not, we need to see if there exist already a multiplexer bound
// to the same endpoint.
const int port = addr.hport();
const int port = reqaddr.hport();
const CSrtConfig& cfgSocket = s->core().m_config;
// This loop is going to check the attempted binding of
// address:port and socket settings against every existing
// multiplexer. Possible results of the check are:
// 1. MATCH: identical address - reuse it and quit.
// 2. CONFLICT: report error: the binding partially overlaps
// so it neither can be reused nor is free to bind.
// 3. PASS: different and not overlapping - continue searching.
// In this function the convention is:
// MATCH: do nothing and proceed with binding reusage, THEN break.
// CONFLICT: throw an exception.
// PASS: use 'continue' to pass to the next element.
bool reuse_attempt = false;
for (map<int, CMultiplexer>::iterator i = m_mMultiplexer.begin(); i != m_mMultiplexer.end(); ++i)
{
@ -2862,74 +2921,166 @@ void srt::CUDTUnited::updateMux(CUDTSocket* s, const sockaddr_any& addr, const U
}
// If this is bound to the wildcard address, it can be reused if:
// - addr is also a wildcard
// - reqaddr is also a wildcard
// - channel settings match
// Otherwise it's a conflict.
sockaddr_any sa;
m.m_pChannel->getSockAddr((sa));
sockaddr_any mux_addr;
m.m_pChannel->getSockAddr((mux_addr));
HLOGC(smlog.Debug,
log << "bind: Found existing muxer @" << m.m_iID << " : " << sa.str() << " - check against "
<< addr.str());
log << "bind: Found existing muxer @" << m.m_iID << " : " << mux_addr.str() << " - check against "
<< reqaddr.str());
if (sa.isany())
if (mux_addr.isany())
{
if (!addr.isany())
if (mux_addr.family() == AF_INET6)
{
LOGC(smlog.Error,
log << "bind: Address: " << addr.str()
<< " conflicts with existing wildcard binding: " << sa.str());
throw CUDTException(MJ_NOTSUP, MN_BUSYPORT, 0);
// With IPv6 we need to research two possibilities:
// iIpV6Only == 1 -> This means that it binds only :: wildcard, but not 0.0.0.0
// iIpV6Only == 0 -> This means that it binds both :: and 0.0.0.0.
// iIpV6Only == -1 -> Hard to say what to do, but treat it as a potential conflict in any doubtful case.
if (m.m_mcfg.iIpV6Only == 1)
{
// PASS IF: candidate is IPv4, no matter the address
// MATCH IF: candidate is IPv6 with only=1
// CONFLICT IF: candidate is IPv6 with only != 1 or IPv6 non-wildcard.
if (reqaddr.family() == AF_INET)
{
HLOGC(smlog.Debug, log << "bind: muxer @" << m.m_iID
<< " is :: v6only - requested IPv4 ANY is NOT IN THE WAY. Searching on.");
continue;
}
// Candidate is AF_INET6
if (cfgSocket.iIpV6Only != 1 || !reqaddr.isany())
{
// CONFLICT:
// 1. attempting to make a wildcard IPv4 + IPv6
// while the multiplexer for wildcard IPv6 exists.
// 2. If binding to a given address, it conflicts with the wildcard
LOGC(smlog.Error,
log << "bind: Address: " << reqaddr.str()
<< " conflicts with existing IPv6 wildcard binding: " << mux_addr.str());
throw CUDTException(MJ_NOTSUP, MN_BUSYPORT, 0);
}
// Otherwise, MATCH.
}
else if (m.m_mcfg.iIpV6Only == 0)
{
// Muxer's address is a wildcard for :: and 0.0.0.0 at once.
// This way only IPv6 wildcard with v6only=0 is a perfect match and everything
// else is a conflict.
if (reqaddr.family() == AF_INET6 && reqaddr.isany() && cfgSocket.iIpV6Only == 0)
{
// MATCH
}
else
{
// CONFLICT: attempting to make a wildcard IPv4 + IPv6 while
// the multiplexer for wildcard IPv6 exists.
LOGC(smlog.Error,
log << "bind: Address: " << reqaddr.str() << " v6only=" << cfgSocket.iIpV6Only
<< " conflicts with existing IPv6 + IPv4 wildcard binding: " << mux_addr.str());
throw CUDTException(MJ_NOTSUP, MN_BUSYPORT, 0);
}
}
else // Case -1, by unknown reason. Accept only with -1 setting, others are conflict.
{
if (reqaddr.family() == AF_INET6 && reqaddr.isany() && cfgSocket.iIpV6Only == -1)
{
// MATCH
}
else
{
LOGC(smlog.Error,
log << "bind: Address: " << reqaddr.str() << " v6only=" << cfgSocket.iIpV6Only
<< " conflicts with existing IPv6 v6only=unknown wildcard binding: " << mux_addr.str());
throw CUDTException(MJ_NOTSUP, MN_BUSYPORT, 0);
}
}
}
else // muxer is IPv4 wildcard
{
// Then only IPv4 wildcard is a match and:
// - IPv6 with only=true is PASS (not a conflict)
// - IPv6 with only=false is CONFLICT
// - IPv6 with only=undefined is CONFLICT
// REASON: we need to make a potential conflict a conflict as there will be
// no bind() call to check if this wouldn't be a conflict in result. If you want
// to have a binding to IPv6 that should avoid conflict with IPv4 wildcard binding,
// then SRTO_IPV6ONLY option must be explicitly set before binding.
// Also:
if (reqaddr.family() == AF_INET)
{
if (reqaddr.isany())
{
// MATCH
}
else
{
LOGC(smlog.Error,
log << "bind: Address: " << reqaddr.str()
<< " conflicts with existing IPv4 wildcard binding: " << mux_addr.str());
throw CUDTException(MJ_NOTSUP, MN_BUSYPORT, 0);
}
}
else // AF_INET6
{
if (cfgSocket.iIpV6Only == 1 || !reqaddr.isany())
{
// PASS
HLOGC(smlog.Debug, log << "bind: muxer @" << m.m_iID
<< " is IPv4 wildcard - requested " << reqaddr.str() << " v6only=" << cfgSocket.iIpV6Only
<< " is NOT IN THE WAY. Searching on.");
continue;
}
else
{
LOGC(smlog.Error,
log << "bind: Address: " << reqaddr.str() << " v6only=" << cfgSocket.iIpV6Only
<< " conflicts with existing IPv4 wildcard binding: " << mux_addr.str());
throw CUDTException(MJ_NOTSUP, MN_BUSYPORT, 0);
}
}
}
// Still, for ANY you need either the same family, or open
// for families.
if (m.m_mcfg.iIpV6Only != -1 && m.m_mcfg.iIpV6Only != cfgSocket.iIpV6Only)
{
LOGC(smlog.Error,
log << "bind: Address: " << addr.str()
<< " conflicts with existing IPv6 wildcard binding: " << sa.str());
throw CUDTException(MJ_NOTSUP, MN_BUSYPORT, 0);
}
if ((m.m_mcfg.iIpV6Only == 0 || cfgSocket.iIpV6Only == 0) && m.m_iIPversion != addr.family())
{
LOGC(smlog.Error,
log << "bind: Address: " << addr.str() << " conflicts with IPv6 wildcard binding: " << sa.str()
<< " : family " << (m.m_iIPversion == AF_INET ? "IPv4" : "IPv6") << " vs. "
<< (addr.family() == AF_INET ? "IPv4" : "IPv6"));
throw CUDTException(MJ_NOTSUP, MN_BUSYPORT, 0);
}
reuse_attempt = true;
HLOGC(smlog.Debug, log << "bind: wildcard address - multiplexer reusable");
}
else if (addr.isany() && addr.family() == sa.family())
// Muxer address is NOT a wildcard, so conflicts only with WILDCARD of the same type
else if (reqaddr.isany() && reqaddr.family() == mux_addr.family())
{
LOGC(smlog.Error,
log << "bind: Wildcard address: " << addr.str()
<< " conflicts with existting IP binding: " << sa.str());
log << "bind: Wildcard address: " << reqaddr.str()
<< " conflicts with existting IP binding: " << mux_addr.str());
throw CUDTException(MJ_NOTSUP, MN_BUSYPORT, 0);
}
// If this is bound to a certain address, AND:
else if (sa.equal_address(addr))
else if (mux_addr.equal_address(reqaddr))
{
// - the address is the same as addr
// - the address is the same as reqaddr
reuse_attempt = true;
HLOGC(smlog.Debug, log << "bind: same IP address - multiplexer reusable");
}
else
{
HLOGC(smlog.Debug, log << "bind: IP addresses differ - ALLOWED to create a new multiplexer");
continue;
}
// Otherwise:
// - the address is different than addr
// - the address is different than reqaddr
// - the address can't be reused, but this can go on with new one.
// If this is a reusage attempt:
if (reuse_attempt)
{
// - if the channel settings match, it can be reused
if (channelSettingsMatch(m.m_mcfg, cfgSocket))
if (channelSettingsMatch(m.m_mcfg, cfgSocket) && inet6SettingsCompat(mux_addr, m.m_mcfg, reqaddr, cfgSocket))
{
HLOGC(smlog.Debug, log << "bind: reusing multiplexer for port " << port);
// reuse the existing multiplexer
@ -2941,7 +3092,7 @@ void srt::CUDTUnited::updateMux(CUDTSocket* s, const sockaddr_any& addr, const U
{
// - if not, it's a conflict
LOGC(smlog.Error,
log << "bind: Address: " << addr.str() << " conflicts with binding: " << sa.str()
log << "bind: Address: " << reqaddr.str() << " conflicts with binding: " << mux_addr.str()
<< " due to channel settings");
throw CUDTException(MJ_NOTSUP, MN_BUSYPORT, 0);
}
@ -2950,13 +3101,15 @@ void srt::CUDTUnited::updateMux(CUDTSocket* s, const sockaddr_any& addr, const U
// candidates, proceed with creating a new multiplexer.
// Note that a binding to a different IP address is not treated
// as a candidate for either reuseage or conflict.
// as a candidate for either reusage or conflict.
LOGC(smlog.Fatal, log << "SHOULD NOT GET HERE!!!");
SRT_ASSERT(false);
}
}
// a new multiplexer is needed
CMultiplexer m;
configureMuxer((m), s, addr.family());
configureMuxer((m), s, reqaddr.family());
try
{
@ -2965,25 +3118,39 @@ void srt::CUDTUnited::updateMux(CUDTSocket* s, const sockaddr_any& addr, const U
if (udpsock)
{
// In this case, addr contains the address
// In this case, reqaddr contains the address
// that has been extracted already from the
// given socket
m.m_pChannel->attach(*udpsock, addr);
m.m_pChannel->attach(*udpsock, reqaddr);
}
else if (addr.empty())
else if (reqaddr.empty())
{
// The case of previously used case of a NULL address.
// This here is used to pass family only, in this case
// just automatically bind to the "0" address to autoselect
// everything.
m.m_pChannel->open(addr.family());
m.m_pChannel->open(reqaddr.family());
}
else
{
// If at least the IP address is specified, then bind to that
// address, but still possibly autoselect the outgoing port, if the
// port was specified as 0.
m.m_pChannel->open(addr);
m.m_pChannel->open(reqaddr);
}
// AFTER OPENING, check the matter of IPV6_V6ONLY option,
// as it decides about the fact that the occupied binding address
// in case of wildcard is both :: and 0.0.0.0, or only ::.
if (reqaddr.family() == AF_INET6 && m.m_mcfg.iIpV6Only == -1)
{
// XXX We don't know how probable it is to get the error here
// and resulting -1 value. As a fallback for that case, the value -1
// is honored here, just all side-bindings for other sockes will be
// rejected as a potential conflict, even if binding would be accepted
// in these circumstances. Only a perfect match in case of potential
// overlapping will be accepted on the same port.
m.m_mcfg.iIpV6Only = m.m_pChannel->sockopt(IPPROTO_IPV6, IPV6_V6ONLY, -1);
}
m.m_pTimer = new CTimer;
@ -3032,8 +3199,14 @@ bool srt::CUDTUnited::updateListenerMux(CUDTSocket* s, const CUDTSocket* ls)
CMultiplexer* mux = map_getp(m_mMultiplexer, ls->m_iMuxID);
// NOTE:
// THIS BELOW CODE is only for a highly unlikely, and probably buggy,
// situation when the Multiplexer wasn't found by ID recorded in the listener.
// THIS BELOW CODE is only for a highly unlikely situation when the listener
// socket has been closed in the meantime when the accepted socket is being
// processed. This procedure is different than updateMux because this time we
// only want to have a multiplexer socket to be assigned to the accepted socket.
// It is also unlikely that the listener socket is garbage-collected so fast, so
// this procedure will most likely find the multiplexer of the zombie listener socket,
// which no longer accepts new connections (the listener is withdrawn immediately from
// the port) that wasn't yet completely deleted.
CMultiplexer* fallback = NULL;
if (!mux)
{
@ -3060,8 +3233,9 @@ bool srt::CUDTUnited::updateListenerMux(CUDTSocket* s, const CUDTSocket* ls)
mux = &m; // best match
break;
}
else
else if (m.m_iIPversion == AF_INET6)
{
// Allowed fallback case when we only need an accepted socket.
fallback = &m;
}
}
@ -4369,7 +4543,7 @@ int epoll_wait2(int eid,
int* lwnum)
{
// This API is an alternative format for epoll_wait, created for
// compatability with other languages. Users need to pass in an array
// compatibility with other languages. Users need to pass in an array
// for holding the returned sockets, with the maximum array length
// stored in *rnum, etc., which will be updated with returned number
// of sockets.