1 // Copyright (C) 2001-2015 Federico Montesino Pouzols <fedemp@altern.org>.
2 //
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation; either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public License
14 // along with GNU ccRTP.  If not, see <http://www.gnu.org/licenses/>.
15 //
16 // As a special exception, you may use this file as part of a free software
17 // library without restriction.  Specifically, if other files instantiate
18 // templates or use macros or inline functions from this file, or you compile
19 // this file and link it with other files to produce an executable, this
20 // file does not by itself cause the resulting executable to be covered by
21 // the GNU General Public License.  This exception does not however
22 // invalidate any other reasons why the executable file might be covered by
23 // the GNU General Public License.
24 //
25 // This exception applies only to the code released under the name GNU
26 // ccRTP.  If you copy code from other releases into a copy of GNU
27 // ccRTP, as the General Public License permits, the exception does
28 // not apply to the code that you add in this way.  To avoid misleading
29 // anyone as to the status of such modified files, you must delete
30 // this exception notice from them.
31 //
32 // If you write modifications of your own for GNU ccRTP, it is your choice
33 // whether to permit this exception to apply to your modifications.
34 // If you do not wish that, delete this exception notice.
35 //
36 
37 #ifndef CCXX_RTP_RTCPPKT_H_
38 #define CCXX_RTP_RTCPPKT_H_
39 
40 #include <ccrtp/base.h>
41 
42 NAMESPACE_COMMONCPP
43 
44 /**
45  * @file rtcppkt.h
46  *
47  * @short RTCP packets handling.
48  **/
49 
50 /**
51  * @defgroup rtcppacket RTCP compound packets manipulation.
52  * @{
53  **/
54 
55 /**
56  * @enum SDESItemType
57  * @short SDES items that may be carried in a Source DEScription RTCP packet.
58  *
59  * CNAME is mandatory in each RTCP compound packet (except when
60  * splitted for partial encryption), the others are optional and have
61  * different sending frequencies, though with recommended default
62  * values.
63  **/
64 typedef enum
65 {
66     SDESItemTypeEND = 0,         ///< END of SDES item list.
67     SDESItemTypeCNAME,           ///< Canonical end-point identifier.
68     SDESItemTypeNAME,            ///< Personal NAME of the user.
69     SDESItemTypeEMAIL,           ///< EMAIL address of the user.
70     SDESItemTypePHONE,           ///< Phone number of the user.
71     SDESItemTypeLOC,             ///< Location where the user is.
72     SDESItemTypeTOOL,            ///< Application or tool.
73     SDESItemTypeNOTE,            ///< Comment usually reporting state.
74     SDESItemTypePRIV,            ///< Private extension.
75     SDESItemTypeH323CADDR,       ///< H323 callable address.
76     SDESItemTypeLast = SDESItemTypeH323CADDR ///< Last defined code.
77 }       SDESItemType;
78 
79 /**
80  * @class RTCPCompoundHandler
81  * @short low level structs and RTCP packet parsing and building
82  * methods.
83  *
84  * Intended to be used, through inheritance, in RTCP management
85  * classes, such as QueueRTCPManager.
86  *
87  * @author Federico Montesino Pouzols <fedemp@altern.org>
88  **/
89 class __EXPORT RTCPCompoundHandler
90 {
91 public:
setPathMTU(uint16 mtu)92     inline void setPathMTU(uint16 mtu)
93     { pathMTU = mtu; }
94 
getPathMTU()95     inline uint16 getPathMTU()
96     { return pathMTU; }
97 
98 #ifdef  CCXX_PACKED
99 #pragma pack(1)
100 #endif
101     /**
102      * @struct ReceiverInfo
103      *
104      * Struct for the data contained in a receiver info
105      * block. Receiver info blocks can be found in SR (sender
106      * report) or RR (receiver report) RTCP packets.
107      **/
108     struct ReceiverInfo
109     {
110         uint8 fractionLost;      ///< packet fraction lost.
111         uint8 lostMSB;           ///< cumulative lost MSB of 3 octets.
112         uint16 lostLSW;          ///< cumulative lost two LSB.
113         uint32 highestSeqNum;    ///< highest sequence number.
114         uint32 jitter;           ///< arrival jitter.
115         uint32 lsr;              ///< last sender report timestamp.
116         uint32 dlsr;             ///< delay since last sender report.
117     };
118 
119     /**
120      * @struct RRBlock
121      *
122      * Struct for a receiver info block in a SR (sender report) or an RR
123      * (receiver report) RTCP packet.
124      **/
125     struct RRBlock
126     {
127         uint32 ssrc;                   ///< source identifier.
128         ReceiverInfo rinfo;            ///< info about the source.
129     };
130 
131     /**
132      * @struct RecvReport
133      *
134      * @short raw structure of the source and every receiver report in an
135      * SR or RR RTCP packet.
136      **/
137     struct RecvReport
138     {
139         uint32 ssrc;                 ///< source identifier.
140         RRBlock blocks[1];           ///< receiver report blocks.
141     };
142 
143     /**
144      * @struct SenderInfo
145      *
146      * Struct for the sender info block in a SR (sender report)
147      * RTCP packet.
148      **/
149     struct SenderInfo
150     {
151         uint32 NTPMSW;              ///< NTP timestamp higher octets.
152         uint32 NTPLSW;              ///< NTP timestamp lower octets.
153         uint32 RTPTimestamp;        ///< RTP timestamp.
154         uint32 packetCount;         ///< cumulative packet counter.
155         uint32 octetCount;          ///< cumulative octet counter.
156     };
157 
158     /**
159      * @struct SendReport
160      *
161      * Struct for SR (sender report) RTCP packets.
162      **/
163     struct SendReport
164     {
165         uint32 ssrc;       ///< source identifier.
166         SenderInfo sinfo;  ///< actual sender info.
167         RRBlock blocks[1]; ///< possibly several receiver info blocks.
168     };
169 
170     /**
171      * @struct SDESItem
172      *
173      * Struct for an item description of a SDES packet.
174      **/
175     struct SDESItem
176     {
177         uint8 type;       ///< item identifier.
178         uint8 len;        ///< item len in octets.
179         char data[1];     ///< item content.
180     };
181 
182     /**
183      * @struct SDESChunk
184      *
185      * Struct for a chunk of items in a SDES RTCP packet.
186      **/
187     struct SDESChunk
188     {
getSSRCSDESChunk189         uint32 getSSRC() const
190         { return (ntohl(ssrc)); }
191 
192         uint32 ssrc;      ///< SSRC identifer from sender.
193         SDESItem item;    ///< SDES item from sender.
194     };
195 
196     /**
197      * @struct BYEPacket
198      *
199      * @short Struct for BYE (leaving session) RTCP packets.
200      **/
201     struct BYEPacket
202     {
203         uint32 ssrc;          ///< ssrc identifier of source leaving.
204         uint8 length;         ///< [optional] length of reason.
205     };
206 
207     /**
208      * @struct APPPacket
209      *
210      * @short Struct for APP (application specific) RTCP packets.
211      **/
212     struct APPPacket
213     {
214         uint32 ssrc;           ///< ssrc identifier of source.
215         char name [4];         ///< Name of the APP packet,
216                        ///interpreted as a sequence of
217                        ///four characters.
218         unsigned char data[1]; ///< application dependent data.
219     };
220 
221     /**
222      * @struct FIRPacket
223      *
224      * @short Struct for Full Intra-frame Request (FIR) RTCP
225      * packet. Specific for H.261 sessions (see RFC 2032).
226      **/
227     struct FIRPacket
228     {
229         uint32 ssrc;           ///< ssrc identifier of source.
230     };
231 
232     /**
233      * @struct NACKPacket
234      *
235      * @short Struct for Negative ACKnowledgements (NACK) RTCP
236      * packet. Specific for H.261 sessions (see RFC 2032).
237      **/
238     struct NACKPacket
239     {
240         uint32 ssrc;           ///< ssrc identifier of source.
241         uint16 fsn;            ///< First Sequence Number lost.
242         uint16 blp;            ///< Bitmask of following Lost Packets.
243     };
244 
245     /**
246      * @struct RTCPFixedHeader
247      * Fixed RTCP packet header. First 32-bit word in any RTCP
248      * packet.
249      */
250     struct RTCPFixedHeader
251     {
252 #if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN
253         ///< For big endian boxes
254         unsigned char version:2;      ///< Version, currently 2.
255         unsigned char padding:1;      ///< Padding bit.
256         unsigned char block_count:5;  ///< Number of RR, SR, or SDES chunks.
257 #else
258         ///< For little endian boxes
259         unsigned char block_count:5;  ///< Number of RR, SR, or SDES chunks.
260         unsigned char padding:1;      ///< Padding bit.
261         unsigned char version:2;      ///< Version, currently 2.
262 #endif
263         uint8 type;    ///< type of RTCP packet.
264         uint16 length; ///< number of 32-bit words in the packet (*minus one*).
265     };
266 
267     /**
268      * @struct RTCPPacket
269      *
270      * @short Struct representing general RTCP packet headers as they are
271      * sent through the network.
272      *
273      * This struct consists of a fixed header, always at the
274      * beginning of any RTCP packet, and a union for all the RTCP
275      * packet types supported.
276      **/
277     struct RTCPPacket
278     {
279         /**
280          * @enum Type rtp.h cc++/rtp.h
281          *
282          * RTCP packet types. They are registered with IANA.
283          */
284         typedef enum {
285             tSR = 200,      ///< Sender Report.
286             tRR,            ///< Receiver Report.
287             tSDES,          ///< Source DEScription.
288             tBYE,           ///< End of participation.
289             tAPP,           ///< APPlication specific.
290             tFIR   = 192,   ///< Full Intra-frame request.
291             tNACK  = 193,   ///< Negative ACK.
292             tXR             ///< Extended Report.
293         }       Type;
294 
295         /**
296          * Get the packet length specified in its header, in
297          * octets and in host order.
298          **/
getLengthRTCPPacket299         uint32 getLength() const
300         { return ((ntohs(fh.length) + 1) << 2); }
301 
302         /**
303          * Get the SSRC identifier specified in the packet
304          * header, in host order.
305          **/
getSSRCRTCPPacket306         uint32 getSSRC()  const
307         { return (ntohl(info.RR.ssrc)); } // SSRC is always the first
308                           // word after fh.
309 
310         RTCPFixedHeader fh;           ///< Fixed RTCP header.
311 
312         // An RTCP packet may be of any of the types defined
313         // above, including APP specific ones.
314         union
315         {
316             SendReport SR;
317             RecvReport RR;
318             SDESChunk SDES;
319             BYEPacket BYE;
320             APPPacket APP;
321             NACKPacket NACK;
322             FIRPacket FIR;
323         }       info;        ///< Union for SR, RR, SDES, BYE and APP
324     };
325 #ifdef  CCXX_PACKED
326 #pragma pack()
327 #endif
328 
329 protected:
330     enum { defaultPathMTU = 1500 };
331 
332     RTCPCompoundHandler(uint16 mtu = defaultPathMTU);
333 
334     ~RTCPCompoundHandler();
335 
336     /**
337      * Perform RTCP compound packet header validity check as
338      * specified in draft-ietv-avt-rtp-new. This method follows
339      * appendix A.2. Correct version, payload type, padding bit
340      * and length of every RTCP packet in the compound are
341      * verified.
342      *
343      * @param len length of the RTCP compound packet in
344      *        the reception buffer
345      * @return whether the header is valid.
346      */
347     bool
348     checkCompoundRTCPHeader(size_t len);
349 
350     // buffer to hold RTCP compound packets being sent. Allocated
351     // in construction time
352     unsigned char* rtcpSendBuffer;
353     // buffer to hold RTCP compound packets being
354     // received. Allocated at construction time
355     unsigned char* rtcpRecvBuffer;
356 
357     friend class RTCPSenderInfo;
358     friend class RTCPReceiverInfo;
359 private:
360     // path MTU. RTCP packets should not be greater than this
361     uint16 pathMTU;
362     // masks for RTCP header validation;
363     static const uint16 RTCP_VALID_MASK;
364     static const uint16 RTCP_VALID_VALUE;
365 };
366 
367 /**
368  * @class RTCPReceiverInfo
369  * @short Report block information of SR/RR RTCP reports.
370  *
371  * @author Federico Montesino Pouzols <fedemp@altern.org>
372  **/
373 class __EXPORT RTCPReceiverInfo
374 {
375 public:
RTCPReceiverInfo(void * ri)376     RTCPReceiverInfo(void* ri)
377     { memcpy(&receiverInfo,&ri,
378          sizeof(RTCPCompoundHandler::ReceiverInfo));}
379 
RTCPReceiverInfo(RTCPCompoundHandler::ReceiverInfo & si)380         RTCPReceiverInfo(RTCPCompoundHandler::ReceiverInfo& si)
381         : receiverInfo( si )
382         {
383         }
384 
~RTCPReceiverInfo()385     ~RTCPReceiverInfo()
386     { }
387 
388     /**
389      * Get fraction of lost packets, as a number between 0 and
390      * 255.
391      **/
392     inline uint8
getFractionLost()393     getFractionLost() const
394     { return receiverInfo.fractionLost; }
395 
396     inline uint32
getCumulativePacketLost()397     getCumulativePacketLost() const
398     { return ( ((uint32)ntohs(receiverInfo.lostLSW)) +
399            (((uint32)receiverInfo.lostMSB) << 16) ); }
400 
401     inline uint32
getExtendedSeqNum()402     getExtendedSeqNum() const
403     { return ntohl(receiverInfo.highestSeqNum); }
404 
405     /**
406     * Get the statistical variance of the RTP data packets
407     * interarrival time.
408     *
409     * @return Interarrival jitter, in timestamp units.
410     **/
411     uint32
getJitter()412     getJitter() const
413     { return ntohl(receiverInfo.jitter); }
414 
415     /**
416      * Get the integer part of the NTP timestamp of the last SR
417      * RTCP packet received from the source this receiver report
418      * refers to.
419      **/
420     uint16
getLastSRNTPTimestampInt()421     getLastSRNTPTimestampInt() const
422     { return (uint16)((ntohl(receiverInfo.lsr) & 0xFFFF0000) >> 16); }
423 
424     /**
425      * Get the fractional part of the NTP timestamp of the last SR
426      * RTCP packet received from the source this receiver report
427      * refers to.
428      **/
429     uint16
getLastSRNTPTimestampFrac()430     getLastSRNTPTimestampFrac() const
431     { return (uint16)(ntohl(receiverInfo.lsr) & 0xFFFF); }
432 
433     /**
434      * Get the delay between the last SR packet received and the
435      * transmission of this report.
436      *
437      * @return Delay, in units of 1/65536 seconds
438      **/
439     uint32
getDelayLastSR()440     getDelayLastSR() const
441     { return ntohl(receiverInfo.dlsr); }
442 
443 private:
444     RTCPCompoundHandler::ReceiverInfo receiverInfo;
445 };
446 
447 /**
448  * @class RTCPSenderInfo
449  * @short Sender block information of SR RTCP reports.
450  *
451  * @author Federico Montesino Pouzols <fedemp@altern.org>
452  **/
453 class __EXPORT RTCPSenderInfo
454 {
455 public:
RTCPSenderInfo(void * si)456     RTCPSenderInfo(void* si)
457     { memcpy(&senderInfo,&si,
458          sizeof(RTCPCompoundHandler::SenderInfo));}
459 
RTCPSenderInfo(RTCPCompoundHandler::SenderInfo & si)460         RTCPSenderInfo(RTCPCompoundHandler::SenderInfo& si)
461         : senderInfo( si )
462         {
463         }
464 
~RTCPSenderInfo()465     ~RTCPSenderInfo()
466     { }
467 
468     /**
469      * Get integer part of the NTP timestamp of this packet.
470      * @see NTP2Timeval
471      **/
472     uint32
getNTPTimestampInt()473     getNTPTimestampInt() const
474     { return ntohl(senderInfo.NTPMSW); }
475 
476     /**
477      * Get fractional part of the NTP timestamp of this packet.
478      * @see NTP2Timeval
479      **/
480     uint32
getNTPTimestampFrac()481     getNTPTimestampFrac() const
482     { return ntohl(senderInfo.NTPLSW); }
483 
484     inline uint32
getRTPTimestamp()485     getRTPTimestamp() const
486     { return ntohl(senderInfo.RTPTimestamp); }
487 
488     /**
489      * Get count of sent data packets.
490      **/
491     inline uint32
getPacketCount()492     getPacketCount() const
493     { return ntohl(senderInfo.packetCount); }
494 
495     inline uint32
getOctetCount()496     getOctetCount() const
497     { return ntohl(senderInfo.octetCount); }
498 
499 private:
500     RTCPCompoundHandler::SenderInfo senderInfo;
501 };
502 
503 /**
504  * Convert a NTP timestamp, expressed as two 32-bit long words, into a
505  * timeval value.
506  *
507  * @param msw Integer part of NTP timestamp.
508  * @param lsw Fractional part of NTP timestamp.
509  * @return timeval value corresponding to the given NTP timestamp.
510  **/
511 timeval
512 NTP2Timeval(uint32 msw, uint32 lsw);
513 
514 /**
515  * Convert a time interval, expressed as a timeval, into a 32-bit time
516  * interval expressed in units of 1/65536 seconds.
517  *
518  * @param t Timeval interval.
519  * @return 32-bit value corresponding to the given timeval interval.
520  **/
521 uint32
522 timevalIntervalTo65536(timeval& t);
523 
524 /** @}*/ // rtcppacket
525 
526 END_NAMESPACE
527 
528 #endif  // ndef CCXX_RTP_RTCPPKT_H_
529 
530 /** EMACS **
531  * Local variables:
532  * mode: c++
533  * c-basic-offset: 8
534  * End:
535  */
536 
537