| 1 | /********** | 
|---|
| 2 | This library is free software; you can redistribute it and/or modify it under | 
|---|
| 3 | the terms of the GNU Lesser General Public License as published by the | 
|---|
| 4 | Free Software Foundation; either version 3 of the License, or (at your | 
|---|
| 5 | option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.) | 
|---|
| 6 |  | 
|---|
| 7 | This library is distributed in the hope that it will be useful, but WITHOUT | 
|---|
| 8 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 
|---|
| 9 | FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for | 
|---|
| 10 | more details. | 
|---|
| 11 |  | 
|---|
| 12 | You should have received a copy of the GNU Lesser General Public License | 
|---|
| 13 | along with this library; if not, write to the Free Software Foundation, Inc., | 
|---|
| 14 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA | 
|---|
| 15 | **********/ | 
|---|
| 16 | // "liveMedia" | 
|---|
| 17 | // Copyright (c) 1996-2020 Live Networks, Inc.  All rights reserved. | 
|---|
| 18 | // RTCP | 
|---|
| 19 | // C++ header | 
|---|
| 20 |  | 
|---|
| 21 | #ifndef _RTCP_HH | 
|---|
| 22 | #define _RTCP_HH | 
|---|
| 23 |  | 
|---|
| 24 | #ifndef _RTP_SINK_HH | 
|---|
| 25 | #include "RTPSink.hh" | 
|---|
| 26 | #endif | 
|---|
| 27 | #ifndef _RTP_SOURCE_HH | 
|---|
| 28 | #include "RTPSource.hh" | 
|---|
| 29 | #endif | 
|---|
| 30 |  | 
|---|
| 31 | class SDESItem { | 
|---|
| 32 | public: | 
|---|
| 33 | SDESItem(unsigned char tag, unsigned char const* value); | 
|---|
| 34 |  | 
|---|
| 35 | unsigned char const* data() const {return fData;} | 
|---|
| 36 | unsigned totalSize() const; | 
|---|
| 37 |  | 
|---|
| 38 | private: | 
|---|
| 39 | unsigned char fData[2 + 0xFF]; // first 2 bytes are tag and length | 
|---|
| 40 | }; | 
|---|
| 41 |  | 
|---|
| 42 | typedef void RTCPAppHandlerFunc(void* clientData, | 
|---|
| 43 | u_int8_t subtype, u_int32_t nameBytes/*big-endian order*/, | 
|---|
| 44 | u_int8_t* appDependentData, unsigned appDependentDataSize); | 
|---|
| 45 |  | 
|---|
| 46 | class RTCPMemberDatabase; // forward | 
|---|
| 47 |  | 
|---|
| 48 | typedef void ByeWithReasonHandlerFunc(void* clientData, char const* reason); | 
|---|
| 49 |  | 
|---|
| 50 | class RTCPInstance: public Medium { | 
|---|
| 51 | public: | 
|---|
| 52 | static RTCPInstance* createNew(UsageEnvironment& env, Groupsock* RTCPgs, | 
|---|
| 53 | unsigned totSessionBW, /* in kbps */ | 
|---|
| 54 | unsigned char const* cname, | 
|---|
| 55 | RTPSink* sink, | 
|---|
| 56 | RTPSource* source, | 
|---|
| 57 | Boolean isSSMSource = False); | 
|---|
| 58 |  | 
|---|
| 59 | static Boolean lookupByName(UsageEnvironment& env, char const* instanceName, | 
|---|
| 60 | RTCPInstance*& resultInstance); | 
|---|
| 61 |  | 
|---|
| 62 | unsigned numMembers() const; | 
|---|
| 63 | unsigned totSessionBW() const { return fTotSessionBW; } | 
|---|
| 64 |  | 
|---|
| 65 | void setByeHandler(TaskFunc* handlerTask, void* clientData, | 
|---|
| 66 | Boolean handleActiveParticipantsOnly = True); | 
|---|
| 67 | // Assigns a handler routine to be called if a "BYE" arrives. | 
|---|
| 68 | // The handler is called once only; for subsequent "BYE"s, | 
|---|
| 69 | // "setByeHandler()" would need to be called again. | 
|---|
| 70 | // If "handleActiveParticipantsOnly" is True, then the handler is called | 
|---|
| 71 | // only if the SSRC is for a known sender (if we have a "RTPSource"), | 
|---|
| 72 | // or if the SSRC is for a known receiver (if we have a "RTPSink"). | 
|---|
| 73 | // This prevents (for example) the handler for a multicast receiver being | 
|---|
| 74 | // called if some other multicast receiver happens to exit. | 
|---|
| 75 | // If "handleActiveParticipantsOnly" is False, then the handler is called | 
|---|
| 76 | // for any incoming RTCP "BYE". | 
|---|
| 77 | // (To remove an existing "BYE" handler, call "setByeHandler()" again, with a "handlerTask" of NULL.) | 
|---|
| 78 | void setByeWithReasonHandler(ByeWithReasonHandlerFunc* handlerTask, void* clientData, | 
|---|
| 79 | Boolean handleActiveParticipantsOnly = True); | 
|---|
| 80 | // Like "setByeHandler()", except that a string 'reason for the bye' (received as part of | 
|---|
| 81 | // the RTCP "BYE" packet) is passed to the handler function (along with "clientData"). | 
|---|
| 82 | // (The 'reason' parameter to the handler function will be a dynamically-allocated string, | 
|---|
| 83 | // or NULL, and should be delete[]d by the handler function.) | 
|---|
| 84 | void setSRHandler(TaskFunc* handlerTask, void* clientData); | 
|---|
| 85 | void setRRHandler(TaskFunc* handlerTask, void* clientData); | 
|---|
| 86 | // Assigns a handler routine to be called if a "SR" or "RR" packet | 
|---|
| 87 | // (respectively) arrives.  Unlike "setByeHandler()", the handler will | 
|---|
| 88 | // be called once for each incoming "SR" or "RR".  (To turn off handling, | 
|---|
| 89 | // call the function again with "handlerTask" (and "clientData") as NULL.) | 
|---|
| 90 | void setSpecificRRHandler(netAddressBits fromAddress, Port fromPort, | 
|---|
| 91 | TaskFunc* handlerTask, void* clientData); | 
|---|
| 92 | // Like "setRRHandler()", but applies only to "RR" packets that come from | 
|---|
| 93 | // a specific source address and port.  (Note that if both a specific | 
|---|
| 94 | // and a general "RR" handler function is set, then both will be called.) | 
|---|
| 95 | void unsetSpecificRRHandler(netAddressBits fromAddress, Port fromPort); // equivalent to setSpecificRRHandler(..., NULL, NULL); | 
|---|
| 96 | void setAppHandler(RTCPAppHandlerFunc* handlerTask, void* clientData); | 
|---|
| 97 | // Assigns a handler routine to be called whenever an "APP" packet arrives.  (To turn off | 
|---|
| 98 | // handling, call the function again with "handlerTask" (and "clientData") as NULL.) | 
|---|
| 99 | void sendAppPacket(u_int8_t subtype, char const* name, | 
|---|
| 100 | u_int8_t* appDependentData, unsigned appDependentDataSize); | 
|---|
| 101 | // Sends a custom RTCP "APP" packet to the peer(s).  The parameters correspond to their | 
|---|
| 102 | // respective fields as described in the RTP/RTCP definition (RFC 3550). | 
|---|
| 103 | // Note that only the low-order 5 bits of "subtype" are used, and only the first 4 bytes | 
|---|
| 104 | // of "name" are used.  (If "name" has fewer than 4 bytes, or is NULL, | 
|---|
| 105 | // then the remaining bytes are '\0'.) | 
|---|
| 106 |  | 
|---|
| 107 | Groupsock* RTCPgs() const { return fRTCPInterface.gs(); } | 
|---|
| 108 |  | 
|---|
| 109 | void setStreamSocket(int sockNum, unsigned char streamChannelId); | 
|---|
| 110 | void addStreamSocket(int sockNum, unsigned char streamChannelId); | 
|---|
| 111 | void removeStreamSocket(int sockNum, unsigned char streamChannelId) { | 
|---|
| 112 | fRTCPInterface.removeStreamSocket(sockNum, streamChannelId); | 
|---|
| 113 | } | 
|---|
| 114 | // hacks to allow sending RTP over TCP (RFC 2236, section 10.12) | 
|---|
| 115 |  | 
|---|
| 116 | void setAuxilliaryReadHandler(AuxHandlerFunc* handlerFunc, | 
|---|
| 117 | void* handlerClientData) { | 
|---|
| 118 | fRTCPInterface.setAuxilliaryReadHandler(handlerFunc, | 
|---|
| 119 | handlerClientData); | 
|---|
| 120 | } | 
|---|
| 121 |  | 
|---|
| 122 | void injectReport(u_int8_t const* packet, unsigned packetSize, struct sockaddr_in const& fromAddress); | 
|---|
| 123 | // Allows an outside party to inject an RTCP report (from other than the network interface) | 
|---|
| 124 |  | 
|---|
| 125 | protected: | 
|---|
| 126 | RTCPInstance(UsageEnvironment& env, Groupsock* RTPgs, unsigned totSessionBW, | 
|---|
| 127 | unsigned char const* cname, | 
|---|
| 128 | RTPSink* sink, RTPSource* source, | 
|---|
| 129 | Boolean isSSMSource); | 
|---|
| 130 | // called only by createNew() | 
|---|
| 131 | virtual ~RTCPInstance(); | 
|---|
| 132 |  | 
|---|
| 133 | virtual void noteArrivingRR(struct sockaddr_in const& fromAddressAndPort, | 
|---|
| 134 | int tcpSocketNum, unsigned char tcpStreamChannelId); | 
|---|
| 135 |  | 
|---|
| 136 | void incomingReportHandler1(); | 
|---|
| 137 |  | 
|---|
| 138 | private: | 
|---|
| 139 | // redefined virtual functions: | 
|---|
| 140 | virtual Boolean isRTCPInstance() const; | 
|---|
| 141 |  | 
|---|
| 142 | private: | 
|---|
| 143 | Boolean addReport(Boolean alwaysAdd = False); | 
|---|
| 144 | void addSR(); | 
|---|
| 145 | void addRR(); | 
|---|
| 146 | void enqueueCommonReportPrefix(unsigned char packetType, u_int32_t SSRC, | 
|---|
| 147 | unsigned  = 0); | 
|---|
| 148 | void enqueueCommonReportSuffix(); | 
|---|
| 149 | void enqueueReportBlock(RTPReceptionStats* receptionStats); | 
|---|
| 150 | void addSDES(); | 
|---|
| 151 | void addBYE(char const* reason); | 
|---|
| 152 |  | 
|---|
| 153 | void sendBuiltPacket(); | 
|---|
| 154 |  | 
|---|
| 155 | static void onExpire(RTCPInstance* instance); | 
|---|
| 156 | void onExpire1(); | 
|---|
| 157 |  | 
|---|
| 158 | static void incomingReportHandler(RTCPInstance* instance, int /*mask*/); | 
|---|
| 159 | void processIncomingReport(unsigned packetSize, struct sockaddr_in const& fromAddressAndPort, | 
|---|
| 160 | int tcpSocketNum, unsigned char tcpStreamChannelId); | 
|---|
| 161 | void onReceive(int typeOfPacket, int totPacketSize, u_int32_t ssrc); | 
|---|
| 162 |  | 
|---|
| 163 | private: | 
|---|
| 164 | u_int8_t* fInBuf; | 
|---|
| 165 | unsigned fNumBytesAlreadyRead; | 
|---|
| 166 | OutPacketBuffer* fOutBuf; | 
|---|
| 167 | RTPInterface fRTCPInterface; | 
|---|
| 168 | unsigned fTotSessionBW; | 
|---|
| 169 | RTPSink* fSink; | 
|---|
| 170 | RTPSource* fSource; | 
|---|
| 171 | Boolean fIsSSMSource; | 
|---|
| 172 |  | 
|---|
| 173 | SDESItem fCNAME; | 
|---|
| 174 | RTCPMemberDatabase* fKnownMembers; | 
|---|
| 175 | unsigned fOutgoingReportCount; // used for SSRC member aging | 
|---|
| 176 |  | 
|---|
| 177 | double fAveRTCPSize; | 
|---|
| 178 | int fIsInitial; | 
|---|
| 179 | double fPrevReportTime; | 
|---|
| 180 | double fNextReportTime; | 
|---|
| 181 | int fPrevNumMembers; | 
|---|
| 182 |  | 
|---|
| 183 | int fLastSentSize; | 
|---|
| 184 | int fLastReceivedSize; | 
|---|
| 185 | u_int32_t fLastReceivedSSRC; | 
|---|
| 186 | int fTypeOfEvent; | 
|---|
| 187 | int fTypeOfPacket; | 
|---|
| 188 | Boolean fHaveJustSentPacket; | 
|---|
| 189 | unsigned fLastPacketSentSize; | 
|---|
| 190 |  | 
|---|
| 191 | TaskFunc* fByeHandlerTask; | 
|---|
| 192 | ByeWithReasonHandlerFunc* fByeWithReasonHandlerTask; | 
|---|
| 193 | void* fByeHandlerClientData; | 
|---|
| 194 | Boolean fByeHandleActiveParticipantsOnly; | 
|---|
| 195 | TaskFunc* fSRHandlerTask; | 
|---|
| 196 | void* fSRHandlerClientData; | 
|---|
| 197 | TaskFunc* fRRHandlerTask; | 
|---|
| 198 | void* fRRHandlerClientData; | 
|---|
| 199 | AddressPortLookupTable* fSpecificRRHandlerTable; | 
|---|
| 200 | RTCPAppHandlerFunc* fAppHandlerTask; | 
|---|
| 201 | void* fAppHandlerClientData; | 
|---|
| 202 |  | 
|---|
| 203 | public: // because this stuff is used by an external "C" function | 
|---|
| 204 | void schedule(double nextTime); | 
|---|
| 205 | void reschedule(double nextTime); | 
|---|
| 206 | void sendReport(); | 
|---|
| 207 | void sendBYE(char const* reason = NULL); | 
|---|
| 208 | int typeOfEvent() {return fTypeOfEvent;} | 
|---|
| 209 | int sentPacketSize() {return fLastSentSize;} | 
|---|
| 210 | int packetType() {return fTypeOfPacket;} | 
|---|
| 211 | int receivedPacketSize() {return fLastReceivedSize;} | 
|---|
| 212 | int checkNewSSRC(); | 
|---|
| 213 | void removeLastReceivedSSRC(); | 
|---|
| 214 | void removeSSRC(u_int32_t ssrc, Boolean alsoRemoveStats); | 
|---|
| 215 | }; | 
|---|
| 216 |  | 
|---|
| 217 | // RTCP packet types: | 
|---|
| 218 | const unsigned char RTCP_PT_SR = 200; | 
|---|
| 219 | const unsigned char RTCP_PT_RR = 201; | 
|---|
| 220 | const unsigned char RTCP_PT_SDES = 202; | 
|---|
| 221 | const unsigned char RTCP_PT_BYE = 203; | 
|---|
| 222 | const unsigned char RTCP_PT_APP = 204; | 
|---|
| 223 | const unsigned char RTCP_PT_RTPFB = 205; // Generic RTP Feedback [RFC4585] | 
|---|
| 224 | const unsigned char RTCP_PT_PSFB = 206; // Payload-specific [RFC4585] | 
|---|
| 225 | const unsigned char RTCP_PT_XR = 207; // extended report [RFC3611] | 
|---|
| 226 | const unsigned char RTCP_PT_AVB = 208; // AVB RTCP packet ["Standard for Layer 3 Transport Protocol for Time Sensitive Applications in Local Area Networks." Work in progress.] | 
|---|
| 227 | const unsigned char RTCP_PT_RSI = 209; // Receiver Summary Information [RFC5760] | 
|---|
| 228 | const unsigned char RTCP_PT_TOKEN = 210; // Port Mapping [RFC6284] | 
|---|
| 229 | const unsigned char RTCP_PT_IDMS = 211; // IDMS Settings [RFC7272] | 
|---|
| 230 |  | 
|---|
| 231 | // SDES tags: | 
|---|
| 232 | const unsigned char RTCP_SDES_END = 0; | 
|---|
| 233 | const unsigned char RTCP_SDES_CNAME = 1; | 
|---|
| 234 | const unsigned char RTCP_SDES_NAME = 2; | 
|---|
| 235 | const unsigned char RTCP_SDES_EMAIL = 3; | 
|---|
| 236 | const unsigned char RTCP_SDES_PHONE = 4; | 
|---|
| 237 | const unsigned char RTCP_SDES_LOC = 5; | 
|---|
| 238 | const unsigned char RTCP_SDES_TOOL = 6; | 
|---|
| 239 | const unsigned char RTCP_SDES_NOTE = 7; | 
|---|
| 240 | const unsigned char RTCP_SDES_PRIV = 8; | 
|---|
| 241 |  | 
|---|
| 242 | #endif | 
|---|
| 243 |  | 
|---|