/********** 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 2.1 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-2015 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 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 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(); 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(); void sendBuiltPacket(); static void onExpire(RTCPInstance* instance); void onExpire1(); static void incomingReportHandler(RTCPInstance* instance, int /*mask*/); void incomingReportHandler1(); void processIncomingReport(unsigned packetSize, struct sockaddr_in const& fromAddress, 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; 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(); 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