//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / UNI
//
//File: uniprotocol.h
//
//Version: $Revision: 1.32 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/12/22 12:42:44 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Jari Katajavuori
//      Sami Raatikainen (based on version 1.19)
//
//Description:
//      Uni protocol conduit implementation. This conduit is connection-
//      oriented so instances are created dynamically above a mux. It
//      implements the main functionality of the signaling protocol.
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//
//Licence:
//
//
//History: 

#ifndef __UNI_UNIPROTOCOL_H__
#define __UNI_UNIPROTOCOL_H__

#include "protocol/sig/sigprotocol.h"
#include "pf/storage.h"
#include "protocol/uni/unidefs.h"
#include "protocol/uni/uniset.h"

class uniMode;
class uniPdu;
class uniSETUPpdu;
class uniCONNECTpdu;
class uniCALL_PROCEEDINGpdu;
class uniALERTINGpdu;
class uniCONNECT_ACKpdu;
class uniRELEASE_COMPLETEpdu;
class uniRELEASEpdu;
class uniADD_PARTYpdu;
class uniADD_PARTY_ACKpdu;
class uniADD_PARTY_REJECTpdu;
class uniDROP_PARTYpdu;
class uniDROP_PARTY_ACKpdu;
class uniSTATUSpdu;
class uniSTATUS_ENQUIRYpdu;
class uniADD_PARTYreq;
class uniADD_PARTYresp;
class uniADD_PARTYerror;
class uniDROP_PARTYreq;
class uniDROP_PARTYresp;
class uniSTATUSreq;
class uniSTATUSresp;

class ccProtocol;

// Constants
const pfUlong uniMaxEndpointReference = 0xffff;
const pfUlong uniCallReferenceFlagBitPosition = 23;
const pfUlong uniCallReferenceFlagBitMask = 0x800000;


//
// Class: uniProtocol
//
// Description:
//      Implements uni protocol conduit.
// 

class uniProtocol : public sigProtocol, public pfStorage
{
    public:
        static uniProtocol *create(bool isUserSide_);
        
        uniProtocol(const uniProtocol &other_);
        virtual ~uniProtocol(void);
        pfProtocol *cloneImplementation(void) const;
        
        // Enabling point-to-point or point-to-multipoint capabilities.
        void createConduitsConnection(sigSETUPind *primitive_);
        pfConduit createPointToPointConduits(void);
        pfConduit createMultipointConduits(void);
        
        void setUserMode(void);
        void setNetworkMode(void);
        
        // PMP management
        void addPMP(pfMessenger *message_);
        void removePMP(pfMessenger *message_);
        bool isExistingPMP(pfUlong endpointReference_);
        bool isPMPSetEmpty(void);
        
        void saveSetupData(sigSETUPind *message_);
        void putSavedSetupDataInto(uniADD_PARTYreq *message_);
        
        // To PMP
        void sendADD_PARTYreqToPMP(uniADD_PARTYpdu *message_);
        void sendADD_PARTYrespToPMP(uniADD_PARTY_ACKpdu *message_);
        void sendADD_PARTYerrorToPMP(uniADD_PARTY_REJECTpdu *message_);
        void sendDROP_PARTYreqToPMP(uniDROP_PARTYpdu *message_);
        void sendDROP_PARTYrespToPMP(uniDROP_PARTY_ACKpdu *message_);
        void sendDROP_PARTYreqToAllPMPs(pfMessenger *message_);
        void sendSTATUSreqToPMP(uniSTATUS_ENQUIRYpdu *message_);

        // To CC, if methods in sigProtocol are inadequate
        

        // To CoOrd
        void sendSETUP_COMPLETEreqToDown(void); //new
        void sendALERTINGreqToDown(sigALERTINGreq *primitive_); //new
        
        void sendRELEASEreqToDown(sigRELEASEreq *primitive_); //new
        void sendRELEASEreqToDown(pfUlong cause_);
        void sendRELEASEreqToDown(pfUlong cause1_, pfUlong cause2_); //new
        
        void sendSTATUSpduToCoOrd(pfUlong cause_);
        void sendSTATUSpduToCoOrd(uniSTATUSresp *message_);
        void sendSTATUSpduToCoOrd(uniSTATUS_ENQUIRYpdu *message_);
        void sendSTATUS_ENQUIRYpduToCoOrd(void);
        
        void sendLINK_ESTABLISHreqToCoOrd(void);
        void sendLINK_RELEASEreqToCoOrd(void);

        void sendADD_PARTYpduToCoOrd(uniADD_PARTYreq *message_);
        void sendADD_PARTY_ACKpduToCoOrd(uniADD_PARTYresp *message_);
        void sendADD_PARTY_REJECTpduToCoOrd(uniADD_PARTYerror *message_);
        void sendDROP_PARTYpduToCoOrd(uniDROP_PARTYreq *message_);
        void sendDROP_PARTY_ACKpduToCoOrd(uniDROP_PARTYresp *message_);
        
        
        // hook methods
        void startPROCEEDINGtimer(void);
        void stopPROCEEDINGtimer(void);
        void startALERTINGtimer(void);
        void stopALERTINGtimer(void);
        void startCONNECTtimer(void);
        void stopCONNECTtimer(void);
        void startCONNECT_ACKtimer(void);
        void stopCONNECT_ACKtimer(void);
        void startRELEASE_COMPLETEtimer(void);
        void stopRELEASE_COMPLETEtimer(void);

        void sigAwaitPROCEEDINGtimeoutAct(void);
        void sigAwaitALERTINGtimeoutAct(void);
        void sigAwaitCONNECTtimeoutAct(void);
        void sigAwaitCONNECT_ACKtimeoutAct(void);
        void sigAwaitRELEASE_COMPLETEtimeoutAct(void);
        
        void incomingResourcesRejectedAct(sigRELEASEresp *primitive_);
        void releaseCollisionAct(sigRELEASEind *primitive_);
       

        // Status enquiry procedure
        void statusEnquiry(void);
        bool isCompatibleState(pfUlong state_);
        
        // Call clearing, miscellaneous
        void clearCallIfNullState(uniSTATUSpdu *message_);
        void stopAllTimers(void);
        void clearPMPs(pfMessenger *message_);
        void triggerContinueClearing(void);
        void finalClearing(void);
        
        bool verifyMessage(pfMessenger *msg_, uniStateValue stateAfter_);
        void reportIncompatibleMessage(pfMessenger *message_);
        
        void setCallReference(pfMessenger *message_); //new        
        void setZeroEndpointReferenceAtOSide(pfMessenger *message_); //new
        void setZeroEndpointReferenceAtTSide(pfMessenger *message_); //new
        void setZeroEndpointReference(pfMessenger *message_); //modified
        
        void initTimers(void);
        
    protected:
        uniProtocol(void);

        void toAllPMPs(pfMessenger *primitive_);
        
    private:
        uniSet _multipointSet;
        ccProtocol *_cc;

        pfUlong _uniT303Timeouts;
        pfUlong _uniT308Timeouts;
        pfUlong _uniT322Timeouts;
        
        pfIE *_causeR;
};

#endif // __UNI_UNIPROTOCOL_H__
