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

View file

@ -1,11 +1,11 @@
/*
* SRT - Secure, Reliable, Transport
* Copyright (c) 2018 Haivision Systems Inc.
*
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*
*/
/*****************************************************************************
@ -50,13 +50,12 @@ modified by
Haivision Systems Inc.
*****************************************************************************/
#ifndef INC_SRT_QUEUE_H
#define INC_SRT_QUEUE_H
#ifndef __UDT_QUEUE_H__
#define __UDT_QUEUE_H__
#include "channel.h"
#include "common.h"
#include "packet.h"
#include "socketconfig.h"
#include "netinet_any.h"
#include "utilities.h"
#include <list>
@ -64,485 +63,548 @@ modified by
#include <queue>
#include <vector>
namespace srt
{
class CChannel;
class CUDT;
struct CUnit
{
CPacket m_Packet; // packet
enum Flag { FREE = 0, GOOD = 1, PASSACK = 2, DROPPED = 3 };
Flag m_iFlag; // 0: free, 1: occupied, 2: msg read but not freed (out-of-order), 3: msg dropped
CPacket m_Packet; // packet
enum Flag
{
FREE = 0,
GOOD = 1,
PASSACK = 2,
DROPPED = 3
};
// TODO: The new RcvBuffer allows to use atomic_bool here.
sync::atomic<Flag> m_iFlag; // 0: free, 1: occupied, 2: msg read but not freed (out-of-order), 3: msg dropped
};
class CUnitQueue
{
public:
/// @brief Construct a unit queue.
/// @param mss Initial number of units to allocate.
/// @param mss Maximum segment size meaning the size of each unit.
/// @throws CUDTException SRT_ENOBUF.
CUnitQueue(int initNumUnits, int mss);
~CUnitQueue();
public:
CUnitQueue();
~CUnitQueue();
public: // Storage size operations
/// Initialize the unit queue.
/// @param [in] size queue size
/// @param [in] mss maximum segment size
/// @param [in] version IP version
/// @return 0: success, -1: failure.
int init(int size, int mss, int version);
/// Increase (double) the unit queue size.
/// @return 0: success, -1: failure.
int increase();
/// Decrease (halve) the unit queue size.
/// @return 0: success, -1: failure.
int shrink();
public: // Operations on units
/// find an available unit for incoming packet.
/// @return Pointer to the available unit, NULL if not found.
CUnit* getNextAvailUnit();
void makeUnitFree(CUnit * unit);
void makeUnitGood(CUnit * unit);
int capacity() const { return m_iSize; }
int size() const { return m_iSize - m_iNumTaken; }
public:
/// @brief Find an available unit for incoming packet. Allocate new units if 90% or more are in use.
/// @note This function is not thread-safe. Currently only CRcvQueue::worker thread calls it, thus
/// it is not an issue. However, must be protected if used from several threads in the future.
/// @return Pointer to the available unit, NULL if not found.
CUnit* getNextAvailUnit();
inline int getIPversion() const { return m_iIPversion; }
void makeUnitFree(CUnit* unit);
void makeUnitGood(CUnit* unit);
private:
struct CQEntry
{
CUnit* m_pUnit; // unit queue
char* m_pBuffer; // data buffer
int m_iSize; // size of each queue
struct CQEntry
{
CUnit* m_pUnit; // unit queue
char* m_pBuffer; // data buffer
int m_iSize; // size of each queue
CQEntry* m_pNext;
}
*m_pQEntry, // pointer to the first unit queue
*m_pCurrQueue, // pointer to the current available queue
*m_pLastQueue; // pointer to the last unit queue
CQEntry* m_pNext;
};
CUnit* m_pAvailUnit; // recent available unit
/// Increase the unit queue size (by @a m_iBlockSize units).
/// Uses m_mtx to protect access and changes of the queue state.
/// @return 0: success, -1: failure.
int increase_();
int m_iSize; // total size of the unit queue, in number of packets
int m_iCount; // total number of valid packets in the queue
int m_iMSS; // unit buffer size
int m_iIPversion; // IP version
/// @brief Allocated a CQEntry of iNumUnits with each unit of mss bytes.
/// @param iNumUnits a number of units to allocate
/// @param mss the size of each unit in bytes.
/// @return a pointer to a newly allocated entry on success, NULL otherwise.
static CQEntry* allocateEntry(const int iNumUnits, const int mss);
private:
CUnitQueue(const CUnitQueue&);
CUnitQueue& operator=(const CUnitQueue&);
CQEntry* m_pQEntry; // pointer to the first unit queue
CQEntry* m_pCurrQueue; // pointer to the current available queue
CQEntry* m_pLastQueue; // pointer to the last unit queue
CUnit* m_pAvailUnit; // recent available unit
int m_iSize; // total size of the unit queue, in number of packets
sync::atomic<int> m_iNumTaken; // total number of valid (occupied) packets in the queue
const int m_iMSS; // unit buffer size
const int m_iBlockSize; // Number of units in each CQEntry.
private:
CUnitQueue(const CUnitQueue&);
CUnitQueue& operator=(const CUnitQueue&);
};
struct CSNode
{
CUDT* m_pUDT; // Pointer to the instance of CUDT socket
uint64_t m_llTimeStamp_tk; // Time Stamp
CUDT* m_pUDT; // Pointer to the instance of CUDT socket
sync::steady_clock::time_point m_tsTimeStamp;
int m_iHeapLoc; // location on the heap, -1 means not on the heap
sync::atomic<int> m_iHeapLoc; // location on the heap, -1 means not on the heap
};
class CSndUList
{
friend class CSndQueue;
public:
CSndUList(sync::CTimer* pTimer);
~CSndUList();
public:
CSndUList();
~CSndUList();
enum EReschedule
{
DONT_RESCHEDULE = 0,
DO_RESCHEDULE = 1
};
public:
static EReschedule rescheduleIf(bool cond) { return cond ? DO_RESCHEDULE : DONT_RESCHEDULE; }
enum EReschedule { DONT_RESCHEDULE = 0, DO_RESCHEDULE = 1 };
/// Update the timestamp of the UDT instance on the list.
/// @param [in] u pointer to the UDT instance
/// @param [in] reschedule if the timestamp should be rescheduled
/// @param [in] ts the next time to trigger sending logic on the CUDT
void update(const CUDT* u, EReschedule reschedule, sync::steady_clock::time_point ts = sync::steady_clock::now());
static EReschedule rescheduleIf(bool cond) { return cond ? DO_RESCHEDULE : DONT_RESCHEDULE; }
/// Retrieve the next (in time) socket from the heap to process its sending request.
/// @return a pointer to CUDT instance to process next.
CUDT* pop();
/// Update the timestamp of the UDT instance on the list.
/// @param [in] u pointer to the UDT instance
/// @param [in] reschedule if the timestamp should be rescheduled
/// Remove UDT instance from the list.
/// @param [in] u pointer to the UDT instance
void remove(const CUDT* u);// EXCLUDES(m_ListLock);
void update(const CUDT* u, EReschedule reschedule);
/// Retrieve the next scheduled processing time.
/// @return Scheduled processing time of the first UDT socket in the list.
sync::steady_clock::time_point getNextProcTime();
/// Retrieve the next packet and peer address from the first entry, and reschedule it in the queue.
/// @param [out] addr destination address of the next packet
/// @param [out] pkt the next packet to be sent
/// @return 1 if successfully retrieved, -1 if no packet found.
/// Wait for the list to become non empty.
void waitNonEmpty() const;
int pop(sockaddr*& addr, CPacket& pkt);
/// Remove UDT instance from the list.
/// @param [in] u pointer to the UDT instance
void remove(const CUDT* u);
/// Retrieve the next scheduled processing time.
/// @return Scheduled processing time of the first UDT socket in the list.
uint64_t getNextProcTime();
/// Signal to stop waiting in waitNonEmpty().
void signalInterrupt() const;
private:
/// Doubles the size of the list.
///
void realloc_();// REQUIRES(m_ListLock);
/// Doubles the size of the list.
///
void realloc_();
/// Insert a new UDT instance into the list with realloc if required.
///
/// @param [in] ts time stamp: next processing time
/// @param [in] u pointer to the UDT instance
void insert_(const sync::steady_clock::time_point& ts, const CUDT* u);
/// Insert a new UDT instance into the list with realloc if required.
///
/// @param [in] ts time stamp: next processing time
/// @param [in] u pointer to the UDT instance
void insert_(int64_t ts, const CUDT* u);
/// Insert a new UDT instance into the list without realloc.
/// Should be called if there is a gauranteed space for the element.
///
/// @param [in] ts time stamp: next processing time
/// @param [in] u pointer to the UDT instance
void insert_norealloc_(const sync::steady_clock::time_point& ts, const CUDT* u);// REQUIRES(m_ListLock);
/// Insert a new UDT instance into the list without realloc.
/// Should be called if there is a gauranteed space for the element.
///
/// @param [in] ts time stamp: next processing time
/// @param [in] u pointer to the UDT instance
void insert_norealloc_(int64_t ts, const CUDT* u);
void remove_(const CUDT* u);
/// Removes CUDT entry from the list.
/// If the last entry is removed, calls sync::CTimer::interrupt().
void remove_(const CUDT* u);
private:
CSNode** m_pHeap; // The heap array
int m_iArrayLength; // physical length of the array
int m_iLastEntry; // position of last entry on the heap array
CSNode** m_pHeap; // The heap array
int m_iArrayLength; // physical length of the array
int m_iLastEntry; // position of last entry on the heap array or -1 if empty.
pthread_mutex_t m_ListLock;
mutable sync::Mutex m_ListLock; // Protects the list (m_pHeap, m_iArrayLength, m_iLastEntry).
mutable sync::Condition m_ListCond;
pthread_mutex_t* m_pWindowLock;
pthread_cond_t* m_pWindowCond;
CTimer* m_pTimer;
sync::CTimer* const m_pTimer;
private:
CSndUList(const CSndUList&);
CSndUList& operator=(const CSndUList&);
CSndUList(const CSndUList&);
CSndUList& operator=(const CSndUList&);
};
struct CRNode
{
CUDT* m_pUDT; // Pointer to the instance of CUDT socket
uint64_t m_llTimeStamp_tk; // Time Stamp
CUDT* m_pUDT; // Pointer to the instance of CUDT socket
sync::steady_clock::time_point m_tsTimeStamp; // Time Stamp
CRNode* m_pPrev; // previous link
CRNode* m_pNext; // next link
CRNode* m_pPrev; // previous link
CRNode* m_pNext; // next link
bool m_bOnList; // if the node is already on the list
sync::atomic<bool> m_bOnList; // if the node is already on the list
};
class CRcvUList
{
public:
CRcvUList();
~CRcvUList();
CRcvUList();
~CRcvUList();
public:
/// Insert a new UDT instance to the list.
/// @param [in] u pointer to the UDT instance
/// Insert a new UDT instance to the list.
/// @param [in] u pointer to the UDT instance
void insert(const CUDT* u);
void insert(const CUDT* u);
/// Remove the UDT instance from the list.
/// @param [in] u pointer to the UDT instance
/// Remove the UDT instance from the list.
/// @param [in] u pointer to the UDT instance
void remove(const CUDT* u);
void remove(const CUDT* u);
/// Move the UDT instance to the end of the list, if it already exists; otherwise, do nothing.
/// @param [in] u pointer to the UDT instance
/// Move the UDT instance to the end of the list, if it already exists; otherwise, do nothing.
/// @param [in] u pointer to the UDT instance
void update(const CUDT* u);
void update(const CUDT* u);
public:
CRNode* m_pUList; // the head node
CRNode* m_pUList; // the head node
private:
CRNode* m_pLast; // the last node
CRNode* m_pLast; // the last node
private:
CRcvUList(const CRcvUList&);
CRcvUList& operator=(const CRcvUList&);
CRcvUList(const CRcvUList&);
CRcvUList& operator=(const CRcvUList&);
};
class CHash
{
public:
CHash();
~CHash();
CHash();
~CHash();
public:
/// Initialize the hash table.
/// @param [in] size hash table size
/// Initialize the hash table.
/// @param [in] size hash table size
void init(int size);
void init(int size);
/// Look for a UDT instance from the hash table.
/// @param [in] id socket ID
/// @return Pointer to a UDT instance, or NULL if not found.
/// Look for a UDT instance from the hash table.
/// @param [in] id socket ID
/// @return Pointer to a UDT instance, or NULL if not found.
CUDT* lookup(int32_t id);
CUDT* lookup(int32_t id);
/// Insert an entry to the hash table.
/// @param [in] id socket ID
/// @param [in] u pointer to the UDT instance
/// Insert an entry to the hash table.
/// @param [in] id socket ID
/// @param [in] u pointer to the UDT instance
void insert(int32_t id, CUDT* u);
void insert(int32_t id, CUDT* u);
/// Remove an entry from the hash table.
/// @param [in] id socket ID
/// Remove an entry from the hash table.
/// @param [in] id socket ID
void remove(int32_t id);
void remove(int32_t id);
private:
struct CBucket
{
int32_t m_iID; // Socket ID
CUDT* m_pUDT; // Socket instance
struct CBucket
{
int32_t m_iID; // Socket ID
CUDT* m_pUDT; // Socket instance
CBucket* m_pNext; // next bucket
} **m_pBucket; // list of buckets (the hash table)
CBucket* m_pNext; // next bucket
} * *m_pBucket; // list of buckets (the hash table)
int m_iHashSize; // size of hash table
int m_iHashSize; // size of hash table
private:
CHash(const CHash&);
CHash& operator=(const CHash&);
CHash(const CHash&);
CHash& operator=(const CHash&);
};
/// @brief A queue of sockets pending for connection.
/// It can be either a caller socket in a non-blocking mode
/// (the connection has to be handled in background),
/// or a socket in rendezvous connection mode.
class CRendezvousQueue
{
public:
CRendezvousQueue();
~CRendezvousQueue();
CRendezvousQueue();
~CRendezvousQueue();
public:
void insert(const SRTSOCKET& id, CUDT* u, int ipv, const sockaddr* addr, uint64_t ttl);
/// @brief Insert a new socket pending for connection (non-blocking caller or rendezvous).
/// @param id socket ID.
/// @param u pointer to a corresponding CUDT instance.
/// @param addr remote address to connect to.
/// @param ttl timepoint for connection attempt to expire.
void insert(const SRTSOCKET& id, CUDT* u, const sockaddr_any& addr, const srt::sync::steady_clock::time_point& ttl);
// The should_lock parameter is given here to state as to whether
// the lock should be applied here. If called from some internals
// and the lock IS ALREADY APPLIED, use false here to prevent
// double locking and deadlock in result.
void remove(const SRTSOCKET& id, bool should_lock);
CUDT* retrieve(const sockaddr* addr, ref_t<SRTSOCKET> id);
/// @brief Remove a socket from the connection pending list.
/// @param id socket ID.
void remove(const SRTSOCKET& id);
void updateConnStatus(EReadStatus rst, EConnectStatus, const CPacket& response);
/// @brief Locate a socket in the connection pending queue.
/// @param addr source address of the packet received over UDP (peer address).
/// @param id socket ID.
/// @return a pointer to CUDT instance retrieved, or NULL if nothing was found.
CUDT* retrieve(const sockaddr_any& addr, SRTSOCKET& id) const;
/// @brief Update status of connections in the pending queue.
/// Stop connecting if TTL expires. Resend handshake request every 250 ms if no response from the peer.
/// @param rst result of reading from a UDP socket: received packet / nothin read / read error.
/// @param cst target status for pending connection: reject or proceed.
/// @param pktIn packet received from the UDP socket.
void updateConnStatus(EReadStatus rst, EConnectStatus cst, CUnit* unit);
private:
struct CRL
{
SRTSOCKET m_iID; // UDT socket ID (self)
CUDT* m_pUDT; // UDT instance
int m_iIPversion; // IP version
sockaddr* m_pPeerAddr; // UDT sonnection peer address
uint64_t m_ullTTL; // the time that this request expires
};
std::list<CRL> m_lRendezvousID; // The sockets currently in rendezvous mode
struct LinkStatusInfo
{
CUDT* u;
SRTSOCKET id;
int errorcode;
sockaddr_any peeraddr;
int token;
pthread_mutex_t m_RIDVectorLock;
struct HasID
{
SRTSOCKET id;
HasID(SRTSOCKET p)
: id(p)
{
}
bool operator()(const LinkStatusInfo& i) { return i.id == id; }
};
};
/// @brief Qualify pending connections:
/// - Sockets with expired TTL go to the 'to_remove' list and removed from the queue straight away.
/// - If HS request is to be resent (resend 250 ms if no response from the peer) go to the 'to_process' list.
///
/// @param rst result of reading from a UDP socket: received packet / nothin read / read error.
/// @param cst target status for pending connection: reject or proceed.
/// @param iDstSockID destination socket ID of the received packet.
/// @param[in,out] toRemove stores sockets with expired TTL.
/// @param[in,out] toProcess stores sockets which should repeat (resend) HS connection request.
bool qualifyToHandle(EReadStatus rst,
EConnectStatus cst,
int iDstSockID,
std::vector<LinkStatusInfo>& toRemove,
std::vector<LinkStatusInfo>& toProcess);
private:
struct CRL
{
SRTSOCKET m_iID; // SRT socket ID (self)
CUDT* m_pUDT; // CUDT instance
sockaddr_any m_PeerAddr; // SRT sonnection peer address
sync::steady_clock::time_point m_tsTTL; // the time that this request expires
};
std::list<CRL> m_lRendezvousID; // The sockets currently in rendezvous mode
mutable sync::Mutex m_RIDListLock;
};
class CSndQueue
{
friend class CUDT;
friend class CUDTUnited;
friend class CUDT;
friend class CUDTUnited;
public:
CSndQueue();
~CSndQueue();
CSndQueue();
~CSndQueue();
public:
// XXX There's currently no way to access the socket ID set for
// whatever the queue is currently working for. Required to find
// some way to do this, possibly by having a "reverse pointer".
// Currently just "unimplemented".
std::string CONID() const { return ""; }
// XXX There's currently no way to access the socket ID set for
// whatever the queue is currently working for. Required to find
// some way to do this, possibly by having a "reverse pointer".
// Currently just "unimplemented".
std::string CONID() const { return ""; }
/// Initialize the sending queue.
/// @param [in] c UDP channel to be associated to the queue
/// @param [in] t Timer
/// Initialize the sending queue.
/// @param [in] c UDP channel to be associated to the queue
/// @param [in] t Timer
void init(CChannel* c, sync::CTimer* t);
void init(CChannel* c, CTimer* t);
/// Send out a packet to a given address.
/// @param [in] addr destination address
/// @param [in] packet packet to be sent out
/// @return Size of data sent out.
/// Send out a packet to a given address.
/// @param [in] addr destination address
/// @param [in] packet packet to be sent out
/// @return Size of data sent out.
int sendto(const sockaddr_any& addr, CPacket& packet);
int sendto(const sockaddr* addr, CPacket& packet);
/// Get the IP TTL.
/// @param [in] ttl IP Time To Live.
/// @return TTL.
#ifdef SRT_ENABLE_IPOPTS
/// Get the IP TTL.
/// @param [in] ttl IP Time To Live.
/// @return TTL.
int getIpTTL() const;
int getIpTTL() const;
/// Get the IP Type of Service.
/// @return ToS.
/// Get the IP Type of Service.
/// @return ToS.
int getIpToS() const;
int getIpToS() const;
#ifdef SRT_ENABLE_BINDTODEVICE
bool getBind(char* dst, size_t len) const;
#endif
int ioctlQuery(int type) const { return m_pChannel->ioctlQuery(type); }
int sockoptQuery(int level, int type) const { return m_pChannel->sockoptQuery(level, type); }
int ioctlQuery(int type) const;
int sockoptQuery(int level, int type) const;
void setClosing()
{
m_bClosing = true;
}
void setClosing() { m_bClosing = true; }
private:
static void* worker(void* param);
pthread_t m_WorkerThread;
static void* worker(void* param);
sync::CThread m_WorkerThread;
private:
CSndUList* m_pSndUList; // List of UDT instances for data sending
CChannel* m_pChannel; // The UDP channel for data sending
CTimer* m_pTimer; // Timing facility
CSndUList* m_pSndUList; // List of UDT instances for data sending
CChannel* m_pChannel; // The UDP channel for data sending
sync::CTimer* m_pTimer; // Timing facility
pthread_mutex_t m_WindowLock;
pthread_cond_t m_WindowCond;
sync::atomic<bool> m_bClosing; // closing the worker
volatile bool m_bClosing; // closing the worker
#if defined(SRT_DEBUG_SNDQ_HIGHRATE)//>>debug high freq worker
uint64_t m_ullDbgPeriod;
uint64_t m_ullDbgTime;
struct {
#if defined(SRT_DEBUG_SNDQ_HIGHRATE) //>>debug high freq worker
uint64_t m_ullDbgPeriod;
uint64_t m_ullDbgTime;
struct
{
unsigned long lIteration; //
unsigned long lSleepTo; //SleepTo
unsigned long lNotReadyPop; //Continue
unsigned long lSleepTo; // SleepTo
unsigned long lNotReadyPop; // Continue
unsigned long lSendTo;
unsigned long lNotReadyTs;
unsigned long lCondWait; //block on m_WindowCond
} m_WorkerStats;
unsigned long lNotReadyTs;
unsigned long lCondWait; // block on m_WindowCond
} m_WorkerStats;
#endif /* SRT_DEBUG_SNDQ_HIGHRATE */
#if ENABLE_LOGGING
static int m_counter;
#endif
private:
CSndQueue(const CSndQueue&);
CSndQueue& operator=(const CSndQueue&);
CSndQueue(const CSndQueue&);
CSndQueue& operator=(const CSndQueue&);
};
class CRcvQueue
{
friend class CUDT;
friend class CUDTUnited;
friend class CUDT;
friend class CUDTUnited;
public:
CRcvQueue();
~CRcvQueue();
CRcvQueue();
~CRcvQueue();
public:
// XXX There's currently no way to access the socket ID set for
// whatever the queue is currently working. Required to find
// some way to do this, possibly by having a "reverse pointer".
// Currently just "unimplemented".
std::string CONID() const { return ""; }
// XXX There's currently no way to access the socket ID set for
// whatever the queue is currently working. Required to find
// some way to do this, possibly by having a "reverse pointer".
// Currently just "unimplemented".
std::string CONID() const { return ""; }
/// Initialize the receiving queue.
/// @param [in] size queue size
/// @param [in] mss maximum packet size
/// @param [in] version IP version
/// @param [in] hsize hash table size
/// @param [in] c UDP channel to be associated to the queue
/// @param [in] t timer
void init(int size, size_t payload, int version, int hsize, CChannel* c, sync::CTimer* t);
/// Initialize the receiving queue.
/// @param [in] size queue size
/// @param [in] mss maximum packet size
/// @param [in] version IP version
/// @param [in] hsize hash table size
/// @param [in] c UDP channel to be associated to the queue
/// @param [in] t timer
/// Read a packet for a specific UDT socket id.
/// @param [in] id Socket ID
/// @param [out] packet received packet
/// @return Data size of the packet
int recvfrom(int32_t id, CPacket& to_packet);
void init(int size, int payload, int version, int hsize, CChannel* c, CTimer* t);
void stopWorker();
/// Read a packet for a specific UDT socket id.
/// @param [in] id Socket ID
/// @param [out] packet received packet
/// @return Data size of the packet
void setClosing() { m_bClosing = true; }
int recvfrom(int32_t id, ref_t<CPacket> packet);
void setClosing()
{
m_bClosing = true;
}
int getIPversion() { return m_iIPversion; }
private:
static void* worker(void* param);
pthread_t m_WorkerThread;
// Subroutines of worker
EReadStatus worker_RetrieveUnit(ref_t<int32_t> id, ref_t<CUnit*> unit, sockaddr* sa);
EConnectStatus worker_ProcessConnectionRequest(CUnit* unit, const sockaddr* sa);
EConnectStatus worker_TryAsyncRend_OrStore(int32_t id, CUnit* unit, const sockaddr* sa);
EConnectStatus worker_ProcessAddressedPacket(int32_t id, CUnit* unit, const sockaddr* sa);
static void* worker(void* param);
sync::CThread m_WorkerThread;
// Subroutines of worker
EReadStatus worker_RetrieveUnit(int32_t& id, CUnit*& unit, sockaddr_any& sa);
EConnectStatus worker_ProcessConnectionRequest(CUnit* unit, const sockaddr_any& sa);
EConnectStatus worker_TryAsyncRend_OrStore(int32_t id, CUnit* unit, const sockaddr_any& sa);
EConnectStatus worker_ProcessAddressedPacket(int32_t id, CUnit* unit, const sockaddr_any& sa);
private:
CUnitQueue m_UnitQueue; // The received packet queue
CUnitQueue* m_pUnitQueue; // The received packet queue
CRcvUList* m_pRcvUList; // List of UDT instances that will read packets from the queue
CHash* m_pHash; // Hash table for UDT socket looking up
CChannel* m_pChannel; // UDP channel for receving packets
sync::CTimer* m_pTimer; // shared timer with the snd queue
CRcvUList* m_pRcvUList; // List of UDT instances that will read packets from the queue
CHash* m_pHash; // Hash table for UDT socket looking up
CChannel* m_pChannel; // UDP channel for receving packets
CTimer* m_pTimer; // shared timer with the snd queue
int m_iIPversion; // IP version
size_t m_szPayloadSize; // packet payload size
int m_iPayloadSize; // packet payload size
volatile bool m_bClosing; // closing the worker
sync::atomic<bool> m_bClosing; // closing the worker
#if ENABLE_LOGGING
static srt::sync::atomic<int> m_counter; // A static counter to log RcvQueue worker thread number.
#endif
private:
int setListener(CUDT* u);
void removeListener(const CUDT* u);
int setListener(CUDT* u);
void removeListener(const CUDT* u);
void registerConnector(const SRTSOCKET& id, CUDT* u, int ipv, const sockaddr* addr, uint64_t ttl);
void removeConnector(const SRTSOCKET& id, bool should_lock = true);
void registerConnector(const SRTSOCKET& id,
CUDT* u,
const sockaddr_any& addr,
const sync::steady_clock::time_point& ttl);
void removeConnector(const SRTSOCKET& id);
void setNewEntry(CUDT* u);
bool ifNewEntry();
CUDT* getNewEntry();
void setNewEntry(CUDT* u);
bool ifNewEntry();
CUDT* getNewEntry();
void storePkt(int32_t id, CPacket* pkt);
void storePkt(int32_t id, CPacket* pkt);
private:
pthread_mutex_t m_LSLock;
CUDT* m_pListener; // pointer to the (unique, if any) listening UDT entity
CRendezvousQueue* m_pRendezvousQueue; // The list of sockets in rendezvous mode
sync::Mutex m_LSLock;
CUDT* m_pListener; // pointer to the (unique, if any) listening UDT entity
CRendezvousQueue* m_pRendezvousQueue; // The list of sockets in rendezvous mode
std::vector<CUDT*> m_vNewEntry; // newly added entries, to be inserted
pthread_mutex_t m_IDLock;
std::vector<CUDT*> m_vNewEntry; // newly added entries, to be inserted
sync::Mutex m_IDLock;
std::map<int32_t, std::queue<CPacket*> > m_mBuffer; // temporary buffer for rendezvous connection request
pthread_mutex_t m_PassLock;
pthread_cond_t m_PassCond;
std::map<int32_t, std::queue<CPacket*> > m_mBuffer; // temporary buffer for rendezvous connection request
sync::Mutex m_BufferLock;
sync::Condition m_BufferCond;
private:
CRcvQueue(const CRcvQueue&);
CRcvQueue& operator=(const CRcvQueue&);
CRcvQueue(const CRcvQueue&);
CRcvQueue& operator=(const CRcvQueue&);
};
struct CMultiplexer
{
CSndQueue* m_pSndQueue; // The sending queue
CRcvQueue* m_pRcvQueue; // The receiving queue
CChannel* m_pChannel; // The UDP channel for sending and receiving
CTimer* m_pTimer; // The timer
CSndQueue* m_pSndQueue; // The sending queue
CRcvQueue* m_pRcvQueue; // The receiving queue
CChannel* m_pChannel; // The UDP channel for sending and receiving
sync::CTimer* m_pTimer; // The timer
int m_iPort; // The UDP port number of this multiplexer
int m_iIPversion; // IP version
#ifdef SRT_ENABLE_IPOPTS
int m_iIpTTL;
int m_iIpToS;
#endif
int m_iMSS; // Maximum Segment Size
int m_iRefCount; // number of UDT instances that are associated with this multiplexer
int m_iIpV6Only; // IPV6_V6ONLY option
bool m_bReusable; // if this one can be shared with others
int m_iPort; // The UDP port number of this multiplexer
int m_iIPversion; // Address family (AF_INET or AF_INET6)
int m_iRefCount; // number of UDT instances that are associated with this multiplexer
int m_iID; // multiplexer ID
CSrtMuxerConfig m_mcfg;
int m_iID; // multiplexer ID
// Constructor should reset all pointers to NULL
// to prevent dangling pointer when checking for memory alloc fails
CMultiplexer()
: m_pSndQueue(NULL)
, m_pRcvQueue(NULL)
, m_pChannel(NULL)
, m_pTimer(NULL)
{
}
void destroy();
};
} // namespace srt
#endif