
On Sun, Sep 28, 2003 at 12:58:04AM +0200, Paul Boehm wrote:
ugh.. using webinterfaces without a mouse is horror.. so i'll do it again and submit another patch here:
i've updated the patch (see end of mail) all trial tests pass sample code why i need the patch included also, i want to ask the list if everyone is okay with me getting cvs access to create and maintain twisted.proxy, a generic proxy, currently capable of transparent proxying using netfilter, pseudotransparent proxying using a shared lib (seperate c code required), and web.proxy, which i'll update or rewrite soon. and a rfc: in the sample code below, i find the way i handle listening in a service instead of the application, a lot more natural. if i stopService() at runtime, i expect the ports of that service to go down at the same time. anything speaking against implementing the neccesary code in application.Service? my expectation is that after the app refactor, noone will want to listen directly in application anymore, so we could even start deprecating the old interface. sample code / usecase: ----------------------------------- # twisted imports from twisted.application import strports from twisted.application.service import Service # sibling imports from proxy.interfaces import * from proxy import adapters flavors = { 'any': IProxyFactory, # a proxy, any proxy! 'transparent': ITransProxyFactory, # a transparent proxy 'http': IHTTPProxyFactory, # a proxy speaking HTTP } def parsePROXY(type, service, port, subproto="any", transport="tcp"): adapter = flavors[subproto] return(transport.upper(), (int(port), adapter(service)), {}) strports.registerTransport("proxy", parsePROXY) class ProxyService(Service): """I am a service that starts proxies, and stores shared policy for them.""" __implements__ = IProxyService def __init__(self, name, parent, *portspecs): self.portstrs = [] self.listeners = [] self.setName(name) self.setServiceParent(parent) for pspec in portspecs: self.listen(pspec) def listen(self, description): self.portstrs.append(description) def doListen(self, description): transport = strports.listen(description, self) self.listeners.append(transport) def startService(self): Service.startService(self) for description in self.portstrs: self.doListen(description) def stopService(self): Service.stopService(self) for port in self.listeners: port.loseConnection() self.listeners.remove(port) ----------------------------------- patch: Index: strports.py =================================================================== RCS file: /cvs/Twisted/twisted/application/strports.py,v retrieving revision 1.1 diff -u -r1.1 strports.py --- strports.py 26 Sep 2003 22:44:48 -0000 1.1 +++ strports.py 28 Sep 2003 02:50:51 -0000 @@ -46,14 +46,22 @@ """ from __future__ import generators -def _parseTCP(factory, port, interface="", backlog=5): - return (int(port), factory), {'interface': interface, +_transportHelpers = {} + +def registerTransport(name, helper): + global _transportHelpers + _transportHelpers[name] = helper + +def _parseTCP(type, factory, port, interface="", backlog=5): + return type, (int(port), factory), {'interface': interface, 'backlog': int(backlog)} +registerTransport("tcp", _parseTCP) -def _parseUNIX(factory, address, mode='666', backlog=5): - return (address, factory), {'mode': int(mode, 8), 'backlog': int(backlog)} +def _parseUNIX(type, factory, address, mode='666', backlog=5): + return type, (address, factory), {'mode': int(mode, 8), 'backlog': int(backlog)} +registerTransport("unix", _parseUNIX) -def _parseSSL(factory, port, privateKey="server.pem", certKey=None, +def _parseSSL(type, factory, port, privateKey="server.pem", certKey=None, sslmethod=None, interface='', backlog=5): from twisted.internet import ssl if certKey is None: @@ -62,12 +70,9 @@ if sslmethod is not None: kw['sslmethod'] = getattr(ssl.SSL, sslmethod) cf = ssl.DefaultOpenSSLContextFactory(privateKey, certKey, **kw) - return ((int(port), factory, cf), + return (type, (int(port), factory, cf), {'interface': interface, 'backlog': int(backlog)}) - -_funcs = {"tcp": _parseTCP, - "unix": _parseUNIX, - "ssl": _parseSSL} +registerTransport("ssl", _parseSSL) _OP, _STRING = range(2) def _tokenize(description): @@ -104,7 +109,7 @@ add(sofar) return args, kw -def parse(description, factory, default=None): +def parse(description, factory, default='tcp'): """Parse a description of a reliable virtual circuit server @type description: C{str} @@ -148,8 +153,10 @@ """ args, kw = _parse(description) if not args or (len(args)==1 and not kw): - args[0:0] = [default or 'tcp'] - return (args[0].upper(),)+_funcs[args[0]](factory, *args[1:], **kw) + type = default + else: + type = args.pop(0) + return _transportHelpers[type](type.upper(), factory, *args, **kw) def service(description, factory, default=None): """Return the service corresponding to a description @@ -185,4 +192,4 @@ name, args, kw = parse(description, factory, default) return getattr(reactor, 'listen'+name)(*args, **kw) -__all__ = ['parse', 'service', 'listen'] +__all__ = ['registerTransport', 'parse', 'service', 'listen']