/*
  Copyright (C) 2006-2012 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>

#define HELLO_FIXED_PART_LEN  22

/**
 * 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; }

    /// Check if packet length matches
    bool isLengthOk()        {return (computedLength == getLength());}

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

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

