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:
parent
f9bba0a9b0
commit
c5e067fb0b
94 changed files with 5974 additions and 6273 deletions
340
trunk/3rdparty/srt-1-fit/srtcore/api.cpp
vendored
340
trunk/3rdparty/srt-1-fit/srtcore/api.cpp
vendored
|
@ -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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue