Пример #1
0
RTPAddress *RTPByteAddress::CreateCopy(RTPMemoryManager *mgr) const
{
	RTPByteAddress *a = RTPNew(mgr, RTPMEM_TYPE_CLASS_RTPADDRESS) RTPByteAddress(hostaddress, addresslength, port);
	return a;
}
Пример #2
0
RTPAddress *RTPIPv6Address::CreateCopy(RTPMemoryManager *mgr) const
{
	RTPIPv6Address *newaddr = RTPNew(mgr,RTPMEM_TYPE_CLASS_RTPADDRESS) RTPIPv6Address(ip,port);
	return newaddr;
}
Пример #3
0
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;
}
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;
}
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::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;
}