Twisted - extending portforward (simple example)
Andrew Bennetts
andrew-pythonlist at puzzling.org
Fri Jun 27 23:22:03 EDT 2003
On Fri, Jun 27, 2003 at 03:42:20AM -0700, Paul Moore wrote:
> I hit a problem yesterday with my mail connection. In a desparate
> attempt to understand what was going on, I wanted to log the
> connection traffic. After a bit of searching, I found a post on c.l.p
> from Andrew Bennetts explaining how to run a port forwarder in 2 lines
> using Twisted.
>
> $ mktap portforward -p 8000 -h remote -d 20
> $ twistd -f portforward.tap
>
> This looked brilliant - all I needed to do was add logging. A quick
> look (I was *very* short of time, so I couldn't spend long) showed me
> no obvious way of adding a hook (at least, not one which wouldn't turn
> the above 2-liner into something more complex, that I didn't have time
> to work out...) So I gave in, and just added a print statement in the
> twisted code.
>
> This gave me the results I wanted, but left me wondering (and not
> getting far in finding out!) how I *should* have done this.
>
> Ideally, I was expecting to be able to write a small .py file,
> importing and minimally overriding portforward.py, and then be able to
> do the mktap/twistd thing. But I couldn't see how.
The easiest way is probably to do this:
--- loggingpf.py ---
from twisted.internet import app
from twisted.python import log
from twisted.protocols import portforward
from twisted.tap.portforward import Options
class LoggingProxyClient(portforward.ProxyClient):
def dataReceived(self, data):
log.msg('server sent: ' + repr(data))
portforward.ProxyClient.dataReceived(self, data)
class LoggingProxyClientFactory(portforward.ProxyClientFactory):
protocol = LoggingProxyClient
class LoggingProxyServer(portforward.ProxyServer):
clientProtocolFactory = LoggingProxyClientFactory
def dataReceived(self, data):
log.msg('client sent: ' + repr(data))
portforward.ProxyServer.dataReceived(self, data)
class LoggingProxyFactory(portforward.ProxyFactory):
protocol = LoggingProxyServer
application = app.Application('LoggingPortForward')
application.listenTCP(8000, LoggingProxyFactory('localhost', 80))
--- end --
Then you can use
$ twistd -n -o -y loggingpf.py
You could easily adapt this to become a mktap plugin; see
http://twistedmatrix.com/documents/howto/plugin
(For instance, the normal portforward plugin is defined in
twisted/plugins.tml and twisted/tap/portforward.py)
An even lazier approach would be to add an "application.run(save=0)" to the
end of loggingpf.py -- then you'd be able to run it directly as
$ python loggingpf.py
(but using twistd gives you the ability to daemonise, use log files, etc).
> Can anyone give me a simple example of how I should have done this?
> The logging portforwarder example seems like a nice simple starting
> point, from which I can go on and learn how to do clever stuff :-)
Unfortunately, it's not very simple, as you can see -- although you only
need to override two methods (ProxyClient.dataReceived and
ProxyServer.dataReceived), you need to make four subclasses to tie it all
together.
-Andrew.
More information about the Python-list
mailing list