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

SRT: Upgrade libsrt from 1.4.1 to 1.5.1. v6.0.12 (#3362)

Co-authored-by: winlin <winlin@vip.126.com>
This commit is contained in:
john 2023-01-04 19:56:33 +08:00 committed by GitHub
parent 7a56208f2f
commit fe086dfc31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
143 changed files with 38185 additions and 15108 deletions

269
trunk/3rdparty/srt-1-fit/srtcore/epoll.h vendored Executable file → Normal file
View file

@ -50,8 +50,8 @@ modified by
Haivision Systems Inc.
*****************************************************************************/
#ifndef __UDT_EPOLL_H__
#define __UDT_EPOLL_H__
#ifndef INC_SRT_EPOLL_H
#define INC_SRT_EPOLL_H
#include <map>
@ -59,8 +59,15 @@ modified by
#include <list>
#include "udt.h"
namespace srt
{
struct CEPollDesc
class CUDT;
class CRendezvousQueue;
class CUDTGroup;
class CEPollDesc
{
const int m_iID; // epoll ID
@ -86,40 +93,62 @@ struct CEPollDesc
{
/// Events the subscriber is interested with. Only those will be
/// regarded when updating event flags.
int watch;
int32_t watch;
/// Which events should be edge-triggered. When the event isn't
/// mentioned in `watch`, this bit flag is disregarded. Otherwise
/// it means that the event is to be waited for persistent state
/// if this flag is not present here, and for edge trigger, if
/// the flag is present here.
int edge;
int32_t edge;
/// The current persistent state. This is usually duplicated in
/// a dedicated state object in `m_USockEventNotice`, however the state
/// here will stay forever as is, regardless of the edge/persistent
/// subscription mode for the event.
int state;
int32_t state;
/// The iterator to `m_USockEventNotice` container that contains the
/// event notice object for this subscription, or the value from
/// `nullNotice()` if there is no such object.
enotice_t::iterator notit;
Wait(int sub, bool etr, enotice_t::iterator i)
Wait(explicit_t<int32_t> sub, explicit_t<int32_t> etr, enotice_t::iterator i)
:watch(sub)
,edge(etr ? sub : 0)
,edge(etr)
,state(0)
,notit(i)
{
}
int edgeOnly() { return edge & watch; }
/// Clear all flags for given direction from the notices
/// and subscriptions, and checks if this made the event list
/// for this watch completely empty.
/// @param direction event type that has to be cleared
/// @return true, if this cleared the last event (the caller
/// want to remove the subscription for this socket)
bool clear(int32_t direction)
{
if (watch & direction)
{
watch &= ~direction;
edge &= ~direction;
state &= ~direction;
return watch == 0;
}
return false;
}
};
typedef std::map<SRTSOCKET, Wait> ewatch_t;
private:
#if ENABLE_HEAVY_LOGGING
std::string DisplayEpollWatch();
#endif
/// Sockets that are subscribed for events in this eid.
ewatch_t m_USockWatchState;
@ -135,7 +164,10 @@ private:
enotice_t::iterator nullNotice() { return m_USockEventNotice.end(); }
public:
// Only CEPoll class should have access to it.
// Guarding private access to the class is not necessary
// within the epoll module.
friend class CEPoll;
CEPollDesc(int id, int localID)
: m_iID(id)
@ -147,13 +179,13 @@ public:
static const int32_t EF_NOCHECK_EMPTY = 1 << 0;
static const int32_t EF_CHECK_REP = 1 << 1;
int32_t flags() { return m_Flags; }
bool flags(int32_t f) { return (m_Flags & f) != 0; }
int32_t flags() const { return m_Flags; }
bool flags(int32_t f) const { return (m_Flags & f) != 0; }
void set_flags(int32_t flg) { m_Flags |= flg; }
void clr_flags(int32_t flg) { m_Flags &= ~flg; }
// Container accessors for ewatch_t.
bool watch_empty() { return m_USockWatchState.empty(); }
bool watch_empty() const { return m_USockWatchState.empty(); }
Wait* watch_find(SRTSOCKET sock)
{
ewatch_t::iterator i = m_USockWatchState.find(sock);
@ -165,13 +197,16 @@ public:
// Container accessors for enotice_t.
enotice_t::iterator enotice_begin() { return m_USockEventNotice.begin(); }
enotice_t::iterator enotice_end() { return m_USockEventNotice.end(); }
enotice_t::const_iterator enotice_begin() const { return m_USockEventNotice.begin(); }
enotice_t::const_iterator enotice_end() const { return m_USockEventNotice.end(); }
bool enotice_empty() const { return m_USockEventNotice.empty(); }
const int m_iLocalID; // local system epoll ID
std::set<SYSSOCKET> m_sLocals; // set of local (non-UDT) descriptors
std::pair<ewatch_t::iterator, bool> addWatch(SRTSOCKET sock, int32_t events, bool edgeTrg)
std::pair<ewatch_t::iterator, bool> addWatch(SRTSOCKET sock, explicit_t<int32_t> events, explicit_t<int32_t> et_events)
{
return m_USockWatchState.insert(std::make_pair(sock, Wait(events, edgeTrg, nullNotice())));
return m_USockWatchState.insert(std::make_pair(sock, Wait(events, et_events, nullNotice())));
}
void addEventNotice(Wait& wait, SRTSOCKET sock, int events)
@ -224,6 +259,12 @@ public:
m_USockWatchState.erase(i);
}
void clearAll()
{
m_USockEventNotice.clear();
m_USockWatchState.clear();
}
void removeExistingNotices(Wait& wait)
{
m_USockEventNotice.erase(wait.notit);
@ -281,12 +322,44 @@ public:
}
return false;
}
/// This should work in a loop around the notice container of
/// the given eid container and clear out the notice for
/// particular event type. If this has cleared effectively the
/// last existing event, it should return the socket id
/// so that the caller knows to remove it also from subscribers.
///
/// @param i iterator in the notice container
/// @param event event type to be cleared
/// @retval (socket) Socket to be removed from subscriptions
/// @retval SRT_INVALID_SOCK Nothing to be done (associated socket
/// still has other subscriptions)
SRTSOCKET clearEventSub(enotice_t::iterator i, int event)
{
// We need to remove the notice and subscription
// for this event. The 'i' iterator is safe to
// delete, even indirectly.
// This works merely like checkEdge, just on request to clear the
// identified event, if found.
if (i->events & event)
{
// The notice has a readiness flag on this event.
// This means that there exists also a subscription.
Wait* w = i->parent;
if (w->clear(event))
return i->fd;
}
return SRT_INVALID_SOCK;
}
};
class CEPoll
{
friend class CUDT;
friend class CRendezvousQueue;
friend class srt::CUDT;
friend class srt::CUDTGroup;
friend class srt::CRendezvousQueue;
public:
CEPoll();
@ -294,90 +367,122 @@ public:
public: // for CUDTUnited API
/// create a new EPoll.
/// @return new EPoll ID if success, otherwise an error number.
/// create a new EPoll.
/// @return new EPoll ID if success, otherwise an error number.
int create(CEPollDesc** ppd = 0);
int create();
/// add a UDT socket to an EPoll.
/// @param [in] eid EPoll ID.
/// @param [in] u UDT Socket ID.
/// @param [in] events events to watch.
/// @return 0 if success, otherwise an error number.
/// delete all user sockets (SRT sockets) from an EPoll
/// @param [in] eid EPoll ID.
/// @return 0
int clear_usocks(int eid);
int add_usock(const int eid, const SRTSOCKET& u, const int* events = NULL) { return update_usock(eid, u, events); }
/// add a system socket to an EPoll.
/// @param [in] eid EPoll ID.
/// @param [in] s system Socket ID.
/// @param [in] events events to watch.
/// @return 0 if success, otherwise an error number.
/// add a system socket to an EPoll.
/// @param [in] eid EPoll ID.
/// @param [in] s system Socket ID.
/// @param [in] events events to watch.
/// @return 0 if success, otherwise an error number.
int add_ssock(const int eid, const SYSSOCKET& s, const int* events = NULL);
/// remove a UDT socket event from an EPoll; socket will be removed if no events to watch.
/// @param [in] eid EPoll ID.
/// @param [in] u UDT socket ID.
/// @return 0 if success, otherwise an error number.
int remove_usock(const int eid, const SRTSOCKET& u) { static const int Null(0); return update_usock(eid, u, &Null);}
/// remove a system socket event from an EPoll; socket will be removed if no events to watch.
/// @param [in] eid EPoll ID.
/// @param [in] s system socket ID.
/// @return 0 if success, otherwise an error number.
/// remove a system socket event from an EPoll; socket will be removed if no events to watch.
/// @param [in] eid EPoll ID.
/// @param [in] s system socket ID.
/// @return 0 if success, otherwise an error number.
int remove_ssock(const int eid, const SYSSOCKET& s);
/// update a UDT socket events from an EPoll.
/// @param [in] eid EPoll ID.
/// @param [in] u UDT socket ID.
/// @param [in] events events to watch.
/// @return 0 if success, otherwise an error number.
/// update a UDT socket events from an EPoll.
/// @param [in] eid EPoll ID.
/// @param [in] u UDT socket ID.
/// @param [in] events events to watch.
/// @return 0 if success, otherwise an error number.
int update_usock(const int eid, const SRTSOCKET& u, const int* events);
/// update a system socket events from an EPoll.
/// @param [in] eid EPoll ID.
/// @param [in] u UDT socket ID.
/// @param [in] events events to watch.
/// @return 0 if success, otherwise an error number.
/// update a system socket events from an EPoll.
/// @param [in] eid EPoll ID.
/// @param [in] u UDT socket ID.
/// @param [in] events events to watch.
/// @return 0 if success, otherwise an error number.
int update_ssock(const int eid, const SYSSOCKET& s, const int* events = NULL);
/// wait for EPoll events or timeout.
/// @param [in] eid EPoll ID.
/// @param [out] readfds UDT sockets available for reading.
/// @param [out] writefds UDT sockets available for writing.
/// @param [in] msTimeOut timeout threshold, in milliseconds.
/// @param [out] lrfds system file descriptors for reading.
/// @param [out] lwfds system file descriptors for writing.
/// @return number of sockets available for IO.
/// wait for EPoll events or timeout.
/// @param [in] eid EPoll ID.
/// @param [out] readfds UDT sockets available for reading.
/// @param [out] writefds UDT sockets available for writing.
/// @param [in] msTimeOut timeout threshold, in milliseconds.
/// @param [out] lrfds system file descriptors for reading.
/// @param [out] lwfds system file descriptors for writing.
/// @return number of sockets available for IO.
int wait(const int eid, std::set<SRTSOCKET>* readfds, std::set<SRTSOCKET>* writefds, int64_t msTimeOut, std::set<SYSSOCKET>* lrfds, std::set<SYSSOCKET>* lwfds);
/// wait for EPoll events or timeout optimized with explicit EPOLL_ERR event and the edge mode option.
/// @param [in] eid EPoll ID.
/// @param [out] fdsSet array of user socket events (SRT_EPOLL_IN | SRT_EPOLL_OUT | SRT_EPOLL_ERR).
/// @param [int] fdsSize of fds array
/// @param [in] msTimeOut timeout threshold, in milliseconds.
/// @return total of available events in the epoll system (can be greater than fdsSize)
typedef std::map<SRTSOCKET, int> fmap_t;
/// Lightweit and more internal-reaching version of `uwait` for internal use only.
/// This function wait for sockets to be ready and reports them in `st` map.
///
/// @param d the internal structure of the epoll container
/// @param st output container for the results: { socket_type, event }
/// @param msTimeOut timeout after which return with empty output is allowed
/// @param report_by_exception if true, errors will result in exception intead of returning -1
/// @retval -1 error occurred
/// @retval >=0 number of ready sockets (actually size of `st`)
int swait(CEPollDesc& d, fmap_t& st, int64_t msTimeOut, bool report_by_exception = true);
/// Empty subscription check - for internal use only.
bool empty(const CEPollDesc& d) const;
/// Reports which events are ready on the given socket.
/// @param mp socket event map retirned by `swait`
/// @param sock which socket to ask
/// @return event flags for given socket, or 0 if none
static int ready(const fmap_t& mp, SRTSOCKET sock)
{
fmap_t::const_iterator y = mp.find(sock);
if (y == mp.end())
return 0;
return y->second;
}
/// Reports whether socket is ready for given event.
/// @param mp socket event map retirned by `swait`
/// @param sock which socket to ask
/// @param event which events it should be ready for
/// @return true if the given socket is ready for given event
static bool isready(const fmap_t& mp, SRTSOCKET sock, SRT_EPOLL_OPT event)
{
return (ready(mp, sock) & event) != 0;
}
// Could be a template directly, but it's now hidden in the imp file.
void clear_ready_usocks(CEPollDesc& d, int direction);
/// wait for EPoll events or timeout optimized with explicit EPOLL_ERR event and the edge mode option.
/// @param [in] eid EPoll ID.
/// @param [out] fdsSet array of user socket events (SRT_EPOLL_IN | SRT_EPOLL_OUT | SRT_EPOLL_ERR).
/// @param [int] fdsSize of fds array
/// @param [in] msTimeOut timeout threshold, in milliseconds.
/// @return total of available events in the epoll system (can be greater than fdsSize)
int uwait(const int eid, SRT_EPOLL_EVENT* fdsSet, int fdsSize, int64_t msTimeOut);
/// close and release an EPoll.
/// @param [in] eid EPoll ID.
/// @return 0 if success, otherwise an error number.
/// close and release an EPoll.
/// @param [in] eid EPoll ID.
/// @return 0 if success, otherwise an error number.
int release(const int eid);
public: // for CUDT to acknowledge IO status
/// Update events available for a UDT socket.
/// @param [in] uid UDT socket ID.
/// @param [in] eids EPoll IDs to be set
/// @param [in] events Combination of events to update
/// @param [in] enable true -> enable, otherwise disable
/// @return 0 if success, otherwise an error number
/// Update events available for a UDT socket. At the end this function
/// counts the number of updated EIDs with given events.
/// @param [in] uid UDT socket ID.
/// @param [in] eids EPoll IDs to be set
/// @param [in] events Combination of events to update
/// @param [in] enable true -> enable, otherwise disable
/// @return -1 if invalid events, otherwise the number of changes
int update_events(const SRTSOCKET& uid, std::set<int>& eids, int events, bool enable);
@ -385,11 +490,17 @@ public: // for CUDT to acknowledge IO status
private:
int m_iIDSeed; // seed to generate a new ID
pthread_mutex_t m_SeedLock;
srt::sync::Mutex m_SeedLock;
std::map<int, CEPollDesc> m_mPolls; // all epolls
pthread_mutex_t m_EPollLock;
mutable srt::sync::Mutex m_EPollLock;
};
#if ENABLE_HEAVY_LOGGING
std::string DisplayEpollResults(const std::map<SRTSOCKET, int>& sockset);
#endif
} // namespace srt
#endif