// This file is a part of the xMule Project.
//
// Copyright (c) 2004 Theodore R. Smith (hopeseekr@xmule.ws / http://www.xmule.ws/)
// DSA-1024 Fingerprint: 10A0 6372 9092 85A2 BB7F 907B CB8B 654B E33B F1ED
//
// Copyright (C)2002 Merkur ( merkur-@users.sourceforge.net / http://www.xmule-project.net )
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.

#ifndef CLIENTCRED_H
#define CLIENTCRED_H

#define CRYPT_CIP_REMOTECLIENT	10
#define CRYPT_CIP_LOCALCLIENT	20
#define CRYPT_CIP_NONECLIENT	30

#include "config.h"                         // HAVE_CRYPTO - audited 6 Nov 2004
#include "wintypes.h"                       // BYTE - audited 6 Nov 2004

#include <stdint.h>                         // uint16_t uint32_t - audited 6 Nov 2004
#include <wx/defs.h>                        // wxByte

#if !HAVE_CRYPTOPP
    #include "CryptoXMpp.h"
#else
    #include <cryptopp/cryptlib.h>
    #include <cryptopp/rsa.h>
    #define CryptoXMpp CryptoPP
#endif

#define MAXPUBKEYSIZE 80

class CPreferences;

#pragma pack(1)
struct CreditStruct_29a
{
    wxByte        abyKey[16];
    uint32_t      nUploadedLo;      // uploaded TO him
    uint32_t      nDownloadedLo;    // downloaded from him
    uint32_t      nLastSeen;
    uint32_t      nUploadedHi;      // upload high 32
    uint32_t      nDownloadedHi;    // download high 32
    uint16_t      nReserved3;
};

struct CreditStruct{
    wxByte        abyKey[16];
    uint32_t      nUploadedLo;      // uploaded TO him
    uint32_t      nDownloadedLo;    // downloaded from him
    uint32_t      nLastSeen;
    uint32_t      nUploadedHi;      // upload high 32
    uint32_t      nDownloadedHi;    // download high 32
    uint16_t      nReserved3;
    uint8_t       nKeySize;
    wxByte        abySecureIdent[MAXPUBKEYSIZE];
};
#pragma pack()

enum EIdentState
{
    IS_NOTAVAILABLE,
    IS_IDNEEDED,
    IS_IDENTIFIED,
    IS_IDFAILED,
    IS_IDBADGUY,
};

class CClientCredits
{
    friend class CClientCreditsList;
public:
    CClientCredits(CreditStruct* in_credits);
    CClientCredits(wxByte* key);
    ~CClientCredits();

    wxByte* GetKey()	
    {
        return m_pCredits->abyKey;
    }

    wxByte* GetSecureIdent()
    {
        return m_abyPublicKey;
    }

    uint8_t	GetSecIDKeyLen()			{return m_nPublicKeyLen;}
    CreditStruct* GetDataStruct()			{return m_pCredits;}
    void	ClearWaitStartTime();
    void	AddDownloaded(uint32_t bytes, uint32_t dwForIP);
    void	AddUploaded(uint32_t bytes, uint32_t dwForIP);
    uint64_t	GetUploadedTotal();
    uint64_t	GetDownloadedTotal();
    float	GetScoreRatio(uint32_t dwForIP);
    float	GetMyScoreRatio(uint32_t dwForIP); //added by sivka [VQB: -ownCredits-]
    void	SetLastSeen()				{m_pCredits->nLastSeen = time(NULL);}
    bool	SetSecureIdent(wxByte* pachIdent,uint8_t nIdentLen);
    void	ShowCHandPK(uint32_t challenge,wxByte* publickey,int length);

    uint32_t	m_dwCryptRndChallengeFor;
    uint32_t	m_dwCryptRndChallengeFrom;
    EIdentState	GetCurrentIdentState(uint32_t dwForIP);

    uint32_t		GetSecureWaitStartTime(uint32_t dwForIP);
    void		SetSecWaitStartTime(uint32_t dwForIP);
protected:
    void		Verified(uint32_t dwForIP);
    EIdentState	IdentState;
private:
    void 		InitalizeIdent();
    CreditStruct*	m_pCredits;
    BYTE		m_abyPublicKey[80];
    uint8_t		m_nPublicKeyLen;
    uint32_t		m_dwIdentIP;
    uint32_t		m_dwWaitTime;
    uint32_t		m_dwSecureWaitTime;
    uint32_t		m_dwUnSecureWaitTime;
    uint32_t		m_dwWaitTimeIP;
};

class CClientCreditsList
{
public:
    CClientCreditsList(CPreferences* in_prefs);
    ~CClientCreditsList();
    
    // return signature size, 0 = Failed | use sigkey param for debug only
    uint8_t	CreateSignature(CClientCredits* pTarget, wxByte* pachOutput, uint8_t nMaxSize, uint32_t ChallengeIP, uint8_t byChaIPKind);
                    //CryptoXMpp::RSASSA_PKCS1v15_SHA_Signer* sigkey = NULL);
    bool	VerifyIdent(CClientCredits* pTarget, wxByte* pachSignature, uint8_t nInputSize, uint32_t dwForIP, uint8_t byChaIPKind);	
    CClientCredits* GetCredit(wxByte* key);

    void	Process();
    uint8_t	GetPubKeyLen()					{ return m_nMyPublicKeyLen; }
    BYTE*	GetPublicKey()					{ return m_abyMyPublicKey; }
    bool	CryptoAvailable();
protected:
    void	LoadList();
    void	SaveList();
    void 	InitalizeCrypting();
    void CreateKeyPair();
private:
    CPreferences*	m_pAppPrefs;
    uint32_t			m_nLastSaved;
    CryptoXMpp::RSASSA_PKCS1v15_SHA_Signer*		m_pSignkey;
    BYTE			m_abyMyPublicKey[80];
    uint8_t			m_nMyPublicKeyLen;
};

#endif
