Пример #1
0
void RTPSession::Destroy()
{
	if (!created)
		return;

#ifdef RTP_SUPPORT_THREAD
	if (pollthread)
		RTPDelete(pollthread,GetMemoryManager());
#endif // RTP_SUPPORT_THREAD
	
	if (deletetransmitter)
		RTPDelete(rtptrans,GetMemoryManager());
	packetbuilder.Destroy();
	rtcpbuilder.Destroy();
	rtcpsched.Reset();
	collisionlist.Clear();
	sources.Clear();

	std::list<RTCPCompoundPacket *>::const_iterator it;

	for (it = byepackets.begin() ; it != byepackets.end() ; it++)
		RTPDelete(*it,GetMemoryManager());
	byepackets.clear();
	
	created = false;
}
Пример #2
0
int RTPSession::Create(const RTPSessionParams &sessparams,const RTPTransmissionParams *transparams /* = 0 */,
		       RTPTransmitter::TransmissionProtocol protocol)
{
	int status;
	
	if (created)
		return ERR_RTP_SESSION_ALREADYCREATED;

	usingpollthread = sessparams.IsUsingPollThread();
	useSR_BYEifpossible = sessparams.GetSenderReportForBYE();
	sentpackets = false;
	
	// Check max packet size
	
	if ((maxpacksize = sessparams.GetMaximumPacketSize()) < RTP_MINPACKETSIZE)
		return ERR_RTP_SESSION_MAXPACKETSIZETOOSMALL;
		
	// Initialize the transmission component
	
	rtptrans = 0;
	switch(protocol)
	{
	case RTPTransmitter::IPv4UDPProto:
		rtptrans = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPTRANSMITTER) RTPUDPv4Transmitter(GetMemoryManager());
		break;
#ifdef RTP_SUPPORT_IPV6
	case RTPTransmitter::IPv6UDPProto:
		rtptrans = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPTRANSMITTER) RTPUDPv6Transmitter(GetMemoryManager());
		break;
#endif // RTP_SUPPORT_IPV6
	case RTPTransmitter::UserDefinedProto:
		rtptrans = NewUserDefinedTransmitter();
		if (rtptrans == 0)
			return ERR_RTP_SESSION_USERDEFINEDTRANSMITTERNULL;
		break;
	default:
		return ERR_RTP_SESSION_UNSUPPORTEDTRANSMISSIONPROTOCOL;
	}
	
	if (rtptrans == 0)
		return ERR_RTP_OUTOFMEM;
	if ((status = rtptrans->Init(usingpollthread)) < 0)
	{
		RTPDelete(rtptrans,GetMemoryManager());
		return status;
	}
	if ((status = rtptrans->Create(maxpacksize,transparams)) < 0)
	{
		RTPDelete(rtptrans,GetMemoryManager());
		return status;
	}

	deletetransmitter = true;
	return InternalCreate(sessparams);
}
Пример #3
0
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;
}
Пример #4
0
void RTPCollisionList::Clear()
{
	std::list<AddressAndTime>::iterator it;
	
	for (it = addresslist.begin() ; it != addresslist.end() ; it++)
		RTPDelete((*it).addr,GetMemoryManager());
	addresslist.clear();
}
Пример #5
0
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();
}
Пример #6
0
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
}
Пример #7
0
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);
}
Пример #8
0
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++;
	}
}
Пример #9
0
// The following function should delete rtppack if necessary
int RTPInternalSourceData::ProcessRTPPacket(RTPPacket *rtppack,const RTPTime &receivetime,bool *stored)
{
	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;
	
	// 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;
}
Пример #10
0
void RTPSession::BYEDestroy(const RTPTime &maxwaittime,const void *reason,size_t reasonlength)
{
	if (!created)
		return;

	// first, stop the thread so we have full control over all components
	
#ifdef RTP_SUPPORT_THREAD
	if (pollthread)
		RTPDelete(pollthread,GetMemoryManager());
#endif // RTP_SUPPORT_THREAD

	RTPTime stoptime = RTPTime::CurrentTime();
	stoptime += maxwaittime;

	// add bye packet to the list if we've sent data

	RTCPCompoundPacket *pack;

	if (sentpackets)
	{
		int status;
		
		reasonlength = (reasonlength>RTCP_BYE_MAXREASONLENGTH)?RTCP_BYE_MAXREASONLENGTH:reasonlength;
	       	status = rtcpbuilder.BuildBYEPacket(&pack,reason,reasonlength,useSR_BYEifpossible);
		if (status >= 0)
		{
			byepackets.push_back(pack);
	
			if (byepackets.size() == 1)
				rtcpsched.ScheduleBYEPacket(pack->GetCompoundPacketLength());
		}
	}
	
	if (!byepackets.empty())
	{
		bool done = false;
		
		while (!done)
		{
			RTPTime curtime = RTPTime::CurrentTime();
			
			if (curtime >= stoptime)
				done = true;
		
			if (rtcpsched.IsTime())
			{
				pack = *(byepackets.begin());
				byepackets.pop_front();
			
				rtptrans->SendRTCPData(pack->GetCompoundPacketData(),pack->GetCompoundPacketLength());
				
				OnSendRTCPCompoundPacket(pack); // we'll place this after the actual send to avoid tampering
				
				RTPDelete(pack,GetMemoryManager());
				if (!byepackets.empty()) // more bye packets to send, schedule them
					rtcpsched.ScheduleBYEPacket((*(byepackets.begin()))->GetCompoundPacketLength());
				else
					done = true;
			}
			if (!done)
				RTPTime::Wait(RTPTime(0,100000));
		}
	}
	
	if (deletetransmitter)
		RTPDelete(rtptrans,GetMemoryManager());
	packetbuilder.Destroy();
	rtcpbuilder.Destroy();
	rtcpsched.Reset();
	collisionlist.Clear();
	sources.Clear();

	// clear rest of bye packets
	std::list<RTCPCompoundPacket *>::const_iterator it;

	for (it = byepackets.begin() ; it != byepackets.end() ; it++)
		RTPDelete(*it,GetMemoryManager());
	byepackets.clear();
	
	created = false;
}
Пример #11
0
int RTPSession::InternalCreate(const RTPSessionParams &sessparams)
{
	int status;

	// Initialize packet builder
	
	if ((status = packetbuilder.Init(maxpacksize)) < 0)
	{
		if (deletetransmitter)
			RTPDelete(rtptrans,GetMemoryManager());
		return status;
	}

	if (sessparams.GetUsePredefinedSSRC())
		packetbuilder.AdjustSSRC(sessparams.GetPredefinedSSRC());

#ifdef RTP_SUPPORT_PROBATION

	// Set probation type
	sources.SetProbationType(sessparams.GetProbationType());

#endif // RTP_SUPPORT_PROBATION

	// Add our own ssrc to the source table
	
	if ((status = sources.CreateOwnSSRC(packetbuilder.GetSSRC())) < 0)
	{
		packetbuilder.Destroy();
		if (deletetransmitter)
			RTPDelete(rtptrans,GetMemoryManager());
		return status;
	}

	// Set the initial receive mode
	
	if ((status = rtptrans->SetReceiveMode(sessparams.GetReceiveMode())) < 0)
	{
		packetbuilder.Destroy();
		sources.Clear();
		if (deletetransmitter)
			RTPDelete(rtptrans,GetMemoryManager());
		return status;
	}

	// Init the RTCP packet builder
	
	double timestampunit = sessparams.GetOwnTimestampUnit();
	uint8_t buf[1024];
	size_t buflen = 1024;
	std::string forcedcname = sessparams.GetCNAME(); 

	if (forcedcname.length() == 0)
	{
		if ((status = CreateCNAME(buf,&buflen,sessparams.GetResolveLocalHostname())) < 0)
		{
			packetbuilder.Destroy();
			sources.Clear();
			if (deletetransmitter)
				RTPDelete(rtptrans,GetMemoryManager());
			return status;
		}
	}
	else
	{
		strncpy((char *)buf, forcedcname.c_str(), buflen);
		buf[buflen-1] = 0;
		buflen = strlen((char *)buf);
	}
	
	if ((status = rtcpbuilder.Init(maxpacksize,timestampunit,buf,buflen)) < 0)
	{
		packetbuilder.Destroy();
		sources.Clear();
		if (deletetransmitter)
			RTPDelete(rtptrans,GetMemoryManager());
		return status;
	}

	// Set scheduler parameters
	
	rtcpsched.Reset();
	rtcpsched.SetHeaderOverhead(rtptrans->GetHeaderOverhead());

	RTCPSchedulerParams schedparams;

	sessionbandwidth = sessparams.GetSessionBandwidth();
	controlfragment = sessparams.GetControlTrafficFraction();
	
	if ((status = schedparams.SetRTCPBandwidth(sessionbandwidth*controlfragment)) < 0)
	{
		if (deletetransmitter)
			RTPDelete(rtptrans,GetMemoryManager());
		packetbuilder.Destroy();
		sources.Clear();
		rtcpbuilder.Destroy();
		return status;
	}
	if ((status = schedparams.SetSenderBandwidthFraction(sessparams.GetSenderControlBandwidthFraction())) < 0)
	{
		if (deletetransmitter)
			RTPDelete(rtptrans,GetMemoryManager());
		packetbuilder.Destroy();
		sources.Clear();
		rtcpbuilder.Destroy();
		return status;
	}
	if ((status = schedparams.SetMinimumTransmissionInterval(sessparams.GetMinimumRTCPTransmissionInterval())) < 0)
	{
		if (deletetransmitter)
			RTPDelete(rtptrans,GetMemoryManager());
		packetbuilder.Destroy();
		sources.Clear();
		rtcpbuilder.Destroy();
		return status;
	}
	schedparams.SetUseHalfAtStartup(sessparams.GetUseHalfRTCPIntervalAtStartup());
	schedparams.SetRequestImmediateBYE(sessparams.GetRequestImmediateBYE());
	
	rtcpsched.SetParameters(schedparams);

	// copy other parameters
	
	acceptownpackets = sessparams.AcceptOwnPackets();
	membermultiplier = sessparams.GetSourceTimeoutMultiplier();
	sendermultiplier = sessparams.GetSenderTimeoutMultiplier();
	byemultiplier = sessparams.GetBYETimeoutMultiplier();
	collisionmultiplier = sessparams.GetCollisionTimeoutMultiplier();
	notemultiplier = sessparams.GetNoteTimeoutMultiplier();

	// Do thread stuff if necessary
	
#ifdef RTP_SUPPORT_THREAD
	pollthread = 0;
	if (usingpollthread)
	{
		if (!sourcesmutex.IsInitialized())	
		{
			if (sourcesmutex.Init() < 0)
			{
				if (deletetransmitter)
					RTPDelete(rtptrans,GetMemoryManager());
				packetbuilder.Destroy();
				sources.Clear();
				rtcpbuilder.Destroy();
				return ERR_RTP_SESSION_CANTINITMUTEX;
			}
		}
		if (!buildermutex.IsInitialized())
		{
			if (buildermutex.Init() < 0)
			{
				if (deletetransmitter)
					RTPDelete(rtptrans,GetMemoryManager());
				packetbuilder.Destroy();
				sources.Clear();
				rtcpbuilder.Destroy();
				return ERR_RTP_SESSION_CANTINITMUTEX;
			}
		}
		if (!schedmutex.IsInitialized())
		{
			if (schedmutex.Init() < 0)
			{
				if (deletetransmitter)
					RTPDelete(rtptrans,GetMemoryManager());
				packetbuilder.Destroy();
				sources.Clear();
				rtcpbuilder.Destroy();
				return ERR_RTP_SESSION_CANTINITMUTEX;
			}
		}
		if (!packsentmutex.IsInitialized())
		{
			if (packsentmutex.Init() < 0)
			{
				if (deletetransmitter)
					RTPDelete(rtptrans,GetMemoryManager());
				packetbuilder.Destroy();
				sources.Clear();
				rtcpbuilder.Destroy();
				return ERR_RTP_SESSION_CANTINITMUTEX;
			}
		}
		
		pollthread = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPPOLLTHREAD) RTPPollThread(*this,rtcpsched);
		if (pollthread == 0)
		{
			if (deletetransmitter)
				RTPDelete(rtptrans,GetMemoryManager());
			packetbuilder.Destroy();
			sources.Clear();
			rtcpbuilder.Destroy();
			return ERR_RTP_OUTOFMEM;
		}
		if ((status = pollthread->Start(rtptrans)) < 0)
		{
			if (deletetransmitter)
				RTPDelete(rtptrans,GetMemoryManager());
			RTPDelete(pollthread,GetMemoryManager());
			packetbuilder.Destroy();
			sources.Clear();
			rtcpbuilder.Destroy();
			return status;
		}
	}
#endif // RTP_SUPPORT_THREAD	
	
	created = true;
	return 0;
}