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; }
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); }
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 RTPCollisionList::Clear() { std::list<AddressAndTime>::iterator it; for (it = addresslist.begin() ; it != addresslist.end() ; it++) RTPDelete((*it).addr,GetMemoryManager()); addresslist.clear(); }
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(); }
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 }
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); }
void RTPCollisionList::Timeout(const RTPTime ¤ttime,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++; } }
// 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; }
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; }
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; }