// Copyright (C) 2002 Federico Montesino Pouzols <fedemp@altern.org>. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // As a special exception, you may use this file as part of a free software // library without restriction. Specifically, if other files instantiate // templates or use macros or inline functions from this file, or you compile // this file and link it with other files to produce an executable, this // file does not by itself cause the resulting executable to be covered by // the GNU General Public License. This exception does not however // invalidate any other reasons why the executable file might be covered by // the GNU General Public License. // // This exception applies only to the code released under the name GNU // ccRTP. If you copy code from other releases into a copy of GNU // ccRTP, as the General Public License permits, the exception does // not apply to the code that you add in this way. To avoid misleading // anyone as to the status of such modified files, you must delete // this exception notice from them. // // If you write modifications of your own for GNU ccRTP, it is your choice // whether to permit this exception to apply to your modifications. // If you do not wish that, delete this exception notice. // #ifndef CCXX_RTP_RTPPKT_H_ #define CCXX_RTP_RTPPKT_H_ #include <ccrtp/base.h> #include <ccrtp/formats.h> #include <ccrtp/CryptoContext.h> #ifdef CCXX_NAMESPACES namespace ost { #endif /** * @file rtppkt.h * * @short RTP packets handling. **/ /** * @defgroup rtppacket RTP data packets manipulation. * @{ **/ /** * @class RTPPacket * @short A base class for both IncomingRTPPkt and OutgoingRTPPkt. * * Provides common low level header structures and related * methods. This class provides an interface that allows for partial * and generic manipulation of RTP data packets. Values are returned * in host order, except raw structures, which are returned as they * are sent through the network. * * @author David Sugar <dyfet@ostel.com> **/ class CryptoContext; class __EXPORT RTPPacket { private: struct RTPFixedHeader; struct RTPHeaderExt; public: /** * Constructor, construct a packet object given the memory * zone its content (header and payload) is stored. Commonly * used to build RTPPacket objects from incoming data. * * @param block whole packet * @param len total length (header + payload + padding) of the * packet * @param duplicate whether to memcopy the packet. At present, * this feature is not used. * @note used in IncomingRTPPkt. **/ RTPPacket(const unsigned char* const block, size_t len, bool duplicate = false); /** * Construct a packet object without specifying its real * content yet. Commonly used for outgoing packets. Header * fields and payload must be filled in by another methods or * by a derived constructor. * * @param hdrlen length of the header (including CSRC and extension). * @param plen payload length. * @param paddinglen pad packet to a multiple of paddinglen * @note used in OutgoingRTPPkt. */ RTPPacket(size_t hdrlen, size_t plen, uint8 paddinglen, CryptoContext* pcc= NULL); /** * Get the length of the header, including contributing * sources identifiers and header extension, if present. * * @return number of octets. **/ inline uint32 getHeaderSize() const { return hdrSize; } /** * @return pointer to the payload section of the packet. **/ inline const uint8* const getPayload() const { return (uint8*)(buffer + getHeaderSize()); } /** * @return length of the payload section, in octets. **/ inline uint32 getPayloadSize() const { return payloadSize; } /** * @return value of the PT header field. **/ inline PayloadType getPayloadType() const { return static_cast<PayloadType>(getHeader()->payload); } /** * @return value of the sequence number header field, in host order. **/ inline uint16 getSeqNum() const { return cachedSeqNum; } /** * @return packet timestamp in host order. **/ inline uint32 getTimestamp() const { return cachedTimestamp; } /** * @return RTP protocol version of packet. **/ inline uint8 getProtocolVersion() const { return getHeader()->version; } /** * Ask whether the packet contains padding bytes at the end * @return true if the header padding bit is 1. **/ inline bool isPadded() const { return getHeader()->padding; } /** * Get the number of octets padding the end of the payload * section. * * @return Padding length in octets. **/ inline uint8 getPaddingSize() const { return buffer[total - 1]; } /** * Ask whether the packet is marked (for isntance, is a new * talk spurt in some audio profiles). * * @return true is the header marker bit is 1. **/ inline bool isMarked() const { return getHeader()->marker; } /** * Ask whether the packet contains header extensions. * * @return true if the header extension bit is 1. **/ inline bool isExtended() const { return getHeader()->extension; } /** * Get the number of contributing sources specified in the * packet header. **/ inline uint16 getCSRCsCount() const { return getHeader()->cc; } /** * Get the 32-bit identifiers of the contributing sources for * the packet as an array, of length getCSRCsCount(). * * @return An array of CSRC identifiers as they are in the * packet (in network order). **/ inline const uint32* getCSRCs() const { return static_cast<const uint32*>(&(getHeader()->sources[1])); } /** * Get the first 16 bits (in network order) of the header of * the RTP header extension. Its meaning is undefined at this * level. * * @return 0 if the packet has no header extension, otherwise * the first 16 bits of the header extension, in * network order. * * @note 0 could be a valid value for the first 16 bits, in * that case RTPPacket::isExtended() should be use. **/ inline uint16 getHdrExtUndefined() const { return (isExtended()? getHeaderExt()->undefined : 0); } /** * Get the length (in octets) of the data contained in the * header extension. Note that this length does not include * the four octets at the beginning of the header extension. * * @return 0 if the packet has no header extension, otherwise * the length. * * @note 0 is a valid value for this field, so * RTPPacket::isExtended() should be used. **/ inline uint32 getHdrExtSize() const { return (isExtended()? (static_cast<uint32>(ntohs(getHeaderExt()->length)) << 2) : 0); } /** * Get the content of the header extension. * * @return NULL if the packet has no header extension, otherwise * a pointer to the packet header extension content. **/ inline const unsigned char* getHdrExtContent() const { return (isExtended() ? (reinterpret_cast<const unsigned char*>(getHeaderExt()) + sizeof(RTPHeaderExt)) : NULL); } /** * Get the raw packet as it will be sent through the network. * * @return memory zone where the raw packet structure is * stored in. **/ inline const unsigned char* const getRawPacket() const { return buffer; } /** * Get the raw packet length, including header, extension, * payload and padding. * * @return size of the raw packet structure. **/ inline uint32 getRawPacketSize() const { return total; } inline uint32 getRawPacketSizeSrtp() const { return total + srtpLength; } inline size_t getSizeOfFixedHeader() const { return sizeof(RTPFixedHeader); } protected: /** * Destructor, free the buffer provided in the constructor. **/ inline virtual ~RTPPacket() { endPacket(); } /** * Free memory allocated for the packet. **/ void endPacket(); /** * Return low level structure for the header of the packet. * * @return RTPFixedHeader pointer to the header of the packet. **/ inline RTPFixedHeader* getHeader() const { return reinterpret_cast<RTPFixedHeader*>(buffer); } inline void setExtension(bool e) { getHeader()->extension = e; } /** * Get a pointer to RTPHeaderExt pointing after the RTP header * (fixed part plus contributing sources). No check for * for the X bit is done. * * @return header extension if present, garbage if not. **/ inline const RTPHeaderExt* getHeaderExt() const { uint32 fixsize = sizeof(RTPFixedHeader) + (getHeader()->cc << 2); return (reinterpret_cast<RTPHeaderExt*>(buffer + fixsize)); } /** * Obtain the absolute timestamp carried in the packet header. * * @return 32-bit timestamp in host order. **/ inline uint32 getRawTimestamp() const { return ntohl(getHeader()->timestamp); } inline void setbuffer(const void* src, size_t len, size_t pos) { memcpy(buffer + pos,src,len); } /// Packet sequence number in host order. uint16 cachedSeqNum; /// Packet timestamp in host order (includes initial shift). uint32 cachedTimestamp; /** * Offset into packet memory pointing to area for SRTP data. * * This offset points to the memory where the SRTP protect will * store the authentication and MKI data. */ uint32 srtpDataOffset; /** * Lebgth of additional SRTP data. * * Covers the SRTP authentication and MKI data. */ int32 srtpLength; /// total length, including header, payload and padding uint32 total; /// note: payload (not full packet) size. uint32 payloadSize; private: /// packet in memory unsigned char* buffer; /// size of the header, including contributing sources and extensions uint32 hdrSize; /// whether the object was contructed with duplicated = true bool duplicated; #ifdef CCXX_PACKED #pragma pack(1) #endif /** * @struct RTPFixedHeader * @short RTP fixed header as it is send through the network. * * A low-level representation for generic RTP packet header as * defined in RFC 1889. A packet consists of the fixed RTP * header, a possibly empty list of contributing sources and * the payload. Header contents are kept in network (big * endian) order. **/ struct RTPFixedHeader { #if __BYTE_ORDER == __BIG_ENDIAN /// For big endian boxes unsigned char version:2; ///< Version, currently 2 unsigned char padding:1; ///< Padding bit unsigned char extension:1; ///< Extension bit unsigned char cc:4; ///< CSRC count unsigned char marker:1; ///< Marker bit unsigned char payload:7; ///< Payload type #else /// For little endian boxes unsigned char cc:4; ///< CSRC count unsigned char extension:1; ///< Extension bit unsigned char padding:1; ///< Padding bit unsigned char version:2; ///< Version, currently 2 unsigned char payload:7; ///< Payload type unsigned char marker:1; ///< Marker bit #endif uint16 sequence; ///< sequence number uint32 timestamp; ///< timestamp uint32 sources[1]; ///< contributing sources }; /** * @struct RFC2833Payload * @short a structure defining RFC2833 Telephony events. * * structure to define RFC2833 telephony events in RTP. You can * use this by recasing the pointer returned by getPayload(). */ public: struct RFC2833Payload { #if __BYTE_ORDER == __BIG_ENDIAN uint8 event : 8; bool ebit : 1; bool rbit : 1; uint8 vol : 6; uint16 duration : 16; #else uint8 event : 8; uint8 vol : 6; bool rbit : 1; bool ebit : 1; uint16 duration : 16; #endif }; private: /** * @struct RTPHeaderExt * * Fixed component of the variable-length header extension, * appended to the fixed header, after the CSRC list, when X * == 1. **/ struct RTPHeaderExt { uint16 undefined; ///< to be defined uint16 length; ///< number of 32-bit words in the extension }; #ifdef CCXX_PACKED #pragma pack() #endif /* definitions for access to most common 2833 fields... */ public: /** * Fetch a raw 2833 packet. * * @return low level 2833 data structure. */ inline struct RFC2833Payload *getRaw2833Payload(void) {return (struct RFC2833Payload *)getPayload();} /** * Fetch 2833 duration field. * * @return 2833 duration in native host machine byte order. */ inline uint16 get2833Duration(void) {return ntohs(getRaw2833Payload()->duration);} /** * Set 2833 duration field. * * @param timestamp to use, native host machine byte order. */ inline void set2833Duration(uint16 timestamp) {getRaw2833Payload()->duration = htons(timestamp);} }; /** * @class OutgoingRTPPkt * @short RTP packets being sent. * * This class is intented to construct packet objects just before they * are inserted into the sending queue, so that they are processed in * a understandable and format independent manner inside the stack. * * @author Federico Montesino Pouzols <fedemp@altern.org> **/ class __EXPORT OutgoingRTPPkt : public RTPPacket { public: /** * Construct a new packet to be sent, containing several * contributing source identifiers, header extensions and * payload. * * A new copy in memory (holding all this components * along with the fixed header) is created. If the pointer * to the SRTP CryptoContext is not NULL and holds a CryptoContext * for the SSRC take the SSRC data into account when computing * the required memory buffer. * * @param csrcs array of countributing source 32-bit * identifiers, in host order. * @param numcsrc number of CSRC identifiers in the array. * @param hdrext whole header extension. * @param hdrextlen size of whole header extension, in octets. * @param data payload. * @param datalen payload length, in octets. * @param paddinglen pad packet to a multiple of paddinglen. * @param pcc Pointer to the SRTP CryptoContext, defaults to NULL * if not specified. * * @note For efficiency purposes, since this constructor is * valid for all packets but is too complex for the common * case, two simpler others are provided. **/ OutgoingRTPPkt(const uint32* const csrcs, uint16 numcsrc, const unsigned char* const hdrext, uint32 hdrextlen, const unsigned char* const data, size_t datalen, uint8 paddinglen= 0, CryptoContext* pcc= NULL); /** * Construct a new packet to be sent, containing several * contributing source identifiers and payload. * * A new copy in * memory (holding all this components along with the fixed * header) is created. If the pointer * to the SRTP CryptoContext is not NULL and holds a CryptoContext * for the SSRC take the SSRC data into account when computing * the required memory buffer. * * @param csrcs array of countributing source 32-bit * identifiers, in host order. * @param numcsrc number of CSRC identifiers in the array. * @param data payload. * @param datalen payload length, in octets. * @param paddinglen pad packet to a multiple of paddinglen. * @param pcc Pointer to the SRTP CryptoContext, defaults to NULL * if not specified. **/ OutgoingRTPPkt(const uint32* const csrcs, uint16 numcsrc, const unsigned char* const data, size_t datalen, uint8 paddinglen= 0, CryptoContext* pcc= NULL); /** * Construct a new packet (fast variant, with no contributing * sources and no header extension) to be sent. * * A new copy in * memory (holding the whole packet) is created. If the pointer * to the SRTP CryptoContext is not NULL and holds a CryptoContext * for the SSRC take the SSRC data into account when computing * the required memory buffer. * * @param data payload. * @param datalen payload length, in octets. * @param paddinglen pad packet to a multiple of paddinglen. * @param pcc Pointer to the SRTP CryptoContext, defaults to NULL * if not specified. **/ OutgoingRTPPkt(const unsigned char* const data, size_t datalen, uint8 paddinglen= 0, CryptoContext* pcc= NULL); ~OutgoingRTPPkt() { } /** * @param pt Packet payload type. **/ inline void setPayloadType(PayloadType pt) { getHeader()->payload = pt; } /** * Sets the sequence number in the header. * * @param seq Packet sequence number, in host order. **/ inline void setSeqNum(uint16 seq) { cachedSeqNum = seq; getHeader()->sequence = htons(seq); } /** * @param pts Packet timestamp, in host order. **/ inline void setTimestamp(uint32 pts) { cachedTimestamp = pts; getHeader()->timestamp = htonl(pts); } /** * Set synchronization source numeric identifier. * * @param ssrc 32-bit Synchronization SouRCe numeric * identifier, in host order. **/ inline void setSSRC(uint32 ssrc) const { getHeader()->sources[0] = htonl(ssrc); } /** * Set synchronization source numeric identifier. Special * version to save endianness conversion. * * @param ssrc 32-bit Synchronization SouRCe numeric * identifier, in network order. **/ inline void setSSRCNetwork(uint32 ssrc) const { getHeader()->sources[0] = ssrc; } /** * Specify the value of the marker bit. By default, the marker * bit of outgoing packets is false/0. This method allows to * explicity specify and change that value. * * @param mark value for the market bit. */ inline void setMarker(bool mark) { getHeader()->marker = mark; } /** * Called packet is setup. * * This private method computes the SRTP data and stores it in the * packet. Then encrypt the payload data (ex padding). */ void protect(uint32 ssrc, CryptoContext* pcc); /** * Outgoing packets are equal if their sequence numbers match. **/ inline bool operator==(const OutgoingRTPPkt &p) const { return ( this->getSeqNum() == p.getSeqNum() ); } /** * Outgoing packets are not equal if their sequence numbers differ. **/ inline bool operator!=(const OutgoingRTPPkt &p) const { return ( this->getSeqNum() != p.getSeqNum() ); } private: /** * Copy constructor from objects of its same kind, declared * private to avoid its use. **/ OutgoingRTPPkt(const OutgoingRTPPkt &o); /** * Assignment operator from objects of its same kind, declared * private to avoid its use. **/ OutgoingRTPPkt& operator=(const OutgoingRTPPkt &o); /** * Set the list of CSRC identifiers in an RTP packet, * switching host to network order. */ void setCSRCArray(const uint32* const csrcs, uint16 numcsrc); }; /** * @class IncomingRTPPkt * * @short RTP packets received from other participants. * * This class is intented to construct a packet object just after * every packet is received by the scheduled queue, so that they are * processed in an understandable and format independent manner inside * the stack. * * @author Federico Montesino Pouzols <fedemp@altern.org> */ class __EXPORT IncomingRTPPkt : public RTPPacket { public: /** * Build an RTP packet object from a data buffer. This * constructor first performs a generic RTP data packet header * check, whose result can be checked via isHeaderValid(). * * @param block pointer to the buffer the whole packet is stored in. * @param len length of the whole packet, expressed in octets. * * @note If check fails, the packet object is * incomplete. checking isHeaderValid() is recommended before * using a new RTPPacket object. **/ IncomingRTPPkt(const unsigned char* block, size_t len); ~IncomingRTPPkt() { } /** * Get validity of this packet * @return whether the header check performed at construction * time ended successfully. **/ inline bool isHeaderValid() { return headerValid; } /** * Get synchronization source numeric identifier. * * @return 32-bits Synchronization SouRCe numeric identifier, * in host order. **/ inline uint32 getSSRC() const { return cachedSSRC; } /** * Unprotect a received packet. * * Perform SRTP processing on this packet. * * @param pcc Pointer to SRTP CryptoContext. * @return * one if no errors, -1 if authentication failed, -2 if * replay check failed */ int32 unprotect(CryptoContext* pcc); /** * Two incoming packets are equal if they come from sources * with the same SSRC and have the same sequence number. **/ inline bool operator==(const IncomingRTPPkt &p) const { return ( (this->getSeqNum() == p.getSeqNum()) && (this->getSSRC() == p.getSSRC()) ); } /** * Two incoming packets are not equal if they come from * different sources or have different sequence numbers. **/ inline bool operator!=(const IncomingRTPPkt &p) const { return !( *this == p ); } private: /** * Copy constructor from objects of its same kind, declared * private to avoid its use. **/ IncomingRTPPkt(const IncomingRTPPkt &ip); /** * Assignment operator from objects of its same kind, declared * private to avoid its use. */ IncomingRTPPkt& operator=(const IncomingRTPPkt &ip); /// Header validity, checked at construction time. bool headerValid; /// SSRC 32-bit identifier in host order. uint32 cachedSSRC; // Masks for RTP header validation: types matching RTCP SR or // RR must be rejected to avoid accepting misaddressed RTCP // packets. static const uint16 RTP_INVALID_PT_MASK; static const uint16 RTP_INVALID_PT_VALUE; }; /** @}*/ // rtppacket #ifdef CCXX_NAMESPACES } #endif #endif // ndef CCXX_RTP_RTPPKT_H_ /** EMACS ** * Local variables: * mode: c++ * c-basic-offset: 8 * End: */