#ifndef _MGEN_EVENT
#define _MGEN_EVENT

#include "mgenPattern.h"
#include "protokit.h"

// Generic base class for MgenEvent and DrecEvent
class MgenBaseEvent
{
    friend class MgenEventList;
    
    public:
        enum Category {MGEN, DREC};
        // Possible protocol types
        enum Protocol
        {
            INVALID_PROTOCOL,
            UDP,
            TCP,
            SINK
        }; 
        static Protocol GetProtocolFromString(const char* string);
        static const char* GetStringFromProtocol(Protocol protocol);
    
        Category GetCategory() const {return category;}
        void SetTime(double theTime) {event_time = theTime;}
        double GetTime() const {return event_time;}
        const MgenBaseEvent* Next() const {return next;}
        const MgenBaseEvent* Prev() const {return prev;}
        
    protected:
        MgenBaseEvent(Category cat);
        // for mapping protocol types from script line fields
        static const StringMapper PROTOCOL_LIST[]; 
        
    
        Category        category;
        double          event_time;
        MgenBaseEvent*  prev;
        MgenBaseEvent*  next;
        
};  // end class MgenBaseEvent

class DrecEvent : public MgenBaseEvent
{
    public:
        // DREC script event types
        enum Type
        {
            INVALID_TYPE,
            JOIN,
            LEAVE,
            LISTEN,
            IGNORE_  // trailing '_' for WIN32
        };
        static Type GetTypeFromString(const char* string);  

        DrecEvent();
        bool InitFromString(const char* string);
        
        Type GetType() const {return event_type;};
        Protocol GetProtocol() const {return protocol;}
        const ProtoAddress& GetGroupAddress() const {return group_addr;}
        const char* GetInterface()  const
            {return (('\0' != interface_name[0]) ? interface_name : (const char*)NULL);}
        unsigned short GetPortCount() const {return port_count;}
        const unsigned short* GetPortList() const {return port_list;}
        unsigned short GetGroupPort() const {return port_count;}        
        unsigned int GetRxBuffer() const {return rx_buffer_size;}            
        
    private:
        unsigned short* CreatePortArray(const char* portList,
                                        unsigned short* portCount);
        static const StringMapper TYPE_LIST[];     // for mapping event types
        enum Option
        {
            INTERFACE,
            PORT,
            RXBUFFER,
            INVALID_OPTION  
        };
        static const StringMapper OPTION_LIST[];
        static Option GetOptionFromString(const char* string);          
        
        Type            event_type;
        Protocol        protocol;
        // JOIN/LEAVE event parameters
        ProtoAddress  group_addr; 
        char            interface_name[16];
        // LISTEN/IGNORE event parameters
        unsigned short  port_count;  // (port_count is also used to hold the JOIN event PORT option)
        unsigned short* port_list;    
        unsigned int    rx_buffer_size;
            
};  // end class DrecEvent

class MgenEvent : public MgenBaseEvent
{    
    public:
        // MGEN script event types
        enum Type
        {
            INVALID_TYPE,
            ON,
            MOD,
            OFF   
        };
        static Type GetTypeFromString(const char* string);
       
        // MGEN script option types/flags (indicates which options were invoked)
        enum Option
        {
            INVALID_OPTION = 0x0000,
            PROTOCOL =       0x0001,  // flow protocol was set
            DST =            0x0002,  // flow destination address was set
            SRC =            0x0004,  // flow source port was set
            PATTERN =        0x0008,  // flow pattern was set
            TOS =            0x0010,  // flow TOS was set
            RSVP =           0x0020,  // flow RSVP spec was set
            INTERFACE =      0x0040,  // flow multicast interface was set
            TTL =            0x0080,  // flow ttl was set
            SEQUENCE =       0x0100,  // flow sequence number was set        
            LABEL =          0x0200,  // flow label option for IPV6
            TXBUFFER  =      0x0400   // Tx socket buffer size
        };
            
        MgenEvent();    
        
        bool InitFromString(const char* string);
        
        unsigned int GetFlowId() const {return flow_id;}
        Type GetType() const {return event_type;}
        unsigned short GetSrcPort() const {return src_port;}
        const ProtoAddress& GetDstAddr() const {return dst_addr;}
        const MgenPattern& GetPattern() const {return pattern;}
        Protocol GetProtocol() const {return protocol;}
        int GetTOS() const {return tos;}
        UINT32 GetFlowLabel() const {return flow_label;}
        unsigned char GetTTL() const {return ttl;}
        unsigned int GetTxBuffer() const {return tx_buffer_size;}
        unsigned long GetSequence() const {return sequence;}
        const char* GetInterface()  const
            {return (('\0' != interface_name[0]) ? interface_name : NULL);}
        
        bool OptionIsSet(Option option) const
            {return (0 != (option & option_mask));}
        
        
    private:
        static const StringMapper TYPE_LIST[];     // for mapping event types
        static const StringMapper OPTION_LIST[];   // for mapping event options
        static Option GetOptionFromString(const char* string);
        static const char* GetStringFromOption(Option option);
        static const unsigned int ON_REQUIRED_OPTIONS;
        
        // Event parameters and options
        unsigned long    flow_id;
        Type             event_type;
        unsigned short   src_port;
        ProtoAddress   dst_addr;        
        MgenPattern      pattern;          
        Protocol         protocol;            
        int              tos;
        UINT32           flow_label;
        unsigned int     tx_buffer_size;    
        unsigned char    ttl;   
        unsigned long    sequence;
        char             interface_name[16];
                  
        unsigned int     option_mask;
};  // end class MgenEvent


// time ordered, linked list of MgenEvent or DrecEvent
class MgenEventList
{
    public:
      MgenEventList();
      ~MgenEventList();
      void Destroy();
      void Insert(MgenBaseEvent* theEvent);
      void Remove(MgenBaseEvent* theEvent);
      // This places "theEvent" _before_ "nextEvent" in the list.
      // (If "nextEvent" is NULL, "theEvent" goes to the end of the list)
      void Precede(MgenBaseEvent* nextEvent, MgenBaseEvent* theEvent);
      
      bool IsEmpty() {return (NULL == head);}
      const MgenBaseEvent* Head() const {return head;}
      const MgenBaseEvent* Tail() const {return tail;}
      
    private:
      MgenBaseEvent* head; 
      MgenBaseEvent* tail; 
}; // end class MgenEventList 


#endif // _MGEN_EVENT


syntax highlighted by Code2HTML, v. 0.9.1