#include <RTCPEndsystemModule.h>
|
|
Recalculates the average size of an RTCPCompoundPacket when one of this size has been sent or received. 00568 {
00569 // add size of ip and udp header to given size before calculating
00570 _averagePacketSize = ((double)(_packetsCalculated) * _averagePacketSize + (double)(size + 20 + 8)) / (double)(++_packetsCalculated);
00571 };
|
|
|
Chooses the ssrc identifier for this end system. 00283 {
00284
00285 u_int32 ssrc = 0;
00286 bool ssrcConflict = false;
00287 do {
00288 ssrc = intrand(0x7fffffff);
00289 ssrcConflict = findParticipantInfo(ssrc) != NULL;
00290 } while (ssrcConflict);
00291 _senderInfo->setSSRC(ssrc);
00292 _participantInfos->add(_senderInfo);
00293 _ssrcChosen = true;
00294 };
|
|
|
Called when the socket layer has finished a connect. 00229 {
00230 // schedule first rtcp packet
00231 double intervalLength = 2.5 * (dblrand() + 0.5);
00232 cMessage *reminderMessage = new cMessage("Interval");
00233 scheduleAt(simTime() + intervalLength, reminderMessage);
00234 };
|
|
|
Requests a client socket from the socket layer. 00253 {
00254 SocketInterfacePacket *sifp = new SocketInterfacePacket("socket()");
00255 sifp->socket(Socket::IPSuite_AF_INET, Socket::IPSuite_SOCK_DGRAM, Socket::UDP);
00256 send(sifp, "toSocketLayer");
00257 };
|
|
|
Creates and sends an RTCPCompoundPacket. 00297 {
00298 // first packet in an rtcp compound packet must
00299 // be a sender or receiver report
00300 RTCPReceiverReportPacket *reportPacket;
00301
00302 // if this rtcp end system is a sender (see SenderInformation::isSender() for
00303 // details) insert a sender report
00304 if (_senderInfo->isSender()) {
00305 RTCPSenderReportPacket *senderReportPacket = new RTCPSenderReportPacket("SenderReportPacket");
00306 senderReportPacket->setSenderReport(_senderInfo->senderReport(simTime()));
00307 reportPacket = senderReportPacket;
00308 }
00309 else {
00310 reportPacket = new RTCPReceiverReportPacket("ReceiverReportPacket");
00311 }
00312 reportPacket->setSSRC(_senderInfo->ssrc());
00313
00314 // insert receiver reports for packets from other sources
00315 for (int i = 0; i < _participantInfos->items(); i++) {
00316
00317 if (_participantInfos->exist(i)) {
00318 RTPParticipantInfo *participantInfo = (RTPParticipantInfo *)(_participantInfos->get(i));
00319 if (participantInfo->ssrc() != _senderInfo->ssrc()) {
00320 ReceptionReport *report = ((RTPReceiverInfo *)participantInfo)->receptionReport(simTime());
00321 if (report != NULL) {
00322 reportPacket->addReceptionReport(report);
00323
00324 };
00325 };
00326 participantInfo->nextInterval(simTime());
00327
00328 if (participantInfo->toBeDeleted(simTime())) {
00329
00330 _participantInfos->remove(participantInfo);
00331 delete participantInfo;
00332 // perhaps inform the profile
00333 };
00334 };
00335 };
00336
00337
00338 // insert source description items (at least common name)
00339 RTCPSDESPacket *sdesPacket = new RTCPSDESPacket("SDESPacket");
00340
00341 SDESChunk *chunk = _senderInfo->sdesChunk();
00342 sdesPacket->addSDESChunk(chunk);
00343
00344 RTCPCompoundPacket *compoundPacket = new RTCPCompoundPacket("RTCPCompoundPacket");
00345
00346 compoundPacket->addRTCPPacket(reportPacket);
00347
00348 compoundPacket->addRTCPPacket(sdesPacket);
00349
00350 // create rtcp app/bye packets if needed
00351 if (_leaveSession) {
00352 RTCPByePacket *byePacket = new RTCPByePacket("ByePacket");
00353 byePacket->setSSRC(_senderInfo->ssrc());
00354 compoundPacket->addRTCPPacket(byePacket);
00355 };
00356
00357 calculateAveragePacketSize(compoundPacket->length());
00358
00359 SocketInterfacePacket *sifp = new SocketInterfacePacket("write()");
00360
00361 sifp->write(_socketFdOut, compoundPacket);
00362
00363 send(sifp, "toSocketLayer");
00364
00365 if (_leaveSession) {
00366 RTPInnerPacket *rinp = new RTPInnerPacket("sessionLeft()");
00367 rinp->sessionLeft();
00368 send(rinp, "toRTP");
00369 };
00370
00371 };
|
|
|
Request a server socket from the socket layer. 00247 {
00248 SocketInterfacePacket *sifp = new SocketInterfacePacket("socket()");
00249 sifp->socket(Socket::IPSuite_AF_INET, Socket::IPSuite_SOCK_DGRAM, Socket::UDP);
00250 send(sifp, "toSocketLayer");
00251 };
|
|
|
Stores information about an outgoing rtp data packet. 00181 {
00182 RTPPacket *rtpPacket = (RTPPacket *)(rinp->decapsulate());
00183 processIncomingRTPPacket(rtpPacket, rinp->address(), rinp->port());
00184 };
|
|
|
Stores information about an outgoing rtp data packet. 00175 {
00176 RTPPacket *rtpPacket = (RTPPacket *)(packet->decapsulate());
00177 processOutgoingRTPPacket(rtpPacket);
00178 };
|
|
|
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. 00556 {
00557 char *ssrcString = RTPParticipantInfo::ssrcToName(ssrc);
00558 int participantIndex = _participantInfos->find(ssrcString);
00559 if (participantIndex != -1) {
00560 return (RTPParticipantInfo *)(_participantInfos->get(participantIndex));
00561 }
00562 else {
00563 return NULL;
00564 };
00565 };
|
|
|
Message handling. Dispatches messages by arrival gate. 00058 {
00059
00060 // first distinguish incoming messages by arrival gate
00061 if (msg->arrivalGateId() == findGate("fromRTP")) {
00062 handleMessageFromRTP(msg);
00063 }
00064 else if (msg->arrivalGateId() == findGate("fromSocketLayer")) {
00065 handleMessageFromSocketLayer(msg);
00066 }
00067 else {
00068 handleSelfMessage(msg);
00069 }
00070
00071 delete msg;
00072 };
|
|
|
Handles messages from the rtp module. 00079 {
00080
00081 // from the rtp module all messages are of type RTPInnerPacket
00082 RTPInnerPacket *rinp = (RTPInnerPacket *)msg;
00083
00084 // distinguish by type
00085 if (rinp->type() == RTPInnerPacket::RTP_INP_INITIALIZE_RTCP) {
00086 initializeRTCP(rinp);
00087 }
00088 else if (rinp->type() == RTPInnerPacket::RTP_INP_SENDER_MODULE_INITIALIZED) {
00089 senderModuleInitialized(rinp);
00090 }
00091 else if (rinp->type() == RTPInnerPacket::RTP_INP_DATA_OUT) {
00092 dataOut(rinp);
00093 }
00094 else if (rinp->type() == RTPInnerPacket::RTP_INP_DATA_IN) {
00095 dataIn(rinp);
00096 }
00097 else if (rinp->type() == RTPInnerPacket::RTP_INP_LEAVE_SESSION) {
00098 leaveSession(rinp);
00099 }
00100 else {
00101 EV << "RTCPEndsystemModule: unknown RTPInnerPacket type !" << endl;
00102 }
00103 };
|
|
|
Handles messages coming from the socket layer. 00106 {
00107 // from SocketLayer all message are of type SocketInterfacePacket
00108 SocketInterfacePacket *sifpIn = (SocketInterfacePacket *)msg;
00109
00110 // distinguish by action (type of SocketInterfacePacket)
00111
00112 if (sifpIn->action() == SocketInterfacePacket::SA_SOCKET_RET) {
00113 socketRet(sifpIn);
00114 }
00115 else if (sifpIn->action() == SocketInterfacePacket::SA_CONNECT_RET) {
00116 connectRet(sifpIn);
00117 }
00118 else if (sifpIn->action() == SocketInterfacePacket::SA_READ_RET) {
00119 // we have rtcp data !
00120 readRet(sifpIn);
00121 }
00122 else {
00123 EV << "RTCPEndsystemModule: unknown SocketInterfacePacket type !" << endl;
00124 }
00125 };
|
|
|
Handles self messages. 00128 {
00129 // it's time to create an rtcp packet
00130 if (!_ssrcChosen) {
00131 chooseSSRC();
00132 RTPInnerPacket *rinp1 = new RTPInnerPacket("rtcpInitialized()");
00133 rinp1->rtcpInitialized(_senderInfo->ssrc());
00134 send(rinp1, "toRTP");
00135 }
00136
00137 createPacket();
00138
00139 if (!_leaveSession) {
00140 scheduleInterval();
00141 }
00142 };
|
|
|
Initializes variables. 00040 {
00041
00042 // initialize variables
00043 _ssrcChosen = false;
00044 _leaveSession = false;
00045 _socketFdIn = Socket::FILEDESC_UNDEF;
00046 _socketFdOut = Socket::FILEDESC_UNDEF;
00047
00048 _packetsCalculated = 0;
00049
00050 _averagePacketSize = 0.0;
00051
00052 _participantInfos = new cArray("ParticipantInfos");
00053
00054 _rtcpIntervalOutVector = new cOutVector();
00055 };
|
|
|
Initializes the rtcp module when the session is started. 00149 {
00150 _mtu = rinp->mtu();
00151 _bandwidth = rinp->bandwidth();
00152 _rtcpPercentage = rinp->rtcpPercentage();
00153 _destinationAddress = rinp->address();
00154 _port = rinp->port();
00155
00156 _senderInfo = new RTPSenderInfo();
00157
00158 SDESItem *sdesItem = new SDESItem(SDESItem::SDES_CNAME, rinp->commonName());
00159 _senderInfo->addSDESItem(sdesItem);
00160
00161
00162 // create server socket for receiving rtcp packets
00163 createServerSocket();
00164 };
|
|
|
Makes the rtcp module send an RTCPByePacket in the next RTCPCompoundPacket to tell other participants in the rtp session that this end system leaves. 00187 {
00188 _leaveSession = true;
00189 };
|
|
||||||||||||||||
|
Extracts information of a received RTCPCompoundPacket. 00405 {
00406
00407 calculateAveragePacketSize(packet->length());
00408
00409 cArray *rtcpPackets = packet->rtcpPackets();
00410
00411 simtime_t arrivalTime = packet->arrivalTime();
00412 delete packet;
00413
00414 for (int i = 0; i < rtcpPackets->items(); i++) {
00415 if (rtcpPackets->exist(i)) {
00416 // remove the rtcp packet from the rtcp compound packet
00417 RTCPPacket *rtcpPacket = (RTCPPacket *)(rtcpPackets->remove(i));
00418
00419 if (rtcpPacket->packetType() == RTCPPacket::RTCP_PT_SR) {
00420
00421 RTCPSenderReportPacket *rtcpSenderReportPacket = (RTCPSenderReportPacket *)rtcpPacket;
00422 u_int32 ssrc = rtcpSenderReportPacket->ssrc();
00423 RTPParticipantInfo *participantInfo = findParticipantInfo(ssrc);
00424
00425 if (participantInfo == NULL) {
00426 participantInfo = new RTPReceiverInfo(ssrc);
00427 participantInfo->setAddress(address);
00428 participantInfo->setRTCPPort(port);
00429 _participantInfos->add(participantInfo);
00430 }
00431 else {
00432 if (participantInfo->address() == address) {
00433 if (participantInfo->rtcpPort() == IPSuite_PORT_UNDEF) {
00434 participantInfo->setRTCPPort(port);
00435 }
00436 else {
00437 // check for ssrc conflict
00438 }
00439 }
00440 else {
00441 // check for ssrc conflict
00442 };
00443 }
00444 participantInfo->processSenderReport(rtcpSenderReportPacket->senderReport(), simTime());
00445
00446 cArray *receptionReports = rtcpSenderReportPacket->receptionReports();
00447 for (int j = 0; j < receptionReports->items(); j++) {
00448 if (receptionReports->exist(j)) {
00449 ReceptionReport *receptionReport = (ReceptionReport *)(receptionReports->remove(j));
00450 if (_senderInfo) {
00451 if (receptionReport->ssrc() == _senderInfo->ssrc()) {
00452 _senderInfo->processReceptionReport(receptionReport, simTime());
00453 }
00454 }
00455 //else
00456 // delete receiverReport;
00457 }
00458 };
00459 delete receptionReports;
00460
00461 }
00462 else if (rtcpPacket->packetType() == RTCPPacket::RTCP_PT_RR) {
00463
00464 RTCPReceiverReportPacket *rtcpReceiverReportPacket = (RTCPReceiverReportPacket *)rtcpPacket;
00465 u_int32 ssrc = rtcpReceiverReportPacket->ssrc();
00466 RTPParticipantInfo *participantInfo = findParticipantInfo(ssrc);
00467 if (participantInfo == NULL) {
00468 participantInfo = new RTPReceiverInfo(ssrc);
00469 participantInfo->setAddress(address);
00470 participantInfo->setRTCPPort(port);
00471 _participantInfos->add(participantInfo);
00472 }
00473 else {
00474 if (participantInfo->address() == address) {
00475 if (participantInfo->rtcpPort() == IPSuite_PORT_UNDEF) {
00476 participantInfo->setRTCPPort(port);
00477 }
00478 else {
00479 // check for ssrc conflict
00480 }
00481 }
00482 else {
00483 // check for ssrc conflict
00484 };
00485 }
00486
00487 cArray *receptionReports = rtcpReceiverReportPacket->receptionReports();
00488 for (int j = 0; j < receptionReports->items(); j++) {
00489 if (receptionReports->exist(j)) {
00490 ReceptionReport *receptionReport = (ReceptionReport *)(receptionReports->remove(j));
00491 if (_senderInfo) {
00492
00493 if (receptionReport->ssrc() == _senderInfo->ssrc()) {
00494 _senderInfo->processReceptionReport(receptionReport, simTime());
00495 }
00496 }
00497
00498 //else
00499 // delete receiverReport;
00500 }
00501 };
00502 delete receptionReports;
00503 }
00504 else if (rtcpPacket->packetType() == RTCPPacket::RTCP_PT_SDES) {
00505
00506 RTCPSDESPacket *rtcpSDESPacket = (RTCPSDESPacket *)rtcpPacket;
00507 cArray *sdesChunks = rtcpSDESPacket->sdesChunks();
00508
00509 for (int j = 0; j < sdesChunks->items(); j++) {
00510 if (sdesChunks->exist(j)) {
00511 // remove the sdes chunk from the cArray of sdes chunks
00512 SDESChunk *sdesChunk = (SDESChunk *)(sdesChunks->remove(j));
00513 // this is needed to avoid seg faults
00514 //sdesChunk->setOwner(this);
00515 u_int32 ssrc = sdesChunk->ssrc();
00516 RTPParticipantInfo *participantInfo = findParticipantInfo(ssrc);
00517 if (participantInfo == NULL) {
00518 participantInfo = new RTPReceiverInfo(ssrc);
00519 participantInfo->setAddress(address);
00520 participantInfo->setRTCPPort(port);
00521 _participantInfos->add(participantInfo);
00522 }
00523 else {
00524 // check for ssrc conflict
00525 }
00526 participantInfo->processSDESChunk(sdesChunk, arrivalTime);
00527 }
00528 }
00529 delete sdesChunks;
00530
00531 }
00532 else if (rtcpPacket->packetType() == RTCPPacket::RTCP_PT_BYE) {
00533 RTCPByePacket *rtcpByePacket = (RTCPByePacket *)rtcpPacket;
00534 u_int32 ssrc = rtcpByePacket->ssrc();
00535 RTPParticipantInfo *participantInfo = findParticipantInfo(ssrc);
00536
00537 if (participantInfo != NULL && participantInfo != _senderInfo) {
00538 _participantInfos->remove(participantInfo);
00539
00540 delete participantInfo;
00541 // perhaps it would be useful to inform
00542 // the profile to remove the corresponding
00543 // receiver module
00544 };
00545 }
00546 else {
00547 // app rtcp packets
00548 }
00549 delete rtcpPacket;
00550 }
00551 }
00552 delete rtcpPackets;
00553 };
|
|
||||||||||||||||
|
Extracts information of a received RTPPacket. 00379 {
00380
00381 u_int32 ssrc = packet->ssrc();
00382 RTPParticipantInfo *participantInfo = findParticipantInfo(ssrc);
00383 if (participantInfo == NULL) {
00384 participantInfo = new RTPParticipantInfo(ssrc);
00385 participantInfo->setAddress(address);
00386 participantInfo->setRTPPort(port);
00387 _participantInfos->add(participantInfo);
00388 }
00389 else {
00390 // check for ssrc conflict
00391 if (participantInfo->address() != address) {
00392 // we have an address conflict
00393 }
00394 if (participantInfo->rtpPort() == IPSuite_PORT_UNDEF) {
00395 participantInfo->setRTPPort(port);
00396 }
00397 else if (participantInfo->rtpPort() != port) {
00398 // we have an rtp port conflict
00399 }
00400 }
00401 participantInfo->processRTPPacket(packet, packet->arrivalTime());
00402 };
|
|
|
Extracts information of a sent RTPPacket. 00374 {
00375 _senderInfo->processRTPPacket(packet, simTime());
00376 };
|
|
|
Called when this rtcp module receives data from the socket layer. 00237 {
00238 RTCPCompoundPacket *packet = (RTCPCompoundPacket *)(sifpIn->decapsulate());
00239 processIncomingRTCPPacket(packet, IN_Addr(sifpIn->fAddr()), IN_Port(sifpIn->fPort()));
00240 };
|
|
|
Calculates the length of the next rtcp interval an issues a self message to remind itself. 00260 {
00261
00262 simtime_t intervalLength = (simtime_t)(_averagePacketSize) * (simtime_t)(_participantInfos->items()) / (simtime_t)(_bandwidth * _rtcpPercentage * (_senderInfo->isSender() ? 1.0 : 0.75) / 100.0);
00263
00264
00265 // write the calculated interval into file
00266 _rtcpIntervalOutVector->record(intervalLength);
00267
00268 // interval length must be at least 5 seconds
00269 if (intervalLength < 5.0)
00270 intervalLength = 5.0;
00271
00272
00273 // to avoid rtcp packet bursts multiply calculated interval length
00274 // with a random number between 0.5 and 1.5
00275 intervalLength = intervalLength * (0.5 + dblrand());
00276
00277
00278 cMessage *reminderMessage = new cMessage("Interval");
00279 scheduleAt(simTime() + intervalLength, reminderMessage);
00280 };
|
|
|
Stores information about the new transmission. 00167 {
00168 _senderInfo->setStartTime(simTime());
00169 _senderInfo->setClockRate(rinp->clockRate());
00170 _senderInfo->setTimeStampBase(rinp->timeStampBase());
00171 _senderInfo->setSequenceNumberBase(rinp->sequenceNumberBase());
00172 };
|
|
|
Called when the socket layer has returned a socket. 00192 {
00193
00194 // first the server socket is created
00195 if (_socketFdIn == Socket::FILEDESC_UNDEF) {
00196 _socketFdIn = sifpIn->filedesc();
00197 // when file descriptor for the server socket is known
00198 // we can bind it to the port
00199 SocketInterfacePacket *sifpOut1 = new SocketInterfacePacket("bind()");
00200 IPAddress ipaddr(_destinationAddress);
00201 if (ipaddr.isMulticast()) {
00202 sifpOut1->bind(_socketFdIn, IN_Addr(_destinationAddress), IN_Port(_port));
00203 }
00204 else {
00205 sifpOut1->bind(_socketFdIn, IPADDRESS_UNDEF, IN_Port(_port));
00206 }
00207 send(sifpOut1, "toSocketLayer");
00208
00209 createClientSocket();
00210 }
00211
00212 // server socket already exists, client socket is created
00213 else if (_socketFdOut == Socket::FILEDESC_UNDEF) {
00214
00215 _socketFdOut = sifpIn->filedesc();
00216
00217 // now connect it, which means set foreign address and port
00218 SocketInterfacePacket *sifpOut = new SocketInterfacePacket("connect()");
00219 sifpOut->connect(_socketFdOut, _destinationAddress, _port);
00220 send(sifpOut, "toSocketLayer");
00221
00222 }
00223 else {
00224 EV << "RTCPEndsystemModule: received unrequested socket from socket layer !" << endl;
00225 }
00226 };
|
|
|
The average size of an RTCPCompoundPacket. |
|
|
The bandwidth for this rtp session. |
|
|
The destination address. |
|
|
True when this end system is about to leave the session. |
|
|
The maximum size an RTCPCompundPacket can have. |
|
|
The number of packets this rtcp module has calculated. |
|
|
Information about all known rtp end system participating in this rtp session. |
|
|
The rtcp port. |
|
|
The output vector for statistical data about the behaviour of rtcp. Every participant's rtcp module writes its calculated rtcp interval (without variation |
|
|
The percentage of bandwidth for rtcp. |
|
|
The RTPSenderInfo about this end system. |
|
|
The server socket for receiving rtcp packets. |
|
|
The client socket for sending rtcp packets. |
|
|
True when this end system has chosen its ssrc identifier. |
1.4.1