#ifndef _VIP_STDPROTOCOL_HH_
#define _VIP_STDPROTOCOL_HH_

#include <vos/vip/vipdefs.hh>

#include <vos/vip/protocol.hh>
#include <deque>

namespace VIP
{
    class StandardProtocol : public Protocol
    {
    private:
        boost::recursive_mutex stdproto_mutex;

        uint32_t lastRecvAcks[VIP_STDPROTO_CHANNELS];
        uint32_t maxSentSeqnum[VIP_STDPROTO_CHANNELS];
        double retransTimer[VIP_STDPROTO_CHANNELS];
        uint32_t lastRecvSeqnum[VIP_STDPROTO_CHANNELS];
        unsigned int needAcks[VIP_STDPROTO_CHANNELS];
        unsigned int ackCount[VIP_STDPROTO_CHANNELS];
        std::deque< VUtil::vRef<Message> > data[VIP_STDPROTO_CHANNELS];

        double backoff[VIP_STDPROTO_CHANNELS];

        void packChannel(int channel, uint8_t* buf, unsigned int* bufsize);
        void rmFromQueue(int channel, uint32_t bytes);
        unsigned int pendingData(int channel);
        unsigned int readAcks(uint8_t* buf, unsigned int bufsize, bool syn);
        bool readSYNSeqNums(uint8_t* buf, unsigned int bufsize,
                            unsigned int* ptr, bool setup);

        bool haveSentEver;

    public:
        StandardProtocol(Connection* c);
        virtual ~StandardProtocol();

        virtual int getProtocolNum();
        virtual void makeSYN(uint8_t* buf, unsigned int* bufsize);
        virtual bool replySYN(uint8_t* received, unsigned int recvsz,
                               uint8_t* reply, unsigned int* replysz);
        virtual void setupWithSYN(uint8_t* received, unsigned int recvsz);

        virtual int queueData(Message* m);
        virtual void handleChunk(uint8_t* buf, unsigned int* bufsize);
        virtual void getNextChunk(uint8_t* buf, unsigned int* bufsize, bool ackOnly);

        virtual double desiredWaitTime();

        virtual bool hasQueuedData();
        virtual unsigned int queuedBytes(int channel);
    };
}

#endif
