From afe3fbabd3e0ef5e475025a3d2f9eaab880a77f9 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 5 Mar 2018 01:17:19 +0100 Subject: [PATCH] qrtplib: new RTPUDPTransmitter --- qrtplib/CMakeLists.txt | 2 + qrtplib/rtcpcompoundpacket.cpp | 21 +- qrtplib/rtcpcompoundpacket.h | 9 +- qrtplib/rtpaddress.cpp | 5 + qrtplib/rtpaddress.h | 3 + qrtplib/rtpinternalutils.h | 10 +- qrtplib/rtppacket.cpp | 96 ++++- qrtplib/rtprawpacket.h | 59 +-- qrtplib/rtpsession.cpp | 760 +++++++++++++-------------------- qrtplib/rtpsession.h | 22 +- qrtplib/rtpsources.cpp | 8 +- qrtplib/rtptransmitter.h | 43 +- qrtplib/rtpudptransmitter.cpp | 373 ++++++++++++++-- qrtplib/rtpudptransmitter.h | 158 +++---- 14 files changed, 835 insertions(+), 734 deletions(-) diff --git a/qrtplib/CMakeLists.txt b/qrtplib/CMakeLists.txt index 0ddab281d..979fd508a 100644 --- a/qrtplib/CMakeLists.txt +++ b/qrtplib/CMakeLists.txt @@ -42,6 +42,7 @@ set (qrtplib_HEADERS rtptransmitter.h rtptypes_win.h rtptypes.h + rtpudpransmitter.h # rtpudpv4transmitter.h # rtpudpv4transmitternobind.h # rtpexternaltransmitter.h @@ -82,6 +83,7 @@ set(qrtplib_SOURCES rtpsourcedata.cpp rtpsources.cpp rtptimeutilities.cpp + rtpudptransmitter.cpp # rtpudpv4transmitter.cpp # rtpudpv4transmitternobind.cpp # rtpexternaltransmitter.cpp diff --git a/qrtplib/rtcpcompoundpacket.cpp b/qrtplib/rtcpcompoundpacket.cpp index 959cd978d..23d8ea179 100644 --- a/qrtplib/rtcpcompoundpacket.cpp +++ b/qrtplib/rtcpcompoundpacket.cpp @@ -61,30 +61,30 @@ RTCPCompoundPacket::RTCPCompoundPacket(RTPRawPacket &rawpack) std::size_t datalen = rawpack.GetDataLength(); error = ParseData(data, datalen); - if (error < 0) + + if (error < 0) { return; + } compoundpacket = rawpack.GetData(); compoundpacketlength = rawpack.GetDataLength(); - deletepacket = true; - - rawpack.ZeroData(); rtcppackit = rtcppacklist.begin(); } -RTCPCompoundPacket::RTCPCompoundPacket(uint8_t *packet, std::size_t packetlen, bool deletedata) +RTCPCompoundPacket::RTCPCompoundPacket(uint8_t *packet, std::size_t packetlen) { compoundpacket = 0; compoundpacketlength = 0; error = ParseData(packet, packetlen); - if (error < 0) + + if (error < 0) { return; + } compoundpacket = packet; compoundpacketlength = packetlen; - deletepacket = deletedata; rtcppackit = rtcppacklist.begin(); } @@ -94,7 +94,6 @@ RTCPCompoundPacket::RTCPCompoundPacket() compoundpacket = 0; compoundpacketlength = 0; error = 0; - deletepacket = true; } int RTCPCompoundPacket::ParseData(uint8_t *data, std::size_t datalen) @@ -195,16 +194,16 @@ int RTCPCompoundPacket::ParseData(uint8_t *data, std::size_t datalen) RTCPCompoundPacket::~RTCPCompoundPacket() { ClearPacketList(); - if (compoundpacket && deletepacket) - delete[] compoundpacket; } void RTCPCompoundPacket::ClearPacketList() { std::list::const_iterator it; - for (it = rtcppacklist.begin(); it != rtcppacklist.end(); it++) + for (it = rtcppacklist.begin(); it != rtcppacklist.end(); it++) { delete *it; + } + rtcppacklist.clear(); rtcppackit = rtcppacklist.begin(); } diff --git a/qrtplib/rtcpcompoundpacket.h b/qrtplib/rtcpcompoundpacket.h index 446504266..c15aaacd1 100644 --- a/qrtplib/rtcpcompoundpacket.h +++ b/qrtplib/rtcpcompoundpacket.h @@ -58,12 +58,8 @@ public: /** Creates an RTCPCompoundPacket instance from the data in \c rawpack, installing a memory manager if specified. */ RTCPCompoundPacket(RTPRawPacket &rawpack); - /** Creates an RTCPCompoundPacket instance from the data in \c packet}, with size \c len. - * Creates an RTCPCompoundPacket instance from the data in \c packet}, with size \c len. The \c deletedata - * flag specifies if the data in \c packet should be deleted when the compound packet is destroyed. If - * specified, a memory manager will be installed. - */ - RTCPCompoundPacket(uint8_t *packet, std::size_t len, bool deletedata = true); + /** Creates an RTCPCompoundPacket instance from the data in \c packet}, with size \c len. */ + RTCPCompoundPacket(uint8_t *packet, std::size_t len); protected: RTCPCompoundPacket(); // this is for the compoundpacket builder public: @@ -118,7 +114,6 @@ protected: uint8_t *compoundpacket; std::size_t compoundpacketlength; - bool deletepacket; std::list rtcppacklist; std::list::const_iterator rtcppackit; diff --git a/qrtplib/rtpaddress.cpp b/qrtplib/rtpaddress.cpp index 4fe56a96b..28b5979f4 100644 --- a/qrtplib/rtpaddress.cpp +++ b/qrtplib/rtpaddress.cpp @@ -77,4 +77,9 @@ bool RTPAddress::IsFromSameHost(const RTPAddress *addr) const return addr->address == address; } +bool RTPAddress::operator==(const RTPAddress& otherAddress) +{ + return IsSameAddress(&otherAddress); +} + } // namespace diff --git a/qrtplib/rtpaddress.h b/qrtplib/rtpaddress.h index 68324b3fe..e5832f6ce 100644 --- a/qrtplib/rtpaddress.h +++ b/qrtplib/rtpaddress.h @@ -82,6 +82,9 @@ public: */ bool IsFromSameHost(const RTPAddress *addr) const; + /** Equality */ + bool operator==(const RTPAddress& otherAddress); + /** Get host address */ const QHostAddress& getAddress() const { diff --git a/qrtplib/rtpinternalutils.h b/qrtplib/rtpinternalutils.h index 9ab51ff29..bbe0e34b7 100644 --- a/qrtplib/rtpinternalutils.h +++ b/qrtplib/rtpinternalutils.h @@ -7,7 +7,7 @@ This library was developed at the Expertise Centre for Digital Media (http://www.edm.uhasselt.be), a research center of the Hasselt University - (http://www.uhasselt.be). The library is based upon work done for + (http://www.uhasselt.be). The library is based upon work done for my thesis at the School for Knowledge Technology (Belgium/The Netherlands). Permission is hereby granted, free of charge, to any person obtaining a @@ -47,13 +47,7 @@ #else #include #define RTP_SNPRINTF snprintf -#endif - -#ifdef RTP_HAVE_STRNCPY_S -#define RTP_STRNCPY(dest, src, len) strncpy_s((dest), (len), (src), _TRUNCATE) -#else -#define RTP_STRNCPY(dest, src, len) strncpy((dest), (src), (len)) -#endif // RTP_HAVE_STRNCPY_S +#endif #endif // RTPINTERNALUTILS_H diff --git a/qrtplib/rtppacket.cpp b/qrtplib/rtppacket.cpp index 08419ef8e..b8aa717ed 100644 --- a/qrtplib/rtppacket.cpp +++ b/qrtplib/rtppacket.cpp @@ -67,18 +67,59 @@ RTPPacket::RTPPacket(RTPRawPacket &rawpack) : error = ParseRawPacket(rawpack); } -RTPPacket::RTPPacket(uint8_t payloadtype, const void *payloaddata, std::size_t payloadlen, uint16_t seqnr, uint32_t timestamp, uint32_t ssrc, bool gotmarker, uint8_t numcsrcs, - const uint32_t *csrcs, bool gotextension, uint16_t extensionid, uint16_t extensionlen_numwords, const void *extensiondata, std::size_t maxpacksize) : - receivetime(0, 0) +RTPPacket::RTPPacket( + uint8_t payloadtype, + const void *payloaddata, + std::size_t payloadlen, + uint16_t seqnr, + uint32_t timestamp, + uint32_t ssrc, + bool gotmarker, + uint8_t numcsrcs, + const uint32_t *csrcs, + bool gotextension, + uint16_t extensionid, + uint16_t extensionlen_numwords, + const void *extensiondata, + std::size_t maxpacksize) : + receivetime(0, 0) { Clear(); - error = BuildPacket(payloadtype, payloaddata, payloadlen, seqnr, timestamp, ssrc, gotmarker, numcsrcs, csrcs, gotextension, extensionid, extensionlen_numwords, extensiondata, - 0, maxpacksize); + error = BuildPacket( + payloadtype, + payloaddata, + payloadlen, + seqnr, + timestamp, + ssrc, + gotmarker, + numcsrcs, + csrcs, + gotextension, + extensionid, + extensionlen_numwords, + extensiondata, + 0, + maxpacksize); } -RTPPacket::RTPPacket(uint8_t payloadtype, const void *payloaddata, std::size_t payloadlen, uint16_t seqnr, uint32_t timestamp, uint32_t ssrc, bool gotmarker, uint8_t numcsrcs, - const uint32_t *csrcs, bool gotextension, uint16_t extensionid, uint16_t extensionlen_numwords, const void *extensiondata, void *buffer, std::size_t buffersize) : - receivetime(0, 0) +RTPPacket::RTPPacket( + uint8_t payloadtype, + const void *payloaddata, + std::size_t payloadlen, + uint16_t seqnr, + uint32_t timestamp, + uint32_t ssrc, + bool gotmarker, + uint8_t numcsrcs, + const uint32_t *csrcs, + bool gotextension, + uint16_t extensionid, + uint16_t extensionlen_numwords, + const void *extensiondata, + void *buffer, + std::size_t buffersize) : + receivetime(0, 0) { Clear(); if (buffer == 0) @@ -86,8 +127,22 @@ RTPPacket::RTPPacket(uint8_t payloadtype, const void *payloaddata, std::size_t p else if (buffersize <= 0) error = ERR_RTP_PACKET_ILLEGALBUFFERSIZE; else - error = BuildPacket(payloadtype, payloaddata, payloadlen, seqnr, timestamp, ssrc, gotmarker, numcsrcs, csrcs, gotextension, extensionid, extensionlen_numwords, - extensiondata, buffer, buffersize); + error = BuildPacket( + payloadtype, + payloaddata, + payloadlen, + seqnr, + timestamp, + ssrc, + gotmarker, + numcsrcs, + csrcs, + gotextension, + extensionid, + extensionlen_numwords, + extensiondata, + buffer, + buffersize); } int RTPPacket::ParseRawPacket(RTPRawPacket &rawpack) @@ -188,9 +243,6 @@ int RTPPacket::ParseRawPacket(RTPRawPacket &rawpack) RTPPacket::packetlength = packetlen; RTPPacket::payloadlength = payloadlength; - // We'll zero the data of the raw packet, since we're using it here now! - rawpack.ZeroData(); - return 0; } @@ -209,8 +261,22 @@ uint32_t RTPPacket::GetCSRC(int num) const return csrcval_hbo; } -int RTPPacket::BuildPacket(uint8_t payloadtype, const void *payloaddata, std::size_t payloadlen, uint16_t seqnr, uint32_t timestamp, uint32_t ssrc, bool gotmarker, uint8_t numcsrcs, - const uint32_t *csrcs, bool gotextension, uint16_t extensionid, uint16_t extensionlen_numwords, const void *extensiondata, void *buffer, std::size_t maxsize) +int RTPPacket::BuildPacket( + uint8_t payloadtype, + const void *payloaddata, + std::size_t payloadlen, + uint16_t seqnr, + uint32_t timestamp, + uint32_t ssrc, + bool gotmarker, + uint8_t numcsrcs, + const uint32_t *csrcs, + bool gotextension, + uint16_t extensionid, + uint16_t extensionlen_numwords, + const void *extensiondata, + void *buffer, + std::size_t maxsize) { if (numcsrcs > RTP_MAXCSRCS) return ERR_RTP_PACKET_TOOMANYCSRCS; diff --git a/qrtplib/rtprawpacket.h b/qrtplib/rtprawpacket.h index 05ab2ed7c..df00af0a6 100644 --- a/qrtplib/rtprawpacket.h +++ b/qrtplib/rtprawpacket.h @@ -57,7 +57,7 @@ public: * The flag which indicates whether this data is RTP or RTCP data is set to \c rtp. A memory * manager can be installed as well. */ - RTPRawPacket(uint8_t *data, std::size_t datalen, RTPAddress *address, RTPTime &recvtime, bool rtp); + RTPRawPacket(const uint8_t *data, std::size_t datalen, const RTPAddress& address, RTPTime &recvtime, bool rtp); ~RTPRawPacket(); /** Returns the pointer to the data which is contained in this packet. */ @@ -79,7 +79,7 @@ public: } /** Returns the address stored in this packet. */ - const RTPAddress *GetSenderAddress() const + const RTPAddress& GetSenderAddress() const { return senderaddress; } @@ -90,45 +90,28 @@ public: return isrtp; } - /** Sets the pointer to the data stored in this packet to zero. - * Sets the pointer to the data stored in this packet to zero. This will prevent - * a \c delete call for the actual data when the destructor of RTPRawPacket is called. - * This function is used by the RTPPacket and RTCPCompoundPacket classes to obtain - * the packet data (without having to copy it) and to make sure the data isn't deleted - * when the destructor of RTPRawPacket is called. - */ - void ZeroData() - { - packetdata = 0; - packetdatalength = 0; - } - - /** Allocates a number of bytes for RTP or RTCP data using the memory manager that - * was used for this raw packet instance, can be useful if the RTPRawPacket::SetData - * function will be used. */ - uint8_t *AllocateBytes(int recvlen) const; - /** Deallocates the previously stored data and replaces it with the data that's * specified, can be useful when e.g. decrypting data in RTPSession::OnChangeIncomingData */ - void SetData(uint8_t *data, std::size_t datalen); + void SetData(const uint8_t *data, std::size_t datalen); /** Deallocates the currently stored RTPAddress instance and replaces it * with the one that's specified (you probably don't need this function). */ - void SetSenderAddress(RTPAddress *address); + void SetSenderAddress(const RTPAddress& address); private: void DeleteData(); uint8_t *packetdata; std::size_t packetdatalength; RTPTime receivetime; - RTPAddress *senderaddress; + RTPAddress senderaddress; bool isrtp; }; -inline RTPRawPacket::RTPRawPacket(uint8_t *data, std::size_t datalen, RTPAddress *address, RTPTime &recvtime, bool rtp) : +inline RTPRawPacket::RTPRawPacket(const uint8_t *data, std::size_t datalen, const RTPAddress& address, RTPTime &recvtime, bool rtp) : receivetime(recvtime) { - packetdata = data; + packetdata = new uint8_t[datalen]; + memcpy(packetdata, data, datalen); packetdatalength = datalen; senderaddress = address; isrtp = rtp; @@ -142,33 +125,25 @@ inline RTPRawPacket::~RTPRawPacket() inline void RTPRawPacket::DeleteData() { if (packetdata) + { delete[] packetdata; - if (senderaddress) - delete senderaddress; - - packetdata = 0; - senderaddress = 0; + packetdata = 0; + } } -inline uint8_t *RTPRawPacket::AllocateBytes(int recvlen) const +inline void RTPRawPacket::SetData(const uint8_t *data, std::size_t datalen) { - return new uint8_t[recvlen]; -} - -inline void RTPRawPacket::SetData(uint8_t *data, std::size_t datalen) -{ - if (packetdata) + if (packetdata) { delete[] packetdata; + } - packetdata = data; + packetdata = new uint8_t[datalen]; + memcpy(packetdata, data, datalen); packetdatalength = datalen; } -inline void RTPRawPacket::SetSenderAddress(RTPAddress *address) +inline void RTPRawPacket::SetSenderAddress(const RTPAddress& address) { - if (senderaddress) - delete senderaddress; - senderaddress = address; } diff --git a/qrtplib/rtpsession.cpp b/qrtplib/rtpsession.cpp index 2d92c502a..c04c7b95b 100644 --- a/qrtplib/rtpsession.cpp +++ b/qrtplib/rtpsession.cpp @@ -55,20 +55,16 @@ #include #endif // WIN32 -#define SOURCES_LOCK -#define SOURCES_UNLOCK -#define BUILDER_LOCK -#define BUILDER_UNLOCK -#define SCHED_LOCK -#define SCHED_UNLOCK -#define PACKSENT_LOCK -#define PACKSENT_UNLOCK namespace qrtplib { RTPSession::RTPSession(RTPRandom *r) : - rtprnd(GetRandomNumberGenerator(r)), sources(*this), packetbuilder(*rtprnd), rtcpsched(sources, *rtprnd), rtcpbuilder(sources, packetbuilder) + rtprnd(GetRandomNumberGenerator(r)), + sources(*this), + packetbuilder(*rtprnd), + rtcpsched(sources, *rtprnd), + rtcpbuilder(sources, packetbuilder) { // We're not going to set these flags in Create, so that the constructor of a derived class // can already change them @@ -97,9 +93,6 @@ int RTPSession::Create(const RTPSessionParams &sessparams, const RTPTransmission return ERR_RTP_SESSION_ALREADYCREATED; usingpollthread = sessparams.IsUsingPollThread(); - needthreadsafety = sessparams.NeedThreadSafety(); - if (usingpollthread && !needthreadsafety) - return ERR_RTP_SESSION_THREADSAFETYCONFLICT; useSR_BYEifpossible = sessparams.GetSenderReportForBYE(); sentpackets = false; @@ -135,7 +128,7 @@ int RTPSession::Create(const RTPSessionParams &sessparams, const RTPTransmission if (rtptrans == 0) return ERR_RTP_OUTOFMEM; - if ((status = rtptrans->Init(needthreadsafety)) < 0) + if ((status = rtptrans->Init()) < 0) { delete rtptrans; return status; @@ -158,9 +151,6 @@ int RTPSession::Create(const RTPSessionParams &sessparams, RTPTransmitter *trans return ERR_RTP_SESSION_ALREADYCREATED; usingpollthread = sessparams.IsUsingPollThread(); - needthreadsafety = sessparams.NeedThreadSafety(); - if (usingpollthread && !needthreadsafety) - return ERR_RTP_SESSION_THREADSAFETYCONFLICT; useSR_BYEifpossible = sessparams.GetSenderReportForBYE(); sentpackets = false; @@ -236,7 +226,7 @@ int RTPSession::InternalCreate(const RTPSessionParams &sessparams) } else { - RTP_STRNCPY((char * )buf, forcedcname.c_str(), buflen); + strncpy((char * )buf, forcedcname.c_str(), buflen); buf[buflen - 1] = 0; buflen = strlen((char *) buf); } @@ -419,9 +409,7 @@ uint32_t RTPSession::GetLocalSSRC() uint32_t ssrc; - BUILDER_LOCK ssrc = packetbuilder.GetSSRC(); - BUILDER_UNLOCK return ssrc; } @@ -467,13 +455,6 @@ int RTPSession::LeaveMulticastGroup(const RTPAddress &addr) return rtptrans->LeaveMulticastGroup(addr); } -void RTPSession::LeaveAllMulticastGroups() -{ - if (!created) - return; - rtptrans->LeaveAllMulticastGroups(); -} - int RTPSession::SendPacket(const void *data, std::size_t len) { int status; @@ -481,25 +462,17 @@ int RTPSession::SendPacket(const void *data, std::size_t len) if (!created) return ERR_RTP_SESSION_NOTCREATED; - BUILDER_LOCK if ((status = packetbuilder.BuildPacket(data, len)) < 0) { - BUILDER_UNLOCK return status; } if ((status = SendRTPData(packetbuilder.GetPacket(), packetbuilder.GetPacketLength())) < 0) { - BUILDER_UNLOCK return status; } - BUILDER_UNLOCK - SOURCES_LOCK sources.SentRTPPacket(); - SOURCES_UNLOCK - PACKSENT_LOCK sentpackets = true; - PACKSENT_UNLOCK return 0; } @@ -510,25 +483,17 @@ int RTPSession::SendPacket(const void *data, std::size_t len, uint8_t pt, bool m if (!created) return ERR_RTP_SESSION_NOTCREATED; - BUILDER_LOCK if ((status = packetbuilder.BuildPacket(data, len, pt, mark, timestampinc)) < 0) { - BUILDER_UNLOCK return status; } if ((status = SendRTPData(packetbuilder.GetPacket(), packetbuilder.GetPacketLength())) < 0) { - BUILDER_UNLOCK return status; } - BUILDER_UNLOCK - SOURCES_LOCK sources.SentRTPPacket(); - SOURCES_UNLOCK - PACKSENT_LOCK sentpackets = true; - PACKSENT_UNLOCK return 0; } @@ -539,25 +504,17 @@ int RTPSession::SendPacketEx(const void *data, std::size_t len, uint16_t hdrextI if (!created) return ERR_RTP_SESSION_NOTCREATED; - BUILDER_LOCK if ((status = packetbuilder.BuildPacketEx(data, len, hdrextID, hdrextdata, numhdrextwords)) < 0) { - BUILDER_UNLOCK return status; } if ((status = SendRTPData(packetbuilder.GetPacket(), packetbuilder.GetPacketLength())) < 0) { - BUILDER_UNLOCK return status; } - BUILDER_UNLOCK - SOURCES_LOCK sources.SentRTPPacket(); - SOURCES_UNLOCK - PACKSENT_LOCK sentpackets = true; - PACKSENT_UNLOCK return 0; } @@ -568,25 +525,17 @@ int RTPSession::SendPacketEx(const void *data, std::size_t len, uint8_t pt, bool if (!created) return ERR_RTP_SESSION_NOTCREATED; - BUILDER_LOCK if ((status = packetbuilder.BuildPacketEx(data, len, pt, mark, timestampinc, hdrextID, hdrextdata, numhdrextwords)) < 0) { - BUILDER_UNLOCK return status; } if ((status = SendRTPData(packetbuilder.GetPacket(), packetbuilder.GetPacketLength())) < 0) { - BUILDER_UNLOCK return status; } - BUILDER_UNLOCK - SOURCES_LOCK sources.SentRTPPacket(); - SOURCES_UNLOCK - PACKSENT_LOCK sentpackets = true; - PACKSENT_UNLOCK return 0; } @@ -599,9 +548,7 @@ int RTPSession::SendRTCPAPPPacket(uint8_t subtype, const uint8_t name[4], const if (!created) return ERR_RTP_SESSION_NOTCREATED; - BUILDER_LOCK uint32_t ssrc = packetbuilder.GetSSRC(); - BUILDER_UNLOCK RTCPCompoundPacketBuilder pb; @@ -618,16 +565,13 @@ int RTPSession::SendRTCPAPPPacket(uint8_t subtype, const uint8_t name[4], const if ((status = pb.AddSDESSource(ssrc)) < 0) return status; - BUILDER_LOCK std::size_t owncnamelen = 0; uint8_t *owncname = rtcpbuilder.GetLocalCNAME(&owncnamelen); if ((status = pb.AddSDESNormalItem(RTCPSDESPacket::CNAME, owncname, owncnamelen)) < 0) { - BUILDER_UNLOCK return status; } - BUILDER_UNLOCK //add our application specific packet if ((status = pb.AddAPPPacket(subtype, ssrc, name, appdata, appdatalen)) < 0) @@ -641,9 +585,7 @@ int RTPSession::SendRTCPAPPPacket(uint8_t subtype, const uint8_t name[4], const if (status < 0) return status; - PACKSENT_LOCK sentpackets = true; - PACKSENT_UNLOCK return pb.GetCompoundPacketLength(); } @@ -671,9 +613,7 @@ int RTPSession::SetDefaultPayloadType(uint8_t pt) int status; - BUILDER_LOCK status = packetbuilder.SetDefaultPayloadType(pt); - BUILDER_UNLOCK return status; } @@ -684,9 +624,7 @@ int RTPSession::SetDefaultMark(bool m) int status; - BUILDER_LOCK status = packetbuilder.SetDefaultMark(m); - BUILDER_UNLOCK return status; } @@ -697,9 +635,7 @@ int RTPSession::SetDefaultTimestampIncrement(uint32_t timestampinc) int status; - BUILDER_LOCK status = packetbuilder.SetDefaultTimestampIncrement(timestampinc); - BUILDER_UNLOCK return status; } @@ -710,9 +646,7 @@ int RTPSession::IncrementTimestamp(uint32_t inc) int status; - BUILDER_LOCK status = packetbuilder.IncrementTimestamp(inc); - BUILDER_UNLOCK return status; } @@ -723,9 +657,7 @@ int RTPSession::IncrementTimestampDefault() int status; - BUILDER_LOCK status = packetbuilder.IncrementTimestampDefault(); - BUILDER_UNLOCK return status; } @@ -736,9 +668,7 @@ int RTPSession::SetPreTransmissionDelay(const RTPTime &delay) int status; - BUILDER_LOCK status = rtcpbuilder.SetPreTransmissionDelay(delay); - BUILDER_UNLOCK return status; } @@ -756,37 +686,6 @@ void RTPSession::DeleteTransmissionInfo(RTPTransmissionInfo *inf) rtptrans->DeleteTransmissionInfo(inf); } -int RTPSession::Poll() -{ - int status; - - if (!created) - return ERR_RTP_SESSION_NOTCREATED; - if (usingpollthread) - return ERR_RTP_SESSION_USINGPOLLTHREAD; - if ((status = rtptrans->Poll()) < 0) - return status; - return ProcessPolledData(); -} - -int RTPSession::WaitForIncomingData(const RTPTime &delay, bool *dataavailable) -{ - if (!created) - return ERR_RTP_SESSION_NOTCREATED; - if (usingpollthread) - return ERR_RTP_SESSION_USINGPOLLTHREAD; - return rtptrans->WaitForIncomingData(delay, dataavailable); -} - -int RTPSession::AbortWait() -{ - if (!created) - return ERR_RTP_SESSION_NOTCREATED; - if (usingpollthread) - return ERR_RTP_SESSION_USINGPOLLTHREAD; - return rtptrans->AbortWait(); -} - RTPTime RTPSession::GetRTCPDelay() { if (!created) @@ -794,11 +693,7 @@ RTPTime RTPSession::GetRTCPDelay() if (usingpollthread) return RTPTime(0, 0); - SOURCES_LOCK - SCHED_LOCK RTPTime t = rtcpsched.GetTransmissionDelay(); - SCHED_UNLOCK - SOURCES_UNLOCK return t; } @@ -806,7 +701,6 @@ int RTPSession::BeginDataAccess() { if (!created) return ERR_RTP_SESSION_NOTCREATED; - SOURCES_LOCK return 0; } @@ -887,7 +781,6 @@ int RTPSession::EndDataAccess() { if (!created) return ERR_RTP_SESSION_NOTCREATED; - SOURCES_UNLOCK return 0; } @@ -953,10 +846,8 @@ int RTPSession::SetMaximumPacketSize(std::size_t s) if ((status = rtptrans->SetMaximumPacketSize(s)) < 0) return status; - BUILDER_LOCK if ((status = packetbuilder.SetMaximumPacketSize(s)) < 0) { - BUILDER_UNLOCK // restore previous max packet size rtptrans->SetMaximumPacketSize(maxpacksize); return status; @@ -965,11 +856,9 @@ int RTPSession::SetMaximumPacketSize(std::size_t s) { // restore previous max packet size packetbuilder.SetMaximumPacketSize(maxpacksize); - BUILDER_UNLOCK rtptrans->SetMaximumPacketSize(maxpacksize); return status; } - BUILDER_UNLOCK maxpacksize = s; return 0; } @@ -980,7 +869,6 @@ int RTPSession::SetSessionBandwidth(double bw) return ERR_RTP_SESSION_NOTCREATED; int status; - SCHED_LOCK RTCPSchedulerParams p = rtcpsched.GetParameters(); status = p.SetRTCPBandwidth(bw * controlfragment); if (status >= 0) @@ -988,7 +876,6 @@ int RTPSession::SetSessionBandwidth(double bw) rtcpsched.SetParameters(p); sessionbandwidth = bw; } - SCHED_UNLOCK return status; } @@ -999,9 +886,7 @@ int RTPSession::SetTimestampUnit(double u) int status; - BUILDER_LOCK status = rtcpbuilder.SetTimestampUnit(u); - BUILDER_UNLOCK return status; } @@ -1009,457 +894,384 @@ void RTPSession::SetNameInterval(int count) { if (!created) return; - BUILDER_LOCK rtcpbuilder.SetNameInterval(count); -BUILDER_UNLOCK } void RTPSession::SetEMailInterval(int count) { -if (!created) - return; -BUILDER_LOCK -rtcpbuilder.SetEMailInterval(count); -BUILDER_UNLOCK + if (!created) + return; + rtcpbuilder.SetEMailInterval(count); } void RTPSession::SetLocationInterval(int count) { -if (!created) -return; -BUILDER_LOCK -rtcpbuilder.SetLocationInterval(count); -BUILDER_UNLOCK + if (!created) + return; + rtcpbuilder.SetLocationInterval(count); } void RTPSession::SetPhoneInterval(int count) { -if (!created) -return; -BUILDER_LOCK -rtcpbuilder.SetPhoneInterval(count); -BUILDER_UNLOCK + if (!created) + return; + rtcpbuilder.SetPhoneInterval(count); } void RTPSession::SetToolInterval(int count) { -if (!created) -return; -BUILDER_LOCK -rtcpbuilder.SetToolInterval(count); -BUILDER_UNLOCK + if (!created) + return; + rtcpbuilder.SetToolInterval(count); } void RTPSession::SetNoteInterval(int count) { -if (!created) -return; -BUILDER_LOCK -rtcpbuilder.SetNoteInterval(count); -BUILDER_UNLOCK + if (!created) + return; + rtcpbuilder.SetNoteInterval(count); } int RTPSession::SetLocalName(const void *s, std::size_t len) { -if (!created) -return ERR_RTP_SESSION_NOTCREATED; + if (!created) + return ERR_RTP_SESSION_NOTCREATED; -int status; -BUILDER_LOCK -status = rtcpbuilder.SetLocalName(s, len); -BUILDER_UNLOCK -return status; + int status; + status = rtcpbuilder.SetLocalName(s, len); + return status; } int RTPSession::SetLocalEMail(const void *s, std::size_t len) { -if (!created) -return ERR_RTP_SESSION_NOTCREATED; + if (!created) + return ERR_RTP_SESSION_NOTCREATED; -int status; -BUILDER_LOCK -status = rtcpbuilder.SetLocalEMail(s, len); -BUILDER_UNLOCK -return status; + int status; + status = rtcpbuilder.SetLocalEMail(s, len); + return status; } int RTPSession::SetLocalLocation(const void *s, std::size_t len) { -if (!created) -return ERR_RTP_SESSION_NOTCREATED; + if (!created) + return ERR_RTP_SESSION_NOTCREATED; -int status; -BUILDER_LOCK -status = rtcpbuilder.SetLocalLocation(s, len); -BUILDER_UNLOCK -return status; + int status; + status = rtcpbuilder.SetLocalLocation(s, len); + return status; } int RTPSession::SetLocalPhone(const void *s, std::size_t len) { -if (!created) -return ERR_RTP_SESSION_NOTCREATED; + if (!created) + return ERR_RTP_SESSION_NOTCREATED; -int status; -BUILDER_LOCK -status = rtcpbuilder.SetLocalPhone(s, len); -BUILDER_UNLOCK -return status; + int status; + status = rtcpbuilder.SetLocalPhone(s, len); + return status; } int RTPSession::SetLocalTool(const void *s, std::size_t len) { -if (!created) -return ERR_RTP_SESSION_NOTCREATED; + if (!created) + return ERR_RTP_SESSION_NOTCREATED; -int status; -BUILDER_LOCK -status = rtcpbuilder.SetLocalTool(s, len); -BUILDER_UNLOCK -return status; + int status; + status = rtcpbuilder.SetLocalTool(s, len); + return status; } int RTPSession::SetLocalNote(const void *s, std::size_t len) { -if (!created) -return ERR_RTP_SESSION_NOTCREATED; + if (!created) + return ERR_RTP_SESSION_NOTCREATED; -int status; -BUILDER_LOCK -status = rtcpbuilder.SetLocalNote(s, len); -BUILDER_UNLOCK -return status; + int status; + status = rtcpbuilder.SetLocalNote(s, len); + return status; } int RTPSession::ProcessPolledData() { -RTPRawPacket *rawpack; -int status; + RTPRawPacket *rawpack; + int status; -SOURCES_LOCK -while ((rawpack = rtptrans->GetNextPacket()) != 0) -{ -if (m_changeIncomingData) -{ - // Provide a way to change incoming data, for decryption for example -if (!OnChangeIncomingData(rawpack)) -{ -delete rawpack; -continue; -} + while ((rawpack = rtptrans->GetNextPacket()) != 0) + { + if (m_changeIncomingData) + { + // Provide a way to change incoming data, for decryption for example + if (!OnChangeIncomingData(rawpack)) + { + delete rawpack; + continue; + } + } + + sources.ClearOwnCollisionFlag(); + + // since our sources instance also uses the scheduler (analysis of incoming packets) + // we'll lock it + if ((status = sources.ProcessRawPacket(rawpack, rtptrans, acceptownpackets)) < 0) + { + delete rawpack; + return status; + } + + if (sources.DetectedOwnCollision()) // collision handling! + { + bool created; + + if ((status = collisionlist.UpdateAddress(&rawpack->GetSenderAddress(), rawpack->GetReceiveTime(), &created)) < 0) + { + delete rawpack; + return status; + } + + if (created) // first time we've encountered this address, send bye packet and + { // change our own SSRC + bool hassentpackets = sentpackets; + + if (hassentpackets) + { + // Only send BYE packet if we've actually sent data using this + // SSRC + + RTCPCompoundPacket *rtcpcomppack; + + if ((status = rtcpbuilder.BuildBYEPacket(&rtcpcomppack, 0, 0, useSR_BYEifpossible)) < 0) + { + delete rawpack; + return status; + } + + byepackets.push_back(rtcpcomppack); + if (byepackets.size() == 1) // was the first packet, schedule a BYE packet (otherwise there's already one scheduled) + { + rtcpsched.ScheduleBYEPacket(rtcpcomppack->GetCompoundPacketLength()); + } + } + // bye packet is built and scheduled, now change our SSRC + // and reset the packet count in the transmitter + + uint32_t newssrc = packetbuilder.CreateNewSSRC(sources); + + sentpackets = false; + + // remove old entry in source table and add new one + + if ((status = sources.DeleteOwnSSRC()) < 0) + { + delete rawpack; + return status; + } + if ((status = sources.CreateOwnSSRC(newssrc)) < 0) + { + delete rawpack; + return status; + } + } + } + delete rawpack; + } + + RTPTime d = rtcpsched.CalculateDeterministicInterval(false); + + RTPTime t = RTPTime::CurrentTime(); + double Td = d.GetDouble(); + RTPTime sendertimeout = RTPTime(Td * sendermultiplier); + RTPTime generaltimeout = RTPTime(Td * membermultiplier); + RTPTime byetimeout = RTPTime(Td * byemultiplier); + RTPTime colltimeout = RTPTime(Td * collisionmultiplier); + RTPTime notetimeout = RTPTime(Td * notemultiplier); + + sources.MultipleTimeouts(t, sendertimeout, byetimeout, generaltimeout, notetimeout); + collisionlist.Timeout(t, colltimeout); + + // We'll check if it's time for RTCP stuff + + bool istime = rtcpsched.IsTime(); + + if (istime) + { + RTCPCompoundPacket *pack; + + // we'll check if there's a bye packet to send, or just a normal packet + + if (byepackets.empty()) + { + if ((status = rtcpbuilder.BuildNextPacket(&pack)) < 0) + { + return status; + } + if ((status = SendRTCPData(pack->GetCompoundPacketData(), pack->GetCompoundPacketLength())) < 0) + { + delete pack; + return status; + } + + sentpackets = true; + + OnSendRTCPCompoundPacket(pack); // we'll place this after the actual send to avoid tampering + } + else + { + pack = *(byepackets.begin()); + byepackets.pop_front(); + + if ((status = SendRTCPData(pack->GetCompoundPacketData(), pack->GetCompoundPacketLength())) < 0) + { + delete pack; + return status; + } + + sentpackets = true; + + OnSendRTCPCompoundPacket(pack); // we'll place this after the actual send to avoid tampering + + if (!byepackets.empty()) // more bye packets to send, schedule them + { + rtcpsched.ScheduleBYEPacket((*(byepackets.begin()))->GetCompoundPacketLength()); + } + } + + rtcpsched.AnalyseOutgoing(*pack); + + delete pack; + } + return 0; } -sources.ClearOwnCollisionFlag(); - - // since our sources instance also uses the scheduler (analysis of incoming packets) - // we'll lock it -SCHED_LOCK -if ((status = sources.ProcessRawPacket(rawpack, rtptrans, acceptownpackets)) < 0) -{ -SCHED_UNLOCK -SOURCES_UNLOCK -delete rawpack; -return status; -} -SCHED_UNLOCK - -if (sources.DetectedOwnCollision()) // collision handling! -{ -bool created; - -if ((status = collisionlist.UpdateAddress(rawpack->GetSenderAddress(), rawpack->GetReceiveTime(), &created)) < 0) -{ -SOURCES_UNLOCK -delete rawpack; -return status; -} - -if (created) // first time we've encountered this address, send bye packet and -{ // change our own SSRC -PACKSENT_LOCK -bool hassentpackets = sentpackets; -PACKSENT_UNLOCK - -if (hassentpackets) -{ - // Only send BYE packet if we've actually sent data using this - // SSRC - -RTCPCompoundPacket *rtcpcomppack; - -BUILDER_LOCK -if ((status = rtcpbuilder.BuildBYEPacket(&rtcpcomppack, 0, 0, useSR_BYEifpossible)) < 0) -{ -BUILDER_UNLOCK -SOURCES_UNLOCK -delete rawpack; -return status; -} -BUILDER_UNLOCK - -byepackets.push_back(rtcpcomppack); -if (byepackets.size() == 1) // was the first packet, schedule a BYE packet (otherwise there's already one scheduled) -{ -SCHED_LOCK -rtcpsched.ScheduleBYEPacket(rtcpcomppack->GetCompoundPacketLength()); -SCHED_UNLOCK -} -} - // bye packet is built and scheduled, now change our SSRC - // and reset the packet count in the transmitter - -BUILDER_LOCK -uint32_t newssrc = packetbuilder.CreateNewSSRC(sources); -BUILDER_UNLOCK - -PACKSENT_LOCK -sentpackets = false; -PACKSENT_UNLOCK - - // remove old entry in source table and add new one - -if ((status = sources.DeleteOwnSSRC()) < 0) -{ -SOURCES_UNLOCK -delete rawpack; -return status; -} -if ((status = sources.CreateOwnSSRC(newssrc)) < 0) -{ -SOURCES_UNLOCK -delete rawpack; -return status; -} -} -} -delete rawpack; -} - -SCHED_LOCK -RTPTime d = rtcpsched.CalculateDeterministicInterval(false); -SCHED_UNLOCK - -RTPTime t = RTPTime::CurrentTime(); -double Td = d.GetDouble(); -RTPTime sendertimeout = RTPTime(Td * sendermultiplier); -RTPTime generaltimeout = RTPTime(Td * membermultiplier); -RTPTime byetimeout = RTPTime(Td * byemultiplier); -RTPTime colltimeout = RTPTime(Td * collisionmultiplier); -RTPTime notetimeout = RTPTime(Td * notemultiplier); - -sources.MultipleTimeouts(t, sendertimeout, byetimeout, generaltimeout, notetimeout); -collisionlist.Timeout(t, colltimeout); - - // We'll check if it's time for RTCP stuff - -SCHED_LOCK -bool istime = rtcpsched.IsTime(); -SCHED_UNLOCK - -if (istime) -{ -RTCPCompoundPacket *pack; - - // we'll check if there's a bye packet to send, or just a normal packet - -if (byepackets.empty()) -{ -BUILDER_LOCK -if ((status = rtcpbuilder.BuildNextPacket(&pack)) < 0) -{ -BUILDER_UNLOCK -SOURCES_UNLOCK -return status; -} -BUILDER_UNLOCK -if ((status = SendRTCPData(pack->GetCompoundPacketData(), pack->GetCompoundPacketLength())) < 0) -{ -SOURCES_UNLOCK -delete pack; -return status; -} - -PACKSENT_LOCK -sentpackets = true; -PACKSENT_UNLOCK - -OnSendRTCPCompoundPacket(pack); // we'll place this after the actual send to avoid tampering -} -else -{ -pack = *(byepackets.begin()); -byepackets.pop_front(); - -if ((status = SendRTCPData(pack->GetCompoundPacketData(), pack->GetCompoundPacketLength())) < 0) -{ -SOURCES_UNLOCK -delete pack; -return status; -} - -PACKSENT_LOCK -sentpackets = true; -PACKSENT_UNLOCK - -OnSendRTCPCompoundPacket(pack); // we'll place this after the actual send to avoid tampering - -if (!byepackets.empty()) // more bye packets to send, schedule them -{ -SCHED_LOCK -rtcpsched.ScheduleBYEPacket((*(byepackets.begin()))->GetCompoundPacketLength()); -SCHED_UNLOCK -} -} - -SCHED_LOCK -rtcpsched.AnalyseOutgoing(*pack); -SCHED_UNLOCK - -delete pack; -} -SOURCES_UNLOCK -return 0; -} - -int RTPSession::CreateCNAME(uint8_t *buffer, std::size_t *bufferlength, bool resolve) +int RTPSession::CreateCNAME(uint8_t *buffer, std::size_t *bufferlength, bool resolve __attribute__((unused))) { #ifndef WIN32 -bool gotlogin = true; + bool gotlogin = true; #ifdef RTP_SUPPORT_GETLOGINR -buffer[0] = 0; -if (getlogin_r((char *) buffer, *bufferlength) != 0) -gotlogin = false; -else -{ -if (buffer[0] == 0) -gotlogin = false; -} + buffer[0] = 0; + if (getlogin_r((char *) buffer, *bufferlength) != 0) + gotlogin = false; + else + { + if (buffer[0] == 0) + gotlogin = false; + } -if (!gotlogin) // try regular getlogin -{ -char *loginname = getlogin(); -if (loginname == 0) -gotlogin = false; -else -strncpy((char *) buffer, loginname, *bufferlength); -} + if (!gotlogin) // try regular getlogin + { + char *loginname = getlogin(); + if (loginname == 0) + gotlogin = false; + else + strncpy((char *) buffer, loginname, *bufferlength); + } #else -char *loginname = getlogin(); -if (loginname == 0) -gotlogin = false; -else -strncpy((char *)buffer,loginname,*bufferlength); + char *loginname = getlogin(); + if (loginname == 0) + gotlogin = false; + else + strncpy((char *)buffer,loginname,*bufferlength); #endif // RTP_SUPPORT_GETLOGINR -if (!gotlogin) -{ -char *logname = getenv("LOGNAME"); -if (logname == 0) -return ERR_RTP_SESSION_CANTGETLOGINNAME; -strncpy((char *) buffer, logname, *bufferlength); -} + if (!gotlogin) + { + char *logname = getenv("LOGNAME"); + if (logname == 0) + return ERR_RTP_SESSION_CANTGETLOGINNAME; + strncpy((char *) buffer, logname, *bufferlength); + } #else // Win32 version #ifndef _WIN32_WCE -DWORD len = *bufferlength; -if (!GetUserName((LPTSTR)buffer,&len)) -RTP_STRNCPY((char *)buffer,"unknown",*bufferlength); + DWORD len = *bufferlength; + if (!GetUserName((LPTSTR)buffer,&len)) + strncpy((char *)buffer,"unknown",*bufferlength); #else -RTP_STRNCPY((char *)buffer,"unknown",*bufferlength); + strncpy((char *)buffer,"unknown",*bufferlength); #endif // _WIN32_WCE #endif // WIN32 -buffer[*bufferlength - 1] = 0; + buffer[*bufferlength - 1] = 0; -std::size_t offset = strlen((const char *) buffer); -if (offset < (*bufferlength - 1)) -buffer[offset] = (uint8_t) '@'; -offset++; + std::size_t offset = strlen((const char *) buffer); + if (offset < (*bufferlength - 1)) + buffer[offset] = (uint8_t) '@'; + offset++; -std::size_t buflen2 = *bufferlength - offset; -int status; + std::size_t buflen2 = *bufferlength - offset; -if (resolve) -{ -if ((status = rtptrans->GetLocalHostName(buffer + offset, &buflen2)) < 0) -return status; -*bufferlength = buflen2 + offset; -} -else -{ -char hostname[1024]; + char hostname[1024]; -RTP_STRNCPY(hostname, "localhost", 1024); // just in case gethostname fails + strncpy(hostname, "localhost", 1024); // just in case gethostname fails -gethostname(hostname, 1024); -RTP_STRNCPY((char * )(buffer + offset), hostname, buflen2); + gethostname(hostname, 1024); + strncpy((char * )(buffer + offset), hostname, buflen2); -*bufferlength = offset + strlen(hostname); -} -if (*bufferlength > RTCP_SDES_MAXITEMLENGTH) -*bufferlength = RTCP_SDES_MAXITEMLENGTH; -return 0; + *bufferlength = offset + strlen(hostname); + if (*bufferlength > RTCP_SDES_MAXITEMLENGTH) + *bufferlength = RTCP_SDES_MAXITEMLENGTH; + return 0; } RTPRandom *RTPSession::GetRandomNumberGenerator(RTPRandom *r) { -RTPRandom *rnew = 0; + RTPRandom *rnew = 0; -if (r == 0) -{ -rnew = RTPRandom::CreateDefaultRandomNumberGenerator(); -deletertprnd = true; -} -else -{ -rnew = r; -deletertprnd = false; -} + if (r == 0) + { + rnew = RTPRandom::CreateDefaultRandomNumberGenerator(); + deletertprnd = true; + } + else + { + rnew = r; + deletertprnd = false; + } -return rnew; + return rnew; } int RTPSession::SendRTPData(const void *data, std::size_t len) { -if (!m_changeOutgoingData) -return rtptrans->SendRTPData(data, len); + if (!m_changeOutgoingData) + return rtptrans->SendRTPData(data, len); -void *pSendData = 0; -std::size_t sendLen = 0; -int status = 0; + void *pSendData = 0; + std::size_t sendLen = 0; + int status = 0; -status = OnChangeRTPOrRTCPData(data, len, true, &pSendData, &sendLen); -if (status < 0) -return status; + status = OnChangeRTPOrRTCPData(data, len, true, &pSendData, &sendLen); + if (status < 0) + return status; -if (pSendData) -{ -status = rtptrans->SendRTPData(pSendData, sendLen); -OnSentRTPOrRTCPData(pSendData, sendLen, true); -} + if (pSendData) + { + status = rtptrans->SendRTPData(pSendData, sendLen); + OnSentRTPOrRTCPData(pSendData, sendLen, true); + } -return status; + return status; } int RTPSession::SendRTCPData(const void *data, std::size_t len) { -if (!m_changeOutgoingData) -return rtptrans->SendRTCPData(data, len); + if (!m_changeOutgoingData) + return rtptrans->SendRTCPData(data, len); -void *pSendData = 0; -std::size_t sendLen = 0; -int status = 0; + void *pSendData = 0; + std::size_t sendLen = 0; + int status = 0; -status = OnChangeRTPOrRTCPData(data, len, false, &pSendData, &sendLen); -if (status < 0) -return status; + status = OnChangeRTPOrRTCPData(data, len, false, &pSendData, &sendLen); + if (status < 0) + return status; -if (pSendData) -{ -status = rtptrans->SendRTCPData(pSendData, sendLen); -OnSentRTPOrRTCPData(pSendData, sendLen, false); -} + if (pSendData) + { + status = rtptrans->SendRTCPData(pSendData, sendLen); + OnSentRTPOrRTCPData(pSendData, sendLen, false); + } -return status; + return status; } } // end namespace diff --git a/qrtplib/rtpsession.h b/qrtplib/rtpsession.h index cf98baf65..2ad288a44 100644 --- a/qrtplib/rtpsession.h +++ b/qrtplib/rtpsession.h @@ -140,9 +140,6 @@ public: /** Leaves the multicast group specified by \c addr. */ int LeaveMulticastGroup(const RTPAddress &addr); - /** Leaves all multicast groups. */ - void LeaveAllMulticastGroups(); - /** Sends the RTP packet with payload \c data which has length \c len. * Sends the RTP packet with payload \c data which has length \c len. * The used payload type, marker and timestamp increment will be those that have been set @@ -233,23 +230,6 @@ public: /** Frees the memory used by the transmission information \c inf. */ void DeleteTransmissionInfo(RTPTransmissionInfo *inf); - /** If you're not using the poll thread, this function must be called regularly to process incoming data - * and to send RTCP data when necessary. - */ - int Poll(); - - /** Waits at most a time \c delay until incoming data has been detected. - * Waits at most a time \c delay until incoming data has been detected. Only works when you're not - * using the poll thread. If \c dataavailable is not \c NULL, it should be set to \c true if data - * was actually read and to \c false otherwise. - */ - int WaitForIncomingData(const RTPTime &delay, bool *dataavailable = 0); - - /** If the previous function has been called, this one aborts the waiting (only works when you're not - * using the poll thread). - */ - int AbortWait(); - /** Returns the time interval after which an RTCP compound packet may have to be sent (only works when * you're not using the poll thread. */ @@ -574,7 +554,7 @@ private: RTPTransmitter *rtptrans; bool created; bool deletetransmitter; - bool usingpollthread, needthreadsafety; + bool usingpollthread; bool acceptownpackets; bool useSR_BYEifpossible; std::size_t maxpacksize; diff --git a/qrtplib/rtpsources.cpp b/qrtplib/rtpsources.cpp index f72c19b3a..62bbc725f 100644 --- a/qrtplib/rtpsources.cpp +++ b/qrtplib/rtpsources.cpp @@ -191,7 +191,7 @@ int RTPSources::ProcessRawPacket(RTPRawPacket *rawpack, RTPTransmitter *rtptrans bool stored = false; bool ownpacket = false; int i; - const RTPAddress *senderaddress = rawpack->GetSenderAddress(); + const RTPAddress& senderaddress = rawpack->GetSenderAddress(); for (i = 0; !ownpacket && i < numtrans; i++) { @@ -217,7 +217,7 @@ int RTPSources::ProcessRawPacket(RTPRawPacket *rawpack, RTPTransmitter *rtptrans } else { - if ((status = ProcessRTPPacket(rtppack, rawpack->GetReceiveTime(), senderaddress, &stored)) < 0) + if ((status = ProcessRTPPacket(rtppack, rawpack->GetReceiveTime(), &senderaddress, &stored)) < 0) { if (!stored) delete rtppack; @@ -245,7 +245,7 @@ int RTPSources::ProcessRawPacket(RTPRawPacket *rawpack, RTPTransmitter *rtptrans { bool ownpacket = false; int i; - const RTPAddress *senderaddress = rawpack->GetSenderAddress(); + const RTPAddress& senderaddress = rawpack->GetSenderAddress(); for (i = 0; !ownpacket && i < numtrans; i++) { @@ -266,7 +266,7 @@ int RTPSources::ProcessRawPacket(RTPRawPacket *rawpack, RTPTransmitter *rtptrans } else // not our own packet { - status = ProcessRTCPCompoundPacket(&rtcpcomppack, rawpack->GetReceiveTime(), rawpack->GetSenderAddress()); + status = ProcessRTCPCompoundPacket(&rtcpcomppack, rawpack->GetReceiveTime(), &rawpack->GetSenderAddress()); if (status < 0) return status; } diff --git a/qrtplib/rtptransmitter.h b/qrtplib/rtptransmitter.h index a337fb30f..595e1bd7b 100644 --- a/qrtplib/rtptransmitter.h +++ b/qrtplib/rtptransmitter.h @@ -94,11 +94,8 @@ public: { } - /** This function must be called before the transmission component can be used. - * This function must be called before the transmission component can be used. Depending on - * the value of \c threadsafe, the component will be created for thread-safe usage or not. - */ - virtual int Init(bool threadsafe) = 0; + /** This function must be called before the transmission component can be used. */ + virtual int Init() = 0; /** Prepares the component to be used. * Prepares the component to be used. The parameter \c maxpacksize specifies the maximum size @@ -110,6 +107,9 @@ public: */ virtual int Create(std::size_t maxpacksize, const RTPTransmissionParams *transparams) = 0; + /** Bind the RTP and RTCP sockets to ports that were set at creation time */ + virtual int BindSockets() = 0; + /** By calling this function, buffers are cleared and the component cannot be used anymore. * By calling this function, buffers are cleared and the component cannot be used anymore. * Only when the Create function is called again can the component be used again. */ @@ -129,36 +129,13 @@ public: */ virtual void DeleteTransmissionInfo(RTPTransmissionInfo *inf) = 0; - /** Looks up the local host name. - * Looks up the local host name based upon internal information about the local host's - * addresses. This function might take some time since a DNS query might be done. \c bufferlength - * should initially contain the number of bytes that may be stored in \c buffer. If the function - * succeeds, \c bufferlength is set to the number of bytes stored in \c buffer. Note that the data - * in \c buffer is not NULL-terminated. If the function fails because the buffer isn't large enough, - * it returns \c ERR_RTP_TRANS_BUFFERLENGTHTOOSMALL and stores the number of bytes needed in - * \c bufferlength. - */ - virtual int GetLocalHostName(uint8_t *buffer, std::size_t *bufferlength) = 0; - /** Returns \c true if the address specified by \c addr is one of the addresses of the transmitter. */ - virtual bool ComesFromThisTransmitter(const RTPAddress *addr) = 0; + virtual bool ComesFromThisTransmitter(const RTPAddress& addr) = 0; /** Returns the amount of bytes that will be added to the RTP packet by the underlying layers (excluding * the link layer). */ virtual std::size_t GetHeaderOverhead() = 0; - /** Checks for incoming data and stores it. */ - virtual int Poll() = 0; - - /** Waits until incoming data is detected. - * Waits at most a time \c delay until incoming data has been detected. If \c dataavailable is not NULL, - * it should be set to \c true if data was actually read and to \c false otherwise. - */ - virtual int WaitForIncomingData(const RTPTime &delay, bool *dataavailable = 0) = 0; - - /** If the previous function has been called, this one aborts the waiting. */ - virtual int AbortWait() = 0; - /** Send a packet with length \c len containing \c data to all RTP addresses of the current destination list. */ virtual int SendRTPData(const void *data, std::size_t len) = 0; @@ -183,9 +160,6 @@ public: /** Leaves the multicast group specified by \c addr. */ virtual int LeaveMulticastGroup(const RTPAddress &addr) = 0; - /** Leaves all the multicast groups that have been joined. */ - virtual void LeaveAllMulticastGroups() = 0; - /** Sets the receive mode. * Sets the receive mode to \c m, which is one of the following: RTPTransmitter::AcceptAll, * RTPTransmitter::AcceptSome or RTPTransmitter::IgnoreSome. Note that if the receive @@ -214,10 +188,7 @@ public: /** Sets the maximum packet size which the transmitter should allow to \c s. */ virtual int SetMaximumPacketSize(std::size_t s) = 0; - /** Returns \c true if packets can be obtained using the GetNextPacket member function. */ - virtual bool NewDataAvailable() = 0; - - /** Returns the raw data of a received RTP packet (received during the Poll function) + /** Returns the raw data of a received RTP packet * in an RTPRawPacket instance. */ virtual RTPRawPacket *GetNextPacket() = 0; }; diff --git a/qrtplib/rtpudptransmitter.cpp b/qrtplib/rtpudptransmitter.cpp index ee889b80a..e7650afc6 100644 --- a/qrtplib/rtpudptransmitter.cpp +++ b/qrtplib/rtpudptransmitter.cpp @@ -32,13 +32,17 @@ #include "rtpudptransmitter.h" #include "rtperrors.h" +#include "rtpaddress.h" +#include "rtpstructs.h" +#include "rtprawpacket.h" -#define RTPUDPTRANS_MAXPACKSIZE 65535 +#include namespace qrtplib { -RTPUDPTransmitter::RTPUDPTransmitter() +RTPUDPTransmitter::RTPUDPTransmitter() : + m_rawPacketQueueLock(QMutex::Recursive) { m_created = false; m_init = false; @@ -48,9 +52,7 @@ RTPUDPTransmitter::RTPUDPTransmitter() m_closesocketswhendone = false; m_rtcpPort = 0; m_rtpPort = 0; - m_supportsmulticasting = false; m_receivemode = RTPTransmitter::AcceptAll; - m_localhostname = 0; } RTPUDPTransmitter::~RTPUDPTransmitter() @@ -71,11 +73,9 @@ int RTPUDPTransmitter::Init() int RTPUDPTransmitter::Create(std::size_t maximumpacketsize, const RTPTransmissionParams *transparams) { const RTPUDPTransmissionParams *params, defaultparams; - struct sockaddr_in addr; qint64 size; - int status; - if (maximumpacketsize > RTPUDPTRANS_MAXPACKSIZE) { + if (maximumpacketsize > m_absoluteMaxPackSize) { return ERR_RTP_UDPV4TRANS_SPECIFIEDSIZETOOBIG; } @@ -98,7 +98,7 @@ int RTPUDPTransmitter::Create(std::size_t maximumpacketsize, const RTPTransmissi { return ERR_RTP_UDPV4TRANS_ILLEGALPARAMETERS; } - params = (const RTPUDPv4TransmissionParams *) transparams; + params = (const RTPUDPTransmissionParams *) transparams; } // Determine the port numbers @@ -155,18 +155,35 @@ int RTPUDPTransmitter::Create(std::size_t maximumpacketsize, const RTPTransmissi } m_maxpacksize = maximumpacketsize; - m_mcastifaceIP = params->GetMulticastInterfaceIP(); + m_multicastInterface = params->GetMulticastInterface(); m_receivemode = RTPTransmitter::AcceptAll; - m_localhostname = 0; - m_localhostnamelength = 0; - m_waitingfordata = false; m_created = true; return 0; } +int RTPUDPTransmitter::BindSockets() +{ + if (!m_rtpsock->bind(m_localIP, m_rtpPort)) { + return ERR_RTP_UDPV4TRANS_CANTBINDRTPSOCKET; + } + + connect(m_rtpsock, SIGNAL(readyRead()), this, SLOT(readRTPPendingDatagrams())); + + if (m_rtpsock != m_rtcpsock) + { + if (!m_rtcpsock->bind(m_localIP, m_rtcpPort)) { + return ERR_RTP_UDPV4TRANS_CANTBINDRTCPSOCKET; + } + + connect(m_rtcpsock, SIGNAL(readyRead()), this, SLOT(readRTCPPendingDatagrams())); + } + + return 0; +} + void RTPUDPTransmitter::Destroy() { if (!m_init) { @@ -178,16 +195,6 @@ void RTPUDPTransmitter::Destroy() return; } - if (m_localhostname) - { - delete[] m_localhostname; - m_localhostname = 0; - m_localhostnamelength = 0; - } - - FlushPackets(); - ClearAcceptIgnoreInfo(); - if (m_closesocketswhendone) { if (m_rtpsock != m_rtcpsock) { @@ -206,8 +213,7 @@ RTPTransmissionInfo *RTPUDPTransmitter::GetTransmissionInfo() return 0; } - RTPTransmissionInfo *tinf = new RTPUDPv4TransmissionNoBindInfo( - m_localIP, m_rtpsock, m_rtcpsock, m_rtpPort, m_rtcpPort); + RTPTransmissionInfo *tinf = new RTPUDPTransmissionInfo(m_localIP, m_rtpsock, m_rtcpsock, m_rtpPort, m_rtcpPort); return tinf; } @@ -221,13 +227,326 @@ void RTPUDPTransmitter::DeleteTransmissionInfo(RTPTransmissionInfo *inf) delete inf; } -bool RTPUDPTransmitter::ComesFromThisTransmitter(const RTPAddress *addr) +bool RTPUDPTransmitter::ComesFromThisTransmitter(const RTPAddress& addr) { - if (addr->getAddress() != m_localIP) { + if (addr.getAddress() != m_localIP) { return false; } - return (addr->getPort() == m_rtpPort) && (addr->getRtcpsendport() == m_rtcpPort); + return (addr.getPort() == m_rtpPort) && (addr.getRtcpsendport() == m_rtcpPort); +} + +int RTPUDPTransmitter::SendRTPData(const void *data, std::size_t len) +{ + if (!m_init) { + return ERR_RTP_UDPV4TRANS_NOTINIT; + } + + if (!m_created) { + return ERR_RTP_UDPV4TRANS_NOTCREATED; + } + + if (len > m_maxpacksize) + { + return ERR_RTP_UDPV4TRANS_SPECIFIEDSIZETOOBIG; + } + + std::list::const_iterator it = m_destinations.begin(); + + for (; it != m_destinations.end(); ++it) + { + m_rtpsock->writeDatagram((const char*) data, (qint64) len, it->getAddress(), it->getPort()); + } + + return 0; +} + +int RTPUDPTransmitter::SendRTCPData(const void *data, std::size_t len) +{ + if (!m_init) { + return ERR_RTP_UDPV4TRANS_NOTINIT; + } + + if (!m_created) { + return ERR_RTP_UDPV4TRANS_NOTCREATED; + } + + if (len > m_maxpacksize) { + return ERR_RTP_UDPV4TRANS_SPECIFIEDSIZETOOBIG; + } + + std::list::const_iterator it = m_destinations.begin(); + + for (; it != m_destinations.end(); ++it) + { + m_rtcpsock->writeDatagram((const char*) data, (qint64) len, it->getAddress(), it->getRtcpsendport()); + } + + return 0; +} + +int RTPUDPTransmitter::AddDestination(const RTPAddress &addr) +{ + m_destinations.push_back(addr); + return 0; +} + +int RTPUDPTransmitter::DeleteDestination(const RTPAddress &addr) +{ + m_destinations.remove(addr); + return 0; +} + +void RTPUDPTransmitter::ClearDestinations() +{ + m_destinations.clear(); +} + +bool RTPUDPTransmitter::SupportsMulticasting() +{ + QNetworkInterface::InterfaceFlags flags = m_multicastInterface.flags(); + QAbstractSocket::SocketState rtpSocketState = m_rtpsock->state(); + QAbstractSocket::SocketState rtcpSocketState = m_rtcpsock->state(); + return m_multicastInterface.isValid() + && (rtpSocketState & QAbstractSocket::BoundState) + && (rtcpSocketState & QAbstractSocket::BoundState) + && (flags & QNetworkInterface::CanMulticast) + && (flags & QNetworkInterface::IsRunning) + && !(flags & QNetworkInterface::IsLoopBack); +} + +int RTPUDPTransmitter::JoinMulticastGroup(const RTPAddress &addr) +{ + if (!m_init) { + return ERR_RTP_UDPV4TRANS_NOTINIT; + } + + if (!m_created) { + return ERR_RTP_UDPV4TRANS_NOTCREATED; + } + + if (!SupportsMulticasting()) { + return ERR_RTP_UDPV6TRANS_NOMULTICASTSUPPORT; + } + + if (m_rtpsock->joinMulticastGroup(addr.getAddress(), m_multicastInterface)) + { + if (m_rtpsock != m_rtcpsock) + { + if (!m_rtcpsock->joinMulticastGroup(addr.getAddress(), m_multicastInterface)) { + return ERR_RTP_UDPV4TRANS_COULDNTJOINMULTICASTGROUP; + } + } + } + else + { + return ERR_RTP_UDPV4TRANS_COULDNTJOINMULTICASTGROUP; + } + + return 0; +} + +int RTPUDPTransmitter::LeaveMulticastGroup(const RTPAddress &addr) +{ + if (!m_init) { + return ERR_RTP_UDPV4TRANS_NOTINIT; + } + + if (!m_created) { + return ERR_RTP_UDPV4TRANS_NOTCREATED; + } + + if (!SupportsMulticasting()) { + return ERR_RTP_UDPV6TRANS_NOMULTICASTSUPPORT; + } + + m_rtpsock->leaveMulticastGroup(addr.getAddress()); + + if (m_rtpsock != m_rtcpsock) + { + m_rtcpsock->leaveMulticastGroup(addr.getAddress()); + } + + return 0; +} + +int RTPUDPTransmitter::SetReceiveMode(RTPTransmitter::ReceiveMode m) +{ + if (!m_init) { + return ERR_RTP_UDPV4TRANS_NOTINIT; + } + + if (!m_created) { + return ERR_RTP_UDPV4TRANS_NOTCREATED; + } + + if (m != m_receivemode) { + m_receivemode = m; + } + + return 0; +} + +int RTPUDPTransmitter::AddToIgnoreList(const RTPAddress &addr) +{ + m_ignoreList.push_back(addr); + return 0; +} + +int RTPUDPTransmitter::DeleteFromIgnoreList(const RTPAddress &addr) +{ + m_ignoreList.remove(addr); + return 0; +} + +void RTPUDPTransmitter::ClearIgnoreList() +{ + m_ignoreList.clear(); +} + +int RTPUDPTransmitter::AddToAcceptList(const RTPAddress &addr) +{ + m_acceptList.push_back(addr); + return 0; +} + +int RTPUDPTransmitter::DeleteFromAcceptList(const RTPAddress &addr) +{ + m_acceptList.remove(addr); + return 0; +} + +void RTPUDPTransmitter::ClearAcceptList() +{ + m_acceptList.clear(); +} + +int RTPUDPTransmitter::SetMaximumPacketSize(std::size_t s) +{ + if (!m_init) { + return ERR_RTP_UDPV4TRANS_NOTINIT; + } + + if (!m_created) { + return ERR_RTP_UDPV4TRANS_NOTCREATED; + } + + if (s > m_absoluteMaxPackSize) { + return ERR_RTP_UDPV4TRANS_SPECIFIEDSIZETOOBIG; + } + + m_maxpacksize = s; + return 0; +} + +RTPRawPacket *RTPUDPTransmitter::GetNextPacket() +{ + QMutexLocker locker(&m_rawPacketQueueLock); + + if (m_rawPacketQueue.isEmpty()) { + return 0; + } else { + return m_rawPacketQueue.takeFirst(); + } +} + +void RTPUDPTransmitter::readRTPPendingDatagrams() +{ + while (m_rtpsock->hasPendingDatagrams()) + { + RTPTime curtime = RTPTime::CurrentTime(); + QHostAddress remoteAddress; + quint16 remotePort; + qint64 pendingDataSize = m_rtpsock->pendingDatagramSize(); + qint64 bytesRead = m_rtpsock->readDatagram(m_rtpBuffer, pendingDataSize, &remoteAddress, &remotePort); + qDebug("RTPUDPTransmitter::readRTPPendingDatagrams: %lld bytes read from %s:%d", + bytesRead, + qPrintable(remoteAddress.toString()), + remotePort); + + RTPAddress rtpAddress; + rtpAddress.setAddress(remoteAddress); + rtpAddress.setPort(remotePort); + + if (ShouldAcceptData(rtpAddress)) + { + bool isrtp = true; + + if (m_rtpsock == m_rtcpsock) // check payload type when multiplexing + { + if ((std::size_t) bytesRead > sizeof(RTCPCommonHeader)) + { + RTCPCommonHeader *rtcpheader = (RTCPCommonHeader *) m_rtpBuffer; + uint8_t packettype = rtcpheader->packettype; + + if (packettype >= 200 && packettype <= 204) { + isrtp = false; + } + } + } + + RTPRawPacket *pack = new RTPRawPacket((uint8_t *) m_rtpBuffer, bytesRead, rtpAddress, curtime, isrtp); + + m_rawPacketQueueLock.lock(); + m_rawPacketQueue.append(pack); + m_rawPacketQueueLock.unlock(); + + emit NewDataAvailable(); + } + } +} + +void RTPUDPTransmitter::readRTCPPendingDatagrams() +{ + while (m_rtcpsock->hasPendingDatagrams()) + { + RTPTime curtime = RTPTime::CurrentTime(); + QHostAddress remoteAddress; + quint16 remotePort; + qint64 pendingDataSize = m_rtcpsock->pendingDatagramSize(); + qint64 bytesRead = m_rtcpsock->readDatagram(m_rtcpBuffer, pendingDataSize, &remoteAddress, &remotePort); + qDebug("RTPUDPTransmitter::readRTCPPendingDatagrams: %lld bytes read from %s:%d", + bytesRead, + qPrintable(remoteAddress.toString()), + remotePort); + + RTPAddress rtpAddress; + rtpAddress.setAddress(remoteAddress); + rtpAddress.setPort(remotePort); + + if (ShouldAcceptData(rtpAddress)) + { + RTPRawPacket *pack = new RTPRawPacket((uint8_t *) m_rtcpBuffer, bytesRead, rtpAddress, curtime, false); + + m_rawPacketQueueLock.lock(); + m_rawPacketQueue.append(pack); + m_rawPacketQueueLock.unlock(); + + emit NewDataAvailable(); + } + } +} + +bool RTPUDPTransmitter::ShouldAcceptData(const RTPAddress& rtpAddress) +{ + if (m_receivemode == RTPTransmitter::AcceptAll) + { + return true; + } + else if (m_receivemode == RTPTransmitter::AcceptSome) + { + std::list::iterator findIt = std::find(m_acceptList.begin(), m_acceptList.end(), rtpAddress); + return findIt != m_acceptList.end(); + } + else if (m_receivemode == RTPTransmitter::IgnoreSome) + { + std::list::iterator findIt = std::find(m_ignoreList.begin(), m_ignoreList.end(), rtpAddress); + return findIt == m_ignoreList.end(); + } + else + { + return false; + } } } // namespace diff --git a/qrtplib/rtpudptransmitter.h b/qrtplib/rtpudptransmitter.h index ae298de9d..48fbbf8b3 100644 --- a/qrtplib/rtpudptransmitter.h +++ b/qrtplib/rtpudptransmitter.h @@ -34,12 +34,17 @@ #define QRTPLIB_RTPUDPTRANSMITTER_H_ #include "rtptransmitter.h" +#include "util/export.h" + +#include #include +#include +#include +#include + #include #include -#include "util/export.h" - #define RTPUDPV4TRANS_HASHSIZE 8317 #define RTPUDPV4TRANS_DEFAULTPORTBASE 5000 #define RTPUDPV4TRANS_RTPRECEIVEBUFFER 32768 @@ -64,8 +69,8 @@ public: } /** Sets the multicast interface IP address. */ - void SetMulticastInterfaceIP(const QHostAddress& mcastGroupAddress) { - m_mcastGroupAddress = mcastGroupAddress; + void SetMulticastInterface(const QNetworkInterface& mcastInterface) { + m_mcastInterface = mcastInterface; } /** Sets the RTP portbase to \c pbase, which has to be an even number @@ -76,21 +81,6 @@ public: m_portbase = pbase; } - /** Passes a list of IP addresses which will be used as the local IP addresses. */ - void SetLocalIPList(const std::list& iplist) - { - m_localIPs = iplist; - } - - /** Clears the list of local IP addresses. - * Clears the list of local IP addresses. An empty list will make the transmission - * component itself determine the local IP addresses. - */ - void ClearLocalIPList() - { - m_localIPs.clear(); - } - /** Returns the IP address which will be used to bind the sockets. */ QHostAddress GetBindIP() const { @@ -98,9 +88,9 @@ public: } /** Returns the multicast interface IP address. */ - QHostAddress GetMulticastInterfaceIP() const + QNetworkInterface GetMulticastInterface() const { - return m_mcastGroupAddress; + return m_mcastInterface; } /** Returns the RTP portbase which will be used (default is 5000). */ @@ -109,12 +99,6 @@ public: return m_portbase; } - /** Returns the list of local IP addresses. */ - const std::list &GetLocalIPList() const - { - return m_localIPs; - } - /** Sets the RTP socket's send buffer size. */ void SetRTPSendBufferSize(int s) { @@ -225,9 +209,8 @@ public: private: QHostAddress m_bindAddress; - QHostAddress m_mcastGroupAddress; + QNetworkInterface m_mcastInterface; uint16_t m_portbase; - std::list m_localIPs; int m_rtpsendbufsz, m_rtprecvbufsz; int m_rtcpsendbufsz, m_rtcprecvbufsz; bool m_rtcpmux; @@ -258,10 +241,15 @@ inline RTPUDPTransmissionParams::RTPUDPTransmissionParams() : class QRTPLIB_API RTPUDPTransmissionInfo: public RTPTransmissionInfo { public: - RTPUDPTransmissionInfo(const std::list& iplist, QUdpSocket *rtpsock, QUdpSocket *rtcpsock, uint16_t rtpport, uint16_t rtcpport) : - RTPTransmissionInfo(RTPTransmitter::IPv4UDPProto) + RTPUDPTransmissionInfo( + QHostAddress localIP, + QUdpSocket *rtpsock, + QUdpSocket *rtcpsock, + uint16_t rtpport, + uint16_t rtcpport) : + RTPTransmissionInfo(RTPTransmitter::IPv4UDPProto) { - m_localIPlist = iplist; + m_localIP = localIP; m_rtpsocket = rtpsock; m_rtcpsocket = rtcpsock; m_rtpPort = rtpport; @@ -272,12 +260,6 @@ public: { } - /** Returns the list of IPv4 addresses the transmitter considers to be the local IP addresses. */ - std::list GetLocalIPList() const - { - return m_localIPlist; - } - /** Returns the socket descriptor used for receiving and transmitting RTP packets. */ QUdpSocket *GetRTPSocket() const { @@ -302,7 +284,7 @@ public: return m_rtcpPort; } private: - std::list m_localIPlist; + QHostAddress m_localIP; QUdpSocket *m_rtpsocket, *m_rtcpsocket; uint16_t m_rtpPort, m_rtcpPort; }; @@ -315,81 +297,79 @@ private: * are described by the class RTPUDPTransmissionParams. The GetTransmissionInfo member function * returns an instance of type RTPUDPTransmissionInfo. */ -class QRTPLIB_API RTPUDPTransmitter: public RTPTransmitter +class QRTPLIB_API RTPUDPTransmitter: public QObject, public RTPTransmitter { + Q_OBJECT public: RTPUDPTransmitter(); - ~RTPUDPTransmitter(); + virtual ~RTPUDPTransmitter(); - int Init(); - int Create(std::size_t maxpacksize, const RTPTransmissionParams *transparams); - void Destroy(); - RTPTransmissionInfo *GetTransmissionInfo(); - void DeleteTransmissionInfo(RTPTransmissionInfo *inf); + virtual int Init(); + virtual int Create(std::size_t maxpacksize, const RTPTransmissionParams *transparams); + virtual int BindSockets(); + virtual void Destroy(); + virtual RTPTransmissionInfo *GetTransmissionInfo(); + virtual void DeleteTransmissionInfo(RTPTransmissionInfo *inf); - bool ComesFromThisTransmitter(const RTPAddress *addr); - std::size_t GetHeaderOverhead() + virtual bool ComesFromThisTransmitter(const RTPAddress& addr); + virtual std::size_t GetHeaderOverhead() { return RTPUDPTRANS_HEADERSIZE; } - int Poll(); - int WaitForIncomingData(const RTPTime &delay, bool *dataavailable = 0); - int AbortWait(); + virtual int SendRTPData(const void *data, std::size_t len); + virtual int SendRTCPData(const void *data, std::size_t len); - int SendRTPData(const void *data, std::size_t len); - int SendRTCPData(const void *data, std::size_t len); + virtual int AddDestination(const RTPAddress &addr); + virtual int DeleteDestination(const RTPAddress &addr); + virtual void ClearDestinations(); - int AddDestination(const RTPAddress &addr); - int DeleteDestination(const RTPAddress &addr); - void ClearDestinations(); + virtual bool SupportsMulticasting(); + virtual int JoinMulticastGroup(const RTPAddress &addr); + virtual int LeaveMulticastGroup(const RTPAddress &addr); - bool SupportsMulticasting(); - int JoinMulticastGroup(const RTPAddress &addr); - int LeaveMulticastGroup(const RTPAddress &addr); - void LeaveAllMulticastGroups(); + virtual int SetReceiveMode(RTPTransmitter::ReceiveMode m); + virtual int AddToIgnoreList(const RTPAddress &addr); + virtual int DeleteFromIgnoreList(const RTPAddress &addr); + virtual void ClearIgnoreList(); + virtual int AddToAcceptList(const RTPAddress &addr); + virtual int DeleteFromAcceptList(const RTPAddress &addr); + virtual void ClearAcceptList(); + virtual int SetMaximumPacketSize(std::size_t s); - int SetReceiveMode(RTPTransmitter::ReceiveMode m); - int AddToIgnoreList(const RTPAddress &addr); - int DeleteFromIgnoreList(const RTPAddress &addr); - void ClearIgnoreList(); - int AddToAcceptList(const RTPAddress &addr); - int DeleteFromAcceptList(const RTPAddress &addr); - void ClearAcceptList(); - int SetMaximumPacketSize(std::size_t s); - - bool NewDataAvailable(); // TODO: emit signal instead - RTPRawPacket *GetNextPacket(); // TODO: use a queue + virtual RTPRawPacket *GetNextPacket(); private: - int CreateLocalIPList(); - bool GetLocalIPList_Interfaces(); - void GetLocalIPList_DNS(); - void AddLoopbackAddress(); - void FlushPackets(); - int ProcessAddAcceptIgnoreEntry(uint32_t ip, uint16_t port); - int ProcessDeleteAcceptIgnoreEntry(uint32_t ip, uint16_t port); - bool ShouldAcceptData(uint32_t srcip, uint16_t srcport); - void ClearAcceptIgnoreInfo(); - bool m_init; bool m_created; bool m_waitingfordata; QUdpSocket *m_rtpsock, *m_rtcpsock; - QHostAddress m_mcastifaceIP; - QHostAddress m_localIP; + QHostAddress m_localIP; //!< from parameters bind IP + QNetworkInterface m_multicastInterface; //!< from parameters multicast interface uint16_t m_rtpPort, m_rtcpPort; RTPTransmitter::ReceiveMode m_receivemode; - uint8_t *m_localhostname; - std::size_t m_localhostnamelength; - - std::list m_rawpacketlist; - - bool m_supportsmulticasting; std::size_t m_maxpacksize; + static const std::size_t m_absoluteMaxPackSize = 65535; + char m_rtpBuffer[m_absoluteMaxPackSize]; + char m_rtcpBuffer[m_absoluteMaxPackSize]; + + std::list m_destinations; + std::list m_acceptList; + std::list m_ignoreList; + QQueue m_rawPacketQueue; + QMutex m_rawPacketQueueLock; bool m_closesocketswhendone; + + bool ShouldAcceptData(const RTPAddress& address); + +private slots: + void readRTPPendingDatagrams(); + void readRTCPPendingDatagrams(); + +signals: + void NewDataAvailable(); };