PySNMP Project Logo

Project diary
Documentation
Examples
License
Download
Mailing lists

Projects using PySNMP
TwistedSNMP
Zenoss


Relevant projects
SNMPy
YAPSNMP
LibSMI
Scotty software

SourceForge Logo

import time
import string
import socket
from types import ClassType
import asyncore
import asynchat
import getopt

# Import PySNMP modules
from pysnmp import asn1, v1, v2c
from pysnmp import asynrole, error

# Initialize a dictionary of running telnet engines
global_engines = {}

class telnet_engine(asynchat.async_chat):
    """Telnet engine class. Implements command line user interface and
       SNMP request queue management.

       Each new SNMP request message context is put into a pool of pending
       requests. As response arrives, it's matched against each of pending
       message contexts.
    """
    def __init__ (self, sock):
        # Call constructor of the parent class
        asynchat.async_chat.__init__ (self, sock)

        # Set up input line terminator
        self.set_terminator ('\n')

        # Initialize input data buffer
        self.data = ''

        # Create async SNMP transport manager
        self.manager = asynrole.manager(self.request_done_fun)
        
        # A queue of pending requests
        self.pending = []

        # Run our own source of SNMP message serial number to preserve its
        # sequentiality
        self.request_id = 1

        # Register this instance of telnet engine at a global dictionary
        # used for their periodic invocations for timeout purposes
        global_engines[self] = 1

        # User interface goodies
        self.prompt = 'query> '
        self.welcome = 'Example Telnet server / SNMP manager ready.\n'

        # Commands help messages
        commands =            'Commands:\n'

        for mod in (v1, v2c):
            rtypes = dir(mod)
            for rtype in rtypes:
                if rtype[-7:] == 'REQUEST':
                    commands = commands + '  ' + '%-14s' % rtype[:-7] + \
                               ' issue SNMP (%s) %s request\n' % \
                               (mod.__name__[7:], rtype[:-7])

        # Options help messages
        options =           'Options:\n'
        options = options + '  -p       port to communicate with at the agent. Default is 161.\n'
        options = options + '  -t    response timeout. Default is 1.'
        self.usage = 'Syntax:  [options]    ' + str(val) + '\n'

        # Send reply back to user
        self.push(reply + self.prompt)

    def tick(self, now):
        """This method gets invoked periodically from upper scope for
           generic housekeeping purposes.
        """
        # Walk over pending message context
        for (req, dst, expire) in self.pending:
            # Expire long pending contexts
            if expire < now:
                # Send a notice on expired request context
                self.push('WARNING: expiring long pending request %s destined %s\n' % (req, dst))

                # Expire context
                self.pending.remove((req, dst, expire))
        
class telnet_server(asyncore.dispatcher):
    """Telnet server class. Listens for incoming requests and creates
       instances of telnet engine classes for handling new session.
    """
    def __init__(self, port=8989):
        """Takes optional TCP port number for the server to bind to.
        """
        # Call parent class constructor explicitly
        asyncore.dispatcher.__init__(self)
        
        # Create socket of requested type
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)

        # Set it to re-use address
        self.set_reuse_addr()
        
        # Bind to all interfaces of this host at specified port
        self.bind(('', port))
        
        # Start listening for incoming requests
        self.listen(5)

    def handle_accept(self):
        """Called by asyncore engine when new connection arrives
        """
        # Accept new connection
        (sock, addr) = self.accept()

        # Create an instance of Telnet engine class to handle this new user
        # session and pass it socket object to use any further
        telnet_engine(sock)

# Run the module if it's invoked for execution
if __name__ == '__main__':
    # Create an instance of Telnet superserver
    server = telnet_server ()

    # Start the select() I/O multiplexing loop
    while 1:
        # Deliver 'tick' event to every instance of telnet engine
        map(lambda x: x.tick(time.time()), global_engines.keys())

        # Do the I/O on active sockets
        asyncore.poll(1.0)

Need help? Try PySNMP mailing lists.