[置顶]发现live555中一个小bug(2)

来源:互联网 发布:苹果电子书阅读软件 编辑:程序博客网 时间:2024/04/30 00:56

在《发现live555中一个小bug》一文中所修改的代码并不起作用。

经测试,RTPSource的Socket检测不到网络出错的情况。而RTCPInstance中的socket可以检测到,所以可以利用RTCPInstance通知RTPSource应停止流传输了。修改如下(//---------------------包含的代码为修改处):

view plain
  1. void RTCPInstance::incomingReportHandler1()  
  2. {  
  3.     do {  
  4.         int tcpReadStreamSocketNum = fRTCPInterface.nextTCPReadStreamSocketNum();  
  5.         unsigned char tcpReadStreamChannelId = fRTCPInterface.nextTCPReadStreamChannelId();  
  6.         unsigned packetSize = 0;  
  7.         unsigned numBytesRead;  
  8.         struct sockaddr_in fromAddress;  
  9.         Boolean packetReadWasIncomplete;  
  10.         Boolean readResult = fRTCPInterface.handleRead(  
  11.                 &fInBuf[fNumBytesAlreadyRead],  
  12.                 maxPacketSize - fNumBytesAlreadyRead, numBytesRead, fromAddress,  
  13.                 packetReadWasIncomplete);  
  14.         if (packetReadWasIncomplete) {  
  15.             fNumBytesAlreadyRead += numBytesRead;  
  16.             return// more reads are needed to get the entire packet  
  17.         } else { // normal case: We've read the entire packet  
  18.             packetSize = fNumBytesAlreadyRead + numBytesRead;  
  19.             fNumBytesAlreadyRead = 0; // for next time  
  20.         }  
  21.         if (!readResult){  
  22.             //--------------------------------  
  23.             //出错了,停止网络读  
  24.             fRTCPInterface.stopNetworkReading();  
  25.             //通知RTPSource和RTPSink,网络出错了,应该停止了  
  26.             if(fSink)  
  27.                 fSink->stopPlaying();  
  28.             if(fSource)  
  29.                 fSource->handleClosure((void*)fSource);  
  30.             //---------------------------------  
  31.             break;  
  32.         }  
  33.   
  34.         // Ignore the packet if it was looped-back from ourself:  
  35.         Boolean packetWasFromOurHost = False;  
  36.         if (RTCPgs()->wasLoopedBackFromUs(envir(), fromAddress)) {  
  37.             packetWasFromOurHost = True;  
  38.             // However, we still want to handle incoming RTCP packets from  
  39.             // *other processes* on the same machine.  To distinguish this  
  40.             // case from a true loop-back, check whether we've just sent a  
  41.             // packet of the same size.  (This check isn't perfect, but it seems  
  42.             // to be the best we can do.)  
  43.             if (fHaveJustSentPacket && fLastPacketSentSize == packetSize) {  
  44.                 // This is a true loop-back:  
  45.                 fHaveJustSentPacket = False;  
  46.                 break// ignore this packet  
  47.             }  
  48.         }  
  49.   
  50.         unsigned char* pkt = fInBuf;  
  51.         if (fIsSSMSource && !packetWasFromOurHost) {  
  52.             // This packet is assumed to have been received via unicast (because we're a SSM source, and SSM receivers send back RTCP "RR"  
  53.             // packets via unicast).  'Reflect' the packet by resending it to the multicast group, so that any other receivers can also  
  54.             // get to see it.  
  55.   
  56.             // NOTE: Denial-of-service attacks are possible here.  
  57.             // Users of this software may wish to add their own,  
  58.             // application-specific mechanism for 'authenticating' the  
  59.             // validity of this packet before reflecting it.  
  60.   
  61.             // NOTE: The test for "!packetWasFromOurHost" means that we won't reflect RTCP packets that come from other processes on  
  62.             // the same host as us.  The reason for this is that the 'packet size' test above is not 100% reliable; some packets  
  63.             // that were truly looped back from us might not be detected as such, and this might lead to infinite forwarding/receiving  
  64.             // of some packets.  To avoid this possibility, we only reflect RTCP packets that we know for sure originated elsewhere.  
  65.             // (Note, though, that if we ever re-enable the code in "Groupsock::multicastSendOnly()", then we could remove the test for  
  66.             // "!packetWasFromOurHost".)  
  67.             fRTCPInterface.sendPacket(pkt, packetSize);  
  68.             fHaveJustSentPacket = True;  
  69.             fLastPacketSentSize = packetSize;  
  70.         }  
  71.   
  72. #ifdef DEBUG  
  73.         fprintf(stderr, "[%p]saw incoming RTCP packet (from address %s, port %d)\n"this, our_inet_ntoa(fromAddress.sin_addr), ntohs(fromAddress.sin_port));  
  74.         for (unsigned i = 0; i < packetSize; ++i) {  
  75.             if (i%4 == 0) fprintf(stderr, " ");  
  76.             fprintf(stderr, "%02x", pkt[i]);  
  77.         }  
  78.         fprintf(stderr, "\n");  
  79. #endif  
  80.         int totPacketSize = IP_UDP_HDR_SIZE + packetSize;  
  81.   
  82.         // Check the RTCP packet for validity:  
  83.         // It must at least contain a header (4 bytes), and this header  
  84.         // must be version=2, with no padding bit, and a payload type of  
  85.         // SR (200) or RR (201):  
  86.         if (packetSize < 4)  
  87.             break;  
  88.         unsigned rtcpHdr = ntohl(*(u_int32_t*) pkt);  
  89.         if ((rtcpHdr & 0xE0FE0000) != (0x80000000 | (RTCP_PT_SR << 16))) {  
  90. #ifdef DEBUG  
  91.             fprintf(stderr, "rejected bad RTCP packet: header 0x%08x\n", rtcpHdr);  
  92. #endif  
  93.             break;  
  94.         }  
  95.   
  96.         // Process each of the individual RTCP 'subpackets' in (what may be)  
  97.         // a compound RTCP packet.  
  98.         int typeOfPacket = PACKET_UNKNOWN_TYPE;  
  99.         unsigned reportSenderSSRC = 0;  
  100.         Boolean packetOK = False;  
  101.         while (1) {  
  102.             unsigned rc = (rtcpHdr >> 24) & 0x1F;  
  103.             unsigned pt = (rtcpHdr >> 16) & 0xFF;  
  104.             unsigned length = 4 * (rtcpHdr & 0xFFFF); // doesn't count hdr  
  105.             ADVANCE(4);  
  106.             // skip over the header  
  107.             if (length > packetSize)  
  108.                 break;  
  109.   
  110.             // Assume that each RTCP subpacket begins with a 4-byte SSRC:  
  111.             if (length < 4)  
  112.                 break;  
  113.             length -= 4;  
  114.             reportSenderSSRC = ntohl(*(u_int32_t*) pkt);  
  115.             ADVANCE(4);  
  116.   
  117.             Boolean subPacketOK = False;  
  118.             switch (pt) {  
  119.             case RTCP_PT_SR: {  
  120. #ifdef DEBUG  
  121.                 fprintf(stderr, "SR\n");  
  122. #endif  
  123.                 if (length < 20)  
  124.                     break;  
  125.                 length -= 20;  
  126.   
  127.                 // Extract the NTP timestamp, and note this:  
  128.                 unsigned NTPmsw = ntohl(*(u_int32_t*) pkt);  
  129.                 ADVANCE(4);  
  130.                 unsigned NTPlsw = ntohl(*(u_int32_t*) pkt);  
  131.                 ADVANCE(4);  
  132.                 unsigned rtpTimestamp = ntohl(*(u_int32_t*) pkt);  
  133.                 ADVANCE(4);  
  134.                 if (fSource != NULL) {  
  135.                     RTPReceptionStatsDB& receptionStats = fSource->receptionStatsDB();  
  136.                     receptionStats.noteIncomingSR(reportSenderSSRC, NTPmsw,  
  137.                             NTPlsw, rtpTimestamp);  
  138.                 }ADVANCE(8);  
  139.                 // skip over packet count, octet count  
  140.   
  141.                 // If a 'SR handler' was set, call it now:  
  142.                 if (fSRHandlerTask != NULL)  
  143.                     (*fSRHandlerTask)(fSRHandlerClientData);  
  144.   
  145.                 // The rest of the SR is handled like a RR (so, no "break;" here)  
  146.             }  
  147.             case RTCP_PT_RR: {  
  148. #ifdef DEBUG  
  149.                 fprintf(stderr, "RR\n");  
  150. #endif  
  151.                 unsigned reportBlocksSize = rc * (6 * 4);  
  152.                 if (length < reportBlocksSize)  
  153.                     break;  
  154.                 length -= reportBlocksSize;  
  155.   
  156.                 if (fSink != NULL) {  
  157.                     // Use this information to update stats about our transmissions:  
  158.                     RTPTransmissionStatsDB& transmissionStats = fSink->transmissionStatsDB();  
  159.                     for (unsigned i = 0; i < rc; ++i) {  
  160.                         unsigned senderSSRC = ntohl(*(u_int32_t*) pkt);  
  161.                         ADVANCE(4);  
  162.                         // We care only about reports about our own transmission, not others'  
  163.                         if (senderSSRC == fSink->SSRC()) {  
  164.                             unsigned lossStats = ntohl(*(u_int32_t*) pkt);  
  165.                             ADVANCE(4);  
  166.                             unsigned highestReceived = ntohl(*(u_int32_t*) pkt);  
  167.                             ADVANCE(4);  
  168.                             unsigned jitter = ntohl(*(u_int32_t*) pkt);  
  169.                             ADVANCE(4);  
  170.                             unsigned timeLastSR = ntohl(*(u_int32_t*) pkt);  
  171.                             ADVANCE(4);  
  172.                             unsigned timeSinceLastSR = ntohl(*(u_int32_t*) pkt);  
  173.                             ADVANCE(4);  
  174.                             transmissionStats.noteIncomingRR(reportSenderSSRC,  
  175.                                     fromAddress, lossStats, highestReceived,  
  176.                                     jitter, timeLastSR, timeSinceLastSR);  
  177.                         } else {  
  178.                             ADVANCE(4*5);  
  179.                         }  
  180.                     }  
  181.                 } else {  
  182.                     ADVANCE(reportBlocksSize);  
  183.                 }  
  184.   
  185.                 if (pt == RTCP_PT_RR) { // i.e., we didn't fall through from 'SR'  
  186.                     // If a 'RR handler' was set, call it now:  
  187.   
  188.                     // Specific RR handler:  
  189.                     if (fSpecificRRHandlerTable != NULL) {  
  190.                         netAddressBits fromAddr;  
  191.                         portNumBits fromPortNum;  
  192.                         if (tcpReadStreamSocketNum < 0) {  
  193.                             // Normal case: We read the RTCP packet over UDP  
  194.                             fromAddr = fromAddress.sin_addr.s_addr;  
  195.                             fromPortNum = ntohs(fromAddress.sin_port);  
  196.                         } else {  
  197.                             // Special case: We read the RTCP packet over TCP (interleaved)  
  198.                             // Hack: Use the TCP socket and channel id to look up the handler  
  199.                             fromAddr = tcpReadStreamSocketNum;  
  200.                             fromPortNum = tcpReadStreamChannelId;  
  201.                         }  
  202.                         Port fromPort(fromPortNum);  
  203.                         RRHandlerRecord* rrHandler = (RRHandlerRecord*) (fSpecificRRHandlerTable->Lookup(  
  204.                                 fromAddr, (~0), fromPort));  
  205.                         if (rrHandler != NULL) {  
  206.                             if (rrHandler->rrHandlerTask != NULL) {  
  207.                                 (*(rrHandler->rrHandlerTask))(  
  208.                                         rrHandler->rrHandlerClientData);  
  209.                             }  
  210.                         }  
  211.                     }  
  212.   
  213.                     // General RR handler:  
  214.                     if (fRRHandlerTask != NULL)  
  215.                         (*fRRHandlerTask)(fRRHandlerClientData);  
  216.                 }  
  217.   
  218.                 subPacketOK = True;  
  219.                 typeOfPacket = PACKET_RTCP_REPORT;  
  220.                 break;  
  221.             }  
  222.             case RTCP_PT_BYE: {  
  223. #ifdef DEBUG  
  224.                 fprintf(stderr, "BYE\n");  
  225. #endif  
  226.                 // If a 'BYE handler' was set, call it now:  
  227.                 TaskFunc* byeHandler = fByeHandlerTask;  
  228.                 if (byeHandler != NULL  
  229.                         && (!fByeHandleActiveParticipantsOnly  
  230.                                 || (fSource != NULL  
  231.                                         && fSource->receptionStatsDB().lookup(  
  232.                                                 reportSenderSSRC) != NULL)  
  233.                                 || (fSink != NULL  
  234.                                         && fSink->transmissionStatsDB().lookup(  
  235.                                                 reportSenderSSRC) != NULL))) {  
  236.                     fByeHandlerTask = NULL;  
  237.                     // we call this only once by default  
  238.                     (*byeHandler)(fByeHandlerClientData);  
  239.                 }  
  240.   
  241.                 // We should really check for & handle >1 SSRCs being present #####  
  242.   
  243.                 subPacketOK = True;  
  244.                 typeOfPacket = PACKET_BYE;  
  245.                 break;  
  246.             }  
  247.                 // Later handle SDES, APP, and compound RTCP packets #####  
  248.             default:  
  249. #ifdef DEBUG  
  250.                 fprintf(stderr, "UNSUPPORTED TYPE(0x%x)\n", pt);  
  251. #endif  
  252.                 subPacketOK = True;  
  253.                 break;  
  254.             }  
  255.             if (!subPacketOK)  
  256.                 break;  
  257.   
  258.             // need to check for (& handle) SSRC collision! #####  
  259.   
  260. #ifdef DEBUG  
  261.             fprintf(stderr, "validated RTCP subpacket (type %d): %d, %d, %d, 0x%08x\n", typeOfPacket, rc, pt, length, reportSenderSSRC);  
  262. #endif  
  263.   
  264.             // Skip over any remaining bytes in this subpacket:  
  265.             ADVANCE(length);  
  266.   
  267.             // Check whether another RTCP 'subpacket' follows:  
  268.             if (packetSize == 0) {  
  269.                 packetOK = True;  
  270.                 break;  
  271.             } else if (packetSize < 4) {  
  272. #ifdef DEBUG  
  273.                 fprintf(stderr, "extraneous %d bytes at end of RTCP packet!\n", packetSize);  
  274. #endif  
  275.                 break;  
  276.             }  
  277.             rtcpHdr = ntohl(*(u_int32_t*) pkt);  
  278.             if ((rtcpHdr & 0xC0000000) != 0x80000000) {  
  279. #ifdef DEBUG  
  280.                 fprintf(stderr, "bad RTCP subpacket: header 0x%08x\n", rtcpHdr);  
  281. #endif  
  282.                 break;  
  283.             }  
  284.         }  
  285.   
  286.         if (!packetOK) {  
  287. #ifdef DEBUG  
  288.             fprintf(stderr, "rejected bad RTCP subpacket: header 0x%08x\n", rtcpHdr);  
  289. #endif  
  290.             break;  
  291.         } else {  
  292. #ifdef DEBUG  
  293.             fprintf(stderr, "validated entire RTCP packet\n");  
  294. #endif  
  295.         }  
  296.   
  297.         onReceive(typeOfPacket, totPacketSize, reportSenderSSRC);  
  298.     } while (0);  
  299. }  

注意,fSource为 const*型的,设计者的原意是不能这样用的,但找不到更好的办法,而且测试没有问题,但是不能保证在以后的版本中不会出问题哦。


转载http://blog.csdn.net/nkmnkm/article/details/7004764

原创粉丝点击