/*
  Copyright (C) 2006-2007 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 _ZRTPPACKETHELLO_H_
#define _ZRTPPACKETHELLO_H_

/**
 * @file ZrtpPacketHello.h
 * @brief The ZRTP Hello message
 *
 * @ingroup GNU_ZRTP
 * @{
 */

#include <libzrtpcpp/ZrtpPacketBase.h>

/**
 * Implement the Hello packet.
 *
 * The ZRTP Hello message. The implementation sends this
 * to start the ZRTP negotiation sequence. The Hello message
 * offers crypto methods and parameters to the other party. The
 * other party selects methods and parameters it can support
 * and uses the Commit message to commit these.
 *
 * @author Werner Dittmann <Werner.Dittmann@t-online.de>
 */

class __EXPORT ZrtpPacketHello : public ZrtpPacketBase {

 protected:
    Hello_t* helloHeader;   ///< Point to the Hello message part

    int32_t nHash,          ///< number of hash algorithms offered
    nCipher,                ///< number of cipher algorithms offered
    nPubkey,                ///< number of key agreement algorithms offered
    nSas,                   ///< number of SAS algorithms offered
    nAuth;                  ///< number of SRTP authentication algorithms offered

    int32_t oHash,          ///< offsets in bytes to hash algorithm names
    oCipher,                ///< offsets in bytes to cipher algorithm names
    oPubkey,                ///< offsets in bytes to key agreement algorithm names
    oSas,                   ///< offsets in bytes to SAS algorithm names
    oAuth,                  ///< offsets in bytes to SRTP authentication algorithm names
    oHmac;                  ///< offsets in bytes to MAC of Hello message

 public:
    /// Creates a Hello packet with default data
    ZrtpPacketHello();

    /// Creates a Hello packet from received data
    ZrtpPacketHello(uint8_t *data);

    virtual ~ZrtpPacketHello();

    /**
     * Set configure data and populate Hello message data.
     *
     * Fill in the offered Algorithm names and compute all offset to
     * names and MAC. An application must call this method on Hello message
     * objects created with the standard constructor (with default data)
     * before the application can use most of the getter and setter methods.
     *
     * @param config
     *    Pointer to ZrtpConfigure data.
     */
    void configureHello(ZrtpConfigure* config);

    /// Get version number from Hello message, fixed ASCII character array
    uint8_t* getVersion()  { return helloHeader->version; };

    /// Get client id from Hello message, fixed ASCII character array
    uint8_t* getClientId() { return helloHeader->clientId; };

    /// Get H3 hash from Hello message, fixed byte array
    uint8_t* getH3()       { return helloHeader->hashH3; };

    /// Get client ZID from Hello message, fixed bytes array
    uint8_t* getZid()      { return helloHeader->zid; };

    /// Set version sting in Hello message, fixed ASCII character array
    void setVersion(uint8_t *text)     { memcpy(helloHeader->version, text,ZRTP_WORD_SIZE ); }

    /// Set client id in Hello message, fixed ASCII character array
    void setClientId(const uint8_t *t) { memcpy(helloHeader->clientId, t, sizeof(helloHeader->clientId)); }

    /// Set H3 hash in Hello message, fixed byte array
    void setH3(uint8_t *hash)          { memcpy(helloHeader->hashH3, hash, sizeof(helloHeader->hashH3)); }

    /// Set client ZID in Hello message, fixed bytes array
    void setZid(uint8_t *text)         { memcpy(helloHeader->zid, text, sizeof(helloHeader->zid)); }

    /// Check passive mode (mode not implemented)
    bool isPassive()       { return helloHeader->flags & 0x10; };

    /// Check if MitM flag is set
    bool isMitmMode()       { return helloHeader->flags & 0x20; };

    /// Check if SAS sign flag is set
    bool isSasSign()       { return helloHeader->flags & 0x40; };

    /// Get hash algorithm name at position n, fixed ASCII character array
    uint8_t* getHashType(int32_t n)   { return ((uint8_t*)helloHeader)+oHash+(n*ZRTP_WORD_SIZE); }

    /// Get ciper algorithm name at position n, fixed ASCII character array
    uint8_t* getCipherType(int32_t n) { return ((uint8_t*)helloHeader)+oCipher+(n*ZRTP_WORD_SIZE); }

    /// Get SRTP authentication algorithm name at position n, fixed ASCII character array
    uint8_t* getAuthLen(int32_t n)    { return ((uint8_t*)helloHeader)+oAuth+(n*ZRTP_WORD_SIZE); }

    /// Get key agreement algorithm name at position n, fixed ASCII character array
    uint8_t* getPubKeyType(int32_t n) { return ((uint8_t*)helloHeader)+oPubkey+(n*ZRTP_WORD_SIZE); }

    /// Get SAS algorithm name at position n, fixed ASCII character array
    uint8_t* getSasType(int32_t n)    { return ((uint8_t*)helloHeader)+oSas+(n*ZRTP_WORD_SIZE); }

    /// Get Hello MAC, fixed byte array
    uint8_t* getHMAC()                { return ((uint8_t*)helloHeader)+oHmac; }

    /// Set hash algorithm name at position n, fixed ASCII character array
    void setHashType(int32_t n, int8_t* t)
        { memcpy(((uint8_t*)helloHeader)+oHash+(n*ZRTP_WORD_SIZE), t, ZRTP_WORD_SIZE); }

    /// Set ciper algorithm name at position n, fixed ASCII character array
    void setCipherType(int32_t n, int8_t* t)
        { memcpy(((uint8_t*)helloHeader)+oCipher+(n*ZRTP_WORD_SIZE), t, ZRTP_WORD_SIZE); }

    /// Set SRTP authentication algorithm name at position n, fixed ASCII character array
    void setAuthLen(int32_t n, int8_t* t)
        { memcpy(((uint8_t*)helloHeader)+oAuth+(n*ZRTP_WORD_SIZE), t, ZRTP_WORD_SIZE); }

    /// Set key agreement algorithm name at position n, fixed ASCII character array
    void setPubKeyType(int32_t n, int8_t* t)
        { memcpy(((uint8_t*)helloHeader)+oPubkey+(n*ZRTP_WORD_SIZE), t, ZRTP_WORD_SIZE); }

    /// Set SAS algorithm name at position n, fixed ASCII character array
    void setSasType(int32_t n, int8_t* t)
        { memcpy(((uint8_t*)helloHeader)+oSas+(n*ZRTP_WORD_SIZE), t, ZRTP_WORD_SIZE); }

    /// Set Hello MAC, fixed byte array
    void setHMAC(uint8_t* t)
        { memcpy(((uint8_t*)helloHeader)+oHmac, t, 2*ZRTP_WORD_SIZE); }

    /// Get number of offered hash algorithms
    int32_t getNumHashes()   {return nHash; }

    /// Get number of offered cipher algorithms
    int32_t getNumCiphers()  {return nCipher; }

    /// Get number of offered key agreement algorithms
    int32_t getNumPubKeys()  {return nPubkey; }

    /// Get number of offered SAS algorithms
    int32_t getNumSas()      {return nSas; }

    /// Get number of offered SRTP authentication algorithms
    int32_t getNumAuth()     {return nAuth; }

    /// set MitM flag
    void setMitmMode()            { helloHeader->flags |= 0x20; }

    /// set SAS sign flag
    void setSasSign()            { helloHeader->flags |= 0x40; }

 private:
     // Hello packet is of variable length. It maximum size is 46 words:
     // - 11 words fixed sizze
     // - up to 35 words variable part, depending on number of algorithms
     // leads to a maximum of 4*46=184 bytes.
     uint8_t data[256];       // large enough to hold a full blown Hello packet
};

/**
 * @}
 */
#endif // ZRTPPACKETHELLO

