#ifndef _VIP_LOWLATENCYPROTO_HH_
#define _VIP_LOWLATENCYPROTO_HH_

#include <vos/vip/vipdefs.hh>

namespace VIP
{
    class LowLatencyProto;
}

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

namespace VIP
{
    struct OutgoingMsg
    {
        OutgoingMsg() { }
        OutgoingMsg(const OutgoingMsg& cp)
            : seqnum(cp.seqnum), bytesSent(cp.bytesSent),
              m(cp.m), lastSentTime(cp.lastSentTime)
            { }

        uint32_t seqnum;
        unsigned int bytesSent;
        VUtil::vRef<Message> m;
        double lastSentTime;
    };

    class LowLatencyProto : public Protocol
    {
    private:
        boost::mutex llp_mutex;

        uint32_t sentSeqCounter;
        uint32_t lastAckNum;

        uint32_t lastRecvNum;
        uint32_t msgidCounter;

        std::deque<OutgoingMsg> outgoingqueue;

        double heartbeatTime;
        double lastHeartbeat;

        bool needSendAck;
        bool haveSentEver;

    public:

        LowLatencyProto(Connection* c);
        virtual ~LowLatencyProto() { };

        virtual int getProtocolNum() { return VIP_LOWLATENCY; }
        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
