INET Framework for OMNeT++/OMNEST
|
#include <RTCP.h>
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 RTPParticipantInfo * | findParticipantInfo (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 |
The class RTCP is responsible for creating, receiving and processing of rtcp packets. It also keeps track of this and other rtp end systems.
RTCP::RTCP | ( | ) |
{ _participantInfos = NULL; }
RTCP::~RTCP | ( | ) | [protected, virtual] |
{ delete _participantInfos; }
void RTCP::calculateAveragePacketSize | ( | int | size | ) | [protected, virtual] |
Recalculates the average size of an RTCPCompoundPacket when one of this size has been sent or received.
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.
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.
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.
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.
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.
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.
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.
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.
{ // 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.
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.
Referenced by handleMessage().
void RTCP::handleSelfMessage | ( | cMessage * | msg | ) | [protected, virtual] |
Handles self messages.
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.
{ // 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.
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.
Referenced by handleMessageFromRTP().
{ _leaveSession = true; }
void RTCP::processIncomingRTCPPacket | ( | RTCPCompoundPacket * | packet, |
IPAddress | address, | ||
int | port | ||
) | [protected, virtual] |
Extracts information of a received RTCPCompoundPacket.
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.
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.
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.
Referenced by handleMessageFromUDP().
{ RTCPCompoundPacket *packet = (RTCPCompoundPacket *)(sifpIn->decapsulate()); processIncomingRTCPPacket(packet, IPAddress(_destinationAddress), _port); }
void RTCP::scheduleInterval | ( | ) | [protected, virtual] |
Calculates the length of the next rtcp interval an issues a self message to remind itself.
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.
Referenced by handleMessageFromRTP().
{ _senderInfo->setStartTime(simTime()); _senderInfo->setClockRate(rinp->getClockRate()); _senderInfo->setTimeStampBase(rinp->getTimeStampBase()); _senderInfo->setSequenceNumberBase(rinp->getSequenceNumberBase()); }
double RTCP::_averagePacketSize [protected] |
The average size of an RTCPCompoundPacket.
Referenced by calculateAveragePacketSize(), initialize(), and scheduleInterval().
int RTCP::_bandwidth [protected] |
The bandwidth for this rtp session.
Referenced by initializeRTCP(), and scheduleInterval().
IPAddress RTCP::_destinationAddress [protected] |
The destination address.
Referenced by createPacket(), createSocket(), initializeRTCP(), and readRet().
bool RTCP::_leaveSession [protected] |
True when this end system is about to leave the session.
Referenced by createPacket(), handleSelfMessage(), initialize(), and leaveSession().
int RTCP::_mtu [protected] |
The maximum size an RTCPCompundPacket can have.
Referenced by initializeRTCP().
int RTCP::_packetsCalculated [protected] |
The number of packets this rtcp module has calculated.
Referenced by calculateAveragePacketSize(), and initialize().
cArray* RTCP::_participantInfos [protected] |
Information about all known rtp end system participating in this rtp session.
Referenced by chooseSSRC(), createPacket(), findParticipantInfo(), initialize(), processIncomingRTCPPacket(), processIncomingRTPPacket(), RTCP(), scheduleInterval(), and ~RTCP().
int RTCP::_port [protected] |
The rtcp port.
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
int RTCP::_rtcpPercentage [protected] |
The percentage of bandwidth for rtcp.
Referenced by initializeRTCP(), and scheduleInterval().
RTPSenderInfo* RTCP::_senderInfo [protected] |
The RTPSenderInfo about this end system.
Referenced by chooseSSRC(), createPacket(), handleSelfMessage(), initializeRTCP(), processIncomingRTCPPacket(), processOutgoingRTPPacket(), scheduleInterval(), and senderModuleInitialized().
int RTCP::_socketFdIn [protected] |
The server socket for receiving rtcp packets.
Referenced by createSocket(), and initialize().
int RTCP::_socketFdOut [protected] |
The client socket for sending rtcp packets.
Referenced by createPacket(), createSocket(), and initialize().
bool RTCP::_ssrcChosen [protected] |
True when this end system has chosen its ssrc identifier.
Referenced by chooseSSRC(), handleSelfMessage(), and initialize().