Twisted - extending portforward (simple example)

Andrew Bennetts andrew-pythonlist at puzzling.org
Sat Jun 28 05:22:03 CEST 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