Public Member Functions | Protected Member Functions | Protected Attributes

RTCP Class Reference

#include <RTCP.h>

List of all members.

Public Member Functions

 RTCP ()

Protected Member Functions

virtual void initialize ()
virtual ~RTCP ()
virtual void handleMessage (cMessage *msg)
virtual void handleMessageFromRTP (cMessage *msg)
virtual void handleMessageFromUDP (cMessage *msg)
virtual void handleSelfMessage (cMessage *msg)
virtual void initializeRTCP (RTPInnerPacket *rinp)
virtual void senderModuleInitialized (RTPInnerPacket *rinp)
virtual void dataOut (RTPInnerPacket *packet)
virtual void dataIn (RTPInnerPacket *rinp)
virtual void leaveSession (RTPInnerPacket *rinp)
virtual void connectRet ()
virtual void readRet (cPacket *sifpIn)
virtual void createSocket ()
virtual void chooseSSRC ()
virtual void scheduleInterval ()
virtual void createPacket ()
virtual void processOutgoingRTPPacket (RTPPacket *packet)
virtual void processIncomingRTPPacket (RTPPacket *packet, IPAddress address, int port)
virtual void processIncomingRTCPPacket (RTCPCompoundPacket *packet, IPAddress address, int port)
virtual RTPParticipantInfofindParticipantInfo (uint32 ssrc)
virtual void calculateAveragePacketSize (int size)

Protected Attributes

int _mtu
int _bandwidth
int _rtcpPercentage
IPAddress _destinationAddress
int _port
bool _ssrcChosen
bool _leaveSession
RTPSenderInfo_senderInfo
cArray * _participantInfos
int _socketFdIn
int _socketFdOut
int _packetsCalculated
double _averagePacketSize
cOutVector * _rtcpIntervalOutVector

Detailed Description

The class RTCP is responsible for creating, receiving and processing of rtcp packets. It also keeps track of this and other rtp end systems.

Definition at line 37 of file RTCP.h.


Constructor & Destructor Documentation

RTCP::RTCP (  ) 

Definition at line 35 of file RTCP.cc.

{
    _participantInfos = NULL;
}

RTCP::~RTCP (  )  [protected, virtual]

Definition at line 55 of file RTCP.cc.

{
    delete _participantInfos;
}


Member Function Documentation

void RTCP::calculateAveragePacketSize ( int  size  )  [protected, virtual]

Recalculates the average size of an RTCPCompoundPacket when one of this size has been sent or received.

Definition at line 532 of file RTCP.cc.

Referenced by createPacket(), and processIncomingRTCPPacket().

{
    // add size of ip and udp header to given size before calculating
    _averagePacketSize = ((double)(_packetsCalculated) * _averagePacketSize + (double)(size + 20 + 8)) / (double)(++_packetsCalculated);
}

void RTCP::chooseSSRC (  )  [protected, virtual]

Chooses the ssrc identifier for this end system.

Definition at line 247 of file RTCP.cc.

Referenced by handleSelfMessage().

                     {

    uint32 ssrc = 0;
    bool ssrcConflict = false;
    do {
        ssrc = intrand(0x7fffffff);
        ssrcConflict = findParticipantInfo(ssrc) != NULL;
    } while (ssrcConflict);
    ev << "chooseSSRC" << ssrc;
    _senderInfo->setSSRC(ssrc);
    _participantInfos->add(_senderInfo);
    _ssrcChosen = true;
}

void RTCP::connectRet (  )  [protected, virtual]

Called when the socket layer has finished a connect.

Definition at line 186 of file RTCP.cc.

Referenced by createSocket().

{
    // schedule first rtcp packet
    double intervalLength = 2.5 * (dblrand() + 0.5);
    cMessage *reminderMessage = new cMessage("Interval");
    scheduleAt(simTime() + intervalLength, reminderMessage);
}

void RTCP::createPacket (  )  [protected, virtual]

Creates and sends an RTCPCompoundPacket.

Definition at line 262 of file RTCP.cc.

Referenced by handleSelfMessage().

{
    // first packet in an rtcp compound packet must
    // be a sender or receiver report
    RTCPReceiverReportPacket *reportPacket;

    // if this rtcp end system is a sender (see SenderInformation::isSender() for
    // details) insert a sender report
    if (_senderInfo->isSender()) {
        RTCPSenderReportPacket *senderReportPacket = new RTCPSenderReportPacket("SenderReportPacket");
        senderReportPacket->setSenderReport(_senderInfo->senderReport(simTime()));
        reportPacket = senderReportPacket;
    }
    else
        reportPacket = new RTCPReceiverReportPacket("ReceiverReportPacket");
    reportPacket->setSSRC(_senderInfo->getSSRC());


    // insert receiver reports for packets from other sources
    for (int i = 0; i < _participantInfos->size(); i++) {

        if (_participantInfos->exist(i)) {
            RTPParticipantInfo *participantInfo = (RTPParticipantInfo *)(_participantInfos->get(i));
            if (participantInfo->getSSRC() != _senderInfo->getSSRC()) {
                ReceptionReport *report = ((RTPReceiverInfo *)participantInfo)->receptionReport(simTime());
                if (report != NULL) {
                    reportPacket->addReceptionReport(report);
                }
            }
            participantInfo->nextInterval(simTime());

            if (participantInfo->toBeDeleted(simTime())) {
                _participantInfos->remove(participantInfo);
                delete participantInfo;
                // perhaps inform the profile
            }
        }
    }
    // insert source description items (at least common name)
    RTCPSDESPacket *sdesPacket = new RTCPSDESPacket("SDESPacket");

    SDESChunk *chunk = _senderInfo->getSDESChunk();
    sdesPacket->addSDESChunk(chunk);

    RTCPCompoundPacket *compoundPacket = new RTCPCompoundPacket("RTCPCompoundPacket");

    compoundPacket->addRTCPPacket(reportPacket);
    compoundPacket->addRTCPPacket(sdesPacket);

    // create rtcp app/bye packets if needed
    if (_leaveSession) {
        RTCPByePacket *byePacket = new RTCPByePacket("ByePacket");
        byePacket->setSSRC(_senderInfo->getSSRC());
        compoundPacket->addRTCPPacket(byePacket);
    }

    calculateAveragePacketSize(compoundPacket->getByteLength());

    cPacket *msg = new cPacket("RTCPCompoundPacket");
    msg->encapsulate(compoundPacket);
    msg->setKind(UDP_C_DATA);
    UDPControlInfo *ctrl = new UDPControlInfo();
    ctrl->setSockId(_socketFdOut);
    ctrl->setDestAddr(_destinationAddress);
    ctrl->setDestPort(_port);
    msg->setControlInfo(ctrl);

    send(msg, "udpOut");

    if (_leaveSession) {
        RTPInnerPacket *rinp = new RTPInnerPacket("sessionLeft()");
        rinp->sessionLeft();
        send(rinp, "rtpOut");
    }
}

void RTCP::createSocket (  )  [protected, virtual]

Request a server socket from the socket layer.

Definition at line 201 of file RTCP.cc.

Referenced by initializeRTCP().

{
    // TODO UDPAppBase should be ported to use UDPSocket sometime, but for now
    // we just manage the UDP socket by hand...
    if (_socketFdIn == -1) {
        _socketFdIn = UDPSocket::generateSocketId();
        UDPControlInfo *ctrl = new UDPControlInfo();
        IPAddress ipaddr(_destinationAddress);

        if (ipaddr.isMulticast()) {
            ctrl->setSrcAddr(IPAddress(_destinationAddress));
            ctrl->setSrcPort(_port);
        }
        else {
             ctrl->setSrcPort(_port);
             ctrl->setSockId(_socketFdOut);
        }
        ctrl->setSockId((int)_socketFdIn);
        cMessage *msg = new cMessage("UDP_C_BIND", UDP_C_BIND);
        msg->setControlInfo(ctrl);
        send(msg,"udpOut");

        connectRet();
    }
}

void RTCP::dataIn ( RTPInnerPacket rinp  )  [protected, virtual]

Stores information about an outgoing rtp data packet.

Definition at line 172 of file RTCP.cc.

Referenced by handleMessageFromRTP().

{
    RTPPacket *rtpPacket = check_and_cast<RTPPacket *>(rinp->decapsulate());
    //rtpPacket->dump();
    processIncomingRTPPacket(rtpPacket, rinp->getAddress(), rinp->getPort());
}

void RTCP::dataOut ( RTPInnerPacket packet  )  [protected, virtual]

Stores information about an outgoing rtp data packet.

Definition at line 165 of file RTCP.cc.

Referenced by handleMessageFromRTP().

{
    RTPPacket *rtpPacket = check_and_cast<RTPPacket *>(packet->decapsulate());
    processOutgoingRTPPacket(rtpPacket);
}

RTPParticipantInfo * RTCP::findParticipantInfo ( uint32  ssrc  )  [protected, virtual]

Returns the RTPParticipantInfo object used for storing information about the rtp end system with this ssrc identifier. Returns NULL if this end system is unknown.

Definition at line 519 of file RTCP.cc.

Referenced by chooseSSRC(), processIncomingRTCPPacket(), and processIncomingRTPPacket().

{
    char *ssrcString = RTPParticipantInfo::ssrcToName(ssrc);
    int participantIndex = _participantInfos->find(ssrcString);
    if (participantIndex != -1) {
        return (RTPParticipantInfo *)(_participantInfos->get(participantIndex));
    }
    else {
        return NULL;
    }
}

void RTCP::handleMessage ( cMessage *  msg  )  [protected, virtual]

Message handling. Dispatches messages by arrival gate.

Definition at line 60 of file RTCP.cc.

{

    // first distinguish incoming messages by arrival gate
    if (msg->getArrivalGateId() == findGate("rtpIn")) {
        handleMessageFromRTP(msg);
    }
    else if (msg->getArrivalGateId() == findGate("udpIn")) {
        handleMessageFromUDP(msg);
    }
    else {
        handleSelfMessage(msg);
    }

    delete msg;
}

void RTCP::handleMessageFromRTP ( cMessage *  msg  )  [protected, virtual]

Handles messages from the rtp module.

Definition at line 81 of file RTCP.cc.

Referenced by handleMessage().

{

    // from the rtp module all messages are of type RTPInnerPacket
    RTPInnerPacket *rinp = check_and_cast<RTPInnerPacket *>(msg);

    // distinguish by type
    if (rinp->getType() == RTPInnerPacket::RTP_INP_INITIALIZE_RTCP) {
        initializeRTCP(rinp);
    }
    else if (rinp->getType() == RTPInnerPacket::RTP_INP_SENDER_MODULE_INITIALIZED) {
        senderModuleInitialized(rinp);
    }
    else if (rinp->getType() == RTPInnerPacket::RTP_INP_DATA_OUT) {
        dataOut(rinp);
    }
    else if (rinp->getType() == RTPInnerPacket::RTP_INP_DATA_IN) {
        dataIn(rinp);
    }
    else if (rinp->getType() == RTPInnerPacket::RTP_INP_LEAVE_SESSION) {
        leaveSession(rinp);
    }
    else {
        error("unknown RTPInnerPacket type");
    }
}

void RTCP::handleMessageFromUDP ( cMessage *  msg  )  [protected, virtual]

Handles messages coming from the socket layer.

Definition at line 109 of file RTCP.cc.

Referenced by handleMessage().

{
    // from SocketLayer all message are of type cMessage
    readRet(PK(msg));
}

void RTCP::handleSelfMessage ( cMessage *  msg  )  [protected, virtual]

Handles self messages.

Definition at line 116 of file RTCP.cc.

Referenced by handleMessage().

{
    // it's time to create an rtcp packet
    if (!_ssrcChosen) {
        chooseSSRC();
        RTPInnerPacket *rinp1 = new RTPInnerPacket("rtcpInitialized()");
        rinp1->rtcpInitialized(_senderInfo->getSSRC());
        send(rinp1, "rtpOut");
    }

    createPacket();

    if (!_leaveSession) {
        scheduleInterval();
    }
}

void RTCP::initialize (  )  [protected, virtual]

Initializes variables.

Definition at line 40 of file RTCP.cc.

{

    // initialize variables
    _ssrcChosen = false;
    _leaveSession = false;
    _socketFdIn = -1;
    _socketFdOut = -1;

    _packetsCalculated = 0;
    _averagePacketSize = 0.0;

    _participantInfos = new cArray("ParticipantInfos");
}

void RTCP::initializeRTCP ( RTPInnerPacket rinp  )  [protected, virtual]

Initializes the rtcp module when the session is started.

Definition at line 137 of file RTCP.cc.

Referenced by handleMessageFromRTP().

{
    _mtu = rinp->getMTU();
    _bandwidth = rinp->getBandwidth();
    _rtcpPercentage = rinp->getRtcpPercentage();
    _destinationAddress = rinp->getAddress();
    _port = rinp->getPort();

    _senderInfo = new RTPSenderInfo();

    SDESItem *sdesItem = new SDESItem(SDESItem::SDES_CNAME, rinp->getCommonName());
    _senderInfo->addSDESItem(sdesItem);


    // create server socket for receiving rtcp packets
    createSocket();
}

void RTCP::leaveSession ( RTPInnerPacket rinp  )  [protected, virtual]

Makes the rtcp module send an RTCPByePacket in the next RTCPCompoundPacket to tell other participants in the rtp session that this end system leaves.

Definition at line 180 of file RTCP.cc.

Referenced by handleMessageFromRTP().

{
    _leaveSession = true;
}

void RTCP::processIncomingRTCPPacket ( RTCPCompoundPacket packet,
IPAddress  address,
int  port 
) [protected, virtual]

Extracts information of a received RTCPCompoundPacket.

Definition at line 371 of file RTCP.cc.

Referenced by readRet().

{
    calculateAveragePacketSize(packet->getByteLength());
    cArray *rtcpPackets = packet->getRtcpPackets();

    simtime_t arrivalTime = packet->getArrivalTime();
    delete packet;

   for (int i = 0; i < rtcpPackets->size(); i++) {
        if (rtcpPackets->exist(i)) {
            // remove the rtcp packet from the rtcp compound packet
            RTCPPacket *rtcpPacket = (RTCPPacket *)(rtcpPackets->remove(i));
            if (rtcpPacket->getPacketType() == RTCPPacket::RTCP_PT_SR) {
                RTCPSenderReportPacket *rtcpSenderReportPacket = (RTCPSenderReportPacket *)rtcpPacket;
                uint32 ssrc = rtcpSenderReportPacket->getSSRC();
                RTPParticipantInfo *participantInfo = findParticipantInfo(ssrc);

                if (participantInfo == NULL) {
                    participantInfo = new RTPReceiverInfo(ssrc);
                    participantInfo->setAddress(address);
                    participantInfo->setRTCPPort(port);
                    _participantInfos->add(participantInfo);
                }
                else {
                    if (participantInfo->getAddress() == address) {
                        if (participantInfo->getRTCPPort() == PORT_UNDEF) {
                            participantInfo->setRTCPPort(port);
                        }
                        else {
                            // check for ssrc conflict
                        }
                    }
                    else {
                        // check for ssrc conflict
                    }
                }
                participantInfo->processSenderReport(rtcpSenderReportPacket->getSenderReport(), simTime());

                cArray *receptionReports = rtcpSenderReportPacket->getReceptionReports();
                for (int j = 0; j < receptionReports->size(); j++) {
                    if (receptionReports->exist(j)) {
                        ReceptionReport *receptionReport = (ReceptionReport *)(receptionReports->remove(j));
                        if (_senderInfo) {
                            if (receptionReport->getSSRC() == _senderInfo->getSSRC()) {
                                _senderInfo->processReceptionReport(receptionReport, simTime());
                            }
                        }
                        else
                            //cancelAndDelete(receptionReport);
                            delete receptionReport;
                    }
                }
                delete receptionReports;

            }
            else if (rtcpPacket->getPacketType() == RTCPPacket::RTCP_PT_RR) {
                RTCPReceiverReportPacket *rtcpReceiverReportPacket = (RTCPReceiverReportPacket *)rtcpPacket;
                uint32 ssrc = rtcpReceiverReportPacket->getSSRC();
                RTPParticipantInfo *participantInfo = findParticipantInfo(ssrc);
                if (participantInfo == NULL) {
                    participantInfo = new RTPReceiverInfo(ssrc);
                    participantInfo->setAddress(address);
                    participantInfo->setRTCPPort(port);
                    _participantInfos->add(participantInfo);
                }
                else {
                    if (participantInfo->getAddress() == address) {
                        if (participantInfo->getRTCPPort() == PORT_UNDEF) {
                            participantInfo->setRTCPPort(port);
                        }
                        else {
                            // check for ssrc conflict
                        }
                    }
                    else {
                        // check for ssrc conflict
                    }
                }

                cArray *receptionReports = rtcpReceiverReportPacket->getReceptionReports();
                for (int j = 0; j < receptionReports->size(); j++) {
                    if (receptionReports->exist(j)) {
                        ReceptionReport *receptionReport = (ReceptionReport *)(receptionReports->remove(j));
                        if (_senderInfo) {

                            if (receptionReport->getSSRC() == _senderInfo->getSSRC()) {
                                _senderInfo->processReceptionReport(receptionReport, simTime());
                            }
                        }

                         else
                            //cancelAndDelete(receptionReport);
                             delete receptionReport;
                    }
                }
                delete receptionReports;
            }
            else if (rtcpPacket->getPacketType() == RTCPPacket::RTCP_PT_SDES) {
                RTCPSDESPacket *rtcpSDESPacket = (RTCPSDESPacket *)rtcpPacket;
                cArray *sdesChunks = rtcpSDESPacket->getSdesChunks();

                for (int j = 0; j < sdesChunks->size(); j++) {
                    if (sdesChunks->exist(j)) {
                        // remove the sdes chunk from the cArray of sdes chunks
                        SDESChunk *sdesChunk = (SDESChunk *)(sdesChunks->remove(j));
                        // this is needed to avoid seg faults
                        //sdesChunk->setOwner(this);
                        uint32 ssrc = sdesChunk->getSSRC();
                        RTPParticipantInfo *participantInfo = findParticipantInfo(ssrc);
                        if (participantInfo == NULL) {
                            participantInfo = new RTPReceiverInfo(ssrc);
                            participantInfo->setAddress(address);
                            participantInfo->setRTCPPort(port);
                            _participantInfos->add(participantInfo);
                        }
                        else {
                            // check for ssrc conflict
                        }
                        participantInfo->processSDESChunk(sdesChunk, arrivalTime);
                    }
                }
                delete sdesChunks;

            }
            else if (rtcpPacket->getPacketType() == RTCPPacket::RTCP_PT_BYE) {
                RTCPByePacket *rtcpByePacket = (RTCPByePacket *)rtcpPacket;
                uint32 ssrc = rtcpByePacket->getSSRC();
                RTPParticipantInfo *participantInfo = findParticipantInfo(ssrc);

                if (participantInfo != NULL && participantInfo != _senderInfo) {
                    _participantInfos->remove(participantInfo);

                    delete participantInfo;
                    // perhaps it would be useful to inform
                    // the profile to remove the corresponding
                    // receiver module
                }
            }
            else {
                // app rtcp packets
            }
        delete rtcpPacket;
        }
    }
    delete rtcpPackets;
}

void RTCP::processIncomingRTPPacket ( RTPPacket packet,
IPAddress  address,
int  port 
) [protected, virtual]

Extracts information of a received RTPPacket.

Definition at line 345 of file RTCP.cc.

Referenced by dataIn().

{
    uint32 ssrc = packet->getSSRC();
    RTPParticipantInfo *participantInfo = findParticipantInfo(ssrc);
    if (participantInfo == NULL) {
        participantInfo = new RTPParticipantInfo(ssrc);
        participantInfo->setAddress(address);
        participantInfo->setRTPPort(port);
        _participantInfos->add(participantInfo);
    }
    else {
        // check for ssrc conflict
        if (participantInfo->getAddress() != address) {
            // we have an address conflict
        }
        if (participantInfo->getRTPPort() == PORT_UNDEF) {
            participantInfo->setRTPPort(port);
        }
        else if (participantInfo->getRTPPort() != port) {
            // we have an rtp port conflict
        }
    }
    participantInfo->processRTPPacket(packet, getId(),  packet->getArrivalTime());
}

void RTCP::processOutgoingRTPPacket ( RTPPacket packet  )  [protected, virtual]

Extracts information of a sent RTPPacket.

Definition at line 339 of file RTCP.cc.

Referenced by dataOut().

{
    _senderInfo->processRTPPacket(packet, getId(), simTime());
}

void RTCP::readRet ( cPacket *  sifpIn  )  [protected, virtual]

Called when this rtcp module receives data from the socket layer.

Definition at line 195 of file RTCP.cc.

Referenced by handleMessageFromUDP().

void RTCP::scheduleInterval (  )  [protected, virtual]

Calculates the length of the next rtcp interval an issues a self message to remind itself.

Definition at line 228 of file RTCP.cc.

Referenced by handleSelfMessage().

                           {

    simtime_t intervalLength = _averagePacketSize * (simtime_t)(_participantInfos->size()) / (simtime_t)(_bandwidth * _rtcpPercentage * (_senderInfo->isSender() ? 1.0 : 0.75) / 100.0);

    // interval length must be at least 5 seconds
    if (intervalLength < 5.0)
        intervalLength = 5.0;

    // to avoid rtcp packet bursts multiply calculated interval length
    // with a random number between 0.5 and 1.5
    intervalLength = intervalLength * (0.5 + dblrand());

    intervalLength /= (double) (2.71828-1.5); // [RFC 3550] , by Ahmed ayadi

    cMessage *reminderMessage = new cMessage("Interval");
    scheduleAt(simTime() + intervalLength, reminderMessage);
}

void RTCP::senderModuleInitialized ( RTPInnerPacket rinp  )  [protected, virtual]

Stores information about the new transmission.

Definition at line 156 of file RTCP.cc.

Referenced by handleMessageFromRTP().


Member Data Documentation

double RTCP::_averagePacketSize [protected]

The average size of an RTCPCompoundPacket.

Definition at line 175 of file RTCP.h.

Referenced by calculateAveragePacketSize(), initialize(), and scheduleInterval().

int RTCP::_bandwidth [protected]

The bandwidth for this rtp session.

Definition at line 118 of file RTCP.h.

Referenced by initializeRTCP(), and scheduleInterval().

The destination address.

Definition at line 128 of file RTCP.h.

Referenced by createPacket(), createSocket(), initializeRTCP(), and readRet().

bool RTCP::_leaveSession [protected]

True when this end system is about to leave the session.

Definition at line 143 of file RTCP.h.

Referenced by createPacket(), handleSelfMessage(), initialize(), and leaveSession().

int RTCP::_mtu [protected]

The maximum size an RTCPCompundPacket can have.

Definition at line 113 of file RTCP.h.

Referenced by initializeRTCP().

int RTCP::_packetsCalculated [protected]

The number of packets this rtcp module has calculated.

Definition at line 170 of file RTCP.h.

Referenced by calculateAveragePacketSize(), and initialize().

cArray* RTCP::_participantInfos [protected]

Information about all known rtp end system participating in this rtp session.

Definition at line 154 of file RTCP.h.

Referenced by chooseSSRC(), createPacket(), findParticipantInfo(), initialize(), processIncomingRTCPPacket(), processIncomingRTPPacket(), RTCP(), scheduleInterval(), and ~RTCP().

int RTCP::_port [protected]

The rtcp port.

Definition at line 133 of file RTCP.h.

Referenced by createPacket(), createSocket(), initializeRTCP(), and readRet().

cOutVector* RTCP::_rtcpIntervalOutVector [protected]

The output vector for statistical data about the behaviour of rtcp. Every participant's rtcp module writes its calculated rtcp interval (without variation

Definition at line 182 of file RTCP.h.

int RTCP::_rtcpPercentage [protected]

The percentage of bandwidth for rtcp.

Definition at line 123 of file RTCP.h.

Referenced by initializeRTCP(), and scheduleInterval().

int RTCP::_socketFdIn [protected]

The server socket for receiving rtcp packets.

Definition at line 159 of file RTCP.h.

Referenced by createSocket(), and initialize().

int RTCP::_socketFdOut [protected]

The client socket for sending rtcp packets.

Definition at line 164 of file RTCP.h.

Referenced by createPacket(), createSocket(), and initialize().

bool RTCP::_ssrcChosen [protected]

True when this end system has chosen its ssrc identifier.

Definition at line 138 of file RTCP.h.

Referenced by chooseSSRC(), handleSelfMessage(), and initialize().


The documentation for this class was generated from the following files: