[Pysnmp-dev] [PATCH] first commit of twisted transport and dispatcher
Brought to you by:
elie
From: Filippo G. <fi...@tr...> - 2009-01-24 15:38:18
|
Hi, the patch below ought to add a dispatcher and an udp transport to be used with twisted, IOW you can use pysnmp while running a twisted reactor. thanks in advance, filippo --- pysnmp/v4/carrier/twisted/dispatch.py | 61 +++++++++++++++++++++++++++ pysnmp/v4/carrier/twisted/udp.py | 74 +++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 0 deletions(-) create mode 100644 pysnmp/v4/carrier/twisted/__init__.py create mode 100644 pysnmp/v4/carrier/twisted/dispatch.py create mode 100644 pysnmp/v4/carrier/twisted/udp.py diff --git a/pysnmp/v4/carrier/twisted/__init__.py b/pysnmp/v4/carrier/twisted/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pysnmp/v4/carrier/twisted/dispatch.py b/pysnmp/v4/carrier/twisted/dispatch.py new file mode 100644 index 0000000..cba5074 --- /dev/null +++ b/pysnmp/v4/carrier/twisted/dispatch.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# +# -*- python -*- +# +# File: transport.py +# +# Copyright (C) 2008 Truelite Srl <in...@tr...> +# +# Author: Filippo Giunchedi <fi...@tr...> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License Version 2 +# as published by the Free Software Foundation +# +# Description: +# Transport dispatcher based on twisted.internet.reactor + +from time import time + +from twisted.internet import reactor, task + +from pysnmp.carrier.base import AbstractTransportDispatcher + +class ReactorDispatcher(AbstractTransportDispatcher): + """TransportDispatcher based on twisted.internet.reactor""" + def __init__(self, *args, **kwargs): + AbstractTransportDispatcher.__init__(self) + + self.timeout = 1 + if kwargs.has_key('timeout'): + self.timeout = kwargs['timeout'] + + self.loopingcall = task.LoopingCall(self.handleTimeout) + + def handleTimeout(self): + self.handleTimerTick(time()) + + def runDispatcher(self, timeout=0.0): + if not reactor.running: + reactor.run() + +# jobstarted/jobfinished might be okay as-is + + def registerTransport(self, tDomain, transport): + if not self.loopingcall.running and self.timeout > 0: + self.loopingcall.start(self.timeout, now = False) + AbstractTransportDispatcher.registerTransport(self, tDomain, transport) + # Ugly, but we need to call handleTimerTick() asyncronously from transports now. + # IOW, it is not possibile to call handleTimerTick after poll()ing every transport' socket + transport.dispatcher = self + + def unregisterTransport(self, tDomain): + t = AbstractTransportDispatcher.getTransport(self, tDomain) + if t is not None: + AbstractTransportDispatcher.unregisterTransport(self, tDomain) + t.closeTransport() + + if len(self._AbstractTransportDispatcher__transports) == 0: + # the last transport has been removed, stop the timeout + if self.loopingcall.running: + self.loopingcall.stop() diff --git a/pysnmp/v4/carrier/twisted/udp.py b/pysnmp/v4/carrier/twisted/udp.py new file mode 100644 index 0000000..dbb657a --- /dev/null +++ b/pysnmp/v4/carrier/twisted/udp.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# +# -*- python -*- +# +# File: transport.py +# +# Copyright (C) 2008 Truelite Srl <in...@tr...> +# +# Author: Filippo Giunchedi <fi...@tr...> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License Version 2 +# as published by the Free Software Foundation +# +# Description: +# twisted DatagramProtocol UDP transport + +from time import time + +from twisted.internet import reactor +from twisted.internet.protocol import DatagramProtocol + +from pysnmp.carrier import error + +class ReactorUDPTransport(DatagramProtocol): + """UDP Transport based on twisted, to be used with ReactorDispatcher""" + + def __init__(self): + self.__writeQ = [] + +# twisted API + def datagramReceived(self, datagram, address): + if self._cbFun is not None: + self._cbFun(self, address, datagram) + else: + raise error.CarrierError('Unable to call cbFun') + + if self.dispatcher is not None: + self.dispatcher.handleTimerTick(time()) + else: + raise error.CarrierError('Unable to call handleTimerTick') + + def startProtocol(self): + while self.__writeQ: + msg, addr = self.__writeQ.pop(0) + self.transport.write(msg, addr) + + def stopProtocol(self): + self.unregisterCbFun() + self.dispatcher = None + +# asyncore AbstractSocketTransport API + def openClientMode(self, iface=''): + self._lport = reactor.listenUDP(0, self, iface) + return self + + def openServerMode(self, iface=None): + self._lport = reactor.listenUDP(iface[1], self, iface[0]) + return self + + def sendMessage(self, outgoingMessage, transportAddress): + if self.transport is None: + self.__writeQ.append((outgoingMessage, transportAddress)) + else: + self.transport.write(outgoingMessage, transportAddress) + + def registerCbFun(self, cbFun): + self._cbFun = cbFun + + def unregisterCbFun(self): + self._cbFun = None + + def closeTransport(self): + self.transport.stopListening() -- 1.6.0.6 |