Source

imalse / core / nodes / base_node.py

"""This file contains the virtual base class."""

import logging

from util.util import abstract_method 

class BaseNode(object):
    
    """ 
    
    Virtual base class for all nodes.
    All nodes should implement the API in this abstract first.
    
    """
    
    name = 'base_node'
    
    def __init__(self):
        self.sockets = dict()
        self.logger = self.set_logger()

    def set_logger(self):
        """Set a logger for debugging purposes"""
        logging.basicConfig()
        logger = logging.getLogger(self.name)
        # self.logger.setLevel(logging.DEBUG)
        logger.setLevel(logging.WARNING)
        return logger

    def start(self):
        """Start the node."""
        abstract_method()

    #################################
    ###  Some Utility Function    ###
    #################################
    @property
    def now(self):
        """Get the current time, either simulation time or real time."""
        abstract_method()
    
    def sleep(self, time, call_back=None):
        """Let the node sleep.
        
        Keyword arguments:
        t -- time that the node sleeps in seconds
        call_back -- if specified, this will be called when the node awakes.
        
        """
        abstract_method()

    def create_timer(self, time, call_back):
        """Create a timer that calls a call_back after t seconds."""
        abstract_method()
    
    #################################
    ###  Network Related          ###
    #################################
    def set_master_sock(self, sock):
        """Set a socket as the master socket."""
        self.sockets[sock]['type'] = 'master'
    
    @property
    def master_sock(self):
        """Return the master socket."""               
        for sock, val in self.sockets.iteritems():
            if val['type'] == 'master': return sock
        
        return None
    
    @property
    def client_socks(self):
        """Return an array containing the client sockets."""
        sockets = []
        
        for sock, val in self.sockets.iteritems():
            if val['type'] == 'client': sockets.append(sock)
        
        return sockets

    #### Socket API ####
    def create_sock(self, desc):
        """Create and return a new socket.
        
        Keyword arguments:
        desc -- the address and port it tries to connect to and the type of 
                the connection.
        
        """
        abstract_method()

    def bind(self, sock, port):
        """Bind the socket to port"""
        abstract_method()

    def listen(self, sock, backlog):
        """Listen for connections made to the socket. 
        
        Keyword arguments:
        backlog -- specifies the maximum number of queued connections.
        
        """
        abstract_method()

    def accept(self, sock):        
        """Accept a connection and return the accepted socket."""
        abstract_method()

    def recv(self, sock, bufsize, dispatcher, threaded=False):
        """Receive data from a socket.
        
        Keyword arguments:
        sock -- the socket in question
        bufsize -- the maximum buffer size
        dispatcher -- a function handler that will manipulate the data
        threaded -- if true a new thread will be created to avoid
                    blocking the main process. Only supported by 'real' nodes. 
                    Threading is not allowed for simulated nodes. 
        """
        abstract_method()

    def send(self, sock, data):
        """Send data to the socket."""
        abstract_method()

    def connect(self, sock, addr_port):
        """Connect to a remote socket at addr_port."""
        abstract_method()

    def sendto(self, sock, data, addr, port):
        """
        
        Send data to the socket. The destination socket is specified
        by the address.
        
        """
        abstract_method()

    def close(self, sock):
        """Close a specific socket."""
        abstract_method()

    def close_socks(self, socket_ids):
        """Specific sockets will be closed. 
        
        Keyword arguments:
        socket_ids -- specifies which sockets will be closed.
        
        """
        socks_set = [self.client_socks[i] for i in socket_ids]
        for sock in socks_set:
            sock.close()
            del self.sockets[sock]

    #################################
    ###  Application Layer    #######
    #################################
    def ping(self, sock, data, threaded=False):
        """Send ping traffic to hosts.
        
        Keyword arguments:
        sock -- the used socket
        data -- contains the server information
        threaded -- create a separate thread if true
        
        """
        abstract_method()

    def ftp(self, sock, data, threaded=False):
        """Send data using ftp through the socket."""
        abstract_method()

    def icmp(self, sock, data, threaded=False):
        """Send data using icmp through the socket."""
        abstract_method()

    def http(self, sock, data, threaded=False):
        """Send data using http through the socket."""
        abstract_method()

    def stop_app(self, sock, app_name):
        """Stop an application.
        
        Keyword arguments:
        sock -- stop the app running on this socket
        app_name -- the name of the app that will be stopped
        
        """
        abstract_method()