/********** 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 .) 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-2019 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 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 isSSMSource = False); 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 isSSMSource); // 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 fIsSSMSource; 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