- format + fix invalid memory access
This commit is contained in:
parent
9d79c01be0
commit
e342abe2f5
|
|
@ -53,56 +53,56 @@ class RTCPPacket;
|
||||||
class JRTPLIB_IMPORTEXPORT RTCPCompoundPacket : public RTPMemoryObject
|
class JRTPLIB_IMPORTEXPORT RTCPCompoundPacket : public RTPMemoryObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/** Creates an RTCPCompoundPacket instance from the data in \c rawpack, installing a memory manager if specified. */
|
/** Creates an RTCPCompoundPacket instance from the data in \c rawpack, installing a memory manager if specified. */
|
||||||
RTCPCompoundPacket(RTPRawPacket &rawpack, RTPMemoryManager *memmgr = 0);
|
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.
|
||||||
* Creates an RTCPCompoundPacket instance from the data in \c packet}, with size \c len. The \c deletedata
|
* 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
|
* 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.
|
* specified, a memory manager will be installed.
|
||||||
*/
|
*/
|
||||||
RTCPCompoundPacket(uint8_t *packet, size_t len, bool deletedata = true, RTPMemoryManager *memmgr = 0);
|
RTCPCompoundPacket(uint8_t *packet, size_t len, bool deletedata = true, RTPMemoryManager *memmgr = 0);
|
||||||
protected:
|
protected:
|
||||||
RTCPCompoundPacket(RTPMemoryManager *memmgr); // this is for the compoundpacket builder
|
RTCPCompoundPacket(RTPMemoryManager *memmgr); // this is for the compoundpacket builder
|
||||||
public:
|
public:
|
||||||
virtual ~RTCPCompoundPacket();
|
virtual ~RTCPCompoundPacket();
|
||||||
|
|
||||||
/** Checks if the RTCP compound packet was created successfully.
|
/** 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
|
* 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.
|
* what went wrong. If the packet had an invalid format, the return value is \c ERR_RTP_RTCPCOMPOUND_INVALIDPACKET.
|
||||||
*/
|
*/
|
||||||
int GetCreationError() { return error; }
|
int GetCreationError() { return error; }
|
||||||
|
|
||||||
/** Returns a pointer to the data of the entire RTCP compound packet. */
|
/** Returns a pointer to the data of the entire RTCP compound packet. */
|
||||||
const uint8_t *GetCompoundPacketData() { return compoundpacket; }
|
const uint8_t *GetCompoundPacketData() { return compoundpacket; }
|
||||||
|
|
||||||
/** Returns the size of the entire RTCP compound packet. */
|
/** Returns the size of the entire RTCP compound packet. */
|
||||||
size_t GetCompoundPacketLength() { return compoundpacketlength; }
|
size_t GetCompoundPacketLength() { return compoundpacketlength; }
|
||||||
|
|
||||||
/** Starts the iteration over the individual RTCP packets in the RTCP compound packet. */
|
/** Starts the iteration over the individual RTCP packets in the RTCP compound packet. */
|
||||||
void GotoFirstPacket() { rtcppackit = rtcppacklist.begin(); }
|
void GotoFirstPacket() { rtcppackit = rtcppacklist.begin(); }
|
||||||
|
|
||||||
/** Returns a pointer to the next individual RTCP packet.
|
/** 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
|
* 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.
|
* on the RTCPPacket instance which is returned.
|
||||||
*/
|
*/
|
||||||
RTCPPacket *GetNextPacket() { if (rtcppackit == rtcppacklist.end()) return 0; RTCPPacket *p = *rtcppackit; rtcppackit++; return p; }
|
RTCPPacket *GetNextPacket() { if (rtcppackit == rtcppacklist.end()) return 0; RTCPPacket *p = *rtcppackit; rtcppackit++; return p; }
|
||||||
|
|
||||||
#ifdef RTPDEBUG
|
#ifdef RTPDEBUG
|
||||||
void Dump();
|
void Dump();
|
||||||
#endif // RTPDEBUG
|
#endif // RTPDEBUG
|
||||||
protected:
|
protected:
|
||||||
void ClearPacketList();
|
void ClearPacketList();
|
||||||
int ParseData(uint8_t *packet, size_t len);
|
int ParseData(uint8_t *packet, size_t len);
|
||||||
|
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
const uint8_t *compoundpacket;
|
const uint8_t *compoundpacket;
|
||||||
size_t compoundpacketlength;
|
size_t compoundpacketlength;
|
||||||
bool deletepacket;
|
bool deletepacket;
|
||||||
|
|
||||||
std::list<RTCPPacket *> rtcppacklist;
|
std::list<RTCPPacket *> rtcppacklist;
|
||||||
std::list<RTCPPacket *>::const_iterator rtcppackit;
|
std::list<RTCPPacket *>::const_iterator rtcppackit;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace
|
} // end namespace
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,12 @@
|
||||||
#include "rtperrors.h"
|
#include "rtperrors.h"
|
||||||
#include "rtprawpacket.h"
|
#include "rtprawpacket.h"
|
||||||
#if ! (defined(WIN32) || defined(_WIN32_WCE))
|
#if ! (defined(WIN32) || defined(_WIN32_WCE))
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
#ifdef RTPDEBUG
|
#ifdef RTPDEBUG
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#endif // RTPDEBUG
|
#endif // RTPDEBUG
|
||||||
|
|
||||||
#include "rtpdebug.h"
|
#include "rtpdebug.h"
|
||||||
|
|
@ -51,306 +51,310 @@ namespace jrtplib
|
||||||
|
|
||||||
void RTPPacket::Clear()
|
void RTPPacket::Clear()
|
||||||
{
|
{
|
||||||
hasextension = false;
|
hasextension = false;
|
||||||
hasmarker = false;
|
hasmarker = false;
|
||||||
numcsrcs = 0;
|
numcsrcs = 0;
|
||||||
payloadtype = 0;
|
payloadtype = 0;
|
||||||
extseqnr = 0;
|
extseqnr = 0;
|
||||||
timestamp = 0;
|
timestamp = 0;
|
||||||
ssrc = 0;
|
ssrc = 0;
|
||||||
packet = 0;
|
packet = 0;
|
||||||
payload = 0;
|
payload = 0;
|
||||||
packetlength = 0;
|
packetlength = 0;
|
||||||
payloadlength = 0;
|
payloadlength = 0;
|
||||||
extid = 0;
|
extid = 0;
|
||||||
extension = 0;
|
extension = 0;
|
||||||
extensionlength = 0;
|
extensionlength = 0;
|
||||||
error = 0;
|
error = 0;
|
||||||
externalbuffer = false;
|
externalbuffer = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RTPPacket::RTPPacket(RTPRawPacket &rawpack,RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(rawpack.GetReceiveTime())
|
RTPPacket::RTPPacket(RTPRawPacket &rawpack,RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(rawpack.GetReceiveTime())
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
error = ParseRawPacket(rawpack);
|
error = ParseRawPacket(rawpack);
|
||||||
}
|
}
|
||||||
|
|
||||||
RTPPacket::RTPPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr,
|
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,
|
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,
|
bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
|
||||||
size_t maxpacksize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
|
size_t maxpacksize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
error = BuildPacket(payloadtype,payloaddata,payloadlen,seqnr,timestamp,ssrc,gotmarker,numcsrcs,
|
error = BuildPacket(payloadtype,payloaddata,payloadlen,seqnr,timestamp,ssrc,gotmarker,numcsrcs,
|
||||||
csrcs,gotextension,extensionid,extensionlen_numwords,extensiondata,0,maxpacksize);
|
csrcs,gotextension,extensionid,extensionlen_numwords,extensiondata,0,maxpacksize);
|
||||||
}
|
}
|
||||||
|
|
||||||
RTPPacket::RTPPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr,
|
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,
|
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,
|
bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
|
||||||
void *buffer,size_t buffersize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
|
void *buffer,size_t buffersize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
if (buffer == 0)
|
if (buffer == 0)
|
||||||
error = ERR_RTP_PACKET_EXTERNALBUFFERNULL;
|
error = ERR_RTP_PACKET_EXTERNALBUFFERNULL;
|
||||||
else if (buffersize <= 0)
|
else if (buffersize <= 0)
|
||||||
error = ERR_RTP_PACKET_ILLEGALBUFFERSIZE;
|
error = ERR_RTP_PACKET_ILLEGALBUFFERSIZE;
|
||||||
else
|
else
|
||||||
error = BuildPacket(payloadtype,payloaddata,payloadlen,seqnr,timestamp,ssrc,gotmarker,numcsrcs,
|
error = BuildPacket(payloadtype,payloaddata,payloadlen,seqnr,timestamp,ssrc,gotmarker,numcsrcs,
|
||||||
csrcs,gotextension,extensionid,extensionlen_numwords,extensiondata,buffer,buffersize);
|
csrcs,gotextension,extensionid,extensionlen_numwords,extensiondata,buffer,buffersize);
|
||||||
}
|
}
|
||||||
|
|
||||||
RTPPacket::~RTPPacket()
|
RTPPacket::~RTPPacket()
|
||||||
{
|
{
|
||||||
if (packet && !externalbuffer)
|
if (packet && !externalbuffer)
|
||||||
{
|
{
|
||||||
RTPDeleteByteArray(packet,GetMemoryManager());
|
RTPDeleteByteArray(packet,GetMemoryManager());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int RTPPacket::ParseRawPacket(RTPRawPacket &rawpack)
|
int RTPPacket::ParseRawPacket(RTPRawPacket &rawpack)
|
||||||
{
|
{
|
||||||
uint8_t *packetbytes;
|
uint8_t *packetbytes;
|
||||||
size_t packetlen;
|
size_t packetlen;
|
||||||
uint8_t payloadtype;
|
uint8_t payloadtype;
|
||||||
RTPHeader *rtpheader;
|
RTPHeader *rtpheader;
|
||||||
bool marker;
|
bool marker;
|
||||||
int csrccount;
|
int csrccount;
|
||||||
bool hasextension;
|
bool hasextension;
|
||||||
int payloadoffset,payloadlength;
|
int payloadoffset,payloadlength;
|
||||||
int numpadbytes;
|
int numpadbytes;
|
||||||
RTPExtensionHeader *rtpextheader;
|
RTPExtensionHeader *rtpextheader;
|
||||||
uint16_t exthdrlen;
|
uint16_t exthdrlen;
|
||||||
|
|
||||||
if (!rawpack.IsRTP()) // If we didn't receive it on the RTP port, we'll ignore it
|
if (!rawpack.IsRTP()) // If we didn't receive it on the RTP port, we'll ignore it
|
||||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||||
|
|
||||||
// The length should be at least the size of the RTP header
|
// The length should be at least the size of the RTP header
|
||||||
packetlen = rawpack.GetDataLength();
|
packetlen = rawpack.GetDataLength();
|
||||||
if (packetlen < sizeof(RTPHeader))
|
if (packetlen < sizeof(RTPHeader))
|
||||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||||
|
|
||||||
packetbytes = (uint8_t *)rawpack.GetData();
|
packetbytes = (uint8_t *)rawpack.GetData();
|
||||||
rtpheader = (RTPHeader *)packetbytes;
|
rtpheader = (RTPHeader *)packetbytes;
|
||||||
|
|
||||||
// The version number should be correct
|
// The version number should be correct
|
||||||
if (rtpheader->version != RTP_VERSION)
|
if (rtpheader->version != RTP_VERSION)
|
||||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||||
|
|
||||||
// We'll check if this is possibly a RTCP packet. For this to be possible
|
// 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
|
// the marker bit and payload type combined should be either an SR or RR
|
||||||
// identifier
|
// identifier
|
||||||
marker = (rtpheader->marker == 0)?false:true;
|
marker = (rtpheader->marker == 0)?false:true;
|
||||||
payloadtype = rtpheader->payloadtype;
|
payloadtype = rtpheader->payloadtype;
|
||||||
if (marker)
|
if (marker)
|
||||||
{
|
{
|
||||||
if (payloadtype == (RTP_RTCPTYPE_SR & 127)) // don't check high bit (this was the marker!!)
|
if (payloadtype == (RTP_RTCPTYPE_SR & 127)) // don't check high bit (this was the marker!!)
|
||||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||||
if (payloadtype == (RTP_RTCPTYPE_RR & 127))
|
if (payloadtype == (RTP_RTCPTYPE_RR & 127))
|
||||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
csrccount = rtpheader->csrccount;
|
csrccount = rtpheader->csrccount;
|
||||||
payloadoffset = sizeof(RTPHeader)+(int)(csrccount*sizeof(uint32_t));
|
payloadoffset = sizeof(RTPHeader)+(int)(csrccount*sizeof(uint32_t));
|
||||||
|
if ((size_t)payloadoffset > packetlen)
|
||||||
|
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||||
|
|
||||||
if (rtpheader->padding) // adjust payload length to take padding into account
|
if (rtpheader->padding) // adjust payload length to take padding into account
|
||||||
{
|
{
|
||||||
numpadbytes = (int)packetbytes[packetlen-1]; // last byte contains number of padding bytes
|
numpadbytes = (int)packetbytes[packetlen-1]; // last byte contains number of padding bytes
|
||||||
if (numpadbytes <= 0)
|
if (numpadbytes <= 0)
|
||||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
numpadbytes = 0;
|
numpadbytes = 0;
|
||||||
|
|
||||||
hasextension = (rtpheader->extension == 0)?false:true;
|
hasextension = (rtpheader->extension == 0)?false:true;
|
||||||
if (hasextension) // got header extension
|
if (hasextension) // got header extension
|
||||||
{
|
{
|
||||||
rtpextheader = (RTPExtensionHeader *)(packetbytes+payloadoffset);
|
rtpextheader = (RTPExtensionHeader *)(packetbytes+payloadoffset);
|
||||||
payloadoffset += sizeof(RTPExtensionHeader);
|
payloadoffset += sizeof(RTPExtensionHeader);
|
||||||
exthdrlen = ntohs(rtpextheader->length);
|
if ((size_t)payloadoffset > packetlen)
|
||||||
payloadoffset += ((int)exthdrlen)*sizeof(uint32_t);
|
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||||
}
|
exthdrlen = ntohs(rtpextheader->length);
|
||||||
else
|
payloadoffset += ((int)exthdrlen)*sizeof(uint32_t);
|
||||||
{
|
}
|
||||||
rtpextheader = 0;
|
else
|
||||||
exthdrlen = 0;
|
{
|
||||||
}
|
rtpextheader = 0;
|
||||||
|
exthdrlen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
payloadlength = packetlen-numpadbytes-payloadoffset;
|
payloadlength = packetlen-numpadbytes-payloadoffset;
|
||||||
if (payloadlength < 0)
|
if (payloadlength < 0)
|
||||||
return ERR_RTP_PACKET_INVALIDPACKET;
|
return ERR_RTP_PACKET_INVALIDPACKET;
|
||||||
|
|
||||||
// Now, we've got a valid packet, so we can create a new instance of RTPPacket
|
// Now, we've got a valid packet, so we can create a new instance of RTPPacket
|
||||||
// and fill in the members
|
// and fill in the members
|
||||||
|
|
||||||
RTPPacket::hasextension = hasextension;
|
RTPPacket::hasextension = hasextension;
|
||||||
if (hasextension)
|
if (hasextension)
|
||||||
{
|
{
|
||||||
RTPPacket::extid = ntohs(rtpextheader->extid);
|
RTPPacket::extid = ntohs(rtpextheader->extid);
|
||||||
RTPPacket::extensionlength = ((int)ntohs(rtpextheader->length))*sizeof(uint32_t);
|
RTPPacket::extensionlength = ((int)ntohs(rtpextheader->length))*sizeof(uint32_t);
|
||||||
RTPPacket::extension = ((uint8_t *)rtpextheader)+sizeof(RTPExtensionHeader);
|
RTPPacket::extension = ((uint8_t *)rtpextheader)+sizeof(RTPExtensionHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
RTPPacket::hasmarker = marker;
|
RTPPacket::hasmarker = marker;
|
||||||
RTPPacket::numcsrcs = csrccount;
|
RTPPacket::numcsrcs = csrccount;
|
||||||
RTPPacket::payloadtype = payloadtype;
|
RTPPacket::payloadtype = payloadtype;
|
||||||
|
|
||||||
// Note: we don't fill in the EXTENDED sequence number here, since we
|
// 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
|
// don't have information about the source here. We just fill in the low
|
||||||
// 16 bits
|
// 16 bits
|
||||||
RTPPacket::extseqnr = (uint32_t)ntohs(rtpheader->sequencenumber);
|
RTPPacket::extseqnr = (uint32_t)ntohs(rtpheader->sequencenumber);
|
||||||
|
|
||||||
RTPPacket::timestamp = ntohl(rtpheader->timestamp);
|
RTPPacket::timestamp = ntohl(rtpheader->timestamp);
|
||||||
RTPPacket::ssrc = ntohl(rtpheader->ssrc);
|
RTPPacket::ssrc = ntohl(rtpheader->ssrc);
|
||||||
RTPPacket::packet = packetbytes;
|
RTPPacket::packet = packetbytes;
|
||||||
RTPPacket::payload = packetbytes+payloadoffset;
|
RTPPacket::payload = packetbytes+payloadoffset;
|
||||||
RTPPacket::packetlength = packetlen;
|
RTPPacket::packetlength = packetlen;
|
||||||
RTPPacket::payloadlength = payloadlength;
|
RTPPacket::payloadlength = payloadlength;
|
||||||
|
|
||||||
// We'll zero the data of the raw packet, since we're using it here now!
|
// We'll zero the data of the raw packet, since we're using it here now!
|
||||||
rawpack.ZeroData();
|
rawpack.ZeroData();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RTPPacket::GetCSRC(int num) const
|
uint32_t RTPPacket::GetCSRC(int num) const
|
||||||
{
|
{
|
||||||
if (num >= numcsrcs)
|
if (num >= numcsrcs)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint8_t *csrcpos;
|
uint8_t *csrcpos;
|
||||||
uint32_t *csrcval_nbo;
|
uint32_t *csrcval_nbo;
|
||||||
uint32_t csrcval_hbo;
|
uint32_t csrcval_hbo;
|
||||||
|
|
||||||
csrcpos = packet+sizeof(RTPHeader)+num*sizeof(uint32_t);
|
csrcpos = packet+sizeof(RTPHeader)+num*sizeof(uint32_t);
|
||||||
csrcval_nbo = (uint32_t *)csrcpos;
|
csrcval_nbo = (uint32_t *)csrcpos;
|
||||||
csrcval_hbo = ntohl(*csrcval_nbo);
|
csrcval_hbo = ntohl(*csrcval_nbo);
|
||||||
return csrcval_hbo;
|
return csrcval_hbo;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RTPPacket::BuildPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr,
|
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,
|
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,
|
bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
|
||||||
void *buffer,size_t maxsize)
|
void *buffer,size_t maxsize)
|
||||||
{
|
{
|
||||||
if (numcsrcs > RTP_MAXCSRCS)
|
if (numcsrcs > RTP_MAXCSRCS)
|
||||||
return ERR_RTP_PACKET_TOOMANYCSRCS;
|
return ERR_RTP_PACKET_TOOMANYCSRCS;
|
||||||
|
|
||||||
if (payloadtype > 127) // high bit should not be used
|
if (payloadtype > 127) // high bit should not be used
|
||||||
return ERR_RTP_PACKET_BADPAYLOADTYPE;
|
return ERR_RTP_PACKET_BADPAYLOADTYPE;
|
||||||
if (payloadtype == 72 || payloadtype == 73) // could cause confusion with rtcp types
|
if (payloadtype == 72 || payloadtype == 73) // could cause confusion with rtcp types
|
||||||
return ERR_RTP_PACKET_BADPAYLOADTYPE;
|
return ERR_RTP_PACKET_BADPAYLOADTYPE;
|
||||||
|
|
||||||
packetlength = sizeof(RTPHeader);
|
packetlength = sizeof(RTPHeader);
|
||||||
packetlength += sizeof(uint32_t)*((size_t)numcsrcs);
|
packetlength += sizeof(uint32_t)*((size_t)numcsrcs);
|
||||||
if (gotextension)
|
if (gotextension)
|
||||||
{
|
{
|
||||||
packetlength += sizeof(RTPExtensionHeader);
|
packetlength += sizeof(RTPExtensionHeader);
|
||||||
packetlength += sizeof(uint32_t)*((size_t)extensionlen_numwords);
|
packetlength += sizeof(uint32_t)*((size_t)extensionlen_numwords);
|
||||||
}
|
}
|
||||||
packetlength += payloadlen;
|
packetlength += payloadlen;
|
||||||
|
|
||||||
if (maxsize > 0 && packetlength > maxsize)
|
if (maxsize > 0 && packetlength > maxsize)
|
||||||
{
|
{
|
||||||
packetlength = 0;
|
packetlength = 0;
|
||||||
return ERR_RTP_PACKET_DATAEXCEEDSMAXSIZE;
|
return ERR_RTP_PACKET_DATAEXCEEDSMAXSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ok, now we'll just fill in...
|
// Ok, now we'll just fill in...
|
||||||
|
|
||||||
RTPHeader *rtphdr;
|
RTPHeader *rtphdr;
|
||||||
|
|
||||||
if (buffer == 0)
|
if (buffer == 0)
|
||||||
{
|
{
|
||||||
packet = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTPPACKET) uint8_t [packetlength];
|
packet = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTPPACKET) uint8_t [packetlength];
|
||||||
if (packet == 0)
|
if (packet == 0)
|
||||||
{
|
{
|
||||||
packetlength = 0;
|
packetlength = 0;
|
||||||
return ERR_RTP_OUTOFMEM;
|
return ERR_RTP_OUTOFMEM;
|
||||||
}
|
}
|
||||||
externalbuffer = false;
|
externalbuffer = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
packet = (uint8_t *)buffer;
|
packet = (uint8_t *)buffer;
|
||||||
externalbuffer = true;
|
externalbuffer = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RTPPacket::hasmarker = gotmarker;
|
RTPPacket::hasmarker = gotmarker;
|
||||||
RTPPacket::hasextension = gotextension;
|
RTPPacket::hasextension = gotextension;
|
||||||
RTPPacket::numcsrcs = numcsrcs;
|
RTPPacket::numcsrcs = numcsrcs;
|
||||||
RTPPacket::payloadtype = payloadtype;
|
RTPPacket::payloadtype = payloadtype;
|
||||||
RTPPacket::extseqnr = (uint32_t)seqnr;
|
RTPPacket::extseqnr = (uint32_t)seqnr;
|
||||||
RTPPacket::timestamp = timestamp;
|
RTPPacket::timestamp = timestamp;
|
||||||
RTPPacket::ssrc = ssrc;
|
RTPPacket::ssrc = ssrc;
|
||||||
RTPPacket::payloadlength = payloadlen;
|
RTPPacket::payloadlength = payloadlen;
|
||||||
RTPPacket::extid = extensionid;
|
RTPPacket::extid = extensionid;
|
||||||
RTPPacket::extensionlength = ((size_t)extensionlen_numwords)*sizeof(uint32_t);
|
RTPPacket::extensionlength = ((size_t)extensionlen_numwords)*sizeof(uint32_t);
|
||||||
|
|
||||||
rtphdr = (RTPHeader *)packet;
|
rtphdr = (RTPHeader *)packet;
|
||||||
rtphdr->version = RTP_VERSION;
|
rtphdr->version = RTP_VERSION;
|
||||||
rtphdr->padding = 0;
|
rtphdr->padding = 0;
|
||||||
if (gotmarker)
|
if (gotmarker)
|
||||||
rtphdr->marker = 1;
|
rtphdr->marker = 1;
|
||||||
else
|
else
|
||||||
rtphdr->marker = 0;
|
rtphdr->marker = 0;
|
||||||
if (gotextension)
|
if (gotextension)
|
||||||
rtphdr->extension = 1;
|
rtphdr->extension = 1;
|
||||||
else
|
else
|
||||||
rtphdr->extension = 0;
|
rtphdr->extension = 0;
|
||||||
rtphdr->csrccount = numcsrcs;
|
rtphdr->csrccount = numcsrcs;
|
||||||
rtphdr->payloadtype = payloadtype&127; // make sure high bit isn't set
|
rtphdr->payloadtype = payloadtype&127; // make sure high bit isn't set
|
||||||
rtphdr->sequencenumber = htons(seqnr);
|
rtphdr->sequencenumber = htons(seqnr);
|
||||||
rtphdr->timestamp = htonl(timestamp);
|
rtphdr->timestamp = htonl(timestamp);
|
||||||
rtphdr->ssrc = htonl(ssrc);
|
rtphdr->ssrc = htonl(ssrc);
|
||||||
|
|
||||||
uint32_t *curcsrc;
|
uint32_t *curcsrc;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
curcsrc = (uint32_t *)(packet+sizeof(RTPHeader));
|
curcsrc = (uint32_t *)(packet+sizeof(RTPHeader));
|
||||||
for (i = 0 ; i < numcsrcs ; i++,curcsrc++)
|
for (i = 0 ; i < numcsrcs ; i++,curcsrc++)
|
||||||
*curcsrc = htonl(csrcs[i]);
|
*curcsrc = htonl(csrcs[i]);
|
||||||
|
|
||||||
payload = packet+sizeof(RTPHeader)+((size_t)numcsrcs)*sizeof(uint32_t);
|
payload = packet+sizeof(RTPHeader)+((size_t)numcsrcs)*sizeof(uint32_t);
|
||||||
if (gotextension)
|
if (gotextension)
|
||||||
{
|
{
|
||||||
RTPExtensionHeader *rtpexthdr = (RTPExtensionHeader *)payload;
|
RTPExtensionHeader *rtpexthdr = (RTPExtensionHeader *)payload;
|
||||||
|
|
||||||
rtpexthdr->extid = htons(extensionid);
|
rtpexthdr->extid = htons(extensionid);
|
||||||
rtpexthdr->length = htons((uint16_t)extensionlen_numwords);
|
rtpexthdr->length = htons((uint16_t)extensionlen_numwords);
|
||||||
|
|
||||||
payload += sizeof(RTPExtensionHeader);
|
payload += sizeof(RTPExtensionHeader);
|
||||||
memcpy(payload,extensiondata,RTPPacket::extensionlength);
|
memcpy(payload,extensiondata,RTPPacket::extensionlength);
|
||||||
|
|
||||||
payload += RTPPacket::extensionlength;
|
payload += RTPPacket::extensionlength;
|
||||||
}
|
}
|
||||||
memcpy(payload,payloaddata,payloadlen);
|
memcpy(payload,payloaddata,payloadlen);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RTPDEBUG
|
#ifdef RTPDEBUG
|
||||||
void RTPPacket::Dump()
|
void RTPPacket::Dump()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
printf("Payload type: %d\n",(int)GetPayloadType());
|
printf("Payload type: %d\n",(int)GetPayloadType());
|
||||||
printf("Extended sequence number: 0x%08x\n",GetExtendedSequenceNumber());
|
printf("Extended sequence number: 0x%08x\n",GetExtendedSequenceNumber());
|
||||||
printf("Timestamp: 0x%08x\n",GetTimestamp());
|
printf("Timestamp: 0x%08x\n",GetTimestamp());
|
||||||
printf("SSRC: 0x%08x\n",GetSSRC());
|
printf("SSRC: 0x%08x\n",GetSSRC());
|
||||||
printf("Marker: %s\n",HasMarker()?"yes":"no");
|
printf("Marker: %s\n",HasMarker()?"yes":"no");
|
||||||
printf("CSRC count: %d\n",GetCSRCCount());
|
printf("CSRC count: %d\n",GetCSRCCount());
|
||||||
for (i = 0 ; i < GetCSRCCount() ; i++)
|
for (i = 0 ; i < GetCSRCCount() ; i++)
|
||||||
printf(" CSRC[%02d]: 0x%08x\n",i,GetCSRC(i));
|
printf(" CSRC[%02d]: 0x%08x\n",i,GetCSRC(i));
|
||||||
printf("Payload: %s\n",GetPayloadData());
|
printf("Payload: %s\n",GetPayloadData());
|
||||||
printf("Payload length: %d\n",GetPayloadLength());
|
printf("Payload length: %d\n",GetPayloadLength());
|
||||||
printf("Packet length: %d\n",GetPacketLength());
|
printf("Packet length: %d\n",GetPacketLength());
|
||||||
printf("Extension: %s\n",HasExtension()?"yes":"no");
|
printf("Extension: %s\n",HasExtension()?"yes":"no");
|
||||||
if (HasExtension())
|
if (HasExtension())
|
||||||
{
|
{
|
||||||
printf(" Extension ID: 0x%04x\n",GetExtensionID());
|
printf(" Extension ID: 0x%04x\n",GetExtensionID());
|
||||||
printf(" Extension data: %s\n",GetExtensionData());
|
printf(" Extension data: %s\n",GetExtensionData());
|
||||||
printf(" Extension length: %d\n",GetExtensionLength());
|
printf(" Extension length: %d\n",GetExtensionLength());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // RTPDEBUG
|
#endif // RTPDEBUG
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue