
/*---------------------------------------------------------------------------*/
/* http_digest_hosts.h                                                       */
/* copyright (c) innovaphone 2016                                            */
/*                                                                           */
/*---------------------------------------------------------------------------*/

#define DIGEST_HOST_LIFETIME    2 * 60

class HTTPDigestNonce : public istd::listElement<HTTPDigestNonce> {
protected:
    friend class HTTPDigestHost;
    char * nonce;
    dword nonceCount;
    dword lastAccess;
    istd::list<class HTTPAuthDigest> ownerList;

    void NotifyOwner();

public:
    HTTPDigestNonce()
    {
        this->nonce = nullptr;
        this->nonceCount = 0;
        this->lastAccess = dword(ITime::TimeStampMilliseconds() / 1000);
    }

    ~HTTPDigestNonce()
    {
        this->NotifyOwner();
        free(this->nonce);
    }

    const char * GetNonce() { return this->nonce; }
    dword GetNonceCount() { return this->nonceCount; }
    dword GetLastAccess() { return this->lastAccess; }

    void IncNonceCount()
    {
        ++this->nonceCount;
        this->lastAccess = dword(ITime::TimeStampMilliseconds() / 1000);
    }

    void Invalidate();
    void SetOwner(class HTTPAuthDigest * owner);
};


class HTTPDigestHost : public btree, public istd::listElement<HTTPDigestHost> {
private:
    char * hostName;
    char serverOpaque[33];

    istd::list<HTTPDigestNonce> nonceList;

public:
    static void MakeMD5String(const byte * in, size_t len, char * out33byte);

    HTTPDigestHost(const char * hostName);
    ~HTTPDigestHost();

    HTTPDigestNonce * CreateNonce();
    HTTPDigestNonce * GetNonceObj(const char * nonce);
    void CleanUpNonceObjects(dword timeStamp);
    bool HasNonceObjects() { return this->nonceList.front() != nullptr; }

    const char * GetHostName();
    const char * GetServerOpaque();

    virtual int btree_compare(void * key);
    virtual int btree_compare(class btree * b);
};


class HTTPDigestHostManager {
protected:
    class HTTPDigestHost * hostList;

public:
    HTTPDigestHostManager();
    virtual ~HTTPDigestHostManager();

    class HTTPDigestHost * GetDigestHost(const char * hostName);
    void RemoveDigestHost(class HTTPDigestHost * dgHost);
    void AddDigestHost(class HTTPDigestHost * dgHost);
    void CleanUpList();
    void CleanUpList(dword timeStamp);
	bool Empty() { return this->hostList == nullptr; }
};
