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 | |