#ifndef _MGEN_SOCKET_LIST
#define _MGEN_SOCKET_LIST

#include "protokit.h"

class MgenSocketList
{
    public:

        enum
        {
            DEFAULT_TTL = 3,  // default multicast ttl
            DEFAULT_TOS = 0   // default type of service
        };   

        class Item
        { 
            friend class MgenSocketList;
            public:
                Item(ProtoSocket::Protocol theProtocol, unsigned short thePort);
                void SetSocketNotifier(ProtoSocket::Notifier* theNotifier)
                {
                    socket.SetNotifier(theNotifier); 
                }
                template <class listenerType>
                bool SetSocketListener(listenerType* theListener, 
                                       void(listenerType::*eventHandler)(ProtoSocket&, ProtoSocket::Event))
                {
                    return socket.SetListener(theListener, eventHandler);    
                }                
                ProtoSocket& GetSocket() {return socket;}
                bool Open(ProtoAddress::Type addrType, bool bindOnOpen);
                void Close();
                bool JoinGroup(const ProtoAddress& groupAddress, 
                               const char* interfaceName = NULL);
                bool LeaveGroup(const ProtoAddress& theAddress, 
                                const char* interfaceName = NULL);
                unsigned int GroupCount() {return group_count;}
                bool SocketHasListener() {return (socket.HasListener());}

        	    bool SetTTL(unsigned char TTL);
        	    unsigned char GetTTL(){return ttl;}
                
        	    bool SetTOS(unsigned char tos);
        	    unsigned char GetTOS(){return tos;}

        	    bool SetTxBufferSize(unsigned int txBufferSize);
                unsigned int GetTxBufferSize() {return tx_buffer;}
        	    bool SetRxBufferSize(unsigned int rxBufferSize);
        	    unsigned int GetRxBufferSize() {return rx_buffer;}

                bool SetMulticastInterface(const char* interfaceName);
                const char* GetMulticastInterface()
                {
                    return (('\0' != interface_name[0]) ? 
                            interface_name : NULL);
                }

            private: 
                ProtoSocket     socket;
                unsigned char   tos;
                unsigned char   ttl;   // multicast time-to-live  
                unsigned int    tx_buffer;
                unsigned int    rx_buffer;        
                char            interface_name[16];
                unsigned short  port;
                unsigned int    reference_count; //mgen flows and drec-multicast ports
                unsigned int    group_count;
                Item*           prev;  
                Item*           next;  
        };  // end class MgenSocketList::Item

        MgenSocketList();
        ~MgenSocketList();
        void Destroy();

        void SetSocketNotifier(ProtoSocket::Notifier* socketNotifier)
        {
            socket_notifier = socketNotifier;
        }
        //Item* FindItemBySocket(const ProtoSocket* socket);
        Item* FindItemByPort(ProtoSocket::Protocol theProtocol, 
                             unsigned short        thePort);
        Item* FindItemByInterface(ProtoSocket::Protocol theProtocol, 
                                  const char*           interfaceName,
                                  unsigned short        thePort = 0);
        
        Item* GetItem(ProtoSocket::Protocol theProtocol, 
                      unsigned short thePort = 0);
        
        Item* JoinGroup(const ProtoAddress& groupAddress, 
                        const char*           interfaceName = NULL,
                        unsigned short        thePort = 0);
        bool LeaveGroup(MgenSocketList::Item* item,
                        const ProtoAddress& groupAddress, 
                        const char*           interfaceName = NULL);
        
      	void SetDefaultTtl(unsigned int ttlValue, bool override)
        {
            default_ttl = default_ttl_lock ?
                            (override ? ttlValue : default_ttl) :
                            ttlValue;
            default_ttl_lock = override ? true : default_ttl_lock;
        }
       	unsigned int GetDefaultTtl(){return default_ttl;}

       	void SetDefaultTos(unsigned int tosValue, bool override)
        {
            default_tos = default_tos_lock ?
                            (override ? tosValue : default_tos) :
                            tosValue;  
            default_tos_lock = override ? true : default_tos_lock;
        }
       	unsigned int GetDefaultTos(){return default_tos;}

	    void SetDefaultTxBufferSize(unsigned int bufferSize, bool override)
        {
            default_tx_buffer = default_tx_buffer_lock ?
                                (override ? bufferSize : default_tx_buffer) :
                                bufferSize;  
            default_tx_buffer_lock = override ? true : default_tx_buffer_lock;
        }
        unsigned int GetDefaultTxBufferSize() {return default_tx_buffer;}
        
	    void SetDefaultRxBufferSize(unsigned int bufferSize, bool override)
        {
            default_rx_buffer = default_rx_buffer_lock ?
                                 (override ? bufferSize : default_rx_buffer) :
                                 bufferSize;  
            default_rx_buffer_lock = override ? true : default_rx_buffer_lock;
        }
        unsigned int GetDefaultRxBufferSize() {return default_rx_buffer;}

        void SetDefaultMulticastInterface(const char* interfaceName, bool override)
        {
            if (override || !default_interface_lock)
            {
                if (interfaceName)
                    strncpy(default_interface, interfaceName, 16);
                else
                    default_interface[0] = '\0'; 
            }
            default_interface_lock = override ? true : default_interface_lock;   
        }
	    const char* GetDefaultMulticastInterface() 
            {return (('\0' != default_interface[0]) ? default_interface : NULL);}

        
    private:
        void Prepend(Item* item);
        void Append(Item* item);
        void Remove(Item* item);
        
        ProtoSocket::Notifier*  socket_notifier;  
        Item*                   head;                  
        Item*                   tail;                  
        unsigned int            default_tx_buffer;                             
        unsigned int            default_rx_buffer;                             
        unsigned char           default_tos;                                        
        unsigned char           default_ttl;           // multicast ttl            
        char                    default_interface[16]; // multicast interface name  

        // Socket state
        bool                    default_tos_lock;
        bool                    default_ttl_lock;
        bool                    default_tx_buffer_lock;     
        bool                    default_rx_buffer_lock;     
        bool                    default_interface_lock;
       
};  // end class MgenSocketList

#endif // _MGEN_SOCKET_LIST


syntax highlighted by Code2HTML, v. 0.9.1