| /********** |
| This library is free software; you can redistribute it and/or modify it under |
| the terms of the GNU Lesser General Public License as published by the |
| Free Software Foundation; either version 3 of the License, or (at your |
| option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.) |
| |
| This library is distributed in the hope that it will be useful, but WITHOUT |
| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for |
| more details. |
| |
| You should have received a copy of the GNU Lesser General Public License |
| along with this library; if not, write to the Free Software Foundation, Inc., |
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| **********/ |
| // "liveMedia" |
| // Copyright (c) 1996-2020 Live Networks, Inc. All rights reserved. |
| // RTCP |
| // C++ header |
| |
| #ifndef _RTCP_HH |
| #define _RTCP_HH |
| |
| #ifndef _RTP_SINK_HH |
| #include "RTPSink.hh" |
| #endif |
| #ifndef _RTP_SOURCE_HH |
| #include "RTPSource.hh" |
| #endif |
| #ifndef _SRTP_CRYPTOGRAPHIC_CONTEXT_HH |
| #include "SRTPCryptographicContext.hh" |
| #endif |
| |
| class SDESItem { |
| public: |
| SDESItem(unsigned char tag, unsigned char const* value); |
| |
| unsigned char const* data() const {return fData;} |
| unsigned totalSize() const; |
| |
| private: |
| unsigned char fData[2 + 0xFF]; // first 2 bytes are tag and length |
| }; |
| |
| typedef void RTCPAppHandlerFunc(void* clientData, |
| u_int8_t subtype, u_int32_t nameBytes/*big-endian order*/, |
| u_int8_t* appDependentData, unsigned appDependentDataSize); |
| |
| class RTCPMemberDatabase; // forward |
| |
| typedef void ByeWithReasonHandlerFunc(void* clientData, char const* reason); |
| |
| class RTCPInstance: public Medium { |
| public: |
| static RTCPInstance* createNew(UsageEnvironment& env, Groupsock* RTCPgs, |
| unsigned totSessionBW, /* in kbps */ |
| unsigned char const* cname, |
| RTPSink* sink, |
| RTPSource* source, |
| Boolean isSSMTransmitter = False, |
| SRTPCryptographicContext* crypto = NULL); |
| |
| static Boolean lookupByName(UsageEnvironment& env, char const* instanceName, |
| RTCPInstance*& resultInstance); |
| |
| unsigned numMembers() const; |
| unsigned totSessionBW() const { return fTotSessionBW; } |
| |
| void setByeHandler(TaskFunc* handlerTask, void* clientData, |
| Boolean handleActiveParticipantsOnly = True); |
| // Assigns a handler routine to be called if a "BYE" arrives. |
| // The handler is called once only; for subsequent "BYE"s, |
| // "setByeHandler()" would need to be called again. |
| // If "handleActiveParticipantsOnly" is True, then the handler is called |
| // only if the SSRC is for a known sender (if we have a "RTPSource"), |
| // or if the SSRC is for a known receiver (if we have a "RTPSink"). |
| // This prevents (for example) the handler for a multicast receiver being |
| // called if some other multicast receiver happens to exit. |
| // If "handleActiveParticipantsOnly" is False, then the handler is called |
| // for any incoming RTCP "BYE". |
| // (To remove an existing "BYE" handler, call "setByeHandler()" again, with a "handlerTask" of NULL.) |
| void setByeWithReasonHandler(ByeWithReasonHandlerFunc* handlerTask, void* clientData, |
| Boolean handleActiveParticipantsOnly = True); |
| // Like "setByeHandler()", except that a string 'reason for the bye' (received as part of |
| // the RTCP "BYE" packet) is passed to the handler function (along with "clientData"). |
| // (The 'reason' parameter to the handler function will be a dynamically-allocated string, |
| // or NULL, and should be delete[]d by the handler function.) |
| void setSRHandler(TaskFunc* handlerTask, void* clientData); |
| void setRRHandler(TaskFunc* handlerTask, void* clientData); |
| // Assigns a handler routine to be called if a "SR" or "RR" packet |
| // (respectively) arrives. Unlike "setByeHandler()", the handler will |
| // be called once for each incoming "SR" or "RR". (To turn off handling, |
| // call the function again with "handlerTask" (and "clientData") as NULL.) |
| void setSpecificRRHandler(netAddressBits fromAddress, Port fromPort, |
| TaskFunc* handlerTask, void* clientData); |
| // Like "setRRHandler()", but applies only to "RR" packets that come from |
| // a specific source address and port. (Note that if both a specific |
| // and a general "RR" handler function is set, then both will be called.) |
| void unsetSpecificRRHandler(netAddressBits fromAddress, Port fromPort); // equivalent to setSpecificRRHandler(..., NULL, NULL); |
| void setAppHandler(RTCPAppHandlerFunc* handlerTask, void* clientData); |
| // Assigns a handler routine to be called whenever an "APP" packet arrives. (To turn off |
| // handling, call the function again with "handlerTask" (and "clientData") as NULL.) |
| void sendAppPacket(u_int8_t subtype, char const* name, |
| u_int8_t* appDependentData, unsigned appDependentDataSize); |
| // Sends a custom RTCP "APP" packet to the peer(s). The parameters correspond to their |
| // respective fields as described in the RTP/RTCP definition (RFC 3550). |
| // Note that only the low-order 5 bits of "subtype" are used, and only the first 4 bytes |
| // of "name" are used. (If "name" has fewer than 4 bytes, or is NULL, |
| // then the remaining bytes are '\0'.) |
| |
| Groupsock* RTCPgs() const { return fRTCPInterface.gs(); } |
| |
| void setStreamSocket(int sockNum, unsigned char streamChannelId); |
| void addStreamSocket(int sockNum, unsigned char streamChannelId); |
| void removeStreamSocket(int sockNum, unsigned char streamChannelId) { |
| fRTCPInterface.removeStreamSocket(sockNum, streamChannelId); |
| } |
| // hacks to allow sending RTP over TCP (RFC 2236, section 10.12) |
| |
| void setAuxilliaryReadHandler(AuxHandlerFunc* handlerFunc, |
| void* handlerClientData) { |
| fRTCPInterface.setAuxilliaryReadHandler(handlerFunc, |
| handlerClientData); |
| } |
| |
| void injectReport(u_int8_t const* packet, unsigned packetSize, struct sockaddr_in const& fromAddress); |
| // Allows an outside party to inject an RTCP report (from other than the network interface) |
| |
| protected: |
| RTCPInstance(UsageEnvironment& env, Groupsock* RTPgs, unsigned totSessionBW, |
| unsigned char const* cname, |
| RTPSink* sink, RTPSource* source, |
| Boolean isSSMTransmitter, |
| SRTPCryptographicContext* crypto); |
| // called only by createNew() |
| virtual ~RTCPInstance(); |
| |
| virtual void noteArrivingRR(struct sockaddr_in const& fromAddressAndPort, |
| int tcpSocketNum, unsigned char tcpStreamChannelId); |
| |
| void incomingReportHandler1(); |
| |
| private: |
| // redefined virtual functions: |
| virtual Boolean isRTCPInstance() const; |
| |
| private: |
| Boolean addReport(Boolean alwaysAdd = False); |
| void addSR(); |
| void addRR(); |
| void enqueueCommonReportPrefix(unsigned char packetType, u_int32_t SSRC, |
| unsigned numExtraWords = 0); |
| void enqueueCommonReportSuffix(); |
| void enqueueReportBlock(RTPReceptionStats* receptionStats); |
| void addSDES(); |
| void addBYE(char const* reason); |
| |
| void sendBuiltPacket(); |
| |
| static void onExpire(RTCPInstance* instance); |
| void onExpire1(); |
| |
| static void incomingReportHandler(RTCPInstance* instance, int /*mask*/); |
| void processIncomingReport(unsigned packetSize, struct sockaddr_in const& fromAddressAndPort, |
| int tcpSocketNum, unsigned char tcpStreamChannelId); |
| void onReceive(int typeOfPacket, int totPacketSize, u_int32_t ssrc); |
| |
| private: |
| u_int8_t* fInBuf; |
| unsigned fNumBytesAlreadyRead; |
| OutPacketBuffer* fOutBuf; |
| RTPInterface fRTCPInterface; |
| unsigned fTotSessionBW; |
| RTPSink* fSink; |
| RTPSource* fSource; |
| Boolean fIsSSMTransmitter; |
| SRTPCryptographicContext* fCrypto; |
| |
| SDESItem fCNAME; |
| RTCPMemberDatabase* fKnownMembers; |
| unsigned fOutgoingReportCount; // used for SSRC member aging |
| |
| double fAveRTCPSize; |
| int fIsInitial; |
| double fPrevReportTime; |
| double fNextReportTime; |
| int fPrevNumMembers; |
| |
| int fLastSentSize; |
| int fLastReceivedSize; |
| u_int32_t fLastReceivedSSRC; |
| int fTypeOfEvent; |
| int fTypeOfPacket; |
| Boolean fHaveJustSentPacket; |
| unsigned fLastPacketSentSize; |
| |
| TaskFunc* fByeHandlerTask; |
| ByeWithReasonHandlerFunc* fByeWithReasonHandlerTask; |
| void* fByeHandlerClientData; |
| Boolean fByeHandleActiveParticipantsOnly; |
| TaskFunc* fSRHandlerTask; |
| void* fSRHandlerClientData; |
| TaskFunc* fRRHandlerTask; |
| void* fRRHandlerClientData; |
| AddressPortLookupTable* fSpecificRRHandlerTable; |
| RTCPAppHandlerFunc* fAppHandlerTask; |
| void* fAppHandlerClientData; |
| |
| public: // because this stuff is used by an external "C" function |
| void schedule(double nextTime); |
| void reschedule(double nextTime); |
| void sendReport(); |
| void sendBYE(char const* reason = NULL); |
| int typeOfEvent() {return fTypeOfEvent;} |
| int sentPacketSize() {return fLastSentSize;} |
| int packetType() {return fTypeOfPacket;} |
| int receivedPacketSize() {return fLastReceivedSize;} |
| int checkNewSSRC(); |
| void removeLastReceivedSSRC(); |
| void removeSSRC(u_int32_t ssrc, Boolean alsoRemoveStats); |
| }; |
| |
| // RTCP packet types: |
| const unsigned char RTCP_PT_SR = 200; |
| const unsigned char RTCP_PT_RR = 201; |
| const unsigned char RTCP_PT_SDES = 202; |
| const unsigned char RTCP_PT_BYE = 203; |
| const unsigned char RTCP_PT_APP = 204; |
| const unsigned char RTCP_PT_RTPFB = 205; // Generic RTP Feedback [RFC4585] |
| const unsigned char RTCP_PT_PSFB = 206; // Payload-specific [RFC4585] |
| const unsigned char RTCP_PT_XR = 207; // extended report [RFC3611] |
| 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.] |
| const unsigned char RTCP_PT_RSI = 209; // Receiver Summary Information [RFC5760] |
| const unsigned char RTCP_PT_TOKEN = 210; // Port Mapping [RFC6284] |
| const unsigned char RTCP_PT_IDMS = 211; // IDMS Settings [RFC7272] |
| |
| // SDES tags: |
| const unsigned char RTCP_SDES_END = 0; |
| const unsigned char RTCP_SDES_CNAME = 1; |
| const unsigned char RTCP_SDES_NAME = 2; |
| const unsigned char RTCP_SDES_EMAIL = 3; |
| const unsigned char RTCP_SDES_PHONE = 4; |
| const unsigned char RTCP_SDES_LOC = 5; |
| const unsigned char RTCP_SDES_TOOL = 6; |
| const unsigned char RTCP_SDES_NOTE = 7; |
| const unsigned char RTCP_SDES_PRIV = 8; |
| |
| #endif |