mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-04 05:30:32 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			1230 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1230 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 | 
						|
 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 "rtpsession.h"
 | 
						|
#include "rtcpcompoundpacketbuilder.h"
 | 
						|
#include "rtperrors.h"
 | 
						|
// TODO: this is for Create with transmitter creation. See if we keep it.
 | 
						|
//#include "rtpudpv4transmitter.h"
 | 
						|
//#include "rtptcptransmitter.h"
 | 
						|
//#include "rtpexternaltransmitter.h"
 | 
						|
#include "rtpsessionparams.h"
 | 
						|
#include "rtpdefines.h"
 | 
						|
#include "rtprawpacket.h"
 | 
						|
#include "rtppacket.h"
 | 
						|
#include "rtptimeutilities.h"
 | 
						|
#ifdef RTP_SUPPORT_SENDAPP
 | 
						|
#include "rtcpcompoundpacket.h"
 | 
						|
#endif // RTP_SUPPORT_SENDAPP
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
#include <QHostInfo>
 | 
						|
 | 
						|
 | 
						|
namespace qrtplib
 | 
						|
{
 | 
						|
 | 
						|
RTPSession::RTPSession(RTPRandom *r) :
 | 
						|
        rtprnd(GetRandomNumberGenerator(r)),
 | 
						|
        sources(*this),
 | 
						|
        packetbuilder(*rtprnd),
 | 
						|
        rtcpsched(sources, *rtprnd),
 | 
						|
        rtcpbuilder(sources, packetbuilder)
 | 
						|
{
 | 
						|
    // We're not going to set these flags in Create, so that the constructor of a derived class
 | 
						|
    // can already change them
 | 
						|
    m_changeIncomingData = false;
 | 
						|
    m_changeOutgoingData = false;
 | 
						|
 | 
						|
    created = false;
 | 
						|
    timeinit.Dummy();
 | 
						|
 | 
						|
    //std::cout << (void *)(rtprnd) << std::endl;
 | 
						|
}
 | 
						|
 | 
						|
RTPSession::~RTPSession()
 | 
						|
{
 | 
						|
    Destroy();
 | 
						|
 | 
						|
    if (deletertprnd)
 | 
						|
        delete rtprnd;
 | 
						|
}
 | 
						|
 | 
						|
//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)
 | 
						|
//    {
 | 
						|
    // TODO: see if we keep this Create method or use the one with the transmitter specified
 | 
						|
//    case RTPTransmitter::IPv4UDPProto:
 | 
						|
//        rtptrans = new RTPUDPv4Transmitter();
 | 
						|
//        break;
 | 
						|
//    case RTPTransmitter::ExternalProto:
 | 
						|
//        rtptrans = new RTPExternalTransmitter();
 | 
						|
//        break;
 | 
						|
//    case RTPTransmitter::UserDefinedProto:
 | 
						|
//        rtptrans = NewUserDefinedTransmitter();
 | 
						|
//        if (rtptrans == 0)
 | 
						|
//            return ERR_RTP_SESSION_USERDEFINEDTRANSMITTERNULL;
 | 
						|
//        break;
 | 
						|
//    case RTPTransmitter::TCPProto:
 | 
						|
//        rtptrans = new RTPTCPTransmitter();
 | 
						|
//        break;
 | 
						|
 | 
						|
//      default:
 | 
						|
//        return ERR_RTP_SESSION_UNSUPPORTEDTRANSMISSIONPROTOCOL;
 | 
						|
//    }
 | 
						|
//
 | 
						|
//    if (rtptrans == 0)
 | 
						|
//        return ERR_RTP_OUTOFMEM;
 | 
						|
//    if ((status = rtptrans->Init()) < 0)
 | 
						|
//    {
 | 
						|
//        delete rtptrans;
 | 
						|
//        return status;
 | 
						|
//    }
 | 
						|
//    if ((status = rtptrans->Create(maxpacksize, transparams)) < 0)
 | 
						|
//    {
 | 
						|
//        delete rtptrans;
 | 
						|
//        return status;
 | 
						|
//    }
 | 
						|
//
 | 
						|
//    deletetransmitter = true;
 | 
						|
//    return InternalCreate(sessparams);
 | 
						|
//}
 | 
						|
 | 
						|
int RTPSession::Create(const RTPSessionParams &sessparams, RTPTransmitter *transmitter)
 | 
						|
{
 | 
						|
    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;
 | 
						|
 | 
						|
    rtptrans = transmitter;
 | 
						|
 | 
						|
    if ((status = rtptrans->SetMaximumPacketSize(maxpacksize)) < 0)
 | 
						|
        return status;
 | 
						|
 | 
						|
    deletetransmitter = false;
 | 
						|
    return InternalCreate(sessparams);
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::InternalCreate(const RTPSessionParams &sessparams)
 | 
						|
{
 | 
						|
    int status;
 | 
						|
 | 
						|
    // Initialize packet builder
 | 
						|
 | 
						|
    if ((status = packetbuilder.Init(maxpacksize)) < 0)
 | 
						|
    {
 | 
						|
        if (deletetransmitter)
 | 
						|
            delete rtptrans;
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
 | 
						|
    if (sessparams.GetUsePredefinedSSRC())
 | 
						|
        packetbuilder.AdjustSSRC(sessparams.GetPredefinedSSRC());
 | 
						|
 | 
						|
    // Add our own ssrc to the source table
 | 
						|
 | 
						|
    if ((status = sources.CreateOwnSSRC(packetbuilder.GetSSRC())) < 0)
 | 
						|
    {
 | 
						|
        packetbuilder.Destroy();
 | 
						|
        if (deletetransmitter)
 | 
						|
            delete rtptrans;
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
 | 
						|
    // Set the initial receive mode
 | 
						|
 | 
						|
    if ((status = rtptrans->SetReceiveMode(sessparams.GetReceiveMode())) < 0)
 | 
						|
    {
 | 
						|
        packetbuilder.Destroy();
 | 
						|
        sources.Clear();
 | 
						|
        if (deletetransmitter)
 | 
						|
            delete rtptrans;
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
 | 
						|
    // Init the RTCP packet builder
 | 
						|
 | 
						|
    double timestampunit = sessparams.GetOwnTimestampUnit();
 | 
						|
    uint8_t buf[1024] = {0};
 | 
						|
    std::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)
 | 
						|
                delete rtptrans;
 | 
						|
            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)
 | 
						|
            delete rtptrans;
 | 
						|
        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)
 | 
						|
            delete rtptrans;
 | 
						|
        packetbuilder.Destroy();
 | 
						|
        sources.Clear();
 | 
						|
        rtcpbuilder.Destroy();
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
    if ((status = schedparams.SetSenderBandwidthFraction(sessparams.GetSenderControlBandwidthFraction())) < 0)
 | 
						|
    {
 | 
						|
        if (deletetransmitter)
 | 
						|
            delete rtptrans;
 | 
						|
        packetbuilder.Destroy();
 | 
						|
        sources.Clear();
 | 
						|
        rtcpbuilder.Destroy();
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
    if ((status = schedparams.SetMinimumTransmissionInterval(sessparams.GetMinimumRTCPTransmissionInterval())) < 0)
 | 
						|
    {
 | 
						|
        if (deletetransmitter)
 | 
						|
            delete rtptrans;
 | 
						|
        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
 | 
						|
 | 
						|
    created = true;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
void RTPSession::Destroy()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return;
 | 
						|
 | 
						|
    if (deletetransmitter)
 | 
						|
        delete rtptrans;
 | 
						|
    packetbuilder.Destroy();
 | 
						|
    rtcpbuilder.Destroy();
 | 
						|
    rtcpsched.Reset();
 | 
						|
    collisionlist.Clear();
 | 
						|
    sources.Clear();
 | 
						|
 | 
						|
    std::list<RTCPCompoundPacket *>::const_iterator it;
 | 
						|
 | 
						|
    for (it = byepackets.begin(); it != byepackets.end(); it++)
 | 
						|
        delete *it;
 | 
						|
    byepackets.clear();
 | 
						|
 | 
						|
    created = false;
 | 
						|
}
 | 
						|
 | 
						|
void RTPSession::BYEDestroy(const RTPTime &maxwaittime, const void *reason, std::size_t reasonlength)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return;
 | 
						|
 | 
						|
    // first, stop the thread so we have full control over all components
 | 
						|
 | 
						|
    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();
 | 
						|
 | 
						|
                SendRTCPData(pack->GetCompoundPacketData(), pack->GetCompoundPacketLength());
 | 
						|
 | 
						|
                OnSendRTCPCompoundPacket(pack); // we'll place this after the actual send to avoid tampering
 | 
						|
 | 
						|
                delete pack;
 | 
						|
                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)
 | 
						|
        delete rtptrans;
 | 
						|
    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++)
 | 
						|
        delete *it;
 | 
						|
    byepackets.clear();
 | 
						|
 | 
						|
    created = false;
 | 
						|
}
 | 
						|
 | 
						|
bool RTPSession::IsActive()
 | 
						|
{
 | 
						|
    return created;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t RTPSession::GetLocalSSRC()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    uint32_t ssrc;
 | 
						|
 | 
						|
    ssrc = packetbuilder.GetSSRC();
 | 
						|
    return ssrc;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::AddDestination(const RTPAddress &addr)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
    return rtptrans->AddDestination(addr);
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::DeleteDestination(const RTPAddress &addr)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
    return rtptrans->DeleteDestination(addr);
 | 
						|
}
 | 
						|
 | 
						|
void RTPSession::ClearDestinations()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return;
 | 
						|
    rtptrans->ClearDestinations();
 | 
						|
}
 | 
						|
 | 
						|
bool RTPSession::SupportsMulticasting()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return false;
 | 
						|
    return rtptrans->SupportsMulticasting();
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::JoinMulticastGroup(const RTPAddress &addr)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
    return rtptrans->JoinMulticastGroup(addr);
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::LeaveMulticastGroup(const RTPAddress &addr)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
    return rtptrans->LeaveMulticastGroup(addr);
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SendPacket(const void *data, std::size_t len)
 | 
						|
{
 | 
						|
    int status;
 | 
						|
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    if ((status = packetbuilder.BuildPacket(data, len)) < 0)
 | 
						|
    {
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
    if ((status = SendRTPData(packetbuilder.GetPacket(), packetbuilder.GetPacketLength())) < 0)
 | 
						|
    {
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
 | 
						|
    sources.SentRTPPacket();
 | 
						|
    sentpackets = true;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SendPacket(const void *data, std::size_t len, uint8_t pt, bool mark, uint32_t timestampinc)
 | 
						|
{
 | 
						|
    int status;
 | 
						|
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    if ((status = packetbuilder.BuildPacket(data, len, pt, mark, timestampinc)) < 0)
 | 
						|
    {
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
    if ((status = SendRTPData(packetbuilder.GetPacket(), packetbuilder.GetPacketLength())) < 0)
 | 
						|
    {
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
 | 
						|
    sources.SentRTPPacket();
 | 
						|
    sentpackets = true;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SendPacketEx(const void *data, std::size_t len, uint16_t hdrextID, const void *hdrextdata, std::size_t numhdrextwords)
 | 
						|
{
 | 
						|
    int status;
 | 
						|
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    if ((status = packetbuilder.BuildPacketEx(data, len, hdrextID, hdrextdata, numhdrextwords)) < 0)
 | 
						|
    {
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
    if ((status = SendRTPData(packetbuilder.GetPacket(), packetbuilder.GetPacketLength())) < 0)
 | 
						|
    {
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
 | 
						|
    sources.SentRTPPacket();
 | 
						|
    sentpackets = true;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SendPacketEx(const void *data, std::size_t len, uint8_t pt, bool mark, uint32_t timestampinc, uint16_t hdrextID, const void *hdrextdata, std::size_t numhdrextwords)
 | 
						|
{
 | 
						|
    int status;
 | 
						|
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    if ((status = packetbuilder.BuildPacketEx(data, len, pt, mark, timestampinc, hdrextID, hdrextdata, numhdrextwords)) < 0)
 | 
						|
    {
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
    if ((status = SendRTPData(packetbuilder.GetPacket(), packetbuilder.GetPacketLength())) < 0)
 | 
						|
    {
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
 | 
						|
    sources.SentRTPPacket();
 | 
						|
    sentpackets = true;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef RTP_SUPPORT_SENDAPP
 | 
						|
 | 
						|
int RTPSession::SendRTCPAPPPacket(uint8_t subtype, const uint8_t name[4], const void *appdata, std::size_t appdatalen)
 | 
						|
{
 | 
						|
    int status;
 | 
						|
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    uint32_t ssrc = packetbuilder.GetSSRC();
 | 
						|
 | 
						|
    RTCPCompoundPacketBuilder pb;
 | 
						|
 | 
						|
    status = pb.InitBuild(maxpacksize);
 | 
						|
 | 
						|
    if (status < 0)
 | 
						|
        return status;
 | 
						|
 | 
						|
    //first packet in an rtcp compound packet should always be SR or RR
 | 
						|
    if ((status = pb.StartReceiverReport(ssrc)) < 0)
 | 
						|
        return status;
 | 
						|
 | 
						|
    //add SDES packet with CNAME item
 | 
						|
    if ((status = pb.AddSDESSource(ssrc)) < 0)
 | 
						|
        return status;
 | 
						|
 | 
						|
    std::size_t owncnamelen = 0;
 | 
						|
    uint8_t *owncname = rtcpbuilder.GetLocalCNAME(&owncnamelen);
 | 
						|
 | 
						|
    if ((status = pb.AddSDESNormalItem(RTCPSDESPacket::CNAME, owncname, owncnamelen)) < 0)
 | 
						|
    {
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
 | 
						|
    //add our application specific packet
 | 
						|
    if ((status = pb.AddAPPPacket(subtype, ssrc, name, appdata, appdatalen)) < 0)
 | 
						|
        return status;
 | 
						|
 | 
						|
    if ((status = pb.EndBuild()) < 0)
 | 
						|
        return status;
 | 
						|
 | 
						|
    //send packet
 | 
						|
    status = SendRTCPData(pb.GetCompoundPacketData(), pb.GetCompoundPacketLength());
 | 
						|
    if (status < 0)
 | 
						|
        return status;
 | 
						|
 | 
						|
    sentpackets = true;
 | 
						|
 | 
						|
    return pb.GetCompoundPacketLength();
 | 
						|
}
 | 
						|
 | 
						|
#endif // RTP_SUPPORT_SENDAPP
 | 
						|
 | 
						|
int RTPSession::SendRawData(const void *data, std::size_t len, bool usertpchannel)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    int status;
 | 
						|
 | 
						|
    if (usertpchannel)
 | 
						|
        status = rtptrans->SendRTPData(data, len);
 | 
						|
    else
 | 
						|
        status = rtptrans->SendRTCPData(data, len);
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SetDefaultPayloadType(uint8_t pt)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    int status;
 | 
						|
 | 
						|
    status = packetbuilder.SetDefaultPayloadType(pt);
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SetDefaultMark(bool m)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    int status;
 | 
						|
 | 
						|
    status = packetbuilder.SetDefaultMark(m);
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SetDefaultTimestampIncrement(uint32_t timestampinc)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    int status;
 | 
						|
 | 
						|
    status = packetbuilder.SetDefaultTimestampIncrement(timestampinc);
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::IncrementTimestamp(uint32_t inc)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    int status;
 | 
						|
 | 
						|
    status = packetbuilder.IncrementTimestamp(inc);
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::IncrementTimestampDefault()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    int status;
 | 
						|
 | 
						|
    status = packetbuilder.IncrementTimestampDefault();
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SetPreTransmissionDelay(const RTPTime &delay)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    int status;
 | 
						|
 | 
						|
    status = rtcpbuilder.SetPreTransmissionDelay(delay);
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
RTPTransmissionInfo *RTPSession::GetTransmissionInfo()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return 0;
 | 
						|
    return rtptrans->GetTransmissionInfo();
 | 
						|
}
 | 
						|
 | 
						|
void RTPSession::DeleteTransmissionInfo(RTPTransmissionInfo *inf)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return;
 | 
						|
    rtptrans->DeleteTransmissionInfo(inf);
 | 
						|
}
 | 
						|
 | 
						|
RTPTime RTPSession::GetRTCPDelay()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return RTPTime(0, 0);
 | 
						|
    if (usingpollthread)
 | 
						|
        return RTPTime(0, 0);
 | 
						|
 | 
						|
    RTPTime t = rtcpsched.GetTransmissionDelay();
 | 
						|
    return t;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::BeginDataAccess()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
bool RTPSession::GotoFirstSource()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return false;
 | 
						|
    return sources.GotoFirstSource();
 | 
						|
}
 | 
						|
 | 
						|
bool RTPSession::GotoNextSource()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return false;
 | 
						|
    return sources.GotoNextSource();
 | 
						|
}
 | 
						|
 | 
						|
bool RTPSession::GotoPreviousSource()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return false;
 | 
						|
    return sources.GotoPreviousSource();
 | 
						|
}
 | 
						|
 | 
						|
bool RTPSession::GotoFirstSourceWithData()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return false;
 | 
						|
    return sources.GotoFirstSourceWithData();
 | 
						|
}
 | 
						|
 | 
						|
bool RTPSession::GotoNextSourceWithData()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return false;
 | 
						|
    return sources.GotoNextSourceWithData();
 | 
						|
}
 | 
						|
 | 
						|
bool RTPSession::GotoPreviousSourceWithData()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return false;
 | 
						|
    return sources.GotoPreviousSourceWithData();
 | 
						|
}
 | 
						|
 | 
						|
RTPSourceData *RTPSession::GetCurrentSourceInfo()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return 0;
 | 
						|
    return sources.GetCurrentSourceInfo();
 | 
						|
}
 | 
						|
 | 
						|
RTPSourceData *RTPSession::GetSourceInfo(uint32_t ssrc)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return 0;
 | 
						|
    return sources.GetSourceInfo(ssrc);
 | 
						|
}
 | 
						|
 | 
						|
RTPPacket *RTPSession::GetNextPacket()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return 0;
 | 
						|
    return sources.GetNextPacket();
 | 
						|
}
 | 
						|
 | 
						|
uint16_t RTPSession::GetNextSequenceNumber() const
 | 
						|
{
 | 
						|
    return packetbuilder.GetSequenceNumber();
 | 
						|
}
 | 
						|
 | 
						|
void RTPSession::DeletePacket(RTPPacket *p)
 | 
						|
{
 | 
						|
    delete p;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::EndDataAccess()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SetReceiveMode(RTPTransmitter::ReceiveMode m)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
    return rtptrans->SetReceiveMode(m);
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::AddToIgnoreList(const RTPAddress &addr)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
    return rtptrans->AddToIgnoreList(addr);
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::DeleteFromIgnoreList(const RTPAddress &addr)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
    return rtptrans->DeleteFromIgnoreList(addr);
 | 
						|
}
 | 
						|
 | 
						|
void RTPSession::ClearIgnoreList()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return;
 | 
						|
    rtptrans->ClearIgnoreList();
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::AddToAcceptList(const RTPAddress &addr)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
    return rtptrans->AddToAcceptList(addr);
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::DeleteFromAcceptList(const RTPAddress &addr)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
    return rtptrans->DeleteFromAcceptList(addr);
 | 
						|
}
 | 
						|
 | 
						|
void RTPSession::ClearAcceptList()
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return;
 | 
						|
    rtptrans->ClearAcceptList();
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SetMaximumPacketSize(std::size_t s)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    if (s < RTP_MINPACKETSIZE)
 | 
						|
        return ERR_RTP_SESSION_MAXPACKETSIZETOOSMALL;
 | 
						|
 | 
						|
    int status;
 | 
						|
 | 
						|
    if ((status = rtptrans->SetMaximumPacketSize(s)) < 0)
 | 
						|
        return status;
 | 
						|
 | 
						|
    if ((status = packetbuilder.SetMaximumPacketSize(s)) < 0)
 | 
						|
    {
 | 
						|
        // restore previous max packet size
 | 
						|
        rtptrans->SetMaximumPacketSize(maxpacksize);
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
    if ((status = rtcpbuilder.SetMaximumPacketSize(s)) < 0)
 | 
						|
    {
 | 
						|
        // restore previous max packet size
 | 
						|
        packetbuilder.SetMaximumPacketSize(maxpacksize);
 | 
						|
        rtptrans->SetMaximumPacketSize(maxpacksize);
 | 
						|
        return status;
 | 
						|
    }
 | 
						|
    maxpacksize = s;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SetSessionBandwidth(double bw)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    int status;
 | 
						|
    RTCPSchedulerParams p = rtcpsched.GetParameters();
 | 
						|
    status = p.SetRTCPBandwidth(bw * controlfragment);
 | 
						|
    if (status >= 0)
 | 
						|
    {
 | 
						|
        rtcpsched.SetParameters(p);
 | 
						|
        sessionbandwidth = bw;
 | 
						|
    }
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SetTimestampUnit(double u)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    int status;
 | 
						|
 | 
						|
    status = rtcpbuilder.SetTimestampUnit(u);
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
void RTPSession::SetNameInterval(int count)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return;
 | 
						|
    rtcpbuilder.SetNameInterval(count);
 | 
						|
}
 | 
						|
 | 
						|
void RTPSession::SetEMailInterval(int count)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return;
 | 
						|
    rtcpbuilder.SetEMailInterval(count);
 | 
						|
}
 | 
						|
 | 
						|
void RTPSession::SetLocationInterval(int count)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return;
 | 
						|
    rtcpbuilder.SetLocationInterval(count);
 | 
						|
}
 | 
						|
 | 
						|
void RTPSession::SetPhoneInterval(int count)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return;
 | 
						|
    rtcpbuilder.SetPhoneInterval(count);
 | 
						|
}
 | 
						|
 | 
						|
void RTPSession::SetToolInterval(int count)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return;
 | 
						|
    rtcpbuilder.SetToolInterval(count);
 | 
						|
}
 | 
						|
 | 
						|
void RTPSession::SetNoteInterval(int count)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return;
 | 
						|
    rtcpbuilder.SetNoteInterval(count);
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SetLocalName(const void *s, std::size_t len)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    int status;
 | 
						|
    status = rtcpbuilder.SetLocalName(s, len);
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SetLocalEMail(const void *s, std::size_t len)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    int status;
 | 
						|
    status = rtcpbuilder.SetLocalEMail(s, len);
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SetLocalLocation(const void *s, std::size_t len)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    int status;
 | 
						|
    status = rtcpbuilder.SetLocalLocation(s, len);
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SetLocalPhone(const void *s, std::size_t len)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    int status;
 | 
						|
    status = rtcpbuilder.SetLocalPhone(s, len);
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SetLocalTool(const void *s, std::size_t len)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    int status;
 | 
						|
    status = rtcpbuilder.SetLocalTool(s, len);
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SetLocalNote(const void *s, std::size_t len)
 | 
						|
{
 | 
						|
    if (!created)
 | 
						|
        return ERR_RTP_SESSION_NOTCREATED;
 | 
						|
 | 
						|
    int status;
 | 
						|
    status = rtcpbuilder.SetLocalNote(s, len);
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::ProcessPolledData()
 | 
						|
{
 | 
						|
    RTPRawPacket *rawpack;
 | 
						|
    int status;
 | 
						|
 | 
						|
    while ((rawpack = rtptrans->GetNextPacket()) != 0)
 | 
						|
    {
 | 
						|
        if (m_changeIncomingData)
 | 
						|
        {
 | 
						|
            // Provide a way to change incoming data, for decryption for example
 | 
						|
            if (!OnChangeIncomingData(rawpack))
 | 
						|
            {
 | 
						|
                delete rawpack;
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        sources.ClearOwnCollisionFlag();
 | 
						|
 | 
						|
        // since our sources instance also uses the scheduler (analysis of incoming packets)
 | 
						|
        // we'll lock it
 | 
						|
        if ((status = sources.ProcessRawPacket(rawpack, rtptrans, acceptownpackets)) < 0)
 | 
						|
        {
 | 
						|
            delete rawpack;
 | 
						|
            return status;
 | 
						|
        }
 | 
						|
 | 
						|
        if (sources.DetectedOwnCollision()) // collision handling!
 | 
						|
        {
 | 
						|
            bool created;
 | 
						|
 | 
						|
            if ((status = collisionlist.UpdateAddress(&rawpack->GetSenderAddress(), rawpack->GetReceiveTime(), &created)) < 0)
 | 
						|
            {
 | 
						|
                delete rawpack;
 | 
						|
                return status;
 | 
						|
            }
 | 
						|
 | 
						|
            if (created) // first time we've encountered this address, send bye packet and
 | 
						|
            {            // change our own SSRC
 | 
						|
                bool hassentpackets = sentpackets;
 | 
						|
 | 
						|
                if (hassentpackets)
 | 
						|
                {
 | 
						|
                    // Only send BYE packet if we've actually sent data using this
 | 
						|
                    // SSRC
 | 
						|
 | 
						|
                    RTCPCompoundPacket *rtcpcomppack;
 | 
						|
 | 
						|
                    if ((status = rtcpbuilder.BuildBYEPacket(&rtcpcomppack, 0, 0, useSR_BYEifpossible)) < 0)
 | 
						|
                    {
 | 
						|
                        delete rawpack;
 | 
						|
                        return status;
 | 
						|
                    }
 | 
						|
 | 
						|
                    byepackets.push_back(rtcpcomppack);
 | 
						|
                    if (byepackets.size() == 1) // was the first packet, schedule a BYE packet (otherwise there's already one scheduled)
 | 
						|
                    {
 | 
						|
                        rtcpsched.ScheduleBYEPacket(rtcpcomppack->GetCompoundPacketLength());
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                // bye packet is built and scheduled, now change our SSRC
 | 
						|
                // and reset the packet count in the transmitter
 | 
						|
 | 
						|
                uint32_t newssrc = packetbuilder.CreateNewSSRC(sources);
 | 
						|
 | 
						|
                sentpackets = false;
 | 
						|
 | 
						|
                // remove old entry in source table and add new one
 | 
						|
 | 
						|
                if ((status = sources.DeleteOwnSSRC()) < 0)
 | 
						|
                {
 | 
						|
                    delete rawpack;
 | 
						|
                    return status;
 | 
						|
                }
 | 
						|
                if ((status = sources.CreateOwnSSRC(newssrc)) < 0)
 | 
						|
                {
 | 
						|
                    delete rawpack;
 | 
						|
                    return status;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        delete rawpack;
 | 
						|
    }
 | 
						|
 | 
						|
    RTPTime d = rtcpsched.CalculateDeterministicInterval(false);
 | 
						|
 | 
						|
    RTPTime t = RTPTime::CurrentTime();
 | 
						|
    double Td = d.GetDouble();
 | 
						|
    RTPTime sendertimeout = RTPTime(Td * sendermultiplier);
 | 
						|
    RTPTime generaltimeout = RTPTime(Td * membermultiplier);
 | 
						|
    RTPTime byetimeout = RTPTime(Td * byemultiplier);
 | 
						|
    RTPTime colltimeout = RTPTime(Td * collisionmultiplier);
 | 
						|
    RTPTime notetimeout = RTPTime(Td * notemultiplier);
 | 
						|
 | 
						|
    sources.MultipleTimeouts(t, sendertimeout, byetimeout, generaltimeout, notetimeout);
 | 
						|
    collisionlist.Timeout(t, colltimeout);
 | 
						|
 | 
						|
    // We'll check if it's time for RTCP stuff
 | 
						|
 | 
						|
    bool istime = rtcpsched.IsTime();
 | 
						|
 | 
						|
    if (istime)
 | 
						|
    {
 | 
						|
        RTCPCompoundPacket *pack;
 | 
						|
 | 
						|
        // we'll check if there's a bye packet to send, or just a normal packet
 | 
						|
 | 
						|
        if (byepackets.empty())
 | 
						|
        {
 | 
						|
            if ((status = rtcpbuilder.BuildNextPacket(&pack)) < 0)
 | 
						|
            {
 | 
						|
                return status;
 | 
						|
            }
 | 
						|
            if ((status = SendRTCPData(pack->GetCompoundPacketData(), pack->GetCompoundPacketLength())) < 0)
 | 
						|
            {
 | 
						|
                delete pack;
 | 
						|
                return status;
 | 
						|
            }
 | 
						|
 | 
						|
            sentpackets = true;
 | 
						|
 | 
						|
            OnSendRTCPCompoundPacket(pack); // we'll place this after the actual send to avoid tampering
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            pack = *(byepackets.begin());
 | 
						|
            byepackets.pop_front();
 | 
						|
 | 
						|
            if ((status = SendRTCPData(pack->GetCompoundPacketData(), pack->GetCompoundPacketLength())) < 0)
 | 
						|
            {
 | 
						|
                delete pack;
 | 
						|
                return status;
 | 
						|
            }
 | 
						|
 | 
						|
            sentpackets = true;
 | 
						|
 | 
						|
            OnSendRTCPCompoundPacket(pack); // we'll place this after the actual send to avoid tampering
 | 
						|
 | 
						|
            if (!byepackets.empty()) // more bye packets to send, schedule them
 | 
						|
            {
 | 
						|
                rtcpsched.ScheduleBYEPacket((*(byepackets.begin()))->GetCompoundPacketLength());
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        rtcpsched.AnalyseOutgoing(*pack);
 | 
						|
 | 
						|
        delete pack;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::CreateCNAME(uint8_t *buffer, std::size_t *bufferlength, bool resolve)
 | 
						|
{
 | 
						|
    (void) resolve;
 | 
						|
    buffer[*bufferlength - 1] = 0;
 | 
						|
 | 
						|
    std::size_t offset = strlen((const char *) buffer);
 | 
						|
    if (offset < (*bufferlength - 1))
 | 
						|
        buffer[offset] = (uint8_t) '@';
 | 
						|
    offset++;
 | 
						|
 | 
						|
    std::size_t buflen2 = *bufferlength - offset;
 | 
						|
 | 
						|
    QString hostnameStr = QHostInfo::localHostName();
 | 
						|
    int hostnameSize = hostnameStr.size();
 | 
						|
 | 
						|
    strncpy((char * )(buffer + offset), hostnameStr.toStdString().c_str(), buflen2);
 | 
						|
    *bufferlength = offset + hostnameSize;
 | 
						|
 | 
						|
    if (*bufferlength > RTCP_SDES_MAXITEMLENGTH)
 | 
						|
        *bufferlength = RTCP_SDES_MAXITEMLENGTH;
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
RTPRandom *RTPSession::GetRandomNumberGenerator(RTPRandom *r)
 | 
						|
{
 | 
						|
    RTPRandom *rnew = 0;
 | 
						|
 | 
						|
    if (r == 0)
 | 
						|
    {
 | 
						|
        rnew = RTPRandom::CreateDefaultRandomNumberGenerator();
 | 
						|
        deletertprnd = true;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        rnew = r;
 | 
						|
        deletertprnd = false;
 | 
						|
    }
 | 
						|
 | 
						|
    return rnew;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SendRTPData(const void *data, std::size_t len)
 | 
						|
{
 | 
						|
    if (!m_changeOutgoingData)
 | 
						|
        return rtptrans->SendRTPData(data, len);
 | 
						|
 | 
						|
    void *pSendData = 0;
 | 
						|
    std::size_t sendLen = 0;
 | 
						|
    int status = 0;
 | 
						|
 | 
						|
    status = OnChangeRTPOrRTCPData(data, len, true, &pSendData, &sendLen);
 | 
						|
    if (status < 0)
 | 
						|
        return status;
 | 
						|
 | 
						|
    if (pSendData)
 | 
						|
    {
 | 
						|
        status = rtptrans->SendRTPData(pSendData, sendLen);
 | 
						|
        OnSentRTPOrRTCPData(pSendData, sendLen, true);
 | 
						|
    }
 | 
						|
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
int RTPSession::SendRTCPData(const void *data, std::size_t len)
 | 
						|
{
 | 
						|
    if (!m_changeOutgoingData)
 | 
						|
        return rtptrans->SendRTCPData(data, len);
 | 
						|
 | 
						|
    void *pSendData = 0;
 | 
						|
    std::size_t sendLen = 0;
 | 
						|
    int status = 0;
 | 
						|
 | 
						|
    status = OnChangeRTPOrRTCPData(data, len, false, &pSendData, &sendLen);
 | 
						|
    if (status < 0)
 | 
						|
        return status;
 | 
						|
 | 
						|
    if (pSendData)
 | 
						|
    {
 | 
						|
        status = rtptrans->SendRTCPData(pSendData, sendLen);
 | 
						|
        OnSentRTPOrRTCPData(pSendData, sendLen, false);
 | 
						|
    }
 | 
						|
 | 
						|
    return status;
 | 
						|
}
 | 
						|
 | 
						|
} // end namespace
 | 
						|
 |