//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project
//
//File: unicoordprotocol.h
//
//Version: $Revision: 1.5 $
//
//State: $State: Exp $
//
//Date: $Date: 1999/01/22 15:47:13 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Jari Pusa
//
//Description:
//
//
//Copyright:
//
//
//Licence:
//
//
//History: 

#ifndef __UNI_UNICOORDPROTOCOL_H__
#define __UNI_UNICOORDPROTOCOL_H__

#include <typeinfo>

#ifndef NON_STD_STL
# include <queue>
#endif // NON_STD_STL

#include <string>
#include <list>
#include <stack>

#include "pf/protocol.h"
#include "pf/storage.h"

class pfFrame;
class pfConduit;
class pfMux;
class uniSETUPpdu;
class uniRESET_ERRORind;
class uniRESETconf;
class uniRESETind;
class uniRESETreq;
class uniRESETresp;
class uniRESET_ERRORresp;
class uniPdu;
class uniErrorInfo;

//
// Class: uniCoOrdProtocol
//
// Description:
//     A protocol conduit implementation for coordination part of uni.
//     Task for coord is to encode/decode messages and deside where they
//     should be sent: to UNI, RSN, RRN or SAAL.
//

class uniCoOrdProtocol : public pfProtocol, public pfStorage
{
    public:
        static pfConduit create(pfConduit &mux_);

        virtual ~uniCoOrdProtocol(void);

        // Modifications to pfConduit interface
        virtual void disconnect(void);

        // Message verification

        bool verifyTrafficParameterCombinations(uniSETUPpdu *message_);
        
        // to SAAL (uaal)

        void sendESTABLISHreqToAAL(void);
        void sendRELEASEreqToAAL(void);
        void sendDATAreqToAAL(pfFrame &frame_);
        void sendDATAreqToAAL(uniPdu *pdu_);


        void sendStatus(uniPdu *pdu_, uniErrorInfo &errorInfo_);
        void sendSTATUSrequestToUNI(uniPdu *message_, uniErrorInfo &errorInfo_);
        void sendSTATUSreplyToAAL(uniErrorInfo &cause_);
        void sendSTATUSreplyToAAL(uniPdu *pdu_, pfUlong cause_);
        void sendSTATUSreplyToAAL(uniPdu *pdu_, uniErrorInfo &cause_);
        void sendRELEASE_COMPLETEreplyToAAL(uniPdu *pdu_, pfUlong cause_);
        void sendRELEASE_COMPLETEreplyToAAL(uniPdu *pdu_,
                                            uniErrorInfo &cause_);
                
        // to UNI

        void sendRESET_ERRORindToUNI(uniRESET_ERRORind *primitive_);
        void sendRESETconfToUNI(uniRESETconf *primitive_);
        void sendRESETindToUNI(uniRESETind *primitive_);
        
        void sendLINK_ESTABLISHconfToUNI(void);
        void sendLINK_ESTABLISHindToUNI(void);
        void sendLINK_ESTABLISHerrorToUNI(void);
        void sendLINK_RELEASEconfToUNI(void);
        void sendLINK_RELEASEindToUNI(void);

        void sendRELEASEpduToUNI(pfUlong cause_);
        void sendRELEASE_COMPLETEpduToUNI(pfUlong cause_);
        
        // to RSN

        void sendRESETreqToRSN(uniRESETreq *primitive_);
        
        // to RRN

        void sendRESETrespToRRN(uniRESETresp *primitive_);
        void sendRESET_ERRORrespToRRN(uniRESET_ERRORresp *primitive_);
        
        // State changes

        virtual void changeToAALConnectionReleasedState(void);
        virtual void changeToAALAwaitingEstablishState(void);
        virtual void changeToAALAwaitingReleaseState(void);
        virtual void changeToAALConnectionEstablishedState(void);

        // Message buffering
        
        void saveMessage(pfMessenger *messenger_);
        void acceptSavedMessages(void);
        void removeSavedMessages(void);

        // Miscellaneous

        bool isMuxKeyAllocated(const pfKey key_);

        void toRSN(pfMessenger *message_);
        void toRSN(pfMsgTransporter *message_);
        void toRRN(pfMessenger *message_);
        void toRRN(pfMsgTransporter *message_);

        void toAllUNIs(pfMessenger *message_);
        void toAllUNIs(pfMsgTransporter *transporter_);
        
    protected:
        uniCoOrdProtocol(void);

        void toExternal(pfConduit &conduit_, pfMessenger *message_);
        void toExternal(pfConduit &conduit_, pfMsgTransporter *transporter_);

    private:

        pfMux *_mux;
        
        pfConduit _RSN;
        pfConduit _RRN;

        // Buffer for saved messages
#ifndef NON_STD_STL
        typedef queue<pfMessenger *> queueType;
#else
        typedef queue<list<pfMessenger *> > queueType;
#endif // NON_STD_STL

        queueType _queue;
};

#endif // __UNI_UNICOORDPROTOCOL_H__
