//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / SSCOP protocol
//
//File: sscopprotocol.h
//
//Version: $Revision: 1.25 $
//
//State: $State: Exp $
//
//Date: $Date: 1999/03/11 18:53:55 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications and Multimedia
//
//Author:
//      Juhana Räsänen
//
//Description:
//      Protocol conduit for SSCOP
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//
//Licence:
//
//
//History: 


#ifndef __SSCOP_SSCOPPROTOCOL_H__
#define __SSCOP_SSCOPPROTOCOL_H__

#include <typeinfo>
#include <string>

#include "sscop.h"
#include "sscopinternals.h"
#include "common/moduloint.h"
#include "pf/protocol.h"
#include "pf/frame.h"
#include "pf/timer.h"
#include "pf/types.h"

#include <deque>
#include <map>

class saalLink;
class sscopSD_PDU;


//
// Class: sscopProtocol
//
// Description:
//     This class implements protocol conduit for SSCOP protocol,
//     defined in ITU-T standard Q.2110. Protocol conduit is a
//     context object for a protocol, containing all state variables,
//     protocol parameters, timers, buffers and communication to
//     above and below layers. Actual functionality is implemented
//     in state classes that accept primitives, PDUs and timer
//     timeouts as inputs.
//     This implementation of SSCOP accepts downward AA-primitives
//     defined in iface/aaif module and CPCS-UNITDATA.indications
//     defined in iface/cpcsif. PDU and timeout inputs (messengers)
//     are implemented within this module.
//     Communication to other layers is carried out in normal
//     OVOPS++ conduit way, the upper layer (SSCF) assumed to be
//     conduit side B and lower layer (CPCS) conduit side A.
//

class sscopProtocol : public pfProtocol
{
// Declare SSCOP state classes as friends so that they can access
// state variables directly -- otherwise there would be too many
// get/set/increment methods
        friend class sscopState;
        friend class sscopIdle;
        friend class sscopOutgoingConnectionPending;
        friend class sscopIncomingConnectionPending;
        friend class sscopOutgoingDisconnectionPending;
        friend class sscopOutgoingResynchronizationPending;
        friend class sscopIncomingResynchronizationPending;
        friend class sscopOutgoingRecoveryPending;
        friend class sscopRecoveryResponsePending;
        friend class sscopIncomingRecoveryPending;
        friend class sscopDataTransferReady;

    public:
        explicit sscopProtocol(saalLink *manager_);
        sscopProtocol(const sscopProtocol &other_, saalLink *manager_);

        virtual ~sscopProtocol(void);

// Access methods for SSCOP protocol parameters and timers so that
// external management entity can set them
        void setMaxSDUsize(pfUlong SDUsize_);
        void setMaxUUsize(pfUlong UUsize_);
        void setMaxCC(pfUlong CC_);
        void setMaxPD(pfUlong PD_);
        void setCCtimeout(pfUlong msec_);
        void setInitialVR_MR(pfUlong windowSize_);
        void setKEEP_ALIVEtimeout(pfUlong msec_);
        void setNO_RESPONSEtimeout(pfUlong msec_);
        void setPOLLtimeout(pfUlong msec_);
        void setIDLEtimeout(pfUlong msec_);

// Methods for lower layer status setting and querying
        void setLowerLayerBusy(void);
        void clearLowerLayerBusy(void);
        bool lowerLayerIsBusy(void);

// Method for querying power-up robustness
        bool isPowerUpRobustnessEnabled(void);

        void changeToIdleState(void);
        void changeToOutgoingConnectionPendingState(void);
        void changeToIncomingConnectionPendingState(void);
        void changeToOutgoingDisconnectionPendingState(void);
        void changeToOutgoingResynchronizationPendingState(void);
        void changeToIncomingResynchronizationPendingState(void);
        void changeToOutgoingRecoveryPendingState(void);
        void changeToRecoveryResponsePendingState(void);
        void changeToIncomingRecoveryPendingState(void);
        void changeToDataTransferReadyState(void);

// Methods from sscopstate moved here
        void releaseBuffers(void);
        void prepareRetrieval(void);
        void prepareRecovery(void);
        void clearTransmitter(void);
        void deliverData(void);
        void initializeStateVariables(void);
        void dataRetrieval(pfUlong retrievalNumber_);
        bool detectRetransmission(pfUlong N_SQ_);
        void setPOLLtimer(void);
        void resetDataTransferTimers(void);
        void setDataTransferTimers(void);
        void initializeVR_MR(void);
        void sendErrorReleaseEND(sscopError code_,
                                 pfUlong count_ = 0,
                                 bool sendRelease_ = false,
                                 bool sendEND_ = false);


    private:
        // These constsructors and operators are not implemented
        sscopProtocol(void);
        sscopProtocol(const sscopProtocol &other_);
        const sscopProtocol &operator=(const sscopProtocol &other_);

    private:
        // acceptSynchronous rewritten here in order to enable 
        // debug printing of the state variables
        virtual void acceptSynchronous(pfTransporter *transporter_);
        void printStateVariables(void);

// Methods to create and send AA-signals upwards to conduit side A
        void sendAaESTABLISHind(const pfFrame &sscop_uu_);
        void sendAaESTABLISHconf(const pfFrame &sscop_uu_);
        void sendAaRELEASEind(const pfFrame &sscop_uu_, pfUlong source_);
        void sendAaRELEASEconf(void);
        void sendAaDATAind(const pfFrame &data_, pfUlong sequenceNumber_);
        void sendAaRESYNCind(const pfFrame &sscop_uu_);
        void sendAaRESYNCconf(void);
        void sendAaRECOVERind(void);
        void sendAaUNITDATAind(const pfFrame &data_);
        void sendAaRETRIEVEind(const pfFrame &data_);
        void sendAaRETRIEVE_COMPLETEind(void);

// Methods to send MAA-indications to the layer management
        void sendMaaERRORind(sscopError code_, pfUlong count_ = 0);
        void sendMaaUNITDATAind(const pfFrame &frame_);

// Methods to create, encode and send SSCOP PDUs to the peer protocol
        void sendBGNpdu(pfFrame &frame_);
        void resendLastBGNpdu(void);
        void sendBGAKpdu(pfFrame &frame_);
        void sendBGREJpdu(pfFrame &frame_);
        void sendENDpdu(pfFrame &frame_, pfUlong source_);
        void resendLastENDpdu(void);
        void sendENDAKpdu(void);
        void sendRSpdu(pfFrame &frame_);
        void resendLastRSpdu(void);
        void sendRSAKpdu(void);
        void sendERpdu(void);
        void resendLastERpdu(void);
        void sendERAKpdu(void);
        void sendSDpdu(pfFrame &frame_, pfUlong sequenceNumber_);
        void sendPOLLpdu(void);
        void sendSTATpdu(pfFrame &frame_, pfUlong N_PS_);
        void sendUSTATpdu(pfUlong listElement1_, pfUlong listElement2_);
        void sendUDpdu(pfFrame &frame_);
        void sendMDpdu(pfFrame &frame_);

// Method to send a frame (encoded PDU) to CPCS protocol (on side B)
// used by sendXXpdu() methods
        void sendCpcsUNITDATAreq(const pfFrame &frame_);
        
// Method to create a "SD PDU Queued Up" internal event
        void createSDpduQueuedUp(void);

// MODIFIED: jturunen
        void setTimerByType(pfTimer &timerType_, 
                            pfUlong &saveValue_,
                            pfTimerMessenger *message_);
        void setAllInitialValues(void);
        
// SSCOP parameters
        pfUlong _maxSDUsize;
        pfUlong _maxUUsize;
        pfUlong _maxCC;
        pfUlong _maxPD;
        pfUlong _maxSTAT;
        pfUlong _initialVR_MR;
        bool _clearBuffers;
        bool _credit;

// State variables
        moduloInteger _VT_S;
        moduloInteger _VT_PS;
        moduloInteger _VT_A;
        moduloInteger _VT_PA;
        moduloInteger _VT_MS;
        pfUlong _VT_PD;
        pfUlong _VT_CC;
        moduloInteger _VT_SQ;
        moduloInteger _VR_R;
        moduloInteger _VR_H;
        moduloInteger _VR_MR;
        moduloInteger _VR_SQ;

// SSCOP timers
        pfTimer _timerCC;
        pfTimer _timerKEEP_ALIVE;
        pfTimer _timerNO_RESPONSE;
        pfTimer _timerPOLL;
        pfTimer _timerIDLE;

// Timer timeout values are saved here for use in copy constructor
        pfUlong _saveCCtimeout;
        pfUlong _saveKEEP_ALIVEtimeout;
        pfUlong _saveNO_RESPONSEtimeout;
        pfUlong _savePOLLtimeout;
        pfUlong _saveIDLEtimeout;

// These are to store some previously sent PDUs for resending
        pfFrame _lastBGNframe;
        pfFrame _lastENDframe;
        pfFrame _lastRSframe;
        pfFrame _lastERframe;
        pfFrame _lastBGNsscop_uu;
        pfFrame _lastBGAKsscop_uu;
        pfFrame _lastBGREJsscop_uu;

// Transmitter/receiver buffers and queues
        typedef deque<pfFrame> frameQueue;
        typedef map<pfUlong, sscopSD_PDU *, less<pfUlong> > pduMap;
        typedef pduMap::iterator pduMapIterator;

        frameQueue _transmissionQueue;
        void clearTransmissionQueue(void);

        pduMap _transmissionBuffer;
        void clearTransmissionBuffer(void);
        void insertIntoTransmissionBuffer(sscopSD_PDU *messenger_);

        pduMap _retransmissionQueue;
        void clearRetransmissionQueue(void);
        void insertIntoRetransmissionQueue(sscopSD_PDU *messenger_);

        pduMap _receiverBuffer;
        void clearReceiverBuffer(void);
        bool receiverBufferIsFull(void) const;
        void insertIntoReceiverBuffer(sscopSD_PDU *messenger_);

        frameQueue _unassuredQueue;
        frameQueue _managementQueue;

// Pointer to the layer management entity of this protocol instance
        saalLink *_manager;

// Status of the lower layer
        bool _lowerLayerIsBusy;
// Power-up robustness indicator e.g. is it implemented or not
        bool _powerUpRobustness;
};


#endif // __SSCOP_SSCOPPROTOCOL_H__
