//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / ILMI
//
//File: ilmiprotocol.h
//
//Version: $Revision: 1.31 $
//
//State: $State: Exp $
//
//Date: $Date: 1999/03/11 17:01:52 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
//
//Author:
//      Timo Pärnänen
//
//Description:
//      
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//
//Licence:
//
//
//History: 

#ifndef __ILMI_PROTOCOL_H__
#define __ILMI_PROTOCOL_H__

#include <typeinfo>
#include <string>
#include <map>

#include <sys/socket.h>
#include <netinet/in.h>
#include <asn-incl.h>

#include "asn/rfc1155-smi.h"
#include "asn/rfc1157-snmp.h"

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

#include "mib/mibtree.h"
#include "mib/mibdestination.h"

#include "mgmt/mgmtdelegationbase.h"

#include "ilmiaddressregistration.h"
#include "ilmicommand.h"

//
//Class: ilmiProtocol
//
//Description:
//

class ilmiProtocol : public pfProtocol,
                     public mgmtDelegationBase,
                     public mibDestination
{
    public:
        static pfConduit createProtocol(const string &portNumber_,
                                        const string &linkNumber_);
        virtual ~ilmiProtocol(void);

        void initIlmiLink(string &vpi_, string &vci_);

        // mgmtDelegationBase interface
        virtual string receiveGet(const string &name_);
        virtual void receiveSet(const string &name_, const string &value_);
        virtual void receiveExecute(mgmtCommand &command_);
        
        // mibDestination interface
        virtual string getValue(const string &name_);
        virtual void setValue(const string &name_, const string &value_);

        // Init methods
        void initMibTree(void);

        // Methods used by state machine.
        bool verifyVersionNumber(MessageInt version_) const;
        bool communityCheck(AsnOcts community_) const;

        void setUDPAddress(const struct sockaddr_in &address_);

        // Handle received PDUs.
        void handleGetPDU(AsnInt &requestID_, VarBindList &list_);
        void handleGetNextPDU(AsnInt &requestID_, VarBindList &list_);
        void handleSetPDU(AsnInt &requestID_, VarBindList &list_);
        void handleGetResponsePDU(AsnInt &requestID_,
                                  PDUInt &errorStatus_,
                                  AsnInt &errorIndex_,
                                  VarBindList &list_);
        void handleTrapPDU(AsnOid &enterprise_,
                           NetworkAddress *agent_addr_,
                           Trap_PDUInt &generic_trap_,
                           AsnInt &specific_trap_,
                           TimeTicks &time_stamp_,
                           VarBindList &list_);
        

        void varBindToString(VarBind *varBind_,
                             string &sname_,
                             string &svalue_);
        
    private:
        friend ilmiAddressRegistration;
        
        ilmiProtocol(const string &portNumber_, 
                     const string &linkNumber_);

        PDUs *initMessage(Message &message_) const;

        // Command map handling.
        pfUlong addCommand(ilmiCommand *command_);
        void removeCommand(pfUlong requestID_);
        
        void processVarBindList(AsnInt &requestID_, VarBindList &list_);

        // Methods to where a function pointer can refers.
        void getFromMibTree(VarBind *var_);
        void getNextFromMibTree(VarBind *var_);

        // Send methods.
        void sendGetRequest(ilmiCommand *command_);
        void sendGetNextRequest(ilmiCommand *command_);
        void sendSetRequest(ilmiCommand *command_);

        void sendGetResponse(AsnInt &requestID_,
                             int errorStatus_,
                             int errorIndex_,
                             const VarBindList &list_);
        void sendColdStartTrap(const VarBindList &list_);

        void sendRequest(ilmiCommand *command_,
                         PDU *pdu_,
                         Message &message_);
        
        void sendMessage(Message &message_);
        
        void fillPdu(PDU *pdu_,
                     AsnInt &requestID_,
                     int errorStatus_,
                     int errorIndex_,
                     const VarBindList &list_) const;

        void clearCommandMap(void);
        
        // Static variables.
        static MessageInt SNMP_VERSION;
        static AsnOcts DEFAULT_COMMUNITY;
        
        static pfUlong MAX_REQUEST_ID;
        static pfUlong SNMP_MESSAGE_LENGTH;
        static pfUlong ENC_BUFFER_SIZE;
        static pfUlong ILMI_SDU_SIZE;
        
        // typedefs
        typedef map<pfUlong, ilmiCommand*, less<pfUlong> > mapType;
        typedef mapType::iterator mapIterType;
        typedef mapType::const_iterator mapConstIterType;
        typedef void (ilmiProtocol::*FunctionPointer) (VarBind *);

        // Attributes
        ilmiAddressRegistration _addressRegistration;        
        mibTree _mibTree;
        
        mapType _commandMap;
        pfUlong _cursor;        

        FunctionPointer _functionPointer;

        struct sockaddr_in _udpAddress;

        // Message "prototypes"
        Message _getRequestMessage;
        Message _getNextRequestMessage;
        Message _getResponseMessage;
        Message _setRequestMessage;
        Message _trapMessage;

        // Proxies
        pfConduit _ilmiProxy;
        pfConduit _cpcsProxy;

        pfUlong _controlPort;
};

#endif // __ILMI_PROTOCOL_H__
