#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. |