qrtplib: removed debug

This commit is contained in:
f4exb 2018-02-27 01:35:16 +01:00
parent 7f067da9cc
commit 30d019d39a
102 changed files with 29077 additions and 0 deletions

124
qrtplib/CMakeLists.txt Normal file
View File

@ -0,0 +1,124 @@
project(qrtplib)
set (qrtplib_HEADERS
rtcpapppacket.h
rtcpbyepacket.h
rtcpcompoundpacket.h
rtcpcompoundpacketbuilder.h
rtcppacket.h
rtcppacketbuilder.h
rtcprrpacket.h
rtcpscheduler.h
rtcpsdesinfo.h
rtcpsdespacket.h
rtcpsrpacket.h
rtcpunknownpacket.h
rtpaddress.h
rtpcollisionlist.h
rtpconfig.h
rtpdefines.h
rtperrors.h
rtphashtable.h
rtpinternalsourcedata.h
rtpipv4address.h
rtpipv4destination.h
rtpipv6address.h
rtpipv6destination.h
rtpkeyhashtable.h
rtplibraryversion.h
rtpmemorymanager.h
rtpmemoryobject.h
rtppacket.h
rtppacketbuilder.h
rtppollthread.h
rtprandom.h
rtprandomrand48.h
rtprandomrands.h
rtprandomurandom.h
rtprawpacket.h
rtpsession.h
rtpsessionparams.h
rtpsessionsources.h
rtpsourcedata.h
rtpsources.h
rtpstructs.h
rtptimeutilities.h
rtptransmitter.h
rtptypes_win.h
rtptypes.h
rtpudpv4transmitter.h
rtpudpv4transmitternobind.h
rtpudpv6transmitter.h
rtpbyteaddress.h
rtpexternaltransmitter.h
rtpsecuresession.h
rtpsocketutil.h
rtpabortdescriptors.h
rtpselect.h
rtptcpaddress.h
rtptcptransmitter.h
)
set(qrtplib_SOURCES
rtcpapppacket.cpp
rtcpbyepacket.cpp
rtcpcompoundpacket.cpp
rtcpcompoundpacketbuilder.cpp
rtcppacketbuilder.cpp
rtcprrpacket.cpp
rtcpscheduler.cpp
rtcpsdesinfo.cpp
rtcpsdespacket.cpp
rtcpsrpacket.cpp
rtpcollisionlist.cpp
rtperrors.cpp
rtpinternalsourcedata.cpp
rtpipv4address.cpp
rtpipv6address.cpp
rtpipv4destination.cpp
rtpipv6destination.cpp
rtplibraryversion.cpp
rtppacket.cpp
rtppacketbuilder.cpp
rtppollthread.cpp
rtprandom.cpp
rtprandomrand48.cpp
rtprandomrands.cpp
rtprandomurandom.cpp
rtpsession.cpp
rtpsessionparams.cpp
rtpsessionsources.cpp
rtpsourcedata.cpp
rtpsources.cpp
rtptimeutilities.cpp
rtpudpv4transmitter.cpp
rtpudpv4transmitternobind.cpp
rtpudpv6transmitter.cpp
rtpbyteaddress.cpp
rtpexternaltransmitter.cpp
rtpsecuresession.cpp
rtpabortdescriptors.cpp
rtptcpaddress.cpp
rtptcptransmitter.cpp
)
include_directories(
.
${CMAKE_CURRENT_BINARY_DIR}
)
add_definitions(${QT_DEFINITIONS})
add_definitions(-DQT_SHARED)
add_library(qrtplib SHARED
${qrtplib_SOURCES}
${qrtplib_HEADERS_MOC}
)
target_link_libraries(qrtplib
${QT_LIBRARIES}
)
qt5_use_modules(qrtplib Core Network)
install(TARGETS qrtplib DESTINATION lib)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,244 @@
/*
This class allows for jrtp to process packets without sending them out
anywhere.
The incoming messages are handed in to jrtp through the TransmissionParams
and can be retreived from jrtp through the normal polling mecanisms.
The outgoing RTP/RTCP packets are given to jrtp through the normal
session->SendPacket() and those packets are handed back out to the
client through a callback function (packet_ready_cb).
example usage : Allows for integration of RTP into gstreamer.
Copyright (c) 2005 Philippe Khalaf <burger@speedy.org>
This file is a part of JRTPLIB
Copyright (c) 1999-2004 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
This library was developed at the "Expertisecentrum Digitale Media"
(http://www.edm.luc.ac.be), a research center of the "Limburgs Universitair
Centrum" (http://www.luc.ac.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
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef RTPFAKETRANSMITTER_H
#define RTPFAKETRANSMITTER_H
#include "rtpconfig.h"
#include "rtptransmitter.h"
#include "rtpipv4destination.h"
#include "rtphashtable.h"
#include "rtpkeyhashtable.h"
#include <list>
#ifdef RTP_SUPPORT_THREAD
#include <jthread/jmutex.h>
#endif // RTP_SUPPORT_THREAD
#define RTPFAKETRANS_HASHSIZE 8317
#define RTPFAKETRANS_DEFAULTPORTBASE 5000
namespace qrtplib
{
// Definition of a callback that is called when a packet is ready for sending
// params (*data, data_len, dest_addr, dest_port, rtp [1 if rtp, 0 if rtcp])
typedef void(*packet_ready_cb)(void*, uint8_t*, uint16_t, uint32_t, uint16_t, int rtp);
class RTPFakeTransmissionParams : public RTPTransmissionParams
{
public:
RTPFakeTransmissionParams():RTPTransmissionParams(RTPTransmitter::UserDefinedProto) { portbase = RTPFAKETRANS_DEFAULTPORTBASE; bindIP = 0; multicastTTL = 1; currentdata = NULL;}
void SetBindIP(uint32_t ip) { bindIP = ip; }
void SetPortbase(uint16_t pbase) { portbase = pbase; }
void SetMulticastTTL(uint8_t mcastTTL) { multicastTTL = mcastTTL; }
void SetLocalIPList(std::list<uint32_t> &iplist) { localIPs = iplist; }
void ClearLocalIPList() { localIPs.clear(); }
void SetCurrentData(uint8_t *data) { currentdata = data; }
void SetCurrentDataLen(uint16_t len) { currentdatalen = len; }
void SetCurrentDataAddr(uint32_t addr) { currentdataaddr = addr; }
void SetCurrentDataPort(uint16_t port) { currentdataport = port; }
void SetCurrentDataType(bool type) { currentdatatype = type; }
void SetPacketReadyCB(packet_ready_cb cb) { packetreadycb = cb; };
void SetPacketReadyCBData(void *data) { packetreadycbdata = data; };
uint32_t GetBindIP() const { return bindIP; }
uint16_t GetPortbase() const { return portbase; }
uint8_t GetMulticastTTL() const { return multicastTTL; }
const std::list<uint32_t> &GetLocalIPList() const { return localIPs; }
uint8_t* GetCurrentData() const { return currentdata; }
uint16_t GetCurrentDataLen() const { return currentdatalen; }
uint32_t GetCurrentDataAddr() const { return currentdataaddr; }
uint16_t GetCurrentDataPort() const { return currentdataport; }
bool GetCurrentDataType() const { return currentdatatype; }
packet_ready_cb GetPacketReadyCB() const { return packetreadycb; }
void* GetPacketReadyCBData() const { return packetreadycbdata; }
private:
uint16_t portbase;
uint32_t bindIP;
std::list<uint32_t> localIPs;
uint8_t multicastTTL;
uint8_t* currentdata;
uint16_t currentdatalen;
uint32_t currentdataaddr;
uint16_t currentdataport;
bool currentdatatype;
packet_ready_cb packetreadycb;
void *packetreadycbdata;
};
class RTPFakeTransmissionInfo : public RTPTransmissionInfo
{
public:
RTPFakeTransmissionInfo(std::list<uint32_t> iplist,
RTPFakeTransmissionParams *transparams) :
RTPTransmissionInfo(RTPTransmitter::UserDefinedProto)
{ localIPlist = iplist; params = transparams; }
~RTPFakeTransmissionInfo() { }
std::list<uint32_t> GetLocalIPList() const { return localIPlist; }
RTPFakeTransmissionParams* GetTransParams() { return params; }
private:
std::list<uint32_t> localIPlist;
RTPFakeTransmissionParams *params;
};
class RTPFakeTrans_GetHashIndex_IPv4Dest
{
public:
static int GetIndex(const RTPIPv4Destination &d) { return d.GetIP()%RTPFAKETRANS_HASHSIZE; }
};
class RTPFakeTrans_GetHashIndex_uint32_t
{
public:
static int GetIndex(const uint32_t &k) { return k%RTPFAKETRANS_HASHSIZE; }
};
#define RTPFAKETRANS_HEADERSIZE (20+8)
class RTPFakeTransmitter : public RTPTransmitter
{
public:
RTPFakeTransmitter(RTPMemoryManager *mgr);
~RTPFakeTransmitter();
int Init(bool treadsafe);
int Create(size_t maxpacksize,const RTPTransmissionParams *transparams);
void Destroy();
RTPTransmissionInfo *GetTransmissionInfo();
void DeleteTransmissionInfo(RTPTransmissionInfo *inf);
int GetLocalHostName(uint8_t *buffer,size_t *bufferlength);
bool ComesFromThisTransmitter(const RTPAddress *addr);
size_t GetHeaderOverhead() { return RTPFAKETRANS_HEADERSIZE; }
int Poll();
int WaitForIncomingData(const RTPTime &delay,bool *dataavailable = 0);
int AbortWait();
int SendRTPData(const void *data,size_t len);
int SendRTCPData(const void *data,size_t len);
int AddDestination(const RTPAddress &addr);
int DeleteDestination(const RTPAddress &addr);
void ClearDestinations();
bool SupportsMulticasting();
int JoinMulticastGroup(const RTPAddress &addr);
int LeaveMulticastGroup(const RTPAddress &addr);
void LeaveAllMulticastGroups();
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(size_t s);
bool NewDataAvailable();
RTPRawPacket *GetNextPacket();
private:
int CreateLocalIPList();
bool GetLocalIPList_Interfaces();
void GetLocalIPList_DNS();
void AddLoopbackAddress();
void FlushPackets();
int FakePoll();
int ProcessAddAcceptIgnoreEntry(uint32_t ip,uint16_t port);
int ProcessDeleteAcceptIgnoreEntry(uint32_t ip,uint16_t port);
#ifdef RTP_SUPPORT_IPV4MULTICAST
bool SetMulticastTTL(uint8_t ttl);
#endif // RTP_SUPPORT_IPV4MULTICAST
bool ShouldAcceptData(uint32_t srcip,uint16_t srcport);
void ClearAcceptIgnoreInfo();
RTPFakeTransmissionParams *params;
bool init;
bool created;
bool waitingfordata;
std::list<uint32_t> localIPs;
uint16_t portbase;
uint8_t multicastTTL;
RTPTransmitter::ReceiveMode receivemode;
uint8_t *localhostname;
size_t localhostnamelength;
RTPHashTable<const RTPIPv4Destination,RTPFakeTrans_GetHashIndex_IPv4Dest,RTPFAKETRANS_HASHSIZE> destinations;
#ifdef RTP_SUPPORT_IPV4MULTICAST
// RTPHashTable<const uint32_t,RTPFakeTrans_GetHashIndex_uint32_t,RTPFAKETRANS_HASHSIZE> multicastgroups;
#endif // RTP_SUPPORT_IPV4MULTICAST
std::list<RTPRawPacket*> rawpacketlist;
bool supportsmulticasting;
size_t maxpacksize;
class PortInfo
{
public:
PortInfo() { all = false; }
bool all;
std::list<uint16_t> portlist;
};
RTPKeyHashTable<const uint32_t,PortInfo*,RTPFakeTrans_GetHashIndex_uint32_t,RTPFAKETRANS_HASHSIZE> acceptignoreinfo;
int CreateAbortDescriptors();
void DestroyAbortDescriptors();
void AbortWaitInternal();
#ifdef RTP_SUPPORT_THREAD
jthread::JMutex mainmutex,waitmutex;
int threadsafe;
#endif // RTP_SUPPORT_THREAD
};
} // end namespace
#endif // RTPFAKETRANSMITTER_H

65
qrtplib/rtcpapppacket.cpp Normal file
View File

@ -0,0 +1,65 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpapppacket.h"
namespace qrtplib
{
RTCPAPPPacket::RTCPAPPPacket(uint8_t *data,size_t datalength)
: RTCPPacket(APP,data,datalength)
{
knownformat = false;
RTCPCommonHeader *hdr;
size_t len = datalength;
hdr = (RTCPCommonHeader *)data;
if (hdr->padding)
{
uint8_t padcount = data[datalength-1];
if ((padcount & 0x03) != 0) // not a multiple of four! (see rfc 3550 p 37)
return;
if (((size_t)padcount) >= len)
return;
len -= (size_t)padcount;
}
if (len < (sizeof(RTCPCommonHeader)+sizeof(uint32_t)*2))
return;
len -= (sizeof(RTCPCommonHeader)+sizeof(uint32_t)*2);
appdatalen = len;
knownformat = true;
}
} // end namespace

129
qrtplib/rtcpapppacket.h Normal file
View File

@ -0,0 +1,129 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpapppacket.h
*/
#ifndef RTCPAPPPACKET_H
#define RTCPAPPPACKET_H
#include "rtpconfig.h"
#include "rtcppacket.h"
#include "rtpstructs.h"
#ifdef RTP_SUPPORT_NETINET_IN
#include <netinet/in.h>
#endif // RTP_SUPPORT_NETINET_IN
namespace qrtplib
{
class RTCPCompoundPacket;
/** Describes an RTCP APP packet. */
class JRTPLIB_IMPORTEXPORT RTCPAPPPacket : public RTCPPacket
{
public:
/** Creates an instance based on the data in \c data with length \c datalen.
* Creates an instance based on the data in \c data with length \c datalen. Since the \c data pointer
* is referenced inside the class (no copy of the data is made) one must make sure that the memory it
* points to is valid as long as the class instance exists.
*/
RTCPAPPPacket(uint8_t *data,size_t datalen);
~RTCPAPPPacket() { }
/** Returns the subtype contained in the APP packet. */
uint8_t GetSubType() const;
/** Returns the SSRC of the source which sent this packet. */
uint32_t GetSSRC() const;
/** Returns the name contained in the APP packet.
* Returns the name contained in the APP packet. This alway consists of four bytes and is not NULL-terminated.
*/
uint8_t *GetName();
/** Returns a pointer to the actual data. */
uint8_t *GetAPPData();
/** Returns the length of the actual data. */
size_t GetAPPDataLength() const;
private:
size_t appdatalen;
};
inline uint8_t RTCPAPPPacket::GetSubType() const
{
if (!knownformat)
return 0;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)data;
return hdr->count;
}
inline uint32_t RTCPAPPPacket::GetSSRC() const
{
if (!knownformat)
return 0;
uint32_t *ssrc = (uint32_t *)(data+sizeof(RTCPCommonHeader));
return ntohl(*ssrc);
}
inline uint8_t *RTCPAPPPacket::GetName()
{
if (!knownformat)
return 0;
return (data+sizeof(RTCPCommonHeader)+sizeof(uint32_t));
}
inline uint8_t *RTCPAPPPacket::GetAPPData()
{
if (!knownformat)
return 0;
if (appdatalen == 0)
return 0;
return (data+sizeof(RTCPCommonHeader)+sizeof(uint32_t)*2);
}
inline size_t RTCPAPPPacket::GetAPPDataLength() const
{
if (!knownformat)
return 0;
return appdatalen;
}
} // end namespace
#endif // RTCPAPPPACKET_H

73
qrtplib/rtcpbyepacket.cpp Normal file
View File

@ -0,0 +1,73 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpbyepacket.h"
namespace qrtplib
{
RTCPBYEPacket::RTCPBYEPacket(uint8_t *data,size_t datalength)
: RTCPPacket(BYE,data,datalength)
{
knownformat = false;
reasonoffset = 0;
RTCPCommonHeader *hdr;
size_t len = datalength;
hdr = (RTCPCommonHeader *)data;
if (hdr->padding)
{
uint8_t padcount = data[datalength-1];
if ((padcount & 0x03) != 0) // not a multiple of four! (see rfc 3550 p 37)
return;
if (((size_t)padcount) >= len)
return;
len -= (size_t)padcount;
}
size_t ssrclen = ((size_t)(hdr->count))*sizeof(uint32_t) + sizeof(RTCPCommonHeader);
if (ssrclen > len)
return;
if (ssrclen < len) // there's probably a reason for leaving
{
uint8_t *reasonlength = (data+ssrclen);
size_t reaslen = (size_t)(*reasonlength);
if (reaslen > (len-ssrclen-1))
return;
reasonoffset = ssrclen;
}
knownformat = true;
}
} // end namespace

137
qrtplib/rtcpbyepacket.h Normal file
View File

@ -0,0 +1,137 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpbyepacket.h
*/
#ifndef RTCPBYEPACKET_H
#define RTCPBYEPACKET_H
#include "rtpconfig.h"
#include "rtcppacket.h"
#include "rtpstructs.h"
#ifdef RTP_SUPPORT_NETINET_IN
#include <netinet/in.h>
#endif // RTP_SUPPORT_NETINET_IN
namespace qrtplib
{
class RTCPCompoundPacket;
/** Describes an RTCP BYE packet. */
class JRTPLIB_IMPORTEXPORT RTCPBYEPacket : public RTCPPacket
{
public:
/** Creates an instance based on the data in \c data with length \c datalen.
* Creates an instance based on the data in \c data with length \c datalen. Since the \c data pointer
* is referenced inside the class (no copy of the data is made) one must make sure that the memory it
* points to is valid as long as the class instance exists.
*/
RTCPBYEPacket(uint8_t *data,size_t datalen);
~RTCPBYEPacket() { }
/** Returns the number of SSRC identifiers present in this BYE packet. */
int GetSSRCCount() const;
/** Returns the SSRC described by \c index which may have a value from 0 to GetSSRCCount()-1
* (note that no check is performed to see if \c index is valid).
*/
uint32_t GetSSRC(int index) const; // note: no check is performed to see if index is valid!
/** Returns true if the BYE packet contains a reason for leaving. */
bool HasReasonForLeaving() const;
/** Returns the length of the string which describes why the source(s) left. */
size_t GetReasonLength() const;
/** Returns the actual reason for leaving data. */
uint8_t *GetReasonData();
private:
size_t reasonoffset;
};
inline int RTCPBYEPacket::GetSSRCCount() const
{
if (!knownformat)
return 0;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)data;
return (int)(hdr->count);
}
inline uint32_t RTCPBYEPacket::GetSSRC(int index) const
{
if (!knownformat)
return 0;
uint32_t *ssrc = (uint32_t *)(data+sizeof(RTCPCommonHeader)+sizeof(uint32_t)*index);
return ntohl(*ssrc);
}
inline bool RTCPBYEPacket::HasReasonForLeaving() const
{
if (!knownformat)
return false;
if (reasonoffset == 0)
return false;
return true;
}
inline size_t RTCPBYEPacket::GetReasonLength() const
{
if (!knownformat)
return 0;
if (reasonoffset == 0)
return 0;
uint8_t *reasonlen = (data+reasonoffset);
return (size_t)(*reasonlen);
}
inline uint8_t *RTCPBYEPacket::GetReasonData()
{
if (!knownformat)
return 0;
if (reasonoffset == 0)
return 0;
uint8_t *reasonlen = (data+reasonoffset);
if ((*reasonlen) == 0)
return 0;
return (data+reasonoffset+1);
}
} // end namespace
#endif // RTCPBYEPACKET_H

View File

@ -0,0 +1,216 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpcompoundpacket.h"
#include "rtprawpacket.h"
#include "rtperrors.h"
#include "rtpstructs.h"
#include "rtpdefines.h"
#include "rtcpsrpacket.h"
#include "rtcprrpacket.h"
#include "rtcpsdespacket.h"
#include "rtcpbyepacket.h"
#include "rtcpapppacket.h"
#include "rtcpunknownpacket.h"
#ifdef RTP_SUPPORT_NETINET_IN
#include <netinet/in.h>
#endif // RTP_SUPPORT_NETINET_IN
namespace qrtplib
{
RTCPCompoundPacket::RTCPCompoundPacket(RTPRawPacket &rawpack, RTPMemoryManager *mgr) : RTPMemoryObject(mgr)
{
compoundpacket = 0;
compoundpacketlength = 0;
error = 0;
if (rawpack.IsRTP())
{
error = ERR_RTP_RTCPCOMPOUND_INVALIDPACKET;
return;
}
uint8_t *data = rawpack.GetData();
size_t datalen = rawpack.GetDataLength();
error = ParseData(data,datalen);
if (error < 0)
return;
compoundpacket = rawpack.GetData();
compoundpacketlength = rawpack.GetDataLength();
deletepacket = true;
rawpack.ZeroData();
rtcppackit = rtcppacklist.begin();
}
RTCPCompoundPacket::RTCPCompoundPacket(uint8_t *packet, size_t packetlen, bool deletedata, RTPMemoryManager *mgr) : RTPMemoryObject(mgr)
{
compoundpacket = 0;
compoundpacketlength = 0;
error = ParseData(packet,packetlen);
if (error < 0)
return;
compoundpacket = packet;
compoundpacketlength = packetlen;
deletepacket = deletedata;
rtcppackit = rtcppacklist.begin();
}
RTCPCompoundPacket::RTCPCompoundPacket(RTPMemoryManager *mgr) : RTPMemoryObject(mgr)
{
compoundpacket = 0;
compoundpacketlength = 0;
error = 0;
deletepacket = true;
}
int RTCPCompoundPacket::ParseData(uint8_t *data, size_t datalen)
{
bool first;
if (datalen < sizeof(RTCPCommonHeader))
return ERR_RTP_RTCPCOMPOUND_INVALIDPACKET;
first = true;
do
{
RTCPCommonHeader *rtcphdr;
size_t length;
rtcphdr = (RTCPCommonHeader *)data;
if (rtcphdr->version != RTP_VERSION) // check version
{
ClearPacketList();
return ERR_RTP_RTCPCOMPOUND_INVALIDPACKET;
}
if (first)
{
// Check if first packet is SR or RR
first = false;
if ( ! (rtcphdr->packettype == RTP_RTCPTYPE_SR || rtcphdr->packettype == RTP_RTCPTYPE_RR))
{
ClearPacketList();
return ERR_RTP_RTCPCOMPOUND_INVALIDPACKET;
}
}
length = (size_t)ntohs(rtcphdr->length);
length++;
length *= sizeof(uint32_t);
if (length > datalen) // invalid length field
{
ClearPacketList();
return ERR_RTP_RTCPCOMPOUND_INVALIDPACKET;
}
if (rtcphdr->padding)
{
// check if it's the last packet
if (length != datalen)
{
ClearPacketList();
return ERR_RTP_RTCPCOMPOUND_INVALIDPACKET;
}
}
RTCPPacket *p;
switch (rtcphdr->packettype)
{
case RTP_RTCPTYPE_SR:
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPSRPACKET) RTCPSRPacket(data,length);
break;
case RTP_RTCPTYPE_RR:
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPRRPACKET) RTCPRRPacket(data,length);
break;
case RTP_RTCPTYPE_SDES:
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPSDESPACKET) RTCPSDESPacket(data,length);
break;
case RTP_RTCPTYPE_BYE:
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPBYEPACKET) RTCPBYEPacket(data,length);
break;
case RTP_RTCPTYPE_APP:
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPAPPPACKET) RTCPAPPPacket(data,length);
break;
default:
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPUNKNOWNPACKET) RTCPUnknownPacket(data,length);
}
if (p == 0)
{
ClearPacketList();
return ERR_RTP_OUTOFMEM;
}
rtcppacklist.push_back(p);
datalen -= length;
data += length;
} while (datalen >= (size_t)sizeof(RTCPCommonHeader));
if (datalen != 0) // some remaining bytes
{
ClearPacketList();
return ERR_RTP_RTCPCOMPOUND_INVALIDPACKET;
}
return 0;
}
RTCPCompoundPacket::~RTCPCompoundPacket()
{
ClearPacketList();
if (compoundpacket && deletepacket)
RTPDeleteByteArray(compoundpacket,GetMemoryManager());
}
void RTCPCompoundPacket::ClearPacketList()
{
std::list<RTCPPacket *>::const_iterator it;
for (it = rtcppacklist.begin() ; it != rtcppacklist.end() ; it++)
RTPDelete(*it,GetMemoryManager());
rtcppacklist.clear();
rtcppackit = rtcppacklist.begin();
}
} // end namespace

View File

@ -0,0 +1,108 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpcompoundpacket.h
*/
#ifndef RTCPCOMPOUNDPACKET_H
#define RTCPCOMPOUNDPACKET_H
#include "rtpconfig.h"
#include "rtptypes.h"
#include "rtpmemoryobject.h"
#include <list>
namespace qrtplib
{
class RTPRawPacket;
class RTCPPacket;
/** Represents an RTCP compound packet. */
class JRTPLIB_IMPORTEXPORT RTCPCompoundPacket : public RTPMemoryObject
{
public:
/** Creates an RTCPCompoundPacket instance from the data in \c rawpack, installing a memory manager if specified. */
RTCPCompoundPacket(RTPRawPacket &rawpack, RTPMemoryManager *memmgr = 0);
/** 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, size_t len, bool deletedata = true, RTPMemoryManager *memmgr = 0);
protected:
RTCPCompoundPacket(RTPMemoryManager *memmgr); // this is for the compoundpacket builder
public:
virtual ~RTCPCompoundPacket();
/** Checks if the RTCP compound packet was created successfully.
* If the raw packet data in the constructor could not be parsed, this function returns the error code of
* what went wrong. If the packet had an invalid format, the return value is \c ERR_RTP_RTCPCOMPOUND_INVALIDPACKET.
*/
int GetCreationError() { return error; }
/** Returns a pointer to the data of the entire RTCP compound packet. */
uint8_t *GetCompoundPacketData() { return compoundpacket; }
/** Returns the size of the entire RTCP compound packet. */
size_t GetCompoundPacketLength() { return compoundpacketlength; }
/** Starts the iteration over the individual RTCP packets in the RTCP compound packet. */
void GotoFirstPacket() { rtcppackit = rtcppacklist.begin(); }
/** Returns a pointer to the next individual RTCP packet.
* Returns a pointer to the next individual RTCP packet. Note that no \c delete call may be done
* on the RTCPPacket instance which is returned.
*/
RTCPPacket *GetNextPacket() { if (rtcppackit == rtcppacklist.end()) return 0; RTCPPacket *p = *rtcppackit; rtcppackit++; return p; }
protected:
void ClearPacketList();
int ParseData(uint8_t *packet, size_t len);
int error;
uint8_t *compoundpacket;
size_t compoundpacketlength;
bool deletepacket;
std::list<RTCPPacket *> rtcppacklist;
std::list<RTCPPacket *>::const_iterator rtcppackit;
};
} // end namespace
#endif // RTCPCOMPOUNDPACKET_H

View File

@ -0,0 +1,811 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpcompoundpacketbuilder.h"
#include "rtcpsrpacket.h"
#include "rtcprrpacket.h"
#include "rtcpsdespacket.h"
#include "rtcpbyepacket.h"
#include "rtcpapppacket.h"
#ifdef RTP_SUPPORT_RTCPUNKNOWN
#include "rtcpunknownpacket.h"
#endif // RTP_SUPPORT_RTCPUNKNOWN
#ifdef RTP_SUPPORT_NETINET_IN
#include <netinet/in.h>
#endif // RTP_SUPPORT_NETINET_IN
#include <string.h>
namespace qrtplib
{
RTCPCompoundPacketBuilder::RTCPCompoundPacketBuilder(RTPMemoryManager *mgr) : RTCPCompoundPacket(mgr), report(mgr), sdes(mgr)
{
byesize = 0;
appsize = 0;
#ifdef RTP_SUPPORT_RTCPUNKNOWN
unknownsize = 0;
#endif // RTP_SUPPORT_RTCPUNKNOWN
maximumpacketsize = 0;
buffer = 0;
external = false;
arebuilding = false;
}
RTCPCompoundPacketBuilder::~RTCPCompoundPacketBuilder()
{
if (external)
compoundpacket = 0; // make sure RTCPCompoundPacket doesn't delete the external buffer
ClearBuildBuffers();
}
void RTCPCompoundPacketBuilder::ClearBuildBuffers()
{
report.Clear();
sdes.Clear();
std::list<Buffer>::const_iterator it;
for (it = byepackets.begin() ; it != byepackets.end() ; it++)
{
if ((*it).packetdata)
RTPDeleteByteArray((*it).packetdata,GetMemoryManager());
}
for (it = apppackets.begin() ; it != apppackets.end() ; it++)
{
if ((*it).packetdata)
RTPDeleteByteArray((*it).packetdata,GetMemoryManager());
}
#ifdef RTP_SUPPORT_RTCPUNKNOWN
for (it = unknownpackets.begin() ; it != unknownpackets.end() ; it++)
{
if ((*it).packetdata)
RTPDeleteByteArray((*it).packetdata,GetMemoryManager());
}
#endif // RTP_SUPPORT_RTCPUNKNOWN
byepackets.clear();
apppackets.clear();
#ifdef RTP_SUPPORT_RTCPUNKNOWN
unknownpackets.clear();
#endif // RTP_SUPPORT_RTCPUNKNOWN
byesize = 0;
appsize = 0;
#ifdef RTP_SUPPORT_RTCPUNKNOWN
unknownsize = 0;
#endif // RTP_SUPPORT_RTCPUNKNOWN
}
int RTCPCompoundPacketBuilder::InitBuild(size_t maxpacketsize)
{
if (arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILDING;
if (compoundpacket)
return ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILT;
if (maxpacketsize < RTP_MINPACKETSIZE)
return ERR_RTP_RTCPCOMPPACKBUILDER_MAXPACKETSIZETOOSMALL;
maximumpacketsize = maxpacketsize;
buffer = 0;
external = false;
byesize = 0;
appsize = 0;
#ifdef RTP_SUPPORT_RTCPUNKNOWN
unknownsize = 0;
#endif // RTP_SUPPORT_RTCPUNKNOWN
arebuilding = true;
return 0;
}
int RTCPCompoundPacketBuilder::InitBuild(void *externalbuffer,size_t buffersize)
{
if (arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILDING;
if (compoundpacket)
return ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILT;
if (buffersize < RTP_MINPACKETSIZE)
return ERR_RTP_RTCPCOMPPACKBUILDER_BUFFERSIZETOOSMALL;
maximumpacketsize = buffersize;
buffer = (uint8_t *)externalbuffer;
external = true;
byesize = 0;
appsize = 0;
#ifdef RTP_SUPPORT_RTCPUNKNOWN
unknownsize = 0;
#endif // RTP_SUPPORT_RTCPUNKNOWN
arebuilding = true;
return 0;
}
int RTCPCompoundPacketBuilder::StartSenderReport(uint32_t senderssrc,const RTPNTPTime &ntptimestamp,uint32_t rtptimestamp,
uint32_t packetcount,uint32_t octetcount)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (report.headerlength != 0)
return ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYGOTREPORT;
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalsize = byesize+appsize+sdes.NeededBytes();
#else
size_t totalsize = byesize+appsize+unknownsize+sdes.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
size_t sizeleft = maximumpacketsize-totalsize;
size_t neededsize = sizeof(RTCPCommonHeader)+sizeof(uint32_t)+sizeof(RTCPSenderReport);
if (neededsize > sizeleft)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
// fill in some things
report.headerlength = sizeof(uint32_t)+sizeof(RTCPSenderReport);
report.isSR = true;
uint32_t *ssrc = (uint32_t *)report.headerdata;
*ssrc = htonl(senderssrc);
RTCPSenderReport *sr = (RTCPSenderReport *)(report.headerdata + sizeof(uint32_t));
sr->ntptime_msw = htonl(ntptimestamp.GetMSW());
sr->ntptime_lsw = htonl(ntptimestamp.GetLSW());
sr->rtptimestamp = htonl(rtptimestamp);
sr->packetcount = htonl(packetcount);
sr->octetcount = htonl(octetcount);
return 0;
}
int RTCPCompoundPacketBuilder::StartReceiverReport(uint32_t senderssrc)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (report.headerlength != 0)
return ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYGOTREPORT;
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalsize = byesize+appsize+sdes.NeededBytes();
#else
size_t totalsize = byesize+appsize+unknownsize+sdes.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
size_t sizeleft = maximumpacketsize-totalsize;
size_t neededsize = sizeof(RTCPCommonHeader)+sizeof(uint32_t);
if (neededsize > sizeleft)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
// fill in some things
report.headerlength = sizeof(uint32_t);
report.isSR = false;
uint32_t *ssrc = (uint32_t *)report.headerdata;
*ssrc = htonl(senderssrc);
return 0;
}
int RTCPCompoundPacketBuilder::AddReportBlock(uint32_t ssrc,uint8_t fractionlost,int32_t packetslost,uint32_t exthighestseq,
uint32_t jitter,uint32_t lsr,uint32_t dlsr)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (report.headerlength == 0)
return ERR_RTP_RTCPCOMPPACKBUILDER_REPORTNOTSTARTED;
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalothersize = byesize+appsize+sdes.NeededBytes();
#else
size_t totalothersize = byesize+appsize+unknownsize+sdes.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
size_t reportsizewithextrablock = report.NeededBytesWithExtraReportBlock();
if ((totalothersize+reportsizewithextrablock) > maximumpacketsize)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
uint8_t *buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPRECEIVERREPORT) uint8_t[sizeof(RTCPReceiverReport)];
if (buf == 0)
return ERR_RTP_OUTOFMEM;
RTCPReceiverReport *rr = (RTCPReceiverReport *)buf;
uint32_t *packlost = (uint32_t *)&packetslost;
uint32_t packlost2 = (*packlost);
rr->ssrc = htonl(ssrc);
rr->fractionlost = fractionlost;
rr->packetslost[2] = (uint8_t)(packlost2&0xFF);
rr->packetslost[1] = (uint8_t)((packlost2>>8)&0xFF);
rr->packetslost[0] = (uint8_t)((packlost2>>16)&0xFF);
rr->exthighseqnr = htonl(exthighestseq);
rr->jitter = htonl(jitter);
rr->lsr = htonl(lsr);
rr->dlsr = htonl(dlsr);
report.reportblocks.push_back(Buffer(buf,sizeof(RTCPReceiverReport)));
return 0;
}
int RTCPCompoundPacketBuilder::AddSDESSource(uint32_t ssrc)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalotherbytes = byesize+appsize+report.NeededBytes();
#else
size_t totalotherbytes = byesize+appsize+unknownsize+report.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
size_t sdessizewithextrasource = sdes.NeededBytesWithExtraSource();
if ((totalotherbytes + sdessizewithextrasource) > maximumpacketsize)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
int status;
if ((status = sdes.AddSSRC(ssrc)) < 0)
return status;
return 0;
}
int RTCPCompoundPacketBuilder::AddSDESNormalItem(RTCPSDESPacket::ItemType t,const void *itemdata,uint8_t itemlength)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (sdes.sdessources.empty())
return ERR_RTP_RTCPCOMPPACKBUILDER_NOCURRENTSOURCE;
uint8_t itemid;
switch(t)
{
case RTCPSDESPacket::CNAME:
itemid = RTCP_SDES_ID_CNAME;
break;
case RTCPSDESPacket::NAME:
itemid = RTCP_SDES_ID_NAME;
break;
case RTCPSDESPacket::EMAIL:
itemid = RTCP_SDES_ID_EMAIL;
break;
case RTCPSDESPacket::PHONE:
itemid = RTCP_SDES_ID_PHONE;
break;
case RTCPSDESPacket::LOC:
itemid = RTCP_SDES_ID_LOCATION;
break;
case RTCPSDESPacket::TOOL:
itemid = RTCP_SDES_ID_TOOL;
break;
case RTCPSDESPacket::NOTE:
itemid = RTCP_SDES_ID_NOTE;
break;
default:
return ERR_RTP_RTCPCOMPPACKBUILDER_INVALIDITEMTYPE;
}
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalotherbytes = byesize+appsize+report.NeededBytes();
#else
size_t totalotherbytes = byesize+appsize+unknownsize+report.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
size_t sdessizewithextraitem = sdes.NeededBytesWithExtraItem(itemlength);
if ((sdessizewithextraitem+totalotherbytes) > maximumpacketsize)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
uint8_t *buf;
size_t len;
buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTCPSDESBLOCK) uint8_t[sizeof(RTCPSDESHeader)+(size_t)itemlength];
if (buf == 0)
return ERR_RTP_OUTOFMEM;
len = sizeof(RTCPSDESHeader)+(size_t)itemlength;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(buf);
sdeshdr->sdesid = itemid;
sdeshdr->length = itemlength;
if (itemlength != 0)
memcpy((buf + sizeof(RTCPSDESHeader)),itemdata,(size_t)itemlength);
sdes.AddItem(buf,len);
return 0;
}
#ifdef RTP_SUPPORT_SDESPRIV
int RTCPCompoundPacketBuilder::AddSDESPrivateItem(const void *prefixdata,uint8_t prefixlength,const void *valuedata,
uint8_t valuelength)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (sdes.sdessources.empty())
return ERR_RTP_RTCPCOMPPACKBUILDER_NOCURRENTSOURCE;
size_t itemlength = ((size_t)prefixlength)+1+((size_t)valuelength);
if (itemlength > 255)
return ERR_RTP_RTCPCOMPPACKBUILDER_TOTALITEMLENGTHTOOBIG;
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalotherbytes = byesize+appsize+report.NeededBytes();
#else
size_t totalotherbytes = byesize+appsize+unknownsize+report.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
size_t sdessizewithextraitem = sdes.NeededBytesWithExtraItem(itemlength);
if ((sdessizewithextraitem+totalotherbytes) > maximumpacketsize)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
uint8_t *buf;
size_t len;
buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTCPSDESBLOCK) uint8_t[sizeof(RTCPSDESHeader)+itemlength];
if (buf == 0)
return ERR_RTP_OUTOFMEM;
len = sizeof(RTCPSDESHeader)+(size_t)itemlength;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(buf);
sdeshdr->sdesid = RTCP_SDES_ID_PRIVATE;
sdeshdr->length = itemlength;
buf[sizeof(RTCPSDESHeader)] = prefixlength;
if (prefixlength != 0)
memcpy((buf+sizeof(RTCPSDESHeader)+1),prefixdata,(size_t)prefixlength);
if (valuelength != 0)
memcpy((buf+sizeof(RTCPSDESHeader)+1+(size_t)prefixlength),valuedata,(size_t)valuelength);
sdes.AddItem(buf,len);
return 0;
}
#endif // RTP_SUPPORT_SDESPRIV
int RTCPCompoundPacketBuilder::AddBYEPacket(uint32_t *ssrcs,uint8_t numssrcs,const void *reasondata,uint8_t reasonlength)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (numssrcs > 31)
return ERR_RTP_RTCPCOMPPACKBUILDER_TOOMANYSSRCS;
size_t packsize = sizeof(RTCPCommonHeader)+sizeof(uint32_t)*((size_t)numssrcs);
size_t zerobytes = 0;
if (reasonlength > 0)
{
packsize += 1; // 1 byte for the length;
packsize += (size_t)reasonlength;
size_t r = (packsize&0x03);
if (r != 0)
{
zerobytes = 4-r;
packsize += zerobytes;
}
}
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalotherbytes = appsize+byesize+sdes.NeededBytes()+report.NeededBytes();
#else
size_t totalotherbytes = appsize+unknownsize+byesize+sdes.NeededBytes()+report.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
if ((totalotherbytes + packsize) > maximumpacketsize)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
uint8_t *buf;
size_t numwords;
buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTCPBYEPACKET) uint8_t[packsize];
if (buf == 0)
return ERR_RTP_OUTOFMEM;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)buf;
hdr->version = 2;
hdr->padding = 0;
hdr->count = numssrcs;
numwords = packsize/sizeof(uint32_t);
hdr->length = htons((uint16_t)(numwords-1));
hdr->packettype = RTP_RTCPTYPE_BYE;
uint32_t *sources = (uint32_t *)(buf+sizeof(RTCPCommonHeader));
uint8_t srcindex;
for (srcindex = 0 ; srcindex < numssrcs ; srcindex++)
sources[srcindex] = htonl(ssrcs[srcindex]);
if (reasonlength != 0)
{
size_t offset = sizeof(RTCPCommonHeader)+((size_t)numssrcs)*sizeof(uint32_t);
buf[offset] = reasonlength;
memcpy((buf+offset+1),reasondata,(size_t)reasonlength);
for (size_t i = 0 ; i < zerobytes ; i++)
buf[packsize-1-i] = 0;
}
byepackets.push_back(Buffer(buf,packsize));
byesize += packsize;
return 0;
}
int RTCPCompoundPacketBuilder::AddAPPPacket(uint8_t subtype,uint32_t ssrc,const uint8_t name[4],const void *appdata,size_t appdatalen)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (subtype > 31)
return ERR_RTP_RTCPCOMPPACKBUILDER_ILLEGALSUBTYPE;
if ((appdatalen%4) != 0)
return ERR_RTP_RTCPCOMPPACKBUILDER_ILLEGALAPPDATALENGTH;
size_t appdatawords = appdatalen/4;
if ((appdatawords+2) > 65535)
return ERR_RTP_RTCPCOMPPACKBUILDER_APPDATALENTOOBIG;
size_t packsize = sizeof(RTCPCommonHeader)+sizeof(uint32_t)*2+appdatalen;
#ifndef RTP_SUPPORT_RTCPUNKNOWN
size_t totalotherbytes = appsize+byesize+sdes.NeededBytes()+report.NeededBytes();
#else
size_t totalotherbytes = appsize+unknownsize+byesize+sdes.NeededBytes()+report.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
if ((totalotherbytes + packsize) > maximumpacketsize)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
uint8_t *buf;
buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTCPAPPPACKET) uint8_t[packsize];
if (buf == 0)
return ERR_RTP_OUTOFMEM;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)buf;
hdr->version = 2;
hdr->padding = 0;
hdr->count = subtype;
hdr->length = htons((uint16_t)(appdatawords+2));
hdr->packettype = RTP_RTCPTYPE_APP;
uint32_t *source = (uint32_t *)(buf+sizeof(RTCPCommonHeader));
*source = htonl(ssrc);
buf[sizeof(RTCPCommonHeader)+sizeof(uint32_t)+0] = name[0];
buf[sizeof(RTCPCommonHeader)+sizeof(uint32_t)+1] = name[1];
buf[sizeof(RTCPCommonHeader)+sizeof(uint32_t)+2] = name[2];
buf[sizeof(RTCPCommonHeader)+sizeof(uint32_t)+3] = name[3];
if (appdatalen > 0)
memcpy((buf+sizeof(RTCPCommonHeader)+sizeof(uint32_t)*2),appdata,appdatalen);
apppackets.push_back(Buffer(buf,packsize));
appsize += packsize;
return 0;
}
#ifdef RTP_SUPPORT_RTCPUNKNOWN
int RTCPCompoundPacketBuilder::AddUnknownPacket(uint8_t payload_type, uint8_t subtype, uint32_t ssrc, const void *data, size_t len)
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
size_t datawords = len/4;
if ((datawords+2) > 65535)
return ERR_RTP_RTCPCOMPPACKBUILDER_APPDATALENTOOBIG;
size_t packsize = sizeof(RTCPCommonHeader)+sizeof(uint32_t)+len;
size_t totalotherbytes = appsize+unknownsize+byesize+sdes.NeededBytes()+report.NeededBytes();
if ((totalotherbytes + packsize) > maximumpacketsize)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT;
uint8_t *buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPUNKNOWNPACKET) uint8_t[packsize];
if (buf == 0)
return ERR_RTP_OUTOFMEM;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)buf;
hdr->version = 2;
hdr->padding = 0;
hdr->count = subtype;
hdr->length = htons((uint16_t)(datawords+1));
hdr->packettype = payload_type;
uint32_t *source = (uint32_t *)(buf+sizeof(RTCPCommonHeader));
*source = htonl(ssrc);
if (len > 0)
memcpy((buf+sizeof(RTCPCommonHeader)+sizeof(uint32_t)),data,len);
unknownpackets.push_back(Buffer(buf,packsize));
unknownsize += packsize;
return 0;
}
#endif // RTP_SUPPORT_RTCPUNKNOWN
int RTCPCompoundPacketBuilder::EndBuild()
{
if (!arebuilding)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING;
if (report.headerlength == 0)
return ERR_RTP_RTCPCOMPPACKBUILDER_NOREPORTPRESENT;
uint8_t *buf;
size_t len;
#ifndef RTP_SUPPORT_RTCPUNKNOWN
len = appsize+byesize+report.NeededBytes()+sdes.NeededBytes();
#else
len = appsize+unknownsize+byesize+report.NeededBytes()+sdes.NeededBytes();
#endif // RTP_SUPPORT_RTCPUNKNOWN
if (!external)
{
buf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTCPCOMPOUNDPACKET) uint8_t[len];
if (buf == 0)
return ERR_RTP_OUTOFMEM;
}
else
buf = buffer;
uint8_t *curbuf = buf;
RTCPPacket *p;
// first, we'll add all report info
{
bool firstpacket = true;
bool done = false;
std::list<Buffer>::const_iterator it = report.reportblocks.begin();
do
{
RTCPCommonHeader *hdr = (RTCPCommonHeader *)curbuf;
size_t offset;
hdr->version = 2;
hdr->padding = 0;
if (firstpacket && report.isSR)
{
hdr->packettype = RTP_RTCPTYPE_SR;
memcpy((curbuf+sizeof(RTCPCommonHeader)),report.headerdata,report.headerlength);
offset = sizeof(RTCPCommonHeader)+report.headerlength;
}
else
{
hdr->packettype = RTP_RTCPTYPE_RR;
memcpy((curbuf+sizeof(RTCPCommonHeader)),report.headerdata,sizeof(uint32_t));
offset = sizeof(RTCPCommonHeader)+sizeof(uint32_t);
}
firstpacket = false;
uint8_t count = 0;
while (it != report.reportblocks.end() && count < 31)
{
memcpy(curbuf+offset,(*it).packetdata,(*it).packetlength);
offset += (*it).packetlength;
count++;
it++;
}
size_t numwords = offset/sizeof(uint32_t);
hdr->length = htons((uint16_t)(numwords-1));
hdr->count = count;
// add entry in parent's list
if (hdr->packettype == RTP_RTCPTYPE_SR)
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPSRPACKET) RTCPSRPacket(curbuf,offset);
else
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPRRPACKET) RTCPRRPacket(curbuf,offset);
if (p == 0)
{
if (!external)
RTPDeleteByteArray(buf,GetMemoryManager());
ClearPacketList();
return ERR_RTP_OUTOFMEM;
}
rtcppacklist.push_back(p);
curbuf += offset;
if (it == report.reportblocks.end())
done = true;
} while (!done);
}
// then, we'll add the sdes info
if (!sdes.sdessources.empty())
{
bool done = false;
std::list<SDESSource *>::const_iterator sourceit = sdes.sdessources.begin();
do
{
RTCPCommonHeader *hdr = (RTCPCommonHeader *)curbuf;
size_t offset = sizeof(RTCPCommonHeader);
hdr->version = 2;
hdr->padding = 0;
hdr->packettype = RTP_RTCPTYPE_SDES;
uint8_t sourcecount = 0;
while (sourceit != sdes.sdessources.end() && sourcecount < 31)
{
uint32_t *ssrc = (uint32_t *)(curbuf+offset);
*ssrc = htonl((*sourceit)->ssrc);
offset += sizeof(uint32_t);
std::list<Buffer>::const_iterator itemit,itemend;
itemit = (*sourceit)->items.begin();
itemend = (*sourceit)->items.end();
while (itemit != itemend)
{
memcpy(curbuf+offset,(*itemit).packetdata,(*itemit).packetlength);
offset += (*itemit).packetlength;
itemit++;
}
curbuf[offset] = 0; // end of item list;
offset++;
size_t r = offset&0x03;
if (r != 0) // align to 32 bit boundary
{
size_t num = 4-r;
size_t i;
for (i = 0 ; i < num ; i++)
curbuf[offset+i] = 0;
offset += num;
}
sourceit++;
sourcecount++;
}
size_t numwords = offset/4;
hdr->count = sourcecount;
hdr->length = htons((uint16_t)(numwords-1));
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPSDESPACKET) RTCPSDESPacket(curbuf,offset);
if (p == 0)
{
if (!external)
RTPDeleteByteArray(buf,GetMemoryManager());
ClearPacketList();
return ERR_RTP_OUTOFMEM;
}
rtcppacklist.push_back(p);
curbuf += offset;
if (sourceit == sdes.sdessources.end())
done = true;
} while (!done);
}
// adding the app data
{
std::list<Buffer>::const_iterator it;
for (it = apppackets.begin() ; it != apppackets.end() ; it++)
{
memcpy(curbuf,(*it).packetdata,(*it).packetlength);
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPAPPPACKET) RTCPAPPPacket(curbuf,(*it).packetlength);
if (p == 0)
{
if (!external)
RTPDeleteByteArray(buf,GetMemoryManager());
ClearPacketList();
return ERR_RTP_OUTOFMEM;
}
rtcppacklist.push_back(p);
curbuf += (*it).packetlength;
}
}
#ifdef RTP_SUPPORT_RTCPUNKNOWN
// adding the unknown data
{
std::list<Buffer>::const_iterator it;
for (it = unknownpackets.begin() ; it != unknownpackets.end() ; it++)
{
memcpy(curbuf,(*it).packetdata,(*it).packetlength);
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPUNKNOWNPACKET) RTCPUnknownPacket(curbuf,(*it).packetlength);
if (p == 0)
{
if (!external)
RTPDeleteByteArray(buf,GetMemoryManager());
ClearPacketList();
return ERR_RTP_OUTOFMEM;
}
rtcppacklist.push_back(p);
curbuf += (*it).packetlength;
}
}
#endif // RTP_SUPPORT_RTCPUNKNOWN
// adding bye packets
{
std::list<Buffer>::const_iterator it;
for (it = byepackets.begin() ; it != byepackets.end() ; it++)
{
memcpy(curbuf,(*it).packetdata,(*it).packetlength);
p = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPBYEPACKET) RTCPBYEPacket(curbuf,(*it).packetlength);
if (p == 0)
{
if (!external)
RTPDeleteByteArray(buf,GetMemoryManager());
ClearPacketList();
return ERR_RTP_OUTOFMEM;
}
rtcppacklist.push_back(p);
curbuf += (*it).packetlength;
}
}
compoundpacket = buf;
compoundpacketlength = len;
arebuilding = false;
ClearBuildBuffers();
return 0;
}
} // end namespace

View File

@ -0,0 +1,400 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpcompoundpacketbuilder.h
*/
#ifndef RTCPCOMPOUNDPACKETBUILDER_H
#define RTCPCOMPOUNDPACKETBUILDER_H
#include "rtpconfig.h"
#include "rtcpcompoundpacket.h"
#include "rtptimeutilities.h"
#include "rtcpsdespacket.h"
#include "rtperrors.h"
#include <list>
namespace qrtplib
{
class RTPMemoryManager;
/** This class can be used to construct an RTCP compound packet.
* The RTCPCompoundPacketBuilder class can be used to construct an RTCP compound packet. It inherits the member
* functions of RTCPCompoundPacket which can be used to access the information in the compound packet once it has
* been built successfully. The member functions described below return \c ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT
* if the action would cause the maximum allowed size to be exceeded.
*/
class JRTPLIB_IMPORTEXPORT RTCPCompoundPacketBuilder : public RTCPCompoundPacket
{
public:
/** Constructs an RTCPCompoundPacketBuilder instance, optionally installing a memory manager. */
RTCPCompoundPacketBuilder(RTPMemoryManager *memmgr = 0);
~RTCPCompoundPacketBuilder();
/** Starts building an RTCP compound packet with maximum size \c maxpacketsize.
* Starts building an RTCP compound packet with maximum size \c maxpacketsize. New memory will be allocated
* to store the packet.
*/
int InitBuild(size_t maxpacketsize);
/** Starts building a RTCP compound packet.
* Starts building a RTCP compound packet. Data will be stored in \c externalbuffer which
* can contain \c buffersize bytes.
*/
int InitBuild(void *externalbuffer,size_t buffersize);
/** Adds a sender report to the compound packet.
* Tells the packet builder that the packet should start with a sender report which will contain
* the sender information specified by this function's arguments. Once the sender report is started,
* report blocks can be added using the AddReportBlock function.
*/
int StartSenderReport(uint32_t senderssrc,const RTPNTPTime &ntptimestamp,uint32_t rtptimestamp,
uint32_t packetcount,uint32_t octetcount);
/** Adds a receiver report to the compound packet.
* Tells the packet builder that the packet should start with a receiver report which will contain
* he sender SSRC \c senderssrc. Once the sender report is started, report blocks can be added using the
* AddReportBlock function.
*/
int StartReceiverReport(uint32_t senderssrc);
/** Adds the report block information specified by the function's arguments.
* Adds the report block information specified by the function's arguments. If more than 31 report blocks
* are added, the builder will automatically use a new RTCP receiver report packet.
*/
int AddReportBlock(uint32_t ssrc,uint8_t fractionlost,int32_t packetslost,uint32_t exthighestseq,
uint32_t jitter,uint32_t lsr,uint32_t dlsr);
/** Starts an SDES chunk for participant \c ssrc. */
int AddSDESSource(uint32_t ssrc);
/** Adds a normal (non-private) SDES item of type \c t to the current SDES chunk.
* Adds a normal (non-private) SDES item of type \c t to the current SDES chunk. The item's value
* will have length \c itemlength and will contain the data \c itemdata.
*/
int AddSDESNormalItem(RTCPSDESPacket::ItemType t,const void *itemdata,uint8_t itemlength);
#ifdef RTP_SUPPORT_SDESPRIV
/** Adds an SDES PRIV item described by the function's arguments to the current SDES chunk. */
int AddSDESPrivateItem(const void *prefixdata,uint8_t prefixlength,const void *valuedata,
uint8_t valuelength);
#endif // RTP_SUPPORT_SDESPRIV
/** Adds a BYE packet to the compound packet.
* Adds a BYE packet to the compound packet. It will contain \c numssrcs source identifiers specified in
* \c ssrcs and will indicate as reason for leaving the string of length \c reasonlength
* containing data \c reasondata.
*/
int AddBYEPacket(uint32_t *ssrcs,uint8_t numssrcs,const void *reasondata,uint8_t reasonlength);
/** Adds the APP packet specified by the arguments to the compound packet.
* Adds the APP packet specified by the arguments to the compound packet. Note that \c appdatalen has to be
* a multiple of four.
*/
int AddAPPPacket(uint8_t subtype,uint32_t ssrc,const uint8_t name[4],const void *appdata,size_t appdatalen);
/** Finishes building the compound packet.
* Finishes building the compound packet. If successful, the RTCPCompoundPacket member functions
* can be used to access the RTCP packet data.
*/
int EndBuild();
#ifdef RTP_SUPPORT_RTCPUNKNOWN
/** Adds the RTCP packet specified by the arguments to the compound packet.
* Adds the RTCP packet specified by the arguments to the compound packet.
*/
int AddUnknownPacket(uint8_t payload_type, uint8_t subtype, uint32_t ssrc, const void *data, size_t len);
#endif // RTP_SUPPORT_RTCPUNKNOWN
private:
class Buffer
{
public:
Buffer():packetdata(0),packetlength(0) { }
Buffer(uint8_t *data,size_t len):packetdata(data),packetlength(len) { }
uint8_t *packetdata;
size_t packetlength;
};
class Report : public RTPMemoryObject
{
public:
Report(RTPMemoryManager *mgr) : RTPMemoryObject(mgr)
{
headerdata = (uint8_t *)headerdata32;
isSR = false;
headerlength = 0;
}
~Report() { Clear(); }
void Clear()
{
std::list<Buffer>::const_iterator it;
for (it = reportblocks.begin() ; it != reportblocks.end() ; it++)
{
if ((*it).packetdata)
RTPDeleteByteArray((*it).packetdata,GetMemoryManager());
}
reportblocks.clear();
isSR = false;
headerlength = 0;
}
size_t NeededBytes()
{
size_t x,n,d,r;
n = reportblocks.size();
if (n == 0)
{
if (headerlength == 0)
return 0;
x = sizeof(RTCPCommonHeader)+headerlength;
}
else
{
x = n*sizeof(RTCPReceiverReport);
d = n/31; // max 31 reportblocks per report
r = n%31;
if (r != 0)
d++;
x += d*(sizeof(RTCPCommonHeader)+sizeof(uint32_t)); /* header and SSRC */
if (isSR)
x += sizeof(RTCPSenderReport);
}
return x;
}
size_t NeededBytesWithExtraReportBlock()
{
size_t x,n,d,r;
n = reportblocks.size() + 1; // +1 for the extra block
x = n*sizeof(RTCPReceiverReport);
d = n/31; // max 31 reportblocks per report
r = n%31;
if (r != 0)
d++;
x += d*(sizeof(RTCPCommonHeader)+sizeof(uint32_t)); /* header and SSRC */
if (isSR)
x += sizeof(RTCPSenderReport);
return x;
}
bool isSR;
uint8_t *headerdata;
uint32_t headerdata32[(sizeof(uint32_t)+sizeof(RTCPSenderReport))/sizeof(uint32_t)]; // either for ssrc and sender info or just ssrc
size_t headerlength;
std::list<Buffer> reportblocks;
};
class SDESSource : public RTPMemoryObject
{
public:
SDESSource(uint32_t s,RTPMemoryManager *mgr) : RTPMemoryObject(mgr),ssrc(s),totalitemsize(0) { }
~SDESSource()
{
std::list<Buffer>::const_iterator it;
for (it = items.begin() ; it != items.end() ; it++)
{
if ((*it).packetdata)
RTPDeleteByteArray((*it).packetdata,GetMemoryManager());
}
items.clear();
}
size_t NeededBytes()
{
size_t x,r;
x = totalitemsize + 1; // +1 for the 0 byte which terminates the item list
r = x%sizeof(uint32_t);
if (r != 0)
x += (sizeof(uint32_t)-r); // make sure it ends on a 32 bit boundary
x += sizeof(uint32_t); // for ssrc
return x;
}
size_t NeededBytesWithExtraItem(uint8_t itemdatalength)
{
size_t x,r;
x = totalitemsize + sizeof(RTCPSDESHeader) + (size_t)itemdatalength + 1;
r = x%sizeof(uint32_t);
if (r != 0)
x += (sizeof(uint32_t)-r); // make sure it ends on a 32 bit boundary
x += sizeof(uint32_t); // for ssrc
return x;
}
void AddItem(uint8_t *buf,size_t len)
{
Buffer b(buf,len);
totalitemsize += len;
items.push_back(b);
}
uint32_t ssrc;
std::list<Buffer> items;
private:
size_t totalitemsize;
};
class SDES : public RTPMemoryObject
{
public:
SDES(RTPMemoryManager *mgr) : RTPMemoryObject(mgr) { sdesit = sdessources.end(); }
~SDES() { Clear(); }
void Clear()
{
std::list<SDESSource *>::const_iterator it;
for (it = sdessources.begin() ; it != sdessources.end() ; it++)
RTPDelete(*it,GetMemoryManager());
sdessources.clear();
}
int AddSSRC(uint32_t ssrc)
{
SDESSource *s = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_SDESSOURCE) SDESSource(ssrc,GetMemoryManager());
if (s == 0)
return ERR_RTP_OUTOFMEM;
sdessources.push_back(s);
sdesit = sdessources.end();
sdesit--;
return 0;
}
int AddItem(uint8_t *buf,size_t len)
{
if (sdessources.empty())
return ERR_RTP_RTCPCOMPPACKBUILDER_NOCURRENTSOURCE;
(*sdesit)->AddItem(buf,len);
return 0;
}
size_t NeededBytes()
{
std::list<SDESSource *>::const_iterator it;
size_t x = 0;
size_t n,d,r;
if (sdessources.empty())
return 0;
for (it = sdessources.begin() ; it != sdessources.end() ; it++)
x += (*it)->NeededBytes();
n = sdessources.size();
d = n/31;
r = n%31;
if (r != 0)
d++;
x += d*sizeof(RTCPCommonHeader);
return x;
}
size_t NeededBytesWithExtraItem(uint8_t itemdatalength)
{
std::list<SDESSource *>::const_iterator it;
size_t x = 0;
size_t n,d,r;
if (sdessources.empty())
return 0;
for (it = sdessources.begin() ; it != sdesit ; it++)
x += (*it)->NeededBytes();
x += (*sdesit)->NeededBytesWithExtraItem(itemdatalength);
n = sdessources.size();
d = n/31;
r = n%31;
if (r != 0)
d++;
x += d*sizeof(RTCPCommonHeader);
return x;
}
size_t NeededBytesWithExtraSource()
{
std::list<SDESSource *>::const_iterator it;
size_t x = 0;
size_t n,d,r;
if (sdessources.empty())
return 0;
for (it = sdessources.begin() ; it != sdessources.end() ; it++)
x += (*it)->NeededBytes();
// for the extra source we'll need at least 8 bytes (ssrc and four 0 bytes)
x += sizeof(uint32_t)*2;
n = sdessources.size() + 1; // also, the number of sources will increase
d = n/31;
r = n%31;
if (r != 0)
d++;
x += d*sizeof(RTCPCommonHeader);
return x;
}
std::list<SDESSource *> sdessources;
private:
std::list<SDESSource *>::const_iterator sdesit;
};
size_t maximumpacketsize;
uint8_t *buffer;
bool external;
bool arebuilding;
Report report;
SDES sdes;
std::list<Buffer> byepackets;
size_t byesize;
std::list<Buffer> apppackets;
size_t appsize;
#ifdef RTP_SUPPORT_RTCPUNKNOWN
std::list<Buffer> unknownpackets;
size_t unknownsize;
#endif // RTP_SUPPORT_RTCPUNKNOWN
void ClearBuildBuffers();
};
} // end namespace
#endif // RTCPCOMPOUNDPACKETBUILDER_H

91
qrtplib/rtcppacket.h Normal file
View File

@ -0,0 +1,91 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcppacket.h
*/
#ifndef RTCPPACKET_H
#define RTCPPACKET_H
#include "rtpconfig.h"
#include "rtptypes.h"
namespace qrtplib
{
class RTCPCompoundPacket;
/** Base class for specific types of RTCP packets. */
class JRTPLIB_IMPORTEXPORT RTCPPacket
{
public:
/** Identifies the specific kind of RTCP packet. */
enum PacketType
{
SR, /**< An RTCP sender report. */
RR, /**< An RTCP receiver report. */
SDES, /**< An RTCP source description packet. */
BYE, /**< An RTCP bye packet. */
APP, /**< An RTCP packet containing application specific data. */
Unknown /**< The type of RTCP packet was not recognized. */
};
protected:
RTCPPacket(PacketType t,uint8_t *d,size_t dlen) : data(d),datalen(dlen),packettype(t) { knownformat = false; }
public:
virtual ~RTCPPacket() { }
/** Returns \c true if the subclass was able to interpret the data and \c false otherwise. */
bool IsKnownFormat() const { return knownformat; }
/** Returns the actual packet type which the subclass implements. */
PacketType GetPacketType() const { return packettype; }
/** Returns a pointer to the data of this RTCP packet. */
uint8_t *GetPacketData() { return data; }
/** Returns the length of this RTCP packet. */
size_t GetPacketLength() const { return datalen; }
protected:
uint8_t *data;
size_t datalen;
bool knownformat;
private:
const PacketType packettype;
};
} // end namespace
#endif // RTCPPACKET_H

View File

@ -0,0 +1,737 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcppacketbuilder.h"
#include "rtpsources.h"
#include "rtppacketbuilder.h"
#include "rtcpscheduler.h"
#include "rtpsourcedata.h"
#include "rtcpcompoundpacketbuilder.h"
#include "rtpmemorymanager.h"
namespace qrtplib
{
RTCPPacketBuilder::RTCPPacketBuilder(RTPSources &s,RTPPacketBuilder &pb,RTPMemoryManager *mgr)
: RTPMemoryObject(mgr),sources(s),rtppacketbuilder(pb),prevbuildtime(0,0),transmissiondelay(0,0),ownsdesinfo(mgr)
{
init = false;
timeinit.Dummy();
}
RTCPPacketBuilder::~RTCPPacketBuilder()
{
Destroy();
}
int RTCPPacketBuilder::Init(size_t maxpacksize,double tsunit,const void *cname,size_t cnamelen)
{
if (init)
return ERR_RTP_RTCPPACKETBUILDER_ALREADYINIT;
if (maxpacksize < RTP_MINPACKETSIZE)
return ERR_RTP_RTCPPACKETBUILDER_ILLEGALMAXPACKSIZE;
if (tsunit < 0.0)
return ERR_RTP_RTCPPACKETBUILDER_ILLEGALTIMESTAMPUNIT;
if (cnamelen>255)
cnamelen = 255;
maxpacketsize = maxpacksize;
timestampunit = tsunit;
int status;
if ((status = ownsdesinfo.SetCNAME((const uint8_t *)cname,cnamelen)) < 0)
return status;
ClearAllSourceFlags();
interval_name = -1;
interval_email = -1;
interval_location = -1;
interval_phone = -1;
interval_tool = -1;
interval_note = -1;
sdesbuildcount = 0;
transmissiondelay = RTPTime(0,0);
firstpacket = true;
processingsdes = false;
init = true;
return 0;
}
void RTCPPacketBuilder::Destroy()
{
if (!init)
return;
ownsdesinfo.Clear();
init = false;
}
int RTCPPacketBuilder::BuildNextPacket(RTCPCompoundPacket **pack)
{
if (!init)
return ERR_RTP_RTCPPACKETBUILDER_NOTINIT;
RTCPCompoundPacketBuilder *rtcpcomppack;
int status;
bool sender = false;
RTPSourceData *srcdat;
*pack = 0;
rtcpcomppack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPCOMPOUNDPACKETBUILDER) RTCPCompoundPacketBuilder(GetMemoryManager());
if (rtcpcomppack == 0)
return ERR_RTP_OUTOFMEM;
if ((status = rtcpcomppack->InitBuild(maxpacketsize)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
if ((srcdat = sources.GetOwnSourceInfo()) != 0)
{
if (srcdat->IsSender())
sender = true;
}
uint32_t ssrc = rtppacketbuilder.GetSSRC();
RTPTime curtime = RTPTime::CurrentTime();
if (sender)
{
RTPTime rtppacktime = rtppacketbuilder.GetPacketTime();
uint32_t rtppacktimestamp = rtppacketbuilder.GetPacketTimestamp();
uint32_t packcount = rtppacketbuilder.GetPacketCount();
uint32_t octetcount = rtppacketbuilder.GetPayloadOctetCount();
RTPTime diff = curtime;
diff -= rtppacktime;
diff += transmissiondelay; // the sample being sampled at this very instant will need a larger timestamp
uint32_t tsdiff = (uint32_t)((diff.GetDouble()/timestampunit)+0.5);
uint32_t rtptimestamp = rtppacktimestamp+tsdiff;
RTPNTPTime ntptimestamp = curtime.GetNTPTime();
if ((status = rtcpcomppack->StartSenderReport(ssrc,ntptimestamp,rtptimestamp,packcount,octetcount)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
}
else
{
if ((status = rtcpcomppack->StartReceiverReport(ssrc)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
}
uint8_t *owncname;
size_t owncnamelen;
owncname = ownsdesinfo.GetCNAME(&owncnamelen);
if ((status = rtcpcomppack->AddSDESSource(ssrc)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::CNAME,owncname,owncnamelen)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
if (!processingsdes)
{
int added,skipped;
bool full,atendoflist;
if ((status = FillInReportBlocks(rtcpcomppack,curtime,sources.GetTotalCount(),&full,&added,&skipped,&atendoflist)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
if (full && added == 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
}
if (!full)
{
processingsdes = true;
sdesbuildcount++;
ClearAllSourceFlags();
doname = false;
doemail = false;
doloc = false;
dophone = false;
dotool = false;
donote = false;
if (interval_name > 0 && ((sdesbuildcount%interval_name) == 0)) doname = true;
if (interval_email > 0 && ((sdesbuildcount%interval_email) == 0)) doemail = true;
if (interval_location > 0 && ((sdesbuildcount%interval_location) == 0)) doloc = true;
if (interval_phone > 0 && ((sdesbuildcount%interval_phone) == 0)) dophone = true;
if (interval_tool > 0 && ((sdesbuildcount%interval_tool) == 0)) dotool = true;
if (interval_note > 0 && ((sdesbuildcount%interval_note) == 0)) donote = true;
bool processedall;
int itemcount;
if ((status = FillInSDES(rtcpcomppack,&full,&processedall,&itemcount)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
if (processedall)
{
processingsdes = false;
ClearAllSDESFlags();
if (!full && skipped > 0)
{
// if the packet isn't full and we skipped some
// sources that we already got in a previous packet,
// we can add some of them now
bool atendoflist;
if ((status = FillInReportBlocks(rtcpcomppack,curtime,skipped,&full,&added,&skipped,&atendoflist)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
}
}
}
}
else // previous sdes processing wasn't finished
{
bool processedall;
int itemcount;
bool full;
if ((status = FillInSDES(rtcpcomppack,&full,&processedall,&itemcount)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
if (itemcount == 0) // Big problem: packet size is too small to let any progress happen
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
}
if (processedall)
{
processingsdes = false;
ClearAllSDESFlags();
if (!full)
{
// if the packet isn't full and we skipped some
// we can add some report blocks
int added,skipped;
bool atendoflist;
if ((status = FillInReportBlocks(rtcpcomppack,curtime,sources.GetTotalCount(),&full,&added,&skipped,&atendoflist)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
if (atendoflist) // filled in all possible sources
ClearAllSourceFlags();
}
}
}
if ((status = rtcpcomppack->EndBuild()) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
*pack = rtcpcomppack;
firstpacket = false;
prevbuildtime = curtime;
return 0;
}
void RTCPPacketBuilder::ClearAllSourceFlags()
{
if (sources.GotoFirstSource())
{
do
{
RTPSourceData *srcdat = sources.GetCurrentSourceInfo();
srcdat->SetProcessedInRTCP(false);
} while (sources.GotoNextSource());
}
}
int RTCPPacketBuilder::FillInReportBlocks(RTCPCompoundPacketBuilder *rtcpcomppack,const RTPTime &curtime,int maxcount,bool *full,int *added,int *skipped,bool *atendoflist)
{
RTPSourceData *srcdat;
int addedcount = 0;
int skippedcount = 0;
bool done = false;
bool filled = false;
bool atend = false;
int status;
if (sources.GotoFirstSource())
{
do
{
bool shouldprocess = false;
srcdat = sources.GetCurrentSourceInfo();
if (!srcdat->IsOwnSSRC()) // don't send to ourselves
{
if (!srcdat->IsCSRC()) // p 35: no reports should go to CSRCs
{
if (srcdat->INF_HasSentData()) // if this isn't true, INF_GetLastRTPPacketTime() won't make any sense
{
if (firstpacket)
shouldprocess = true;
else
{
// p 35: only if rtp packets were received since the last RTP packet, a report block
// should be added
RTPTime lastrtptime = srcdat->INF_GetLastRTPPacketTime();
if (lastrtptime > prevbuildtime)
shouldprocess = true;
}
}
}
}
if (shouldprocess)
{
if (srcdat->IsProcessedInRTCP()) // already covered this one
{
skippedcount++;
}
else
{
uint32_t rr_ssrc = srcdat->GetSSRC();
uint32_t num = srcdat->INF_GetNumPacketsReceivedInInterval();
uint32_t prevseq = srcdat->INF_GetSavedExtendedSequenceNumber();
uint32_t curseq = srcdat->INF_GetExtendedHighestSequenceNumber();
uint32_t expected = curseq-prevseq;
uint8_t fraclost;
if (expected < num) // got duplicates
fraclost = 0;
else
{
double lost = (double)(expected-num);
double frac = lost/((double)expected);
fraclost = (uint8_t)(frac*256.0);
}
expected = curseq-srcdat->INF_GetBaseSequenceNumber();
num = srcdat->INF_GetNumPacketsReceived();
uint32_t diff = expected-num;
int32_t *packlost = (int32_t *)&diff;
uint32_t jitter = srcdat->INF_GetJitter();
uint32_t lsr;
uint32_t dlsr;
if (!srcdat->SR_HasInfo())
{
lsr = 0;
dlsr = 0;
}
else
{
RTPNTPTime srtime = srcdat->SR_GetNTPTimestamp();
uint32_t m = (srtime.GetMSW()&0xFFFF);
uint32_t l = ((srtime.GetLSW()>>16)&0xFFFF);
lsr = ((m<<16)|l);
RTPTime diff = curtime;
diff -= srcdat->SR_GetReceiveTime();
double diff2 = diff.GetDouble();
diff2 *= 65536.0;
dlsr = (uint32_t)diff2;
}
status = rtcpcomppack->AddReportBlock(rr_ssrc,fraclost,*packlost,curseq,jitter,lsr,dlsr);
if (status < 0)
{
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
{
done = true;
filled = true;
}
else
return status;
}
else
{
addedcount++;
if (addedcount >= maxcount)
{
done = true;
if (!sources.GotoNextSource())
atend = true;
}
srcdat->INF_StartNewInterval();
srcdat->SetProcessedInRTCP(true);
}
}
}
if (!done)
{
if (!sources.GotoNextSource())
{
atend = true;
done = true;
}
}
} while (!done);
}
*added = addedcount;
*skipped = skippedcount;
*full = filled;
if (!atend) // search for available sources
{
bool shouldprocess = false;
do
{
srcdat = sources.GetCurrentSourceInfo();
if (!srcdat->IsOwnSSRC()) // don't send to ourselves
{
if (!srcdat->IsCSRC()) // p 35: no reports should go to CSRCs
{
if (srcdat->INF_HasSentData()) // if this isn't true, INF_GetLastRTPPacketTime() won't make any sense
{
if (firstpacket)
shouldprocess = true;
else
{
// p 35: only if rtp packets were received since the last RTP packet, a report block
// should be added
RTPTime lastrtptime = srcdat->INF_GetLastRTPPacketTime();
if (lastrtptime > prevbuildtime)
shouldprocess = true;
}
}
}
}
if (shouldprocess)
{
if (srcdat->IsProcessedInRTCP())
shouldprocess = false;
}
if (!shouldprocess)
{
if (!sources.GotoNextSource())
atend = true;
}
} while (!atend && !shouldprocess);
}
*atendoflist = atend;
return 0;
}
int RTCPPacketBuilder::FillInSDES(RTCPCompoundPacketBuilder *rtcpcomppack,bool *full,bool *processedall,int *added)
{
int status;
uint8_t *data;
size_t datalen;
*full = false;
*processedall = false;
*added = 0;
// We don't need to add a SSRC for our own data, this is still set
// from adding the CNAME
if (doname)
{
if (!ownsdesinfo.ProcessedName())
{
data = ownsdesinfo.GetName(&datalen);
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::NAME,data,datalen)) < 0)
{
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
{
*full = true;
return 0;
}
}
(*added)++;
ownsdesinfo.SetProcessedName(true);
}
}
if (doemail)
{
if (!ownsdesinfo.ProcessedEMail())
{
data = ownsdesinfo.GetEMail(&datalen);
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::EMAIL,data,datalen)) < 0)
{
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
{
*full = true;
return 0;
}
}
(*added)++;
ownsdesinfo.SetProcessedEMail(true);
}
}
if (doloc)
{
if (!ownsdesinfo.ProcessedLocation())
{
data = ownsdesinfo.GetLocation(&datalen);
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::LOC,data,datalen)) < 0)
{
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
{
*full = true;
return 0;
}
}
(*added)++;
ownsdesinfo.SetProcessedLocation(true);
}
}
if (dophone)
{
if (!ownsdesinfo.ProcessedPhone())
{
data = ownsdesinfo.GetPhone(&datalen);
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::PHONE,data,datalen)) < 0)
{
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
{
*full = true;
return 0;
}
}
(*added)++;
ownsdesinfo.SetProcessedPhone(true);
}
}
if (dotool)
{
if (!ownsdesinfo.ProcessedTool())
{
data = ownsdesinfo.GetTool(&datalen);
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::TOOL,data,datalen)) < 0)
{
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
{
*full = true;
return 0;
}
}
(*added)++;
ownsdesinfo.SetProcessedTool(true);
}
}
if (donote)
{
if (!ownsdesinfo.ProcessedNote())
{
data = ownsdesinfo.GetNote(&datalen);
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::NOTE,data,datalen)) < 0)
{
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
{
*full = true;
return 0;
}
}
(*added)++;
ownsdesinfo.SetProcessedNote(true);
}
}
*processedall = true;
return 0;
}
void RTCPPacketBuilder::ClearAllSDESFlags()
{
ownsdesinfo.ClearFlags();
}
int RTCPPacketBuilder::BuildBYEPacket(RTCPCompoundPacket **pack,const void *reason,size_t reasonlength,bool useSRifpossible)
{
if (!init)
return ERR_RTP_RTCPPACKETBUILDER_NOTINIT;
RTCPCompoundPacketBuilder *rtcpcomppack;
int status;
if (reasonlength > 255)
reasonlength = 255;
*pack = 0;
rtcpcomppack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTCPCOMPOUNDPACKETBUILDER) RTCPCompoundPacketBuilder(GetMemoryManager());
if (rtcpcomppack == 0)
return ERR_RTP_OUTOFMEM;
if ((status = rtcpcomppack->InitBuild(maxpacketsize)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
uint32_t ssrc = rtppacketbuilder.GetSSRC();
bool useSR = false;
if (useSRifpossible)
{
RTPSourceData *srcdat;
if ((srcdat = sources.GetOwnSourceInfo()) != 0)
{
if (srcdat->IsSender())
useSR = true;
}
}
if (useSR)
{
RTPTime curtime = RTPTime::CurrentTime();
RTPTime rtppacktime = rtppacketbuilder.GetPacketTime();
uint32_t rtppacktimestamp = rtppacketbuilder.GetPacketTimestamp();
uint32_t packcount = rtppacketbuilder.GetPacketCount();
uint32_t octetcount = rtppacketbuilder.GetPayloadOctetCount();
RTPTime diff = curtime;
diff -= rtppacktime;
uint32_t tsdiff = (uint32_t)((diff.GetDouble()/timestampunit)+0.5);
uint32_t rtptimestamp = rtppacktimestamp+tsdiff;
RTPNTPTime ntptimestamp = curtime.GetNTPTime();
if ((status = rtcpcomppack->StartSenderReport(ssrc,ntptimestamp,rtptimestamp,packcount,octetcount)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
}
else
{
if ((status = rtcpcomppack->StartReceiverReport(ssrc)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
}
uint8_t *owncname;
size_t owncnamelen;
owncname = ownsdesinfo.GetCNAME(&owncnamelen);
if ((status = rtcpcomppack->AddSDESSource(ssrc)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
if ((status = rtcpcomppack->AddSDESNormalItem(RTCPSDESPacket::CNAME,owncname,owncnamelen)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
uint32_t ssrcs[1];
ssrcs[0] = ssrc;
if ((status = rtcpcomppack->AddBYEPacket(ssrcs,1,(const uint8_t *)reason,reasonlength)) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
if (status == ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT)
return ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON;
return status;
}
if ((status = rtcpcomppack->EndBuild()) < 0)
{
RTPDelete(rtcpcomppack,GetMemoryManager());
return status;
}
*pack = rtcpcomppack;
return 0;
}
} // end namespace

229
qrtplib/rtcppacketbuilder.h Normal file
View File

@ -0,0 +1,229 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcppacketbuilder.h
*/
#ifndef RTCPPACKETBUILDER_H
#define RTCPPACKETBUILDER_H
#include "rtpconfig.h"
#include "rtptypes.h"
#include "rtperrors.h"
#include "rtcpsdesinfo.h"
#include "rtptimeutilities.h"
#include "rtpmemoryobject.h"
namespace qrtplib
{
class RTPSources;
class RTPPacketBuilder;
class RTCPScheduler;
class RTCPCompoundPacket;
class RTCPCompoundPacketBuilder;
/** This class can be used to build RTCP compound packets, on a higher level than the RTCPCompoundPacketBuilder.
* The class RTCPPacketBuilder can be used to build RTCP compound packets. This class is more high-level
* than the RTCPCompoundPacketBuilder class: it uses the information of an RTPPacketBuilder instance and of
* an RTPSources instance to automatically generate the next compound packet which should be sent. It also
* provides functions to determine when SDES items other than the CNAME item should be sent.
*/
class JRTPLIB_IMPORTEXPORT RTCPPacketBuilder : public RTPMemoryObject
{
public:
/** Creates an RTCPPacketBuilder instance.
* Creates an instance which will use the source table \c sources and the RTP packet builder
* \c rtppackbuilder to determine the information for the next RTCP compound packet. Optionally,
* the memory manager \c mgr can be installed.
*/
RTCPPacketBuilder(RTPSources &sources,RTPPacketBuilder &rtppackbuilder, RTPMemoryManager *mgr = 0);
~RTCPPacketBuilder();
/** Initializes the builder.
* Initializes the builder to use the maximum allowed packet size \c maxpacksize, timestamp unit
* \c timestampunit and the SDES CNAME item specified by \c cname with length \c cnamelen.
* The timestamp unit is defined as a time interval divided by the timestamp interval corresponding to
* that interval: for 8000 Hz audio this would be 1/8000.
*/
int Init(size_t maxpacksize,double timestampunit,const void *cname,size_t cnamelen);
/** Cleans up the builder. */
void Destroy();
/** Sets the timestamp unit to be used to \c tsunit.
* Sets the timestamp unit to be used to \c tsunit. The timestamp unit is defined as a time interval
* divided by the timestamp interval corresponding to that interval: for 8000 Hz audio this would
* be 1/8000.
*/
int SetTimestampUnit(double tsunit) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; if (tsunit < 0) return ERR_RTP_RTCPPACKETBUILDER_ILLEGALTIMESTAMPUNIT; timestampunit = tsunit; return 0; }
/** Sets the maximum size allowed size of an RTCP compound packet to \c maxpacksize. */
int SetMaximumPacketSize(size_t maxpacksize) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; if (maxpacksize < RTP_MINPACKETSIZE) return ERR_RTP_RTCPPACKETBUILDER_ILLEGALMAXPACKSIZE; maxpacketsize = maxpacksize; return 0; }
/** This function allows you to inform RTCP packet builder about the delay between sampling the first
* sample of a packet and sending the packet.
* This function allows you to inform RTCP packet builder about the delay between sampling the first
* sample of a packet and sending the packet. This delay is taken into account when calculating the
* relation between RTP timestamp and wallclock time, used for inter-media synchronization.
*/
int SetPreTransmissionDelay(const RTPTime &delay) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; transmissiondelay = delay; return 0; }
/** Builds the next RTCP compound packet which should be sent and stores it in \c pack. */
int BuildNextPacket(RTCPCompoundPacket **pack);
/** Builds a BYE packet with reason for leaving specified by \c reason and length \c reasonlength.
* Builds a BYE packet with reason for leaving specified by \c reason and length \c reasonlength. If
* \c useSRifpossible is set to \c true, the RTCP compound packet will start with a sender report if
* allowed. Otherwise, a receiver report is used.
*/
int BuildBYEPacket(RTCPCompoundPacket **pack,const void *reason,size_t reasonlength,bool useSRifpossible = true);
/** Sets the RTCP interval for the SDES name item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES name item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetNameInterval(int count) { if (!init) return; interval_name = count; }
/** Sets the RTCP interval for the SDES e-mail item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES e-mail item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetEMailInterval(int count) { if (!init) return; interval_email = count; }
/** Sets the RTCP interval for the SDES location item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES location item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetLocationInterval(int count) { if (!init) return; interval_location = count; }
/** Sets the RTCP interval for the SDES phone item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES phone item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetPhoneInterval(int count) { if (!init) return; interval_phone = count; }
/** Sets the RTCP interval for the SDES tool item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES tool item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetToolInterval(int count) { if (!init) return; interval_tool = count; }
/** Sets the RTCP interval for the SDES note item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES note item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetNoteInterval(int count) { if (!init) return; interval_note = count; }
/** Sets the SDES name item for the local participant to the value \c s with length \c len. */
int SetLocalName(const void *s,size_t len) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; return ownsdesinfo.SetName((const uint8_t *)s,len); }
/** Sets the SDES e-mail item for the local participant to the value \c s with length \c len. */
int SetLocalEMail(const void *s,size_t len) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; return ownsdesinfo.SetEMail((const uint8_t *)s,len); }
/** Sets the SDES location item for the local participant to the value \c s with length \c len. */
int SetLocalLocation(const void *s,size_t len) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; return ownsdesinfo.SetLocation((const uint8_t *)s,len); }
/** Sets the SDES phone item for the local participant to the value \c s with length \c len. */
int SetLocalPhone(const void *s,size_t len) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; return ownsdesinfo.SetPhone((const uint8_t *)s,len); }
/** Sets the SDES tool item for the local participant to the value \c s with length \c len. */
int SetLocalTool(const void *s,size_t len) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; return ownsdesinfo.SetTool((const uint8_t *)s,len); }
/** Sets the SDES note item for the local participant to the value \c s with length \c len. */
int SetLocalNote(const void *s,size_t len) { if (!init) return ERR_RTP_RTCPPACKETBUILDER_NOTINIT; return ownsdesinfo.SetNote((const uint8_t *)s,len); }
/** Returns the own CNAME item with length \c len */
uint8_t *GetLocalCNAME(size_t *len) const { if (!init) return 0; return ownsdesinfo.GetCNAME(len); }
private:
void ClearAllSourceFlags();
int FillInReportBlocks(RTCPCompoundPacketBuilder *pack,const RTPTime &curtime,int maxcount,bool *full,int *added,int *skipped,bool *atendoflist);
int FillInSDES(RTCPCompoundPacketBuilder *pack,bool *full,bool *processedall,int *added);
void ClearAllSDESFlags();
RTPSources &sources;
RTPPacketBuilder &rtppacketbuilder;
bool init;
size_t maxpacketsize;
double timestampunit;
bool firstpacket;
RTPTime prevbuildtime,transmissiondelay;
class RTCPSDESInfoInternal : public RTCPSDESInfo
{
public:
RTCPSDESInfoInternal(RTPMemoryManager *mgr) : RTCPSDESInfo(mgr) { ClearFlags(); }
void ClearFlags() { pname = false; pemail = false; plocation = false; pphone = false; ptool = false; pnote = false; }
bool ProcessedName() const { return pname; }
bool ProcessedEMail() const { return pemail; }
bool ProcessedLocation() const { return plocation; }
bool ProcessedPhone() const { return pphone; }
bool ProcessedTool() const { return ptool; }
bool ProcessedNote() const { return pnote; }
void SetProcessedName(bool v) { pname = v; }
void SetProcessedEMail(bool v) { pemail = v; }
void SetProcessedLocation(bool v) { plocation = v; }
void SetProcessedPhone(bool v) { pphone = v; }
void SetProcessedTool(bool v) { ptool = v; }
void SetProcessedNote(bool v) { pnote = v; }
private:
bool pname,pemail,plocation,pphone,ptool,pnote;
};
RTCPSDESInfoInternal ownsdesinfo;
int interval_name,interval_email,interval_location;
int interval_phone,interval_tool,interval_note;
bool doname,doemail,doloc,dophone,dotool,donote;
bool processingsdes;
int sdesbuildcount;
};
} // end namespace
#endif // RTCPPACKETBUILDER_H

68
qrtplib/rtcprrpacket.cpp Normal file
View File

@ -0,0 +1,68 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcprrpacket.h"
namespace qrtplib
{
RTCPRRPacket::RTCPRRPacket(uint8_t *data,size_t datalength)
: RTCPPacket(RR,data,datalength)
{
knownformat = false;
RTCPCommonHeader *hdr;
size_t len = datalength;
size_t expectedlength;
hdr = (RTCPCommonHeader *)data;
if (hdr->padding)
{
uint8_t padcount = data[datalength-1];
if ((padcount & 0x03) != 0) // not a multiple of four! (see rfc 3550 p 37)
return;
if (((size_t)padcount) >= len)
return;
len -= (size_t)padcount;
}
expectedlength = sizeof(RTCPCommonHeader)+sizeof(uint32_t);
expectedlength += sizeof(RTCPReceiverReport)*((int)hdr->count);
if (expectedlength != len)
return;
knownformat = true;
}
} // end namespace

203
qrtplib/rtcprrpacket.h Normal file
View File

@ -0,0 +1,203 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcprrpacket.h
*/
#ifndef RTCPRRPACKET_H
#define RTCPRRPACKET_H
#include "rtpconfig.h"
#include "rtcppacket.h"
#include "rtpstructs.h"
#ifdef RTP_SUPPORT_NETINET_IN
#include <netinet/in.h>
#endif // RTP_SUPPORT_NETINET_IN
namespace qrtplib
{
class RTCPCompoundPacket;
/** Describes an RTCP receiver report packet. */
class JRTPLIB_IMPORTEXPORT RTCPRRPacket : public RTCPPacket
{
public:
/** Creates an instance based on the data in \c data with length \c datalen.
* Creates an instance based on the data in \c data with length \c datalen. Since the \c data pointer
* is referenced inside the class (no copy of the data is made) one must make sure that the memory it points
* to is valid as long as the class instance exists.
*/
RTCPRRPacket(uint8_t *data,size_t datalen);
~RTCPRRPacket() { }
/** Returns the SSRC of the participant who sent this packet. */
uint32_t GetSenderSSRC() const;
/** Returns the number of reception report blocks present in this packet. */
int GetReceptionReportCount() const;
/** Returns the SSRC of the reception report block described by \c index which may have a value
* from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetSSRC(int index) const;
/** Returns the `fraction lost' field of the reception report described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint8_t GetFractionLost(int index) const;
/** Returns the number of lost packets in the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
int32_t GetLostPacketCount(int index) const;
/** Returns the extended highest sequence number of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetExtendedHighestSequenceNumber(int index) const;
/** Returns the jitter field of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetJitter(int index) const;
/** Returns the LSR field of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetLSR(int index) const;
/** Returns the DLSR field of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetDLSR(int index) const;
private:
RTCPReceiverReport *GotoReport(int index) const;
};
inline uint32_t RTCPRRPacket::GetSenderSSRC() const
{
if (!knownformat)
return 0;
uint32_t *ssrcptr = (uint32_t *)(data+sizeof(RTCPCommonHeader));
return ntohl(*ssrcptr);
}
inline int RTCPRRPacket::GetReceptionReportCount() const
{
if (!knownformat)
return 0;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)data;
return ((int)hdr->count);
}
inline RTCPReceiverReport *RTCPRRPacket::GotoReport(int index) const
{
RTCPReceiverReport *r = (RTCPReceiverReport *)(data+sizeof(RTCPCommonHeader)+sizeof(uint32_t)+index*sizeof(RTCPReceiverReport));
return r;
}
inline uint32_t RTCPRRPacket::GetSSRC(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->ssrc);
}
inline uint8_t RTCPRRPacket::GetFractionLost(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return r->fractionlost;
}
inline int32_t RTCPRRPacket::GetLostPacketCount(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
uint32_t count = ((uint32_t)r->packetslost[2])|(((uint32_t)r->packetslost[1])<<8)|(((uint32_t)r->packetslost[0])<<16);
if ((count&0x00800000) != 0) // test for negative number
count |= 0xFF000000;
int32_t *count2 = (int32_t *)(&count);
return (*count2);
}
inline uint32_t RTCPRRPacket::GetExtendedHighestSequenceNumber(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->exthighseqnr);
}
inline uint32_t RTCPRRPacket::GetJitter(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->jitter);
}
inline uint32_t RTCPRRPacket::GetLSR(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->lsr);
}
inline uint32_t RTCPRRPacket::GetDLSR(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->dlsr);
}
} // end namespace
#endif // RTCPRRPACKET_H

419
qrtplib/rtcpscheduler.cpp Normal file
View File

@ -0,0 +1,419 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpscheduler.h"
#include "rtpsources.h"
#include "rtpdefines.h"
#include "rtcppacket.h"
#include "rtppacket.h"
#include "rtcpcompoundpacket.h"
#include "rtpsourcedata.h"
#define RTCPSCHED_MININTERVAL 1.0
namespace qrtplib
{
RTCPSchedulerParams::RTCPSchedulerParams() : mininterval(RTCP_DEFAULTMININTERVAL)
{
bandwidth = 1000; // TODO What is a good value here?
senderfraction = RTCP_DEFAULTSENDERFRACTION;
usehalfatstartup = RTCP_DEFAULTHALFATSTARTUP;
immediatebye = RTCP_DEFAULTIMMEDIATEBYE;
timeinit.Dummy();
}
RTCPSchedulerParams::~RTCPSchedulerParams()
{
}
int RTCPSchedulerParams::SetRTCPBandwidth(double bw)
{
if (bw < 0.0)
return ERR_RTP_SCHEDPARAMS_INVALIDBANDWIDTH;
bandwidth = bw;
return 0;
}
int RTCPSchedulerParams::SetSenderBandwidthFraction(double fraction)
{
if (fraction < 0.0 || fraction > 1.0)
return ERR_RTP_SCHEDPARAMS_BADFRACTION;
senderfraction = fraction;
return 0;
}
int RTCPSchedulerParams::SetMinimumTransmissionInterval(const RTPTime &t)
{
double t2 = t.GetDouble();
if (t2 < RTCPSCHED_MININTERVAL)
return ERR_RTP_SCHEDPARAMS_BADMINIMUMINTERVAL;
mininterval = t;
return 0;
}
RTCPScheduler::RTCPScheduler(RTPSources &s, RTPRandom &r) : sources(s),nextrtcptime(0,0),prevrtcptime(0,0),rtprand(r)
{
Reset();
//std::cout << (void *)(&rtprand) << std::endl;
}
RTCPScheduler::~RTCPScheduler()
{
}
void RTCPScheduler::Reset()
{
headeroverhead = 0; // user has to set this to an appropriate value
hassentrtcp = false;
firstcall = true;
avgrtcppacksize = 1000; // TODO: what is a good value for this?
byescheduled = false;
sendbyenow = false;
}
void RTCPScheduler::AnalyseIncoming(RTCPCompoundPacket &rtcpcomppack)
{
bool isbye = false;
RTCPPacket *p;
rtcpcomppack.GotoFirstPacket();
while (!isbye && ((p = rtcpcomppack.GetNextPacket()) != 0))
{
if (p->GetPacketType() == RTCPPacket::BYE)
isbye = true;
}
if (!isbye)
{
size_t packsize = headeroverhead+rtcpcomppack.GetCompoundPacketLength();
avgrtcppacksize = (size_t)((1.0/16.0)*((double)packsize)+(15.0/16.0)*((double)avgrtcppacksize));
}
else
{
if (byescheduled)
{
size_t packsize = headeroverhead+rtcpcomppack.GetCompoundPacketLength();
avgbyepacketsize = (size_t)((1.0/16.0)*((double)packsize)+(15.0/16.0)*((double)avgbyepacketsize));
byemembers++;
}
}
}
void RTCPScheduler::AnalyseOutgoing(RTCPCompoundPacket &rtcpcomppack)
{
bool isbye = false;
RTCPPacket *p;
rtcpcomppack.GotoFirstPacket();
while (!isbye && ((p = rtcpcomppack.GetNextPacket()) != 0))
{
if (p->GetPacketType() == RTCPPacket::BYE)
isbye = true;
}
if (!isbye)
{
size_t packsize = headeroverhead+rtcpcomppack.GetCompoundPacketLength();
avgrtcppacksize = (size_t)((1.0/16.0)*((double)packsize)+(15.0/16.0)*((double)avgrtcppacksize));
}
hassentrtcp = true;
}
RTPTime RTCPScheduler::GetTransmissionDelay()
{
if (firstcall)
{
firstcall = false;
prevrtcptime = RTPTime::CurrentTime();
pmembers = sources.GetActiveMemberCount();
CalculateNextRTCPTime();
}
RTPTime curtime = RTPTime::CurrentTime();
if (curtime > nextrtcptime) // packet should be sent
return RTPTime(0,0);
RTPTime diff = nextrtcptime;
diff -= curtime;
return diff;
}
bool RTCPScheduler::IsTime()
{
if (firstcall)
{
firstcall = false;
prevrtcptime = RTPTime::CurrentTime();
pmembers = sources.GetActiveMemberCount();
CalculateNextRTCPTime();
return false;
}
RTPTime currenttime = RTPTime::CurrentTime();
// // TODO: for debugging
// double diff = nextrtcptime.GetDouble() - currenttime.GetDouble();
//
// std::cout << "Delay till next RTCP interval: " << diff << std::endl;
if (currenttime < nextrtcptime) // timer has not yet expired
return false;
RTPTime checktime(0,0);
if (!byescheduled)
{
bool aresender = false;
RTPSourceData *srcdat;
if ((srcdat = sources.GetOwnSourceInfo()) != 0)
aresender = srcdat->IsSender();
checktime = CalculateTransmissionInterval(aresender);
}
else
checktime = CalculateBYETransmissionInterval();
// std::cout << "Calculated checktime: " << checktime.GetDouble() << std::endl;
checktime += prevrtcptime;
if (checktime <= currenttime) // Okay
{
byescheduled = false;
prevrtcptime = currenttime;
pmembers = sources.GetActiveMemberCount();
CalculateNextRTCPTime();
return true;
}
// std::cout << "New delay: " << nextrtcptime.GetDouble() - currenttime.GetDouble() << std::endl;
nextrtcptime = checktime;
pmembers = sources.GetActiveMemberCount();
return false;
}
void RTCPScheduler::CalculateNextRTCPTime()
{
bool aresender = false;
RTPSourceData *srcdat;
if ((srcdat = sources.GetOwnSourceInfo()) != 0)
aresender = srcdat->IsSender();
nextrtcptime = RTPTime::CurrentTime();
nextrtcptime += CalculateTransmissionInterval(aresender);
}
RTPTime RTCPScheduler::CalculateDeterministicInterval(bool sender /* = false */)
{
int numsenders = sources.GetSenderCount();
int numtotal = sources.GetActiveMemberCount();
// std::cout << "CalculateDeterministicInterval" << std::endl;
// std::cout << " numsenders: " << numsenders << std::endl;
// std::cout << " numtotal: " << numtotal << std::endl;
// Try to avoid division by zero:
if (numtotal == 0)
numtotal++;
double sfraction = ((double)numsenders)/((double)numtotal);
double C,n;
if (sfraction <= schedparams.GetSenderBandwidthFraction())
{
if (sender)
{
C = ((double)avgrtcppacksize)/(schedparams.GetSenderBandwidthFraction()*schedparams.GetRTCPBandwidth());
n = (double)numsenders;
}
else
{
C = ((double)avgrtcppacksize)/((1.0-schedparams.GetSenderBandwidthFraction())*schedparams.GetRTCPBandwidth());
n = (double)(numtotal-numsenders);
}
}
else
{
C = ((double)avgrtcppacksize)/schedparams.GetRTCPBandwidth();
n = (double)numtotal;
}
RTPTime Tmin = schedparams.GetMinimumTransmissionInterval();
double tmin = Tmin.GetDouble();
if (!hassentrtcp && schedparams.GetUseHalfAtStartup())
tmin /= 2.0;
double ntimesC = n*C;
double Td = (tmin>ntimesC)?tmin:ntimesC;
// TODO: for debugging
// std::cout << " Td: " << Td << std::endl;
return RTPTime(Td);
}
RTPTime RTCPScheduler::CalculateTransmissionInterval(bool sender)
{
RTPTime Td = CalculateDeterministicInterval(sender);
double td,mul,T;
// std::cout << "CalculateTransmissionInterval" << std::endl;
td = Td.GetDouble();
mul = rtprand.GetRandomDouble()+0.5; // gives random value between 0.5 and 1.5
T = (td*mul)/1.21828; // see RFC 3550 p 30
// std::cout << " Td: " << td << std::endl;
// std::cout << " mul: " << mul << std::endl;
// std::cout << " T: " << T << std::endl;
return RTPTime(T);
}
void RTCPScheduler::PerformReverseReconsideration()
{
if (firstcall)
return;
double diff1,diff2;
int members = sources.GetActiveMemberCount();
RTPTime tc = RTPTime::CurrentTime();
RTPTime tn_min_tc = nextrtcptime;
if (tn_min_tc > tc)
tn_min_tc -= tc;
else
tn_min_tc = RTPTime(0,0);
// std::cout << "+tn_min_tc0 " << nextrtcptime.GetDouble()-tc.GetDouble() << std::endl;
// std::cout << "-tn_min_tc0 " << -nextrtcptime.GetDouble()+tc.GetDouble() << std::endl;
// std::cout << "tn_min_tc " << tn_min_tc.GetDouble() << std::endl;
RTPTime tc_min_tp = tc;
if (tc_min_tp > prevrtcptime)
tc_min_tp -= prevrtcptime;
else
tc_min_tp = 0;
if (pmembers == 0) // avoid division by zero
pmembers++;
diff1 = (((double)members)/((double)pmembers))*tn_min_tc.GetDouble();
diff2 = (((double)members)/((double)pmembers))*tc_min_tp.GetDouble();
nextrtcptime = tc;
prevrtcptime = tc;
nextrtcptime += RTPTime(diff1);
prevrtcptime -= RTPTime(diff2);
pmembers = members;
}
void RTCPScheduler::ScheduleBYEPacket(size_t packetsize)
{
if (byescheduled)
return;
if (firstcall)
{
firstcall = false;
pmembers = sources.GetActiveMemberCount();
}
byescheduled = true;
avgbyepacketsize = packetsize+headeroverhead;
// For now, we will always use the BYE backoff algorithm as described in rfc 3550 p 33
byemembers = 1;
pbyemembers = 1;
if (schedparams.GetRequestImmediateBYE() && sources.GetActiveMemberCount() < 50) // p 34 (top)
sendbyenow = true;
else
sendbyenow = false;
prevrtcptime = RTPTime::CurrentTime();
nextrtcptime = prevrtcptime;
nextrtcptime += CalculateBYETransmissionInterval();
}
void RTCPScheduler::ActiveMemberDecrease()
{
if (sources.GetActiveMemberCount() < pmembers)
PerformReverseReconsideration();
}
RTPTime RTCPScheduler::CalculateBYETransmissionInterval()
{
if (!byescheduled)
return RTPTime(0,0);
if (sendbyenow)
return RTPTime(0,0);
double C,n;
C = ((double)avgbyepacketsize)/((1.0-schedparams.GetSenderBandwidthFraction())*schedparams.GetRTCPBandwidth());
n = (double)byemembers;
RTPTime Tmin = schedparams.GetMinimumTransmissionInterval();
double tmin = Tmin.GetDouble();
if (schedparams.GetUseHalfAtStartup())
tmin /= 2.0;
double ntimesC = n*C;
double Td = (tmin>ntimesC)?tmin:ntimesC;
double mul = rtprand.GetRandomDouble()+0.5; // gives random value between 0.5 and 1.5
double T = (Td*mul)/1.21828; // see RFC 3550 p 30
return RTPTime(T);
}
} // end namespace

189
qrtplib/rtcpscheduler.h Normal file
View File

@ -0,0 +1,189 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpscheduler.h
*/
#ifndef RTCPSCHEDULER_H
#define RTCPSCHEDULER_H
#include "rtpconfig.h"
#include "rtptimeutilities.h"
#include "rtprandom.h"
namespace qrtplib
{
class RTCPCompoundPacket;
class RTPPacket;
class RTPSources;
/** Describes parameters used by the RTCPScheduler class. */
class JRTPLIB_IMPORTEXPORT RTCPSchedulerParams
{
public:
RTCPSchedulerParams();
~RTCPSchedulerParams();
/** Sets the RTCP bandwidth to be used to \c bw (in bytes per second). */
int SetRTCPBandwidth(double bw);
/** Returns the used RTCP bandwidth in bytes per second (default is 1000). */
double GetRTCPBandwidth() const { return bandwidth; }
/** Sets the fraction of the RTCP bandwidth reserved for senders to \c fraction. */
int SetSenderBandwidthFraction(double fraction);
/** Returns the fraction of the RTCP bandwidth reserved for senders (default is 25%). */
double GetSenderBandwidthFraction() const { return senderfraction; }
/** Sets the minimum (deterministic) interval between RTCP compound packets to \c t. */
int SetMinimumTransmissionInterval(const RTPTime &t);
/** Returns the minimum RTCP transmission interval (default is 5 seconds). */
RTPTime GetMinimumTransmissionInterval() const { return mininterval; }
/** If \c usehalf is \c true, only use half the minimum interval before sending the first RTCP compound packet. */
void SetUseHalfAtStartup(bool usehalf) { usehalfatstartup = usehalf; }
/** Returns \c true if only half the minimum interval should be used before sending the first RTCP compound packet
* (defualt is \c true).
*/
bool GetUseHalfAtStartup() const { return usehalfatstartup; }
/** If \c v is \c true, the scheduler will schedule a BYE packet to be sent immediately if allowed. */
void SetRequestImmediateBYE(bool v) { immediatebye = v; }
/** Returns if the scheduler will schedule a BYE packet to be sent immediately if allowed
* (default is \c true).
*/
bool GetRequestImmediateBYE() const { return immediatebye; }
private:
double bandwidth;
double senderfraction;
RTPTime mininterval;
bool usehalfatstartup;
bool immediatebye;
};
/** This class determines when RTCP compound packets should be sent. */
class JRTPLIB_IMPORTEXPORT RTCPScheduler
{
public:
/** Creates an instance which will use the source table RTPSources to determine when RTCP compound
* packets should be scheduled.
* Creates an instance which will use the source table RTPSources to determine when RTCP compound
* packets should be scheduled. Note that for correct operation the \c sources instance should have information
* about the own SSRC (added by RTPSources::CreateOwnSSRC). You must also supply a random number
* generator \c rtprand which will be used for adding randomness to the RTCP intervals.
*/
RTCPScheduler(RTPSources &sources, RTPRandom &rtprand);
~RTCPScheduler();
/** Resets the scheduler. */
void Reset();
/** Sets the scheduler parameters to be used to \c params. */
void SetParameters(const RTCPSchedulerParams &params) { schedparams = params; }
/** Returns the currently used scheduler parameters. */
RTCPSchedulerParams GetParameters() const { return schedparams; }
/** Sets the header overhead from underlying protocols (for example UDP and IP) to \c numbytes. */
void SetHeaderOverhead(size_t numbytes) { headeroverhead = numbytes; }
/** Returns the currently used header overhead. */
size_t GetHeaderOverhead() const { return headeroverhead; }
/** For each incoming RTCP compound packet, this function has to be called for the scheduler to work correctly. */
void AnalyseIncoming(RTCPCompoundPacket &rtcpcomppack);
/** For each outgoing RTCP compound packet, this function has to be called for the scheduler to work correctly. */
void AnalyseOutgoing(RTCPCompoundPacket &rtcpcomppack);
/** This function has to be called each time a member times out or sends a BYE packet. */
void ActiveMemberDecrease();
/** Asks the scheduler to schedule an RTCP compound packet containing a BYE packetl; the compound packet
* has size \c packetsize.
*/
void ScheduleBYEPacket(size_t packetsize);
/** Returns the delay after which an RTCP compound will possibly have to be sent.
* Returns the delay after which an RTCP compound will possibly have to be sent. The IsTime member function
* should be called afterwards to make sure that it actually is time to send an RTCP compound packet.
*/
RTPTime GetTransmissionDelay();
/** This function returns \c true if it's time to send an RTCP compound packet and \c false otherwise.
* This function returns \c true if it's time to send an RTCP compound packet and \c false otherwise.
* If the function returns \c true, it will also have calculated the next time at which a packet should
* be sent, so if it is called again right away, it will return \c false.
*/
bool IsTime();
/** Calculates the deterministic interval at this time.
* Calculates the deterministic interval at this time. This is used - in combination with a certain multiplier -
* to time out members, senders etc.
*/
RTPTime CalculateDeterministicInterval(bool sender = false);
private:
void CalculateNextRTCPTime();
void PerformReverseReconsideration();
RTPTime CalculateBYETransmissionInterval();
RTPTime CalculateTransmissionInterval(bool sender);
RTPSources &sources;
RTCPSchedulerParams schedparams;
size_t headeroverhead;
size_t avgrtcppacksize;
bool hassentrtcp;
bool firstcall;
RTPTime nextrtcptime;
RTPTime prevrtcptime;
int pmembers;
// for BYE packet scheduling
bool byescheduled;
int byemembers,pbyemembers;
size_t avgbyepacketsize;
bool sendbyenow;
RTPRandom &rtprand;
};
} // end namespace
#endif // RTCPSCHEDULER_H

180
qrtplib/rtcpsdesinfo.cpp Normal file
View File

@ -0,0 +1,180 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpsdesinfo.h"
namespace qrtplib
{
void RTCPSDESInfo::Clear()
{
#ifdef RTP_SUPPORT_SDESPRIV
std::list<SDESPrivateItem *>::const_iterator it;
for (it = privitems.begin() ; it != privitems.end() ; ++it)
RTPDelete(*it,GetMemoryManager());
privitems.clear();
#endif // RTP_SUPPORT_SDESPRIV
}
#ifdef RTP_SUPPORT_SDESPRIV
int RTCPSDESInfo::SetPrivateValue(const uint8_t *prefix,size_t prefixlen,const uint8_t *value,size_t valuelen)
{
std::list<SDESPrivateItem *>::const_iterator it;
bool found;
found = false;
it = privitems.begin();
while (!found && it != privitems.end())
{
uint8_t *p;
size_t l;
p = (*it)->GetPrefix(&l);
if (l == prefixlen)
{
if (l <= 0)
found = true;
else if (memcmp(prefix,p,l) == 0)
found = true;
else
++it;
}
else
++it;
}
SDESPrivateItem *item;
if (found) // replace the value for this entry
item = *it;
else // no entry for this prefix found... add it
{
if (privitems.size() >= RTP_MAXPRIVITEMS) // too many items present, just ignore it
return ERR_RTP_SDES_MAXPRIVITEMS;
int status;
item = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_SDESPRIVATEITEM) SDESPrivateItem(GetMemoryManager());
if (item == 0)
return ERR_RTP_OUTOFMEM;
if ((status = item->SetPrefix(prefix,prefixlen)) < 0)
{
RTPDelete(item,GetMemoryManager());
return status;
}
privitems.push_front(item);
}
return item->SetInfo(value,valuelen);
}
int RTCPSDESInfo::DeletePrivatePrefix(const uint8_t *prefix,size_t prefixlen)
{
std::list<SDESPrivateItem *>::iterator it;
bool found;
found = false;
it = privitems.begin();
while (!found && it != privitems.end())
{
uint8_t *p;
size_t l;
p = (*it)->GetPrefix(&l);
if (l == prefixlen)
{
if (l <= 0)
found = true;
else if (memcmp(prefix,p,l) == 0)
found = true;
else
++it;
}
else
++it;
}
if (!found)
return ERR_RTP_SDES_PREFIXNOTFOUND;
RTPDelete(*it,GetMemoryManager());
privitems.erase(it);
return 0;
}
void RTCPSDESInfo::GotoFirstPrivateValue()
{
curitem = privitems.begin();
}
bool RTCPSDESInfo::GetNextPrivateValue(uint8_t **prefix,size_t *prefixlen,uint8_t **value,size_t *valuelen)
{
if (curitem == privitems.end())
return false;
*prefix = (*curitem)->GetPrefix(prefixlen);
*value = (*curitem)->GetInfo(valuelen);
++curitem;
return true;
}
bool RTCPSDESInfo::GetPrivateValue(const uint8_t *prefix,size_t prefixlen,uint8_t **value,size_t *valuelen) const
{
std::list<SDESPrivateItem *>::const_iterator it;
bool found;
found = false;
it = privitems.begin();
while (!found && it != privitems.end())
{
uint8_t *p;
size_t l;
p = (*it)->GetPrefix(&l);
if (l == prefixlen)
{
if (l <= 0)
found = true;
else if (memcmp(prefix,p,l) == 0)
found = true;
else
++it;
}
else
++it;
}
if (found)
*value = (*it)->GetInfo(valuelen);
return found;
}
#endif // RTP_SUPPORT_SDESPRIV
} // end namespace

220
qrtplib/rtcpsdesinfo.h Normal file
View File

@ -0,0 +1,220 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpsdesinfo.h
*/
#ifndef RTCPSDESINFO_H
#define RTCPSDESINFO_H
#include "rtpconfig.h"
#include "rtperrors.h"
#include "rtpdefines.h"
#include "rtptypes.h"
#include "rtpmemoryobject.h"
#include <string.h>
#include <list>
namespace qrtplib
{
/** The class RTCPSDESInfo is a container for RTCP SDES information. */
class JRTPLIB_IMPORTEXPORT RTCPSDESInfo : public RTPMemoryObject
{
public:
/** Constructs an instance, optionally installing a memory manager. */
RTCPSDESInfo(RTPMemoryManager *mgr = 0) : RTPMemoryObject(mgr) { for (int i = 0 ; i < RTCP_SDES_NUMITEMS_NONPRIVATE ; i++) nonprivateitems[i].SetMemoryManager(mgr); }
virtual ~RTCPSDESInfo() { Clear(); }
/** Clears all SDES information. */
void Clear();
/** Sets the SDES CNAME item to \c s with length \c l. */
int SetCNAME(const uint8_t *s,size_t l) { return SetNonPrivateItem(RTCP_SDES_ID_CNAME-1,s,l); }
/** Sets the SDES name item to \c s with length \c l. */
int SetName(const uint8_t *s,size_t l) { return SetNonPrivateItem(RTCP_SDES_ID_NAME-1,s,l); }
/** Sets the SDES e-mail item to \c s with length \c l. */
int SetEMail(const uint8_t *s,size_t l) { return SetNonPrivateItem(RTCP_SDES_ID_EMAIL-1,s,l); }
/** Sets the SDES phone item to \c s with length \c l. */
int SetPhone(const uint8_t *s,size_t l) { return SetNonPrivateItem(RTCP_SDES_ID_PHONE-1,s,l); }
/** Sets the SDES location item to \c s with length \c l. */
int SetLocation(const uint8_t *s,size_t l) { return SetNonPrivateItem(RTCP_SDES_ID_LOCATION-1,s,l); }
/** Sets the SDES tool item to \c s with length \c l. */
int SetTool(const uint8_t *s,size_t l) { return SetNonPrivateItem(RTCP_SDES_ID_TOOL-1,s,l); }
/** Sets the SDES note item to \c s with length \c l. */
int SetNote(const uint8_t *s,size_t l) { return SetNonPrivateItem(RTCP_SDES_ID_NOTE-1,s,l); }
#ifdef RTP_SUPPORT_SDESPRIV
/** Sets the entry for the prefix string specified by \c prefix with length \c prefixlen to contain
* the value string specified by \c value with length \c valuelen (if the maximum allowed
* number of prefixes was reached, the error code \c ERR_RTP_SDES_MAXPRIVITEMS is returned.
*/
int SetPrivateValue(const uint8_t *prefix,size_t prefixlen,const uint8_t *value,size_t valuelen);
/** Deletes the entry for the prefix specified by \c s with length \c len. */
int DeletePrivatePrefix(const uint8_t *s,size_t len);
#endif // RTP_SUPPORT_SDESPRIV
/** Returns the SDES CNAME item and stores its length in \c len. */
uint8_t *GetCNAME(size_t *len) const { return GetNonPrivateItem(RTCP_SDES_ID_CNAME-1,len); }
/** Returns the SDES name item and stores its length in \c len. */
uint8_t *GetName(size_t *len) const { return GetNonPrivateItem(RTCP_SDES_ID_NAME-1,len); }
/** Returns the SDES e-mail item and stores its length in \c len. */
uint8_t *GetEMail(size_t *len) const { return GetNonPrivateItem(RTCP_SDES_ID_EMAIL-1,len); }
/** Returns the SDES phone item and stores its length in \c len. */
uint8_t *GetPhone(size_t *len) const { return GetNonPrivateItem(RTCP_SDES_ID_PHONE-1,len); }
/** Returns the SDES location item and stores its length in \c len. */
uint8_t *GetLocation(size_t *len) const { return GetNonPrivateItem(RTCP_SDES_ID_LOCATION-1,len); }
/** Returns the SDES tool item and stores its length in \c len. */
uint8_t *GetTool(size_t *len) const { return GetNonPrivateItem(RTCP_SDES_ID_TOOL-1,len); }
/** Returns the SDES note item and stores its length in \c len. */
uint8_t *GetNote(size_t *len) const { return GetNonPrivateItem(RTCP_SDES_ID_NOTE-1,len); }
#ifdef RTP_SUPPORT_SDESPRIV
/** Starts the iteration over the stored SDES private item prefixes and their associated values. */
void GotoFirstPrivateValue();
/** Returns SDES priv item information.
* If available, returns \c true and stores the next SDES
* private item prefix in \c prefix and its length in
* \c prefixlen. The associated value and its length are
* then stored in \c value and \c valuelen. Otherwise,
* it returns \c false.
*/
bool GetNextPrivateValue(uint8_t **prefix,size_t *prefixlen,uint8_t **value,size_t *valuelen);
/** Returns SDES priv item information.
* Looks for the entry which corresponds to the SDES private
* item prefix \c prefix with length \c prefixlen. If found,
* the function returns \c true and stores the associated
* value and its length in \c value and \c valuelen
* respectively.
*/
bool GetPrivateValue(const uint8_t *prefix,size_t prefixlen,uint8_t **value,size_t *valuelen) const;
#endif // RTP_SUPPORT_SDESPRIV
private:
int SetNonPrivateItem(int itemno,const uint8_t *s,size_t l) { if (l > RTCP_SDES_MAXITEMLENGTH) return ERR_RTP_SDES_LENGTHTOOBIG; return nonprivateitems[itemno].SetInfo(s,l); }
uint8_t *GetNonPrivateItem(int itemno,size_t *len) const { return nonprivateitems[itemno].GetInfo(len); }
class SDESItem : public RTPMemoryObject
{
public:
SDESItem(RTPMemoryManager *mgr = 0) : RTPMemoryObject(mgr)
{
str = 0;
length = 0;
}
void SetMemoryManager(RTPMemoryManager *mgr)
{
RTPMemoryObject::SetMemoryManager(mgr);
}
~SDESItem()
{
if (str)
RTPDeleteByteArray(str,GetMemoryManager());
}
uint8_t *GetInfo(size_t *len) const { *len = length; return str; }
int SetInfo(const uint8_t *s,size_t len) { return SetString(&str,&length,s,len); }
protected:
int SetString(uint8_t **dest,size_t *destlen,const uint8_t *s,size_t len)
{
if (len <= 0)
{
if (*dest)
RTPDeleteByteArray((*dest),GetMemoryManager());
*dest = 0;
*destlen = 0;
}
else
{
len = (len>RTCP_SDES_MAXITEMLENGTH)?RTCP_SDES_MAXITEMLENGTH:len;
uint8_t *str2 = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_SDESITEM) uint8_t[len];
if (str2 == 0)
return ERR_RTP_OUTOFMEM;
memcpy(str2,s,len);
*destlen = len;
if (*dest)
RTPDeleteByteArray((*dest),GetMemoryManager());
*dest = str2;
}
return 0;
}
private:
uint8_t *str;
size_t length;
};
SDESItem nonprivateitems[RTCP_SDES_NUMITEMS_NONPRIVATE];
#ifdef RTP_SUPPORT_SDESPRIV
class SDESPrivateItem : public SDESItem
{
public:
SDESPrivateItem(RTPMemoryManager *mgr) : SDESItem(mgr)
{
prefixlen = 0;
prefix = 0;
}
~SDESPrivateItem()
{
if (prefix)
RTPDeleteByteArray(prefix,GetMemoryManager());
}
uint8_t *GetPrefix(size_t *len) const { *len = prefixlen; return prefix; }
int SetPrefix(const uint8_t *s,size_t len) { return SetString(&prefix,&prefixlen,s,len); }
private:
uint8_t *prefix;
size_t prefixlen;
};
std::list<SDESPrivateItem *> privitems;
std::list<SDESPrivateItem *>::const_iterator curitem;
#endif // RTP_SUPPORT_SDESPRIV
};
} // end namespace
#endif // RTCPSDESINFO_H

141
qrtplib/rtcpsdespacket.cpp Normal file
View File

@ -0,0 +1,141 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpsdespacket.h"
namespace qrtplib
{
RTCPSDESPacket::RTCPSDESPacket(uint8_t *data,size_t datalength)
: RTCPPacket(SDES,data,datalength)
{
knownformat = false;
currentchunk = 0;
itemoffset = 0;
curchunknum = 0;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)data;
size_t len = datalength;
if (hdr->padding)
{
uint8_t padcount = data[datalength-1];
if ((padcount & 0x03) != 0) // not a multiple of four! (see rfc 3550 p 37)
return;
if (((size_t)padcount) >= len)
return;
len -= (size_t)padcount;
}
if (hdr->count == 0)
{
if (len != sizeof(RTCPCommonHeader))
return;
}
else
{
int ssrccount = (int)(hdr->count);
uint8_t *chunk;
int chunkoffset;
if (len < sizeof(RTCPCommonHeader))
return;
len -= sizeof(RTCPCommonHeader);
chunk = data+sizeof(RTCPCommonHeader);
while ((ssrccount > 0) && (len > 0))
{
if (len < (sizeof(uint32_t)*2)) // chunk must contain at least a SSRC identifier
return; // and a (possibly empty) item
len -= sizeof(uint32_t);
chunkoffset = sizeof(uint32_t);
bool done = false;
while (!done)
{
if (len < 1) // at least a zero byte (end of item list) should be there
return;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(chunk+chunkoffset);
if (sdeshdr->sdesid == 0) // end of item list
{
len--;
chunkoffset++;
size_t r = (chunkoffset&0x03);
if (r != 0)
{
size_t addoffset = 4-r;
if (addoffset > len)
return;
len -= addoffset;
chunkoffset += addoffset;
}
done = true;
}
else
{
if (len < sizeof(RTCPSDESHeader))
return;
len -= sizeof(RTCPSDESHeader);
chunkoffset += sizeof(RTCPSDESHeader);
size_t itemlen = (size_t)(sdeshdr->length);
if (itemlen > len)
return;
len -= itemlen;
chunkoffset += itemlen;
}
}
ssrccount--;
chunk += chunkoffset;
}
// check for remaining bytes
if (len > 0)
return;
if (ssrccount > 0)
return;
}
knownformat = true;
}
} // end namespace

383
qrtplib/rtcpsdespacket.h Normal file
View File

@ -0,0 +1,383 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpsdespacket.h
*/
#ifndef RTCPSDESPACKET_H
#define RTCPSDESPACKET_H
#include "rtpconfig.h"
#include "rtcppacket.h"
#include "rtpstructs.h"
#include "rtpdefines.h"
#ifdef RTP_SUPPORT_NETINET_IN
#include <netinet/in.h>
#endif // RTP_SUPPORT_NETINET_IN
namespace qrtplib
{
class RTCPCompoundPacket;
/** Describes an RTCP source description packet. */
class JRTPLIB_IMPORTEXPORT RTCPSDESPacket : public RTCPPacket
{
public:
/** Identifies the type of an SDES item. */
enum ItemType
{
None, /**< Used when the iteration over the items has finished. */
CNAME, /**< Used for a CNAME (canonical name) item. */
NAME, /**< Used for a NAME item. */
EMAIL, /**< Used for an EMAIL item. */
PHONE, /**< Used for a PHONE item. */
LOC, /**< Used for a LOC (location) item. */
TOOL, /**< Used for a TOOL item. */
NOTE, /**< Used for a NOTE item. */
PRIV, /**< Used for a PRIV item. */
Unknown /**< Used when there is an item present, but the type is not recognized. */
};
/** Creates an instance based on the data in \c data with length \c datalen.
* Creates an instance based on the data in \c data with length \c datalen. Since the \c data pointer
* is referenced inside the class (no copy of the data is made) one must make sure that the memory it
* points to is valid as long as the class instance exists.
*/
RTCPSDESPacket(uint8_t *data,size_t datalen);
~RTCPSDESPacket() { }
/** Returns the number of SDES chunks in the SDES packet.
* Returns the number of SDES chunks in the SDES packet. Each chunk has its own SSRC identifier.
*/
int GetChunkCount() const;
/** Starts the iteration over the chunks.
* Starts the iteration. If no SDES chunks are present, the function returns \c false. Otherwise,
* it returns \c true and sets the current chunk to be the first chunk.
*/
bool GotoFirstChunk();
/** Sets the current chunk to the next available chunk.
* Sets the current chunk to the next available chunk. If no next chunk is present, this function returns
* \c false, otherwise it returns \c true.
*/
bool GotoNextChunk();
/** Returns the SSRC identifier of the current chunk. */
uint32_t GetChunkSSRC() const;
/** Starts the iteration over the SDES items in the current chunk.
* Starts the iteration over the SDES items in the current chunk. If no SDES items are
* present, the function returns \c false. Otherwise, the function sets the current item
* to be the first one and returns \c true.
*/
bool GotoFirstItem();
/** Advances the iteration to the next item in the current chunk.
* If there's another item in the chunk, the current item is set to be the next one and the function
* returns \c true. Otherwise, the function returns \c false.
*/
bool GotoNextItem();
/** Returns the SDES item type of the current item in the current chunk. */
ItemType GetItemType() const;
/** Returns the item length of the current item in the current chunk. */
size_t GetItemLength() const;
/** Returns the item data of the current item in the current chunk. */
uint8_t *GetItemData();
#ifdef RTP_SUPPORT_SDESPRIV
/** If the current item is an SDES PRIV item, this function returns the length of the
* prefix string of the private item.
*/
size_t GetPRIVPrefixLength() const;
/** If the current item is an SDES PRIV item, this function returns actual data of the
* prefix string.
*/
uint8_t *GetPRIVPrefixData();
/** If the current item is an SDES PRIV item, this function returns the length of the
* value string of the private item.
*/
size_t GetPRIVValueLength() const;
/** If the current item is an SDES PRIV item, this function returns actual value data of the
* private item.
*/
uint8_t *GetPRIVValueData();
#endif // RTP_SUPPORT_SDESPRIV
private:
uint8_t *currentchunk;
int curchunknum;
size_t itemoffset;
};
inline int RTCPSDESPacket::GetChunkCount() const
{
if (!knownformat)
return 0;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)data;
return ((int)hdr->count);
}
inline bool RTCPSDESPacket::GotoFirstChunk()
{
if (GetChunkCount() == 0)
{
currentchunk = 0;
return false;
}
currentchunk = data+sizeof(RTCPCommonHeader);
curchunknum = 1;
itemoffset = sizeof(uint32_t);
return true;
}
inline bool RTCPSDESPacket::GotoNextChunk()
{
if (!knownformat)
return false;
if (currentchunk == 0)
return false;
if (curchunknum == GetChunkCount())
return false;
size_t offset = sizeof(uint32_t);
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+sizeof(uint32_t));
while (sdeshdr->sdesid != 0)
{
offset += sizeof(RTCPSDESHeader);
offset += (size_t)(sdeshdr->length);
sdeshdr = (RTCPSDESHeader *)(currentchunk+offset);
}
offset++; // for the zero byte
if ((offset&0x03) != 0)
offset += (4-(offset&0x03));
currentchunk += offset;
curchunknum++;
itemoffset = sizeof(uint32_t);
return true;
}
inline uint32_t RTCPSDESPacket::GetChunkSSRC() const
{
if (!knownformat)
return 0;
if (currentchunk == 0)
return 0;
uint32_t *ssrc = (uint32_t *)currentchunk;
return ntohl(*ssrc);
}
inline bool RTCPSDESPacket::GotoFirstItem()
{
if (!knownformat)
return false;
if (currentchunk == 0)
return false;
itemoffset = sizeof(uint32_t);
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid == 0)
return false;
return true;
}
inline bool RTCPSDESPacket::GotoNextItem()
{
if (!knownformat)
return false;
if (currentchunk == 0)
return false;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid == 0)
return false;
size_t offset = itemoffset;
offset += sizeof(RTCPSDESHeader);
offset += (size_t)(sdeshdr->length);
sdeshdr = (RTCPSDESHeader *)(currentchunk+offset);
if (sdeshdr->sdesid == 0)
return false;
itemoffset = offset;
return true;
}
inline RTCPSDESPacket::ItemType RTCPSDESPacket::GetItemType() const
{
if (!knownformat)
return None;
if (currentchunk == 0)
return None;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
switch (sdeshdr->sdesid)
{
case 0:
return None;
case RTCP_SDES_ID_CNAME:
return CNAME;
case RTCP_SDES_ID_NAME:
return NAME;
case RTCP_SDES_ID_EMAIL:
return EMAIL;
case RTCP_SDES_ID_PHONE:
return PHONE;
case RTCP_SDES_ID_LOCATION:
return LOC;
case RTCP_SDES_ID_TOOL:
return TOOL;
case RTCP_SDES_ID_NOTE:
return NOTE;
case RTCP_SDES_ID_PRIVATE:
return PRIV;
default:
return Unknown;
}
return Unknown;
}
inline size_t RTCPSDESPacket::GetItemLength() const
{
if (!knownformat)
return None;
if (currentchunk == 0)
return None;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid == 0)
return 0;
return (size_t)(sdeshdr->length);
}
inline uint8_t *RTCPSDESPacket::GetItemData()
{
if (!knownformat)
return 0;
if (currentchunk == 0)
return 0;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid == 0)
return 0;
return (currentchunk+itemoffset+sizeof(RTCPSDESHeader));
}
#ifdef RTP_SUPPORT_SDESPRIV
inline size_t RTCPSDESPacket::GetPRIVPrefixLength() const
{
if (!knownformat)
return 0;
if (currentchunk == 0)
return 0;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid != RTCP_SDES_ID_PRIVATE)
return 0;
if (sdeshdr->length == 0)
return 0;
uint8_t *preflen = currentchunk+itemoffset+sizeof(RTCPSDESHeader);
size_t prefixlength = (size_t)(*preflen);
if (prefixlength > (size_t)((sdeshdr->length)-1))
return 0;
return prefixlength;
}
inline uint8_t *RTCPSDESPacket::GetPRIVPrefixData()
{
if (!knownformat)
return 0;
if (currentchunk == 0)
return 0;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid != RTCP_SDES_ID_PRIVATE)
return 0;
if (sdeshdr->length == 0)
return 0;
uint8_t *preflen = currentchunk+itemoffset+sizeof(RTCPSDESHeader);
size_t prefixlength = (size_t)(*preflen);
if (prefixlength > (size_t)((sdeshdr->length)-1))
return 0;
if (prefixlength == 0)
return 0;
return (currentchunk+itemoffset+sizeof(RTCPSDESHeader)+1);
}
inline size_t RTCPSDESPacket::GetPRIVValueLength() const
{
if (!knownformat)
return 0;
if (currentchunk == 0)
return 0;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid != RTCP_SDES_ID_PRIVATE)
return 0;
if (sdeshdr->length == 0)
return 0;
uint8_t *preflen = currentchunk+itemoffset+sizeof(RTCPSDESHeader);
size_t prefixlength = (size_t)(*preflen);
if (prefixlength > (size_t)((sdeshdr->length)-1))
return 0;
return ((size_t)(sdeshdr->length))-prefixlength-1;
}
inline uint8_t *RTCPSDESPacket::GetPRIVValueData()
{
if (!knownformat)
return 0;
if (currentchunk == 0)
return 0;
RTCPSDESHeader *sdeshdr = (RTCPSDESHeader *)(currentchunk+itemoffset);
if (sdeshdr->sdesid != RTCP_SDES_ID_PRIVATE)
return 0;
if (sdeshdr->length == 0)
return 0;
uint8_t *preflen = currentchunk+itemoffset+sizeof(RTCPSDESHeader);
size_t prefixlength = (size_t)(*preflen);
if (prefixlength > (size_t)((sdeshdr->length)-1))
return 0;
size_t valuelen = ((size_t)(sdeshdr->length))-prefixlength-1;
if (valuelen == 0)
return 0;
return (currentchunk+itemoffset+sizeof(RTCPSDESHeader)+1+prefixlength);
}
#endif // RTP_SUPPORT_SDESPRIV
} // end namespace
#endif // RTCPSDESPACKET_H

69
qrtplib/rtcpsrpacket.cpp Normal file
View File

@ -0,0 +1,69 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtcpsrpacket.h"
namespace qrtplib
{
RTCPSRPacket::RTCPSRPacket(uint8_t *data,size_t datalength)
: RTCPPacket(SR,data,datalength)
{
knownformat = false;
RTCPCommonHeader *hdr;
size_t len = datalength;
size_t expectedlength;
hdr = (RTCPCommonHeader *)data;
if (hdr->padding)
{
uint8_t padcount = data[datalength-1];
if ((padcount & 0x03) != 0) // not a multiple of four! (see rfc 3550 p 37)
return;
if (((size_t)padcount) >= len)
return;
len -= (size_t)padcount;
}
expectedlength = sizeof(RTCPCommonHeader)+sizeof(uint32_t)+sizeof(RTCPSenderReport);
expectedlength += sizeof(RTCPReceiverReport)*((int)hdr->count);
if (expectedlength != len)
return;
knownformat = true;
}
} // end namespace

249
qrtplib/rtcpsrpacket.h Normal file
View File

@ -0,0 +1,249 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpsrpacket.h
*/
#ifndef RTCPSRPACKET_H
#define RTCPSRPACKET_H
#include "rtpconfig.h"
#include "rtcppacket.h"
#include "rtptimeutilities.h"
#include "rtpstructs.h"
#ifdef RTP_SUPPORT_NETINET_IN
#include <netinet/in.h>
#endif // RTP_SUPPORT_NETINET_IN
namespace qrtplib
{
class RTCPCompoundPacket;
/** Describes an RTCP sender report packet. */
class JRTPLIB_IMPORTEXPORT RTCPSRPacket : public RTCPPacket
{
public:
/** Creates an instance based on the data in \c data with length \c datalen.
* Creates an instance based on the data in \c data with length \c datalen. Since the \c data pointer
* is referenced inside the class (no copy of the data is made) one must make sure that the memory it
* points to is valid as long as the class instance exists.
*/
RTCPSRPacket(uint8_t *data,size_t datalength);
~RTCPSRPacket() { }
/** Returns the SSRC of the participant who sent this packet. */
uint32_t GetSenderSSRC() const;
/** Returns the NTP timestamp contained in the sender report. */
RTPNTPTime GetNTPTimestamp() const;
/** Returns the RTP timestamp contained in the sender report. */
uint32_t GetRTPTimestamp() const;
/** Returns the sender's packet count contained in the sender report. */
uint32_t GetSenderPacketCount() const;
/** Returns the sender's octet count contained in the sender report. */
uint32_t GetSenderOctetCount() const;
/** Returns the number of reception report blocks present in this packet. */
int GetReceptionReportCount() const;
/** Returns the SSRC of the reception report block described by \c index which may have a value
* from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetSSRC(int index) const;
/** Returns the `fraction lost' field of the reception report described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint8_t GetFractionLost(int index) const;
/** Returns the number of lost packets in the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
int32_t GetLostPacketCount(int index) const;
/** Returns the extended highest sequence number of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetExtendedHighestSequenceNumber(int index) const;
/** Returns the jitter field of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetJitter(int index) const;
/** Returns the LSR field of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetLSR(int index) const;
/** Returns the DLSR field of the reception report block described by \c index which may have
* a value from 0 to GetReceptionReportCount()-1 (note that no check is performed to see if \c index is
* valid).
*/
uint32_t GetDLSR(int index) const;
private:
RTCPReceiverReport *GotoReport(int index) const;
};
inline uint32_t RTCPSRPacket::GetSenderSSRC() const
{
if (!knownformat)
return 0;
uint32_t *ssrcptr = (uint32_t *)(data+sizeof(RTCPCommonHeader));
return ntohl(*ssrcptr);
}
inline RTPNTPTime RTCPSRPacket::GetNTPTimestamp() const
{
if (!knownformat)
return RTPNTPTime(0,0);
RTCPSenderReport *sr = (RTCPSenderReport *)(data+sizeof(RTCPCommonHeader)+sizeof(uint32_t));
return RTPNTPTime(ntohl(sr->ntptime_msw),ntohl(sr->ntptime_lsw));
}
inline uint32_t RTCPSRPacket::GetRTPTimestamp() const
{
if (!knownformat)
return 0;
RTCPSenderReport *sr = (RTCPSenderReport *)(data+sizeof(RTCPCommonHeader)+sizeof(uint32_t));
return ntohl(sr->rtptimestamp);
}
inline uint32_t RTCPSRPacket::GetSenderPacketCount() const
{
if (!knownformat)
return 0;
RTCPSenderReport *sr = (RTCPSenderReport *)(data+sizeof(RTCPCommonHeader)+sizeof(uint32_t));
return ntohl(sr->packetcount);
}
inline uint32_t RTCPSRPacket::GetSenderOctetCount() const
{
if (!knownformat)
return 0;
RTCPSenderReport *sr = (RTCPSenderReport *)(data+sizeof(RTCPCommonHeader)+sizeof(uint32_t));
return ntohl(sr->octetcount);
}
inline int RTCPSRPacket::GetReceptionReportCount() const
{
if (!knownformat)
return 0;
RTCPCommonHeader *hdr = (RTCPCommonHeader *)data;
return ((int)hdr->count);
}
inline RTCPReceiverReport *RTCPSRPacket::GotoReport(int index) const
{
RTCPReceiverReport *r = (RTCPReceiverReport *)(data+sizeof(RTCPCommonHeader)+sizeof(uint32_t)+sizeof(RTCPSenderReport)+index*sizeof(RTCPReceiverReport));
return r;
}
inline uint32_t RTCPSRPacket::GetSSRC(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->ssrc);
}
inline uint8_t RTCPSRPacket::GetFractionLost(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return r->fractionlost;
}
inline int32_t RTCPSRPacket::GetLostPacketCount(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
uint32_t count = ((uint32_t)r->packetslost[2])|(((uint32_t)r->packetslost[1])<<8)|(((uint32_t)r->packetslost[0])<<16);
if ((count&0x00800000) != 0) // test for negative number
count |= 0xFF000000;
int32_t *count2 = (int32_t *)(&count);
return (*count2);
}
inline uint32_t RTCPSRPacket::GetExtendedHighestSequenceNumber(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->exthighseqnr);
}
inline uint32_t RTCPSRPacket::GetJitter(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->jitter);
}
inline uint32_t RTCPSRPacket::GetLSR(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->lsr);
}
inline uint32_t RTCPSRPacket::GetDLSR(int index) const
{
if (!knownformat)
return 0;
RTCPReceiverReport *r = GotoReport(index);
return ntohl(r->dlsr);
}
} // end namespace
#endif // RTCPSRPACKET_H

View File

@ -0,0 +1,73 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtcpunknownpacket.h
*/
#ifndef RTCPUNKNOWNPACKET_H
#define RTCPUNKNOWNPACKET_H
#include "rtpconfig.h"
#include "rtcppacket.h"
namespace qrtplib
{
class RTCPCompoundPacket;
/** Describes an RTCP packet of unknown type.
* Describes an RTCP packet of unknown type. This class doesn't have any extra member functions besides
* the ones it inherited. Note that since an unknown packet type doesn't have any format to check
* against, the IsKnownFormat function will trivially return \c true.
*/
class JRTPLIB_IMPORTEXPORT RTCPUnknownPacket : public RTCPPacket
{
public:
/** Creates an instance based on the data in \c data with length \c datalen.
* Creates an instance based on the data in \c data with length \c datalen. Since the \c data pointer
* is referenced inside the class (no copy of the data is made) one must make sure that the memory it
* points to is valid as long as the class instance exists.
*/
RTCPUnknownPacket(uint8_t *data,size_t datalen) : RTCPPacket(Unknown,data,datalen)
{
// Since we don't expect a format, we'll trivially put knownformat = true
knownformat = true;
}
~RTCPUnknownPacket() { }
};
} // end namespace
#endif // RTCPUNKNOWNPACKET_H

View File

@ -0,0 +1,258 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpabortdescriptors.h"
#include "rtpsocketutilinternal.h"
#include "rtperrors.h"
#include "rtpselect.h"
namespace qrtplib
{
RTPAbortDescriptors::RTPAbortDescriptors()
{
m_descriptors[0] = RTPSOCKERR;
m_descriptors[1] = RTPSOCKERR;
m_init = false;
}
RTPAbortDescriptors::~RTPAbortDescriptors()
{
Destroy();
}
#ifdef RTP_SOCKETTYPE_WINSOCK
int RTPAbortDescriptors::Init()
{
if (m_init)
return ERR_RTP_ABORTDESC_ALREADYINIT;
SOCKET listensock;
int size;
struct sockaddr_in addr;
listensock = socket(PF_INET,SOCK_STREAM,0);
if (listensock == RTPSOCKERR)
return ERR_RTP_ABORTDESC_CANTCREATEABORTDESCRIPTORS;
memset(&addr,0,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
if (bind(listensock,(struct sockaddr *)&addr,sizeof(struct sockaddr_in)) != 0)
{
RTPCLOSE(listensock);
return ERR_RTP_ABORTDESC_CANTCREATEABORTDESCRIPTORS;
}
memset(&addr,0,sizeof(struct sockaddr_in));
size = sizeof(struct sockaddr_in);
if (getsockname(listensock,(struct sockaddr*)&addr,&size) != 0)
{
RTPCLOSE(listensock);
return ERR_RTP_ABORTDESC_CANTCREATEABORTDESCRIPTORS;
}
unsigned short connectport = ntohs(addr.sin_port);
m_descriptors[0] = socket(PF_INET,SOCK_STREAM,0);
if (m_descriptors[0] == RTPSOCKERR)
{
RTPCLOSE(listensock);
return ERR_RTP_ABORTDESC_CANTCREATEABORTDESCRIPTORS;
}
memset(&addr,0,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
if (bind(m_descriptors[0],(struct sockaddr *)&addr,sizeof(struct sockaddr_in)) != 0)
{
RTPCLOSE(listensock);
RTPCLOSE(m_descriptors[0]);
return ERR_RTP_ABORTDESC_CANTCREATEABORTDESCRIPTORS;
}
if (listen(listensock,1) != 0)
{
RTPCLOSE(listensock);
RTPCLOSE(m_descriptors[0]);
return ERR_RTP_ABORTDESC_CANTCREATEABORTDESCRIPTORS;
}
memset(&addr,0,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(connectport);
if (connect(m_descriptors[0],(struct sockaddr *)&addr,sizeof(struct sockaddr_in)) != 0)
{
RTPCLOSE(listensock);
RTPCLOSE(m_descriptors[0]);
return ERR_RTP_ABORTDESC_CANTCREATEABORTDESCRIPTORS;
}
memset(&addr,0,sizeof(struct sockaddr_in));
size = sizeof(struct sockaddr_in);
m_descriptors[1] = accept(listensock,(struct sockaddr *)&addr,&size);
if (m_descriptors[1] == RTPSOCKERR)
{
RTPCLOSE(listensock);
RTPCLOSE(m_descriptors[0]);
return ERR_RTP_ABORTDESC_CANTCREATEABORTDESCRIPTORS;
}
// okay, got the connection, close the listening socket
RTPCLOSE(listensock);
m_init = true;
return 0;
}
void RTPAbortDescriptors::Destroy()
{
if (!m_init)
return;
RTPCLOSE(m_descriptors[0]);
RTPCLOSE(m_descriptors[1]);
m_descriptors[0] = RTPSOCKERR;
m_descriptors[1] = RTPSOCKERR;
m_init = false;
}
int RTPAbortDescriptors::SendAbortSignal()
{
if (!m_init)
return ERR_RTP_ABORTDESC_NOTINIT;
send(m_descriptors[1],"*",1,0);
return 0;
}
int RTPAbortDescriptors::ReadSignallingByte()
{
if (!m_init)
return ERR_RTP_ABORTDESC_NOTINIT;
char buf[1];
recv(m_descriptors[0],buf,1,0);
return 0;
}
#else // unix-style
int RTPAbortDescriptors::Init()
{
if (m_init)
return ERR_RTP_ABORTDESC_ALREADYINIT;
if (pipe(m_descriptors) < 0)
return ERR_RTP_ABORTDESC_CANTCREATEPIPE;
m_init = true;
return 0;
}
void RTPAbortDescriptors::Destroy()
{
if (!m_init)
return;
close(m_descriptors[0]);
close(m_descriptors[1]);
m_descriptors[0] = RTPSOCKERR;
m_descriptors[1] = RTPSOCKERR;
m_init = false;
}
int RTPAbortDescriptors::SendAbortSignal()
{
if (!m_init)
return ERR_RTP_ABORTDESC_NOTINIT;
if (write(m_descriptors[1],"*",1))
{
// To get rid of __wur related compiler warnings
}
return 0;
}
int RTPAbortDescriptors::ReadSignallingByte()
{
if (!m_init)
return ERR_RTP_ABORTDESC_NOTINIT;
unsigned char buf[1];
if (read(m_descriptors[0],buf,1))
{
// To get rid of __wur related compiler warnings
}
return 0;
}
#endif // RTP_SOCKETTYPE_WINSOCK
// Keep calling 'ReadSignallingByte' until there's no byte left
int RTPAbortDescriptors::ClearAbortSignal()
{
if (!m_init)
return ERR_RTP_ABORTDESC_NOTINIT;
bool done = false;
while (!done)
{
int8_t isset = 0;
// Not used: struct timeval tv = { 0, 0 };
int status = RTPSelect(&m_descriptors[0], &isset, 1, RTPTime(0));
if (status < 0)
return status;
if (!isset)
done = true;
else
{
int status = ReadSignallingByte();
if (status < 0)
return status;
}
}
return 0;
}
} // end namespace

View File

@ -0,0 +1,103 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpabortdescriptors.h
*/
#ifndef RTPABORTDESCRIPTORS_H
#define RTPABORTDESCRIPTORS_H
#include "rtpconfig.h"
#include "rtpsocketutil.h"
namespace qrtplib
{
/**
* Helper class for several RTPTransmitter instances, to be able to cancel a
* call to 'select', 'poll' or 'WSAPoll'.
*
* This is a helper class for several RTPTransmitter instances. Typically a
* call to 'select' (or 'poll' or 'WSAPoll', depending on the platform) is used
* to wait for incoming data for a certain time. To be able to cancel this wait
* from another thread, this class provides a socket descriptor that's compatible
* with e.g. the 'select' call, and to which data can be sent using
* RTPAbortDescriptors::SendAbortSignal. If the descriptor is included in the
* 'select' call, the function will detect incoming data and the function stops
* waiting for incoming data.
*
* The class can be useful in case you'd like to create an implementation which
* uses a single poll thread for several RTPSession and RTPTransmitter instances.
* This idea is further illustrated in `example8.cpp`.
*/
class JRTPLIB_IMPORTEXPORT RTPAbortDescriptors
{
public:
RTPAbortDescriptors();
~RTPAbortDescriptors();
/** Initializes this instance. */
int Init();
/** Returns the socket descriptor that can be included in a call to
* 'select' (for example).*/
SocketType GetAbortSocket() const { return m_descriptors[0]; }
/** Returns a flag indicating if this instance was initialized. */
bool IsInitialized() const { return m_init; }
/** De-initializes this instance. */
void Destroy();
/** Send a signal to the socket that's returned by RTPAbortDescriptors::GetAbortSocket,
* causing the 'select' call to detect that data is available, making the call
* end. */
int SendAbortSignal();
/** For each RTPAbortDescriptors::SendAbortSignal function that's called, a call
* to this function can be made to clear the state again. */
int ReadSignallingByte();
/** Similar to ReadSignallingByte::ReadSignallingByte, this function clears the signalling
* state, but this also works independently from the amount of times that
* RTPAbortDescriptors::SendAbortSignal was called. */
int ClearAbortSignal();
private:
SocketType m_descriptors[2];
bool m_init;
};
} // end namespace
#endif // RTPABORTDESCRIPTORS_H

97
qrtplib/rtpaddress.h Normal file
View File

@ -0,0 +1,97 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpaddress.h
*/
#ifndef RTPADDRESS_H
#define RTPADDRESS_H
#include "rtpconfig.h"
#include <string>
namespace qrtplib
{
class RTPMemoryManager;
/** This class is an abstract class which is used to specify destinations, multicast groups etc. */
class JRTPLIB_IMPORTEXPORT RTPAddress
{
public:
/** Identifies the actual implementation being used. */
enum AddressType
{
IPv4Address, /**< Used by the UDP over IPv4 transmitter. */
IPv6Address, /**< Used by the UDP over IPv6 transmitter. */
ByteAddress, /**< A very general type of address, consisting of a port number and a number of bytes representing the host address. */
UserDefinedAddress, /**< Can be useful for a user-defined transmitter. */
TCPAddress /**< Used by the TCP transmitter. */
};
/** Returns the type of address the actual implementation represents. */
AddressType GetAddressType() const { return addresstype; }
/** Creates a copy of the RTPAddress instance.
* Creates a copy of the RTPAddress instance. If \c mgr is not NULL, the
* corresponding memory manager will be used to allocate the memory for the address
* copy.
*/
virtual RTPAddress *CreateCopy(RTPMemoryManager *mgr) const = 0;
/** Checks if the address \c addr is the same address as the one this instance represents.
* Checks if the address \c addr is the same address as the one this instance represents.
* Implementations must be able to handle a NULL argument.
*/
virtual bool IsSameAddress(const RTPAddress *addr) const = 0;
/** Checks if the address \c addr represents the same host as this instance.
* Checks if the address \c addr represents the same host as this instance. Implementations
* must be able to handle a NULL argument.
*/
virtual bool IsFromSameHost(const RTPAddress *addr) const = 0;
virtual ~RTPAddress() { }
protected:
// only allow subclasses to be created
RTPAddress(const AddressType t) : addresstype(t) { }
private:
const AddressType addresstype;
};
} // end namespace
#endif // RTPADDRESS_H

View File

@ -0,0 +1,81 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpbyteaddress.h"
#include "rtpmemorymanager.h"
namespace qrtplib
{
bool RTPByteAddress::IsSameAddress(const RTPAddress *addr) const
{
if (addr == 0)
return false;
if (addr->GetAddressType() != ByteAddress)
return false;
const RTPByteAddress *addr2 = (const RTPByteAddress *)addr;
if (addr2->addresslength != addresslength)
return false;
if (addresslength == 0 || (memcmp(hostaddress, addr2->hostaddress, addresslength) == 0))
{
if (port == addr2->port)
return true;
}
return false;
}
bool RTPByteAddress::IsFromSameHost(const RTPAddress *addr) const
{
if (addr == 0)
return false;
if (addr->GetAddressType() != ByteAddress)
return false;
const RTPByteAddress *addr2 = (const RTPByteAddress *)addr;
if (addr2->addresslength != addresslength)
return false;
if (addresslength == 0 || (memcmp(hostaddress, addr2->hostaddress, addresslength) == 0))
return true;
return false;
}
RTPAddress *RTPByteAddress::CreateCopy(RTPMemoryManager *mgr) const
{
JRTPLIB_UNUSED(mgr); // possibly unused
RTPByteAddress *a = RTPNew(mgr, RTPMEM_TYPE_CLASS_RTPADDRESS) RTPByteAddress(hostaddress, addresslength, port);
return a;
}
} // end namespace

91
qrtplib/rtpbyteaddress.h Normal file
View File

@ -0,0 +1,91 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpbyteaddress.h
*/
#ifndef RTPBYTEADDRESS_H
#define RTPBYTEADDRESS_H
#include "rtpconfig.h"
#include "rtpaddress.h"
#include "rtptypes.h"
#include <string.h>
#define RTPBYTEADDRESS_MAXLENGTH 128
namespace qrtplib
{
class RTPMemoryManager;
/** A very general kind of address consisting of a port number and a number of bytes describing the host address.
* A very general kind of address, consisting of a port number and a number of bytes describing the host address.
*/
class JRTPLIB_IMPORTEXPORT RTPByteAddress : public RTPAddress
{
public:
/** Creates an instance of the class using \c addrlen bytes of \c hostaddress as host identification,
* and using \c port as the port number. */
RTPByteAddress(const uint8_t hostaddress[RTPBYTEADDRESS_MAXLENGTH], size_t addrlen, uint16_t port = 0) : RTPAddress(ByteAddress) { if (addrlen > RTPBYTEADDRESS_MAXLENGTH) addrlen = RTPBYTEADDRESS_MAXLENGTH; memcpy(RTPByteAddress::hostaddress, hostaddress, addrlen); RTPByteAddress::addresslength = addrlen; RTPByteAddress::port = port; }
/** Sets the host address to the first \c addrlen bytes of \c hostaddress. */
void SetHostAddress(const uint8_t hostaddress[RTPBYTEADDRESS_MAXLENGTH], size_t addrlen) { if (addrlen > RTPBYTEADDRESS_MAXLENGTH) addrlen = RTPBYTEADDRESS_MAXLENGTH; memcpy(RTPByteAddress::hostaddress, hostaddress, addrlen); RTPByteAddress::addresslength = addrlen; }
/** Sets the port number to \c port. */
void SetPort(uint16_t port) { RTPByteAddress::port = port; }
/** Returns a pointer to the stored host address. */
const uint8_t *GetHostAddress() const { return hostaddress; }
/** Returns the length in bytes of the stored host address. */
size_t GetHostAddressLength() const { return addresslength; }
/** Returns the port number stored in this instance. */
uint16_t GetPort() const { return port; }
RTPAddress *CreateCopy(RTPMemoryManager *mgr) const;
bool IsSameAddress(const RTPAddress *addr) const;
bool IsFromSameHost(const RTPAddress *addr) const;
private:
uint8_t hostaddress[RTPBYTEADDRESS_MAXLENGTH];
size_t addresslength;
uint16_t port;
};
} // end namespace
#endif // RTPBYTEADDRESS_H

View File

@ -0,0 +1,113 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpcollisionlist.h"
#include "rtperrors.h"
#include "rtpmemorymanager.h"
namespace qrtplib
{
RTPCollisionList::RTPCollisionList(RTPMemoryManager *mgr) : RTPMemoryObject(mgr)
{
timeinit.Dummy();
}
void RTPCollisionList::Clear()
{
std::list<AddressAndTime>::iterator it;
for (it = addresslist.begin() ; it != addresslist.end() ; it++)
RTPDelete((*it).addr,GetMemoryManager());
addresslist.clear();
}
int RTPCollisionList::UpdateAddress(const RTPAddress *addr,const RTPTime &receivetime,bool *created)
{
if (addr == 0)
return ERR_RTP_COLLISIONLIST_BADADDRESS;
std::list<AddressAndTime>::iterator it;
for (it = addresslist.begin() ; it != addresslist.end() ; it++)
{
if (((*it).addr)->IsSameAddress(addr))
{
(*it).recvtime = receivetime;
*created = false;
return 0;
}
}
RTPAddress *newaddr = addr->CreateCopy(GetMemoryManager());
if (newaddr == 0)
return ERR_RTP_OUTOFMEM;
addresslist.push_back(AddressAndTime(newaddr,receivetime));
*created = true;
return 0;
}
bool RTPCollisionList::HasAddress(const RTPAddress *addr) const
{
std::list<AddressAndTime>::const_iterator it;
for (it = addresslist.begin() ; it != addresslist.end() ; it++)
{
if (((*it).addr)->IsSameAddress(addr))
return true;
}
return false;
}
void RTPCollisionList::Timeout(const RTPTime &currenttime,const RTPTime &timeoutdelay)
{
std::list<AddressAndTime>::iterator it;
RTPTime checktime = currenttime;
checktime -= timeoutdelay;
it = addresslist.begin();
while(it != addresslist.end())
{
if ((*it).recvtime < checktime) // timeout
{
RTPDelete((*it).addr,GetMemoryManager());
it = addresslist.erase(it);
}
else
it++;
}
}
} // end namespace

View File

@ -0,0 +1,93 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpcollisionlist.h
*/
#ifndef RTPCOLLISIONLIST_H
#define RTPCOLLISIONLIST_H
#include "rtpconfig.h"
#include "rtpaddress.h"
#include "rtptimeutilities.h"
#include "rtpmemoryobject.h"
#include <list>
namespace qrtplib
{
class RTPAddress;
/** This class represents a list of addresses from which SSRC collisions were detected. */
class JRTPLIB_IMPORTEXPORT RTPCollisionList : public RTPMemoryObject
{
public:
/** Constructs an instance, optionally installing a memory manager. */
RTPCollisionList(RTPMemoryManager *mgr = 0);
~RTPCollisionList() { Clear(); }
/** Clears the list of addresses. */
void Clear();
/** Updates the entry for address \c addr to indicate that a collision was detected at time \c receivetime.
* Updates the entry for address \c addr to indicate that a collision was detected at time \c receivetime.
* If the entry did not exist yet, the flag \c created is set to \c true, otherwise it is set to \c false.
*/
int UpdateAddress(const RTPAddress *addr,const RTPTime &receivetime,bool *created);
/** Returns \c true} if the address \c addr appears in the list. */
bool HasAddress(const RTPAddress *addr) const;
/** Assuming that the current time is given by \c currenttime, this function times out entries which
* haven't been updated in the previous time interval specified by \c timeoutdelay.
*/
void Timeout(const RTPTime &currenttime,const RTPTime &timeoutdelay);
private:
class AddressAndTime
{
public:
AddressAndTime(RTPAddress *a,const RTPTime &t) : addr(a),recvtime(t) { }
RTPAddress *addr;
RTPTime recvtime;
};
std::list<AddressAndTime> addresslist;
};
} // end namespace
#endif // RTPCOLLISIONLIST_H

111
qrtplib/rtpconfig.h Normal file
View File

@ -0,0 +1,111 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef RTPCONFIG_UNIX_H
#define RTPCONFIG_UNIX_H
#ifndef JRTPLIB_UNUSED
/**
* Provide a macro to use for marking method parameters as unused.
*/
#define JRTPLIB_UNUSED(x) (void)(x)
#endif // JRTPLIB_UNUSED
#define JRTPLIB_IMPORT
#define JRTPLIB_EXPORT
#ifdef JRTPLIB_COMPILING
#define JRTPLIB_IMPORTEXPORT JRTPLIB_EXPORT
#else
#define JRTPLIB_IMPORTEXPORT JRTPLIB_IMPORT
#endif // JRTPLIB_COMPILING
// Don't have <sys/filio.h>
// Don't have <sys/sockio.h>
// Little endian system
#define RTP_SOCKLENTYPE_UINT
// No sa_len member in struct sockaddr
#define RTP_SUPPORT_IPV4MULTICAST
// No support for JThread was enabled
#define RTP_SUPPORT_SDESPRIV
#define RTP_SUPPORT_PROBATION
#define RTP_SUPPORT_GETLOGINR
#define RTP_SUPPORT_IPV6
#define RTP_SUPPORT_IPV6MULTICAST
#define RTP_SUPPORT_IFADDRS
#define RTP_SUPPORT_SENDAPP
#define RTP_SUPPORT_MEMORYMANAGEMENT
// No support for sending unknown RTCP packets
#define RTP_SUPPORT_NETINET_IN
// Not using winsock sockets
// No QueryPerformanceCounter support
// No ui64 suffix
// Stdio snprintf version
#define RTP_HAVE_ARRAYALLOC
// No rand_s support
// No strncpy_s support
// No SRTP support
#define RTP_HAVE_CLOCK_GETTIME
#define RTP_HAVE_POLL
// No 'WSAPoll' support
#define RTP_HAVE_MSG_NOSIGNAL
#endif // RTPCONFIG_UNIX_H

76
qrtplib/rtpdefines.h Normal file
View File

@ -0,0 +1,76 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef RTPDEFINES_H
#define RTPDEFINES_H
#define RTP_VERSION 2
#define RTP_MAXCSRCS 15
#define RTP_MINPACKETSIZE 600
#define RTP_DEFAULTPACKETSIZE 1400
#define RTP_PROBATIONCOUNT 2
#define RTP_MAXPRIVITEMS 256
#define RTP_SENDERTIMEOUTMULTIPLIER 2
#define RTP_BYETIMEOUTMULTIPLIER 1
#define RTP_MEMBERTIMEOUTMULTIPLIER 5
#define RTP_COLLISIONTIMEOUTMULTIPLIER 10
#define RTP_NOTETTIMEOUTMULTIPLIER 25
#define RTP_DEFAULTSESSIONBANDWIDTH 10000.0
#define RTP_RTCPTYPE_SR 200
#define RTP_RTCPTYPE_RR 201
#define RTP_RTCPTYPE_SDES 202
#define RTP_RTCPTYPE_BYE 203
#define RTP_RTCPTYPE_APP 204
#define RTCP_SDES_ID_CNAME 1
#define RTCP_SDES_ID_NAME 2
#define RTCP_SDES_ID_EMAIL 3
#define RTCP_SDES_ID_PHONE 4
#define RTCP_SDES_ID_LOCATION 5
#define RTCP_SDES_ID_TOOL 6
#define RTCP_SDES_ID_NOTE 7
#define RTCP_SDES_ID_PRIVATE 8
#define RTCP_SDES_NUMITEMS_NONPRIVATE 7
#define RTCP_SDES_MAXITEMLENGTH 255
#define RTCP_BYE_MAXREASONLENGTH 255
#define RTCP_DEFAULTMININTERVAL 5.0
#define RTCP_DEFAULTBANDWIDTHFRACTION 0.05
#define RTCP_DEFAULTSENDERFRACTION 0.25
#define RTCP_DEFAULTHALFATSTARTUP true
#define RTCP_DEFAULTIMMEDIATEBYE true
#define RTCP_DEFAULTSRBYE true
#endif // RTPDEFINES_H

272
qrtplib/rtperrors.cpp Normal file
View File

@ -0,0 +1,272 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtperrors.h"
#include "rtpdefines.h"
#include "rtpinternalutils.h"
#include <stdio.h>
namespace qrtplib
{
struct RTPErrorInfo
{
int code;
const char *description;
};
static RTPErrorInfo ErrorDescriptions[]=
{
{ ERR_RTP_OUTOFMEM,"Out of memory" },
{ ERR_RTP_NOTHREADSUPPORT, "No JThread support was compiled in"},
{ ERR_RTP_COLLISIONLIST_BADADDRESS, "Passed invalid address (null) to collision list"},
{ ERR_RTP_HASHTABLE_ELEMENTALREADYEXISTS, "Element already exists in hash table"},
{ ERR_RTP_HASHTABLE_ELEMENTNOTFOUND, "Element not found in hash table"},
{ ERR_RTP_HASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX, "Function returned an illegal hash index"},
{ ERR_RTP_HASHTABLE_NOCURRENTELEMENT, "No current element selected in hash table"},
{ ERR_RTP_KEYHASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX, "Function returned an illegal hash index"},
{ ERR_RTP_KEYHASHTABLE_KEYALREADYEXISTS, "Key value already exists in key hash table"},
{ ERR_RTP_KEYHASHTABLE_KEYNOTFOUND, "Key value not found in key hash table"},
{ ERR_RTP_KEYHASHTABLE_NOCURRENTELEMENT, "No current element selected in key hash table"},
{ ERR_RTP_PACKBUILD_ALREADYINIT, "RTP packet builder is already initialized"},
{ ERR_RTP_PACKBUILD_CSRCALREADYINLIST, "The specified CSRC is already in the RTP packet builder's CSRC list"},
{ ERR_RTP_PACKBUILD_CSRCLISTFULL, "The RTP packet builder's CSRC list already contains 15 entries"},
{ ERR_RTP_PACKBUILD_CSRCNOTINLIST, "The specified CSRC was not found in the RTP packet builder's CSRC list"},
{ ERR_RTP_PACKBUILD_DEFAULTMARKNOTSET, "The RTP packet builder's default mark flag is not set"},
{ ERR_RTP_PACKBUILD_DEFAULTPAYLOADTYPENOTSET, "The RTP packet builder's default payload type is not set"},
{ ERR_RTP_PACKBUILD_DEFAULTTSINCNOTSET, "The RTP packet builder's default timestamp increment is not set"},
{ ERR_RTP_PACKBUILD_INVALIDMAXPACKETSIZE, "The specified maximum packet size for the RTP packet builder is invalid"},
{ ERR_RTP_PACKBUILD_NOTINIT, "The RTP packet builder is not initialized"},
{ ERR_RTP_PACKET_BADPAYLOADTYPE, "Invalid payload type"},
{ ERR_RTP_PACKET_DATAEXCEEDSMAXSIZE, "Tried to create an RTP packet which whould exceed the specified maximum packet size"},
{ ERR_RTP_PACKET_EXTERNALBUFFERNULL, "Illegal value (null) passed as external buffer for the RTP packet"},
{ ERR_RTP_PACKET_ILLEGALBUFFERSIZE, "Illegal buffer size specified for the RTP packet"},
{ ERR_RTP_PACKET_INVALIDPACKET, "Invalid RTP packet format"},
{ ERR_RTP_PACKET_TOOMANYCSRCS, "More than 15 CSRCs specified for the RTP packet"},
{ ERR_RTP_POLLTHREAD_ALREADYRUNNING, "Poll thread is already running"},
{ ERR_RTP_POLLTHREAD_CANTINITMUTEX, "Can't initialize a mutex for the poll thread"},
{ ERR_RTP_POLLTHREAD_CANTSTARTTHREAD, "Can't start the poll thread"},
{ ERR_RTP_RTCPCOMPOUND_INVALIDPACKET, "Invalid RTCP compound packet format"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILDING, "Already building this RTCP compound packet"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILT, "This RTCP compound packet is already built"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYGOTREPORT, "There's already a SR or RR in this RTCP compound packet"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_APPDATALENTOOBIG, "The specified APP data length for the RTCP compound packet is too big"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_BUFFERSIZETOOSMALL, "The specified buffer size for the RTCP comound packet is too small"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_ILLEGALAPPDATALENGTH, "The APP data length must be a multiple of four"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_ILLEGALSUBTYPE, "The APP packet subtype must be smaller than 32"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_INVALIDITEMTYPE, "Invalid SDES item type specified for the RTCP compound packet"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_MAXPACKETSIZETOOSMALL, "The specified maximum packet size for the RTCP compound packet is too small"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_NOCURRENTSOURCE, "Tried to add an SDES item to the RTCP compound packet when no SSRC was present"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_NOREPORTPRESENT, "An RTCP compound packet must contain a SR or RR"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING, "The RTCP compound packet builder is not initialized"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT, "Adding this data would exceed the specified maximum RTCP compound packet size"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_REPORTNOTSTARTED, "Tried to add a report block to the RTCP compound packet when no SR or RR was started"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_TOOMANYSSRCS, "Only 31 SSRCs will fit into a BYE packet for the RTCP compound packet"},
{ ERR_RTP_RTCPCOMPPACKBUILDER_TOTALITEMLENGTHTOOBIG, "The total data for the SDES PRIV item exceeds the maximum size (255 bytes) of an SDES item"},
{ ERR_RTP_RTCPPACKETBUILDER_ALREADYINIT, "The RTCP packet builder is already initialized"},
{ ERR_RTP_RTCPPACKETBUILDER_ILLEGALMAXPACKSIZE, "The specified maximum packet size for the RTCP packet builder is too small"},
{ ERR_RTP_RTCPPACKETBUILDER_ILLEGALTIMESTAMPUNIT, "Speficied an illegal timestamp unit for the the RTCP packet builder"},
{ ERR_RTP_RTCPPACKETBUILDER_NOTINIT, "The RTCP packet builder was not initialized"},
{ ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON, "The RTCP compound packet filled sooner than expected"},
{ ERR_RTP_SCHEDPARAMS_BADFRACTION, "Illegal sender bandwidth fraction specified"},
{ ERR_RTP_SCHEDPARAMS_BADMINIMUMINTERVAL, "The minimum RTCP interval specified for the scheduler is too small"},
{ ERR_RTP_SCHEDPARAMS_INVALIDBANDWIDTH, "Invalid RTCP bandwidth specified for the RTCP scheduler"},
{ ERR_RTP_SDES_LENGTHTOOBIG, "Specified size for the SDES item exceeds 255 bytes"},
{ ERR_RTP_SDES_PREFIXNOTFOUND, "The specified SDES PRIV prefix was not found"},
{ ERR_RTP_SESSION_ALREADYCREATED, "The session is already created"},
{ ERR_RTP_SESSION_CANTGETLOGINNAME, "Can't retrieve login name"},
{ ERR_RTP_SESSION_CANTINITMUTEX, "A mutex for the RTP session couldn't be initialized"},
{ ERR_RTP_SESSION_MAXPACKETSIZETOOSMALL, "The maximum packet size specified for the RTP session is too small"},
{ ERR_RTP_SESSION_NOTCREATED, "The RTP session was not created"},
{ ERR_RTP_SESSION_UNSUPPORTEDTRANSMISSIONPROTOCOL, "The requested transmission protocol for the RTP session is not supported"},
{ ERR_RTP_SESSION_USINGPOLLTHREAD, "This function is not available when using the RTP poll thread feature"},
{ ERR_RTP_SESSION_USERDEFINEDTRANSMITTERNULL, "A user-defined transmitter was requested but the supplied transmitter component is NULL"},
{ ERR_RTP_SOURCES_ALREADYHAVEOWNSSRC, "Only one source can be marked as own SSRC in the source table"},
{ ERR_RTP_SOURCES_DONTHAVEOWNSSRC, "No source was marked as own SSRC in the source table"},
{ ERR_RTP_SOURCES_ILLEGALSDESTYPE, "Illegal SDES type specified for processing into the source table"},
{ ERR_RTP_SOURCES_SSRCEXISTS, "Can't create own SSRC because this SSRC identifier is already in the source table"},
{ ERR_RTP_UDPV4TRANS_ALREADYCREATED, "The transmitter was already created"},
{ ERR_RTP_UDPV4TRANS_ALREADYINIT, "The transmitter was already initialize"},
{ ERR_RTP_UDPV4TRANS_ALREADYWAITING, "The transmitter is already waiting for incoming data"},
{ ERR_RTP_UDPV4TRANS_CANTBINDRTCPSOCKET, "The 'bind' call for the RTCP socket failed"},
{ ERR_RTP_UDPV4TRANS_CANTBINDRTPSOCKET, "The 'bind' call for the RTP socket failed"},
{ ERR_RTP_UDPV4TRANS_CANTCREATESOCKET, "Couldn't create the RTP or RTCP socket"},
{ ERR_RTP_UDPV4TRANS_CANTINITMUTEX, "Failed to initialize a mutex used by the transmitter"},
{ ERR_RTP_UDPV4TRANS_CANTSETRTCPRECEIVEBUF, "Couldn't set the receive buffer size for the RTCP socket"},
{ ERR_RTP_UDPV4TRANS_CANTSETRTCPTRANSMITBUF, "Couldn't set the transmission buffer size for the RTCP socket"},
{ ERR_RTP_UDPV4TRANS_CANTSETRTPRECEIVEBUF, "Couldn't set the receive buffer size for the RTP socket"},
{ ERR_RTP_UDPV4TRANS_CANTSETRTPTRANSMITBUF, "Couldn't set the transmission buffer size for the RTP socket"},
{ ERR_RTP_UDPV4TRANS_COULDNTJOINMULTICASTGROUP, "Unable to join the specified multicast group"},
{ ERR_RTP_UDPV4TRANS_DIFFERENTRECEIVEMODE, "The function called doens't match the current receive mode"},
{ ERR_RTP_UDPV4TRANS_ILLEGALPARAMETERS, "Illegal parameters type passed to the transmitter"},
{ ERR_RTP_UDPV4TRANS_INVALIDADDRESSTYPE, "Specified address type isn't compatible with this transmitter"},
{ ERR_RTP_UDPV4TRANS_NOLOCALIPS, "Couldn't determine the local host name since the local IP list is empty"},
{ ERR_RTP_UDPV4TRANS_NOMULTICASTSUPPORT, "Multicast support is not available"},
{ ERR_RTP_UDPV4TRANS_NOSUCHENTRY, "Specified entry could not be found"},
{ ERR_RTP_UDPV4TRANS_NOTAMULTICASTADDRESS, "The specified address is not a multicast address"},
{ ERR_RTP_UDPV4TRANS_NOTCREATED, "The 'Create' call for this transmitter has not been called"},
{ ERR_RTP_UDPV4TRANS_NOTINIT, "The 'Init' call for this transmitter has not been called"},
{ ERR_RTP_UDPV4TRANS_NOTWAITING, "The transmitter is not waiting for incoming data"},
{ ERR_RTP_UDPV4TRANS_PORTBASENOTEVEN, "The specified port base is not an even number"},
{ ERR_RTP_UDPV4TRANS_SPECIFIEDSIZETOOBIG, "The maximum packet size is too big for this transmitter"},
{ ERR_RTP_UDPV6TRANS_ALREADYCREATED, "The transmitter was already created"},
{ ERR_RTP_UDPV6TRANS_ALREADYINIT, "The transmitter was already initialize"},
{ ERR_RTP_UDPV6TRANS_ALREADYWAITING, "The transmitter is already waiting for incoming data"},
{ ERR_RTP_UDPV6TRANS_CANTBINDRTCPSOCKET, "The 'bind' call for the RTCP socket failed"},
{ ERR_RTP_UDPV6TRANS_CANTBINDRTPSOCKET, "The 'bind' call for the RTP socket failed"},
{ ERR_RTP_UDPV6TRANS_CANTCREATESOCKET, "Couldn't create the RTP or RTCP socket"},
{ ERR_RTP_UDPV6TRANS_CANTINITMUTEX, "Failed to initialize a mutex used by the transmitter"},
{ ERR_RTP_UDPV6TRANS_CANTSETRTCPRECEIVEBUF, "Couldn't set the receive buffer size for the RTCP socket"},
{ ERR_RTP_UDPV6TRANS_CANTSETRTCPTRANSMITBUF, "Couldn't set the transmission buffer size for the RTCP socket"},
{ ERR_RTP_UDPV6TRANS_CANTSETRTPRECEIVEBUF, "Couldn't set the receive buffer size for the RTP socket"},
{ ERR_RTP_UDPV6TRANS_CANTSETRTPTRANSMITBUF, "Couldn't set the transmission buffer size for the RTP socket"},
{ ERR_RTP_UDPV6TRANS_COULDNTJOINMULTICASTGROUP, "Unable to join the specified multicast group"},
{ ERR_RTP_UDPV6TRANS_DIFFERENTRECEIVEMODE, "The function called doens't match the current receive mode"},
{ ERR_RTP_UDPV6TRANS_ILLEGALPARAMETERS, "Illegal parameters type passed to the transmitter"},
{ ERR_RTP_UDPV6TRANS_INVALIDADDRESSTYPE, "Specified address type isn't compatible with this transmitter"},
{ ERR_RTP_UDPV6TRANS_NOLOCALIPS, "Couldn't determine the local host name since the local IP list is empty"},
{ ERR_RTP_UDPV6TRANS_NOMULTICASTSUPPORT, "Multicast support is not available"},
{ ERR_RTP_UDPV6TRANS_NOSUCHENTRY, "Specified entry could not be found"},
{ ERR_RTP_UDPV6TRANS_NOTAMULTICASTADDRESS, "The specified address is not a multicast address"},
{ ERR_RTP_UDPV6TRANS_NOTCREATED, "The 'Create' call for this transmitter has not been called"},
{ ERR_RTP_UDPV6TRANS_NOTINIT, "The 'Init' call for this transmitter has not been called"},
{ ERR_RTP_UDPV6TRANS_NOTWAITING, "The transmitter is not waiting for incoming data"},
{ ERR_RTP_UDPV6TRANS_PORTBASENOTEVEN, "The specified port base is not an even number"},
{ ERR_RTP_UDPV6TRANS_SPECIFIEDSIZETOOBIG, "The maximum packet size is too big for this transmitter"},
{ ERR_RTP_TRANS_BUFFERLENGTHTOOSMALL,"The hostname is larger than the specified buffer size"},
{ ERR_RTP_SDES_MAXPRIVITEMS,"The maximum number of SDES private item prefixes was reached"},
{ ERR_RTP_INTERNALSOURCEDATA_INVALIDPROBATIONTYPE,"An invalid probation type was specified"},
{ ERR_RTP_FAKETRANS_ALREADYCREATED, "The transmitter was already created"},
{ ERR_RTP_FAKETRANS_ALREADYINIT, "The transmitter was already initialize"},
{ ERR_RTP_FAKETRANS_CANTINITMUTEX, "Failed to initialize a mutex used by the transmitter"},
{ ERR_RTP_FAKETRANS_COULDNTJOINMULTICASTGROUP, "Unable to join the specified multicast group"},
{ ERR_RTP_FAKETRANS_DIFFERENTRECEIVEMODE, "The function called doens't match the current receive mode"},
{ ERR_RTP_FAKETRANS_ILLEGALPARAMETERS, "Illegal parameters type passed to the transmitter"},
{ ERR_RTP_FAKETRANS_INVALIDADDRESSTYPE, "Specified address type isn't compatible with this transmitter"},
{ ERR_RTP_FAKETRANS_NOLOCALIPS, "Couldn't determine the local host name since the local IP list is empty"},
{ ERR_RTP_FAKETRANS_NOMULTICASTSUPPORT, "Multicast support is not available"},
{ ERR_RTP_FAKETRANS_NOSUCHENTRY, "Specified entry could not be found"},
{ ERR_RTP_FAKETRANS_NOTAMULTICASTADDRESS, "The specified address is not a multicast address"},
{ ERR_RTP_FAKETRANS_NOTCREATED, "The 'Create' call for this transmitter has not been called"},
{ ERR_RTP_FAKETRANS_NOTINIT, "The 'Init' call for this transmitter has not been called"},
{ ERR_RTP_FAKETRANS_PORTBASENOTEVEN, "The specified port base is not an even number"},
{ ERR_RTP_FAKETRANS_SPECIFIEDSIZETOOBIG, "The maximum packet size is too big for this transmitter"},
{ ERR_RTP_FAKETRANS_WAITNOTIMPLEMENTED, "The WaitForIncomingData is not implemented in the Gst transmitter"},
{ ERR_RTP_RTPRANDOMURANDOM_CANTOPEN, "Unable to open /dev/urandom for reading"},
{ ERR_RTP_RTPRANDOMURANDOM_ALREADYOPEN, "The device /dev/urandom was already opened"},
{ ERR_RTP_RTPRANDOMRANDS_NOTSUPPORTED, "The rand_s call is not supported on this platform"},
{ ERR_RTP_EXTERNALTRANS_ALREADYCREATED, "The external transmission component was already created"},
{ ERR_RTP_EXTERNALTRANS_ALREADYINIT, "The external transmission component was already initialized"},
{ ERR_RTP_EXTERNALTRANS_ALREADYWAITING, "The external transmission component is already waiting for incoming data"},
{ ERR_RTP_EXTERNALTRANS_BADRECEIVEMODE, "The external transmission component only supports accepting all incoming packets"},
{ ERR_RTP_EXTERNALTRANS_CANTINITMUTEX, "The external transmitter was unable to initialize a required mutex"},
{ ERR_RTP_EXTERNALTRANS_ILLEGALPARAMETERS, "Only parameters of type RTPExternalTransmissionParams can be passed to the external transmission component"},
{ ERR_RTP_EXTERNALTRANS_NOACCEPTLIST, "The external transmitter does not have an accept list"},
{ ERR_RTP_EXTERNALTRANS_NODESTINATIONSSUPPORTED, "The external transmitter does not have a destination list"},
{ ERR_RTP_EXTERNALTRANS_NOIGNORELIST, "The external transmitter does not have an ignore list"},
{ ERR_RTP_EXTERNALTRANS_NOMULTICASTSUPPORT, "The external transmitter does not support the multicast functions"},
{ ERR_RTP_EXTERNALTRANS_NOSENDER, "No sender has been set for this external transmitter"},
{ ERR_RTP_EXTERNALTRANS_NOTCREATED, "The external transmitter has not been created yet"},
{ ERR_RTP_EXTERNALTRANS_NOTINIT, "The external transmitter has not been initialized yet"},
{ ERR_RTP_EXTERNALTRANS_NOTWAITING, "The external transmitter is not currently waiting for incoming data"},
{ ERR_RTP_EXTERNALTRANS_SENDERROR, "The external transmitter was unable to actually send the data"},
{ ERR_RTP_EXTERNALTRANS_SPECIFIEDSIZETOOBIG, "The specified data size exceeds the maximum amount that has been set"},
{ ERR_RTP_UDPV4TRANS_CANTGETSOCKETPORT, "Unable to obtain the existing socket info using 'getsockname'"},
{ ERR_RTP_UDPV4TRANS_NOTANIPV4SOCKET, "The existing socket specified does not appear to be an IPv4 socket"},
{ ERR_RTP_UDPV4TRANS_SOCKETPORTNOTSET, "The existing socket that was specified does not have its port set yet"},
{ ERR_RTP_UDPV4TRANS_CANTGETSOCKETTYPE, "Can't get the socket type of the specified existing socket"},
{ ERR_RTP_UDPV4TRANS_INVALIDSOCKETTYPE, "The specified existing socket is not an UDP socket"},
{ ERR_RTP_UDPV4TRANS_CANTGETVALIDSOCKET, "Can't get a valid socket when trying to choose a port automatically"},
{ ERR_RTP_UDPV4TRANS_TOOMANYATTEMPTSCHOOSINGSOCKET, "Can't seem to get RTP/RTCP ports automatically, too many attempts"},
{ ERR_RTP_RTPSESSION_CHANGEREQUESTEDBUTNOTIMPLEMENTED, "Flag to change data was requested, but OnChangeRTPOrRTCPData was not reimplemented"},
{ ERR_RTP_SECURESESSION_CONTEXTALREADYINITIALIZED, "The initialization function was already called"},
{ ERR_RTP_SECURESESSION_CANTINITIALIZE_SRTPCONTEXT, "Unable to initialize libsrtp context"},
{ ERR_RTP_SECURESESSION_CANTINITMUTEX, "Unable to initialize a mutex" },
{ ERR_RTP_SECURESESSION_CONTEXTNOTINITIALIZED, "The libsrtp context initilization function must be called before it can be used"},
{ ERR_RTP_SECURESESSION_NOTENOUGHDATATOENCRYPT, "There's not enough RTP or RTCP data to encrypt"},
{ ERR_RTP_SECURESESSION_CANTENCRYPTRTPDATA, "Unable to encrypt RTP data"},
{ ERR_RTP_SECURESESSION_CANTENCRYPTRTCPDATA, "Unable to encrypt RTCP data"},
{ ERR_RTP_SECURESESSION_NOTENOUGHDATATODECRYPT, "There's not enough RTP or RTCP data to decrypt"},
{ ERR_RTP_SECURESESSION_CANTDECRYPTRTPDATA, "Unable to decrypt RTP data"},
{ ERR_RTP_SECURESESSION_CANTDECRYPTRTCPDATA, "Unable to decrypt RTCP data"},
{ ERR_RTP_ABORTDESC_ALREADYINIT, "The RTPAbortDescriptors instance is already initialized" },
{ ERR_RTP_ABORTDESC_NOTINIT, "The RTPAbortDescriptors instance is not yet initialized" },
{ ERR_RTP_ABORTDESC_CANTCREATEABORTDESCRIPTORS, "Unable to create two connected TCP sockets for the abort descriptors" },
{ ERR_RTP_ABORTDESC_CANTCREATEPIPE, "Unable to create a pipe for the abort descriptors" },
{ ERR_RTP_SESSION_THREADSAFETYCONFLICT, "For the background poll thread to be used, thread safety must also be set" },
{ ERR_RTP_SELECT_ERRORINSELECT, "Error in the call to 'select'" },
{ ERR_RTP_SELECT_SOCKETDESCRIPTORTOOLARGE, "A socket descriptor value is too large for a call to 'select' (exceeds FD_SETSIZE)" },
{ ERR_RTP_SELECT_ERRORINPOLL, "Error in the call to 'poll' or 'WSAPoll'" },
{ ERR_RTP_TCPTRANS_NOTINIT, "The TCP transmitter is not yet initialized" },
{ ERR_RTP_TCPTRANS_ALREADYINIT, "The TCP transmitter is already initialized" },
{ ERR_RTP_TCPTRANS_NOTCREATED, "The TCP transmitter is not yet created" },
{ ERR_RTP_TCPTRANS_ALREADYCREATED, "The TCP transmitter is already created" },
{ ERR_RTP_TCPTRANS_ILLEGALPARAMETERS, "The parameters for the TCP transmitter are invalid" },
{ ERR_RTP_TCPTRANS_CANTINITMUTEX, "Unable to initialize a mutex during the initialization of the TCP transmitter" },
{ ERR_RTP_TCPTRANS_ALREADYWAITING, "The TCP transmitter is already waiting for data" },
{ ERR_RTP_TCPTRANS_INVALIDADDRESSTYPE, "The address specified is not a valid address for the TCP transmitter" },
{ ERR_RTP_TCPTRANS_NOSOCKETSPECIFIED, "No socket was specified in the address used for the TCP transmitter" },
{ ERR_RTP_TCPTRANS_NOMULTICASTSUPPORT, "The TCP transmitter does not support multicasting" },
{ ERR_RTP_TCPTRANS_RECEIVEMODENOTSUPPORTED, "The TCP transmitter does not support receive modes other than 'accept all'" },
{ ERR_RTP_TCPTRANS_SPECIFIEDSIZETOOBIG, "The maximum packet size for the TCP transmitter is limited to 64KB" },
{ ERR_RTP_TCPTRANS_NOTWAITING, "The TCP transmitter is not waiting for data" },
{ ERR_RTP_TCPTRANS_SOCKETALREADYINDESTINATIONS, "The specified destination address (socket) was already added to the destination list of the TCP transmitter" },
{ ERR_RTP_TCPTRANS_SOCKETNOTFOUNDINDESTINATIONS, "The specified destination address (socket) was not found in the list of destinations of the TCP transmitter" },
{ ERR_RTP_TCPTRANS_ERRORINSEND, "An error occurred in the TCP transmitter while sending a packet" },
{ ERR_RTP_TCPTRANS_ERRORINRECV, "An error occurred in the TCP transmitter while receiving a packet" },
{ 0,0 }
};
std::string RTPGetErrorString(int errcode)
{
int i;
if (errcode >= 0)
return std::string("No error");
i = 0;
while (ErrorDescriptions[i].code != 0)
{
if (ErrorDescriptions[i].code == errcode)
return std::string(ErrorDescriptions[i].description);
i++;
}
char str[16];
RTP_SNPRINTF(str,16,"(%d)",errcode);
return std::string("Unknown error code") + std::string(str);
}
} // end namespace

251
qrtplib/rtperrors.h Normal file
View File

@ -0,0 +1,251 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtperrors.h
*/
#ifndef RTPERRORS_H
#define RTPERRORS_H
#include "rtpconfig.h"
#include <string>
namespace qrtplib
{
/** Returns a string describing the error code \c errcode. */
std::string JRTPLIB_IMPORTEXPORT RTPGetErrorString(int errcode);
} // end namespace
#define ERR_RTP_OUTOFMEM -1
#define ERR_RTP_NOTHREADSUPPORT -2
#define ERR_RTP_COLLISIONLIST_BADADDRESS -3
#define ERR_RTP_HASHTABLE_ELEMENTALREADYEXISTS -4
#define ERR_RTP_HASHTABLE_ELEMENTNOTFOUND -5
#define ERR_RTP_HASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX -6
#define ERR_RTP_HASHTABLE_NOCURRENTELEMENT -7
#define ERR_RTP_KEYHASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX -8
#define ERR_RTP_KEYHASHTABLE_KEYALREADYEXISTS -9
#define ERR_RTP_KEYHASHTABLE_KEYNOTFOUND -10
#define ERR_RTP_KEYHASHTABLE_NOCURRENTELEMENT -11
#define ERR_RTP_PACKBUILD_ALREADYINIT -12
#define ERR_RTP_PACKBUILD_CSRCALREADYINLIST -13
#define ERR_RTP_PACKBUILD_CSRCLISTFULL -14
#define ERR_RTP_PACKBUILD_CSRCNOTINLIST -15
#define ERR_RTP_PACKBUILD_DEFAULTMARKNOTSET -16
#define ERR_RTP_PACKBUILD_DEFAULTPAYLOADTYPENOTSET -17
#define ERR_RTP_PACKBUILD_DEFAULTTSINCNOTSET -18
#define ERR_RTP_PACKBUILD_INVALIDMAXPACKETSIZE -19
#define ERR_RTP_PACKBUILD_NOTINIT -20
#define ERR_RTP_PACKET_BADPAYLOADTYPE -21
#define ERR_RTP_PACKET_DATAEXCEEDSMAXSIZE -22
#define ERR_RTP_PACKET_EXTERNALBUFFERNULL -23
#define ERR_RTP_PACKET_ILLEGALBUFFERSIZE -24
#define ERR_RTP_PACKET_INVALIDPACKET -25
#define ERR_RTP_PACKET_TOOMANYCSRCS -26
#define ERR_RTP_POLLTHREAD_ALREADYRUNNING -27
#define ERR_RTP_POLLTHREAD_CANTINITMUTEX -28
#define ERR_RTP_POLLTHREAD_CANTSTARTTHREAD -29
#define ERR_RTP_RTCPCOMPOUND_INVALIDPACKET -30
#define ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILDING -31
#define ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYBUILT -32
#define ERR_RTP_RTCPCOMPPACKBUILDER_ALREADYGOTREPORT -33
#define ERR_RTP_RTCPCOMPPACKBUILDER_APPDATALENTOOBIG -34
#define ERR_RTP_RTCPCOMPPACKBUILDER_BUFFERSIZETOOSMALL -35
#define ERR_RTP_RTCPCOMPPACKBUILDER_ILLEGALAPPDATALENGTH -36
#define ERR_RTP_RTCPCOMPPACKBUILDER_ILLEGALSUBTYPE -37
#define ERR_RTP_RTCPCOMPPACKBUILDER_INVALIDITEMTYPE -38
#define ERR_RTP_RTCPCOMPPACKBUILDER_MAXPACKETSIZETOOSMALL -39
#define ERR_RTP_RTCPCOMPPACKBUILDER_NOCURRENTSOURCE -40
#define ERR_RTP_RTCPCOMPPACKBUILDER_NOREPORTPRESENT -41
#define ERR_RTP_RTCPCOMPPACKBUILDER_NOTBUILDING -42
#define ERR_RTP_RTCPCOMPPACKBUILDER_NOTENOUGHBYTESLEFT -43
#define ERR_RTP_RTCPCOMPPACKBUILDER_REPORTNOTSTARTED -44
#define ERR_RTP_RTCPCOMPPACKBUILDER_TOOMANYSSRCS -45
#define ERR_RTP_RTCPCOMPPACKBUILDER_TOTALITEMLENGTHTOOBIG -46
#define ERR_RTP_RTCPPACKETBUILDER_ALREADYINIT -47
#define ERR_RTP_RTCPPACKETBUILDER_ILLEGALMAXPACKSIZE -48
#define ERR_RTP_RTCPPACKETBUILDER_ILLEGALTIMESTAMPUNIT -49
#define ERR_RTP_RTCPPACKETBUILDER_NOTINIT -50
#define ERR_RTP_RTCPPACKETBUILDER_PACKETFILLEDTOOSOON -51
#define ERR_RTP_SCHEDPARAMS_BADFRACTION -52
#define ERR_RTP_SCHEDPARAMS_BADMINIMUMINTERVAL -53
#define ERR_RTP_SCHEDPARAMS_INVALIDBANDWIDTH -54
#define ERR_RTP_SDES_LENGTHTOOBIG -55
#define ERR_RTP_SDES_MAXPRIVITEMS -56
#define ERR_RTP_SDES_PREFIXNOTFOUND -57
#define ERR_RTP_SESSION_ALREADYCREATED -58
#define ERR_RTP_SESSION_CANTGETLOGINNAME -59
#define ERR_RTP_SESSION_CANTINITMUTEX -60
#define ERR_RTP_SESSION_MAXPACKETSIZETOOSMALL -61
#define ERR_RTP_SESSION_NOTCREATED -62
#define ERR_RTP_SESSION_UNSUPPORTEDTRANSMISSIONPROTOCOL -63
#define ERR_RTP_SESSION_USINGPOLLTHREAD -64
#define ERR_RTP_SOURCES_ALREADYHAVEOWNSSRC -65
#define ERR_RTP_SOURCES_DONTHAVEOWNSSRC -66
#define ERR_RTP_SOURCES_ILLEGALSDESTYPE -67
#define ERR_RTP_SOURCES_SSRCEXISTS -68
#define ERR_RTP_TRANS_BUFFERLENGTHTOOSMALL -69
#define ERR_RTP_UDPV4TRANS_ALREADYCREATED -70
#define ERR_RTP_UDPV4TRANS_ALREADYINIT -71
#define ERR_RTP_UDPV4TRANS_ALREADYWAITING -72
#define ERR_RTP_UDPV4TRANS_CANTBINDRTCPSOCKET -73
#define ERR_RTP_UDPV4TRANS_CANTBINDRTPSOCKET -74
#define ERR_RTP_UDPV4TRANS_CANTCREATESOCKET -75
#define ERR_RTP_UDPV4TRANS_CANTINITMUTEX -76
#define ERR_RTP_UDPV4TRANS_CANTSETRTCPRECEIVEBUF -77
#define ERR_RTP_UDPV4TRANS_CANTSETRTCPTRANSMITBUF -78
#define ERR_RTP_UDPV4TRANS_CANTSETRTPRECEIVEBUF -79
#define ERR_RTP_UDPV4TRANS_CANTSETRTPTRANSMITBUF -80
#define ERR_RTP_UDPV4TRANS_COULDNTJOINMULTICASTGROUP -81
#define ERR_RTP_UDPV4TRANS_DIFFERENTRECEIVEMODE -82
#define ERR_RTP_UDPV4TRANS_ILLEGALPARAMETERS -83
#define ERR_RTP_UDPV4TRANS_INVALIDADDRESSTYPE -84
#define ERR_RTP_UDPV4TRANS_NOLOCALIPS -85
#define ERR_RTP_UDPV4TRANS_NOMULTICASTSUPPORT -86
#define ERR_RTP_UDPV4TRANS_NOSUCHENTRY -87
#define ERR_RTP_UDPV4TRANS_NOTAMULTICASTADDRESS -88
#define ERR_RTP_UDPV4TRANS_NOTCREATED -89
#define ERR_RTP_UDPV4TRANS_NOTINIT -90
#define ERR_RTP_UDPV4TRANS_NOTWAITING -91
#define ERR_RTP_UDPV4TRANS_PORTBASENOTEVEN -92
#define ERR_RTP_UDPV4TRANS_SPECIFIEDSIZETOOBIG -93
#define ERR_RTP_UDPV6TRANS_ALREADYCREATED -94
#define ERR_RTP_UDPV6TRANS_ALREADYINIT -95
#define ERR_RTP_UDPV6TRANS_ALREADYWAITING -96
#define ERR_RTP_UDPV6TRANS_CANTBINDRTCPSOCKET -97
#define ERR_RTP_UDPV6TRANS_CANTBINDRTPSOCKET -98
#define ERR_RTP_UDPV6TRANS_CANTCREATESOCKET -99
#define ERR_RTP_UDPV6TRANS_CANTINITMUTEX -100
#define ERR_RTP_UDPV6TRANS_CANTSETRTCPRECEIVEBUF -101
#define ERR_RTP_UDPV6TRANS_CANTSETRTCPTRANSMITBUF -102
#define ERR_RTP_UDPV6TRANS_CANTSETRTPRECEIVEBUF -103
#define ERR_RTP_UDPV6TRANS_CANTSETRTPTRANSMITBUF -104
#define ERR_RTP_UDPV6TRANS_COULDNTJOINMULTICASTGROUP -105
#define ERR_RTP_UDPV6TRANS_DIFFERENTRECEIVEMODE -106
#define ERR_RTP_UDPV6TRANS_ILLEGALPARAMETERS -107
#define ERR_RTP_UDPV6TRANS_INVALIDADDRESSTYPE -108
#define ERR_RTP_UDPV6TRANS_NOLOCALIPS -109
#define ERR_RTP_UDPV6TRANS_NOMULTICASTSUPPORT -110
#define ERR_RTP_UDPV6TRANS_NOSUCHENTRY -111
#define ERR_RTP_UDPV6TRANS_NOTAMULTICASTADDRESS -112
#define ERR_RTP_UDPV6TRANS_NOTCREATED -113
#define ERR_RTP_UDPV6TRANS_NOTINIT -114
#define ERR_RTP_UDPV6TRANS_NOTWAITING -115
#define ERR_RTP_UDPV6TRANS_PORTBASENOTEVEN -116
#define ERR_RTP_UDPV6TRANS_SPECIFIEDSIZETOOBIG -117
#define ERR_RTP_INTERNALSOURCEDATA_INVALIDPROBATIONTYPE -118
#define ERR_RTP_SESSION_USERDEFINEDTRANSMITTERNULL -119
#define ERR_RTP_FAKETRANS_ALREADYCREATED -120
#define ERR_RTP_FAKETRANS_ALREADYINIT -121
#define ERR_RTP_FAKETRANS_CANTINITMUTEX -122
#define ERR_RTP_FAKETRANS_COULDNTJOINMULTICASTGROUP -123
#define ERR_RTP_FAKETRANS_DIFFERENTRECEIVEMODE -124
#define ERR_RTP_FAKETRANS_ILLEGALPARAMETERS -125
#define ERR_RTP_FAKETRANS_INVALIDADDRESSTYPE -126
#define ERR_RTP_FAKETRANS_NOLOCALIPS -127
#define ERR_RTP_FAKETRANS_NOMULTICASTSUPPORT -128
#define ERR_RTP_FAKETRANS_NOSUCHENTRY -129
#define ERR_RTP_FAKETRANS_NOTAMULTICASTADDRESS -130
#define ERR_RTP_FAKETRANS_NOTCREATED -131
#define ERR_RTP_FAKETRANS_NOTINIT -132
#define ERR_RTP_FAKETRANS_PORTBASENOTEVEN -133
#define ERR_RTP_FAKETRANS_SPECIFIEDSIZETOOBIG -134
#define ERR_RTP_FAKETRANS_WAITNOTIMPLEMENTED -135
#define ERR_RTP_RTPRANDOMURANDOM_CANTOPEN -136
#define ERR_RTP_RTPRANDOMURANDOM_ALREADYOPEN -137
#define ERR_RTP_RTPRANDOMRANDS_NOTSUPPORTED -138
#define ERR_RTP_EXTERNALTRANS_ALREADYCREATED -139
#define ERR_RTP_EXTERNALTRANS_ALREADYINIT -140
#define ERR_RTP_EXTERNALTRANS_ALREADYWAITING -141
#define ERR_RTP_EXTERNALTRANS_BADRECEIVEMODE -142
#define ERR_RTP_EXTERNALTRANS_CANTINITMUTEX -143
#define ERR_RTP_EXTERNALTRANS_ILLEGALPARAMETERS -144
#define ERR_RTP_EXTERNALTRANS_NOACCEPTLIST -145
#define ERR_RTP_EXTERNALTRANS_NODESTINATIONSSUPPORTED -146
#define ERR_RTP_EXTERNALTRANS_NOIGNORELIST -147
#define ERR_RTP_EXTERNALTRANS_NOMULTICASTSUPPORT -148
#define ERR_RTP_EXTERNALTRANS_NOSENDER -149
#define ERR_RTP_EXTERNALTRANS_NOTCREATED -150
#define ERR_RTP_EXTERNALTRANS_NOTINIT -151
#define ERR_RTP_EXTERNALTRANS_NOTWAITING -152
#define ERR_RTP_EXTERNALTRANS_SENDERROR -153
#define ERR_RTP_EXTERNALTRANS_SPECIFIEDSIZETOOBIG -154
#define ERR_RTP_UDPV4TRANS_CANTGETSOCKETPORT -155
#define ERR_RTP_UDPV4TRANS_NOTANIPV4SOCKET -156
#define ERR_RTP_UDPV4TRANS_SOCKETPORTNOTSET -157
#define ERR_RTP_UDPV4TRANS_CANTGETSOCKETTYPE -158
#define ERR_RTP_UDPV4TRANS_INVALIDSOCKETTYPE -159
#define ERR_RTP_UDPV4TRANS_CANTGETVALIDSOCKET -160
#define ERR_RTP_UDPV4TRANS_TOOMANYATTEMPTSCHOOSINGSOCKET -161
#define ERR_RTP_RTPSESSION_CHANGEREQUESTEDBUTNOTIMPLEMENTED -162
#define ERR_RTP_SECURESESSION_CONTEXTALREADYINITIALIZED -163
#define ERR_RTP_SECURESESSION_CANTINITIALIZE_SRTPCONTEXT -164
#define ERR_RTP_SECURESESSION_CANTINITMUTEX -165
#define ERR_RTP_SECURESESSION_CONTEXTNOTINITIALIZED -166
#define ERR_RTP_SECURESESSION_NOTENOUGHDATATOENCRYPT -167
#define ERR_RTP_SECURESESSION_CANTENCRYPTRTPDATA -168
#define ERR_RTP_SECURESESSION_CANTENCRYPTRTCPDATA -169
#define ERR_RTP_SECURESESSION_NOTENOUGHDATATODECRYPT -170
#define ERR_RTP_SECURESESSION_CANTDECRYPTRTPDATA -171
#define ERR_RTP_SECURESESSION_CANTDECRYPTRTCPDATA -172
#define ERR_RTP_ABORTDESC_ALREADYINIT -173
#define ERR_RTP_ABORTDESC_NOTINIT -174
#define ERR_RTP_ABORTDESC_CANTCREATEABORTDESCRIPTORS -175
#define ERR_RTP_ABORTDESC_CANTCREATEPIPE -176
#define ERR_RTP_SESSION_THREADSAFETYCONFLICT -177
#define ERR_RTP_SELECT_ERRORINSELECT -178
#define ERR_RTP_SELECT_SOCKETDESCRIPTORTOOLARGE -179
#define ERR_RTP_SELECT_ERRORINPOLL -180
#define ERR_RTP_TCPTRANS_NOTINIT -181
#define ERR_RTP_TCPTRANS_ALREADYINIT -182
#define ERR_RTP_TCPTRANS_ALREADYCREATED -183
#define ERR_RTP_TCPTRANS_ILLEGALPARAMETERS -184
#define ERR_RTP_TCPTRANS_CANTINITMUTEX -185
#define ERR_RTP_TCPTRANS_ALREADYWAITING -186
#define ERR_RTP_TCPTRANS_NOTCREATED -187
#define ERR_RTP_TCPTRANS_INVALIDADDRESSTYPE -188
#define ERR_RTP_TCPTRANS_NOSOCKETSPECIFIED -189
#define ERR_RTP_TCPTRANS_NOMULTICASTSUPPORT -190
#define ERR_RTP_TCPTRANS_RECEIVEMODENOTSUPPORTED -191
#define ERR_RTP_TCPTRANS_SPECIFIEDSIZETOOBIG -192
#define ERR_RTP_TCPTRANS_NOTWAITING -193
#define ERR_RTP_TCPTRANS_SOCKETALREADYINDESTINATIONS -194
#define ERR_RTP_TCPTRANS_SOCKETNOTFOUNDINDESTINATIONS -195
#define ERR_RTP_TCPTRANS_ERRORINSEND -196
#define ERR_RTP_TCPTRANS_ERRORINRECV -197
#endif // RTPERRORS_H

View File

@ -0,0 +1,733 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpexternaltransmitter.h"
#include "rtprawpacket.h"
#include "rtptimeutilities.h"
#include "rtpdefines.h"
#include "rtperrors.h"
#include "rtpsocketutilinternal.h"
#include "rtpselect.h"
#include <stdio.h>
#include <string.h>
#include <iostream>
#ifdef RTP_SUPPORT_THREAD
#define MAINMUTEX_LOCK { if (threadsafe) mainmutex.Lock(); }
#define MAINMUTEX_UNLOCK { if (threadsafe) mainmutex.Unlock(); }
#define WAITMUTEX_LOCK { if (threadsafe) waitmutex.Lock(); }
#define WAITMUTEX_UNLOCK { if (threadsafe) waitmutex.Unlock(); }
#else
#define MAINMUTEX_LOCK
#define MAINMUTEX_UNLOCK
#define WAITMUTEX_LOCK
#define WAITMUTEX_UNLOCK
#endif // RTP_SUPPORT_THREAD
namespace qrtplib
{
RTPExternalTransmitter::RTPExternalTransmitter(RTPMemoryManager *mgr) : RTPTransmitter(mgr), packetinjector((RTPExternalTransmitter *)this)
{
created = false;
init = false;
}
RTPExternalTransmitter::~RTPExternalTransmitter()
{
Destroy();
}
int RTPExternalTransmitter::Init(bool tsafe)
{
if (init)
return ERR_RTP_EXTERNALTRANS_ALREADYINIT;
#ifdef RTP_SUPPORT_THREAD
threadsafe = tsafe;
if (threadsafe)
{
int status;
status = mainmutex.Init();
if (status < 0)
return ERR_RTP_EXTERNALTRANS_CANTINITMUTEX;
status = waitmutex.Init();
if (status < 0)
return ERR_RTP_EXTERNALTRANS_CANTINITMUTEX;
}
#else
if (tsafe)
return ERR_RTP_NOTHREADSUPPORT;
#endif // RTP_SUPPORT_THREAD
init = true;
return 0;
}
int RTPExternalTransmitter::Create(size_t maximumpacketsize,const RTPTransmissionParams *transparams)
{
const RTPExternalTransmissionParams *params;
int status;
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
if (created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_ALREADYCREATED;
}
// Obtain transmission parameters
if (transparams == 0)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_ILLEGALPARAMETERS;
}
if (transparams->GetTransmissionProtocol() != RTPTransmitter::ExternalProto)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_ILLEGALPARAMETERS;
}
params = (const RTPExternalTransmissionParams *)transparams;
if ((status = m_abortDesc.Init()) < 0)
{
MAINMUTEX_UNLOCK
return status;
}
m_abortCount = 0;
maxpacksize = maximumpacketsize;
sender = params->GetSender();
headersize = params->GetAdditionalHeaderSize();
localhostname = 0;
localhostnamelength = 0;
waitingfordata = false;
created = true;
MAINMUTEX_UNLOCK
return 0;
}
void RTPExternalTransmitter::Destroy()
{
if (!init)
return;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK;
return;
}
if (localhostname)
{
RTPDeleteByteArray(localhostname,GetMemoryManager());
localhostname = 0;
localhostnamelength = 0;
}
FlushPackets();
created = false;
if (waitingfordata)
{
m_abortDesc.SendAbortSignal();
m_abortCount++;
m_abortDesc.Destroy();
MAINMUTEX_UNLOCK
WAITMUTEX_LOCK // to make sure that the WaitForIncomingData function ended
WAITMUTEX_UNLOCK
}
else
m_abortDesc.Destroy();
MAINMUTEX_UNLOCK
}
RTPTransmissionInfo *RTPExternalTransmitter::GetTransmissionInfo()
{
if (!init)
return 0;
MAINMUTEX_LOCK
RTPTransmissionInfo *tinf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPTRANSMISSIONINFO) RTPExternalTransmissionInfo(&packetinjector);
MAINMUTEX_UNLOCK
return tinf;
}
void RTPExternalTransmitter::DeleteTransmissionInfo(RTPTransmissionInfo *i)
{
if (!init)
return;
RTPDelete(i, GetMemoryManager());
}
int RTPExternalTransmitter::GetLocalHostName(uint8_t *buffer,size_t *bufferlength)
{
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTCREATED;
}
if (localhostname == 0)
{
// We'll just use 'gethostname' for simplicity
char name[1024];
if (gethostname(name,1023) != 0)
strcpy(name, "localhost"); // failsafe
else
name[1023] = 0; // ensure null-termination
localhostnamelength = strlen(name);
localhostname = RTPNew(GetMemoryManager(),RTPMEM_TYPE_OTHER) uint8_t [localhostnamelength+1];
memcpy(localhostname, name, localhostnamelength);
localhostname[localhostnamelength] = 0;
}
if ((*bufferlength) < localhostnamelength)
{
*bufferlength = localhostnamelength; // tell the application the required size of the buffer
MAINMUTEX_UNLOCK
return ERR_RTP_TRANS_BUFFERLENGTHTOOSMALL;
}
memcpy(buffer,localhostname,localhostnamelength);
*bufferlength = localhostnamelength;
MAINMUTEX_UNLOCK
return 0;
}
bool RTPExternalTransmitter::ComesFromThisTransmitter(const RTPAddress *addr)
{
MAINMUTEX_LOCK
bool value = false;
if (sender)
value = sender->ComesFromThisSender(addr);
MAINMUTEX_UNLOCK
return value;
}
int RTPExternalTransmitter::Poll()
{
return 0;
}
int RTPExternalTransmitter::WaitForIncomingData(const RTPTime &delay,bool *dataavailable)
{
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTCREATED;
}
if (waitingfordata)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_ALREADYWAITING;
}
waitingfordata = true;
if (!rawpacketlist.empty())
{
if (dataavailable != 0)
*dataavailable = true;
waitingfordata = false;
MAINMUTEX_UNLOCK
return 0;
}
WAITMUTEX_LOCK
MAINMUTEX_UNLOCK
int8_t isset = 0;
SocketType abortSock = m_abortDesc.GetAbortSocket();
int status = RTPSelect(&abortSock, &isset, 1, delay);
if (status < 0)
{
MAINMUTEX_LOCK
waitingfordata = false;
MAINMUTEX_UNLOCK
WAITMUTEX_UNLOCK
return status;
}
MAINMUTEX_LOCK
waitingfordata = false;
if (!created) // destroy called
{
MAINMUTEX_UNLOCK;
WAITMUTEX_UNLOCK
return 0;
}
// if aborted, read from abort buffer
if (isset)
{
m_abortDesc.ClearAbortSignal();
m_abortCount = 0;
}
if (dataavailable != 0)
{
if (rawpacketlist.empty())
*dataavailable = false;
else
*dataavailable = true;
}
MAINMUTEX_UNLOCK
WAITMUTEX_UNLOCK
return 0;
}
int RTPExternalTransmitter::AbortWait()
{
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTCREATED;
}
if (!waitingfordata)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTWAITING;
}
m_abortDesc.SendAbortSignal();
m_abortCount++;
MAINMUTEX_UNLOCK
return 0;
}
int RTPExternalTransmitter::SendRTPData(const void *data,size_t len)
{
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTCREATED;
}
if (len > maxpacksize)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_SPECIFIEDSIZETOOBIG;
}
if (!sender)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOSENDER;
}
MAINMUTEX_UNLOCK
if (!sender->SendRTP(data, len))
return ERR_RTP_EXTERNALTRANS_SENDERROR;
return 0;
}
int RTPExternalTransmitter::SendRTCPData(const void *data,size_t len)
{
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTCREATED;
}
if (len > maxpacksize)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_SPECIFIEDSIZETOOBIG;
}
if (!sender)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOSENDER;
}
MAINMUTEX_UNLOCK
if (!sender->SendRTCP(data, len))
return ERR_RTP_EXTERNALTRANS_SENDERROR;
return 0;
}
int RTPExternalTransmitter::AddDestination(const RTPAddress &)
{
return ERR_RTP_EXTERNALTRANS_NODESTINATIONSSUPPORTED;
}
int RTPExternalTransmitter::DeleteDestination(const RTPAddress &)
{
return ERR_RTP_EXTERNALTRANS_NODESTINATIONSSUPPORTED;
}
void RTPExternalTransmitter::ClearDestinations()
{
}
bool RTPExternalTransmitter::SupportsMulticasting()
{
return false;
}
int RTPExternalTransmitter::JoinMulticastGroup(const RTPAddress &)
{
return ERR_RTP_EXTERNALTRANS_NOMULTICASTSUPPORT;
}
int RTPExternalTransmitter::LeaveMulticastGroup(const RTPAddress &)
{
return ERR_RTP_EXTERNALTRANS_NOMULTICASTSUPPORT;
}
void RTPExternalTransmitter::LeaveAllMulticastGroups()
{
}
int RTPExternalTransmitter::SetReceiveMode(RTPTransmitter::ReceiveMode m)
{
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTCREATED;
}
if (m != RTPTransmitter::AcceptAll)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_BADRECEIVEMODE;
}
MAINMUTEX_UNLOCK
return 0;
}
int RTPExternalTransmitter::AddToIgnoreList(const RTPAddress &)
{
return ERR_RTP_EXTERNALTRANS_NOIGNORELIST;
}
int RTPExternalTransmitter::DeleteFromIgnoreList(const RTPAddress &)
{
return ERR_RTP_EXTERNALTRANS_NOIGNORELIST;
}
void RTPExternalTransmitter::ClearIgnoreList()
{
}
int RTPExternalTransmitter::AddToAcceptList(const RTPAddress &)
{
return ERR_RTP_EXTERNALTRANS_NOACCEPTLIST;
}
int RTPExternalTransmitter::DeleteFromAcceptList(const RTPAddress &)
{
return ERR_RTP_EXTERNALTRANS_NOACCEPTLIST;
}
void RTPExternalTransmitter::ClearAcceptList()
{
}
int RTPExternalTransmitter::SetMaximumPacketSize(size_t s)
{
if (!init)
return ERR_RTP_EXTERNALTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_EXTERNALTRANS_NOTCREATED;
}
maxpacksize = s;
MAINMUTEX_UNLOCK
return 0;
}
bool RTPExternalTransmitter::NewDataAvailable()
{
if (!init)
return false;
MAINMUTEX_LOCK
bool v;
if (!created)
v = false;
else
{
if (rawpacketlist.empty())
v = false;
else
v = true;
}
MAINMUTEX_UNLOCK
return v;
}
RTPRawPacket *RTPExternalTransmitter::GetNextPacket()
{
if (!init)
return 0;
MAINMUTEX_LOCK
RTPRawPacket *p;
if (!created)
{
MAINMUTEX_UNLOCK
return 0;
}
if (rawpacketlist.empty())
{
MAINMUTEX_UNLOCK
return 0;
}
p = *(rawpacketlist.begin());
rawpacketlist.pop_front();
MAINMUTEX_UNLOCK
return p;
}
// Here the private functions start...
void RTPExternalTransmitter::FlushPackets()
{
std::list<RTPRawPacket*>::const_iterator it;
for (it = rawpacketlist.begin() ; it != rawpacketlist.end() ; ++it)
RTPDelete(*it,GetMemoryManager());
rawpacketlist.clear();
}
void RTPExternalTransmitter::InjectRTP(const void *data, size_t len, const RTPAddress &a)
{
if (!init)
return;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return;
}
RTPAddress *addr = a.CreateCopy(GetMemoryManager());
if (addr == 0)
return;
uint8_t *datacopy;
datacopy = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RECEIVEDRTPPACKET) uint8_t[len];
if (datacopy == 0)
{
RTPDelete(addr,GetMemoryManager());
return;
}
memcpy(datacopy, data, len);
RTPTime curtime = RTPTime::CurrentTime();
RTPRawPacket *pack;
pack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPRAWPACKET) RTPRawPacket(datacopy,len,addr,curtime,true,GetMemoryManager());
if (pack == 0)
{
RTPDelete(addr,GetMemoryManager());
RTPDeleteByteArray(localhostname,GetMemoryManager());
return;
}
rawpacketlist.push_back(pack);
if (m_abortCount == 0)
{
m_abortDesc.SendAbortSignal();
m_abortCount++;
}
MAINMUTEX_UNLOCK
}
void RTPExternalTransmitter::InjectRTCP(const void *data, size_t len, const RTPAddress &a)
{
if (!init)
return;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return;
}
RTPAddress *addr = a.CreateCopy(GetMemoryManager());
if (addr == 0)
return;
uint8_t *datacopy;
datacopy = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RECEIVEDRTCPPACKET) uint8_t[len];
if (datacopy == 0)
{
RTPDelete(addr,GetMemoryManager());
return;
}
memcpy(datacopy, data, len);
RTPTime curtime = RTPTime::CurrentTime();
RTPRawPacket *pack;
pack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPRAWPACKET) RTPRawPacket(datacopy,len,addr,curtime,false,GetMemoryManager());
if (pack == 0)
{
RTPDelete(addr,GetMemoryManager());
RTPDeleteByteArray(localhostname,GetMemoryManager());
return;
}
rawpacketlist.push_back(pack);
if (m_abortCount == 0)
{
m_abortDesc.SendAbortSignal();
m_abortCount++;
}
MAINMUTEX_UNLOCK
}
void RTPExternalTransmitter::InjectRTPorRTCP(const void *data, size_t len, const RTPAddress &a)
{
if (!init)
return;
MAINMUTEX_LOCK
if (!created)
{
MAINMUTEX_UNLOCK
return;
}
RTPAddress *addr = a.CreateCopy(GetMemoryManager());
if (addr == 0)
return;
uint8_t *datacopy;
bool rtp = true;
if (len >= 2)
{
const uint8_t *pData = (const uint8_t *)data;
if (pData[1] >= 200 && pData[1] <= 204)
rtp = false;
}
datacopy = RTPNew(GetMemoryManager(),(rtp)?RTPMEM_TYPE_BUFFER_RECEIVEDRTPPACKET:RTPMEM_TYPE_BUFFER_RECEIVEDRTCPPACKET) uint8_t[len];
if (datacopy == 0)
{
RTPDelete(addr,GetMemoryManager());
return;
}
memcpy(datacopy, data, len);
RTPTime curtime = RTPTime::CurrentTime();
RTPRawPacket *pack;
pack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPRAWPACKET) RTPRawPacket(datacopy,len,addr,curtime,rtp,GetMemoryManager());
if (pack == 0)
{
RTPDelete(addr,GetMemoryManager());
RTPDeleteByteArray(localhostname,GetMemoryManager());
return;
}
rawpacketlist.push_back(pack);
if (m_abortCount == 0)
{
m_abortDesc.SendAbortSignal();
m_abortCount++;
}
MAINMUTEX_UNLOCK
}
} // end namespace

View File

@ -0,0 +1,231 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpexternaltransmitter.h
*/
#ifndef RTPEXTERNALTRANSMITTER_H
#define RTPEXTERNALTRANSMITTER_H
#include "rtpconfig.h"
#include "rtptransmitter.h"
#include "rtpabortdescriptors.h"
#include <list>
#ifdef RTP_SUPPORT_THREAD
#include <jthread/jmutex.h>
#endif // RTP_SUPPORT_THREAD
namespace qrtplib
{
class RTPExternalTransmitter;
/** Base class to specify a mechanism to transmit RTP packets outside of this library.
* Base class to specify a mechanism to transmit RTP packets outside of this library. When
* you want to use your own mechanism to transmit RTP packets, you need to specify that
* you'll be using the external transmission component, and derive a class from this base
* class. An instance should then be specified in the RTPExternalTransmissionParams object,
* so that the transmitter will call the \c SendRTP, \c SendRTCP and \c ComesFromThisSender
* methods of this instance when needed.
*/
class JRTPLIB_IMPORTEXPORT RTPExternalSender
{
public:
RTPExternalSender() { }
virtual ~RTPExternalSender() { }
/** This member function will be called when RTP data needs to be transmitted. */
virtual bool SendRTP(const void *data, size_t len) = 0;
/** This member function will be called when an RTCP packet needs to be transmitted. */
virtual bool SendRTCP(const void *data, size_t len) = 0;
/** Used to identify if an RTPAddress instance originated from this sender (to be able to detect own packets). */
virtual bool ComesFromThisSender(const RTPAddress *a) = 0;
};
/** Interface to inject incoming RTP and RTCP packets into the library.
* Interface to inject incoming RTP and RTCP packets into the library. When you have your own
* mechanism to receive incoming RTP/RTCP data, you'll need to pass these packets to the library.
* By first retrieving the RTPExternalTransmissionInfo instance for the external transmitter you'll
* be using, you can obtain the associated RTPExternalPacketInjecter instance. By calling it's
* member functions, you can then inject RTP or RTCP data into the library for further processing.
*/
class JRTPLIB_IMPORTEXPORT RTPExternalPacketInjecter
{
public:
RTPExternalPacketInjecter(RTPExternalTransmitter *trans) { transmitter = trans; }
~RTPExternalPacketInjecter() { }
/** This function can be called to insert an RTP packet into the transmission component. */
void InjectRTP(const void *data, size_t len, const RTPAddress &a);
/** This function can be called to insert an RTCP packet into the transmission component. */
void InjectRTCP(const void *data, size_t len, const RTPAddress &a);
/** Use this function to inject an RTP or RTCP packet and the transmitter will try to figure out which type of packet it is. */
void InjectRTPorRTCP(const void *data, size_t len, const RTPAddress &a);
private:
RTPExternalTransmitter *transmitter;
};
/** Parameters to initialize a transmitter of type RTPExternalTransmitter. */
class JRTPLIB_IMPORTEXPORT RTPExternalTransmissionParams : public RTPTransmissionParams
{
public:
/** Using this constructor you can specify which RTPExternalSender object you'll be using
* and how much the additional header overhead for each packet will be. */
RTPExternalTransmissionParams(RTPExternalSender *s, int headeroverhead):RTPTransmissionParams(RTPTransmitter::ExternalProto) { sender = s; headersize = headeroverhead; }
RTPExternalSender *GetSender() const { return sender; }
int GetAdditionalHeaderSize() const { return headersize; }
private:
RTPExternalSender *sender;
int headersize;
};
/** Additional information about the external transmission component. */
class JRTPLIB_IMPORTEXPORT RTPExternalTransmissionInfo : public RTPTransmissionInfo
{
public:
RTPExternalTransmissionInfo(RTPExternalPacketInjecter *p) : RTPTransmissionInfo(RTPTransmitter::ExternalProto) { packetinjector = p; }
/** Tells you which RTPExternalPacketInjecter you need to use to pass RTP or RTCP
* data on to the transmission component. */
RTPExternalPacketInjecter *GetPacketInjector() const { return packetinjector; }
private:
RTPExternalPacketInjecter *packetinjector;
};
/** A transmission component which will use user specified functions to transmit the data and
* which will expose functions to inject received RTP or RTCP data into this component.
* A transmission component which will use user specified functions to transmit the data and
* which will expose functions to inject received RTP or RTCP data into this component. Use
* a class derived from RTPExternalSender to specify the functions which need to be used for
* sending the data. Obtain the RTPExternalTransmissionInfo object associated with this
* transmitter to obtain the functions needed to pass RTP/RTCP packets on to the transmitter.
*/
class JRTPLIB_IMPORTEXPORT RTPExternalTransmitter : public RTPTransmitter
{
public:
RTPExternalTransmitter(RTPMemoryManager *mgr);
~RTPExternalTransmitter();
int Init(bool treadsafe);
int Create(size_t maxpacksize, const RTPTransmissionParams *transparams);
void Destroy();
RTPTransmissionInfo *GetTransmissionInfo();
void DeleteTransmissionInfo(RTPTransmissionInfo *inf);
int GetLocalHostName(uint8_t *buffer,size_t *bufferlength);
bool ComesFromThisTransmitter(const RTPAddress *addr);
size_t GetHeaderOverhead() { return headersize; }
int Poll();
int WaitForIncomingData(const RTPTime &delay,bool *dataavailable = 0);
int AbortWait();
int SendRTPData(const void *data,size_t len);
int SendRTCPData(const void *data,size_t len);
int AddDestination(const RTPAddress &addr);
int DeleteDestination(const RTPAddress &addr);
void ClearDestinations();
bool SupportsMulticasting();
int JoinMulticastGroup(const RTPAddress &addr);
int LeaveMulticastGroup(const RTPAddress &addr);
void LeaveAllMulticastGroups();
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(size_t s);
bool NewDataAvailable();
RTPRawPacket *GetNextPacket();
void InjectRTP(const void *data, size_t len, const RTPAddress &a);
void InjectRTCP(const void *data, size_t len, const RTPAddress &a);
void InjectRTPorRTCP(const void *data, size_t len, const RTPAddress &a);
private:
void FlushPackets();
bool init;
bool created;
bool waitingfordata;
RTPExternalSender *sender;
RTPExternalPacketInjecter packetinjector;
std::list<RTPRawPacket*> rawpacketlist;
uint8_t *localhostname;
size_t localhostnamelength;
size_t maxpacksize;
int headersize;
RTPAbortDescriptors m_abortDesc;
int m_abortCount;
#ifdef RTP_SUPPORT_THREAD
jthread::JMutex mainmutex,waitmutex;
int threadsafe;
#endif // RTP_SUPPORT_THREAD
};
inline void RTPExternalPacketInjecter::InjectRTP(const void *data, size_t len, const RTPAddress &a)
{
transmitter->InjectRTP(data, len, a);
}
inline void RTPExternalPacketInjecter::InjectRTCP(const void *data, size_t len, const RTPAddress &a)
{
transmitter->InjectRTCP(data, len, a);
}
inline void RTPExternalPacketInjecter::InjectRTPorRTCP(const void *data, size_t len, const RTPAddress &a)
{
transmitter->InjectRTPorRTCP(data, len, a);
}
} // end namespace
#endif // RTPTCPSOCKETTRANSMITTER_H

308
qrtplib/rtphashtable.h Normal file
View File

@ -0,0 +1,308 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef RTPHASHTABLE_H
#define RTPHASHTABLE_H
/**
* \file rtphashtable.h
*/
#include "rtperrors.h"
#include "rtpmemoryobject.h"
namespace qrtplib
{
//template<class Element,int GetIndex(const Element &k),int hashsize>
template<class Element,class GetIndex,int hashsize>
class RTPHashTable : public RTPMemoryObject
{
public:
RTPHashTable(RTPMemoryManager *mgr = 0, int memtype = RTPMEM_TYPE_OTHER);
~RTPHashTable() { Clear(); }
void GotoFirstElement() { curhashelem = firsthashelem; }
void GotoLastElement() { curhashelem = lasthashelem; }
bool HasCurrentElement() { return (curhashelem == 0)?false:true; }
int DeleteCurrentElement();
Element &GetCurrentElement() { return curhashelem->GetElement(); }
int GotoElement(const Element &e);
bool HasElement(const Element &e);
void GotoNextElement();
void GotoPreviousElement();
void Clear();
int AddElement(const Element &elem);
int DeleteElement(const Element &elem);
private:
class HashElement
{
public:
HashElement(const Element &e,int index):element(e) { hashprev = 0; hashnext = 0; listnext = 0; listprev = 0; hashindex = index; }
int GetHashIndex() { return hashindex; }
Element &GetElement() { return element; }
private:
int hashindex;
Element element;
public:
HashElement *hashprev,*hashnext;
HashElement *listprev,*listnext;
};
HashElement *table[hashsize];
HashElement *firsthashelem,*lasthashelem;
HashElement *curhashelem;
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
int memorytype;
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
};
template<class Element,class GetIndex,int hashsize>
inline RTPHashTable<Element,GetIndex,hashsize>::RTPHashTable(RTPMemoryManager *mgr,int memtype) : RTPMemoryObject(mgr)
{
JRTPLIB_UNUSED(memtype); // possibly unused
for (int i = 0 ; i < hashsize ; i++)
table[i] = 0;
firsthashelem = 0;
lasthashelem = 0;
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
memorytype = memtype;
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
}
template<class Element,class GetIndex,int hashsize>
inline int RTPHashTable<Element,GetIndex,hashsize>::DeleteCurrentElement()
{
if (curhashelem)
{
HashElement *tmp1,*tmp2;
int index;
// First, relink elements in current hash bucket
index = curhashelem->GetHashIndex();
tmp1 = curhashelem->hashprev;
tmp2 = curhashelem->hashnext;
if (tmp1 == 0) // no previous element in hash bucket
{
table[index] = tmp2;
if (tmp2 != 0)
tmp2->hashprev = 0;
}
else // there is a previous element in the hash bucket
{
tmp1->hashnext = tmp2;
if (tmp2 != 0)
tmp2->hashprev = tmp1;
}
// Relink elements in list
tmp1 = curhashelem->listprev;
tmp2 = curhashelem->listnext;
if (tmp1 == 0) // curhashelem is first in list
{
firsthashelem = tmp2;
if (tmp2 != 0)
tmp2->listprev = 0;
else // curhashelem is also last in list
lasthashelem = 0;
}
else
{
tmp1->listnext = tmp2;
if (tmp2 != 0)
tmp2->listprev = tmp1;
else // curhashelem is last in list
lasthashelem = tmp1;
}
// finally, with everything being relinked, we can delete curhashelem
RTPDelete(curhashelem,GetMemoryManager());
curhashelem = tmp2; // Set to next element in the list
}
else
return ERR_RTP_HASHTABLE_NOCURRENTELEMENT;
return 0;
}
template<class Element,class GetIndex,int hashsize>
inline int RTPHashTable<Element,GetIndex,hashsize>::GotoElement(const Element &e)
{
int index;
bool found;
index = GetIndex::GetIndex(e);
if (index >= hashsize)
return ERR_RTP_HASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX;
curhashelem = table[index];
found = false;
while(!found && curhashelem != 0)
{
if (curhashelem->GetElement() == e)
found = true;
else
curhashelem = curhashelem->hashnext;
}
if (!found)
return ERR_RTP_HASHTABLE_ELEMENTNOTFOUND;
return 0;
}
template<class Element,class GetIndex,int hashsize>
inline bool RTPHashTable<Element,GetIndex,hashsize>::HasElement(const Element &e)
{
int index;
bool found;
HashElement *tmp;
index = GetIndex::GetIndex(e);
if (index >= hashsize)
return false;
tmp = table[index];
found = false;
while(!found && tmp != 0)
{
if (tmp->GetElement() == e)
found = true;
else
tmp = tmp->hashnext;
}
return found;
}
template<class Element,class GetIndex,int hashsize>
inline void RTPHashTable<Element,GetIndex,hashsize>::GotoNextElement()
{
if (curhashelem)
curhashelem = curhashelem->listnext;
}
template<class Element,class GetIndex,int hashsize>
inline void RTPHashTable<Element,GetIndex,hashsize>::GotoPreviousElement()
{
if (curhashelem)
curhashelem = curhashelem->listprev;
}
template<class Element,class GetIndex,int hashsize>
inline void RTPHashTable<Element,GetIndex,hashsize>::Clear()
{
HashElement *tmp1,*tmp2;
for (int i = 0 ; i < hashsize ; i++)
table[i] = 0;
tmp1 = firsthashelem;
while (tmp1 != 0)
{
tmp2 = tmp1->listnext;
RTPDelete(tmp1,GetMemoryManager());
tmp1 = tmp2;
}
firsthashelem = 0;
lasthashelem = 0;
}
template<class Element,class GetIndex,int hashsize>
inline int RTPHashTable<Element,GetIndex,hashsize>::AddElement(const Element &elem)
{
int index;
bool found;
HashElement *e,*newelem;
index = GetIndex::GetIndex(elem);
if (index >= hashsize)
return ERR_RTP_HASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX;
e = table[index];
found = false;
while(!found && e != 0)
{
if (e->GetElement() == elem)
found = true;
else
e = e->hashnext;
}
if (found)
return ERR_RTP_HASHTABLE_ELEMENTALREADYEXISTS;
// Okay, the key doesn't exist, so we can add the new element in the hash table
newelem = RTPNew(GetMemoryManager(),memorytype) HashElement(elem,index);
if (newelem == 0)
return ERR_RTP_OUTOFMEM;
e = table[index];
table[index] = newelem;
newelem->hashnext = e;
if (e != 0)
e->hashprev = newelem;
// Now, we still got to add it to the linked list
if (firsthashelem == 0)
{
firsthashelem = newelem;
lasthashelem = newelem;
}
else // there already are some elements in the list
{
lasthashelem->listnext = newelem;
newelem->listprev = lasthashelem;
lasthashelem = newelem;
}
return 0;
}
template<class Element,class GetIndex,int hashsize>
inline int RTPHashTable<Element,GetIndex,hashsize>::DeleteElement(const Element &elem)
{
int status;
status = GotoElement(elem);
if (status < 0)
return status;
return DeleteCurrentElement();
}
} // end namespace
#endif // RTPHASHTABLE_H

View File

@ -0,0 +1,294 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpinternalsourcedata.h"
#include "rtppacket.h"
#include <string.h>
#define RTPINTERNALSOURCEDATA_MAXPROBATIONPACKETS 32
namespace qrtplib
{
RTPInternalSourceData::RTPInternalSourceData(uint32_t ssrc,RTPSources::ProbationType probtype,RTPMemoryManager *mgr):RTPSourceData(ssrc,mgr)
{
JRTPLIB_UNUSED(probtype); // possibly unused
#ifdef RTP_SUPPORT_PROBATION
probationtype = probtype;
#endif // RTP_SUPPORT_PROBATION
}
RTPInternalSourceData::~RTPInternalSourceData()
{
}
// The following function should delete rtppack if necessary
int RTPInternalSourceData::ProcessRTPPacket(RTPPacket *rtppack,const RTPTime &receivetime,bool *stored,RTPSources *sources)
{
bool accept,onprobation,applyprobation;
double tsunit;
*stored = false;
if (timestampunit < 0)
tsunit = INF_GetEstimatedTimestampUnit();
else
tsunit = timestampunit;
#ifdef RTP_SUPPORT_PROBATION
if (validated) // If the source is our own process, we can already be validated. No
applyprobation = false; // probation should be applied in that case.
else
{
if (probationtype == RTPSources::NoProbation)
applyprobation = false;
else
applyprobation = true;
}
#else
applyprobation = false;
#endif // RTP_SUPPORT_PROBATION
stats.ProcessPacket(rtppack,receivetime,tsunit,ownssrc,&accept,applyprobation,&onprobation);
#ifdef RTP_SUPPORT_PROBATION
switch (probationtype)
{
case RTPSources::ProbationStore:
if (!(onprobation || accept))
return 0;
if (accept)
validated = true;
break;
case RTPSources::ProbationDiscard:
case RTPSources::NoProbation:
if (!accept)
return 0;
validated = true;
break;
default:
return ERR_RTP_INTERNALSOURCEDATA_INVALIDPROBATIONTYPE;
}
#else
if (!accept)
return 0;
validated = true;
#endif // RTP_SUPPORT_PROBATION;
if (validated && !ownssrc) // for own ssrc these variables depend on the outgoing packets, not on the incoming
issender = true;
bool isonprobation = !validated;
bool ispackethandled = false;
sources->OnValidatedRTPPacket(this, rtppack, isonprobation, &ispackethandled);
if (ispackethandled) // Packet is already handled in the callback, no need to store it in the list
{
// Set 'stored' to true to avoid the packet being deallocated
*stored = true;
return 0;
}
// Now, we can place the packet in the queue
if (packetlist.empty())
{
*stored = true;
packetlist.push_back(rtppack);
return 0;
}
if (!validated) // still on probation
{
// Make sure that we don't buffer too much packets to avoid wasting memory
// on a bad source. Delete the packet in the queue with the lowest sequence
// number.
if (packetlist.size() == RTPINTERNALSOURCEDATA_MAXPROBATIONPACKETS)
{
RTPPacket *p = *(packetlist.begin());
packetlist.pop_front();
RTPDelete(p,GetMemoryManager());
}
}
// find the right position to insert the packet
std::list<RTPPacket*>::iterator it,start;
bool done = false;
uint32_t newseqnr = rtppack->GetExtendedSequenceNumber();
it = packetlist.end();
--it;
start = packetlist.begin();
while (!done)
{
RTPPacket *p;
uint32_t seqnr;
p = *it;
seqnr = p->GetExtendedSequenceNumber();
if (seqnr > newseqnr)
{
if (it != start)
--it;
else // we're at the start of the list
{
*stored = true;
done = true;
packetlist.push_front(rtppack);
}
}
else if (seqnr < newseqnr) // insert after this packet
{
++it;
packetlist.insert(it,rtppack);
done = true;
*stored = true;
}
else // they're equal !! Drop packet
{
done = true;
}
}
return 0;
}
int RTPInternalSourceData::ProcessSDESItem(uint8_t sdesid,const uint8_t *data,size_t itemlen,const RTPTime &receivetime,bool *cnamecollis)
{
*cnamecollis = false;
stats.SetLastMessageTime(receivetime);
switch(sdesid)
{
case RTCP_SDES_ID_CNAME:
{
size_t curlen;
uint8_t *oldcname;
// NOTE: we're going to make sure that the CNAME is only set once.
oldcname = SDESinf.GetCNAME(&curlen);
if (curlen == 0)
{
// if CNAME is set, the source is validated
SDESinf.SetCNAME(data,itemlen);
validated = true;
}
else // check if this CNAME is equal to the one that is already present
{
if (curlen != itemlen)
*cnamecollis = true;
else
{
if (memcmp(data,oldcname,itemlen) != 0)
*cnamecollis = true;
}
}
}
break;
case RTCP_SDES_ID_NAME:
{
size_t oldlen;
SDESinf.GetName(&oldlen);
if (oldlen == 0) // Name not set
return SDESinf.SetName(data,itemlen);
}
break;
case RTCP_SDES_ID_EMAIL:
{
size_t oldlen;
SDESinf.GetEMail(&oldlen);
if (oldlen == 0)
return SDESinf.SetEMail(data,itemlen);
}
break;
case RTCP_SDES_ID_PHONE:
return SDESinf.SetPhone(data,itemlen);
case RTCP_SDES_ID_LOCATION:
return SDESinf.SetLocation(data,itemlen);
case RTCP_SDES_ID_TOOL:
{
size_t oldlen;
SDESinf.GetTool(&oldlen);
if (oldlen == 0)
return SDESinf.SetTool(data,itemlen);
}
break;
case RTCP_SDES_ID_NOTE:
stats.SetLastNoteTime(receivetime);
return SDESinf.SetNote(data,itemlen);
}
return 0;
}
#ifdef RTP_SUPPORT_SDESPRIV
int RTPInternalSourceData::ProcessPrivateSDESItem(const uint8_t *prefix,size_t prefixlen,const uint8_t *value,size_t valuelen,const RTPTime &receivetime)
{
int status;
stats.SetLastMessageTime(receivetime);
status = SDESinf.SetPrivateValue(prefix,prefixlen,value,valuelen);
if (status == ERR_RTP_SDES_MAXPRIVITEMS)
return 0; // don't stop processing just because the number of items is full
return status;
}
#endif // RTP_SUPPORT_SDESPRIV
int RTPInternalSourceData::ProcessBYEPacket(const uint8_t *reason,size_t reasonlen,const RTPTime &receivetime)
{
if (byereason)
{
RTPDeleteByteArray(byereason,GetMemoryManager());
byereason = 0;
byereasonlen = 0;
}
byetime = receivetime;
byereason = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTCPBYEREASON) uint8_t[reasonlen];
if (byereason == 0)
return ERR_RTP_OUTOFMEM;
memcpy(byereason,reason,reasonlen);
byereasonlen = reasonlen;
receivedbye = true;
stats.SetLastMessageTime(receivetime);
return 0;
}
} // end namespace

View File

@ -0,0 +1,135 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpinternalsourcedata.h
*/
#ifndef RTPINTERNALSOURCEDATA_H
#define RTPINTERNALSOURCEDATA_H
#include "rtpconfig.h"
#include "rtpsourcedata.h"
#include "rtpaddress.h"
#include "rtptimeutilities.h"
#include "rtpsources.h"
namespace qrtplib
{
class JRTPLIB_IMPORTEXPORT RTPInternalSourceData : public RTPSourceData
{
public:
RTPInternalSourceData(uint32_t ssrc, RTPSources::ProbationType probtype, RTPMemoryManager *mgr = 0);
~RTPInternalSourceData();
int ProcessRTPPacket(RTPPacket *rtppack,const RTPTime &receivetime,bool *stored, RTPSources *sources);
void ProcessSenderInfo(const RTPNTPTime &ntptime,uint32_t rtptime,uint32_t packetcount,
uint32_t octetcount,const RTPTime &receivetime) { SRprevinf = SRinf; SRinf.Set(ntptime,rtptime,packetcount,octetcount,receivetime); stats.SetLastMessageTime(receivetime); }
void ProcessReportBlock(uint8_t fractionlost,int32_t lostpackets,uint32_t exthighseqnr,
uint32_t jitter,uint32_t lsr,uint32_t dlsr,
const RTPTime &receivetime) { RRprevinf = RRinf; RRinf.Set(fractionlost,lostpackets,exthighseqnr,jitter,lsr,dlsr,receivetime); stats.SetLastMessageTime(receivetime); }
void UpdateMessageTime(const RTPTime &receivetime) { stats.SetLastMessageTime(receivetime); }
int ProcessSDESItem(uint8_t sdesid,const uint8_t *data,size_t itemlen,const RTPTime &receivetime,bool *cnamecollis);
#ifdef RTP_SUPPORT_SDESPRIV
int ProcessPrivateSDESItem(const uint8_t *prefix,size_t prefixlen,const uint8_t *value,size_t valuelen,const RTPTime &receivetime);
#endif // RTP_SUPPORT_SDESPRIV
int ProcessBYEPacket(const uint8_t *reason,size_t reasonlen,const RTPTime &receivetime);
int SetRTPDataAddress(const RTPAddress *a);
int SetRTCPDataAddress(const RTPAddress *a);
void ClearSenderFlag() { issender = false; }
void SentRTPPacket() { if (!ownssrc) return; RTPTime t = RTPTime::CurrentTime(); issender = true; stats.SetLastRTPPacketTime(t); stats.SetLastMessageTime(t); }
void SetOwnSSRC() { ownssrc = true; validated = true; }
void SetCSRC() { validated = true; iscsrc = true; }
void ClearNote() { SDESinf.SetNote(0,0); }
#ifdef RTP_SUPPORT_PROBATION
private:
RTPSources::ProbationType probationtype;
#endif // RTP_SUPPORT_PROBATION
};
inline int RTPInternalSourceData::SetRTPDataAddress(const RTPAddress *a)
{
if (a == 0)
{
if (rtpaddr)
{
RTPDelete(rtpaddr,GetMemoryManager());
rtpaddr = 0;
}
}
else
{
RTPAddress *newaddr = a->CreateCopy(GetMemoryManager());
if (newaddr == 0)
return ERR_RTP_OUTOFMEM;
if (rtpaddr && a != rtpaddr)
RTPDelete(rtpaddr,GetMemoryManager());
rtpaddr = newaddr;
}
isrtpaddrset = true;
return 0;
}
inline int RTPInternalSourceData::SetRTCPDataAddress(const RTPAddress *a)
{
if (a == 0)
{
if (rtcpaddr)
{
RTPDelete(rtcpaddr,GetMemoryManager());
rtcpaddr = 0;
}
}
else
{
RTPAddress *newaddr = a->CreateCopy(GetMemoryManager());
if (newaddr == 0)
return ERR_RTP_OUTOFMEM;
if (rtcpaddr && a != rtcpaddr)
RTPDelete(rtcpaddr,GetMemoryManager());
rtcpaddr = newaddr;
}
isrtcpaddrset = true;
return 0;
}
} // end namespace
#endif // RTPINTERNALSOURCEDATA_H

View File

@ -0,0 +1,59 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef RTPINTERNALUTILS_H
#define RTPINTERNALUTILS_H
#include "rtpconfig.h"
#if defined(RTP_HAVE_SNPRINTF_S)
#include <windows.h>
#include <stdio.h>
#define RTP_SNPRINTF _snprintf_s
#elif defined(RTP_HAVE_SNPRINTF)
#include <windows.h>
#include <stdio.h>
#define RTP_SNPRINTF _snprintf
#else
#include <stdio.h>
#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 // RTPINTERNALUTILS_H

View File

@ -0,0 +1,74 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpipv4address.h"
#include "rtpmemorymanager.h"
namespace qrtplib
{
bool RTPIPv4Address::IsSameAddress(const RTPAddress *addr) const
{
if (addr == 0)
return false;
if (addr->GetAddressType() != IPv4Address)
return false;
const RTPIPv4Address *addr2 = (const RTPIPv4Address *)addr;
if (addr2->GetIP() == ip && addr2->GetPort() == port)
return true;
return false;
}
bool RTPIPv4Address::IsFromSameHost(const RTPAddress *addr) const
{
if (addr == 0)
return false;
if (addr->GetAddressType() != IPv4Address)
return false;
const RTPIPv4Address *addr2 = (const RTPIPv4Address *)addr;
if (addr2->GetIP() == ip)
return true;
return false;
}
RTPAddress *RTPIPv4Address::CreateCopy(RTPMemoryManager *mgr) const
{
JRTPLIB_UNUSED(mgr); // possibly unused
RTPIPv4Address *a = RTPNew(mgr,RTPMEM_TYPE_CLASS_RTPADDRESS) RTPIPv4Address(ip,port);
return a;
}
} // end namespace

149
qrtplib/rtpipv4address.h Normal file
View File

@ -0,0 +1,149 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpipv4address.h
*/
#ifndef RTPIPV4ADDRESS_H
#define RTPIPV4ADDRESS_H
#include "rtpconfig.h"
#include "rtpaddress.h"
#include "rtptypes.h"
namespace qrtplib
{
class RTPMemoryManager;
/** Represents an IPv4 IP address and port.
* This class is used by the UDP over IPv4 transmission component.
* When an RTPIPv4Address is used in one of the multicast functions of the transmitter, the port
* number is ignored. When an instance is used in one of the accept or ignore functions of the
* transmitter, a zero port number represents all ports for the specified IP address.
*/
class JRTPLIB_IMPORTEXPORT RTPIPv4Address : public RTPAddress
{
public:
/** Creates an instance with IP address \c ip and port number \c port (both
* are interpreted in host byte order), and possibly sets the RTCP multiplex flag
* (see RTPIPv4Address::UseRTCPMultiplexingOnTransmission). */
RTPIPv4Address(uint32_t ip = 0, uint16_t port = 0,bool rtcpmux = false):RTPAddress(IPv4Address)
{
RTPIPv4Address::ip = ip;
RTPIPv4Address::port = port;
if (rtcpmux)
rtcpsendport = port;
else
rtcpsendport = port+1;
}
/** Creates an instance with IP address \c ip and port number \c port (both
* are interpreted in host byte order), and sets a specific port to
* send RTCP packets to (see RTPIPv4Address::GetRTCPSendPort). */
RTPIPv4Address(uint32_t ip, uint16_t port, uint16_t rtcpsendport):RTPAddress(IPv4Address)
{
RTPIPv4Address::ip = ip;
RTPIPv4Address::port = port;
RTPIPv4Address::rtcpsendport = rtcpsendport;
}
/** Creates an instance with IP address \c ip and port number \c port (\c port is
* interpreted in host byte order) and possibly sets the RTCP multiplex flag
* (see RTPIPv4Address::UseRTCPMultiplexingOnTransmission). */
RTPIPv4Address(const uint8_t ip[4],uint16_t port = 0,bool rtcpmux = false):RTPAddress(IPv4Address)
{
RTPIPv4Address::ip = (uint32_t)ip[3];
RTPIPv4Address::ip |= (((uint32_t)ip[2])<<8);
RTPIPv4Address::ip |= (((uint32_t)ip[1])<<16);
RTPIPv4Address::ip |= (((uint32_t)ip[0])<<24);
RTPIPv4Address::port = port;
if (rtcpmux)
rtcpsendport = port;
else
rtcpsendport = port+1;
}
/** Creates an instance with IP address \c ip and port number \c port (both
* are interpreted in host byte order), and sets a specific port to
* send RTCP packets to (see RTPIPv4Address::GetRTCPSendPort). */
RTPIPv4Address(const uint8_t ip[4],uint16_t port,uint16_t rtcpsendport):RTPAddress(IPv4Address)
{
RTPIPv4Address::ip = (uint32_t)ip[3];
RTPIPv4Address::ip |= (((uint32_t)ip[2])<<8);
RTPIPv4Address::ip |= (((uint32_t)ip[1])<<16);
RTPIPv4Address::ip |= (((uint32_t)ip[0])<<24);
RTPIPv4Address::port = port;
RTPIPv4Address::rtcpsendport = rtcpsendport;
}
~RTPIPv4Address() { }
/** Sets the IP address for this instance to \c ip which is assumed to be in host byte order. */
void SetIP(uint32_t ip) { RTPIPv4Address::ip = ip; }
/** Sets the IP address of this instance to \c ip. */
void SetIP(const uint8_t ip[4]) { RTPIPv4Address::ip = (uint32_t)ip[3]; RTPIPv4Address::ip |= (((uint32_t)ip[2])<<8); RTPIPv4Address::ip |= (((uint32_t)ip[1])<<16); RTPIPv4Address::ip |= (((uint32_t)ip[0])<<24); }
/** Sets the port number for this instance to \c port which is interpreted in host byte order. */
void SetPort(uint16_t port) { RTPIPv4Address::port = port; }
/** Returns the IP address contained in this instance in host byte order. */
uint32_t GetIP() const { return ip; }
/** Returns the port number of this instance in host byte order. */
uint16_t GetPort() const { return port; }
/** For outgoing packets, this indicates to which port RTCP packets will be sent (can,
* be the same port as the RTP packets in case RTCP multiplexing is used). */
uint16_t GetRTCPSendPort() const { return rtcpsendport; }
RTPAddress *CreateCopy(RTPMemoryManager *mgr) const;
// Note that these functions are only used for received packets, and for those
// the rtcpsendport variable is not important and should be ignored.
bool IsSameAddress(const RTPAddress *addr) const;
bool IsFromSameHost(const RTPAddress *addr) const;
private:
uint32_t ip;
uint16_t port;
uint16_t rtcpsendport;
};
} // end namespace
#endif // RTPIPV4ADDRESS_H

View File

@ -0,0 +1,51 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpipv4destination.h"
#include "rtpinternalutils.h"
namespace qrtplib
{
std::string RTPIPv4Destination::GetDestinationString() const
{
char str[24];
uint32_t ip = GetIP();
uint16_t portbase = ntohs(GetRTPPort_NBO());
RTP_SNPRINTF(str,24,"%d.%d.%d.%d:%d",(int)((ip>>24)&0xFF),(int)((ip>>16)&0xFF),(int)((ip>>8)&0xFF),(int)(ip&0xFF),(int)(portbase));
return std::string(str);
}
} // end namespace

View File

@ -0,0 +1,118 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpipv4destination.h
*/
#ifndef RTPIPV4DESTINATION_H
#define RTPIPV4DESTINATION_H
#include "rtpconfig.h"
#include "rtptypes.h"
#include "rtpipv4address.h"
#ifndef RTP_SOCKETTYPE_WINSOCK
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#endif // RTP_SOCKETTYPE_WINSOCK
#include <string.h>
#include <string>
namespace qrtplib
{
class JRTPLIB_IMPORTEXPORT RTPIPv4Destination
{
public:
RTPIPv4Destination()
{
ip = 0;
memset(&rtpaddr,0,sizeof(struct sockaddr_in));
memset(&rtcpaddr,0,sizeof(struct sockaddr_in));
}
RTPIPv4Destination(uint32_t ip,uint16_t rtpport,uint16_t rtcpport)
{
memset(&rtpaddr,0,sizeof(struct sockaddr_in));
memset(&rtcpaddr,0,sizeof(struct sockaddr_in));
rtpaddr.sin_family = AF_INET;
rtpaddr.sin_port = htons(rtpport);
rtpaddr.sin_addr.s_addr = htonl(ip);
rtcpaddr.sin_family = AF_INET;
rtcpaddr.sin_port = htons(rtcpport);
rtcpaddr.sin_addr.s_addr = htonl(ip);
RTPIPv4Destination::ip = ip;
}
bool operator==(const RTPIPv4Destination &src) const
{
if (rtpaddr.sin_addr.s_addr == src.rtpaddr.sin_addr.s_addr && rtpaddr.sin_port == src.rtpaddr.sin_port)
return true;
return false;
}
uint32_t GetIP() const { return ip; }
// nbo = network byte order
uint32_t GetIP_NBO() const { return rtpaddr.sin_addr.s_addr; }
uint16_t GetRTPPort_NBO() const { return rtpaddr.sin_port; }
uint16_t GetRTCPPort_NBO() const { return rtcpaddr.sin_port; }
const struct sockaddr_in *GetRTPSockAddr() const { return &rtpaddr; }
const struct sockaddr_in *GetRTCPSockAddr() const { return &rtcpaddr; }
std::string GetDestinationString() const;
static bool AddressToDestination(const RTPAddress &addr, RTPIPv4Destination &dest)
{
if (addr.GetAddressType() != RTPAddress::IPv4Address)
return false;
const RTPIPv4Address &address = (const RTPIPv4Address &)addr;
uint16_t rtpport = address.GetPort();
uint16_t rtcpport = address.GetRTCPSendPort();
dest = RTPIPv4Destination(address.GetIP(),rtpport,rtcpport);
return true;
}
private:
uint32_t ip;
struct sockaddr_in rtpaddr;
struct sockaddr_in rtcpaddr;
};
} // end namespace
#endif // RTPIPV4DESTINATION_H

View File

@ -0,0 +1,91 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpipv6address.h"
#include "rtpmemorymanager.h"
#ifdef RTP_SUPPORT_IPV6
namespace qrtplib
{
RTPAddress *RTPIPv6Address::CreateCopy(RTPMemoryManager *mgr) const
{
JRTPLIB_UNUSED(mgr); // possibly unused
RTPIPv6Address *newaddr = RTPNew(mgr,RTPMEM_TYPE_CLASS_RTPADDRESS) RTPIPv6Address(ip,port);
return newaddr;
}
bool RTPIPv6Address::IsSameAddress(const RTPAddress *addr) const
{
if (addr == 0)
return false;
if (addr->GetAddressType() != RTPAddress::IPv6Address)
return false;
const RTPIPv6Address *addr2 = (const RTPIPv6Address *)addr;
const uint8_t *ip2 = addr2->ip.s6_addr;
if (port != addr2->port)
return false;
for (int i = 0 ; i < 16 ; i++)
{
if (ip.s6_addr[i] != ip2[i])
return false;
}
return true;
}
bool RTPIPv6Address::IsFromSameHost(const RTPAddress *addr) const
{
if (addr == 0)
return false;
if (addr->GetAddressType() != RTPAddress::IPv6Address)
return false;
const RTPIPv6Address *addr2 = (const RTPIPv6Address *)addr;
const uint8_t *ip2 = addr2->ip.s6_addr;
for (int i = 0 ; i < 16 ; i++)
{
if (ip.s6_addr[i] != ip2[i])
return false;
}
return true;
}
} // end namespace
#endif // RTP_SUPPORT_IPV6

108
qrtplib/rtpipv6address.h Normal file
View File

@ -0,0 +1,108 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpipv6address.h
*/
#ifndef RTPIPV6ADDRESS_H
#define RTPIPV6ADDRESS_H
#include "rtpconfig.h"
#ifdef RTP_SUPPORT_IPV6
#include "rtpaddress.h"
#include "rtptypes.h"
#ifdef RTP_SUPPORT_NETINET_IN
#include <netinet/in.h>
#endif // RTP_SUPPORT_NETINET_IN
namespace qrtplib
{
/** Represents an IPv6 IP address and port.
* This class is used by the UDP over IPv4 transmission component.
* When an RTPIPv6Address is used in one of the multicast functions of the
* transmitter, the port number is ignored. When an instance is used in one of
* the accept or ignore functions of the transmitter, a zero port number represents
* all ports for the specified IP address.
*/
class JRTPLIB_IMPORTEXPORT RTPIPv6Address : public RTPAddress
{
public:
/** Creates an instance with IP address and port number set to zero. */
RTPIPv6Address():RTPAddress(IPv6Address) { for (int i = 0 ; i < 16 ; i++) ip.s6_addr[i] = 0; port = 0; }
/** Creates an instance with IP address \c ip and port number \c port (the port number is assumed to be in
* host byte order). */
RTPIPv6Address(const uint8_t ip[16],uint16_t port = 0):RTPAddress(IPv6Address) { SetIP(ip); RTPIPv6Address::port = port; }
/** Creates an instance with IP address \c ip and port number \c port (the port number is assumed to be in
* host byte order). */
RTPIPv6Address(in6_addr ip,uint16_t port = 0):RTPAddress(IPv6Address) { RTPIPv6Address::ip = ip; RTPIPv6Address::port = port; }
~RTPIPv6Address() { }
/** Sets the IP address for this instance to \c ip. */
void SetIP(in6_addr ip) { RTPIPv6Address::ip = ip; }
/** Sets the IP address for this instance to \c ip. */
void SetIP(const uint8_t ip[16]) { for (int i = 0 ; i < 16 ; i++) RTPIPv6Address::ip.s6_addr[i] = ip[i]; }
/** Sets the port number for this instance to \c port, which is interpreted in host byte order. */
void SetPort(uint16_t port) { RTPIPv6Address::port = port; }
/** Copies the IP address of this instance in \c ip. */
void GetIP(uint8_t ip[16]) const { for (int i = 0 ; i < 16 ; i++) ip[i] = RTPIPv6Address::ip.s6_addr[i]; }
/** Returns the IP address of this instance. */
in6_addr GetIP() const { return ip; }
/** Returns the port number contained in this instance in host byte order. */
uint16_t GetPort() const { return port; }
RTPAddress *CreateCopy(RTPMemoryManager *mgr) const;
bool IsSameAddress(const RTPAddress *addr) const;
bool IsFromSameHost(const RTPAddress *addr) const;
private:
in6_addr ip;
uint16_t port;
};
} // end namespace
#endif // RTP_SUPPORT_IPV6
#endif // RTPIPV6ADDRESS_H

View File

@ -0,0 +1,61 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2011 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpipv6destination.h"
#ifdef RTP_SUPPORT_IPV6
#include "rtpinternalutils.h"
namespace qrtplib
{
std::string RTPIPv6Destination::GetDestinationString() const
{
uint16_t ip16[8];
char str[48];
uint16_t portbase = ntohs(rtpaddr.sin6_port);
int i,j;
for (i = 0,j = 0 ; j < 8 ; j++,i += 2)
{
ip16[j] = (((uint16_t)rtpaddr.sin6_addr.s6_addr[i])<<8);
ip16[j] |= ((uint16_t)rtpaddr.sin6_addr.s6_addr[i+1]);
}
RTP_SNPRINTF(str,48,"%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X/%d",(int)ip16[0],(int)ip16[1],(int)ip16[2],(int)ip16[3],(int)ip16[4],(int)ip16[5],(int)ip16[6],(int)ip16[7],(int)portbase);
return std::string(str);
}
} // end namespace
#endif // RTP_SUPPORT_IPV6

View File

@ -0,0 +1,91 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpipv6destination.h
*/
#ifndef RTPIPV6DESTINATION_H
#define RTPIPV6DESTINATION_H
#include "rtpconfig.h"
#ifdef RTP_SUPPORT_IPV6
#include "rtptypes.h"
#include <string.h>
#include <string>
#ifndef RTP_SOCKETTYPE_WINSOCK
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#endif // RTP_SOCKETTYPE_WINSOCK
namespace qrtplib
{
class JRTPLIB_IMPORTEXPORT RTPIPv6Destination
{
public:
RTPIPv6Destination(in6_addr ip,uint16_t portbase)
{
memset(&rtpaddr,0,sizeof(struct sockaddr_in6));
memset(&rtcpaddr,0,sizeof(struct sockaddr_in6));
rtpaddr.sin6_family = AF_INET6;
rtpaddr.sin6_port = htons(portbase);
rtpaddr.sin6_addr = ip;
rtcpaddr.sin6_family = AF_INET6;
rtcpaddr.sin6_port = htons(portbase+1);
rtcpaddr.sin6_addr = ip;
}
in6_addr GetIP() const { return rtpaddr.sin6_addr; }
bool operator==(const RTPIPv6Destination &src) const
{
if (rtpaddr.sin6_port == src.rtpaddr.sin6_port && (memcmp(&(src.rtpaddr.sin6_addr),&(rtpaddr.sin6_addr),sizeof(in6_addr)) == 0))
return true;
return false;
}
const struct sockaddr_in6 *GetRTPSockAddr() const { return &rtpaddr; }
const struct sockaddr_in6 *GetRTCPSockAddr() const { return &rtcpaddr; }
std::string GetDestinationString() const;
private:
struct sockaddr_in6 rtpaddr;
struct sockaddr_in6 rtcpaddr;
};
} // end namespace
#endif // RTP_SUPPORT_IPV6
#endif // RTPIPV6DESTINATION_H

310
qrtplib/rtpkeyhashtable.h Normal file
View File

@ -0,0 +1,310 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpkeyhashtable.h
*/
#ifndef RTPKEYHASHTABLE_H
#define RTPKEYHASHTABLE_H
#include "rtpconfig.h"
#include "rtperrors.h"
#include "rtpmemoryobject.h"
namespace qrtplib
{
template<class Key,class Element,class GetIndex,int hashsize>
class RTPKeyHashTable : public RTPMemoryObject
{
public:
RTPKeyHashTable(RTPMemoryManager *mgr = 0,int memtype = RTPMEM_TYPE_OTHER);
~RTPKeyHashTable() { Clear(); }
void GotoFirstElement() { curhashelem = firsthashelem; }
void GotoLastElement() { curhashelem = lasthashelem; }
bool HasCurrentElement() { return (curhashelem == 0)?false:true; }
int DeleteCurrentElement();
Element &GetCurrentElement() { return curhashelem->GetElement(); }
Key &GetCurrentKey() { return curhashelem->GetKey(); }
int GotoElement(const Key &k);
bool HasElement(const Key &k);
void GotoNextElement();
void GotoPreviousElement();
void Clear();
int AddElement(const Key &k,const Element &elem);
int DeleteElement(const Key &k);
private:
class HashElement
{
public:
HashElement(const Key &k,const Element &e,int index):key(k),element(e) { hashprev = 0; hashnext = 0; listnext = 0; listprev = 0; hashindex = index; }
int GetHashIndex() { return hashindex; }
Key &GetKey() { return key; }
Element &GetElement() { return element; }
private:
int hashindex;
Key key;
Element element;
public:
HashElement *hashprev,*hashnext;
HashElement *listprev,*listnext;
};
HashElement *table[hashsize];
HashElement *firsthashelem,*lasthashelem;
HashElement *curhashelem;
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
int memorytype;
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
};
template<class Key,class Element,class GetIndex,int hashsize>
inline RTPKeyHashTable<Key,Element,GetIndex,hashsize>::RTPKeyHashTable(RTPMemoryManager *mgr,int memtype) : RTPMemoryObject(mgr)
{
JRTPLIB_UNUSED(memtype); // possibly unused
for (int i = 0 ; i < hashsize ; i++)
table[i] = 0;
firsthashelem = 0;
lasthashelem = 0;
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
memorytype = memtype;
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
}
template<class Key,class Element,class GetIndex,int hashsize>
inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::DeleteCurrentElement()
{
if (curhashelem)
{
HashElement *tmp1,*tmp2;
int index;
// First, relink elements in current hash bucket
index = curhashelem->GetHashIndex();
tmp1 = curhashelem->hashprev;
tmp2 = curhashelem->hashnext;
if (tmp1 == 0) // no previous element in hash bucket
{
table[index] = tmp2;
if (tmp2 != 0)
tmp2->hashprev = 0;
}
else // there is a previous element in the hash bucket
{
tmp1->hashnext = tmp2;
if (tmp2 != 0)
tmp2->hashprev = tmp1;
}
// Relink elements in list
tmp1 = curhashelem->listprev;
tmp2 = curhashelem->listnext;
if (tmp1 == 0) // curhashelem is first in list
{
firsthashelem = tmp2;
if (tmp2 != 0)
tmp2->listprev = 0;
else // curhashelem is also last in list
lasthashelem = 0;
}
else
{
tmp1->listnext = tmp2;
if (tmp2 != 0)
tmp2->listprev = tmp1;
else // curhashelem is last in list
lasthashelem = tmp1;
}
// finally, with everything being relinked, we can delete curhashelem
RTPDelete(curhashelem,GetMemoryManager());
curhashelem = tmp2; // Set to next element in list
}
else
return ERR_RTP_KEYHASHTABLE_NOCURRENTELEMENT;
return 0;
}
template<class Key,class Element,class GetIndex,int hashsize>
inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::GotoElement(const Key &k)
{
int index;
bool found;
index = GetIndex::GetIndex(k);
if (index >= hashsize)
return ERR_RTP_KEYHASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX;
curhashelem = table[index];
found = false;
while(!found && curhashelem != 0)
{
if (curhashelem->GetKey() == k)
found = true;
else
curhashelem = curhashelem->hashnext;
}
if (!found)
return ERR_RTP_KEYHASHTABLE_KEYNOTFOUND;
return 0;
}
template<class Key,class Element,class GetIndex,int hashsize>
inline bool RTPKeyHashTable<Key,Element,GetIndex,hashsize>::HasElement(const Key &k)
{
int index;
bool found;
HashElement *tmp;
index = GetIndex::GetIndex(k);
if (index >= hashsize)
return false;
tmp = table[index];
found = false;
while(!found && tmp != 0)
{
if (tmp->GetKey() == k)
found = true;
else
tmp = tmp->hashnext;
}
return found;
}
template<class Key,class Element,class GetIndex,int hashsize>
inline void RTPKeyHashTable<Key,Element,GetIndex,hashsize>::GotoNextElement()
{
if (curhashelem)
curhashelem = curhashelem->listnext;
}
template<class Key,class Element,class GetIndex,int hashsize>
inline void RTPKeyHashTable<Key,Element,GetIndex,hashsize>::GotoPreviousElement()
{
if (curhashelem)
curhashelem = curhashelem->listprev;
}
template<class Key,class Element,class GetIndex,int hashsize>
inline void RTPKeyHashTable<Key,Element,GetIndex,hashsize>::Clear()
{
HashElement *tmp1,*tmp2;
for (int i = 0 ; i < hashsize ; i++)
table[i] = 0;
tmp1 = firsthashelem;
while (tmp1 != 0)
{
tmp2 = tmp1->listnext;
RTPDelete(tmp1,GetMemoryManager());
tmp1 = tmp2;
}
firsthashelem = 0;
lasthashelem = 0;
}
template<class Key,class Element,class GetIndex,int hashsize>
inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::AddElement(const Key &k,const Element &elem)
{
int index;
bool found;
HashElement *e,*newelem;
index = GetIndex::GetIndex(k);
if (index >= hashsize)
return ERR_RTP_KEYHASHTABLE_FUNCTIONRETURNEDINVALIDHASHINDEX;
e = table[index];
found = false;
while(!found && e != 0)
{
if (e->GetKey() == k)
found = true;
else
e = e->hashnext;
}
if (found)
return ERR_RTP_KEYHASHTABLE_KEYALREADYEXISTS;
// Okay, the key doesn't exist, so we can add the new element in the hash table
newelem = RTPNew(GetMemoryManager(),memorytype) HashElement(k,elem,index);
if (newelem == 0)
return ERR_RTP_OUTOFMEM;
e = table[index];
table[index] = newelem;
newelem->hashnext = e;
if (e != 0)
e->hashprev = newelem;
// Now, we still got to add it to the linked list
if (firsthashelem == 0)
{
firsthashelem = newelem;
lasthashelem = newelem;
}
else // there already are some elements in the list
{
lasthashelem->listnext = newelem;
newelem->listprev = lasthashelem;
lasthashelem = newelem;
}
return 0;
}
template<class Key,class Element,class GetIndex,int hashsize>
inline int RTPKeyHashTable<Key,Element,GetIndex,hashsize>::DeleteElement(const Key &k)
{
int status;
status = GotoElement(k);
if (status < 0)
return status;
return DeleteCurrentElement();
}
} // end namespace
#endif // RTPKEYHASHTABLE_H

View File

@ -0,0 +1,57 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtplibraryversion.h"
#include "rtpdefines.h"
#include "rtplibraryversioninternal.h"
#include "rtpinternalutils.h"
#include <stdio.h>
namespace qrtplib
{
RTPLibraryVersion RTPLibraryVersion::GetVersion()
{
return RTPLibraryVersion(JRTPLIB_VERSION_MAJOR, JRTPLIB_VERSION_MINOR, JRTPLIB_VERSION_DEBUG);
}
std::string RTPLibraryVersion::GetVersionString() const
{
char str[16];
RTP_SNPRINTF(str,16,"%d.%d.%d",majornr,minornr,debugnr);
return std::string(str);
}
} // end namespace

View File

@ -0,0 +1,77 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtplibraryversion.h
*/
#ifndef RTPLIBRARYVERSION_H
#define RTPLIBRARYVERSION_H
#include "rtpconfig.h"
#include <string>
#include <stdio.h>
namespace qrtplib
{
/**
* Used to provide information about the version of the library.
*/
class JRTPLIB_IMPORTEXPORT RTPLibraryVersion
{
public:
/** Returns an instance of RTPLibraryVersion describing the version of the library. */
static RTPLibraryVersion GetVersion();
private:
RTPLibraryVersion(int major,int minor,int debug) { majornr = major; minornr = minor; debugnr = debug; }
public:
/** Returns the major version number. */
int GetMajorNumber() const { return majornr; }
/** Returns the minor version number. */
int GetMinorNumber() const { return minornr; }
/** Returns the debug version number. */
int GetDebugNumber() const { return debugnr; }
/** Returns a string describing the library version. */
std::string GetVersionString() const;
private:
int debugnr,minornr,majornr;
};
} // end namespace
#endif // RTPLIBRARYVERSION_H

View File

@ -0,0 +1,46 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtplibraryversioninternal.h
*/
#ifndef RTPLIBRARYVERSIONINTERNAL_H
#define RTPLIBRARYVERSIONINTERNAL_H
#define JRTPLIB_VERSION_MAJOR 3
#define JRTPLIB_VERSION_MINOR 11
#define JRTPLIB_VERSION_DEBUG 1
#endif // RTPLIBRARYVERSIONINTERNAL_H

245
qrtplib/rtpmemorymanager.h Normal file
View File

@ -0,0 +1,245 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpmemorymanager.h
*/
#ifndef RTPMEMORYMANAGER_H
#define RTPMEMORYMANAGER_H
#include "rtpconfig.h"
#include "rtptypes.h"
/** Used to indicate a general kind of memory block. */
#define RTPMEM_TYPE_OTHER 0
/** Buffer to store an incoming RTP packet. */
#define RTPMEM_TYPE_BUFFER_RECEIVEDRTPPACKET 1
/** Buffer to store an incoming RTCP packet. */
#define RTPMEM_TYPE_BUFFER_RECEIVEDRTCPPACKET 2
/** Buffer to store an RTCP APP packet. */
#define RTPMEM_TYPE_BUFFER_RTCPAPPPACKET 3
/** Buffer to store an RTCP BYE packet. */
#define RTPMEM_TYPE_BUFFER_RTCPBYEPACKET 4
/** Buffer to store a BYE reason. */
#define RTPMEM_TYPE_BUFFER_RTCPBYEREASON 5
/** Buffer to store an RTCP compound packet. */
#define RTPMEM_TYPE_BUFFER_RTCPCOMPOUNDPACKET 6
/** Buffer to store an SDES block. */
#define RTPMEM_TYPE_BUFFER_RTCPSDESBLOCK 7
/** Buffer to store an RTP packet. */
#define RTPMEM_TYPE_BUFFER_RTPPACKET 8
/** Buffer used by an RTPPacketBuilder instance. */
#define RTPMEM_TYPE_BUFFER_RTPPACKETBUILDERBUFFER 9
/** Buffer to store an SDES item. */
#define RTPMEM_TYPE_BUFFER_SDESITEM 10
/** Hash element used in the accept/ignore table. */
#define RTPMEM_TYPE_CLASS_ACCEPTIGNOREHASHELEMENT 11
/** Buffer to store a PortInfo instance, used by the UDP over IPv4 and IPv6 transmitters. */
#define RTPMEM_TYPE_CLASS_ACCEPTIGNOREPORTINFO 12
/** Buffer to store a HashElement instance for the destination hash table. */
#define RTPMEM_TYPE_CLASS_DESTINATIONLISTHASHELEMENT 13
/** Buffer to store a HashElement instance for the multicast hash table. */
#define RTPMEM_TYPE_CLASS_MULTICASTHASHELEMENT 14
/** Buffer to store an instance of RTCPAPPPacket. */
#define RTPMEM_TYPE_CLASS_RTCPAPPPACKET 15
/** Buffer to store an instance of RTCPBYEPacket. */
#define RTPMEM_TYPE_CLASS_RTCPBYEPACKET 16
/** Buffer to store an instance of RTCPCompoundPacketBuilder. */
#define RTPMEM_TYPE_CLASS_RTCPCOMPOUNDPACKETBUILDER 17
/** Buffer to store an RTCPReceiverReport instance. */
#define RTPMEM_TYPE_CLASS_RTCPRECEIVERREPORT 18
/** Buffer to store an instance of RTCPRRPacket. */
#define RTPMEM_TYPE_CLASS_RTCPRRPACKET 19
/** Buffer to store an instance of RTCPSDESPacket. */
#define RTPMEM_TYPE_CLASS_RTCPSDESPACKET 20
/** Buffer to store an instance of RTCPSRPacket. */
#define RTPMEM_TYPE_CLASS_RTCPSRPACKET 21
/** Buffer to store an instance of RTCPUnknownPacket. */
#define RTPMEM_TYPE_CLASS_RTCPUNKNOWNPACKET 22
/** Buffer to store an instance of an RTPAddress derived class. */
#define RTPMEM_TYPE_CLASS_RTPADDRESS 23
/** Buffer to store an instance of RTPInternalSourceData. */
#define RTPMEM_TYPE_CLASS_RTPINTERNALSOURCEDATA 24
/** Buffer to store an RTPPacket instance. */
#define RTPMEM_TYPE_CLASS_RTPPACKET 25
/** Buffer to store an RTPPollThread instance. */
#define RTPMEM_TYPE_CLASS_RTPPOLLTHREAD 26
/** Buffer to store an RTPRawPacket instance. */
#define RTPMEM_TYPE_CLASS_RTPRAWPACKET 27
/** Buffer to store an RTPTransmissionInfo derived class. */
#define RTPMEM_TYPE_CLASS_RTPTRANSMISSIONINFO 28
/** Buffer to store an RTPTransmitter derived class. */
#define RTPMEM_TYPE_CLASS_RTPTRANSMITTER 29
/** Buffer to store an SDESPrivateItem instance. */
#define RTPMEM_TYPE_CLASS_SDESPRIVATEITEM 30
/** Buffer to store an SDESSource instance. */
#define RTPMEM_TYPE_CLASS_SDESSOURCE 31
/** Buffer to store a HashElement instance for the source table. */
#define RTPMEM_TYPE_CLASS_SOURCETABLEHASHELEMENT 32
/** Buffer that's used when encrypting a packet. */
#define RTPMEM_TYPE_BUFFER_SRTPDATA 33
namespace qrtplib
{
/** A memory manager. */
class JRTPLIB_IMPORTEXPORT RTPMemoryManager
{
public:
RTPMemoryManager() { }
virtual ~RTPMemoryManager() { }
/** Called to allocate \c numbytes of memory.
* Called to allocate \c numbytes of memory. The \c memtype parameter
* indicates what the purpose of the memory block is. Relevant values
* can be found in rtpmemorymanager.h . Note that the types starting with
* \c RTPMEM_TYPE_CLASS indicate fixed size buffers and that types starting
* with \c RTPMEM_TYPE_BUFFER indicate variable size buffers.
*/
virtual void *AllocateBuffer(size_t numbytes, int memtype) = 0;
/** Frees the previously allocated memory block \c buffer */
virtual void FreeBuffer(void *buffer) = 0;
};
} // end namespace
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
#include <new>
inline void *operator new(size_t numbytes, qrtplib::RTPMemoryManager *mgr, int memtype)
{
if (mgr == 0)
return operator new(numbytes);
return mgr->AllocateBuffer(numbytes,memtype);
}
inline void operator delete(void *buffer, qrtplib::RTPMemoryManager *mgr, int memtype)
{
JRTPLIB_UNUSED(memtype);
if (mgr == 0)
operator delete(buffer);
else
mgr->FreeBuffer(buffer);
}
#ifdef RTP_HAVE_ARRAYALLOC
inline void *operator new[](size_t numbytes, qrtplib::RTPMemoryManager *mgr, int memtype)
{
if (mgr == 0)
return operator new[](numbytes);
return mgr->AllocateBuffer(numbytes,memtype);
}
inline void operator delete[](void *buffer, qrtplib::RTPMemoryManager *mgr, int memtype)
{
JRTPLIB_UNUSED(memtype);
if (mgr == 0)
operator delete[](buffer);
else
mgr->FreeBuffer(buffer);
}
#endif // RTP_HAVE_ARRAYALLOC
namespace qrtplib
{
inline void RTPDeleteByteArray(uint8_t *buf, RTPMemoryManager *mgr)
{
if (mgr == 0)
delete [] buf;
else
mgr->FreeBuffer(buf);
}
template<class ClassName>
inline void RTPDelete(ClassName *obj, RTPMemoryManager *mgr)
{
if (mgr == 0)
delete obj;
else
{
obj->~ClassName();
mgr->FreeBuffer(obj);
}
}
} // end namespace
#define RTPNew(a,b) new(a,b)
#else
#define RTPNew(a,b) new
#define RTPDelete(a,b) delete a
#define RTPDeleteByteArray(a,b) delete [] a;
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
#endif // RTPMEMORYMANAGER_H

74
qrtplib/rtpmemoryobject.h Normal file
View File

@ -0,0 +1,74 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpmemoryobject.h
*/
#ifndef RTPMEMORYOBJECT_H
#define RTPMEMORYOBJECT_H
#include "rtpconfig.h"
#include "rtpmemorymanager.h"
namespace qrtplib
{
class JRTPLIB_IMPORTEXPORT RTPMemoryObject
{
protected:
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
RTPMemoryObject(RTPMemoryManager *memmgr) : mgr(memmgr) { }
#else
RTPMemoryObject(RTPMemoryManager *memmgr) { JRTPLIB_UNUSED(memmgr); }
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
virtual ~RTPMemoryObject() { }
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
RTPMemoryManager *GetMemoryManager() const { return mgr; }
void SetMemoryManager(RTPMemoryManager *m) { mgr = m; }
#else
RTPMemoryManager *GetMemoryManager() const { return 0; }
void SetMemoryManager(RTPMemoryManager *m) { JRTPLIB_UNUSED(m); }
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
private:
RTPMemoryManager *mgr;
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
};
} // end namespace
#endif // RTPMEMORYOBJECT_H

317
qrtplib/rtppacket.cpp Normal file
View File

@ -0,0 +1,317 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtppacket.h"
#include "rtpstructs.h"
#include "rtpdefines.h"
#include "rtperrors.h"
#include "rtprawpacket.h"
#ifdef RTP_SUPPORT_NETINET_IN
#include <netinet/in.h>
#endif // RTP_SUPPORT_NETINET_IN
#include <string.h>
namespace qrtplib
{
void RTPPacket::Clear()
{
hasextension = false;
hasmarker = false;
numcsrcs = 0;
payloadtype = 0;
extseqnr = 0;
timestamp = 0;
ssrc = 0;
packet = 0;
payload = 0;
packetlength = 0;
payloadlength = 0;
extid = 0;
extension = 0;
extensionlength = 0;
error = 0;
externalbuffer = false;
}
RTPPacket::RTPPacket(RTPRawPacket &rawpack,RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(rawpack.GetReceiveTime())
{
Clear();
error = ParseRawPacket(rawpack);
}
RTPPacket::RTPPacket(uint8_t payloadtype,const void *payloaddata,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,
size_t maxpacksize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
{
Clear();
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,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,size_t buffersize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
{
Clear();
if (buffer == 0)
error = ERR_RTP_PACKET_EXTERNALBUFFERNULL;
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);
}
int RTPPacket::ParseRawPacket(RTPRawPacket &rawpack)
{
uint8_t *packetbytes;
size_t packetlen;
uint8_t payloadtype;
RTPHeader *rtpheader;
bool marker;
int csrccount;
bool hasextension;
int payloadoffset,payloadlength;
int numpadbytes;
RTPExtensionHeader *rtpextheader;
if (!rawpack.IsRTP()) // If we didn't receive it on the RTP port, we'll ignore it
return ERR_RTP_PACKET_INVALIDPACKET;
// The length should be at least the size of the RTP header
packetlen = rawpack.GetDataLength();
if (packetlen < sizeof(RTPHeader))
return ERR_RTP_PACKET_INVALIDPACKET;
packetbytes = (uint8_t *)rawpack.GetData();
rtpheader = (RTPHeader *)packetbytes;
// The version number should be correct
if (rtpheader->version != RTP_VERSION)
return ERR_RTP_PACKET_INVALIDPACKET;
// We'll check if this is possibly a RTCP packet. For this to be possible
// the marker bit and payload type combined should be either an SR or RR
// identifier
marker = (rtpheader->marker == 0)?false:true;
payloadtype = rtpheader->payloadtype;
if (marker)
{
if (payloadtype == (RTP_RTCPTYPE_SR & 127)) // don't check high bit (this was the marker!!)
return ERR_RTP_PACKET_INVALIDPACKET;
if (payloadtype == (RTP_RTCPTYPE_RR & 127))
return ERR_RTP_PACKET_INVALIDPACKET;
}
csrccount = rtpheader->csrccount;
payloadoffset = sizeof(RTPHeader)+(int)(csrccount*sizeof(uint32_t));
if (rtpheader->padding) // adjust payload length to take padding into account
{
numpadbytes = (int)packetbytes[packetlen-1]; // last byte contains number of padding bytes
if (numpadbytes <= 0)
return ERR_RTP_PACKET_INVALIDPACKET;
}
else
numpadbytes = 0;
hasextension = (rtpheader->extension == 0)?false:true;
if (hasextension) // got header extension
{
rtpextheader = (RTPExtensionHeader *)(packetbytes+payloadoffset);
payloadoffset += sizeof(RTPExtensionHeader);
uint16_t exthdrlen = ntohs(rtpextheader->length);
payloadoffset += ((int)exthdrlen)*sizeof(uint32_t);
}
else
{
rtpextheader = 0;
}
payloadlength = packetlen-numpadbytes-payloadoffset;
if (payloadlength < 0)
return ERR_RTP_PACKET_INVALIDPACKET;
// Now, we've got a valid packet, so we can create a new instance of RTPPacket
// and fill in the members
RTPPacket::hasextension = hasextension;
if (hasextension)
{
RTPPacket::extid = ntohs(rtpextheader->extid);
RTPPacket::extensionlength = ((int)ntohs(rtpextheader->length))*sizeof(uint32_t);
RTPPacket::extension = ((uint8_t *)rtpextheader)+sizeof(RTPExtensionHeader);
}
RTPPacket::hasmarker = marker;
RTPPacket::numcsrcs = csrccount;
RTPPacket::payloadtype = payloadtype;
// Note: we don't fill in the EXTENDED sequence number here, since we
// don't have information about the source here. We just fill in the low
// 16 bits
RTPPacket::extseqnr = (uint32_t)ntohs(rtpheader->sequencenumber);
RTPPacket::timestamp = ntohl(rtpheader->timestamp);
RTPPacket::ssrc = ntohl(rtpheader->ssrc);
RTPPacket::packet = packetbytes;
RTPPacket::payload = packetbytes+payloadoffset;
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;
}
uint32_t RTPPacket::GetCSRC(int num) const
{
if (num >= numcsrcs)
return 0;
uint8_t *csrcpos;
uint32_t *csrcval_nbo;
uint32_t csrcval_hbo;
csrcpos = packet+sizeof(RTPHeader)+num*sizeof(uint32_t);
csrcval_nbo = (uint32_t *)csrcpos;
csrcval_hbo = ntohl(*csrcval_nbo);
return csrcval_hbo;
}
int RTPPacket::BuildPacket(uint8_t payloadtype,const void *payloaddata,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,size_t maxsize)
{
if (numcsrcs > RTP_MAXCSRCS)
return ERR_RTP_PACKET_TOOMANYCSRCS;
if (payloadtype > 127) // high bit should not be used
return ERR_RTP_PACKET_BADPAYLOADTYPE;
if (payloadtype == 72 || payloadtype == 73) // could cause confusion with rtcp types
return ERR_RTP_PACKET_BADPAYLOADTYPE;
packetlength = sizeof(RTPHeader);
packetlength += sizeof(uint32_t)*((size_t)numcsrcs);
if (gotextension)
{
packetlength += sizeof(RTPExtensionHeader);
packetlength += sizeof(uint32_t)*((size_t)extensionlen_numwords);
}
packetlength += payloadlen;
if (maxsize > 0 && packetlength > maxsize)
{
packetlength = 0;
return ERR_RTP_PACKET_DATAEXCEEDSMAXSIZE;
}
// Ok, now we'll just fill in...
RTPHeader *rtphdr;
if (buffer == 0)
{
packet = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTPPACKET) uint8_t [packetlength];
if (packet == 0)
{
packetlength = 0;
return ERR_RTP_OUTOFMEM;
}
externalbuffer = false;
}
else
{
packet = (uint8_t *)buffer;
externalbuffer = true;
}
RTPPacket::hasmarker = gotmarker;
RTPPacket::hasextension = gotextension;
RTPPacket::numcsrcs = numcsrcs;
RTPPacket::payloadtype = payloadtype;
RTPPacket::extseqnr = (uint32_t)seqnr;
RTPPacket::timestamp = timestamp;
RTPPacket::ssrc = ssrc;
RTPPacket::payloadlength = payloadlen;
RTPPacket::extid = extensionid;
RTPPacket::extensionlength = ((size_t)extensionlen_numwords)*sizeof(uint32_t);
rtphdr = (RTPHeader *)packet;
rtphdr->version = RTP_VERSION;
rtphdr->padding = 0;
if (gotmarker)
rtphdr->marker = 1;
else
rtphdr->marker = 0;
if (gotextension)
rtphdr->extension = 1;
else
rtphdr->extension = 0;
rtphdr->csrccount = numcsrcs;
rtphdr->payloadtype = payloadtype&127; // make sure high bit isn't set
rtphdr->sequencenumber = htons(seqnr);
rtphdr->timestamp = htonl(timestamp);
rtphdr->ssrc = htonl(ssrc);
uint32_t *curcsrc;
int i;
curcsrc = (uint32_t *)(packet+sizeof(RTPHeader));
for (i = 0 ; i < numcsrcs ; i++,curcsrc++)
*curcsrc = htonl(csrcs[i]);
payload = packet+sizeof(RTPHeader)+((size_t)numcsrcs)*sizeof(uint32_t);
if (gotextension)
{
RTPExtensionHeader *rtpexthdr = (RTPExtensionHeader *)payload;
rtpexthdr->extid = htons(extensionid);
rtpexthdr->length = htons((uint16_t)extensionlen_numwords);
payload += sizeof(RTPExtensionHeader);
memcpy(payload,extensiondata,RTPPacket::extensionlength);
payload += RTPPacket::extensionlength;
}
memcpy(payload,payloaddata,payloadlen);
return 0;
}
} // end namespace

180
qrtplib/rtppacket.h Normal file
View File

@ -0,0 +1,180 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtppacket.h
*/
#ifndef RTPPACKET_H
#define RTPPACKET_H
#include "rtpconfig.h"
#include "rtptypes.h"
#include "rtptimeutilities.h"
#include "rtpmemoryobject.h"
namespace qrtplib
{
class RTPRawPacket;
/** Represents an RTP Packet.
* The RTPPacket class can be used to parse a RTPRawPacket instance if it represents RTP data.
* The class can also be used to create a new RTP packet according to the parameters specified by
* the user.
*/
class JRTPLIB_IMPORTEXPORT RTPPacket : public RTPMemoryObject
{
public:
/** Creates an RTPPacket instance based upon the data in \c rawpack, optionally installing a memory manager.
* Creates an RTPPacket instance based upon the data in \c rawpack, optionally installing a memory manager.
* If successful, the data is moved from the raw packet to the RTPPacket instance.
*/
RTPPacket(RTPRawPacket &rawpack,RTPMemoryManager *mgr = 0);
/** Creates a new buffer for an RTP packet and fills in the fields according to the specified parameters.
* Creates a new buffer for an RTP packet and fills in the fields according to the specified parameters.
* If \c maxpacksize is not equal to zero, an error is generated if the total packet size would exceed
* \c maxpacksize. The arguments of the constructor are self-explanatory. Note that the size of a header
* extension is specified in a number of 32-bit words. A memory manager can be installed.
*/
RTPPacket(uint8_t payloadtype,const void *payloaddata,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,
size_t maxpacksize, RTPMemoryManager *mgr = 0);
/** This constructor is similar to the other constructor, but here data is stored in an external buffer
* \c buffer with size \c buffersize. */
RTPPacket(uint8_t payloadtype,const void *payloaddata,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,size_t buffersize,RTPMemoryManager *mgr = 0);
virtual ~RTPPacket() { if (packet && !externalbuffer) RTPDeleteByteArray(packet,GetMemoryManager()); }
/** If an error occurred in one of the constructors, this function returns the error code. */
int GetCreationError() const { return error; }
/** Returns \c true if the RTP packet has a header extension and \c false otherwise. */
bool HasExtension() const { return hasextension; }
/** Returns \c true if the marker bit was set and \c false otherwise. */
bool HasMarker() const { return hasmarker; }
/** Returns the number of CSRCs contained in this packet. */
int GetCSRCCount() const { return numcsrcs; }
/** Returns a specific CSRC identifier.
* Returns a specific CSRC identifier. The parameter \c num can go from 0 to GetCSRCCount()-1.
*/
uint32_t GetCSRC(int num) const;
/** Returns the payload type of the packet. */
uint8_t GetPayloadType() const { return payloadtype; }
/** Returns the extended sequence number of the packet.
* Returns the extended sequence number of the packet. When the packet is just received,
* only the low $16$ bits will be set. The high 16 bits can be filled in later.
*/
uint32_t GetExtendedSequenceNumber() const { return extseqnr; }
/** Returns the sequence number of this packet. */
uint16_t GetSequenceNumber() const { return (uint16_t)(extseqnr&0x0000FFFF); }
/** Sets the extended sequence number of this packet to \c seq. */
void SetExtendedSequenceNumber(uint32_t seq) { extseqnr = seq; }
/** Returns the timestamp of this packet. */
uint32_t GetTimestamp() const { return timestamp; }
/** Returns the SSRC identifier stored in this packet. */
uint32_t GetSSRC() const { return ssrc; }
/** Returns a pointer to the data of the entire packet. */
uint8_t *GetPacketData() const { return packet; }
/** Returns a pointer to the actual payload data. */
uint8_t *GetPayloadData() const { return payload; }
/** Returns the length of the entire packet. */
size_t GetPacketLength() const { return packetlength; }
/** Returns the payload length. */
size_t GetPayloadLength() const { return payloadlength; }
/** If a header extension is present, this function returns the extension identifier. */
uint16_t GetExtensionID() const { return extid; }
/** Returns the length of the header extension data. */
uint8_t *GetExtensionData() const { return extension; }
/** Returns the length of the header extension data. */
size_t GetExtensionLength() const { return extensionlength; }
/** Returns the time at which this packet was received.
* When an RTPPacket instance is created from an RTPRawPacket instance, the raw packet's
* reception time is stored in the RTPPacket instance. This function then retrieves that
* time.
*/
RTPTime GetReceiveTime() const { return receivetime; }
private:
void Clear();
int ParseRawPacket(RTPRawPacket &rawpack);
int BuildPacket(uint8_t payloadtype,const void *payloaddata,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,size_t maxsize);
int error;
bool hasextension,hasmarker;
int numcsrcs;
uint8_t payloadtype;
uint32_t extseqnr,timestamp,ssrc;
uint8_t *packet,*payload;
size_t packetlength,payloadlength;
uint16_t extid;
uint8_t *extension;
size_t extensionlength;
bool externalbuffer;
RTPTime receivetime;
};
} // end namespace
#endif // RTPPACKET_H

View File

@ -0,0 +1,267 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtppacketbuilder.h"
#include "rtperrors.h"
#include "rtppacket.h"
#include "rtpsources.h"
#include <time.h>
#include <stdlib.h>
namespace qrtplib
{
RTPPacketBuilder::RTPPacketBuilder(RTPRandom &r,RTPMemoryManager *mgr) : RTPMemoryObject(mgr),rtprnd(r),lastwallclocktime(0,0)
{
init = false;
timeinit.Dummy();
//std::cout << (void *)(&rtprnd) << std::endl;
}
RTPPacketBuilder::~RTPPacketBuilder()
{
Destroy();
}
int RTPPacketBuilder::Init(size_t max)
{
if (init)
return ERR_RTP_PACKBUILD_ALREADYINIT;
if (max <= 0)
return ERR_RTP_PACKBUILD_INVALIDMAXPACKETSIZE;
maxpacksize = max;
buffer = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTPPACKETBUILDERBUFFER) uint8_t [max];
if (buffer == 0)
return ERR_RTP_OUTOFMEM;
packetlength = 0;
CreateNewSSRC();
deftsset = false;
defptset = false;
defmarkset = false;
numcsrcs = 0;
init = true;
return 0;
}
void RTPPacketBuilder::Destroy()
{
if (!init)
return;
RTPDeleteByteArray(buffer,GetMemoryManager());
init = false;
}
int RTPPacketBuilder::SetMaximumPacketSize(size_t max)
{
uint8_t *newbuf;
if (max <= 0)
return ERR_RTP_PACKBUILD_INVALIDMAXPACKETSIZE;
newbuf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTPPACKETBUILDERBUFFER) uint8_t[max];
if (newbuf == 0)
return ERR_RTP_OUTOFMEM;
RTPDeleteByteArray(buffer,GetMemoryManager());
buffer = newbuf;
maxpacksize = max;
return 0;
}
int RTPPacketBuilder::AddCSRC(uint32_t csrc)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
if (numcsrcs >= RTP_MAXCSRCS)
return ERR_RTP_PACKBUILD_CSRCLISTFULL;
int i;
for (i = 0 ; i < numcsrcs ; i++)
{
if (csrcs[i] == csrc)
return ERR_RTP_PACKBUILD_CSRCALREADYINLIST;
}
csrcs[numcsrcs] = csrc;
numcsrcs++;
return 0;
}
int RTPPacketBuilder::DeleteCSRC(uint32_t csrc)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
int i = 0;
bool found = false;
while (!found && i < numcsrcs)
{
if (csrcs[i] == csrc)
found = true;
else
i++;
}
if (!found)
return ERR_RTP_PACKBUILD_CSRCNOTINLIST;
// move the last csrc in the place of the deleted one
numcsrcs--;
if (numcsrcs > 0 && numcsrcs != i)
csrcs[i] = csrcs[numcsrcs];
return 0;
}
void RTPPacketBuilder::ClearCSRCList()
{
if (!init)
return;
numcsrcs = 0;
}
uint32_t RTPPacketBuilder::CreateNewSSRC()
{
ssrc = rtprnd.GetRandom32();
timestamp = rtprnd.GetRandom32();
seqnr = rtprnd.GetRandom16();
// p 38: the count SHOULD be reset if the sender changes its SSRC identifier
numpayloadbytes = 0;
numpackets = 0;
return ssrc;
}
uint32_t RTPPacketBuilder::CreateNewSSRC(RTPSources &sources)
{
bool found;
do
{
ssrc = rtprnd.GetRandom32();
found = sources.GotEntry(ssrc);
} while (found);
timestamp = rtprnd.GetRandom32();
seqnr = rtprnd.GetRandom16();
// p 38: the count SHOULD be reset if the sender changes its SSRC identifier
numpayloadbytes = 0;
numpackets = 0;
return ssrc;
}
int RTPPacketBuilder::BuildPacket(const void *data,size_t len)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
if (!defptset)
return ERR_RTP_PACKBUILD_DEFAULTPAYLOADTYPENOTSET;
if (!defmarkset)
return ERR_RTP_PACKBUILD_DEFAULTMARKNOTSET;
if (!deftsset)
return ERR_RTP_PACKBUILD_DEFAULTTSINCNOTSET;
return PrivateBuildPacket(data,len,defaultpayloadtype,defaultmark,defaulttimestampinc,false);
}
int RTPPacketBuilder::BuildPacket(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
return PrivateBuildPacket(data,len,pt,mark,timestampinc,false);
}
int RTPPacketBuilder::BuildPacketEx(const void *data,size_t len,
uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
if (!defptset)
return ERR_RTP_PACKBUILD_DEFAULTPAYLOADTYPENOTSET;
if (!defmarkset)
return ERR_RTP_PACKBUILD_DEFAULTMARKNOTSET;
if (!deftsset)
return ERR_RTP_PACKBUILD_DEFAULTTSINCNOTSET;
return PrivateBuildPacket(data,len,defaultpayloadtype,defaultmark,defaulttimestampinc,true,hdrextID,hdrextdata,numhdrextwords);
}
int RTPPacketBuilder::BuildPacketEx(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc,
uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
return PrivateBuildPacket(data,len,pt,mark,timestampinc,true,hdrextID,hdrextdata,numhdrextwords);
}
int RTPPacketBuilder::PrivateBuildPacket(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc,bool gotextension,
uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords)
{
RTPPacket p(pt,data,len,seqnr,timestamp,ssrc,mark,numcsrcs,csrcs,gotextension,hdrextID,
(uint16_t)numhdrextwords,hdrextdata,buffer,maxpacksize,GetMemoryManager());
int status = p.GetCreationError();
if (status < 0)
return status;
packetlength = p.GetPacketLength();
if (numpackets == 0) // first packet
{
lastwallclocktime = RTPTime::CurrentTime();
lastrtptimestamp = timestamp;
prevrtptimestamp = timestamp;
}
else if (timestamp != prevrtptimestamp)
{
lastwallclocktime = RTPTime::CurrentTime();
lastrtptimestamp = timestamp;
prevrtptimestamp = timestamp;
}
numpayloadbytes += (uint32_t)p.GetPayloadLength();
numpackets++;
timestamp += timestampinc;
seqnr++;
return 0;
}
} // end namespace

274
qrtplib/rtppacketbuilder.h Normal file
View File

@ -0,0 +1,274 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtppacketbuilder.h
*/
#ifndef RTPPACKETBUILDER_H
#define RTPPACKETBUILDER_H
#include "rtpconfig.h"
#include "rtperrors.h"
#include "rtpdefines.h"
#include "rtprandom.h"
#include "rtptimeutilities.h"
#include "rtptypes.h"
#include "rtpmemoryobject.h"
namespace qrtplib
{
class RTPSources;
/** This class can be used to build RTP packets and is a bit more high-level than the RTPPacket
* class: it generates an SSRC identifier, keeps track of timestamp and sequence number etc.
*/
class JRTPLIB_IMPORTEXPORT RTPPacketBuilder : public RTPMemoryObject
{
public:
/** Constructs an instance which will use \c rtprand for generating random numbers
* (used to initialize the SSRC value and sequence number), optionally installing a memory manager.
**/
RTPPacketBuilder(RTPRandom &rtprand, RTPMemoryManager *mgr = 0);
~RTPPacketBuilder();
/** Initializes the builder to only allow packets with a size below \c maxpacksize. */
int Init(size_t maxpacksize);
/** Cleans up the builder. */
void Destroy();
/** Returns the number of packets which have been created with the current SSRC identifier. */
uint32_t GetPacketCount() { if (!init) return 0; return numpackets; }
/** Returns the number of payload octets which have been generated with this SSRC identifier. */
uint32_t GetPayloadOctetCount() { if (!init) return 0; return numpayloadbytes; }
/** Sets the maximum allowed packet size to \c maxpacksize. */
int SetMaximumPacketSize(size_t maxpacksize);
/** Adds a CSRC to the CSRC list which will be stored in the RTP packets. */
int AddCSRC(uint32_t csrc);
/** Deletes a CSRC from the list which will be stored in the RTP packets. */
int DeleteCSRC(uint32_t csrc);
/** Clears the CSRC list. */
void ClearCSRCList();
/** Builds a packet with payload \c data and payload length \c len.
* Builds a packet with payload \c data and payload length \c len. The payload type, marker
* and timestamp increment used will be those that have been set using the \c SetDefault
* functions below.
*/
int BuildPacket(const void *data,size_t len);
/** Builds a packet with payload \c data and payload length \c len.
* Builds a packet with payload \c data and payload length \c len. The payload type will be
* set to \c pt, the marker bit to \c mark and after building this packet, the timestamp will
* be incremented with \c timestamp.
*/
int BuildPacket(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc);
/** Builds a packet with payload \c data and payload length \c len.
* Builds a packet with payload \c data and payload length \c len. The payload type, marker
* and timestamp increment used will be those that have been set using the \c SetDefault
* functions below. This packet will also contain an RTP header extension with identifier
* \c hdrextID and data \c hdrextdata. The length of the header extension data is given by
* \c numhdrextwords which expresses the length in a number of 32-bit words.
*/
int BuildPacketEx(const void *data,size_t len,
uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords);
/** Builds a packet with payload \c data and payload length \c len.
* Builds a packet with payload \c data and payload length \c len. The payload type will be set
* to \c pt, the marker bit to \c mark and after building this packet, the timestamp will
* be incremented with \c timestamp. This packet will also contain an RTP header extension
* with identifier \c hdrextID and data \c hdrextdata. The length of the header extension
* data is given by \c numhdrextwords which expresses the length in a number of 32-bit words.
*/
int BuildPacketEx(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc,
uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords);
/** Returns a pointer to the last built RTP packet data. */
uint8_t *GetPacket() { if (!init) return 0; return buffer; }
/** Returns the size of the last built RTP packet. */
size_t GetPacketLength() { if (!init) return 0; return packetlength; }
/** Sets the default payload type to \c pt. */
int SetDefaultPayloadType(uint8_t pt);
/** Sets the default marker bit to \c m. */
int SetDefaultMark(bool m);
/** Sets the default timestamp increment to \c timestampinc. */
int SetDefaultTimestampIncrement(uint32_t timestampinc);
/** This function increments the timestamp with the amount given by \c inc.
* This function increments the timestamp with the amount given by \c inc. This can be useful
* if, for example, a packet was not sent because it contained only silence. Then, this function
* should be called to increment the timestamp with the appropriate amount so that the next packets
* will still be played at the correct time at other hosts.
*/
int IncrementTimestamp(uint32_t inc);
/** This function increments the timestamp with the amount given set by the SetDefaultTimestampIncrement
* member function.
* This function increments the timestamp with the amount given set by the SetDefaultTimestampIncrement
* member function. This can be useful if, for example, a packet was not sent because it contained only silence.
* Then, this function should be called to increment the timestamp with the appropriate amount so that the next
* packets will still be played at the correct time at other hosts.
*/
int IncrementTimestampDefault();
/** Creates a new SSRC to be used in generated packets.
* Creates a new SSRC to be used in generated packets. This will also generate new timestamp and
* sequence number offsets.
*/
uint32_t CreateNewSSRC();
/** Creates a new SSRC to be used in generated packets.
* Creates a new SSRC to be used in generated packets. This will also generate new timestamp and
* sequence number offsets. The source table \c sources is used to make sure that the chosen SSRC
* isn't used by another participant yet.
*/
uint32_t CreateNewSSRC(RTPSources &sources);
/** Returns the current SSRC identifier. */
uint32_t GetSSRC() const { if (!init) return 0; return ssrc; }
/** Returns the current RTP timestamp. */
uint32_t GetTimestamp() const { if (!init) return 0; return timestamp; }
/** Returns the current sequence number. */
uint16_t GetSequenceNumber() const { if (!init) return 0; return seqnr; }
/** Returns the time at which a packet was generated.
* Returns the time at which a packet was generated. This is not necessarily the time at which
* the last RTP packet was generated: if the timestamp increment was zero, the time is not updated.
*/
RTPTime GetPacketTime() const { if (!init) return RTPTime(0,0); return lastwallclocktime; }
/** Returns the RTP timestamp which corresponds to the time returned by the previous function. */
uint32_t GetPacketTimestamp() const { if (!init) return 0; return lastrtptimestamp; }
/** Sets a specific SSRC to be used.
* Sets a specific SSRC to be used. Does not create a new timestamp offset or sequence number
* offset. Does not reset the packet count or byte count. Think twice before using this!
*/
void AdjustSSRC(uint32_t s) { ssrc = s; }
private:
int PrivateBuildPacket(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc,bool gotextension,
uint16_t hdrextID = 0,const void *hdrextdata = 0,size_t numhdrextwords = 0);
RTPRandom &rtprnd;
size_t maxpacksize;
uint8_t *buffer;
size_t packetlength;
uint32_t numpayloadbytes;
uint32_t numpackets;
bool init;
uint32_t ssrc;
uint32_t timestamp;
uint16_t seqnr;
uint32_t defaulttimestampinc;
uint8_t defaultpayloadtype;
bool defaultmark;
bool deftsset,defptset,defmarkset;
uint32_t csrcs[RTP_MAXCSRCS];
int numcsrcs;
RTPTime lastwallclocktime;
uint32_t lastrtptimestamp;
uint32_t prevrtptimestamp;
};
inline int RTPPacketBuilder::SetDefaultPayloadType(uint8_t pt)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
defptset = true;
defaultpayloadtype = pt;
return 0;
}
inline int RTPPacketBuilder::SetDefaultMark(bool m)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
defmarkset = true;
defaultmark = m;
return 0;
}
inline int RTPPacketBuilder::SetDefaultTimestampIncrement(uint32_t timestampinc)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
deftsset = true;
defaulttimestampinc = timestampinc;
return 0;
}
inline int RTPPacketBuilder::IncrementTimestamp(uint32_t inc)
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
timestamp += inc;
return 0;
}
inline int RTPPacketBuilder::IncrementTimestampDefault()
{
if (!init)
return ERR_RTP_PACKBUILD_NOTINIT;
if (!deftsset)
return ERR_RTP_PACKBUILD_DEFAULTTSINCNOTSET;
timestamp += defaulttimestampinc;
return 0;
}
} // end namespace
#endif // RTPPACKETBUILDER_H

171
qrtplib/rtppollthread.cpp Normal file
View File

@ -0,0 +1,171 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtppollthread.h"
#ifdef RTP_SUPPORT_THREAD
#include "rtpsession.h"
#include "rtcpscheduler.h"
#include "rtperrors.h"
#include "rtprawpacket.h"
#include <time.h>
#include <iostream>
namespace qrtplib
{
RTPPollThread::RTPPollThread(RTPSession &session,RTCPScheduler &sched):rtpsession(session),rtcpsched(sched)
{
stop = false;
transmitter = 0;
timeinit.Dummy();
}
RTPPollThread::~RTPPollThread()
{
Stop();
}
int RTPPollThread::Start(RTPTransmitter *trans)
{
if (JThread::IsRunning())
return ERR_RTP_POLLTHREAD_ALREADYRUNNING;
transmitter = trans;
if (!stopmutex.IsInitialized())
{
if (stopmutex.Init() < 0)
return ERR_RTP_POLLTHREAD_CANTINITMUTEX;
}
stop = false;
if (JThread::Start() < 0)
return ERR_RTP_POLLTHREAD_CANTSTARTTHREAD;
return 0;
}
void RTPPollThread::Stop()
{
if (!IsRunning())
return;
stopmutex.Lock();
stop = true;
stopmutex.Unlock();
if (transmitter)
transmitter->AbortWait();
RTPTime thetime = RTPTime::CurrentTime();
bool done = false;
while (JThread::IsRunning() && !done)
{
// wait max 5 sec
RTPTime curtime = RTPTime::CurrentTime();
if ((curtime.GetDouble()-thetime.GetDouble()) > 5.0)
done = true;
RTPTime::Wait(RTPTime(0,10000));
}
if (JThread::IsRunning())
{
std::cerr << "RTPPollThread: Warning! Having to kill thread!" << std::endl;
JThread::Kill();
}
stop = false;
transmitter = 0;
}
void *RTPPollThread::Thread()
{
JThread::ThreadStarted();
bool stopthread;
stopmutex.Lock();
stopthread = stop;
stopmutex.Unlock();
rtpsession.OnPollThreadStart(stopthread);
while (!stopthread)
{
int status;
rtpsession.schedmutex.Lock();
rtpsession.sourcesmutex.Lock();
RTPTime rtcpdelay = rtcpsched.GetTransmissionDelay();
rtpsession.sourcesmutex.Unlock();
rtpsession.schedmutex.Unlock();
if ((status = transmitter->WaitForIncomingData(rtcpdelay)) < 0)
{
stopthread = true;
rtpsession.OnPollThreadError(status);
}
else
{
if ((status = transmitter->Poll()) < 0)
{
stopthread = true;
rtpsession.OnPollThreadError(status);
}
else
{
if ((status = rtpsession.ProcessPolledData()) < 0)
{
stopthread = true;
rtpsession.OnPollThreadError(status);
}
else
{
rtpsession.OnPollThreadStep();
stopmutex.Lock();
stopthread = stop;
stopmutex.Unlock();
}
}
}
}
rtpsession.OnPollThreadStop();
return 0;
}
} // end namespace
#endif // RTP_SUPPORT_THREAD

79
qrtplib/rtppollthread.h Normal file
View File

@ -0,0 +1,79 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtppollthread.h
*/
#ifndef RTPPOLLTHREAD_H
#define RTPPOLLTHREAD_H
#include "rtpconfig.h"
#ifdef RTP_SUPPORT_THREAD
#include "rtptransmitter.h"
#include <jthread/jthread.h>
#include <jthread/jmutex.h>
#include <list>
namespace qrtplib
{
class RTPSession;
class RTCPScheduler;
class JRTPLIB_IMPORTEXPORT RTPPollThread : private jthread::JThread
{
public:
RTPPollThread(RTPSession &session,RTCPScheduler &rtcpsched);
~RTPPollThread();
int Start(RTPTransmitter *trans);
void Stop();
private:
void *Thread();
bool stop;
jthread::JMutex stopmutex;
RTPTransmitter *transmitter;
RTPSession &rtpsession;
RTCPScheduler &rtcpsched;
};
} // end namespace
#endif // RTP_SUPPORT_THREAD
#endif // RTPPOLLTHREAD_H

105
qrtplib/rtprandom.cpp Normal file
View File

@ -0,0 +1,105 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#if defined(WIN32) && !defined(_WIN32_WCE)
#define _CRT_RAND_S
#endif // WIN32 || _WIN32_WCE
#include "rtprandom.h"
#include "rtprandomrands.h"
#include "rtprandomurandom.h"
#include "rtprandomrand48.h"
#include <time.h>
#ifndef WIN32
#include <unistd.h>
#else
#ifndef _WIN32_WCE
#include <process.h>
#else
#include <windows.h>
#include <kfuncs.h>
#endif // _WIN32_WINCE
#include <stdlib.h>
#endif // WIN32
namespace qrtplib
{
uint32_t RTPRandom::PickSeed()
{
uint32_t x;
#if defined(WIN32) || defined(_WIN32_WINCE)
#ifndef _WIN32_WCE
x = (uint32_t)_getpid();
x += (uint32_t)time(0);
x += (uint32_t)clock();
#else
x = (uint32_t)GetCurrentProcessId();
FILETIME ft;
SYSTEMTIME st;
GetSystemTime(&st);
SystemTimeToFileTime(&st,&ft);
x += ft.dwLowDateTime;
#endif // _WIN32_WCE
x ^= (uint32_t)((uint8_t *)this - (uint8_t *)0);
#else
x = (uint32_t)getpid();
x += (uint32_t)time(0);
x += (uint32_t)clock();
x ^= (uint32_t)((uint8_t *)this - (uint8_t *)0);
#endif
return x;
}
RTPRandom *RTPRandom::CreateDefaultRandomNumberGenerator()
{
#ifdef RTP_HAVE_RAND_S
RTPRandomRandS *r = new RTPRandomRandS();
#else
RTPRandomURandom *r = new RTPRandomURandom();
#endif // RTP_HAVE_RAND_S
RTPRandom *rRet = r;
if (r->Init() < 0) // fall back to rand48
{
delete r;
rRet = new RTPRandomRand48();
}
return rRet;
}
} // end namespace

79
qrtplib/rtprandom.h Normal file
View File

@ -0,0 +1,79 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtprandom.h
*/
#ifndef RTPRANDOM_H
#define RTPRANDOM_H
#include "rtpconfig.h"
#include "rtptypes.h"
#include <stdlib.h>
#define RTPRANDOM_2POWMIN63 1.08420217248550443400745280086994171142578125e-19
namespace qrtplib
{
/** Interface for generating random numbers. */
class JRTPLIB_IMPORTEXPORT RTPRandom
{
public:
RTPRandom() { }
virtual ~RTPRandom() { }
/** Returns a random eight bit value. */
virtual uint8_t GetRandom8() = 0;
/** Returns a random sixteen bit value. */
virtual uint16_t GetRandom16() = 0;
/** Returns a random thirty-two bit value. */
virtual uint32_t GetRandom32() = 0;
/** Returns a random number between $0.0$ and $1.0$. */
virtual double GetRandomDouble() = 0;
/** Can be used by subclasses to generate a seed for a random number generator. */
uint32_t PickSeed();
/** Allocate a default random number generator based on your platform. */
static RTPRandom *CreateDefaultRandomNumberGenerator();
};
} // end namespace
#endif // RTPRANDOM_H

125
qrtplib/rtprandomrand48.cpp Normal file
View File

@ -0,0 +1,125 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtprandomrand48.h"
namespace qrtplib
{
RTPRandomRand48::RTPRandomRand48()
{
SetSeed(PickSeed());
}
RTPRandomRand48::RTPRandomRand48(uint32_t seed)
{
SetSeed(seed);
}
RTPRandomRand48::~RTPRandomRand48()
{
}
void RTPRandomRand48::SetSeed(uint32_t seed)
{
#ifdef RTP_SUPPORT_THREAD
mutex.Init(); // TODO: check error!
#endif // RTP_SUPPORT_THREAD
#ifdef RTP_HAVE_VSUINT64SUFFIX
state = ((uint64_t)seed) << 16 | 0x330Eui64;
#else
state = ((uint64_t)seed) << 16 | 0x330EULL;
#endif // RTP_HAVE_VSUINT64SUFFIX
}
uint8_t RTPRandomRand48::GetRandom8()
{
uint32_t x = ((GetRandom32() >> 24)&0xff);
return (uint8_t)x;
}
uint16_t RTPRandomRand48::GetRandom16()
{
uint32_t x = ((GetRandom32() >> 16)&0xffff);
return (uint16_t)x;
}
uint32_t RTPRandomRand48::GetRandom32()
{
#ifdef RTP_SUPPORT_THREAD
mutex.Lock();
#endif // RTP_SUPPORT_THREAD
#ifdef RTP_HAVE_VSUINT64SUFFIX
state = ((0x5DEECE66Dui64*state) + 0xBui64)&0x0000ffffffffffffui64;
uint32_t x = (uint32_t)((state>>16)&0xffffffffui64);
#else
state = ((0x5DEECE66DULL*state) + 0xBULL)&0x0000ffffffffffffULL;
uint32_t x = (uint32_t)((state>>16)&0xffffffffULL);
#endif // RTP_HAVE_VSUINT64SUFFIX
#ifdef RTP_SUPPORT_THREAD
mutex.Unlock();
#endif // RTP_SUPPORT_THREAD
return x;
}
double RTPRandomRand48::GetRandomDouble()
{
#ifdef RTP_SUPPORT_THREAD
mutex.Lock();
#endif // RTP_SUPPORT_THREAD
#ifdef RTP_HAVE_VSUINT64SUFFIX
state = ((0x5DEECE66Dui64*state) + 0xBui64)&0x0000ffffffffffffui64;
int64_t x = (int64_t)state;
#else
state = ((0x5DEECE66DULL*state) + 0xBULL)&0x0000ffffffffffffULL;
int64_t x = (int64_t)state;
#endif // RTP_HAVE_VSUINT64SUFFIX
#ifdef RTP_SUPPORT_THREAD
mutex.Unlock();
#endif // RTP_SUPPORT_THREAD
double y = 3.552713678800500929355621337890625e-15 * (double)x;
return y;
}
} // end namespace

75
qrtplib/rtprandomrand48.h Normal file
View File

@ -0,0 +1,75 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtprandomrand48.h
*/
#ifndef RTPRANDOMRAND48_H
#define RTPRANDOMRAND48_H
#include "rtpconfig.h"
#include "rtprandom.h"
#ifdef RTP_SUPPORT_THREAD
#include <jthread/jmutex.h>
#endif // RTP_SUPPORT_THREAD
#include <stdio.h>
namespace qrtplib
{
/** A random number generator using the algorithm of the rand48 set of functions. */
class JRTPLIB_IMPORTEXPORT RTPRandomRand48 : public RTPRandom
{
public:
RTPRandomRand48();
RTPRandomRand48(uint32_t seed);
~RTPRandomRand48();
uint8_t GetRandom8();
uint16_t GetRandom16();
uint32_t GetRandom32();
double GetRandomDouble();
private:
void SetSeed(uint32_t seed);
#ifdef RTP_SUPPORT_THREAD
jthread::JMutex mutex;
#endif // RTP_SUPPORT_THREAD
uint64_t state;
};
} // end namespace
#endif // RTPRANDOMRAND48_H

196
qrtplib/rtprandomrands.cpp Normal file
View File

@ -0,0 +1,196 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpconfig.h"
#ifdef RTP_HAVE_RAND_S
#define _CRT_RAND_S
#endif // RTP_HAVE_RAND_S
#include "rtprandomrands.h"
#include "rtperrors.h"
#include <stdlib.h>
#include <math.h>
// If compiling on VC 8 or later for full Windows, we'll attempt to use rand_s,
// which generates better random numbers. However, its only supported on Windows XP,
// Windows Server 2003, and later, so we'll do a run-time check to see if we can
// use it (it won't work on Windows 2000 SP4 for example).
namespace qrtplib
{
#ifndef RTP_HAVE_RAND_S
RTPRandomRandS::RTPRandomRandS()
{
initialized = false;
}
RTPRandomRandS::~RTPRandomRandS()
{
}
int RTPRandomRandS::Init()
{
return ERR_RTP_RTPRANDOMRANDS_NOTSUPPORTED;
}
uint8_t RTPRandomRandS::GetRandom8()
{
return 0;
}
uint16_t RTPRandomRandS::GetRandom16()
{
return 0;
}
uint32_t RTPRandomRandS::GetRandom32()
{
return 0;
}
double RTPRandomRandS::GetRandomDouble()
{
return 0;
}
#else
RTPRandomRandS::RTPRandomRandS()
{
initialized = false;
}
RTPRandomRandS::~RTPRandomRandS()
{
}
int RTPRandomRandS::Init()
{
if (initialized) // doesn't matter then
return 0;
HMODULE hAdvApi32 = LoadLibrary(TEXT("ADVAPI32.DLL"));
if(hAdvApi32 != NULL)
{
if(NULL != GetProcAddress( hAdvApi32, "SystemFunction036" )) // RtlGenRandom
{
initialized = true;
}
FreeLibrary(hAdvApi32);
hAdvApi32 = NULL;
}
if (!initialized)
return ERR_RTP_RTPRANDOMRANDS_NOTSUPPORTED;
return 0;
}
// rand_s gives a number between 0 and UINT_MAX. We'll assume that UINT_MAX is at least 8 bits
uint8_t RTPRandomRandS::GetRandom8()
{
if (!initialized)
return 0;
unsigned int r;
rand_s(&r);
return (uint8_t)(r&0xff);
}
uint16_t RTPRandomRandS::GetRandom16()
{
if (!initialized)
return 0;
unsigned int r;
int shift = 0;
uint16_t x = 0;
for (int i = 0 ; i < 2 ; i++, shift += 8)
{
rand_s(&r);
x ^= ((uint16_t)r << shift);
}
return x;
}
uint32_t RTPRandomRandS::GetRandom32()
{
if (!initialized)
return 0;
unsigned int r;
int shift = 0;
uint32_t x = 0;
for (int i = 0 ; i < 4 ; i++, shift += 8)
{
rand_s(&r);
x ^= ((uint32_t)r << shift);
}
return x;
}
double RTPRandomRandS::GetRandomDouble()
{
if (!initialized)
return 0;
unsigned int r;
int shift = 0;
uint64_t x = 0;
for (int i = 0 ; i < 8 ; i++, shift += 8)
{
rand_s(&r);
x ^= ((uint64_t)r << shift);
}
x &= 0x7fffffffffffffffULL;
int64_t x2 = (int64_t)x;
return RTPRANDOM_2POWMIN63*(double)x2;
}
#endif // RTP_HAVE_RAND_S
} // end namespace

70
qrtplib/rtprandomrands.h Normal file
View File

@ -0,0 +1,70 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtprandomrands.h
*/
#ifndef RTPRANDOMRANDS_H
#define RTPRANDOMRANDS_H
#include "rtpconfig.h"
#include "rtprandom.h"
namespace qrtplib
{
/** A random number generator which tries to use the \c rand_s function on the
* Win32 platform.
*/
class JRTPLIB_IMPORTEXPORT RTPRandomRandS : public RTPRandom
{
public:
RTPRandomRandS();
~RTPRandomRandS();
/** Initialize the random number generator. */
int Init();
uint8_t GetRandom8();
uint16_t GetRandom16();
uint32_t GetRandom32();
double GetRandomDouble();
private:
bool initialized;
};
} // end namespace
#endif // RTPRANDOMRANDS_H

View File

@ -0,0 +1,129 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtprandomurandom.h"
#include "rtperrors.h"
namespace qrtplib
{
RTPRandomURandom::RTPRandomURandom()
{
device = 0;
}
RTPRandomURandom::~RTPRandomURandom()
{
if (device)
fclose(device);
}
int RTPRandomURandom::Init()
{
if (device)
return ERR_RTP_RTPRANDOMURANDOM_ALREADYOPEN;
device = fopen("/dev/urandom","rb");
if (device == 0)
return ERR_RTP_RTPRANDOMURANDOM_CANTOPEN;
return 0;
}
uint8_t RTPRandomURandom::GetRandom8()
{
if (!device)
return 0;
uint8_t value;
if (fread(&value, sizeof(uint8_t), 1, device) != sizeof(uint8_t)) {
return 0;
}
return value;
}
uint16_t RTPRandomURandom::GetRandom16()
{
if (!device)
return 0;
uint16_t value;
if (fread(&value, sizeof(uint16_t), 1, device) != sizeof(uint16_t)) {
return 0;
}
return value;
}
uint32_t RTPRandomURandom::GetRandom32()
{
if (!device)
return 0;
uint32_t value;
if (fread(&value, sizeof(uint32_t), 1, device) != sizeof(uint32_t)) {
return 0;
}
return value;
}
double RTPRandomURandom::GetRandomDouble()
{
if (!device)
return 0;
uint64_t value;
if (fread(&value, sizeof(uint64_t), 1, device) != sizeof(uint64_t)) {
return 0;
}
#ifdef RTP_HAVE_VSUINT64SUFFIX
value &= 0x7fffffffffffffffui64;
#else
value &= 0x7fffffffffffffffULL;
#endif // RTP_HAVE_VSUINT64SUFFIX
int64_t value2 = (int64_t)value;
double x = RTPRANDOM_2POWMIN63*(double)value2;
return x;
}
} // end namespace

View File

@ -0,0 +1,68 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtprandomurandom.h
*/
#ifndef RTPRANDOMURANDOM_H
#define RTPRANDOMURANDOM_H
#include "rtpconfig.h"
#include "rtprandom.h"
#include <stdio.h>
namespace qrtplib
{
/** A random number generator which uses bytes delivered by the /dev/urandom device. */
class JRTPLIB_IMPORTEXPORT RTPRandomURandom : public RTPRandom
{
public:
RTPRandomURandom();
~RTPRandomURandom();
/** Initialize the random number generator. */
int Init();
uint8_t GetRandom8();
uint16_t GetRandom16();
uint32_t GetRandom32();
double GetRandomDouble();
private:
FILE *device;
};
} // end namespace
#endif // RTPRANDOMURANDOM_H

160
qrtplib/rtprawpacket.h Normal file
View File

@ -0,0 +1,160 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtprawpacket.h
*/
#ifndef RTPRAWPACKET_H
#define RTPRAWPACKET_H
#include "rtpconfig.h"
#include "rtptimeutilities.h"
#include "rtpaddress.h"
#include "rtptypes.h"
#include "rtpmemoryobject.h"
namespace qrtplib
{
/** This class is used by the transmission component to store the incoming RTP and RTCP data in. */
class JRTPLIB_IMPORTEXPORT RTPRawPacket : public RTPMemoryObject
{
public:
/** Creates an instance which stores data from \c data with length \c datalen.
* Creates an instance which stores data from \c data with length \c datalen. Only the pointer
* to the data is stored, no actual copy is made! The address from which this packet originated
* is set to \c address and the time at which the packet was received is set to \c recvtime.
* 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,size_t datalen,RTPAddress *address,RTPTime &recvtime,bool rtp,RTPMemoryManager *mgr = 0);
~RTPRawPacket();
/** Returns the pointer to the data which is contained in this packet. */
uint8_t *GetData() { return packetdata; }
/** Returns the length of the packet described by this instance. */
size_t GetDataLength() const { return packetdatalength; }
/** Returns the time at which this packet was received. */
RTPTime GetReceiveTime() const { return receivetime; }
/** Returns the address stored in this packet. */
const RTPAddress *GetSenderAddress() const { return senderaddress; }
/** Returns \c true if this data is RTP data, \c false if it is RTCP data. */
bool IsRTP() const { 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(bool isrtp, 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, 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);
private:
void DeleteData();
uint8_t *packetdata;
size_t packetdatalength;
RTPTime receivetime;
RTPAddress *senderaddress;
bool isrtp;
};
inline RTPRawPacket::RTPRawPacket(uint8_t *data,size_t datalen,RTPAddress *address,RTPTime &recvtime,bool rtp,RTPMemoryManager *mgr):RTPMemoryObject(mgr),receivetime(recvtime)
{
packetdata = data;
packetdatalength = datalen;
senderaddress = address;
isrtp = rtp;
}
inline RTPRawPacket::~RTPRawPacket()
{
DeleteData();
}
inline void RTPRawPacket::DeleteData()
{
if (packetdata)
RTPDeleteByteArray(packetdata,GetMemoryManager());
if (senderaddress)
RTPDelete(senderaddress,GetMemoryManager());
packetdata = 0;
senderaddress = 0;
}
inline uint8_t *RTPRawPacket::AllocateBytes(bool isrtp, int recvlen) const
{
JRTPLIB_UNUSED(isrtp); // possibly unused
return RTPNew(GetMemoryManager(),(isrtp)?RTPMEM_TYPE_BUFFER_RECEIVEDRTPPACKET:RTPMEM_TYPE_BUFFER_RECEIVEDRTCPPACKET) uint8_t[recvlen];
}
inline void RTPRawPacket::SetData(uint8_t *data, size_t datalen)
{
if (packetdata)
RTPDeleteByteArray(packetdata,GetMemoryManager());
packetdata = data;
packetdatalength = datalen;
}
inline void RTPRawPacket::SetSenderAddress(RTPAddress *address)
{
if (senderaddress)
RTPDelete(senderaddress, GetMemoryManager());
senderaddress = address;
}
} // end namespace
#endif // RTPRAWPACKET_H

View File

@ -0,0 +1,283 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpsecuresession.h"
#ifdef RTP_SUPPORT_SRTP
#include "rtprawpacket.h"
#include <jthread/jmutexautolock.h>
#include <srtp/srtp.h>
#include <iostream>
#include <vector>
using namespace std;
using namespace jthread;
namespace qrtplib
{
// SRTP library needs to be initialized already!
RTPSecureSession::RTPSecureSession(RTPRandom *rnd, RTPMemoryManager *mgr) : RTPSession(rnd, mgr)
{
// Make sure the OnChange... functions will be called
SetChangeIncomingData(true);
SetChangeOutgoingData(true);
m_pSRTPContext = 0;
m_lastSRTPError = 0;
}
RTPSecureSession::~RTPSecureSession()
{
if (m_pSRTPContext)
srtp_dealloc(m_pSRTPContext);
}
int RTPSecureSession::InitializeSRTPContext()
{
#ifdef RTP_SUPPORT_THREAD
if (!m_srtpLock.IsInitialized())
{
if (m_srtpLock.Init() < 0)
return ERR_RTP_SECURESESSION_CANTINITMUTEX;
}
JMutexAutoLock l(m_srtpLock);
#endif // RTP_SUPPORT_THREAD
if (m_pSRTPContext)
return ERR_RTP_SECURESESSION_CONTEXTALREADYINITIALIZED;
err_status_t result = srtp_create(&m_pSRTPContext, NULL);
if (result != err_status_ok)
{
m_pSRTPContext = 0;
m_lastSRTPError = (int)result;
return ERR_RTP_SECURESESSION_CANTINITIALIZE_SRTPCONTEXT;
}
return 0;
}
int RTPSecureSession::GetLastLibSRTPError()
{
#ifdef RTP_SUPPORT_THREAD
JMutexAutoLock l(m_srtpLock);
#endif // RTP_SUPPORT_THREAD
int err = m_lastSRTPError;
m_lastSRTPError = 0; // clear it
return err;
}
void RTPSecureSession::SetLastLibSRTPError(int err)
{
#ifdef RTP_SUPPORT_THREAD
JMutexAutoLock l(m_srtpLock);
#endif // RTP_SUPPORT_THREAD
m_lastSRTPError = err;
}
srtp_ctx_t *RTPSecureSession::LockSRTPContext()
{
#ifdef RTP_SUPPORT_THREAD
m_srtpLock.Lock();
#endif // RTP_SUPPORT_THREAD
if (!m_pSRTPContext)
{
#ifdef RTP_SUPPORT_THREAD
m_srtpLock.Unlock(); // Make sure the mutex is not locked on error
#endif // RTP_SUPPORT_THREAD
return 0;
}
return m_pSRTPContext;
}
int RTPSecureSession::UnlockSRTPContext()
{
if (!m_pSRTPContext)
return ERR_RTP_SECURESESSION_CONTEXTNOTINITIALIZED;
#ifdef RTP_SUPPORT_THREAD
m_srtpLock.Unlock();
#endif // RTP_SUPPORT_THREAD
return 0;
}
int RTPSecureSession::encryptData(uint8_t *pData, int &dataLength, bool rtp)
{
int length = dataLength;
if (rtp)
{
if (length < (int)sizeof(uint32_t)*3)
return ERR_RTP_SECURESESSION_NOTENOUGHDATATOENCRYPT ;
err_status_t result = srtp_protect(m_pSRTPContext, (void *)pData, &length);
if (result != err_status_ok)
{
m_lastSRTPError = (int)result;
return ERR_RTP_SECURESESSION_CANTENCRYPTRTPDATA;
}
}
else // rtcp
{
if (length < (int)sizeof(uint32_t)*2)
return ERR_RTP_SECURESESSION_NOTENOUGHDATATOENCRYPT;
err_status_t result = srtp_protect_rtcp(m_pSRTPContext, (void *)pData, &length);
if (result != err_status_ok)
{
m_lastSRTPError = (int)result;
return ERR_RTP_SECURESESSION_CANTENCRYPTRTCPDATA;
}
}
dataLength = length;
return 0;
}
int RTPSecureSession::OnChangeRTPOrRTCPData(const void *origdata, size_t origlen, bool isrtp, void **senddata, size_t *sendlen)
{
*senddata = 0;
if (!origdata || origlen == 0) // Nothing to do in this case, packet can be ignored
return 0;
srtp_ctx_t *pCtx = LockSRTPContext();
if (pCtx == 0)
return ERR_RTP_SECURESESSION_CONTEXTNOTINITIALIZED;
// Need to add some extra bytes, and we'll add a few more to be really safe
uint8_t *pDataCopy = RTPNew(GetMemoryManager(), RTPMEM_TYPE_BUFFER_SRTPDATA) uint8_t [origlen + SRTP_MAX_TRAILER_LEN + 32];
memcpy(pDataCopy, origdata, origlen);
int status = 0;
int dataLength = (int)origlen;
if ((status = encryptData(pDataCopy, dataLength, isrtp)) < 0)
{
UnlockSRTPContext();
RTPDeleteByteArray(pDataCopy, GetMemoryManager());
return status;
}
UnlockSRTPContext();
*senddata = pDataCopy;
*sendlen = dataLength;
return 0;
}
int RTPSecureSession::decryptRawPacket(RTPRawPacket *rawpack, int *srtpError)
{
*srtpError = 0;
uint8_t *pData = rawpack->GetData();
int dataLength = (int)rawpack->GetDataLength();
if (rawpack->IsRTP())
{
if (dataLength < (int)sizeof(uint32_t)*3)
return ERR_RTP_SECURESESSION_NOTENOUGHDATATODECRYPT;
err_status_t result = srtp_unprotect(m_pSRTPContext, (void*)pData, &dataLength);
if (result != err_status_ok)
{
*srtpError = result;
return ERR_RTP_SECURESESSION_CANTDECRYPTRTPDATA;
}
}
else // RTCP
{
if (dataLength < (int)sizeof(uint32_t)*2)
return ERR_RTP_SECURESESSION_NOTENOUGHDATATODECRYPT;
err_status_t result = srtp_unprotect_rtcp(m_pSRTPContext, (void *)pData, &dataLength);
if (result != err_status_ok)
{
*srtpError = result;
return ERR_RTP_SECURESESSION_CANTDECRYPTRTCPDATA;
}
}
rawpack->ZeroData(); // make sure we don't delete the data we're going to store
rawpack->SetData(pData, (size_t)dataLength);
return 0;
}
bool RTPSecureSession::OnChangeIncomingData(RTPRawPacket *rawpack)
{
if (!rawpack)
return false;
srtp_ctx_t *pCtx = LockSRTPContext();
if (pCtx == 0)
{
OnErrorChangeIncomingData(ERR_RTP_SECURESESSION_CONTEXTNOTINITIALIZED, 0);
return false;
}
int srtpErr = 0;
int status = decryptRawPacket(rawpack, &srtpErr);
UnlockSRTPContext();
if (status < 0)
{
OnErrorChangeIncomingData(status, srtpErr);
return false;
}
return true;
}
void RTPSecureSession::OnSentRTPOrRTCPData(void *senddata, size_t sendlen, bool isrtp)
{
JRTPLIB_UNUSED(sendlen);
JRTPLIB_UNUSED(isrtp);
if (senddata)
RTPDeleteByteArray((uint8_t *)senddata, GetMemoryManager());
}
} // end namespace
#endif // RTP_SUPPORT_SRTP

132
qrtplib/rtpsecuresession.h Normal file
View File

@ -0,0 +1,132 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpsecuresession.h
*/
#ifndef RTPSECURESESSION_H
#define RTPSECURESESSION_H
#include "rtpconfig.h"
#ifdef RTP_SUPPORT_SRTP
#include "rtpsession.h"
#ifdef RTP_SUPPORT_THREAD
#include <jthread/jthread.h>
#endif // RTP_SUPPORT_THREAD
struct srtp_ctx_t;
namespace qrtplib
{
class RTPCrypt;
// SRTP library needs to be initialized already!
/** RTPSession derived class that serves as a base class for an SRTP implementation.
*
* This is an RTPSession derived class that serves as a base class for an SRTP implementation.
* The class sets the RTPSession::SetChangeIncomingData and RTPSession::SetChangeOutgoingData
* flags, and implements RTPSession::OnChangeIncomingData, RTPSession::OnChangeRTPOrRTCPData
* and RTPSession::OnSentRTPOrRTCPData so that encryption and decryption is applied to packets.
* The encryption and decryption will be done using [libsrtp](https://github.com/cisco/libsrtp),
* which must be available at compile time.
*
* Your derived class should call RTPSecureSession::InitializeSRTPContext to initialize a context
* struct of `libsrtp`. When this succeeds, the context can be obtained and used with the
* RTPSecureSession::LockSRTPContext function, which also locks a mutex if thread support was
* available. After you're done using the context yourself (to set encryption parameters for
* SSRCs), you **must** release it again using RTPSecureSession::UnlockSRTPContext.
*
* See `example7.cpp` for an example of how to use this class.
*/
class JRTPLIB_IMPORTEXPORT RTPSecureSession : public RTPSession
{
public:
/** Constructs an RTPSecureSession instance, see RTPSession::RTPSession
* for more information about the parameters. */
RTPSecureSession(RTPRandom *rnd = 0, RTPMemoryManager *mgr = 0);
~RTPSecureSession();
protected:
/** Initializes the SRTP context, in case of an error it may be useful to inspect
* RTPSecureSession::GetLastLibSRTPError. */
int InitializeSRTPContext();
/** This function locks a mutex and returns the `libsrtp` context that was
* created in RTPSecureSession::InitializeSRTPContext, so that you can further
* use it to specify encryption parameters for various sources; note that you
* **must** release the context again after use with the
* RTPSecureSession::UnlockSRTPContext function. */
srtp_ctx_t *LockSRTPContext();
/** Releases the lock on the SRTP context that was obtained in
* RTPSecureSession::LockSRTPContext. */
int UnlockSRTPContext();
/** Returns (and clears) the last error that was encountered when using a
* `libsrtp` based function. */
int GetLastLibSRTPError();
void SetLastLibSRTPError(int err);
/** In case the reimplementation of OnChangeIncomingData (which may take place
* in a background thread) encounters an error, this member function will be
* called; implement it in a derived class to receive notification of this. */
virtual void OnErrorChangeIncomingData(int errcode, int libsrtperrorcode);
int OnChangeRTPOrRTCPData(const void *origdata, size_t origlen, bool isrtp, void **senddata, size_t *sendlen);
bool OnChangeIncomingData(RTPRawPacket *rawpack);
void OnSentRTPOrRTCPData(void *senddata, size_t sendlen, bool isrtp);
private:
int encryptData(uint8_t *pData, int &dataLength, bool rtp);
int decryptRawPacket(RTPRawPacket *rawpack, int *srtpError);
srtp_ctx_t *m_pSRTPContext;
int m_lastSRTPError;
#ifdef RTP_SUPPORT_THREAD
jthread::JMutex m_srtpLock;
#endif // RTP_SUPPORT_THREAD
};
inline void RTPSecureSession::OnErrorChangeIncomingData(int, int) { }
} // end namespace
#endif // RTP_SUPPORT_SRTP
#endif // RTPSECURESESSION_H

190
qrtplib/rtpselect.h Normal file
View File

@ -0,0 +1,190 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpselect.h
*/
#ifndef RTPSELECT_H
#define RTPSELECT_H
#include "rtpconfig.h"
#include "rtptypes.h"
#include "rtperrors.h"
#include "rtptimeutilities.h"
#include "rtpsocketutil.h"
#if defined(RTP_HAVE_WSAPOLL) || defined(RTP_HAVE_POLL)
#ifndef RTP_HAVE_WSAPOLL
#include <poll.h>
#include <errno.h>
#endif // !RTP_HAVE_WSAPOLL
#include <vector>
#include <limits>
namespace qrtplib
{
inline int RTPSelect(const SocketType *sockets, int8_t *readflags, size_t numsocks, RTPTime timeout)
{
using namespace std;
vector<struct pollfd> fds(numsocks);
for (size_t i = 0 ; i < numsocks ; i++)
{
fds[i].fd = sockets[i];
fds[i].events = POLLIN;
fds[i].revents = 0;
readflags[i] = 0;
}
int timeoutmsec = -1;
if (timeout.GetDouble() >= 0)
{
double dtimeoutmsec = timeout.GetDouble()*1000.0;
if (dtimeoutmsec > (numeric_limits<int>::max)()) // parentheses to prevent windows 'max' macro expansion
dtimeoutmsec = (numeric_limits<int>::max)();
timeoutmsec = (int)dtimeoutmsec;
}
#ifdef RTP_HAVE_WSAPOLL
int status = WSAPoll(&(fds[0]), (ULONG)numsocks, timeoutmsec);
if (status < 0)
return ERR_RTP_SELECT_ERRORINPOLL;
#else
int status = poll(&(fds[0]), numsocks, timeoutmsec);
if (status < 0)
{
// We're just going to ignore an EINTR
if (errno == EINTR)
return 0;
return ERR_RTP_SELECT_ERRORINPOLL;
}
#endif // RTP_HAVE_WSAPOLL
if (status > 0)
{
for (size_t i = 0 ; i < numsocks ; i++)
{
if (fds[i].revents)
readflags[i] = 1;
}
}
return status;
}
} // end namespace
#else
#ifndef RTP_SOCKETTYPE_WINSOCK
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <errno.h>
#endif // !RTP_SOCKETTYPE_WINSOCK
namespace qrtplib
{
/** Wrapper function around 'select', 'poll' or 'WSAPoll', depending on the
* availability on your platform.
*
* Wrapper function around 'select', 'poll' or 'WSAPoll', depending on the
* availability on your platform. The function will check the specified
* `sockets` for incoming data and sets the flags in `readflags` if so.
* A maximum time `timeout` will be waited for data to arrive, which is
* indefinitely if set to a negative value. The function returns the number
* of sockets that have data incoming.
*/
inline int RTPSelect(const SocketType *sockets, int8_t *readflags, size_t numsocks, RTPTime timeout)
{
struct timeval tv;
struct timeval *pTv = 0;
if (timeout.GetDouble() >= 0)
{
tv.tv_sec = (long)timeout.GetSeconds();
tv.tv_usec = timeout.GetMicroSeconds();
pTv = &tv;
}
fd_set fdset;
FD_ZERO(&fdset);
for (size_t i = 0 ; i < numsocks ; i++)
{
#ifndef RTP_SOCKETTYPE_WINSOCK
const int setsize = FD_SETSIZE;
// On windows it seems that comparing the socket value to FD_SETSIZE does
// not make sense
if (sockets[i] >= setsize)
return ERR_RTP_SELECT_SOCKETDESCRIPTORTOOLARGE;
#endif // RTP_SOCKETTYPE_WINSOCK
FD_SET(sockets[i], &fdset);
readflags[i] = 0;
}
int status = select(FD_SETSIZE, &fdset, 0, 0, pTv);
#ifdef RTP_SOCKETTYPE_WINSOCK
if (status < 0)
return ERR_RTP_SELECT_ERRORINSELECT;
#else
if (status < 0)
{
// We're just going to ignore an EINTR
if (errno == EINTR)
return 0;
return ERR_RTP_SELECT_ERRORINSELECT;
}
#endif // RTP_HAVE_WSAPOLL
if (status > 0) // some descriptors were set, check them
{
for (size_t i = 0 ; i < numsocks ; i++)
{
if (FD_ISSET(sockets[i], &fdset))
readflags[i] = 1;
}
}
return status;
}
} // end namespace
#endif // RTP_HAVE_POLL || RTP_HAVE_WSAPOLL
#endif // RTPSELECT_H

1701
qrtplib/rtpsession.cpp Normal file

File diff suppressed because it is too large Load Diff

690
qrtplib/rtpsession.h Normal file
View File

@ -0,0 +1,690 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpsession.h
*/
#ifndef RTPSESSION_H
#define RTPSESSION_H
#include "rtpconfig.h"
#include "rtplibraryversion.h"
#include "rtppacketbuilder.h"
#include "rtpsessionsources.h"
#include "rtptransmitter.h"
#include "rtpcollisionlist.h"
#include "rtcpscheduler.h"
#include "rtcppacketbuilder.h"
#include "rtptimeutilities.h"
#include "rtcpcompoundpacketbuilder.h"
#include "rtpmemoryobject.h"
#include <list>
#ifdef RTP_SUPPORT_THREAD
#include <jthread/jmutex.h>
#endif // RTP_SUPPORT_THREAD
namespace qrtplib
{
class RTPTransmitter;
class RTPSessionParams;
class RTPTransmissionParams;
class RTPAddress;
class RTPSourceData;
class RTPPacket;
class RTPPollThread;
class RTPTransmissionInfo;
class RTCPCompoundPacket;
class RTCPPacket;
class RTCPAPPPacket;
/** High level class for using RTP.
* For most RTP based applications, the RTPSession class will probably be the one to use. It handles
* the RTCP part completely internally, so the user can focus on sending and receiving the actual data.
* In case you want to use SRTP, you should create an RTPSecureSession derived class.
* \note The RTPSession class is not meant to be thread safe. The user should use some kind of locking
* mechanism to prevent different threads from using the same RTPSession instance.
*/
class JRTPLIB_IMPORTEXPORT RTPSession : public RTPMemoryObject
{
public:
/** Constructs an RTPSession instance, optionally using a specific instance of a random
* number generator, and optionally installing a memory manager.
* Constructs an RTPSession instance, optionally using a specific instance of a random
* number generator, and optionally installing a memory manager. If no random number generator
* is specified, the RTPSession object will try to use either a RTPRandomURandom or
* RTPRandomRandS instance. If neither is available on the current platform, a RTPRandomRand48
* instance will be used instead. By specifying a random number generator yourself, it is
* possible to use the same generator in several RTPSession instances.
*/
RTPSession(RTPRandom *rnd = 0, RTPMemoryManager *mgr = 0);
virtual ~RTPSession();
/** Creates an RTP session.
* This function creates an RTP session with parameters \c sessparams, which will use a transmitter
* corresponding to \c proto. Parameters for this transmitter can be specified as well. If \c
* proto is of type RTPTransmitter::UserDefinedProto, the NewUserDefinedTransmitter function must
* be implemented.
*/
int Create(const RTPSessionParams &sessparams,const RTPTransmissionParams *transparams = 0, RTPTransmitter::TransmissionProtocol proto = RTPTransmitter::IPv4UDPProto);
/** Creates an RTP session using \c transmitter as transmission component.
* This function creates an RTP session with parameters \c sessparams, which will use the
* transmission component \c transmitter. Initialization and destruction of the transmitter
* will not be done by the RTPSession class if this Create function is used. This function
* can be useful if you which to reuse the transmission component in another RTPSession
* instance, once the original RTPSession isn't using the transmitter anymore.
*/
int Create(const RTPSessionParams &sessparams,RTPTransmitter *transmitter);
/** Leaves the session without sending a BYE packet. */
void Destroy();
/** Sends a BYE packet and leaves the session.
* Sends a BYE packet and leaves the session. At most a time \c maxwaittime will be waited to
* send the BYE packet. If this time expires, the session will be left without sending a BYE packet.
* The BYE packet will contain as reason for leaving \c reason with length \c reasonlength.
*/
void BYEDestroy(const RTPTime &maxwaittime,const void *reason,size_t reasonlength);
/** Returns whether the session has been created or not. */
bool IsActive();
/** Returns our own SSRC. */
uint32_t GetLocalSSRC();
/** Adds \c addr to the list of destinations. */
int AddDestination(const RTPAddress &addr);
/** Deletes \c addr from the list of destinations. */
int DeleteDestination(const RTPAddress &addr);
/** Clears the list of destinations. */
void ClearDestinations();
/** Returns \c true if multicasting is supported. */
bool SupportsMulticasting();
/** Joins the multicast group specified by \c addr. */
int JoinMulticastGroup(const RTPAddress &addr);
/** 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
* using the \c SetDefault member functions.
*/
int SendPacket(const void *data,size_t len);
/** Sends the RTP packet with payload \c data which has length \c len.
* It will use payload type \c pt, marker \c mark and after the packet has been built, the
* timestamp will be incremented by \c timestampinc.
*/
int SendPacket(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc);
/** Sends the RTP packet with payload \c data which has length \c len.
* The packet will contain a header extension with identifier \c hdrextID and containing data
* \c hdrextdata. The length of this data is given by \c numhdrextwords and is specified in a
* number of 32-bit words. The used payload type, marker and timestamp increment will be those that
* have been set using the \c SetDefault member functions.
*/
int SendPacketEx(const void *data,size_t len,
uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords);
/** Sends the RTP packet with payload \c data which has length \c len.
* It will use payload type \c pt, marker \c mark and after the packet has been built, the
* timestamp will be incremented by \c timestampinc. The packet will contain a header
* extension with identifier \c hdrextID and containing data \c hdrextdata. The length
* of this data is given by \c numhdrextwords and is specified in a number of 32-bit words.
*/
int SendPacketEx(const void *data,size_t len,
uint8_t pt,bool mark,uint32_t timestampinc,
uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords);
#ifdef RTP_SUPPORT_SENDAPP
/** If sending of RTCP APP packets was enabled at compile time, this function creates a compound packet
* containing an RTCP APP packet and sends it immediately.
* If sending of RTCP APP packets was enabled at compile time, this function creates a compound packet
* containing an RTCP APP packet and sends it immediately. If successful, the function returns the number
* of bytes in the RTCP compound packet. Note that this immediate sending is not compliant with the RTP
* specification, so use with care.
*/
int SendRTCPAPPPacket(uint8_t subtype, const uint8_t name[4], const void *appdata, size_t appdatalen);
#endif // RTP_SUPPORT_SENDAPP
#ifdef RTP_SUPPORT_RTCPUNKNOWN
/** Tries to send an Unknown packet immediately.
* Tries to send an Unknown packet immediately. If successful, the function returns the number
* of bytes in the RTCP compound packet. Note that this immediate sending is not compliant with the RTP
* specification, so use with care. Can send message along with a receiver report or a sender report
*/
int SendUnknownPacket(bool sr, uint8_t payload_type, uint8_t subtype, const void *data, size_t len);
#endif // RTP_SUPPORT_RTCPUNKNOWN
/** With this function raw data can be sent directly over the RTP or
* RTCP channel (if they are different); the data is **not** passed through the
* RTPSession::OnChangeRTPOrRTCPData function. */
int SendRawData(const void *data, size_t len, bool usertpchannel);
/** Sets the default payload type for RTP packets to \c pt. */
int SetDefaultPayloadType(uint8_t pt);
/** Sets the default marker for RTP packets to \c m. */
int SetDefaultMark(bool m);
/** Sets the default value to increment the timestamp with to \c timestampinc. */
int SetDefaultTimestampIncrement(uint32_t timestampinc);
/** This function increments the timestamp with the amount given by \c inc.
* This function increments the timestamp with the amount given by \c inc. This can be useful
* if, for example, a packet was not sent because it contained only silence. Then, this function
* should be called to increment the timestamp with the appropriate amount so that the next packets
* will still be played at the correct time at other hosts.
*/
int IncrementTimestamp(uint32_t inc);
/** This function increments the timestamp with the amount given set by the SetDefaultTimestampIncrement
* member function.
* This function increments the timestamp with the amount given set by the SetDefaultTimestampIncrement
* member function. This can be useful if, for example, a packet was not sent because it contained only silence.
* Then, this function should be called to increment the timestamp with the appropriate amount so that the next
* packets will still be played at the correct time at other hosts.
*/
int IncrementTimestampDefault();
/** This function allows you to inform the library about the delay between sampling the first
* sample of a packet and sending the packet.
* This function allows you to inform the library about the delay between sampling the first
* sample of a packet and sending the packet. This delay is taken into account when calculating the
* relation between RTP timestamp and wallclock time, used for inter-media synchronization.
*/
int SetPreTransmissionDelay(const RTPTime &delay);
/** This function returns an instance of a subclass of RTPTransmissionInfo which will give some
* additional information about the transmitter (a list of local IP addresses for example).
* This function returns an instance of a subclass of RTPTransmissionInfo which will give some
* additional information about the transmitter (a list of local IP addresses for example). The user
* has to free the returned instance when it is no longer needed, preferably using the DeleteTransmissionInfo
* function.
*/
RTPTransmissionInfo *GetTransmissionInfo();
/** 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.
*/
RTPTime GetRTCPDelay();
/** The following member functions (till EndDataAccess}) need to be accessed between a call
* to BeginDataAccess and EndDataAccess.
* The BeginDataAccess function makes sure that the poll thread won't access the source table
* at the same time that you're using it. When the EndDataAccess is called, the lock on the
* source table is freed again.
*/
int BeginDataAccess();
/** Starts the iteration over the participants by going to the first member in the table.
* Starts the iteration over the participants by going to the first member in the table.
* If a member was found, the function returns \c true, otherwise it returns \c false.
*/
bool GotoFirstSource();
/** Sets the current source to be the next source in the table.
* Sets the current source to be the next source in the table. If we're already at the last
* source, the function returns \c false, otherwise it returns \c true.
*/
bool GotoNextSource();
/** Sets the current source to be the previous source in the table.
* Sets the current source to be the previous source in the table. If we're at the first source,
* the function returns \c false, otherwise it returns \c true.
*/
bool GotoPreviousSource();
/** Sets the current source to be the first source in the table which has RTPPacket instances
* that we haven't extracted yet.
* Sets the current source to be the first source in the table which has RTPPacket instances
* that we haven't extracted yet. If no such member was found, the function returns \c false,
* otherwise it returns \c true.
*/
bool GotoFirstSourceWithData();
/** Sets the current source to be the next source in the table which has RTPPacket instances
* that we haven't extracted yet.
* Sets the current source to be the next source in the table which has RTPPacket instances
* that we haven't extracted yet. If no such member was found, the function returns \c false,
* otherwise it returns \c true.
*/
bool GotoNextSourceWithData();
/** Sets the current source to be the previous source in the table which has RTPPacket
* instances that we haven't extracted yet.
* Sets the current source to be the previous source in the table which has RTPPacket
* instances that we haven't extracted yet. If no such member was found, the function returns \c false,
* otherwise it returns \c true.
*/
bool GotoPreviousSourceWithData();
/** Returns the \c RTPSourceData instance for the currently selected participant. */
RTPSourceData *GetCurrentSourceInfo();
/** Returns the \c RTPSourceData instance for the participant identified by \c ssrc,
* or NULL if no such entry exists.
*/
RTPSourceData *GetSourceInfo(uint32_t ssrc);
/** Extracts the next packet from the received packets queue of the current participant,
* or NULL if no more packets are available.
* Extracts the next packet from the received packets queue of the current participant,
* or NULL if no more packets are available. When the packet is no longer needed, its
* memory should be freed using the DeletePacket member function.
*/
RTPPacket *GetNextPacket();
/** Returns the Sequence Number that will be used in the next SendPacket function call. */
uint16_t GetNextSequenceNumber() const;
/** Frees the memory used by \c p. */
void DeletePacket(RTPPacket *p);
/** See BeginDataAccess. */
int EndDataAccess();
/** Sets the receive mode to \c m.
* Sets the receive mode to \c m. Note that when the receive mode is changed, the list of
* addresses to be ignored ot accepted will be cleared.
*/
int SetReceiveMode(RTPTransmitter::ReceiveMode m);
/** Adds \c addr to the list of addresses to ignore. */
int AddToIgnoreList(const RTPAddress &addr);
/** Deletes \c addr from the list of addresses to ignore. */
int DeleteFromIgnoreList(const RTPAddress &addr);
/** Clears the list of addresses to ignore. */
void ClearIgnoreList();
/** Adds \c addr to the list of addresses to accept. */
int AddToAcceptList(const RTPAddress &addr);
/** Deletes \c addr from the list of addresses to accept. */
int DeleteFromAcceptList(const RTPAddress &addr);
/** Clears the list of addresses to accept. */
void ClearAcceptList();
/** Sets the maximum allowed packet size to \c s. */
int SetMaximumPacketSize(size_t s);
/** Sets the session bandwidth to \c bw, which is specified in bytes per second. */
int SetSessionBandwidth(double bw);
/** Sets the timestamp unit for our own data.
* Sets the timestamp unit for our own data. The timestamp unit is defined as a time interval in
* seconds divided by the corresponding timestamp interval. For example, for 8000 Hz audio, the
* timestamp unit would typically be 1/8000. Since this value is initially set to an illegal value,
* the user must set this to an allowed value to be able to create a session.
*/
int SetTimestampUnit(double u);
/** Sets the RTCP interval for the SDES name item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES name item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetNameInterval(int count);
/** Sets the RTCP interval for the SDES e-mail item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES e-mail item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetEMailInterval(int count);
/** Sets the RTCP interval for the SDES location item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES location item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetLocationInterval(int count);
/** Sets the RTCP interval for the SDES phone item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES phone item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetPhoneInterval(int count);
/** Sets the RTCP interval for the SDES tool item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES tool item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetToolInterval(int count);
/** Sets the RTCP interval for the SDES note item.
* After all possible sources in the source table have been processed, the class will check if other
* SDES items need to be sent. If \c count is zero or negative, nothing will happen. If \c count
* is positive, an SDES note item will be added after the sources in the source table have been
* processed \c count times.
*/
void SetNoteInterval(int count);
/** Sets the SDES name item for the local participant to the value \c s with length \c len. */
int SetLocalName(const void *s,size_t len);
/** Sets the SDES e-mail item for the local participant to the value \c s with length \c len. */
int SetLocalEMail(const void *s,size_t len);
/** Sets the SDES location item for the local participant to the value \c s with length \c len. */
int SetLocalLocation(const void *s,size_t len);
/** Sets the SDES phone item for the local participant to the value \c s with length \c len. */
int SetLocalPhone(const void *s,size_t len);
/** Sets the SDES tool item for the local participant to the value \c s with length \c len. */
int SetLocalTool(const void *s,size_t len);
/** Sets the SDES note item for the local participant to the value \c s with length \c len. */
int SetLocalNote(const void *s,size_t len);
protected:
/** Allocate a user defined transmitter.
* In case you specified in the Create function that you want to use a
* user defined transmitter, you should override this function. The RTPTransmitter
* instance returned by this function will then be used to send and receive RTP and
* RTCP packets. Note that when the session is destroyed, this RTPTransmitter
* instance will be destroyed as well.
*/
virtual RTPTransmitter *NewUserDefinedTransmitter();
/** Is called when an incoming RTP packet is about to be processed.
* Is called when an incoming RTP packet is about to be processed. This is _not_
* a good function to process an RTP packet in, in case you want to avoid iterating
* over the sources using the GotoFirst/GotoNext functions. In that case, the
* RTPSession::OnValidatedRTPPacket function should be used.
*/
virtual void OnRTPPacket(RTPPacket *pack,const RTPTime &receivetime, const RTPAddress *senderaddress);
/** Is called when an incoming RTCP packet is about to be processed. */
virtual void OnRTCPCompoundPacket(RTCPCompoundPacket *pack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
/** Is called when an SSRC collision was detected.
* Is called when an SSRC collision was detected. The instance \c srcdat is the one present in
* the table, the address \c senderaddress is the one that collided with one of the addresses
* and \c isrtp indicates against which address of \c srcdat the check failed.
*/
virtual void OnSSRCCollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,bool isrtp);
/** Is called when another CNAME was received than the one already present for source \c srcdat. */
virtual void OnCNAMECollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,
const uint8_t *cname,size_t cnamelength);
/** Is called when a new entry \c srcdat is added to the source table. */
virtual void OnNewSource(RTPSourceData *srcdat);
/** Is called when the entry \c srcdat is about to be deleted from the source table. */
virtual void OnRemoveSource(RTPSourceData *srcdat);
/** Is called when participant \c srcdat is timed out. */
virtual void OnTimeout(RTPSourceData *srcdat);
/** Is called when participant \c srcdat is timed after having sent a BYE packet. */
virtual void OnBYETimeout(RTPSourceData *srcdat);
/** Is called when an RTCP APP packet \c apppacket has been received at time \c receivetime
* from address \c senderaddress.
*/
virtual void OnAPPPacket(RTCPAPPPacket *apppacket,const RTPTime &receivetime,
const RTPAddress *senderaddress);
/** Is called when an unknown RTCP packet type was detected. */
virtual void OnUnknownPacketType(RTCPPacket *rtcppack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
/** Is called when an unknown packet format for a known packet type was detected. */
virtual void OnUnknownPacketFormat(RTCPPacket *rtcppack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
/** Is called when the SDES NOTE item for source \c srcdat has been timed out. */
virtual void OnNoteTimeout(RTPSourceData *srcdat);
/** Is called when an RTCP sender report has been processed for this source. */
virtual void OnRTCPSenderReport(RTPSourceData *srcdat);
/** Is called when an RTCP receiver report has been processed for this source. */
virtual void OnRTCPReceiverReport(RTPSourceData *srcdat);
/** Is called when a specific SDES item was received for this source. */
virtual void OnRTCPSDESItem(RTPSourceData *srcdat, RTCPSDESPacket::ItemType t,
const void *itemdata, size_t itemlength);
#ifdef RTP_SUPPORT_SDESPRIV
/** Is called when a specific SDES item of 'private' type was received for this source. */
virtual void OnRTCPSDESPrivateItem(RTPSourceData *srcdat, const void *prefixdata, size_t prefixlen,
const void *valuedata, size_t valuelen);
#endif // RTP_SUPPORT_SDESPRIV
/** Is called when a BYE packet has been processed for source \c srcdat. */
virtual void OnBYEPacket(RTPSourceData *srcdat);
/** Is called when an RTCP compound packet has just been sent (useful to inspect outgoing RTCP data). */
virtual void OnSendRTCPCompoundPacket(RTCPCompoundPacket *pack);
#ifdef RTP_SUPPORT_THREAD
/** Is called when error \c errcode was detected in the poll thread. */
virtual void OnPollThreadError(int errcode);
/** Is called each time the poll thread loops.
* Is called each time the poll thread loops. This happens when incoming data was
* detected or when it's time to send an RTCP compound packet.
*/
virtual void OnPollThreadStep();
/** Is called when the poll thread is started.
* Is called when the poll thread is started. This happens just before entering the
* thread main loop.
* \param stop This can be used to stop the thread immediately without entering the loop.
*/
virtual void OnPollThreadStart(bool &stop);
/** Is called when the poll thread is going to stop.
* Is called when the poll thread is going to stop. This happens just before termitating the thread.
*/
virtual void OnPollThreadStop();
#endif // RTP_SUPPORT_THREAD
/** If this is set to true, outgoing data will be passed through RTPSession::OnChangeRTPOrRTCPData
* and RTPSession::OnSentRTPOrRTCPData, allowing you to modify the data (e.g. to encrypt it). */
void SetChangeOutgoingData(bool change) { m_changeOutgoingData = change; }
/** If this is set to true, incoming data will be passed through RTPSession::OnChangeIncomingData,
* allowing you to modify the data (e.g. to decrypt it). */
void SetChangeIncomingData(bool change) { m_changeIncomingData = change; }
/** If RTPSession::SetChangeOutgoingData was sent to true, overriding this you can change the
* data packet that will actually be sent, for example adding encryption.
* If RTPSession::SetChangeOutgoingData was sent to true, overriding this you can change the
* data packet that will actually be sent, for example adding encryption.
* Note that no memory management will be performed on the `senddata` pointer you fill in,
* so if it needs to be deleted at some point you need to take care of this in some way
* yourself, a good way may be to do this in RTPSession::OnSentRTPOrRTCPData. If `senddata` is
* set to 0, no packet will be sent out. This also provides a way to turn off sending RTCP
* packets if desired. */
virtual int OnChangeRTPOrRTCPData(const void *origdata, size_t origlen, bool isrtp, void **senddata, size_t *sendlen);
/** This function is called when an RTP or RTCP packet was sent, it can be helpful
* when data was allocated in RTPSession::OnChangeRTPOrRTCPData to deallocate it
* here. */
virtual void OnSentRTPOrRTCPData(void *senddata, size_t sendlen, bool isrtp);
/** By overriding this function, the raw incoming data can be inspected
* and modified (e.g. for encryption).
* By overriding this function, the raw incoming data can be inspected
* and modified (e.g. for encryption). If the function returns `false`,
* the packet is discarded.
*/
virtual bool OnChangeIncomingData(RTPRawPacket *rawpack);
/** Allows you to use an RTP packet from the specified source directly.
* Allows you to use an RTP packet from the specified source directly. If
* `ispackethandled` is set to `true`, the packet will no longer be stored in this
* source's packet list. Note that if you do set this flag, you'll need to
* deallocate the packet yourself at an appropriate time.
*
* The difference with RTPSession::OnRTPPacket is that that
* function will always process the RTP packet further and is therefore not
* really suited to actually do something with the data.
*/
virtual void OnValidatedRTPPacket(RTPSourceData *srcdat, RTPPacket *rtppack, bool isonprobation, bool *ispackethandled);
private:
int InternalCreate(const RTPSessionParams &sessparams);
int CreateCNAME(uint8_t *buffer,size_t *bufferlength,bool resolve);
int ProcessPolledData();
int ProcessRTCPCompoundPacket(RTCPCompoundPacket &rtcpcomppack,RTPRawPacket *pack);
RTPRandom *GetRandomNumberGenerator(RTPRandom *r);
int SendRTPData(const void *data, size_t len);
int SendRTCPData(const void *data, size_t len);
RTPRandom *rtprnd;
bool deletertprnd;
RTPTransmitter *rtptrans;
bool created;
bool deletetransmitter;
bool usingpollthread, needthreadsafety;
bool acceptownpackets;
bool useSR_BYEifpossible;
size_t maxpacksize;
double sessionbandwidth;
double controlfragment;
double sendermultiplier;
double byemultiplier;
double membermultiplier;
double collisionmultiplier;
double notemultiplier;
bool sentpackets;
bool m_changeIncomingData, m_changeOutgoingData;
RTPSessionSources sources;
RTPPacketBuilder packetbuilder;
RTCPScheduler rtcpsched;
RTCPPacketBuilder rtcpbuilder;
RTPCollisionList collisionlist;
std::list<RTCPCompoundPacket *> byepackets;
#ifdef RTP_SUPPORT_THREAD
RTPPollThread *pollthread;
jthread::JMutex sourcesmutex,buildermutex,schedmutex,packsentmutex;
friend class RTPPollThread;
#endif // RTP_SUPPORT_THREAD
friend class RTPSessionSources;
friend class RTCPSessionPacketBuilder;
};
inline RTPTransmitter *RTPSession::NewUserDefinedTransmitter() { return 0; }
inline void RTPSession::OnRTPPacket(RTPPacket *, const RTPTime &, const RTPAddress *) { }
inline void RTPSession::OnRTCPCompoundPacket(RTCPCompoundPacket *, const RTPTime &, const RTPAddress *) { }
inline void RTPSession::OnSSRCCollision(RTPSourceData *, const RTPAddress *, bool ) { }
inline void RTPSession::OnCNAMECollision(RTPSourceData *, const RTPAddress *, const uint8_t *, size_t ) { }
inline void RTPSession::OnNewSource(RTPSourceData *) { }
inline void RTPSession::OnRemoveSource(RTPSourceData *) { }
inline void RTPSession::OnTimeout(RTPSourceData *) { }
inline void RTPSession::OnBYETimeout(RTPSourceData *) { }
inline void RTPSession::OnAPPPacket(RTCPAPPPacket *, const RTPTime &, const RTPAddress *) { }
inline void RTPSession::OnUnknownPacketType(RTCPPacket *, const RTPTime &, const RTPAddress *) { }
inline void RTPSession::OnUnknownPacketFormat(RTCPPacket *, const RTPTime &, const RTPAddress *) { }
inline void RTPSession::OnNoteTimeout(RTPSourceData *) { }
inline void RTPSession::OnRTCPSenderReport(RTPSourceData *) { }
inline void RTPSession::OnRTCPReceiverReport(RTPSourceData *) { }
inline void RTPSession::OnRTCPSDESItem(RTPSourceData *, RTCPSDESPacket::ItemType, const void *, size_t) { }
#ifdef RTP_SUPPORT_SDESPRIV
inline void RTPSession::OnRTCPSDESPrivateItem(RTPSourceData *, const void *, size_t, const void *, size_t) { }
#endif // RTP_SUPPORT_SDESPRIV
inline void RTPSession::OnBYEPacket(RTPSourceData *) { }
inline void RTPSession::OnSendRTCPCompoundPacket(RTCPCompoundPacket *) { }
#ifdef RTP_SUPPORT_THREAD
inline void RTPSession::OnPollThreadError(int) { }
inline void RTPSession::OnPollThreadStep() { }
inline void RTPSession::OnPollThreadStart(bool &) { }
inline void RTPSession::OnPollThreadStop() { }
#endif // RTP_SUPPORT_THREAD
inline int RTPSession::OnChangeRTPOrRTCPData(const void *, size_t, bool, void **, size_t *) {
return ERR_RTP_RTPSESSION_CHANGEREQUESTEDBUTNOTIMPLEMENTED;
}
inline void RTPSession::OnSentRTPOrRTCPData(void *, size_t, bool) { }
inline bool RTPSession::OnChangeIncomingData(RTPRawPacket *) { return true; }
inline void RTPSession::OnValidatedRTPPacket(RTPSourceData *, RTPPacket *, bool, bool *) { }
} // end namespace
#endif // RTPSESSION_H

View File

@ -0,0 +1,100 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpconfig.h"
#include "rtpsessionparams.h"
#include "rtpdefines.h"
#include "rtperrors.h"
namespace qrtplib
{
RTPSessionParams::RTPSessionParams() : mininterval(0,0)
{
#ifdef RTP_SUPPORT_THREAD
usepollthread = true;
m_needThreadSafety = true;
#else
usepollthread = false;
m_needThreadSafety = false;
#endif // RTP_SUPPORT_THREAD
maxpacksize = RTP_DEFAULTPACKETSIZE;
receivemode = RTPTransmitter::AcceptAll;
acceptown = false;
owntsunit = -1; // The user will have to set it to the correct value himself
resolvehostname = false;
#ifdef RTP_SUPPORT_PROBATION
probationtype = RTPSources::ProbationStore;
#endif // RTP_SUPPORT_PROBATION
mininterval = RTPTime(RTCP_DEFAULTMININTERVAL);
sessionbandwidth = RTP_DEFAULTSESSIONBANDWIDTH;
controlfrac = RTCP_DEFAULTBANDWIDTHFRACTION;
senderfrac = RTCP_DEFAULTSENDERFRACTION;
usehalfatstartup = RTCP_DEFAULTHALFATSTARTUP;
immediatebye = RTCP_DEFAULTIMMEDIATEBYE;
SR_BYE = RTCP_DEFAULTSRBYE;
sendermultiplier = RTP_SENDERTIMEOUTMULTIPLIER;
generaltimeoutmultiplier = RTP_MEMBERTIMEOUTMULTIPLIER;
byetimeoutmultiplier = RTP_BYETIMEOUTMULTIPLIER;
collisionmultiplier = RTP_COLLISIONTIMEOUTMULTIPLIER;
notemultiplier = RTP_NOTETTIMEOUTMULTIPLIER;
usepredefinedssrc = false;
predefinedssrc = 0;
}
int RTPSessionParams::SetUsePollThread(bool usethread)
{
#ifndef RTP_SUPPORT_THREAD
JRTPLIB_UNUSED(usethread);
return ERR_RTP_NOTHREADSUPPORT;
#else
usepollthread = usethread;
return 0;
#endif // RTP_SUPPORT_THREAD
}
int RTPSessionParams::SetNeedThreadSafety(bool s)
{
#ifndef RTP_SUPPORT_THREAD
JRTPLIB_UNUSED(s);
return ERR_RTP_NOTHREADSUPPORT;
#else
m_needThreadSafety = s;
return 0;
#endif // RTP_SUPPORT_THREAD
}
} // end namespace

256
qrtplib/rtpsessionparams.h Normal file
View File

@ -0,0 +1,256 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpsessionparams.h
*/
#ifndef RTPSESSIONPARAMS_H
#define RTPSESSIONPARAMS_H
#include "rtpconfig.h"
#include "rtptypes.h"
#include "rtptransmitter.h"
#include "rtptimeutilities.h"
#include "rtpsources.h"
namespace qrtplib
{
/** Describes the parameters for to be used by an RTPSession instance.
* Describes the parameters for to be used by an RTPSession instance. Note that the own timestamp
* unit must be set to a valid number, otherwise the session can't be created.
*/
class JRTPLIB_IMPORTEXPORT RTPSessionParams
{
public:
RTPSessionParams();
/** If \c usethread is \c true, the session will use a poll thread to automatically process incoming
* data and to send RTCP packets when necessary.
*/
int SetUsePollThread(bool usethread);
/** if `s` is `true`, the session will use mutexes in case multiple threads
* are at work. */
int SetNeedThreadSafety(bool s);
/** Returns whether the session should use a poll thread or not (default is \c true). */
bool IsUsingPollThread() const { return usepollthread; }
/** Sets the maximum allowed packet size for the session. */
void SetMaximumPacketSize(size_t max) { maxpacksize = max; }
/** Returns the maximum allowed packet size (default is 1400 bytes). */
size_t GetMaximumPacketSize() const { return maxpacksize; }
/** If the argument is \c true, the session should accept its own packets and store
* them accordingly in the source table.
*/
void SetAcceptOwnPackets(bool accept) { acceptown = accept; }
/** Returns \c true if the session should accept its own packets (default is \c false). */
bool AcceptOwnPackets() const { return acceptown; }
/** Sets the receive mode to be used by the session. */
void SetReceiveMode(RTPTransmitter::ReceiveMode recvmode) { receivemode = recvmode; }
/** Sets the receive mode to be used by the session (default is: accept all packets). */
RTPTransmitter::ReceiveMode GetReceiveMode() const { return receivemode; }
/** Sets the timestamp unit for our own data.
* Sets the timestamp unit for our own data. The timestamp unit is defined as a time interval in
* seconds divided by the corresponding timestamp interval. For example, for 8000 Hz audio, the
* timestamp unit would typically be 1/8000. Since this value is initially set to an illegal value,
* the user must set this to an allowed value to be able to create a session.
*/
void SetOwnTimestampUnit(double tsunit) { owntsunit = tsunit; }
/** Returns the currently set timestamp unit. */
double GetOwnTimestampUnit() const { return owntsunit; }
/** Sets a flag indicating if a DNS lookup should be done to determine our hostname (to construct a CNAME item).
* If \c v is set to \c true, the session will ask the transmitter to find a host name based upon the IP
* addresses in its list of local IP addresses. If set to \c false, a call to \c gethostname or something
* similar will be used to find the local hostname. Note that the first method might take some time.
*/
void SetResolveLocalHostname(bool v) { resolvehostname = v; }
/** Returns whether the local hostname should be determined from the transmitter's list of local IP addresses
* or not (default is \c false).
*/
bool GetResolveLocalHostname() const { return resolvehostname; }
#ifdef RTP_SUPPORT_PROBATION
/** If probation support is enabled, this function sets the probation type to be used. */
void SetProbationType(RTPSources::ProbationType probtype) { probationtype = probtype; }
/** Returns the probation type which will be used (default is RTPSources::ProbationStore). */
RTPSources::ProbationType GetProbationType() const { return probationtype; }
#endif // RTP_SUPPORT_PROBATION
/** Sets the session bandwidth in bytes per second. */
void SetSessionBandwidth(double sessbw) { sessionbandwidth = sessbw; }
/** Returns the session bandwidth in bytes per second (default is 10000 bytes per second). */
double GetSessionBandwidth() const { return sessionbandwidth; }
/** Sets the fraction of the session bandwidth to be used for control traffic. */
void SetControlTrafficFraction(double frac) { controlfrac = frac; }
/** Returns the fraction of the session bandwidth that will be used for control traffic (default is 5%). */
double GetControlTrafficFraction() const { return controlfrac; }
/** Sets the minimum fraction of the control traffic that will be used by senders. */
void SetSenderControlBandwidthFraction(double frac) { senderfrac = frac; }
/** Returns the minimum fraction of the control traffic that will be used by senders (default is 25%). */
double GetSenderControlBandwidthFraction() const { return senderfrac; }
/** Set the minimal time interval between sending RTCP packets. */
void SetMinimumRTCPTransmissionInterval(const RTPTime &t) { mininterval = t; }
/** Returns the minimal time interval between sending RTCP packets (default is 5 seconds). */
RTPTime GetMinimumRTCPTransmissionInterval() const { return mininterval; }
/** If \c usehalf is set to \c true, the session will only wait half of the calculated RTCP
* interval before sending its first RTCP packet.
*/
void SetUseHalfRTCPIntervalAtStartup(bool usehalf) { usehalfatstartup = usehalf; }
/** Returns whether the session will only wait half of the calculated RTCP interval before sending its
* first RTCP packet or not (default is \c true).
*/
bool GetUseHalfRTCPIntervalAtStartup() const { return usehalfatstartup; }
/** If \c v is \c true, the session will send a BYE packet immediately if this is allowed. */
void SetRequestImmediateBYE(bool v) { immediatebye = v; }
/** Returns whether the session should send a BYE packet immediately (if allowed) or not (default is \c true). */
bool GetRequestImmediateBYE() const { return immediatebye; }
/** When sending a BYE packet, this indicates whether it will be part of an RTCP compound packet
* that begins with a sender report (if allowed) or a receiver report.
*/
void SetSenderReportForBYE(bool v) { SR_BYE = v; }
/** Returns \c true if a BYE packet will be sent in an RTCP compound packet which starts with a
* sender report; if a receiver report will be used, the function returns \c false (default is \c true).
*/
bool GetSenderReportForBYE() const { return SR_BYE; }
/** Sets the multiplier to be used when timing out senders. */
void SetSenderTimeoutMultiplier(double m) { sendermultiplier = m; }
/** Returns the multiplier to be used when timing out senders (default is 2). */
double GetSenderTimeoutMultiplier() const { return sendermultiplier; }
/** Sets the multiplier to be used when timing out members. */
void SetSourceTimeoutMultiplier(double m) { generaltimeoutmultiplier = m; }
/** Returns the multiplier to be used when timing out members (default is 5). */
double GetSourceTimeoutMultiplier() const { return generaltimeoutmultiplier; }
/** Sets the multiplier to be used when timing out a member after it has sent a BYE packet. */
void SetBYETimeoutMultiplier(double m) { byetimeoutmultiplier = m; }
/** Returns the multiplier to be used when timing out a member after it has sent a BYE packet (default is 1). */
double GetBYETimeoutMultiplier() const { return byetimeoutmultiplier; }
/** Sets the multiplier to be used when timing out entries in the collision table. */
void SetCollisionTimeoutMultiplier(double m) { collisionmultiplier = m; }
/** Returns the multiplier to be used when timing out entries in the collision table (default is 10). */
double GetCollisionTimeoutMultiplier() const { return collisionmultiplier; }
/** Sets the multiplier to be used when timing out SDES NOTE information. */
void SetNoteTimeoutMultiplier(double m) { notemultiplier = m; }
/** Returns the multiplier to be used when timing out SDES NOTE information (default is 25). */
double GetNoteTimeoutMultiplier() const { return notemultiplier; }
/** Sets a flag which indicates if a predefined SSRC identifier should be used. */
void SetUsePredefinedSSRC(bool f) { usepredefinedssrc = f; }
/** Returns a flag indicating if a predefined SSRC should be used. */
bool GetUsePredefinedSSRC() const { return usepredefinedssrc; }
/** Sets the SSRC which will be used if RTPSessionParams::GetUsePredefinedSSRC returns true. */
void SetPredefinedSSRC(uint32_t ssrc) { predefinedssrc = ssrc; }
/** Returns the SSRC which will be used if RTPSessionParams::GetUsePredefinedSSRC returns true. */
uint32_t GetPredefinedSSRC() const { return predefinedssrc; }
/** Forces this string to be used as the CNAME identifier. */
void SetCNAME(const std::string &s) { cname = s; }
/** Returns the currently set CNAME, is blank when this will be generated automatically (the default). */
std::string GetCNAME() const { return cname; }
/** Returns `true` if thread safety was requested using RTPSessionParams::SetNeedThreadSafety. */
bool NeedThreadSafety() const { return m_needThreadSafety; }
private:
bool acceptown;
bool usepollthread;
size_t maxpacksize;
double owntsunit;
RTPTransmitter::ReceiveMode receivemode;
bool resolvehostname;
#ifdef RTP_SUPPORT_PROBATION
RTPSources::ProbationType probationtype;
#endif // RTP_SUPPORT_PROBATION
double sessionbandwidth;
double controlfrac;
double senderfrac;
RTPTime mininterval;
bool usehalfatstartup;
bool immediatebye;
bool SR_BYE;
double sendermultiplier;
double generaltimeoutmultiplier;
double byetimeoutmultiplier;
double collisionmultiplier;
double notemultiplier;
bool usepredefinedssrc;
uint32_t predefinedssrc;
std::string cname;
bool m_needThreadSafety;
};
} // end namespace
#endif // RTPSESSIONPARAMS_H

View File

@ -0,0 +1,141 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpsessionsources.h"
#include "rtpsession.h"
#include "rtpsourcedata.h"
namespace qrtplib
{
void RTPSessionSources::OnRTPPacket(RTPPacket *pack,const RTPTime &receivetime,const RTPAddress *senderaddress)
{
rtpsession.OnRTPPacket(pack,receivetime,senderaddress);
}
void RTPSessionSources::OnRTCPCompoundPacket(RTCPCompoundPacket *pack,const RTPTime &receivetime,const RTPAddress *senderaddress)
{
if (senderaddress != 0) // don't analyse own RTCP packets again (they're already analysed on their way out)
rtpsession.rtcpsched.AnalyseIncoming(*pack);
rtpsession.OnRTCPCompoundPacket(pack,receivetime,senderaddress);
}
void RTPSessionSources::OnSSRCCollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,bool isrtp)
{
if (srcdat->IsOwnSSRC())
owncollision = true;
rtpsession.OnSSRCCollision(srcdat,senderaddress,isrtp);
}
void RTPSessionSources::OnCNAMECollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,const uint8_t *cname,size_t cnamelength)
{
rtpsession.OnCNAMECollision(srcdat,senderaddress,cname,cnamelength);
}
void RTPSessionSources::OnNewSource(RTPSourceData *srcdat)
{
rtpsession.OnNewSource(srcdat);
}
void RTPSessionSources::OnRemoveSource(RTPSourceData *srcdat)
{
rtpsession.OnRemoveSource(srcdat);
}
void RTPSessionSources::OnTimeout(RTPSourceData *srcdat)
{
rtpsession.rtcpsched.ActiveMemberDecrease();
rtpsession.OnTimeout(srcdat);
}
void RTPSessionSources::OnBYETimeout(RTPSourceData *srcdat)
{
rtpsession.OnBYETimeout(srcdat);
}
void RTPSessionSources::OnBYEPacket(RTPSourceData *srcdat)
{
rtpsession.rtcpsched.ActiveMemberDecrease();
rtpsession.OnBYEPacket(srcdat);
}
void RTPSessionSources::OnAPPPacket(RTCPAPPPacket *apppacket,const RTPTime &receivetime,const RTPAddress *senderaddress)
{
rtpsession.OnAPPPacket(apppacket,receivetime,senderaddress);
}
void RTPSessionSources::OnUnknownPacketType(RTCPPacket *rtcppack,const RTPTime &receivetime, const RTPAddress *senderaddress)
{
rtpsession.OnUnknownPacketType(rtcppack,receivetime,senderaddress);
}
void RTPSessionSources::OnUnknownPacketFormat(RTCPPacket *rtcppack,const RTPTime &receivetime,const RTPAddress *senderaddress)
{
rtpsession.OnUnknownPacketFormat(rtcppack,receivetime,senderaddress);
}
void RTPSessionSources::OnNoteTimeout(RTPSourceData *srcdat)
{
rtpsession.OnNoteTimeout(srcdat);
}
void RTPSessionSources::OnValidatedRTPPacket(RTPSourceData *srcdat, RTPPacket *rtppack, bool isonprobation, bool *ispackethandled)
{
rtpsession.OnValidatedRTPPacket(srcdat, rtppack, isonprobation, ispackethandled);
}
void RTPSessionSources::OnRTCPSenderReport(RTPSourceData *srcdat)
{
rtpsession.OnRTCPSenderReport(srcdat);
}
void RTPSessionSources::OnRTCPReceiverReport(RTPSourceData *srcdat)
{
rtpsession.OnRTCPReceiverReport(srcdat);
}
void RTPSessionSources::OnRTCPSDESItem(RTPSourceData *srcdat, RTCPSDESPacket::ItemType t,
const void *itemdata, size_t itemlength)
{
rtpsession.OnRTCPSDESItem(srcdat, t, itemdata, itemlength);
}
#ifdef RTP_SUPPORT_SDESPRIV
void RTPSessionSources::OnRTCPSDESPrivateItem(RTPSourceData *srcdat, const void *prefixdata, size_t prefixlen,
const void *valuedata, size_t valuelen)
{
rtpsession.OnRTCPSDESPrivateItem(srcdat, prefixdata, prefixlen, valuedata, valuelen);
}
#endif // RTP_SUPPORT_SDESPRIV
} // end namespace

View File

@ -0,0 +1,93 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpsessionsources.h
*/
#ifndef RTPSESSIONSOURCES_H
#define RTPSESSIONSOURCES_H
#include "rtpconfig.h"
#include "rtpsources.h"
namespace qrtplib
{
class RTPSession;
class JRTPLIB_IMPORTEXPORT RTPSessionSources : public RTPSources
{
public:
RTPSessionSources(RTPSession &sess,RTPMemoryManager *mgr) : RTPSources(RTPSources::ProbationStore,mgr),rtpsession(sess)
{ owncollision = false; }
~RTPSessionSources() { }
void ClearOwnCollisionFlag() { owncollision = false; }
bool DetectedOwnCollision() const { return owncollision; }
private:
void OnRTPPacket(RTPPacket *pack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
void OnRTCPCompoundPacket(RTCPCompoundPacket *pack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
void OnSSRCCollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,bool isrtp);
void OnCNAMECollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,
const uint8_t *cname,size_t cnamelength);
void OnNewSource(RTPSourceData *srcdat);
void OnRemoveSource(RTPSourceData *srcdat);
void OnTimeout(RTPSourceData *srcdat);
void OnBYETimeout(RTPSourceData *srcdat);
void OnBYEPacket(RTPSourceData *srcdat);
void OnAPPPacket(RTCPAPPPacket *apppacket,const RTPTime &receivetime,
const RTPAddress *senderaddress);
void OnUnknownPacketType(RTCPPacket *rtcppack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
void OnUnknownPacketFormat(RTCPPacket *rtcppack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
void OnNoteTimeout(RTPSourceData *srcdat);
void OnValidatedRTPPacket(RTPSourceData *srcdat, RTPPacket *rtppack, bool isonprobation, bool *ispackethandled);
void OnRTCPSenderReport(RTPSourceData *srcdat);
void OnRTCPReceiverReport(RTPSourceData *srcdat);
void OnRTCPSDESItem(RTPSourceData *srcdat, RTCPSDESPacket::ItemType t,
const void *itemdata, size_t itemlength);
#ifdef RTP_SUPPORT_SDESPRIV
void OnRTCPSDESPrivateItem(RTPSourceData *srcdat, const void *prefixdata, size_t prefixlen,
const void *valuedata, size_t valuelen);
#endif // RTP_SUPPORT_SDESPRIV
RTPSession &rtpsession;
bool owncollision;
};
} // end namespace
#endif // RTPSESSIONSOURCES_H

61
qrtplib/rtpsocketutil.h Normal file
View File

@ -0,0 +1,61 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpsocketutil.h
*/
#ifndef RTPSOCKETUTIL_H
#define RTPSOCKETUTIL_H
#include "rtpconfig.h"
#ifdef RTP_SOCKETTYPE_WINSOCK
#include "rtptypes.h"
#endif // RTP_SOCKETTYPE_WINSOCK
namespace qrtplib
{
#ifndef RTP_SOCKETTYPE_WINSOCK
typedef int SocketType;
#else
typedef SOCKET SocketType;
#endif // RTP_SOCKETTYPE_WINSOCK
} // end namespace
#endif // RTPSOCKETUTIL_H

View File

@ -0,0 +1,79 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpsocketutilinternal.h
*/
#ifndef RTPSOCKETUTILINTERNAL_H
#define RTPSOCKETUTILINTERNAL_H
#ifdef RTP_SOCKETTYPE_WINSOCK
#define RTPSOCKERR INVALID_SOCKET
#define RTPCLOSE(x) closesocket(x)
#define RTPSOCKLENTYPE int
#define RTPIOCTL ioctlsocket
#else // not Win32
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#ifdef RTP_HAVE_SYS_FILIO
#include <sys/filio.h>
#endif // RTP_HAVE_SYS_FILIO
#ifdef RTP_HAVE_SYS_SOCKIO
#include <sys/sockio.h>
#endif // RTP_HAVE_SYS_SOCKIO
#ifdef RTP_SUPPORT_IFADDRS
#include <ifaddrs.h>
#endif // RTP_SUPPORT_IFADDRS
#define RTPSOCKERR -1
#define RTPCLOSE(x) close(x)
#ifdef RTP_SOCKLENTYPE_UINT
#define RTPSOCKLENTYPE unsigned int
#else
#define RTPSOCKLENTYPE int
#endif // RTP_SOCKLENTYPE_UINT
#define RTPIOCTL ioctl
#endif // RTP_SOCKETTYPE_WINSOCK
#endif // RTPSOCKETUTILINTERNAL_H

324
qrtplib/rtpsourcedata.cpp Normal file
View File

@ -0,0 +1,324 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpsourcedata.h"
#include "rtpdefines.h"
#include "rtpaddress.h"
#include "rtpmemorymanager.h"
#ifdef RTP_SUPPORT_NETINET_IN
#include <netinet/in.h>
#endif // RTP_SUPPORT_NETINET_IN
#define ACCEPTPACKETCODE \
*accept = true; \
\
sentdata = true; \
packetsreceived++; \
numnewpackets++; \
\
if (pack->GetExtendedSequenceNumber() == 0) \
{ \
baseseqnr = 0x0000FFFF; \
numcycles = 0x00010000; \
} \
else \
baseseqnr = pack->GetExtendedSequenceNumber() - 1; \
\
exthighseqnr = baseseqnr + 1; \
prevpacktime = receivetime; \
prevexthighseqnr = baseseqnr; \
savedextseqnr = baseseqnr; \
\
pack->SetExtendedSequenceNumber(exthighseqnr); \
\
prevtimestamp = pack->GetTimestamp(); \
lastmsgtime = prevpacktime; \
if (!ownpacket) /* for own packet, this value is set on an outgoing packet */ \
lastrtptime = prevpacktime;
namespace qrtplib
{
void RTPSourceStats::ProcessPacket(RTPPacket *pack,const RTPTime &receivetime,double tsunit,
bool ownpacket,bool *accept,bool applyprobation,bool *onprobation)
{
JRTPLIB_UNUSED(applyprobation); // possibly unused
// Note that the sequence number in the RTP packet is still just the
// 16 bit number contained in the RTP header
*onprobation = false;
if (!sentdata) // no valid packets received yet
{
#ifdef RTP_SUPPORT_PROBATION
if (applyprobation)
{
bool acceptpack = false;
if (probation)
{
uint16_t pseq;
uint32_t pseq2;
pseq = prevseqnr;
pseq++;
pseq2 = (uint32_t)pseq;
if (pseq2 == pack->GetExtendedSequenceNumber()) // ok, its the next expected packet
{
prevseqnr = (uint16_t)pack->GetExtendedSequenceNumber();
probation--;
if (probation == 0) // probation over
acceptpack = true;
else
*onprobation = true;
}
else // not next packet
{
probation = RTP_PROBATIONCOUNT;
prevseqnr = (uint16_t)pack->GetExtendedSequenceNumber();
*onprobation = true;
}
}
else // first packet received with this SSRC ID, start probation
{
probation = RTP_PROBATIONCOUNT;
prevseqnr = (uint16_t)pack->GetExtendedSequenceNumber();
*onprobation = true;
}
if (acceptpack)
{
ACCEPTPACKETCODE
}
else
{
*accept = false;
lastmsgtime = receivetime;
}
}
else // No probation
{
ACCEPTPACKETCODE
}
#else // No compiled-in probation support
ACCEPTPACKETCODE
#endif // RTP_SUPPORT_PROBATION
}
else // already got packets
{
uint16_t maxseq16;
uint32_t extseqnr;
// Adjust max extended sequence number and set extende seq nr of packet
*accept = true;
packetsreceived++;
numnewpackets++;
maxseq16 = (uint16_t)(exthighseqnr&0x0000FFFF);
if (pack->GetExtendedSequenceNumber() >= maxseq16)
{
extseqnr = numcycles+pack->GetExtendedSequenceNumber();
exthighseqnr = extseqnr;
}
else
{
uint16_t dif1,dif2;
dif1 = ((uint16_t)pack->GetExtendedSequenceNumber());
dif1 -= maxseq16;
dif2 = maxseq16;
dif2 -= ((uint16_t)pack->GetExtendedSequenceNumber());
if (dif1 < dif2)
{
numcycles += 0x00010000;
extseqnr = numcycles+pack->GetExtendedSequenceNumber();
exthighseqnr = extseqnr;
}
else
extseqnr = numcycles+pack->GetExtendedSequenceNumber();
}
pack->SetExtendedSequenceNumber(extseqnr);
// Calculate jitter
if (tsunit > 0)
{
#if 0
RTPTime curtime = receivetime;
double diffts1,diffts2,diff;
curtime -= prevpacktime;
diffts1 = curtime.GetDouble()/tsunit;
diffts2 = (double)pack->GetTimestamp() - (double)prevtimestamp;
diff = diffts1 - diffts2;
if (diff < 0)
diff = -diff;
diff -= djitter;
diff /= 16.0;
djitter += diff;
jitter = (uint32_t)djitter;
#else
RTPTime curtime = receivetime;
double diffts1,diffts2,diff;
uint32_t curts = pack->GetTimestamp();
curtime -= prevpacktime;
diffts1 = curtime.GetDouble()/tsunit;
if (curts > prevtimestamp)
{
uint32_t unsigneddiff = curts - prevtimestamp;
if (unsigneddiff < 0x10000000) // okay, curts realy is larger than prevtimestamp
diffts2 = (double)unsigneddiff;
else
{
// wraparound occurred and curts is actually smaller than prevtimestamp
unsigneddiff = -unsigneddiff; // to get the actual difference (in absolute value)
diffts2 = -((double)unsigneddiff);
}
}
else if (curts < prevtimestamp)
{
uint32_t unsigneddiff = prevtimestamp - curts;
if (unsigneddiff < 0x10000000) // okay, curts really is smaller than prevtimestamp
diffts2 = -((double)unsigneddiff); // negative since we actually need curts-prevtimestamp
else
{
// wraparound occurred and curts is actually larger than prevtimestamp
unsigneddiff = -unsigneddiff; // to get the actual difference (in absolute value)
diffts2 = (double)unsigneddiff;
}
}
else
diffts2 = 0;
diff = diffts1 - diffts2;
if (diff < 0)
diff = -diff;
diff -= djitter;
diff /= 16.0;
djitter += diff;
jitter = (uint32_t)djitter;
#endif
}
else
{
djitter = 0;
jitter = 0;
}
prevpacktime = receivetime;
prevtimestamp = pack->GetTimestamp();
lastmsgtime = prevpacktime;
if (!ownpacket) // for own packet, this value is set on an outgoing packet
lastrtptime = prevpacktime;
}
}
RTPSourceData::RTPSourceData(uint32_t s, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),SDESinf(mgr),byetime(0,0)
{
ssrc = s;
issender = false;
iscsrc = false;
timestampunit = -1;
receivedbye = false;
byereason = 0;
byereasonlen = 0;
rtpaddr = 0;
rtcpaddr = 0;
ownssrc = false;
validated = false;
processedinrtcp = false;
isrtpaddrset = false;
isrtcpaddrset = false;
}
RTPSourceData::~RTPSourceData()
{
FlushPackets();
if (byereason)
RTPDeleteByteArray(byereason,GetMemoryManager());
if (rtpaddr)
RTPDelete(rtpaddr,GetMemoryManager());
if (rtcpaddr)
RTPDelete(rtcpaddr,GetMemoryManager());
}
double RTPSourceData::INF_GetEstimatedTimestampUnit() const
{
if (!SRprevinf.HasInfo())
return -1.0;
RTPTime t1 = RTPTime(SRinf.GetNTPTimestamp());
RTPTime t2 = RTPTime(SRprevinf.GetNTPTimestamp());
if (t1.IsZero() || t2.IsZero()) // one of the times couldn't be calculated
return -1.0;
if (t1 <= t2)
return -1.0;
t1 -= t2; // get the time difference
uint32_t tsdiff = SRinf.GetRTPTimestamp()-SRprevinf.GetRTPTimestamp();
return (t1.GetDouble()/((double)tsdiff));
}
RTPTime RTPSourceData::INF_GetRoundtripTime() const
{
if (!RRinf.HasInfo())
return RTPTime(0,0);
if (RRinf.GetDelaySinceLastSR() == 0 && RRinf.GetLastSRTimestamp() == 0)
return RTPTime(0,0);
RTPNTPTime recvtime = RRinf.GetReceiveTime().GetNTPTime();
uint32_t rtt = ((recvtime.GetMSW()&0xFFFF)<<16)|((recvtime.GetLSW()>>16)&0xFFFF);
rtt -= RRinf.GetLastSRTimestamp();
rtt -= RRinf.GetDelaySinceLastSR();
double drtt = (((double)rtt)/65536.0);
return RTPTime(drtt);
}
} // end namespace

476
qrtplib/rtpsourcedata.h Normal file
View File

@ -0,0 +1,476 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpsourcedata.h
*/
#ifndef RTPSOURCEDATA_H
#define RTPSOURCEDATA_H
#include "rtpconfig.h"
#include "rtptimeutilities.h"
#include "rtppacket.h"
#include "rtcpsdesinfo.h"
#include "rtptypes.h"
#include "rtpsources.h"
#include "rtpmemoryobject.h"
#include <list>
namespace qrtplib
{
class RTPAddress;
class JRTPLIB_IMPORTEXPORT RTCPSenderReportInfo
{
public:
RTCPSenderReportInfo():ntptimestamp(0,0),receivetime(0,0) { hasinfo = false; rtptimestamp = 0; packetcount = 0; bytecount = 0; }
void Set(const RTPNTPTime &ntptime,uint32_t rtptime,uint32_t pcount,
uint32_t bcount,const RTPTime &rcvtime) { ntptimestamp = ntptime; rtptimestamp = rtptime; packetcount = pcount; bytecount = bcount; receivetime = rcvtime; hasinfo = true; }
bool HasInfo() const { return hasinfo; }
RTPNTPTime GetNTPTimestamp() const { return ntptimestamp; }
uint32_t GetRTPTimestamp() const { return rtptimestamp; }
uint32_t GetPacketCount() const { return packetcount; }
uint32_t GetByteCount() const { return bytecount; }
RTPTime GetReceiveTime() const { return receivetime; }
private:
bool hasinfo;
RTPNTPTime ntptimestamp;
uint32_t rtptimestamp;
uint32_t packetcount;
uint32_t bytecount;
RTPTime receivetime;
};
class JRTPLIB_IMPORTEXPORT RTCPReceiverReportInfo
{
public:
RTCPReceiverReportInfo():receivetime(0,0) { hasinfo = false; fractionlost = 0; packetslost = 0; exthighseqnr = 0; jitter = 0; lsr = 0; dlsr = 0; }
void Set(uint8_t fraclost,int32_t plost,uint32_t exthigh,
uint32_t jit,uint32_t l,uint32_t dl,const RTPTime &rcvtime) { fractionlost = ((double)fraclost)/256.0; packetslost = plost; exthighseqnr = exthigh; jitter = jit; lsr = l; dlsr = dl; receivetime = rcvtime; hasinfo = true; }
bool HasInfo() const { return hasinfo; }
double GetFractionLost() const { return fractionlost; }
int32_t GetPacketsLost() const { return packetslost; }
uint32_t GetExtendedHighestSequenceNumber() const { return exthighseqnr; }
uint32_t GetJitter() const { return jitter; }
uint32_t GetLastSRTimestamp() const { return lsr; }
uint32_t GetDelaySinceLastSR() const { return dlsr; }
RTPTime GetReceiveTime() const { return receivetime; }
private:
bool hasinfo;
double fractionlost;
int32_t packetslost;
uint32_t exthighseqnr;
uint32_t jitter;
uint32_t lsr;
uint32_t dlsr;
RTPTime receivetime;
};
class JRTPLIB_IMPORTEXPORT RTPSourceStats
{
public:
RTPSourceStats();
void ProcessPacket(RTPPacket *pack,const RTPTime &receivetime,double tsunit,bool ownpacket,bool *accept,bool applyprobation,bool *onprobation);
bool HasSentData() const { return sentdata; }
uint32_t GetNumPacketsReceived() const { return packetsreceived; }
uint32_t GetBaseSequenceNumber() const { return baseseqnr; }
uint32_t GetExtendedHighestSequenceNumber() const { return exthighseqnr; }
uint32_t GetJitter() const { return jitter; }
int32_t GetNumPacketsReceivedInInterval() const { return numnewpackets; }
uint32_t GetSavedExtendedSequenceNumber() const { return savedextseqnr; }
void StartNewInterval() { numnewpackets = 0; savedextseqnr = exthighseqnr; }
void SetLastMessageTime(const RTPTime &t) { lastmsgtime = t; }
RTPTime GetLastMessageTime() const { return lastmsgtime; }
void SetLastRTPPacketTime(const RTPTime &t) { lastrtptime = t; }
RTPTime GetLastRTPPacketTime() const { return lastrtptime; }
void SetLastNoteTime(const RTPTime &t) { lastnotetime = t; }
RTPTime GetLastNoteTime() const { return lastnotetime; }
private:
bool sentdata;
uint32_t packetsreceived;
uint32_t numcycles; // shifted left 16 bits
uint32_t baseseqnr;
uint32_t exthighseqnr,prevexthighseqnr;
uint32_t jitter,prevtimestamp;
double djitter;
RTPTime prevpacktime;
RTPTime lastmsgtime;
RTPTime lastrtptime;
RTPTime lastnotetime;
uint32_t numnewpackets;
uint32_t savedextseqnr;
#ifdef RTP_SUPPORT_PROBATION
uint16_t prevseqnr;
int probation;
#endif // RTP_SUPPORT_PROBATION
};
inline RTPSourceStats::RTPSourceStats():prevpacktime(0,0),lastmsgtime(0,0),lastrtptime(0,0),lastnotetime(0,0)
{
sentdata = false;
packetsreceived = 0;
baseseqnr = 0;
exthighseqnr = 0;
prevexthighseqnr = 0;
jitter = 0;
numcycles = 0;
numnewpackets = 0;
prevtimestamp = 0;
djitter = 0;
savedextseqnr = 0;
#ifdef RTP_SUPPORT_PROBATION
probation = 0;
prevseqnr = 0;
#endif // RTP_SUPPORT_PROBATION
}
/** Describes an entry in the RTPSources source table. */
class JRTPLIB_IMPORTEXPORT RTPSourceData : public RTPMemoryObject
{
protected:
RTPSourceData(uint32_t ssrc, RTPMemoryManager *mgr = 0);
virtual ~RTPSourceData();
public:
/** Extracts the first packet of this participants RTP packet queue. */
RTPPacket *GetNextPacket();
/** Clears the participant's RTP packet list. */
void FlushPackets();
/** Returns \c true if there are RTP packets which can be extracted. */
bool HasData() const { if (!validated) return false; return packetlist.empty()?false:true; }
/** Returns the SSRC identifier for this member. */
uint32_t GetSSRC() const { return ssrc; }
/** Returns \c true if the participant was added using the RTPSources member function CreateOwnSSRC and
* returns \c false otherwise.
*/
bool IsOwnSSRC() const { return ownssrc; }
/** Returns \c true if the source identifier is actually a CSRC from an RTP packet. */
bool IsCSRC() const { return iscsrc; }
/** Returns \c true if this member is marked as a sender and \c false if not. */
bool IsSender() const { return issender; }
/** Returns \c true if the participant is validated, which is the case if a number of
* consecutive RTP packets have been received or if a CNAME item has been received for
* this participant.
*/
bool IsValidated() const { return validated; }
/** Returns \c true if the source was validated and had not yet sent a BYE packet. */
bool IsActive() const { if (!validated) return false; if (receivedbye) return false; return true; }
/** This function is used by the RTCPPacketBuilder class to mark whether this participant's
* information has been processed in a report block or not.
*/
void SetProcessedInRTCP(bool v) { processedinrtcp = v; }
/** This function is used by the RTCPPacketBuilder class and returns whether this participant
* has been processed in a report block or not.
*/
bool IsProcessedInRTCP() const { return processedinrtcp; }
/** Returns \c true if the address from which this participant's RTP packets originate has
* already been set.
*/
bool IsRTPAddressSet() const { return isrtpaddrset; }
/** Returns \c true if the address from which this participant's RTCP packets originate has
* already been set.
*/
bool IsRTCPAddressSet() const { return isrtcpaddrset; }
/** Returns the address from which this participant's RTP packets originate.
* Returns the address from which this participant's RTP packets originate. If the address has
* been set and the returned value is NULL, this indicates that it originated from the local
* participant.
*/
const RTPAddress *GetRTPDataAddress() const { return rtpaddr; }
/** Returns the address from which this participant's RTCP packets originate.
* Returns the address from which this participant's RTCP packets originate. If the address has
* been set and the returned value is NULL, this indicates that it originated from the local
* participant.
*/
const RTPAddress *GetRTCPDataAddress() const { return rtcpaddr; }
/** Returns \c true if we received a BYE message for this participant and \c false otherwise. */
bool ReceivedBYE() const { return receivedbye; }
/** Returns the reason for leaving contained in the BYE packet of this participant.
* Returns the reason for leaving contained in the BYE packet of this participant. The length of
* the reason is stored in \c len.
*/
uint8_t *GetBYEReason(size_t *len) const { *len = byereasonlen; return byereason; }
/** Returns the time at which the BYE packet was received. */
RTPTime GetBYETime() const { return byetime; }
/** Sets the value for the timestamp unit to be used in jitter calculations for data received from this participant.
* Sets the value for the timestamp unit to be used in jitter calculations for data received from this participant.
* If not set, the library uses an approximation for the timestamp unit which is calculated from two consecutive
* RTCP sender reports. The timestamp unit is defined as a time interval divided by the corresponding timestamp
* interval. For 8000 Hz audio this would be 1/8000. For video, often a timestamp unit of 1/90000 is used.
*/
void SetTimestampUnit(double tsu) { timestampunit = tsu; }
/** Returns the timestamp unit used for this participant. */
double GetTimestampUnit() const { return timestampunit; }
/** Returns \c true if an RTCP sender report has been received from this participant. */
bool SR_HasInfo() const { return SRinf.HasInfo(); }
/** Returns the NTP timestamp contained in the last sender report. */
RTPNTPTime SR_GetNTPTimestamp() const { return SRinf.GetNTPTimestamp(); }
/** Returns the RTP timestamp contained in the last sender report. */
uint32_t SR_GetRTPTimestamp() const { return SRinf.GetRTPTimestamp(); }
/** Returns the packet count contained in the last sender report. */
uint32_t SR_GetPacketCount() const { return SRinf.GetPacketCount(); }
/** Returns the octet count contained in the last sender report. */
uint32_t SR_GetByteCount() const { return SRinf.GetByteCount(); }
/** Returns the time at which the last sender report was received. */
RTPTime SR_GetReceiveTime() const { return SRinf.GetReceiveTime(); }
/** Returns \c true if more than one RTCP sender report has been received. */
bool SR_Prev_HasInfo() const { return SRprevinf.HasInfo(); }
/** Returns the NTP timestamp contained in the second to last sender report. */
RTPNTPTime SR_Prev_GetNTPTimestamp() const { return SRprevinf.GetNTPTimestamp(); }
/** Returns the RTP timestamp contained in the second to last sender report. */
uint32_t SR_Prev_GetRTPTimestamp() const { return SRprevinf.GetRTPTimestamp(); }
/** Returns the packet count contained in the second to last sender report. */
uint32_t SR_Prev_GetPacketCount() const { return SRprevinf.GetPacketCount(); }
/** Returns the octet count contained in the second to last sender report. */
uint32_t SR_Prev_GetByteCount() const { return SRprevinf.GetByteCount(); }
/** Returns the time at which the second to last sender report was received. */
RTPTime SR_Prev_GetReceiveTime() const { return SRprevinf.GetReceiveTime(); }
/** Returns \c true if this participant sent a receiver report with information about the reception of our data. */
bool RR_HasInfo() const { return RRinf.HasInfo(); }
/** Returns the fraction lost value from the last report. */
double RR_GetFractionLost() const { return RRinf.GetFractionLost(); }
/** Returns the number of lost packets contained in the last report. */
int32_t RR_GetPacketsLost() const { return RRinf.GetPacketsLost(); }
/** Returns the extended highest sequence number contained in the last report. */
uint32_t RR_GetExtendedHighestSequenceNumber() const { return RRinf.GetExtendedHighestSequenceNumber(); }
/** Returns the jitter value from the last report. */
uint32_t RR_GetJitter() const { return RRinf.GetJitter(); }
/** Returns the LSR value from the last report. */
uint32_t RR_GetLastSRTimestamp() const { return RRinf.GetLastSRTimestamp(); }
/** Returns the DLSR value from the last report. */
uint32_t RR_GetDelaySinceLastSR() const { return RRinf.GetDelaySinceLastSR(); }
/** Returns the time at which the last report was received. */
RTPTime RR_GetReceiveTime() const { return RRinf.GetReceiveTime(); }
/** Returns \c true if this participant sent more than one receiver report with information
* about the reception of our data.
*/
bool RR_Prev_HasInfo() const { return RRprevinf.HasInfo(); }
/** Returns the fraction lost value from the second to last report. */
double RR_Prev_GetFractionLost() const { return RRprevinf.GetFractionLost(); }
/** Returns the number of lost packets contained in the second to last report. */
int32_t RR_Prev_GetPacketsLost() const { return RRprevinf.GetPacketsLost(); }
/** Returns the extended highest sequence number contained in the second to last report. */
uint32_t RR_Prev_GetExtendedHighestSequenceNumber() const { return RRprevinf.GetExtendedHighestSequenceNumber(); }
/** Returns the jitter value from the second to last report. */
uint32_t RR_Prev_GetJitter() const { return RRprevinf.GetJitter(); }
/** Returns the LSR value from the second to last report. */
uint32_t RR_Prev_GetLastSRTimestamp() const { return RRprevinf.GetLastSRTimestamp(); }
/** Returns the DLSR value from the second to last report. */
uint32_t RR_Prev_GetDelaySinceLastSR() const { return RRprevinf.GetDelaySinceLastSR(); }
/** Returns the time at which the second to last report was received. */
RTPTime RR_Prev_GetReceiveTime() const { return RRprevinf.GetReceiveTime(); }
/** Returns \c true if validated RTP packets have been received from this participant. */
bool INF_HasSentData() const { return stats.HasSentData(); }
/** Returns the total number of received packets from this participant. */
int32_t INF_GetNumPacketsReceived() const { return stats.GetNumPacketsReceived(); }
/** Returns the base sequence number of this participant. */
uint32_t INF_GetBaseSequenceNumber() const { return stats.GetBaseSequenceNumber(); }
/** Returns the extended highest sequence number received from this participant. */
uint32_t INF_GetExtendedHighestSequenceNumber() const { return stats.GetExtendedHighestSequenceNumber(); }
/** Returns the current jitter value for this participant. */
uint32_t INF_GetJitter() const { return stats.GetJitter(); }
/** Returns the time at which something was last heard from this member. */
RTPTime INF_GetLastMessageTime() const { return stats.GetLastMessageTime(); }
/** Returns the time at which the last RTP packet was received. */
RTPTime INF_GetLastRTPPacketTime() const { return stats.GetLastRTPPacketTime(); }
/** Returns the estimated timestamp unit, calculated from two consecutive sender reports. */
double INF_GetEstimatedTimestampUnit() const;
/** Returns the number of packets received since a new interval was started with INF_StartNewInterval. */
uint32_t INF_GetNumPacketsReceivedInInterval() const { return stats.GetNumPacketsReceivedInInterval(); }
/** Returns the extended sequence number which was stored by the INF_StartNewInterval call. */
uint32_t INF_GetSavedExtendedSequenceNumber() const { return stats.GetSavedExtendedSequenceNumber(); }
/** Starts a new interval to count received packets in; this also stores the current extended highest sequence
* number to be able to calculate the packet loss during the interval.
*/
void INF_StartNewInterval() { stats.StartNewInterval(); }
/** Estimates the round trip time by using the LSR and DLSR info from the last receiver report. */
RTPTime INF_GetRoundtripTime() const;
/** Returns the time at which the last SDES NOTE item was received. */
RTPTime INF_GetLastSDESNoteTime() const { return stats.GetLastNoteTime(); }
/** Returns a pointer to the SDES CNAME item of this participant and stores its length in \c len. */
uint8_t *SDES_GetCNAME(size_t *len) const { return SDESinf.GetCNAME(len); }
/** Returns a pointer to the SDES name item of this participant and stores its length in \c len. */
uint8_t *SDES_GetName(size_t *len) const { return SDESinf.GetName(len); }
/** Returns a pointer to the SDES e-mail item of this participant and stores its length in \c len. */
uint8_t *SDES_GetEMail(size_t *len) const { return SDESinf.GetEMail(len); }
/** Returns a pointer to the SDES phone item of this participant and stores its length in \c len. */
uint8_t *SDES_GetPhone(size_t *len) const { return SDESinf.GetPhone(len); }
/** Returns a pointer to the SDES location item of this participant and stores its length in \c len. */
uint8_t *SDES_GetLocation(size_t *len) const { return SDESinf.GetLocation(len); }
/** Returns a pointer to the SDES tool item of this participant and stores its length in \c len. */
uint8_t *SDES_GetTool(size_t *len) const { return SDESinf.GetTool(len); }
/** Returns a pointer to the SDES note item of this participant and stores its length in \c len. */
uint8_t *SDES_GetNote(size_t *len) const { return SDESinf.GetNote(len); }
#ifdef RTP_SUPPORT_SDESPRIV
/** Starts the iteration over the stored SDES private item prefixes and their associated values. */
void SDES_GotoFirstPrivateValue() { SDESinf.GotoFirstPrivateValue(); }
/** If available, returns \c true and stores the next SDES private item prefix in \c prefix and its length in
* \c prefixlen; the associated value and its length are then stored in \c value and \c valuelen.
*/
bool SDES_GetNextPrivateValue(uint8_t **prefix,size_t *prefixlen,uint8_t **value,size_t *valuelen) { return SDESinf.GetNextPrivateValue(prefix,prefixlen,value,valuelen); }
/** Looks for the entry which corresponds to the SDES private item prefix \c prefix with length
* \c prefixlen; if found, the function returns \c true and stores the associated value and
* its length in \c value and \c valuelen respectively.
*/
bool SDES_GetPrivateValue(uint8_t *prefix,size_t prefixlen,uint8_t **value,size_t *valuelen) const { return SDESinf.GetPrivateValue(prefix,prefixlen,value,valuelen); }
#endif // RTP_SUPPORT_SDESPRIV
protected:
std::list<RTPPacket *> packetlist;
uint32_t ssrc;
bool ownssrc;
bool iscsrc;
double timestampunit;
bool receivedbye;
bool validated;
bool processedinrtcp;
bool issender;
RTCPSenderReportInfo SRinf,SRprevinf;
RTCPReceiverReportInfo RRinf,RRprevinf;
RTPSourceStats stats;
RTCPSDESInfo SDESinf;
bool isrtpaddrset,isrtcpaddrset;
RTPAddress *rtpaddr,*rtcpaddr;
RTPTime byetime;
uint8_t *byereason;
size_t byereasonlen;
};
inline RTPPacket *RTPSourceData::GetNextPacket()
{
if (!validated)
return 0;
RTPPacket *p;
if (packetlist.empty())
return 0;
p = *(packetlist.begin());
packetlist.pop_front();
return p;
}
inline void RTPSourceData::FlushPackets()
{
std::list<RTPPacket *>::const_iterator it;
for (it = packetlist.begin() ; it != packetlist.end() ; ++it)
RTPDelete(*it,GetMemoryManager());
packetlist.clear();
}
} // end namespace
#endif // RTPSOURCEDATA_H

1277
qrtplib/rtpsources.cpp Normal file

File diff suppressed because it is too large Load Diff

406
qrtplib/rtpsources.h Normal file
View File

@ -0,0 +1,406 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpsources.h
*/
#ifndef RTPSOURCES_H
#define RTPSOURCES_H
#include "rtpconfig.h"
#include "rtpkeyhashtable.h"
#include "rtcpsdespacket.h"
#include "rtptypes.h"
#include "rtpmemoryobject.h"
#define RTPSOURCES_HASHSIZE 8317
namespace qrtplib
{
class JRTPLIB_IMPORTEXPORT RTPSources_GetHashIndex
{
public:
static int GetIndex(const uint32_t &ssrc) { return ssrc%RTPSOURCES_HASHSIZE; }
};
class RTPNTPTime;
class RTPTransmitter;
class RTCPAPPPacket;
class RTPInternalSourceData;
class RTPRawPacket;
class RTPPacket;
class RTPTime;
class RTPAddress;
class RTPSourceData;
/** Represents a table in which information about the participating sources is kept.
* Represents a table in which information about the participating sources is kept. The class has member
* functions to process RTP and RTCP data and to iterate over the participants. Note that a NULL address
* is used to identify packets from our own session. The class also provides some overridable functions
* which can be used to catch certain events (new SSRC, SSRC collision, ...).
*/
class JRTPLIB_IMPORTEXPORT RTPSources : public RTPMemoryObject
{
public:
/** Type of probation to use for new sources. */
enum ProbationType
{
NoProbation, /**< Don't use the probation algorithm; accept RTP packets immediately. */
ProbationDiscard, /**< Discard incoming RTP packets originating from a source that's on probation. */
ProbationStore /**< Store incoming RTP packet from a source that's on probation for later retrieval. */
};
/** In the constructor you can select the probation type you'd like to use and also a memory manager. */
RTPSources(ProbationType = ProbationStore,RTPMemoryManager *mgr = 0);
virtual ~RTPSources();
/** Clears the source table. */
void Clear();
#ifdef RTP_SUPPORT_PROBATION
/** Changes the current probation type. */
void SetProbationType(ProbationType probtype) { probationtype = probtype; }
#endif // RTP_SUPPORT_PROBATION
/** Creates an entry for our own SSRC identifier. */
int CreateOwnSSRC(uint32_t ssrc);
/** Deletes the entry for our own SSRC identifier. */
int DeleteOwnSSRC();
/** This function should be called if our own session has sent an RTP packet.
* This function should be called if our own session has sent an RTP packet.
* For our own SSRC entry, the sender flag is updated based upon outgoing packets instead of incoming packets.
*/
void SentRTPPacket();
/** Processes a raw packet \c rawpack.
* Processes a raw packet \c rawpack. The instance \c trans will be used to check if this
* packet is one of our own packets. The flag \c acceptownpackets indicates whether own packets should be
* accepted or ignored.
*/
int ProcessRawPacket(RTPRawPacket *rawpack,RTPTransmitter *trans,bool acceptownpackets);
/** Processes a raw packet \c rawpack.
* Processes a raw packet \c rawpack. Every transmitter in the array \c trans of length \c numtrans
* is used to check if the packet is from our own session. The flag \c acceptownpackets indicates
* whether own packets should be accepted or ignored.
*/
int ProcessRawPacket(RTPRawPacket *rawpack,RTPTransmitter *trans[],int numtrans,bool acceptownpackets);
/** Processes an RTPPacket instance \c rtppack which was received at time \c receivetime and
* which originated from \c senderaddres.
* Processes an RTPPacket instance \c rtppack which was received at time \c receivetime and
* which originated from \c senderaddres. The \c senderaddress parameter must be NULL if
* the packet was sent by the local participant. The flag \c stored indicates whether the packet
* was stored in the table or not. If so, the \c rtppack instance may not be deleted.
*/
int ProcessRTPPacket(RTPPacket *rtppack,const RTPTime &receivetime,const RTPAddress *senderaddress,bool *stored);
/** Processes the RTCP compound packet \c rtcpcomppack which was received at time \c receivetime from \c senderaddress.
* Processes the RTCP compound packet \c rtcpcomppack which was received at time \c receivetime from \c senderaddress.
* The \c senderaddress parameter must be NULL if the packet was sent by the local participant.
*/
int ProcessRTCPCompoundPacket(RTCPCompoundPacket *rtcpcomppack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
/** Process the sender information of SSRC \c ssrc into the source table.
* Process the sender information of SSRC \c ssrc into the source table. The information was received
* at time \c receivetime from address \c senderaddress. The \c senderaddress} parameter must be NULL
* if the packet was sent by the local participant.
*/
int ProcessRTCPSenderInfo(uint32_t ssrc,const RTPNTPTime &ntptime,uint32_t rtptime,
uint32_t packetcount,uint32_t octetcount,const RTPTime &receivetime,
const RTPAddress *senderaddress);
/** Processes the report block information which was sent by participant \c ssrc into the source table.
* Processes the report block information which was sent by participant \c ssrc into the source table.
* The information was received at time \c receivetime from address \c senderaddress The \c senderaddress
* parameter must be NULL if the packet was sent by the local participant.
*/
int ProcessRTCPReportBlock(uint32_t ssrc,uint8_t fractionlost,int32_t lostpackets,
uint32_t exthighseqnr,uint32_t jitter,uint32_t lsr,
uint32_t dlsr,const RTPTime &receivetime,const RTPAddress *senderaddress);
/** Processes the non-private SDES item from source \c ssrc into the source table.
* Processes the non-private SDES item from source \c ssrc into the source table. The information was
* received at time \c receivetime from address \c senderaddress. The \c senderaddress parameter must
* be NULL if the packet was sent by the local participant.
*/
int ProcessSDESNormalItem(uint32_t ssrc,RTCPSDESPacket::ItemType t,size_t itemlength,
const void *itemdata,const RTPTime &receivetime,const RTPAddress *senderaddress);
#ifdef RTP_SUPPORT_SDESPRIV
/** Processes the SDES private item from source \c ssrc into the source table.
* Processes the SDES private item from source \c ssrc into the source table. The information was
* received at time \c receivetime from address \c senderaddress. The \c senderaddress
* parameter must be NULL if the packet was sent by the local participant.
*/
int ProcessSDESPrivateItem(uint32_t ssrc,size_t prefixlen,const void *prefixdata,
size_t valuelen,const void *valuedata,const RTPTime &receivetime,
const RTPAddress *senderaddress);
#endif //RTP_SUPPORT_SDESPRIV
/** Processes the BYE message for SSRC \c ssrc.
* Processes the BYE message for SSRC \c ssrc. The information was received at time \c receivetime from
* address \c senderaddress. The \c senderaddress parameter must be NULL if the packet was sent by the
* local participant.
*/
int ProcessBYE(uint32_t ssrc,size_t reasonlength,const void *reasondata,const RTPTime &receivetime,
const RTPAddress *senderaddress);
/** If we heard from source \c ssrc, but no actual data was added to the source table (for example, if
* no report block was meant for us), this function can e used to indicate that something was received from
* this source.
* If we heard from source \c ssrc, but no actual data was added to the source table (for example, if
* no report block was meant for us), this function can e used to indicate that something was received from
* this source. This will prevent a premature timeout for this participant. The message was received at time
* \c receivetime from address \c senderaddress. The \c senderaddress parameter must be NULL if the
* packet was sent by the local participant.
*/
int UpdateReceiveTime(uint32_t ssrc,const RTPTime &receivetime,const RTPAddress *senderaddress);
/** Starts the iteration over the participants by going to the first member in the table.
* Starts the iteration over the participants by going to the first member in the table.
* If a member was found, the function returns \c true, otherwise it returns \c false.
*/
bool GotoFirstSource();
/** Sets the current source to be the next source in the table.
* Sets the current source to be the next source in the table. If we're already at the last source,
* the function returns \c false, otherwise it returns \c true.
*/
bool GotoNextSource();
/** Sets the current source to be the previous source in the table.
* Sets the current source to be the previous source in the table. If we're at the first source,
* the function returns \c false, otherwise it returns \c true.
*/
bool GotoPreviousSource();
/** Sets the current source to be the first source in the table which has RTPPacket instances
* that we haven't extracted yet.
* Sets the current source to be the first source in the table which has RTPPacket instances
* that we haven't extracted yet. If no such member was found, the function returns \c false,
* otherwise it returns \c true.
*/
bool GotoFirstSourceWithData();
/** Sets the current source to be the next source in the table which has RTPPacket instances that
* we haven't extracted yet.
* Sets the current source to be the next source in the table which has RTPPacket instances that
* we haven't extracted yet. If no such member was found, the function returns \c false,
* otherwise it returns \c true.
*/
bool GotoNextSourceWithData();
/** Sets the current source to be the previous source in the table which has RTPPacket instances
* that we haven't extracted yet.
* Sets the current source to be the previous source in the table which has RTPPacket instances
* that we haven't extracted yet. If no such member was found, the function returns \c false,
* otherwise it returns \c true.
*/
bool GotoPreviousSourceWithData();
/** Returns the RTPSourceData instance for the currently selected participant. */
RTPSourceData *GetCurrentSourceInfo();
/** Returns the RTPSourceData instance for the participant identified by \c ssrc, or
* NULL if no such entry exists.
*/
RTPSourceData *GetSourceInfo(uint32_t ssrc);
/** Extracts the next packet from the received packets queue of the current participant. */
RTPPacket *GetNextPacket();
/** Returns \c true if an entry for participant \c ssrc exists and \c false otherwise. */
bool GotEntry(uint32_t ssrc);
/** If present, it returns the RTPSourceData instance of the entry which was created by CreateOwnSSRC. */
RTPSourceData *GetOwnSourceInfo() { return (RTPSourceData *)owndata; }
/** Assuming that the current time is \c curtime, time out the members from whom we haven't heard
* during the previous time interval \c timeoutdelay.
*/
void Timeout(const RTPTime &curtime,const RTPTime &timeoutdelay);
/** Assuming that the current time is \c curtime, remove the sender flag for senders from whom we haven't
* received any RTP packets during the previous time interval \c timeoutdelay.
*/
void SenderTimeout(const RTPTime &curtime,const RTPTime &timeoutdelay);
/** Assuming that the current time is \c curtime, remove the members who sent a BYE packet more than
* the time interval \c timeoutdelay ago.
*/
void BYETimeout(const RTPTime &curtime,const RTPTime &timeoutdelay);
/** Assuming that the current time is \c curtime, clear the SDES NOTE items which haven't been updated
* during the previous time interval \c timeoutdelay.
*/
void NoteTimeout(const RTPTime &curtime,const RTPTime &timeoutdelay);
/** Combines the functions SenderTimeout, BYETimeout, Timeout and NoteTimeout.
* Combines the functions SenderTimeout, BYETimeout, Timeout and NoteTimeout. This is more efficient
* than calling all four functions since only one iteration is needed in this function.
*/
void MultipleTimeouts(const RTPTime &curtime,const RTPTime &sendertimeout,
const RTPTime &byetimeout,const RTPTime &generaltimeout,
const RTPTime &notetimeout);
/** Returns the number of participants which are marked as a sender. */
int GetSenderCount() const { return sendercount; }
/** Returns the total number of entries in the source table. */
int GetTotalCount() const { return totalcount; }
/** Returns the number of members which have been validated and which haven't sent a BYE packet yet. */
int GetActiveMemberCount() const { return activecount; }
protected:
/** Is called when an RTP packet is about to be processed. */
virtual void OnRTPPacket(RTPPacket *pack,const RTPTime &receivetime, const RTPAddress *senderaddress);
/** Is called when an RTCP compound packet is about to be processed. */
virtual void OnRTCPCompoundPacket(RTCPCompoundPacket *pack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
/** Is called when an SSRC collision was detected.
* Is called when an SSRC collision was detected. The instance \c srcdat is the one present in
* the table, the address \c senderaddress is the one that collided with one of the addresses
* and \c isrtp indicates against which address of \c srcdat the check failed.
*/
virtual void OnSSRCCollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,bool isrtp);
/** Is called when another CNAME was received than the one already present for source \c srcdat. */
virtual void OnCNAMECollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,
const uint8_t *cname,size_t cnamelength);
/** Is called when a new entry \c srcdat is added to the source table. */
virtual void OnNewSource(RTPSourceData *srcdat);
/** Is called when the entry \c srcdat is about to be deleted from the source table. */
virtual void OnRemoveSource(RTPSourceData *srcdat);
/** Is called when participant \c srcdat is timed out. */
virtual void OnTimeout(RTPSourceData *srcdat);
/** Is called when participant \c srcdat is timed after having sent a BYE packet. */
virtual void OnBYETimeout(RTPSourceData *srcdat);
/** Is called when a BYE packet has been processed for source \c srcdat. */
virtual void OnBYEPacket(RTPSourceData *srcdat);
/** Is called when an RTCP sender report has been processed for this source. */
virtual void OnRTCPSenderReport(RTPSourceData *srcdat);
/** Is called when an RTCP receiver report has been processed for this source. */
virtual void OnRTCPReceiverReport(RTPSourceData *srcdat);
/** Is called when a specific SDES item was received for this source. */
virtual void OnRTCPSDESItem(RTPSourceData *srcdat, RTCPSDESPacket::ItemType t,
const void *itemdata, size_t itemlength);
#ifdef RTP_SUPPORT_SDESPRIV
/** Is called when a specific SDES item of 'private' type was received for this source. */
virtual void OnRTCPSDESPrivateItem(RTPSourceData *srcdat, const void *prefixdata, size_t prefixlen,
const void *valuedata, size_t valuelen);
#endif // RTP_SUPPORT_SDESPRIV
/** Is called when an RTCP APP packet \c apppacket has been received at time \c receivetime
* from address \c senderaddress.
*/
virtual void OnAPPPacket(RTCPAPPPacket *apppacket,const RTPTime &receivetime,
const RTPAddress *senderaddress);
/** Is called when an unknown RTCP packet type was detected. */
virtual void OnUnknownPacketType(RTCPPacket *rtcppack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
/** Is called when an unknown packet format for a known packet type was detected. */
virtual void OnUnknownPacketFormat(RTCPPacket *rtcppack,const RTPTime &receivetime,
const RTPAddress *senderaddress);
/** Is called when the SDES NOTE item for source \c srcdat has been timed out. */
virtual void OnNoteTimeout(RTPSourceData *srcdat);
/** Allows you to use an RTP packet from the specified source directly.
* Allows you to use an RTP packet from the specified source directly. If
* `ispackethandled` is set to `true`, the packet will no longer be stored in this
* source's packet list. */
virtual void OnValidatedRTPPacket(RTPSourceData *srcdat, RTPPacket *rtppack, bool isonprobation, bool *ispackethandled);
private:
void ClearSourceList();
int ObtainSourceDataInstance(uint32_t ssrc,RTPInternalSourceData **srcdat,bool *created);
int GetRTCPSourceData(uint32_t ssrc,const RTPAddress *senderaddress,RTPInternalSourceData **srcdat,bool *newsource);
bool CheckCollision(RTPInternalSourceData *srcdat,const RTPAddress *senderaddress,bool isrtp);
RTPKeyHashTable<const uint32_t,RTPInternalSourceData*,RTPSources_GetHashIndex,RTPSOURCES_HASHSIZE> sourcelist;
int sendercount;
int totalcount;
int activecount;
#ifdef RTP_SUPPORT_PROBATION
ProbationType probationtype;
#endif // RTP_SUPPORT_PROBATION
RTPInternalSourceData *owndata;
friend class RTPInternalSourceData;
};
// Inlining the default implementations to avoid unused-parameter errors.
inline void RTPSources::OnRTPPacket(RTPPacket *, const RTPTime &, const RTPAddress *) { }
inline void RTPSources::OnRTCPCompoundPacket(RTCPCompoundPacket *, const RTPTime &, const RTPAddress *) { }
inline void RTPSources::OnSSRCCollision(RTPSourceData *, const RTPAddress *, bool) { }
inline void RTPSources::OnCNAMECollision(RTPSourceData *, const RTPAddress *, const uint8_t *, size_t) { }
inline void RTPSources::OnNewSource(RTPSourceData *) { }
inline void RTPSources::OnRemoveSource(RTPSourceData *) { }
inline void RTPSources::OnTimeout(RTPSourceData *) { }
inline void RTPSources::OnBYETimeout(RTPSourceData *) { }
inline void RTPSources::OnBYEPacket(RTPSourceData *) { }
inline void RTPSources::OnRTCPSenderReport(RTPSourceData *) { }
inline void RTPSources::OnRTCPReceiverReport(RTPSourceData *) { }
inline void RTPSources::OnRTCPSDESItem(RTPSourceData *, RTCPSDESPacket::ItemType, const void *, size_t) { }
#ifdef RTP_SUPPORT_SDESPRIV
inline void RTPSources::OnRTCPSDESPrivateItem(RTPSourceData *, const void *, size_t, const void *, size_t) { }
#endif // RTP_SUPPORT_SDESPRIV
inline void RTPSources::OnAPPPacket(RTCPAPPPacket *, const RTPTime &, const RTPAddress *) { }
inline void RTPSources::OnUnknownPacketType(RTCPPacket *, const RTPTime &, const RTPAddress *) { }
inline void RTPSources::OnUnknownPacketFormat(RTCPPacket *, const RTPTime &, const RTPAddress *) { }
inline void RTPSources::OnNoteTimeout(RTPSourceData *) { }
inline void RTPSources::OnValidatedRTPPacket(RTPSourceData *, RTPPacket *, bool, bool *) { }
} // end namespace
#endif // RTPSOURCES_H

128
qrtplib/rtpstructs.h Normal file
View File

@ -0,0 +1,128 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpstructs.h
*/
#ifndef RTPSTRUCTS_H
#define RTPSTRUCTS_H
#include "rtpconfig.h"
#include "rtptypes.h"
namespace qrtplib
{
struct RTPHeader
{
#ifdef RTP_BIG_ENDIAN
uint8_t version:2;
uint8_t padding:1;
uint8_t extension:1;
uint8_t csrccount:4;
uint8_t marker:1;
uint8_t payloadtype:7;
#else // little endian
uint8_t csrccount:4;
uint8_t extension:1;
uint8_t padding:1;
uint8_t version:2;
uint8_t payloadtype:7;
uint8_t marker:1;
#endif // RTP_BIG_ENDIAN
uint16_t sequencenumber;
uint32_t timestamp;
uint32_t ssrc;
};
struct RTPExtensionHeader
{
uint16_t extid;
uint16_t length;
};
struct RTPSourceIdentifier
{
uint32_t ssrc;
};
struct RTCPCommonHeader
{
#ifdef RTP_BIG_ENDIAN
uint8_t version:2;
uint8_t padding:1;
uint8_t count:5;
#else // little endian
uint8_t count:5;
uint8_t padding:1;
uint8_t version:2;
#endif // RTP_BIG_ENDIAN
uint8_t packettype;
uint16_t length;
};
struct RTCPSenderReport
{
uint32_t ntptime_msw;
uint32_t ntptime_lsw;
uint32_t rtptimestamp;
uint32_t packetcount;
uint32_t octetcount;
};
struct RTCPReceiverReport
{
uint32_t ssrc; // Identifies about which SSRC's data this report is...
uint8_t fractionlost;
uint8_t packetslost[3];
uint32_t exthighseqnr;
uint32_t jitter;
uint32_t lsr;
uint32_t dlsr;
};
struct RTCPSDESHeader
{
uint8_t sdesid;
uint8_t length;
};
} // end namespace
#endif // RTPSTRUCTS

68
qrtplib/rtptcpaddress.cpp Normal file
View File

@ -0,0 +1,68 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtptcpaddress.h"
#include "rtpmemorymanager.h"
namespace qrtplib
{
bool RTPTCPAddress::IsSameAddress(const RTPAddress *addr) const
{
if (addr == 0)
return false;
if (addr->GetAddressType() != TCPAddress)
return false;
const RTPTCPAddress *a = static_cast<const RTPTCPAddress *>(addr);
// We're using a socket to identify connections
if (a->m_socket == m_socket)
return true;
return false;
}
bool RTPTCPAddress::IsFromSameHost(const RTPAddress *addr) const
{
return IsSameAddress(addr);
}
RTPAddress *RTPTCPAddress::CreateCopy(RTPMemoryManager *mgr) const
{
JRTPLIB_UNUSED(mgr); // possibly unused
RTPTCPAddress *a = RTPNew(mgr,RTPMEM_TYPE_CLASS_RTPADDRESS) RTPTCPAddress(m_socket);
return a;
}
} // end namespace

84
qrtplib/rtptcpaddress.h Normal file
View File

@ -0,0 +1,84 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtptcpaddress.h
*/
#ifndef RTPTCPADDRESS_H
#define RTPTCPADDRESS_H
#include "rtpconfig.h"
#include "rtpaddress.h"
#include "rtptypes.h"
#include "rtpsocketutil.h"
namespace qrtplib
{
class RTPMemoryManager;
/** Represents a TCP 'address' and port.
* This class is used by the TCP transmission component, to specify which sockets
* should be used to send/receive data, and to know on which socket incoming data
* was received.
*/
class JRTPLIB_IMPORTEXPORT RTPTCPAddress : public RTPAddress
{
public:
/** Creates an instance with which you can use a specific socket
* in the TCP transmitter (must be connected). */
RTPTCPAddress(SocketType sock):RTPAddress(TCPAddress)
{
m_socket = sock;
}
~RTPTCPAddress() { }
/** Returns the socket that was specified in the constructor. */
SocketType GetSocket() const { return m_socket; }
RTPAddress *CreateCopy(RTPMemoryManager *mgr) const;
// Note that these functions are only used for received packets
bool IsSameAddress(const RTPAddress *addr) const;
bool IsFromSameHost(const RTPAddress *addr) const;
private:
SocketType m_socket;
};
} // end namespace
#endif // RTPTCPADDRESS_H

View File

@ -0,0 +1,924 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtptcptransmitter.h"
#include "rtprawpacket.h"
#include "rtptcpaddress.h"
#include "rtptimeutilities.h"
#include "rtpdefines.h"
#include "rtpstructs.h"
#include "rtpsocketutilinternal.h"
#include "rtpinternalutils.h"
#include "rtpselect.h"
#include <stdio.h>
#include <assert.h>
#include <vector>
#include <iostream>
using namespace std;
#define RTPTCPTRANS_MAXPACKSIZE 65535
#ifdef RTP_SUPPORT_THREAD
#define MAINMUTEX_LOCK { if (m_threadsafe) m_mainMutex.Lock(); }
#define MAINMUTEX_UNLOCK { if (m_threadsafe) m_mainMutex.Unlock(); }
#define WAITMUTEX_LOCK { if (m_threadsafe) m_waitMutex.Lock(); }
#define WAITMUTEX_UNLOCK { if (m_threadsafe) m_waitMutex.Unlock(); }
#else
#define MAINMUTEX_LOCK
#define MAINMUTEX_UNLOCK
#define WAITMUTEX_LOCK
#define WAITMUTEX_UNLOCK
#endif // RTP_SUPPORT_THREAD
namespace qrtplib
{
RTPTCPTransmitter::RTPTCPTransmitter(RTPMemoryManager *mgr) : RTPTransmitter(mgr)
{
m_created = false;
m_init = false;
}
RTPTCPTransmitter::~RTPTCPTransmitter()
{
Destroy();
}
int RTPTCPTransmitter::Init(bool tsafe)
{
if (m_init)
return ERR_RTP_TCPTRANS_ALREADYINIT;
#ifdef RTP_SUPPORT_THREAD
m_threadsafe = tsafe;
if (m_threadsafe)
{
int status;
status = m_mainMutex.Init();
if (status < 0)
return ERR_RTP_TCPTRANS_CANTINITMUTEX;
status = m_waitMutex.Init();
if (status < 0)
return ERR_RTP_TCPTRANS_CANTINITMUTEX;
}
#else
if (tsafe)
return ERR_RTP_NOTHREADSUPPORT;
#endif // RTP_SUPPORT_THREAD
m_maxPackSize = RTPTCPTRANS_MAXPACKSIZE;
m_init = true;
return 0;
}
int RTPTCPTransmitter::Create(size_t maximumpacketsize, const RTPTransmissionParams *transparams)
{
JRTPLIB_UNUSED(maximumpacketsize);
const RTPTCPTransmissionParams *params,defaultparams;
int status;
if (!m_init)
return ERR_RTP_TCPTRANS_NOTINIT;
MAINMUTEX_LOCK
if (m_created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_ALREADYCREATED;
}
// Obtain transmission parameters
if (transparams == 0)
params = &defaultparams;
else
{
if (transparams->GetTransmissionProtocol() != RTPTransmitter::TCPProto)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_ILLEGALPARAMETERS;
}
params = static_cast<const RTPTCPTransmissionParams *>(transparams);
}
if (!params->GetCreatedAbortDescriptors())
{
if ((status = m_abortDesc.Init()) < 0)
{
MAINMUTEX_UNLOCK
return status;
}
m_pAbortDesc = &m_abortDesc;
}
else
{
m_pAbortDesc = params->GetCreatedAbortDescriptors();
if (!m_pAbortDesc->IsInitialized())
{
MAINMUTEX_UNLOCK
return ERR_RTP_ABORTDESC_NOTINIT;
}
}
m_waitingForData = false;
m_created = true;
MAINMUTEX_UNLOCK
return 0;
}
void RTPTCPTransmitter::Destroy()
{
if (!m_init)
return;
MAINMUTEX_LOCK
if (!m_created)
{
MAINMUTEX_UNLOCK;
return;
}
ClearDestSockets();
FlushPackets();
m_created = false;
if (m_waitingForData)
{
m_pAbortDesc->SendAbortSignal();
m_abortDesc.Destroy(); // Doesn't do anything if not initialized
MAINMUTEX_UNLOCK
WAITMUTEX_LOCK // to make sure that the WaitForIncomingData function ended
WAITMUTEX_UNLOCK
}
else
m_abortDesc.Destroy(); // Doesn't do anything if not initialized
MAINMUTEX_UNLOCK
}
RTPTransmissionInfo *RTPTCPTransmitter::GetTransmissionInfo()
{
if (!m_init)
return 0;
MAINMUTEX_LOCK
RTPTransmissionInfo *tinf = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPTRANSMISSIONINFO) RTPTCPTransmissionInfo();
MAINMUTEX_UNLOCK
return tinf;
}
void RTPTCPTransmitter::DeleteTransmissionInfo(RTPTransmissionInfo *i)
{
if (!m_init)
return;
RTPDelete(i, GetMemoryManager());
}
int RTPTCPTransmitter::GetLocalHostName(uint8_t *buffer,size_t *bufferlength)
{
if (!m_init)
return ERR_RTP_TCPTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!m_created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_NOTCREATED;
}
if (m_localHostname.size() == 0)
{
//
// TODO
// TODO
// TODO
// TODO
//
m_localHostname.resize(9);
memcpy(&m_localHostname[0], "localhost", m_localHostname.size());
}
if ((*bufferlength) < m_localHostname.size())
{
*bufferlength = m_localHostname.size(); // tell the application the required size of the buffer
MAINMUTEX_UNLOCK
return ERR_RTP_TRANS_BUFFERLENGTHTOOSMALL;
}
memcpy(buffer,&m_localHostname[0], m_localHostname.size());
*bufferlength = m_localHostname.size();
MAINMUTEX_UNLOCK
return 0;
}
bool RTPTCPTransmitter::ComesFromThisTransmitter(const RTPAddress *addr)
{
if (!m_init)
return false;
if (addr == 0)
return false;
MAINMUTEX_LOCK
if (!m_created)
return false;
if (addr->GetAddressType() != RTPAddress::TCPAddress)
return false;
const RTPTCPAddress *pAddr = static_cast<const RTPTCPAddress *>(addr);
bool v = false;
JRTPLIB_UNUSED(pAddr);
// TODO: for now, we're assuming that we can't just send to the same transmitter
MAINMUTEX_UNLOCK
return v;
}
int RTPTCPTransmitter::Poll()
{
if (!m_init)
return ERR_RTP_TCPTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!m_created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_NOTCREATED;
}
std::map<SocketType, SocketData>::iterator it = m_destSockets.begin();
std::map<SocketType, SocketData>::iterator end = m_destSockets.end();
int status = 0;
vector<SocketType> errSockets;
while (it != end)
{
SocketType sock = it->first;
status = PollSocket(sock, it->second);
if (status < 0)
{
// Stop immediately on out of memory
if (status == ERR_RTP_OUTOFMEM)
break;
else
{
errSockets.push_back(sock);
// Don't let this count as an error (due to a closed connection for example),
// otherwise the poll thread (if used) will stop because of this. Since there
// may be more than one connection, that's not desirable in general.
status = 0;
}
}
++it;
}
MAINMUTEX_UNLOCK
for (size_t i = 0 ; i < errSockets.size() ; i++)
OnReceiveError(errSockets[i]);
return status;
}
int RTPTCPTransmitter::WaitForIncomingData(const RTPTime &delay,bool *dataavailable)
{
if (!m_init)
return ERR_RTP_TCPTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!m_created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_NOTCREATED;
}
if (m_waitingForData)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_ALREADYWAITING;
}
m_tmpSocks.resize(m_destSockets.size()+1);
m_tmpFlags.resize(m_tmpSocks.size());
SocketType abortSocket = m_pAbortDesc->GetAbortSocket();
std::map<SocketType, SocketData>::iterator it = m_destSockets.begin();
std::map<SocketType, SocketData>::iterator end = m_destSockets.end();
int idx = 0;
while (it != end)
{
m_tmpSocks[idx] = it->first;
m_tmpFlags[idx] = 0;
++it;
idx++;
}
m_tmpSocks[idx] = abortSocket;
m_tmpFlags[idx] = 0;
int idxAbort = idx;
m_waitingForData = true;
WAITMUTEX_LOCK
MAINMUTEX_UNLOCK
//cout << "Waiting for " << delay.GetDouble() << " seconds for data on " << m_tmpSocks.size() << " sockets" << endl;
int status = RTPSelect(&m_tmpSocks[0], &m_tmpFlags[0], m_tmpSocks.size(), delay);
if (status < 0)
{
MAINMUTEX_LOCK
m_waitingForData = false;
MAINMUTEX_UNLOCK
WAITMUTEX_UNLOCK
return status;
}
MAINMUTEX_LOCK
m_waitingForData = false;
if (!m_created) // destroy called
{
MAINMUTEX_UNLOCK;
WAITMUTEX_UNLOCK
return 0;
}
// if aborted, read from abort buffer
if (m_tmpFlags[idxAbort])
m_pAbortDesc->ReadSignallingByte();
if (dataavailable != 0)
{
bool avail = false;
for (size_t i = 0 ; i < m_tmpFlags.size() ; i++)
{
if (m_tmpFlags[i])
{
avail = true;
//cout << "Data available!" << endl;
break;
}
}
if (avail)
*dataavailable = true;
else
*dataavailable = false;
}
MAINMUTEX_UNLOCK
WAITMUTEX_UNLOCK
return 0;
}
int RTPTCPTransmitter::AbortWait()
{
if (!m_init)
return ERR_RTP_TCPTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!m_created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_NOTCREATED;
}
if (!m_waitingForData)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_NOTWAITING;
}
m_pAbortDesc->SendAbortSignal();
MAINMUTEX_UNLOCK
return 0;
}
int RTPTCPTransmitter::SendRTPData(const void *data,size_t len)
{
return SendRTPRTCPData(data, len);
}
int RTPTCPTransmitter::SendRTCPData(const void *data,size_t len)
{
return SendRTPRTCPData(data, len);
}
int RTPTCPTransmitter::AddDestination(const RTPAddress &addr)
{
if (!m_init)
return ERR_RTP_TCPTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!m_created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_NOTCREATED;
}
if (addr.GetAddressType() != RTPAddress::TCPAddress)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_INVALIDADDRESSTYPE;
}
const RTPTCPAddress &a = static_cast<const RTPTCPAddress &>(addr);
SocketType s = a.GetSocket();
if (s == 0)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_NOSOCKETSPECIFIED;
}
int status = ValidateSocket(s);
if (status != 0)
{
MAINMUTEX_UNLOCK
return status;
}
std::map<SocketType, SocketData>::iterator it = m_destSockets.find(s);
if (it != m_destSockets.end())
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_SOCKETALREADYINDESTINATIONS;
}
m_destSockets[s] = SocketData();
// Because the sockets are also used for incoming data, we'll abort a wait
// that may be in progress, otherwise it could take a few seconds until the
// new socket is monitored for incoming data
m_pAbortDesc->SendAbortSignal();
MAINMUTEX_UNLOCK
return 0;
}
int RTPTCPTransmitter::DeleteDestination(const RTPAddress &addr)
{
if (!m_init)
return ERR_RTP_TCPTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!m_created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_NOTCREATED;
}
if (addr.GetAddressType() != RTPAddress::TCPAddress)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_INVALIDADDRESSTYPE;
}
const RTPTCPAddress &a = static_cast<const RTPTCPAddress &>(addr);
SocketType s = a.GetSocket();
if (s == 0)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_NOSOCKETSPECIFIED;
}
std::map<SocketType, SocketData>::iterator it = m_destSockets.find(s);
if (it == m_destSockets.end())
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_SOCKETNOTFOUNDINDESTINATIONS;
}
// Clean up possibly allocated memory
uint8_t *pBuf = it->second.ExtractDataBuffer();
if (pBuf)
RTPDeleteByteArray(pBuf, GetMemoryManager());
m_destSockets.erase(it);
MAINMUTEX_UNLOCK
return 0;
}
void RTPTCPTransmitter::ClearDestinations()
{
if (!m_init)
return;
MAINMUTEX_LOCK
if (m_created)
ClearDestSockets();
MAINMUTEX_UNLOCK
}
bool RTPTCPTransmitter::SupportsMulticasting()
{
return false;
}
int RTPTCPTransmitter::JoinMulticastGroup(const RTPAddress &)
{
return ERR_RTP_TCPTRANS_NOMULTICASTSUPPORT;
}
int RTPTCPTransmitter::LeaveMulticastGroup(const RTPAddress &)
{
return ERR_RTP_TCPTRANS_NOMULTICASTSUPPORT;
}
void RTPTCPTransmitter::LeaveAllMulticastGroups()
{
}
int RTPTCPTransmitter::SetReceiveMode(RTPTransmitter::ReceiveMode m)
{
if (m != RTPTransmitter::AcceptAll)
return ERR_RTP_TCPTRANS_RECEIVEMODENOTSUPPORTED;
return 0;
}
int RTPTCPTransmitter::AddToIgnoreList(const RTPAddress &)
{
return ERR_RTP_TCPTRANS_RECEIVEMODENOTSUPPORTED;
}
int RTPTCPTransmitter::DeleteFromIgnoreList(const RTPAddress &)
{
return ERR_RTP_TCPTRANS_RECEIVEMODENOTSUPPORTED;
}
void RTPTCPTransmitter::ClearIgnoreList()
{
}
int RTPTCPTransmitter::AddToAcceptList(const RTPAddress &)
{
return ERR_RTP_TCPTRANS_RECEIVEMODENOTSUPPORTED;
}
int RTPTCPTransmitter::DeleteFromAcceptList(const RTPAddress &)
{
return ERR_RTP_TCPTRANS_RECEIVEMODENOTSUPPORTED;
}
void RTPTCPTransmitter::ClearAcceptList()
{
}
int RTPTCPTransmitter::SetMaximumPacketSize(size_t s)
{
if (!m_init)
return ERR_RTP_TCPTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!m_created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_NOTCREATED;
}
if (s > RTPTCPTRANS_MAXPACKSIZE)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_SPECIFIEDSIZETOOBIG;
}
m_maxPackSize = s;
MAINMUTEX_UNLOCK
return 0;
}
bool RTPTCPTransmitter::NewDataAvailable()
{
if (!m_init)
return false;
MAINMUTEX_LOCK
bool v;
if (!m_created)
v = false;
else
{
if (m_rawpacketlist.empty())
v = false;
else
v = true;
}
MAINMUTEX_UNLOCK
return v;
}
RTPRawPacket *RTPTCPTransmitter::GetNextPacket()
{
if (!m_init)
return 0;
MAINMUTEX_LOCK
RTPRawPacket *p;
if (!m_created)
{
MAINMUTEX_UNLOCK
return 0;
}
if (m_rawpacketlist.empty())
{
MAINMUTEX_UNLOCK
return 0;
}
p = *(m_rawpacketlist.begin());
m_rawpacketlist.pop_front();
MAINMUTEX_UNLOCK
return p;
}
// Here the private functions start...
void RTPTCPTransmitter::FlushPackets()
{
std::list<RTPRawPacket*>::const_iterator it;
for (it = m_rawpacketlist.begin() ; it != m_rawpacketlist.end() ; ++it)
RTPDelete(*it,GetMemoryManager());
m_rawpacketlist.clear();
}
int RTPTCPTransmitter::PollSocket(SocketType sock, SocketData &sdata)
{
#ifdef RTP_SOCKETTYPE_WINSOCK
unsigned long len;
#else
size_t len;
#endif // RTP_SOCKETTYPE_WINSOCK
bool dataavailable;
do
{
len = 0;
RTPIOCTL(sock, FIONREAD, &len);
if (len <= 0)
dataavailable = false;
else
dataavailable = true;
if (dataavailable)
{
RTPTime curtime = RTPTime::CurrentTime();
int relevantLen = RTPTCPTRANS_MAXPACKSIZE+2;
if ((int)len < relevantLen)
relevantLen = (int)len;
bool complete = false;
int status = sdata.ProcessAvailableBytes(sock, relevantLen, complete, GetMemoryManager());
if (status < 0)
return status;
if (complete)
{
uint8_t *pBuf = sdata.ExtractDataBuffer();
if (pBuf)
{
int dataLength = sdata.m_dataLength;
sdata.Reset();
RTPTCPAddress *pAddr = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPADDRESS) RTPTCPAddress(sock);
if (pAddr == 0)
return ERR_RTP_OUTOFMEM;
bool isrtp = true;
if (dataLength > (int)sizeof(RTCPCommonHeader))
{
RTCPCommonHeader *rtcpheader = (RTCPCommonHeader *)pBuf;
uint8_t packettype = rtcpheader->packettype;
if (packettype >= 200 && packettype <= 204)
isrtp = false;
}
RTPRawPacket *pPack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPRAWPACKET) RTPRawPacket(pBuf, dataLength, pAddr, curtime, isrtp, GetMemoryManager());
if (pPack == 0)
{
RTPDelete(pAddr,GetMemoryManager());
RTPDeleteByteArray(pBuf,GetMemoryManager());
return ERR_RTP_OUTOFMEM;
}
m_rawpacketlist.push_back(pPack);
}
}
}
} while (dataavailable);
return 0;
}
int RTPTCPTransmitter::SendRTPRTCPData(const void *data, size_t len)
{
if (!m_init)
return ERR_RTP_TCPTRANS_NOTINIT;
MAINMUTEX_LOCK
if (!m_created)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_NOTCREATED;
}
if (len > RTPTCPTRANS_MAXPACKSIZE)
{
MAINMUTEX_UNLOCK
return ERR_RTP_TCPTRANS_SPECIFIEDSIZETOOBIG;
}
std::map<SocketType, SocketData>::iterator it = m_destSockets.begin();
std::map<SocketType, SocketData>::iterator end = m_destSockets.end();
vector<SocketType> errSockets;
int flags = 0;
#ifdef RTP_HAVE_MSG_NOSIGNAL
flags = MSG_NOSIGNAL;
#endif // RTP_HAVE_MSG_NOSIGNAL
while (it != end)
{
uint8_t lengthBytes[2] = { (uint8_t)((len >> 8)&0xff), (uint8_t)(len&0xff) };
SocketType sock = it->first;
if (send(sock,(const char *)lengthBytes,2,flags) < 0 ||
send(sock,(const char *)data,len,flags) < 0)
errSockets.push_back(sock);
++it;
}
MAINMUTEX_UNLOCK
if (errSockets.size() != 0)
{
for (size_t i = 0 ; i < errSockets.size() ; i++)
OnSendError(errSockets[i]);
}
// Don't return an error code to avoid the poll thread exiting
// due to one closed connection for example
return 0;
}
int RTPTCPTransmitter::ValidateSocket(SocketType)
{
// TODO: should we even do a check (for a TCP socket)?
return 0;
}
void RTPTCPTransmitter::ClearDestSockets()
{
std::map<SocketType, SocketData>::iterator it = m_destSockets.begin();
std::map<SocketType, SocketData>::iterator end = m_destSockets.end();
while (it != end)
{
uint8_t *pBuf = it->second.ExtractDataBuffer();
if (pBuf)
RTPDeleteByteArray(pBuf, GetMemoryManager());
++it;
}
m_destSockets.clear();
}
RTPTCPTransmitter::SocketData::SocketData()
{
Reset();
}
void RTPTCPTransmitter::SocketData::Reset()
{
m_lengthBufferOffset = 0;
m_dataLength = 0;
m_dataBufferOffset = 0;
m_pDataBuffer = 0;
}
RTPTCPTransmitter::SocketData::~SocketData()
{
assert(m_pDataBuffer == 0); // Should be deleted externally to avoid storing a memory manager in the class
}
int RTPTCPTransmitter::SocketData::ProcessAvailableBytes(SocketType sock, int availLen, bool &complete, RTPMemoryManager *pMgr)
{
JRTPLIB_UNUSED(pMgr); // possibly unused
const int numLengthBuffer = 2;
if (m_lengthBufferOffset < numLengthBuffer) // first we need to get the length
{
assert(m_pDataBuffer == 0);
int num = numLengthBuffer-m_lengthBufferOffset;
if (num > availLen)
num = availLen;
int r = 0;
if (num > 0)
{
r = (int)recv(sock, (char *)(m_lengthBuffer+m_lengthBufferOffset), num, 0);
if (r < 0)
return ERR_RTP_TCPTRANS_ERRORINRECV;
}
m_lengthBufferOffset += r;
availLen -= r;
assert(m_lengthBufferOffset <= numLengthBuffer);
if (m_lengthBufferOffset == numLengthBuffer) // we can constuct a length
{
int l = 0;
for (int i = numLengthBuffer-1, shift = 0 ; i >= 0 ; i--, shift += 8)
l |= ((int)m_lengthBuffer[i]) << shift;
m_dataLength = l;
m_dataBufferOffset = 0;
//cout << "Expecting " << m_dataLength << " bytes" << endl;
// avoid allocation of length 0
if (l == 0)
l = 1;
// We don't yet know if it's an RTP or RTCP packet, so we'll stick to RTP
m_pDataBuffer = RTPNew(pMgr, RTPMEM_TYPE_BUFFER_RECEIVEDRTPPACKET) uint8_t[l];
if (m_pDataBuffer == 0)
return ERR_RTP_OUTOFMEM;
}
}
if (m_lengthBufferOffset == numLengthBuffer && m_pDataBuffer) // the last one is to make sure we didn't run out of memory
{
if (m_dataBufferOffset < m_dataLength)
{
int num = m_dataLength-m_dataBufferOffset;
if (num > availLen)
num = availLen;
int r = 0;
if (num > 0)
{
r = (int)recv(sock, (char *)(m_pDataBuffer+m_dataBufferOffset), num, 0);
if (r < 0)
return ERR_RTP_TCPTRANS_ERRORINRECV;
}
m_dataBufferOffset += r;
availLen -= r;
}
if (m_dataBufferOffset == m_dataLength)
complete = true;
}
return 0;
}
} // end namespace

207
qrtplib/rtptcptransmitter.h Normal file
View File

@ -0,0 +1,207 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtptcptransmitter.h
*/
#ifndef RTPTCPTRANSMITTER_H
#define RTPTCPTRANSMITTER_H
#include "rtpconfig.h"
#include "rtptransmitter.h"
#include "rtpsocketutil.h"
#include "rtpabortdescriptors.h"
#include <map>
#include <list>
#include <vector>
namespace qrtplib
{
/** Parameters for the TCP transmitter. */
class JRTPLIB_IMPORTEXPORT RTPTCPTransmissionParams : public RTPTransmissionParams
{
public:
RTPTCPTransmissionParams();
/** If non null, the specified abort descriptors will be used to cancel
* the function that's waiting for packets to arrive; set to null (the default)
* to let the transmitter create its own instance. */
void SetCreatedAbortDescriptors(RTPAbortDescriptors *desc) { m_pAbortDesc = desc; }
/** If non-null, this RTPAbortDescriptors instance will be used internally,
* which can be useful when creating your own poll thread for multiple
* sessions. */
RTPAbortDescriptors *GetCreatedAbortDescriptors() const { return m_pAbortDesc; }
private:
RTPAbortDescriptors *m_pAbortDesc;
};
inline RTPTCPTransmissionParams::RTPTCPTransmissionParams() : RTPTransmissionParams(RTPTransmitter::TCPProto)
{
m_pAbortDesc = 0;
}
/** Additional information about the TCP transmitter. */
class JRTPLIB_IMPORTEXPORT RTPTCPTransmissionInfo : public RTPTransmissionInfo
{
public:
RTPTCPTransmissionInfo() : RTPTransmissionInfo(RTPTransmitter::TCPProto) { }
~RTPTCPTransmissionInfo() { }
};
// TODO: this is for IPv4, and will only be valid if one rtp packet is in one tcp frame
#define RTPTCPTRANS_HEADERSIZE (20+20+2) // 20 IP, 20 TCP, 2 for framing (RFC 4571)
/** A TCP transmission component.
*
* This class inherits the RTPTransmitter interface and implements a transmission component
* which uses TCP to send and receive RTP and RTCP data. The component's parameters
* are described by the class RTPTCPTransmissionParams. The functions which have an RTPAddress
* argument require an argument of RTPTCPAddress. The RTPTransmitter::GetTransmissionInfo member function
* returns an instance of type RTPTCPTransmissionInfo.
*
* After this transmission component was created, no data will actually be sent or received
* yet. You can specify over which TCP connections (which must be established first) data
* should be transmitted by using the RTPTransmitter::AddDestination member function. This
* takes an argument of type RTPTCPAddress, with which relevant the socket descriptor can
* be passed to the transmitter.
*
* These sockets will also be used to check for incoming RTP or RTCP data. The RTPTCPAddress
* instance that's associated with a received packet, will contain the socket descriptor
* on which the data was received. This descriptor can be obtained using RTPTCPAddress::GetSocket.
*
* To get notified of an error when sending over or receiving from a socket, override the
* RTPTCPTransmitter::OnSendError and RTPTCPTransmitter::OnReceiveError member functions.
*/
class JRTPLIB_IMPORTEXPORT RTPTCPTransmitter : public RTPTransmitter
{
public:
RTPTCPTransmitter(RTPMemoryManager *mgr);
~RTPTCPTransmitter();
int Init(bool treadsafe);
int Create(size_t maxpacksize,const RTPTransmissionParams *transparams);
void Destroy();
RTPTransmissionInfo *GetTransmissionInfo();
void DeleteTransmissionInfo(RTPTransmissionInfo *inf);
int GetLocalHostName(uint8_t *buffer,size_t *bufferlength);
bool ComesFromThisTransmitter(const RTPAddress *addr);
size_t GetHeaderOverhead() { return RTPTCPTRANS_HEADERSIZE; }
int Poll();
int WaitForIncomingData(const RTPTime &delay,bool *dataavailable = 0);
int AbortWait();
int SendRTPData(const void *data,size_t len);
int SendRTCPData(const void *data,size_t len);
int AddDestination(const RTPAddress &addr);
int DeleteDestination(const RTPAddress &addr);
void ClearDestinations();
bool SupportsMulticasting();
int JoinMulticastGroup(const RTPAddress &addr);
int LeaveMulticastGroup(const RTPAddress &addr);
void LeaveAllMulticastGroups();
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(size_t s);
bool NewDataAvailable();
RTPRawPacket *GetNextPacket();
protected:
/** By overriding this function you can be notified of an error when sending over a socket. */
virtual void OnSendError(SocketType sock);
/** By overriding this function you can be notified of an error when receiving from a socket. */
virtual void OnReceiveError(SocketType sock);
private:
class SocketData
{
public:
SocketData();
~SocketData();
void Reset();
uint8_t m_lengthBuffer[2];
int m_lengthBufferOffset;
int m_dataLength;
int m_dataBufferOffset;
uint8_t *m_pDataBuffer;
uint8_t *ExtractDataBuffer() { uint8_t *pTmp = m_pDataBuffer; m_pDataBuffer = 0; return pTmp; }
int ProcessAvailableBytes(SocketType sock, int availLen, bool &complete, RTPMemoryManager *pMgr);
};
int SendRTPRTCPData(const void *data,size_t len);
void FlushPackets();
int PollSocket(SocketType sock, SocketData &sdata);
void ClearDestSockets();
int ValidateSocket(SocketType s);
bool m_init;
bool m_created;
bool m_waitingForData;
std::map<SocketType, SocketData> m_destSockets;
std::vector<SocketType> m_tmpSocks;
std::vector<int8_t> m_tmpFlags;
std::vector<uint8_t> m_localHostname;
size_t m_maxPackSize;
std::list<RTPRawPacket*> m_rawpacketlist;
RTPAbortDescriptors m_abortDesc;
RTPAbortDescriptors *m_pAbortDesc; // in case an external one was specified
#ifdef RTP_SUPPORT_THREAD
jthread::JMutex m_mainMutex, m_waitMutex;
bool m_threadsafe;
#endif // RTP_SUPPORT_THREAD
};
inline void RTPTCPTransmitter::OnSendError(SocketType) { }
inline void RTPTCPTransmitter::OnReceiveError(SocketType) { }
} // end namespace
#endif // RTPTCPTRANSMITTER_H

View File

@ -0,0 +1,49 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include "rtpconfig.h"
#include "rtptimeutilities.h"
namespace qrtplib
{
RTPTimeInitializerObject::RTPTimeInitializerObject()
{
RTPTime curtime = RTPTime::CurrentTime();
JRTPLIB_UNUSED(curtime);
dummy = -1;
}
RTPTimeInitializerObject timeinit;
} // end namespace

393
qrtplib/rtptimeutilities.h Normal file
View File

@ -0,0 +1,393 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtptimeutilities.h
*/
#ifndef RTPTIMEUTILITIES_H
#define RTPTIMEUTILITIES_H
#include "rtpconfig.h"
#include "rtptypes.h"
#ifndef RTP_HAVE_QUERYPERFORMANCECOUNTER
#include <sys/time.h>
#include <time.h>
#include <errno.h>
#endif // RTP_HAVE_QUERYPERFORMANCECOUNTER
#define RTP_NTPTIMEOFFSET 2208988800UL
#ifdef RTP_HAVE_VSUINT64SUFFIX
#define C1000000 1000000ui64
#define CEPOCH 11644473600000000ui64
#else
#define C1000000 1000000ULL
#define CEPOCH 11644473600000000ULL
#endif // RTP_HAVE_VSUINT64SUFFIX
namespace qrtplib
{
/**
* This is a simple wrapper for the most significant word (MSW) and least
* significant word (LSW) of an NTP timestamp.
*/
class JRTPLIB_IMPORTEXPORT RTPNTPTime
{
public:
/** This constructor creates and instance with MSW \c m and LSW \c l. */
RTPNTPTime(uint32_t m,uint32_t l) { msw = m ; lsw = l; }
/** Returns the most significant word. */
uint32_t GetMSW() const { return msw; }
/** Returns the least significant word. */
uint32_t GetLSW() const { return lsw; }
private:
uint32_t msw,lsw;
};
/** This class is used to specify wallclock time, delay intervals etc.
* This class is used to specify wallclock time, delay intervals etc.
* It stores a number of seconds and a number of microseconds.
*/
class JRTPLIB_IMPORTEXPORT RTPTime
{
public:
/** Returns an RTPTime instance representing the current wallclock time.
* Returns an RTPTime instance representing the current wallclock time. This is expressed
* as a number of seconds since 00:00:00 UTC, January 1, 1970.
*/
static RTPTime CurrentTime();
/** This function waits the amount of time specified in \c delay. */
static void Wait(const RTPTime &delay);
/** Creates an RTPTime instance representing \c t, which is expressed in units of seconds. */
RTPTime(double t);
/** Creates an instance that corresponds to \c ntptime.
* Creates an instance that corresponds to \c ntptime. If
* the conversion cannot be made, both the seconds and the
* microseconds are set to zero.
*/
RTPTime(RTPNTPTime ntptime);
/** Creates an instance corresponding to \c seconds and \c microseconds. */
RTPTime(int64_t seconds, uint32_t microseconds);
/** Returns the number of seconds stored in this instance. */
int64_t GetSeconds() const;
/** Returns the number of microseconds stored in this instance. */
uint32_t GetMicroSeconds() const;
/** Returns the time stored in this instance, expressed in units of seconds. */
double GetDouble() const { return m_t; }
/** Returns the NTP time corresponding to the time stored in this instance. */
RTPNTPTime GetNTPTime() const;
RTPTime &operator-=(const RTPTime &t);
RTPTime &operator+=(const RTPTime &t);
bool operator<(const RTPTime &t) const;
bool operator>(const RTPTime &t) const;
bool operator<=(const RTPTime &t) const;
bool operator>=(const RTPTime &t) const;
bool IsZero() const { return m_t == 0; }
private:
#ifdef RTP_HAVE_QUERYPERFORMANCECOUNTER
static inline uint64_t CalculateMicroseconds(uint64_t performancecount,uint64_t performancefrequency);
#endif // RTP_HAVE_QUERYPERFORMANCECOUNTER
double m_t;
};
inline RTPTime::RTPTime(double t)
{
m_t = t;
}
inline RTPTime::RTPTime(int64_t seconds, uint32_t microseconds)
{
if (seconds >= 0)
{
m_t = (double)seconds + 1e-6*(double)microseconds;
}
else
{
int64_t possec = -seconds;
m_t = (double)possec + 1e-6*(double)microseconds;
m_t = -m_t;
}
}
inline RTPTime::RTPTime(RTPNTPTime ntptime)
{
if (ntptime.GetMSW() < RTP_NTPTIMEOFFSET)
{
m_t = 0;
}
else
{
uint32_t sec = ntptime.GetMSW() - RTP_NTPTIMEOFFSET;
double x = (double)ntptime.GetLSW();
x /= (65536.0*65536.0);
x *= 1000000.0;
uint32_t microsec = (uint32_t)x;
m_t = (double)sec + 1e-6*(double)microsec;
}
}
inline int64_t RTPTime::GetSeconds() const
{
return (int64_t)m_t;
}
inline uint32_t RTPTime::GetMicroSeconds() const
{
uint32_t microsec;
if (m_t >= 0)
{
int64_t sec = (int64_t)m_t;
microsec = (uint32_t)(1e6*(m_t - (double)sec) + 0.5);
}
else // m_t < 0
{
int64_t sec = (int64_t)(-m_t);
microsec = (uint32_t)(1e6*((-m_t) - (double)sec) + 0.5);
}
if (microsec >= 1000000)
return 999999;
// Unsigned, it can never be less than 0
// if (microsec < 0)
// return 0;
return microsec;
}
#ifdef RTP_HAVE_QUERYPERFORMANCECOUNTER
inline uint64_t RTPTime::CalculateMicroseconds(uint64_t performancecount,uint64_t performancefrequency)
{
uint64_t f = performancefrequency;
uint64_t a = performancecount;
uint64_t b = a/f;
uint64_t c = a%f; // a = b*f+c => (a*1000000)/f = b*1000000+(c*1000000)/f
return b*C1000000+(c*C1000000)/f;
}
inline RTPTime RTPTime::CurrentTime()
{
static int inited = 0;
static uint64_t microseconds, initmicroseconds;
static LARGE_INTEGER performancefrequency;
uint64_t emulate_microseconds, microdiff;
SYSTEMTIME systemtime;
FILETIME filetime;
LARGE_INTEGER performancecount;
QueryPerformanceCounter(&performancecount);
if(!inited){
inited = 1;
QueryPerformanceFrequency(&performancefrequency);
GetSystemTime(&systemtime);
SystemTimeToFileTime(&systemtime,&filetime);
microseconds = ( ((uint64_t)(filetime.dwHighDateTime) << 32) + (uint64_t)(filetime.dwLowDateTime) ) / (uint64_t)10;
microseconds-= CEPOCH; // EPOCH
initmicroseconds = CalculateMicroseconds(performancecount.QuadPart, performancefrequency.QuadPart);
}
emulate_microseconds = CalculateMicroseconds(performancecount.QuadPart, performancefrequency.QuadPart);
microdiff = emulate_microseconds - initmicroseconds;
double t = 1e-6*(double)(microseconds + microdiff);
return RTPTime(t);
}
inline void RTPTime::Wait(const RTPTime &delay)
{
if (delay.m_t <= 0)
return;
uint64_t sec = (uint64_t)delay.m_t;
uint32_t microsec = (uint32_t)(1e6*(delay.m_t-(double)sec));
DWORD t = ((DWORD)sec)*1000+(((DWORD)microsec)/1000);
Sleep(t);
}
#else // unix style
#ifdef RTP_HAVE_CLOCK_GETTIME
inline double RTPTime_timespecToDouble(struct timespec &ts)
{
return (double)ts.tv_sec + 1e-9*(double)ts.tv_nsec;
}
inline RTPTime RTPTime::CurrentTime()
{
static bool s_initialized = false;
static double s_startOffet = 0;
if (!s_initialized)
{
s_initialized = true;
// Get the corresponding times in system time and monotonic time
struct timespec tpSys, tpMono;
clock_gettime(CLOCK_REALTIME, &tpSys);
clock_gettime(CLOCK_MONOTONIC, &tpMono);
double tSys = RTPTime_timespecToDouble(tpSys);
double tMono = RTPTime_timespecToDouble(tpMono);
s_startOffet = tSys - tMono;
return tSys;
}
struct timespec tpMono;
clock_gettime(CLOCK_MONOTONIC, &tpMono);
double tMono0 = RTPTime_timespecToDouble(tpMono);
return tMono0 + s_startOffet;
}
#else // gettimeofday fallback
inline RTPTime RTPTime::CurrentTime()
{
struct timeval tv;
gettimeofday(&tv,0);
return RTPTime((uint64_t)tv.tv_sec,(uint32_t)tv.tv_usec);
}
#endif // RTP_HAVE_CLOCK_GETTIME
inline void RTPTime::Wait(const RTPTime &delay)
{
if (delay.m_t <= 0)
return;
uint64_t sec = (uint64_t)delay.m_t;
uint64_t nanosec = (uint32_t)(1e9*(delay.m_t-(double)sec));
struct timespec req,rem;
int ret;
req.tv_sec = (time_t)sec;
req.tv_nsec = ((long)nanosec);
do
{
ret = nanosleep(&req,&rem);
req = rem;
} while (ret == -1 && errno == EINTR);
}
#endif // RTP_HAVE_QUERYPERFORMANCECOUNTER
inline RTPTime &RTPTime::operator-=(const RTPTime &t)
{
m_t -= t.m_t;
return *this;
}
inline RTPTime &RTPTime::operator+=(const RTPTime &t)
{
m_t += t.m_t;
return *this;
}
inline RTPNTPTime RTPTime::GetNTPTime() const
{
uint32_t sec = (uint32_t)m_t;
uint32_t microsec = (uint32_t)((m_t - (double)sec)*1e6);
uint32_t msw = sec+RTP_NTPTIMEOFFSET;
uint32_t lsw;
double x;
x = microsec/1000000.0;
x *= (65536.0*65536.0);
lsw = (uint32_t)x;
return RTPNTPTime(msw,lsw);
}
inline bool RTPTime::operator<(const RTPTime &t) const
{
return m_t < t.m_t;
}
inline bool RTPTime::operator>(const RTPTime &t) const
{
return m_t > t.m_t;
}
inline bool RTPTime::operator<=(const RTPTime &t) const
{
return m_t <= t.m_t;
}
inline bool RTPTime::operator>=(const RTPTime &t) const
{
return m_t >= t.m_t;
}
class JRTPLIB_IMPORTEXPORT RTPTimeInitializerObject
{
public:
RTPTimeInitializerObject();
void Dummy() { dummy++; }
private:
int dummy;
};
extern RTPTimeInitializerObject timeinit;
} // end namespace
#endif // RTPTIMEUTILITIES_H

260
qrtplib/rtptransmitter.h Normal file
View File

@ -0,0 +1,260 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtptransmitter.h
*/
#ifndef RTPTRANSMITTER_H
#define RTPTRANSMITTER_H
#include "rtpconfig.h"
#include "rtptypes.h"
#include "rtpmemoryobject.h"
#include "rtptimeutilities.h"
namespace qrtplib
{
class RTPRawPacket;
class RTPAddress;
class RTPTransmissionParams;
class RTPTime;
class RTPTransmissionInfo;
/** Abstract class from which actual transmission components should be derived.
* Abstract class from which actual transmission components should be derived.
* The abstract class RTPTransmitter specifies the interface for
* actual transmission components. Currently, three implementations exist:
* an UDP over IPv4 transmitter, an UDP over IPv6 transmitter and a transmitter
* which can be used to use an external transmission mechanism.
*/
class JRTPLIB_IMPORTEXPORT RTPTransmitter : public RTPMemoryObject
{
public:
/** Used to identify a specific transmitter.
* If UserDefinedProto is used in the RTPSession::Create function, the RTPSession
* virtual member function NewUserDefinedTransmitter will be called to create
* a transmission component.
*/
enum TransmissionProtocol
{
IPv4UDPProto, /**< Specifies the internal UDP over IPv4 transmitter. */
IPv6UDPProto, /**< Specifies the internal UDP over IPv6 transmitter. */
TCPProto, /**< Specifies the internal TCP transmitter. */
ExternalProto, /**< Specifies the transmitter which can send packets using an external mechanism, and which can have received packets injected into it - see RTPExternalTransmitter for additional information. */
UserDefinedProto /**< Specifies a user defined, external transmitter. */
};
/** Three kind of receive modes can be specified. */
enum ReceiveMode
{
AcceptAll, /**< All incoming data is accepted, no matter where it originated from. */
AcceptSome, /**< Only data coming from specific sources will be accepted. */
IgnoreSome /**< All incoming data is accepted, except for data coming from a specific set of sources. */
};
protected:
/** Constructor in which you can specify a memory manager to use. */
RTPTransmitter(RTPMemoryManager *mgr) : RTPMemoryObject(mgr) { timeinit.Dummy(); }
public:
virtual ~RTPTransmitter() { }
/** 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;
/** Prepares the component to be used.
* Prepares the component to be used. The parameter \c maxpacksize specifies the maximum size
* a packet can have: if the packet is larger it will not be transmitted. The \c transparams
* parameter specifies a pointer to an RTPTransmissionParams instance. This is also an abstract
* class and each actual component will define its own parameters by inheriting a class
* from RTPTransmissionParams. If \c transparams is NULL, the default transmission parameters
* for the component will be used.
*/
virtual int Create(size_t maxpacksize,const RTPTransmissionParams *transparams) = 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. */
virtual void Destroy() = 0;
/** Returns additional information about the transmitter.
* This function returns an instance of a subclass of RTPTransmissionInfo which will give
* some additional information about the transmitter (a list of local IP addresses for example).
* Currently, either an instance of RTPUDPv4TransmissionInfo or RTPUDPv6TransmissionInfo is
* returned, depending on the type of the transmitter. The user has to deallocate the returned
* instance when it is no longer needed, which can be done using RTPTransmitter::DeleteTransmissionInfo.
*/
virtual RTPTransmissionInfo *GetTransmissionInfo() = 0;
/** Deallocates the information returned by RTPTransmitter::GetTransmissionInfo .
* Deallocates the information returned by RTPTransmitter::GetTransmissionInfo .
*/
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,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;
/** Returns the amount of bytes that will be added to the RTP packet by the underlying layers (excluding
* the link layer). */
virtual 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,size_t len) = 0;
/** Send a packet with length \c len containing \c data to all RTCP addresses of the current destination list. */
virtual int SendRTCPData(const void *data,size_t len) = 0;
/** Adds the address specified by \c addr to the list of destinations. */
virtual int AddDestination(const RTPAddress &addr) = 0;
/** Deletes the address specified by \c addr from the list of destinations. */
virtual int DeleteDestination(const RTPAddress &addr) = 0;
/** Clears the list of destinations. */
virtual void ClearDestinations() = 0;
/** Returns \c true if the transmission component supports multicasting. */
virtual bool SupportsMulticasting() = 0;
/** Joins the multicast group specified by \c addr. */
virtual int JoinMulticastGroup(const RTPAddress &addr) = 0;
/** 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
* mode is changed, all information about the addresses to ignore to accept is lost.
*/
virtual int SetReceiveMode(RTPTransmitter::ReceiveMode m) = 0;
/** Adds \c addr to the list of addresses to ignore. */
virtual int AddToIgnoreList(const RTPAddress &addr) = 0;
/** Deletes \c addr from the list of addresses to accept. */
virtual int DeleteFromIgnoreList(const RTPAddress &addr)= 0;
/** Clears the list of addresses to ignore. */
virtual void ClearIgnoreList() = 0;
/** Adds \c addr to the list of addresses to accept. */
virtual int AddToAcceptList(const RTPAddress &addr) = 0;
/** Deletes \c addr from the list of addresses to accept. */
virtual int DeleteFromAcceptList(const RTPAddress &addr) = 0;
/** Clears the list of addresses to accept. */
virtual void ClearAcceptList() = 0;
/** Sets the maximum packet size which the transmitter should allow to \c s. */
virtual int SetMaximumPacketSize(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)
* in an RTPRawPacket instance. */
virtual RTPRawPacket *GetNextPacket() = 0;
};
/** Base class for transmission parameters.
* This class is an abstract class which will have a specific implementation for a
* specific kind of transmission component. All actual implementations inherit the
* GetTransmissionProtocol function which identifies the component type for which
* these parameters are valid.
*/
class JRTPLIB_IMPORTEXPORT RTPTransmissionParams
{
protected:
RTPTransmissionParams(RTPTransmitter::TransmissionProtocol p) { protocol = p; }
public:
virtual ~RTPTransmissionParams() { }
/** Returns the transmitter type for which these parameters are valid. */
RTPTransmitter::TransmissionProtocol GetTransmissionProtocol() const { return protocol; }
private:
RTPTransmitter::TransmissionProtocol protocol;
};
/** Base class for additional information about the transmitter.
* This class is an abstract class which will have a specific implementation for a
* specific kind of transmission component. All actual implementations inherit the
* GetTransmissionProtocol function which identifies the component type for which
* these parameters are valid.
*/
class JRTPLIB_IMPORTEXPORT RTPTransmissionInfo
{
protected:
RTPTransmissionInfo(RTPTransmitter::TransmissionProtocol p) { protocol = p; }
public:
virtual ~RTPTransmissionInfo() { }
/** Returns the transmitter type for which these parameters are valid. */
RTPTransmitter::TransmissionProtocol GetTransmissionProtocol() const { return protocol; }
private:
RTPTransmitter::TransmissionProtocol protocol;
};
} // end namespace
#endif // RTPTRANSMITTER_H

5
qrtplib/rtptypes.h Normal file
View File

@ -0,0 +1,5 @@
#include "rtpconfig.h"
#include <stdint.h>
#include <sys/types.h>

53
qrtplib/rtptypes_win.h Normal file
View File

@ -0,0 +1,53 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#ifndef RTPTYPES_WIN_H
#define RTPTYPES_WIN_H
#ifndef INTTYPES_DEFINED
#define INTTYPES_DEFINED
typedef char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#endif // INTTYPES_DEFINED
#endif // RTPTYPES_WIN_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,367 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpudpv4transmitter.h
*/
#ifndef RTPUDPV4TRANSMITTER_H
#define RTPUDPV4TRANSMITTER_H
#include "rtpconfig.h"
#include "rtptransmitter.h"
#include "rtpipv4destination.h"
#include "rtphashtable.h"
#include "rtpkeyhashtable.h"
#include "rtpsocketutil.h"
#include "rtpabortdescriptors.h"
#include <list>
#ifdef RTP_SUPPORT_THREAD
#include <jthread/jmutex.h>
#endif // RTP_SUPPORT_THREAD
#define RTPUDPV4TRANS_HASHSIZE 8317
#define RTPUDPV4TRANS_DEFAULTPORTBASE 5000
#define RTPUDPV4TRANS_RTPRECEIVEBUFFER 32768
#define RTPUDPV4TRANS_RTCPRECEIVEBUFFER 32768
#define RTPUDPV4TRANS_RTPTRANSMITBUFFER 32768
#define RTPUDPV4TRANS_RTCPTRANSMITBUFFER 32768
namespace qrtplib
{
/** Parameters for the UDP over IPv4 transmitter. */
class JRTPLIB_IMPORTEXPORT RTPUDPv4TransmissionParams : public RTPTransmissionParams
{
public:
RTPUDPv4TransmissionParams();
/** Sets the IP address which is used to bind the sockets to \c ip. */
void SetBindIP(uint32_t ip) { bindIP = ip; }
/** Sets the multicast interface IP address. */
void SetMulticastInterfaceIP(uint32_t ip) { mcastifaceIP = ip; }
/** Sets the RTP portbase to \c pbase, which has to be an even number
* unless RTPUDPv4TransmissionParams::SetAllowOddPortbase was called;
* a port number of zero will cause a port to be chosen automatically. */
void SetPortbase(uint16_t pbase) { portbase = pbase; }
/** Sets the multicast TTL to be used to \c mcastTTL. */
void SetMulticastTTL(uint8_t mcastTTL) { multicastTTL = mcastTTL; }
/** Passes a list of IP addresses which will be used as the local IP addresses. */
void SetLocalIPList(std::list<uint32_t> &iplist) { 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() { localIPs.clear(); }
/** Returns the IP address which will be used to bind the sockets. */
uint32_t GetBindIP() const { return bindIP; }
/** Returns the multicast interface IP address. */
uint32_t GetMulticastInterfaceIP() const { return mcastifaceIP; }
/** Returns the RTP portbase which will be used (default is 5000). */
uint16_t GetPortbase() const { return portbase; }
/** Returns the multicast TTL which will be used (default is 1). */
uint8_t GetMulticastTTL() const { return multicastTTL; }
/** Returns the list of local IP addresses. */
const std::list<uint32_t> &GetLocalIPList() const { return localIPs; }
/** Sets the RTP socket's send buffer size. */
void SetRTPSendBuffer(int s) { rtpsendbuf = s; }
/** Sets the RTP socket's receive buffer size. */
void SetRTPReceiveBuffer(int s) { rtprecvbuf = s; }
/** Sets the RTCP socket's send buffer size. */
void SetRTCPSendBuffer(int s) { rtcpsendbuf = s; }
/** Sets the RTCP socket's receive buffer size. */
void SetRTCPReceiveBuffer(int s) { rtcprecvbuf = s; }
/** Enables or disables multiplexing RTCP traffic over the RTP channel, so that only a single port is used. */
void SetRTCPMultiplexing(bool f) { rtcpmux = f; }
/** Can be used to allow the RTP port base to be any number, not just even numbers. */
void SetAllowOddPortbase(bool f) { allowoddportbase = f; }
/** Force the RTCP socket to use a specific port, not necessarily one more than
* the RTP port (set this to zero to disable). */
void SetForcedRTCPPort(uint16_t rtcpport) { forcedrtcpport = rtcpport; }
/** Use sockets that have already been created, no checks on port numbers
* will be done, and no buffer sizes will be set; you'll need to close
* the sockets yourself when done, it will **not** be done automatically. */
void SetUseExistingSockets(SocketType rtpsocket, SocketType rtcpsocket) { rtpsock = rtpsocket; rtcpsock = rtcpsocket; useexistingsockets = true; }
/** If non null, the specified abort descriptors will be used to cancel
* the function that's waiting for packets to arrive; set to null (the default
* to let the transmitter create its own instance. */
void SetCreatedAbortDescriptors(RTPAbortDescriptors *desc) { m_pAbortDesc = desc; }
/** Returns the RTP socket's send buffer size. */
int GetRTPSendBuffer() const { return rtpsendbuf; }
/** Returns the RTP socket's receive buffer size. */
int GetRTPReceiveBuffer() const { return rtprecvbuf; }
/** Returns the RTCP socket's send buffer size. */
int GetRTCPSendBuffer() const { return rtcpsendbuf; }
/** Returns the RTCP socket's receive buffer size. */
int GetRTCPReceiveBuffer() const { return rtcprecvbuf; }
/** Returns a flag indicating if RTCP traffic will be multiplexed over the RTP channel. */
bool GetRTCPMultiplexing() const { return rtcpmux; }
/** If true, any RTP portbase will be allowed, not just even numbers. */
bool GetAllowOddPortbase() const { return allowoddportbase; }
/** If non-zero, the specified port will be used to receive RTCP traffic. */
uint16_t GetForcedRTCPPort() const { return forcedrtcpport; }
/** Returns true and fills in sockets if existing sockets were set
* using RTPUDPv4TransmissionParams::SetUseExistingSockets. */
bool GetUseExistingSockets(SocketType &rtpsocket, SocketType &rtcpsocket) const { if (!useexistingsockets) return false; rtpsocket = rtpsock; rtcpsocket = rtcpsock; return true; }
/** If non-null, this RTPAbortDescriptors instance will be used internally,
* which can be useful when creating your own poll thread for multiple
* sessions. */
RTPAbortDescriptors *GetCreatedAbortDescriptors() const { return m_pAbortDesc; }
private:
uint16_t portbase;
uint32_t bindIP, mcastifaceIP;
std::list<uint32_t> localIPs;
uint8_t multicastTTL;
int rtpsendbuf, rtprecvbuf;
int rtcpsendbuf, rtcprecvbuf;
bool rtcpmux;
bool allowoddportbase;
uint16_t forcedrtcpport;
SocketType rtpsock, rtcpsock;
bool useexistingsockets;
RTPAbortDescriptors *m_pAbortDesc;
};
inline RTPUDPv4TransmissionParams::RTPUDPv4TransmissionParams() : RTPTransmissionParams(RTPTransmitter::IPv4UDPProto)
{
portbase = RTPUDPV4TRANS_DEFAULTPORTBASE;
bindIP = 0;
multicastTTL = 1;
mcastifaceIP = 0;
rtpsendbuf = RTPUDPV4TRANS_RTPTRANSMITBUFFER;
rtprecvbuf = RTPUDPV4TRANS_RTPRECEIVEBUFFER;
rtcpsendbuf = RTPUDPV4TRANS_RTCPTRANSMITBUFFER;
rtcprecvbuf = RTPUDPV4TRANS_RTCPRECEIVEBUFFER;
rtcpmux = false;
allowoddportbase = false;
forcedrtcpport = 0;
useexistingsockets = false;
rtpsock = 0;
rtcpsock = 0;
m_pAbortDesc = 0;
}
/** Additional information about the UDP over IPv4 transmitter. */
class JRTPLIB_IMPORTEXPORT RTPUDPv4TransmissionInfo : public RTPTransmissionInfo
{
public:
RTPUDPv4TransmissionInfo(std::list<uint32_t> iplist,SocketType rtpsock,SocketType rtcpsock,
uint16_t rtpport, uint16_t rtcpport) : RTPTransmissionInfo(RTPTransmitter::IPv4UDPProto)
{ localIPlist = iplist; rtpsocket = rtpsock; rtcpsocket = rtcpsock; m_rtpPort = rtpport; m_rtcpPort = rtcpport; }
~RTPUDPv4TransmissionInfo() { }
/** Returns the list of IPv4 addresses the transmitter considers to be the local IP addresses. */
std::list<uint32_t> GetLocalIPList() const { return localIPlist; }
/** Returns the socket descriptor used for receiving and transmitting RTP packets. */
SocketType GetRTPSocket() const { return rtpsocket; }
/** Returns the socket descriptor used for receiving and transmitting RTCP packets. */
SocketType GetRTCPSocket() const { return rtcpsocket; }
/** Returns the port number that the RTP socket receives packets on. */
uint16_t GetRTPPort() const { return m_rtpPort; }
/** Returns the port number that the RTCP socket receives packets on. */
uint16_t GetRTCPPort() const { return m_rtcpPort; }
private:
std::list<uint32_t> localIPlist;
SocketType rtpsocket,rtcpsocket;
uint16_t m_rtpPort, m_rtcpPort;
};
class JRTPLIB_IMPORTEXPORT RTPUDPv4Trans_GetHashIndex_IPv4Dest
{
public:
static int GetIndex(const RTPIPv4Destination &d) { return d.GetIP()%RTPUDPV4TRANS_HASHSIZE; }
};
class JRTPLIB_IMPORTEXPORT RTPUDPv4Trans_GetHashIndex_uint32_t
{
public:
static int GetIndex(const uint32_t &k) { return k%RTPUDPV4TRANS_HASHSIZE; }
};
#define RTPUDPV4TRANS_HEADERSIZE (20+8)
/** An UDP over IPv4 transmission component.
* This class inherits the RTPTransmitter interface and implements a transmission component
* which uses UDP over IPv4 to send and receive RTP and RTCP data. The component's parameters
* are described by the class RTPUDPv4TransmissionParams. The functions which have an RTPAddress
* argument require an argument of RTPIPv4Address. The GetTransmissionInfo member function
* returns an instance of type RTPUDPv4TransmissionInfo.
*/
class JRTPLIB_IMPORTEXPORT RTPUDPv4Transmitter : public RTPTransmitter
{
public:
RTPUDPv4Transmitter(RTPMemoryManager *mgr);
~RTPUDPv4Transmitter();
int Init(bool treadsafe);
int Create(size_t maxpacksize,const RTPTransmissionParams *transparams);
void Destroy();
RTPTransmissionInfo *GetTransmissionInfo();
void DeleteTransmissionInfo(RTPTransmissionInfo *inf);
int GetLocalHostName(uint8_t *buffer,size_t *bufferlength);
bool ComesFromThisTransmitter(const RTPAddress *addr);
size_t GetHeaderOverhead() { return RTPUDPV4TRANS_HEADERSIZE; }
int Poll();
int WaitForIncomingData(const RTPTime &delay,bool *dataavailable = 0);
int AbortWait();
int SendRTPData(const void *data,size_t len);
int SendRTCPData(const void *data,size_t len);
int AddDestination(const RTPAddress &addr);
int DeleteDestination(const RTPAddress &addr);
void ClearDestinations();
bool SupportsMulticasting();
int JoinMulticastGroup(const RTPAddress &addr);
int LeaveMulticastGroup(const RTPAddress &addr);
void LeaveAllMulticastGroups();
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(size_t s);
bool NewDataAvailable();
RTPRawPacket *GetNextPacket();
private:
int CreateLocalIPList();
bool GetLocalIPList_Interfaces();
void GetLocalIPList_DNS();
void AddLoopbackAddress();
void FlushPackets();
int PollSocket(bool rtp);
int ProcessAddAcceptIgnoreEntry(uint32_t ip,uint16_t port);
int ProcessDeleteAcceptIgnoreEntry(uint32_t ip,uint16_t port);
#ifdef RTP_SUPPORT_IPV4MULTICAST
bool SetMulticastTTL(uint8_t ttl);
#endif // RTP_SUPPORT_IPV4MULTICAST
bool ShouldAcceptData(uint32_t srcip,uint16_t srcport);
void ClearAcceptIgnoreInfo();
int GetAutoSockets(uint32_t bindIP, bool allowOdd, bool rtcpMux,
SocketType *pRtpSock, SocketType *pRtcpSock,
uint16_t *pRtpPort, uint16_t *pRtcpPort);
static int GetIPv4SocketPort(SocketType s, uint16_t *pPort);
bool init;
bool created;
bool waitingfordata;
SocketType rtpsock,rtcpsock;
uint32_t mcastifaceIP;
std::list<uint32_t> localIPs;
uint16_t m_rtpPort, m_rtcpPort;
uint8_t multicastTTL;
RTPTransmitter::ReceiveMode receivemode;
uint8_t *localhostname;
size_t localhostnamelength;
RTPHashTable<const RTPIPv4Destination,RTPUDPv4Trans_GetHashIndex_IPv4Dest,RTPUDPV4TRANS_HASHSIZE> destinations;
#ifdef RTP_SUPPORT_IPV4MULTICAST
RTPHashTable<const uint32_t,RTPUDPv4Trans_GetHashIndex_uint32_t,RTPUDPV4TRANS_HASHSIZE> multicastgroups;
#endif // RTP_SUPPORT_IPV4MULTICAST
std::list<RTPRawPacket*> rawpacketlist;
bool supportsmulticasting;
size_t maxpacksize;
class PortInfo
{
public:
PortInfo() { all = false; }
bool all;
std::list<uint16_t> portlist;
};
RTPKeyHashTable<const uint32_t,PortInfo*,RTPUDPv4Trans_GetHashIndex_uint32_t,RTPUDPV4TRANS_HASHSIZE> acceptignoreinfo;
bool closesocketswhendone;
RTPAbortDescriptors m_abortDesc;
RTPAbortDescriptors *m_pAbortDesc; // in case an external one was specified
#ifdef RTP_SUPPORT_THREAD
jthread::JMutex mainmutex,waitmutex;
int threadsafe;
#endif // RTP_SUPPORT_THREAD
};
} // end namespace
#endif // RTPUDPV4TRANSMITTER_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,371 @@
/*
This file is a part of JRTPLIB
Copyright (c) 1999-2017 Jori Liesenborgs
Contact: jori.liesenborgs@gmail.com
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
my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
* \file rtpudpv4transmitternobind.h
*/
#ifndef RTPUDPV4TRANSMITTERNOBIND_H
#define RTPUDPV4TRANSMITTERNOBIND_H
#include "rtpconfig.h"
#include "rtptransmitter.h"
#include "rtpipv4destination.h"
#include "rtphashtable.h"
#include "rtpkeyhashtable.h"
#include "rtpsocketutil.h"
#include "rtpabortdescriptors.h"
#include <list>
#ifdef RTP_SUPPORT_THREAD
#include <jthread/jmutex.h>
#endif // RTP_SUPPORT_THREAD
#define RTPUDPV4TRANSNOBIND_HASHSIZE 8317
#define RTPUDPV4TRANSNOBIND_DEFAULTPORTBASE 5000
#define RTPUDPV4TRANSNOBIND_RTPRECEIVEBUFFER 32768
#define RTPUDPV4TRANSNOBIND_RTCPRECEIVEBUFFER 32768
#define RTPUDPV4TRANSNOBIND_RTPTRANSMITBUFFER 32768
#define RTPUDPV4TRANSNOBIND_RTCPTRANSMITBUFFER 32768
namespace qrtplib
{
/** Parameters for the UDP over IPv4 transmitter that does not automatically bind sockets */
class JRTPLIB_IMPORTEXPORT RTPUDPv4TransmissionNoBindParams : public RTPTransmissionParams
{
public:
RTPUDPv4TransmissionNoBindParams();
/** Sets the IP address which is used to bind the sockets to \c ip. */
void SetBindIP(uint32_t ip) { bindIP = ip; }
/** Sets the multicast interface IP address. */
void SetMulticastInterfaceIP(uint32_t ip) { mcastifaceIP = ip; }
/** Sets the RTP portbase to \c pbase, which has to be an even number
* unless RTPUDPv4TransmissionParams::SetAllowOddPortbase was called;
* a port number of zero will cause a port to be chosen automatically. */
void SetPortbase(uint16_t pbase) { portbase = pbase; }
/** Sets the multicast TTL to be used to \c mcastTTL. */
void SetMulticastTTL(uint8_t mcastTTL) { multicastTTL = mcastTTL; }
/** Passes a list of IP addresses which will be used as the local IP addresses. */
void SetLocalIPList(std::list<uint32_t> &iplist) { 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() { localIPs.clear(); }
/** Returns the IP address which will be used to bind the sockets. */
uint32_t GetBindIP() const { return bindIP; }
/** Returns the multicast interface IP address. */
uint32_t GetMulticastInterfaceIP() const { return mcastifaceIP; }
/** Returns the RTP portbase which will be used (default is 5000). */
uint16_t GetPortbase() const { return portbase; }
/** Returns the multicast TTL which will be used (default is 1). */
uint8_t GetMulticastTTL() const { return multicastTTL; }
/** Returns the list of local IP addresses. */
const std::list<uint32_t> &GetLocalIPList() const { return localIPs; }
/** Sets the RTP socket's send buffer size. */
void SetRTPSendBuffer(int s) { rtpsendbuf = s; }
/** Sets the RTP socket's receive buffer size. */
void SetRTPReceiveBuffer(int s) { rtprecvbuf = s; }
/** Sets the RTCP socket's send buffer size. */
void SetRTCPSendBuffer(int s) { rtcpsendbuf = s; }
/** Sets the RTCP socket's receive buffer size. */
void SetRTCPReceiveBuffer(int s) { rtcprecvbuf = s; }
/** Enables or disables multiplexing RTCP traffic over the RTP channel, so that only a single port is used. */
void SetRTCPMultiplexing(bool f) { rtcpmux = f; }
/** Can be used to allow the RTP port base to be any number, not just even numbers. */
void SetAllowOddPortbase(bool f) { allowoddportbase = f; }
/** Force the RTCP socket to use a specific port, not necessarily one more than
* the RTP port (set this to zero to disable). */
void SetForcedRTCPPort(uint16_t rtcpport) { forcedrtcpport = rtcpport; }
/** Use sockets that have already been created, no checks on port numbers
* will be done, and no buffer sizes will be set; you'll need to close
* the sockets yourself when done, it will **not** be done automatically. */
void SetUseExistingSockets(SocketType rtpsocket, SocketType rtcpsocket) { rtpsock = rtpsocket; rtcpsock = rtcpsocket; useexistingsockets = true; }
/** If non null, the specified abort descriptors will be used to cancel
* the function that's waiting for packets to arrive; set to null (the default
* to let the transmitter create its own instance. */
void SetCreatedAbortDescriptors(RTPAbortDescriptors *desc) { m_pAbortDesc = desc; }
/** Returns the RTP socket's send buffer size. */
int GetRTPSendBuffer() const { return rtpsendbuf; }
/** Returns the RTP socket's receive buffer size. */
int GetRTPReceiveBuffer() const { return rtprecvbuf; }
/** Returns the RTCP socket's send buffer size. */
int GetRTCPSendBuffer() const { return rtcpsendbuf; }
/** Returns the RTCP socket's receive buffer size. */
int GetRTCPReceiveBuffer() const { return rtcprecvbuf; }
/** Returns a flag indicating if RTCP traffic will be multiplexed over the RTP channel. */
bool GetRTCPMultiplexing() const { return rtcpmux; }
/** If true, any RTP portbase will be allowed, not just even numbers. */
bool GetAllowOddPortbase() const { return allowoddportbase; }
/** If non-zero, the specified port will be used to receive RTCP traffic. */
uint16_t GetForcedRTCPPort() const { return forcedrtcpport; }
/** Returns true and fills in sockets if existing sockets were set
* using RTPUDPv4TransmissionParams::SetUseExistingSockets. */
bool GetUseExistingSockets(SocketType &rtpsocket, SocketType &rtcpsocket) const { if (!useexistingsockets) return false; rtpsocket = rtpsock; rtcpsocket = rtcpsock; return true; }
/** If non-null, this RTPAbortDescriptors instance will be used internally,
* which can be useful when creating your own poll thread for multiple
* sessions. */
RTPAbortDescriptors *GetCreatedAbortDescriptors() const { return m_pAbortDesc; }
private:
uint16_t portbase;
uint32_t bindIP, mcastifaceIP;
std::list<uint32_t> localIPs;
uint8_t multicastTTL;
int rtpsendbuf, rtprecvbuf;
int rtcpsendbuf, rtcprecvbuf;
bool rtcpmux;
bool allowoddportbase;
uint16_t forcedrtcpport;
SocketType rtpsock, rtcpsock;
bool useexistingsockets;
RTPAbortDescriptors *m_pAbortDesc;
};
inline RTPUDPv4TransmissionNoBindParams::RTPUDPv4TransmissionNoBindParams() : RTPTransmissionParams(RTPTransmitter::IPv4UDPProto)
{
portbase = RTPUDPV4TRANSNOBIND_DEFAULTPORTBASE;
bindIP = 0;
multicastTTL = 1;
mcastifaceIP = 0;
rtpsendbuf = RTPUDPV4TRANSNOBIND_RTPTRANSMITBUFFER;
rtprecvbuf = RTPUDPV4TRANSNOBIND_RTPRECEIVEBUFFER;
rtcpsendbuf = RTPUDPV4TRANSNOBIND_RTCPTRANSMITBUFFER;
rtcprecvbuf = RTPUDPV4TRANSNOBIND_RTCPRECEIVEBUFFER;
rtcpmux = false;
allowoddportbase = false;
forcedrtcpport = 0;
useexistingsockets = false;
rtpsock = 0;
rtcpsock = 0;
m_pAbortDesc = 0;
}
/** Additional information about the UDP over IPv4 transmitter that does not automatically bind sockets. */
class JRTPLIB_IMPORTEXPORT RTPUDPv4TransmissionNoBindInfo : public RTPTransmissionInfo
{
public:
RTPUDPv4TransmissionNoBindInfo(std::list<uint32_t> iplist,SocketType rtpsock,SocketType rtcpsock,
uint16_t rtpport, uint16_t rtcpport) : RTPTransmissionInfo(RTPTransmitter::IPv4UDPProto)
{ localIPlist = iplist; rtpsocket = rtpsock; rtcpsocket = rtcpsock; m_rtpPort = rtpport; m_rtcpPort = rtcpport; }
~RTPUDPv4TransmissionNoBindInfo() { }
/** Returns the list of IPv4 addresses the transmitter considers to be the local IP addresses. */
std::list<uint32_t> GetLocalIPList() const { return localIPlist; }
/** Returns the socket descriptor used for receiving and transmitting RTP packets. */
SocketType GetRTPSocket() const { return rtpsocket; }
/** Returns the socket descriptor used for receiving and transmitting RTCP packets. */
SocketType GetRTCPSocket() const { return rtcpsocket; }
/** Returns the port number that the RTP socket receives packets on. */
uint16_t GetRTPPort() const { return m_rtpPort; }
/** Returns the port number that the RTCP socket receives packets on. */
uint16_t GetRTCPPort() const { return m_rtcpPort; }
private:
std::list<uint32_t> localIPlist;
SocketType rtpsocket,rtcpsocket;
uint16_t m_rtpPort, m_rtcpPort;
};
class JRTPLIB_IMPORTEXPORT RTPUDPv4TransNoBind_GetHashIndex_IPv4Dest
{
public:
static int GetIndex(const RTPIPv4Destination &d) { return d.GetIP()%RTPUDPV4TRANSNOBIND_HASHSIZE; }
};
class JRTPLIB_IMPORTEXPORT RTPUDPv4TransNoBind_GetHashIndex_uint32_t
{
public:
static int GetIndex(const uint32_t &k) { return k%RTPUDPV4TRANSNOBIND_HASHSIZE; }
};
#define RTPUDPV4TRANSNOBIND_HEADERSIZE (20+8)
/** An UDP over IPv4 transmission component.
* This class inherits the RTPTransmitter interface and implements a transmission component
* which uses UDP over IPv4 to send and receive RTP and RTCP data. The component's parameters
* are described by the class RTPUDPv4TransmissionNoBindParams. The functions which have an RTPAddress
* argument require an argument of RTPIPv4Address. The GetTransmissionInfo member function
* returns an instance of type RTPUDPv4TransmissionNoBindInfo.
* This flavor of a RTPUDPv4Transmitter class does not automatically bind sockets. Use the
* BindSockets method to do so.
*/
class JRTPLIB_IMPORTEXPORT RTPUDPv4TransmitterNoBind : public RTPTransmitter
{
public:
RTPUDPv4TransmitterNoBind(RTPMemoryManager *mgr);
~RTPUDPv4TransmitterNoBind();
int Init(bool treadsafe);
int Create(size_t maxpacksize,const RTPTransmissionParams *transparams);
/** Bind the RTP and RTCP sockets to ports defined in the transmission parameters */
int BindSockets(const RTPTransmissionParams *transparams);
void Destroy();
RTPTransmissionInfo *GetTransmissionInfo();
void DeleteTransmissionInfo(RTPTransmissionInfo *inf);
int GetLocalHostName(uint8_t *buffer,size_t *bufferlength);
bool ComesFromThisTransmitter(const RTPAddress *addr);
size_t GetHeaderOverhead() { return RTPUDPV4TRANSNOBIND_HEADERSIZE; }
int Poll();
int WaitForIncomingData(const RTPTime &delay,bool *dataavailable = 0);
int AbortWait();
int SendRTPData(const void *data,size_t len);
int SendRTCPData(const void *data,size_t len);
int AddDestination(const RTPAddress &addr);
int DeleteDestination(const RTPAddress &addr);
void ClearDestinations();
bool SupportsMulticasting();
int JoinMulticastGroup(const RTPAddress &addr);
int LeaveMulticastGroup(const RTPAddress &addr);
void LeaveAllMulticastGroups();
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(size_t s);
bool NewDataAvailable();
RTPRawPacket *GetNextPacket();
private:
int CreateLocalIPList();
bool GetLocalIPList_Interfaces();
void GetLocalIPList_DNS();
void AddLoopbackAddress();
void FlushPackets();
int PollSocket(bool rtp);
int ProcessAddAcceptIgnoreEntry(uint32_t ip,uint16_t port);
int ProcessDeleteAcceptIgnoreEntry(uint32_t ip,uint16_t port);
#ifdef RTP_SUPPORT_IPV4MULTICAST
bool SetMulticastTTL(uint8_t ttl);
#endif // RTP_SUPPORT_IPV4MULTICAST
bool ShouldAcceptData(uint32_t srcip,uint16_t srcport);
void ClearAcceptIgnoreInfo();
int GetAutoSockets(uint32_t bindIP, bool allowOdd, bool rtcpMux,
SocketType *pRtpSock, SocketType *pRtcpSock,
uint16_t *pRtpPort, uint16_t *pRtcpPort);
static int GetIPv4SocketPort(SocketType s, uint16_t *pPort);
bool init;
bool created;
bool waitingfordata;
SocketType rtpsock,rtcpsock;
uint32_t mcastifaceIP;
std::list<uint32_t> localIPs;
uint16_t m_rtpPort, m_rtcpPort;
uint8_t multicastTTL;
RTPTransmitter::ReceiveMode receivemode;
uint8_t *localhostname;
size_t localhostnamelength;
RTPHashTable<const RTPIPv4Destination,RTPUDPv4TransNoBind_GetHashIndex_IPv4Dest,RTPUDPV4TRANSNOBIND_HASHSIZE> destinations;
#ifdef RTP_SUPPORT_IPV4MULTICAST
RTPHashTable<const uint32_t,RTPUDPv4TransNoBind_GetHashIndex_uint32_t,RTPUDPV4TRANSNOBIND_HASHSIZE> multicastgroups;
#endif // RTP_SUPPORT_IPV4MULTICAST
std::list<RTPRawPacket*> rawpacketlist;
bool supportsmulticasting;
size_t maxpacksize;
class PortInfo
{
public:
PortInfo() { all = false; }
bool all;
std::list<uint16_t> portlist;
};
RTPKeyHashTable<const uint32_t,PortInfo*,RTPUDPv4TransNoBind_GetHashIndex_uint32_t,RTPUDPV4TRANSNOBIND_HASHSIZE> acceptignoreinfo;
bool closesocketswhendone;
RTPAbortDescriptors m_abortDesc;
RTPAbortDescriptors *m_pAbortDesc; // in case an external one was specified
#ifdef RTP_SUPPORT_THREAD
jthread::JMutex mainmutex,waitmutex;
int threadsafe;
#endif // RTP_SUPPORT_THREAD
};
} // end namespace
#endif // RTPUDPV4TRANSMITTERNOBIND_H

Some files were not shown because too many files have changed in this diff Show More