/*
  Copyright (C) 2006-2009 Werner Dittmann

  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 3 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, see <http://www.gnu.org/licenses/>.
*/

#ifndef _ZRTPQUEUE_H_
#define _ZRTPQUEUE_H_

#include <ccrtp/cqueue.h>
#include <ccrtp/rtppkt.h>
#include <libzrtpcpp/ZrtpCallback.h>
#include <libzrtpcpp/TimeoutProvider.h>
#include <libzrtpcpp/ZrtpConfigure.h>

class ZrtpUserCallback;
class ZRtp;

#ifdef  CCXX_NAMESPACES
namespace ost {
#endif

    /** 
     * GNU ccRTP extension to support GNU ZRTP.
     *
     * ZRTP was developed by Phil Zimmermann and provides functions to
     * negotiate keys and other necessary data (crypto data) to set-up
     * the Secure RTP (SRTP) crypto context. Refer to Phil's ZRTP
     * specification at his <a href="http://zfoneproject.com/">Zfone
     * project</a> site to get more detailed imformation about the
     * capabilities of ZRTP.
     * 
     * <b>Short overview of the ZRTP implementation</b>
     *
     * ZRTP is a specific protocol to negotiate encryption algorithms
     * and the required key material. ZRTP uses a RTP session to
     * exchange its protocol messages.
     *
     * A complete GNU ZRTP implementation consists of two parts, the
     * GNU ZRTP core and specific code that binds the GNU ZRTP core to
     * the underlying RTP/SRTP stack and the operating system:
     * <ul> 
     * <li> 
     *      The GNU ZRTP core is independent of a specific RTP/SRTP
     *      stack and the operationg system and consists of the ZRTP
     *      protocol state engine, the ZRTP protocol messages, and the
     *      GNU ZRTP engine. The GNU ZRTP engine provides methods to
     *      setup ZRTP message and to analyze received ZRTP messages,
     *      to compute the crypto data required for SRTP, and to
     *      maintain the required hashes and HMAC.
     * </li>
     * <li>
     *      The second part of an implementation is specific
     *      <em>glue</em> code the binds the GNU ZRTP core to the
     *      actual RTP/SRTP implementation and other operating system
     *      specific services  such as timers.
     * </li>
     * </ul>
     *
     * The GNU ZRTP core uses a callback interface class (refer to
     * ZrtpCallback) to access RTP/SRTP or operating specific methods,
     * for example to send data via the RTP/SRTP stack, to access
     * timers, provide mutex handling, and to report events to the
     * application.
     *
     * <b>The ZrtpQueue</b>
     *
     * ZrtpQueue implements code that is specific to the GNU ccRTP
     * implementation. ZrtpQueue also implements the specific code to
     * provide the mutex and timeout handling to the GNU ZRTP
     * core. Both, the mutex and the timeout handling, use the GNU
     * Common C++ library to stay independent of the operating
     * seystem. For more information refer to the <a
     * href="http://www.gnutelephony.org/index.php/GNU_Common_C%2B%2B">GNU
     * Common C++</a> web site.
     *
     * To perform its tasks ZrtpQueue
     * <ul>
     * <li> extends GNU ccRTP classes to use the underlying
     *      ccRTP methods and the RTP/SRTP send and receive queues
     * </li>
     * <li> implements the ZrtpCallback interface to provide ccRTP
     *      access and other specific services (timer, mutex) to GNU
     *      ZRTP 
     * </li>
     * <li> provides ZRTP specific methods that applications may use
     *      to control and setup GNU ZRTP
     * </li>
     * <li> can register and use an application specific callback
     *      class (refer to ZrtpUserCallback)
     * </li>
     * </ul>
     *
     * After instantiating a GNU ZRTP session (see below for a short
     * example) applications may use the ZRTP specific methods of
     * ZrtpQueue to control and setup GNU ZRTP, for example enable or
     * disable ZRTP processing or getting ZRTP status information.
     *
     * GNU ZRTP provides a ZrtpUserCallback class that an application
     * may extend and register with ZrtpQueue. GNU ZRTP and ZrtpQueue
     * use the ZrtpUserCallback methods to report ZRTP events to the
     * application. The application may display this information to
     * the user or act otherwise.
     *
     * The following figure depicts the relationships between
     * ZrtpQueue, ccRTP RTP/SRTP implementation, the GNU ZRTP core,
     * and an application that provides an ZrtpUserCallback class.
     *
 @verbatim

                          +----------+
                          |  ccRTP   |
                          | RTP/SRTP |
                          |          |
                          +----------+
                               ^
                               | extends
                               |
 +----------------+      +-----+------+
 |  Application   |      |            |      +-----------------+
 |  instantiates  | uses | ZrtpQueue  | uses |                 |
 | a ZRTP Session +------+ implements +------+    GNU ZRTP     |
 |  and provides  |      |ZrtpCallback|      |      core       |
 |ZrtpUserCallback|      |            |      | implementation  |
 +----------------+      +------------+      |  (ZRtp et al)   |
                                             |                 |
                                             +-----------------+
@endverbatim
     *
     * Because ZrtpQueue extends the ccRTP RTP/SRTP implementation
     * (AVPQueue) all public methods defined by ccRTP are also
     * available for a ZRTP session. ZrtpQueue overwrites some of the
     * public methods of ccRTP (AVPQueue) to implement ZRTP specific
     * code.
     *
     * GNU ZRTP provides a <em>SymmetricZRTPSession</em> type to
     * simplify its use. An application uses this type in the same way
     * as it would use the normal ccRTP <em>SymmetricRTPSession</em>
     * type. The following short code snippets show how an application
     * could instantiate ccRTP and GNU ZRTP sessions. The first
     * snippet shows how to instantiate a ccRTP session:
     *
     * @code
     * ...
     * #include <ccrtp/rtp.h>
     * ...
     *     SymmetricRTPSession tx(pattern.getSsrc(), 
     *                            InetHostAddress("localhost"));
     * ...
     *
     * @endcode
     *
     * The same code as above but using a GNU ZRTP session this time:
     * @code
     * ...
     * #include <libzrtpcpp/zrtpccrtp.h>
     * ...
     *     SymmetricZRTPSession tx(pattern.getSsrc(), 
     *                             InetHostAddress("localhost"));
     * ...
     *
     * @endcode
     *
     * The only differences are the different include statements and
     * the different session types.
     *
     * The <em>demo</em> folder contains a small example that shows
     * how to use GNU ZRTP.
     *
     * Please refer to the GNU ccRTP documentation for a description
     * of ccRTP methods and functions. This ZrtpQueue documentation
     * shows the ZRTP specific extensions and describes overloaded
     * methods and a possible different behaviour.
     *
     * @author Werner Dittmann <Werner.Dittmann@t-online.de>
     */

    class ZrtpQueue : public AVPQueue, ZrtpCallback {

    public:

        /**
         * Initialize the ZrtpQueue.
         *
         * Before an application can use ZRTP it has to initialize the
         * ZRTP implementation. This method initializes the timeout
         * thread and opens a file that contains ZRTP specific
         * information such as the applications ZID (ZRTP id) and its
         * retained shared secrets.
         *
         * If one application requires several ZRTP sessions all
         * sessions use the same timeout thread and use the same ZID
         * file. Therefore an application does not need to do any
         * synchronisation regading ZID files or timeouts. This is
         * managed by the ZRTP implementation.
         *
         * The current implementation of ZrtpQueue does not support
         * different ZID files for one application instance. This
         * restriction may be removed in later versions.
         *
         * The application may specify its own ZID file name. If no
         * ZID file name is specified it defaults to
         * <code>$HOME/.GNUccRTP.zid</code> if the <code>HOME</code>
         * environment variable is set. If it is not set the current
         * directory is used.
         *
         * If the method could set up the timeout thread and open the ZID
         * file then it enables ZRTP processing and returns.
         *
         * @param zidFilename
         *     The name of the ZID file, can be a relative or absolut 
         *     filename.
         *
         * @param autoEnable
         *     if set to true the method automatically sets enableZrtp to
         *     true. This enables the ZRTP auto-sense mode. Default is true.
         *
         * @param config
         *     this parameter points to ZRTP configuration data. If it is
         *     NULL then ZrtpQueue uses a default setting. Default is NULL.
         * 
         * @return 
         *     1 on success, ZRTP processing enabled, -1 on failure,
         *     ZRTP processing disabled.
         *
         */
        int32_t initialize(const char *zidFilename, bool autoEnable = true, 
                           ZrtpConfigure* config = NULL);

        /*
         * Applications use the following methods to control ZRTP, for example
         * to enable ZRTP, set flags etc.
         */

        /**
         * Enable or disable ZRTP processing.
         *
         * Call this method to enable or disable ZRTP processing after
         * calling <code>initialize()</code>. This can be done before
         * using a RTP session or at any time during a RTP session.
         *
         * Existing SRTP sessions or currently active ZRTP processing will
         * not be stopped or disconnected.
         *
         * If the application enables ZRTP then:
         * <ul>
         * <li>ZrtpQueue starts to send ZRTP Hello packets after at least
         * one RTP packet was sent and received on the associated RTP
         * session. Thus if an application enables ZRTP and ZrtpQueue
         * detects traffic on the RTP session then ZrtpQueue automatically
         * starts the ZRTP protocol. This automatic start is convenient
         * for applications that negotiate RTP parameters and set up RTP
         * sessions but the actual RTP traffic starts some time later.
         * </li>
         * <li>ZrtpQueue analyses incoming packets to detect ZRTP
         * messages. If ZRTP was started, either via automatic start (see
         * above) or explicitly via startZrtp(), then ZrtpQueue
         * forwards ZRTP packets to the GNU ZRTP core.
         * </ul>
         *
         * @param onOff
         *     @c true to enable ZRTP, @c false to disable ZRTP
         */
        void setEnableZrtp(bool onOff);

        /**
         * Return the state of ZRTP enable state.
         *
         * @return @c true if ZRTP processing is enabled, @c false
         * otherwise.
         */
        bool isEnableZrtp();

        /**
         * Set SAS as verified.
         *
         * The application may call this method if the user confirmed
         * (verfied) the Short Authentication String (SAS) with the peer.
         *
         * ZRTP calls ZrtpUserCallback#showSAS after it computed the SAS
         * and the application registered a user callback class. The
         * application should display the SAS and provide a mechanism at
         * the user interface that enables the user to confirm the SAS.
         *
         * ZRTP remembers the SAS confirmation status together with the
         * retained secrets data. If both parties confirmed the SAS then
         * ZRTP informs the application about this status on the next ZRTP
         * session.
         *
         * For more detailed information regarding SAS please refer to the
         * ZRTP specification, chapter 8.
         */
        void SASVerified();

        /**
         * Reset the SAS verfied flag for the current user's retained secrets.
         *
         */
        void resetSASVerified();

        /**
         * To confirm a go clear request.
         *
         * Call this method if the user confirmed a go clear (secure mode off).
         */
        void goClearOk();

        /**
         * Request to switch off secure mode.
         *
         * Call this method is the user itself wants to switch off secure
         * mode (go clear). After sending the "go clear" request to the peer
         * ZRTP immediatly switch off SRTP processing. Every RTP data is sent
         * in clear after the go clear request.
         */
        void requestGoClear();

        /**
         * Set the auxilliary secret.
         *
         * Use this method to set the srtps secret data. Refer to ZRTP
         * specification, chapter 5.3 ff
         *
         * @param data
         *     Points to the auxilliary secret data.
         * @param length
         *     Length of the auxilliary secrect in bytes
         */
        void setAuxSecret(uint8_t* data, int32_t length);

        /**
         * Set the other secret.
         *
         * Use this method to set the other secret data. Refer to ZRTP
         * specification, chapter 5.3 ff
         *
         * @param data
         *     Points to the other secret data.
         * @param length
         *     The length in bytes of the data.
         */
        void setPbxSecret(uint8* data, int32 length);

        /**
         * Set the application's callback class.
         *
         * The destructor of ZrtpQueue also destorys the user callback
         * class if it was set. The application must not delete the
         * callback object or use/reference the callback object after
         * ZrtpQueue was destroyed.
         *
         * @param ucb
         *     Implementation of the application's ZrtpUserCallback class
         */
        void setUserCallback(ZrtpUserCallback* ucb);

        /**
         * Set the client ID for ZRTP Hello message.
         *
         * The GNU ccRTP client may set its id to identify itself in the
         * ZRTP Hello message. The maximum length is 16 characters. A
         * shorter id string is possible, it will be filled with blanks. A
         * longer id string will be truncated to 16 characters. The
         * standard client id is <code>'GNU ccRTP ZRTP '</code> (without
         * the quotes).
         *
         * Setting the client's id must be done before calling
         * ZrtpQueue#initialize() or ZrtpQueue#startZrtp() .
         *
         * @param id
         *     The client's id string
         */
        void setClientId(std::string id);

        /**
         * Get the ZRTP Hello Hash data.
         *
         * Use this method to get the ZRTP Hello Hash data. The method 
         * returns the data as a string containing hex-digits. Refer 
         * to ZRTP specification, chapter 9.1.
         *
         * @return
         *    a std:string containing the Hello hash value as hex-digits. The
         *    hello hash is available immediatly after calling 
         *    ZrtpQueue#startZrtp. If ZRTP was not started the method returns
         *    an empty string.
         */
        std::string getHelloHash();

        /**
         * Get Multi-stream parameters.
         *
         * Use this method to get the Multi-stream that were computed during
         * the ZRTP handshake. An application may use these parameters to
         * enable multi-stream processing for an associated SRTP session.
         *
         * Refer to chapter 5.4.2 in the ZRTP specification for further details
         * and restriction how and when to use multi-stream mode.
         *
         * @return
         *    a string that contains the multi-stream parameters. The application
         *    must not modify the contents of this string, it is opaque data. The
         *    application may hand over this string to a new ZrtpQueue instance
         *    to enable multi-stream processing for this ZrtpQueue. If ZRTP was 
         *    not started or ZRTP is not yet in secure state the method returns an
         *    empty string.
         *
         * @see setMultiStrParams()
         */
        std::string getMultiStrParams();

        /**
         * Set Multi-stream parameters.
         *
         * Use this method to set the parameters required to enable Multi-stream
         * processing of ZRTP. The multi-stream parameters must be set before the
         * application starts the ZRTP protocol engine.
         *
         * Refer to chapter 5.4.2 in the ZRTP specification for further details
         * of multi-stream mode.
         *
         * @param parameters
         *     A string that contains the multi-stream parameters that this
         *     new ZrtpQueue instanace shall use.
         *
         * @see getMultiStrParams()
         */
        void setMultiStrParams(std::string parameters);

        /**
         * Check if this ZRTP use Multi-stream.
         *
         * Use this method to check if this ZRTP instance uses multi-stream. Even
         * if the application provided multi-stram parameters it may happen that
         * full DH mode was used. Refer to chapters 5.2 and 5.4.2 in the ZRTP #
         * when this may happen.
         *
         * @return
         *     True if multi-stream is used, false otherwise.
         */
        bool isMultiStream();

        /**
         * Check if the other ZRTP client supports Multi-stream.
         *
         * Use this method to check if the other ZRTP client supports
         * Multi-stream mode.
         *
         * @return
         *     True if multi-stream is available, false otherwise.
         */
        bool isMultiStreamAvailable();

        /**
         * Accept a PBX enrollment request.
         *
         * If a PBX service asks to enroll the MiTM key and the user accepts this
         * requtes, for example by pressing an OK button, the client application
         * shall call this method and set the parameter <code>accepted</code> to
         * true. If the user does not accept the request set the parameter to 
         * false.
         *
         * @param accepted
         *     True if the enrollment request is accepted, false otherwise.
         */
        void acceptEnrollment(bool accepted);

        /**
         * Set signature data
         *
         * This functions stores signature data and transmitts it during ZRTP
         * processing to the other party as part of the Confirm packets. Refer to 
         * chapters 6.7 and 8.2 in the ZRTP specification.
         *
         * @param data
         *    The signature data including the signature type block. The method
         *    copies this data into the Confirm packet at signature type block.
         * @param length
         *    The length of the signature data in bytes. This length must be
         *    multiple of 4.
         * @return
         *    True if the method stored the data, false otherwise.
         */
        bool setSignatureData(uint8* data, int32 length);

        /**
         * Get signature data
         *
         * This functions returns signature data that was receivied during ZRTP
         * processing. Refer to chapters 6.7 and 8.2.
         *
         * The signature data can be retrieved after ZRTP enters secure state.
         * <code>start()</code>.
         *
         * @param data
         *    Pointer to a data buffer. This buffer must be large enough to
         *    hold the signature data. Refer to <code>getSignatureLength()</code>
         *    to get the length of the received signature data.
         * @return
         *    Number of bytes copied into the data buffer
         */
        int32 getSignatureData(uint8* data);

        /**
         * Get length of signature data
         *
         * This functions returns the length of signature data that was receivied 
         * during ZRTP processing. Refer to chapters 6.7 and 8.2.
         *
         * @return
         *    Length in bytes of the received signature data. The method returns
         *    zero if no signature data avilable.
         */
        int32 getSignatureLength();

        /**
         * Enable PBX enrollment
         *
         * The application calls this method to allow or disallow PBX enrollment.
         * If the applications allows PBX enrollment then the ZRTP implementation
         * honors the PBX enrollment flag in Confirm packets. Refer to chapter 8.3
         * for further details of PBX enrollment.
         *
         * @param yesNo
         *    If set to true then ZRTP honors the PBX enrollment flag in Commit
         *    packets and calls the appropriate user callback methods. If
         *    the parameter is set to false ZRTP ignores the PBX enrollment flags.
         */
        void setPBXEnrollment(bool yesNo);

        /**
         * Put data into the RTP output queue.
         *
         * This is used to create a data packet in the send queue.
         * Sometimes a "NULL" or empty packet will be used instead, and
         * these are known as "silent" packets.  "Silent" packets are
         * used simply to "push" the scheduler along more accurately
         * by giving the appearence that a next packet is waiting to
         * be sent and to provide a valid timestamp for that packet.
         *
         * This method overrides the same method in OutgoingDataQueue class.
         * During ZRTP processing it may be necessary to control the
         * flow of outgoing RTP payload packets (GoClear processing).
         *
         * @param stamp Timestamp for expected send time of packet.
         * @param data Value or NULL if special "silent" packet.
         * @param len May be 0 to indicate a default by payload type.
         **/
        void
        putData(uint32 stamp, const unsigned char* data = NULL, size_t len = 0);

        /**
         * Immediatly send a data packet.
         *
         * This is used to create a data packet and send it immediately.
         * Sometimes a "NULL" or empty packet will be used instead, and
         * these are known as "silent" packets.  "Silent" packets are
         * used simply to "push" the scheduler along more accurately
         * by giving the appearence that a next packet is waiting to
         * be sent and to provide a valid timestamp for that packet.
         *
         * This method overrides the same method in OutgoingDataQueue
         * class.  During ZRTP processing it may be necessary to
         * control the flow of outgoing RTP payload packets (GoClear
         * processing).
         *
         * @param stamp Timestamp immediate send time of packet.
         * @param data Value or NULL if special "silent" packet.
         * @param len May be 0 to indicate a default by payload type.
         **/
        void
        sendImmediate(uint32 stamp, const unsigned char* data = NULL, size_t len = 0);

        /**
         * Starts the ZRTP protocol engine.
         *
         * Applications may call this method to immediatly start the ZRTP protocol
         * engine any time after initializing ZRTP and setting optinal parameters,
         * for example client id or multi-stream parameters.
         *
         * If the application does not call this method but sucessfully initialized
         * the ZRTP engine using <code>initialize()</code> then ZRTP also starts
         * after the application sent and received RTP packets. An application can
         * disable this automatic, delayed start of the ZRTP engine using 
         * <code>setEnableZrtp(false)</code> before sending or receiving RTP
         * packets.
         *
         */
        void startZrtp();

        /**
         * Stops the ZRTP protocol engine.
         *
         * Applications call this method to stop the ZRTP protocol
         * engine.
         *
         */
        void stopZrtp();

        /**
         * Get other party's ZID (ZRTP Identifier) data
         *
         * This functions returns the other party's ZID that was receivied 
         * during ZRTP processing. 
         *
         * The ZID data can be retrieved after ZRTP receive the first Hello
         * packet from the other party. The application may call this method
         * for example during SAS processing in showSAS(...) user callback
         * method.
         *
         * @param data
         *    Pointer to a data buffer. This buffer must have a size of
         *    at least 12 bytes (96 bit) (ZRTP Identifier, see chap. 4.9)
         * @return
         *    Number of bytes copied into the data buffer - must be equivalent
         *    to 96 bit, usually 12 bytes.
         */
        int32 getZid(uint8* data);

    protected:
	friend class TimeoutProvider<std::string, ost::ZrtpQueue*>;

        /**
         * A hook that gets called if the decoding of an incoming SRTP
         * was erroneous
         *
         * @param pkt
         *     The SRTP packet with error.
         * @param errorCode
         *     The error code: -1 - SRTP authentication failure, -2 - replay
         *     check failed
         * @return
         *     True: put the packet in incoming queue for further processing
         *     by the applications; false: dismiss packet. The default
         *     implementation returns false.
         */
        virtual bool
        onSRTPPacketError(IncomingRTPPkt& pkt, int32 errorCode);

        /**
         * Handle timeout event forwarded by the TimeoutProvider.
         *
         * Just call the ZRTP engine for further processing.
         */
        void handleTimeout(const std::string &c);

        /**
         * This function is used by the service thread to process
         * the next incoming packet and place it in the receive list.
         *
         * This class overloads the function of IncomingDataQueue
         * implementation.
         *
         * @return number of payload bytes received,  <0 if error.
         */
        virtual size_t takeInDataPacket();

        /*
         * The following methods implement the GNU ZRTP callback interface.
         * For detailed documentation refer to file ZrtpCallback.h
         */
        int32_t sendDataZRTP(const unsigned char* data, int32_t length);

        int32_t activateTimer(int32_t time);

        int32_t cancelTimer();

        void sendInfo(GnuZrtpCodes::MessageSeverity severity, int32_t subCode);

        bool srtpSecretsReady(SrtpSecret_t* secrets, EnableSecurity part);

        void srtpSecretsOff(EnableSecurity part);

        void srtpSecretsOn(std::string c, std::string s, bool verified);

        void handleGoClear();

        void zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity severity, int32_t subCode);

        void zrtpNotSuppOther();

        void synchEnter();

        void synchLeave();

        void zrtpAskEnrollment(std::string info);

        void zrtpInformEnrollment(std::string info);

        void signSAS(std::string sas);

        bool checkSASSignature(std::string sas);

        /*
         * End of ZrtpCallback functions.
         */

        ZrtpQueue(uint32 size = RTPDataQueue::defaultMembersHashSize,
                  RTPApplication& app = defaultApplication());

        /**
         * Local SSRC is given instead of computed by the queue.
         */
        ZrtpQueue(uint32 ssrc, uint32 size =
                  RTPDataQueue::defaultMembersHashSize,
                  RTPApplication& app = defaultApplication());

        virtual ~ZrtpQueue();

    private:
        void init();
        size_t rtpDataPacket(unsigned char* packet, int32 rtn, 
                             InetHostAddress network_address, 
                             tpport_t transport_port);

        ZRtp *zrtpEngine;
        ZrtpUserCallback* zrtpUserCallback;

        std::string clientIdString;

        bool enableZrtp;

        int32 secureParts;

//        CryptoContext* recvCryptoContext;
//        CryptoContext* senderCryptoContext;
        int16 senderZrtpSeqNo;
        ost::Mutex synchLock;   // Mutex for ZRTP (used by ZrtpStateClass)
        uint32 peerSSRC;
        bool started;

    };

    class IncomingZRTPPkt : public IncomingRTPPkt {

    public:
        /**
         * Build a ZRTP packet object from a data buffer.
         *
         * @param block pointer to the buffer the whole packet is stored in.
         * @param len length of the whole packet, expressed in octets.
         *
         **/

        IncomingZRTPPkt(const unsigned char* block, size_t len);

        ~IncomingZRTPPkt()
            { }

        uint32
        getZrtpMagic() const;

        uint32
        getSSRC() const;
    };

    class OutgoingZRTPPkt : public OutgoingRTPPkt {

    public:
        /**
         * Construct a new ZRTP packet to be sent.
         *
         * A new copy in memory (holding all this components
         * along with the fixed header) is created.
         *
         * @param hdrext whole header extension.
         * @param hdrextlen size of whole header extension, in octets.
         **/
        OutgoingZRTPPkt(const unsigned char* const hdrext, uint32 hdrextlen);
        ~OutgoingZRTPPkt()
            { }
    };

#ifdef  CCXX_NAMESPACES
}
#endif

#endif

/** EMACS **
 * Local variables:
 * mode: c++
 * c-default-style: ellemtel
 * c-basic-offset: 4
 * End:
 */

