Ticket #203: 0001-Migrated-Listener-to-Twisted-endpoints-Service.patch

File 0001-Migrated-Listener-to-Twisted-endpoints-Service.patch, 5.0 KB (added by str4d, 11 years ago)
  • foolscap/pb.py

    From a25d4f4a712857a0d07a39a8b23884d6bd39890e Mon Sep 17 00:00:00 2001
    From: str4d <str4d@mail.i2p>
    Date: Wed, 16 Oct 2013 20:40:32 -0500
    Subject: [PATCH] Migrated Listener to Twisted endpoints Service
    
    ---
     foolscap/pb.py | 52 ++++++++++++++++++++++++++++++++++------------------
     1 file changed, 34 insertions(+), 18 deletions(-)
    
    diff --git a/foolscap/pb.py b/foolscap/pb.py
    index 473d853..88a16fa 100644
    a b  
    33import os.path, weakref, binascii, re
    44from zope.interface import implements
    55from twisted.internet import defer, protocol, error
     6from twisted.internet.endpoints import serverFromString
    67from twisted.application import service, internet
    78from twisted.python.failure import Failure
    89
    except ImportError: 
    2526    pass
    2627
    2728
     29# TODO: Only used by foolscap.logging.web, remove when
     30# that has been migrated to use Twisted endpoints.
    2831def parse_strport(port):
    2932    if port.startswith("unix:"):
    3033        raise ValueError("UNIX sockets are not supported for Listeners")
    class Listener(protocol.ServerFactory): 
    5053
    5154    # this also serves as the ServerFactory
    5255
    53     def __init__(self, port, options={},
     56    def __init__(self, desc, options={},
    5457                 negotiationClass=negotiate.Negotiation):
    5558        """
    56         @type port: string
    57         @param port: a L{twisted.application.strports} -style description,
    58         specifying a TCP server
     59        @type desc: string
     60        @param desc: a L{twisted.internet.endpoints.serverFromString} -style
     61        description, specifying the endpoint to use
    5962        """
    60         # parse the following 'port' strings:
    61         #  80
    62         #  tcp:80
    63         #  tcp:80:interface=127.0.0.1
    64         # we reject UNIX sockets.. I don't know if they ever worked.
    65 
    66         portnum, interface = parse_strport(port)
    67         self.port = port
     63        self.desc = desc
    6864        self.options = options
    6965        self.negotiationClass = negotiationClass
    7066        self.parentTub = None
    7167        self.tubs = {}
    7268        self.redirects = {}
    73         self.s = internet.TCPServer(portnum, self, interface=interface)
     69        # Import the reactor here so we don't mess up reactor selection
     70        from twisted.internet import reactor
     71        endpoint = serverFromString(reactor, desc)
     72        self.s = internet.StreamServerEndpointService(endpoint, self)
     73        self.port = None
    7474        Listeners.append(self)
    7575
     76    def setPort(self, port):
     77        self.port = port
     78
    7679    def getPortnum(self):
    7780        """When this Listener was created with a port string of '0' or
    7881        'tcp:0' (meaning 'please allocate me something'), and if the Listener
    class Listener(protocol.ServerFactory): 
    8689        """
    8790
    8891        assert self.s.running
    89         return self.s._port.getHost().port
     92        # TODO: Not all endpoints will necessarily have a port?
     93        return self.port.getHost().port
     94
     95    def getHost(self):
     96        """
     97        Returns the IAddress provider for the endpoint.
     98        """
     99        # The IListeningPort is started when we get it.
     100        assert self.port
     101        return self.port.getHost()
    90102
    91103    def __repr__(self):
    92104        if self.tubs:
    93105            return "<Listener at 0x%x on %s with tubs %s>" % (
    94106                abs(id(self)),
    95                 self.port,
     107                self.desc,
    96108                ",".join([str(k) for k in self.tubs.keys()]))
    97109        return "<Listener at 0x%x on %s with no tubs>" % (abs(id(self)),
    98                                                           self.port)
     110                                                          self.desc)
    99111
    100112    def addTub(self, tub):
    101113        if tub.tubID in self.tubs:
    102114            if tub.tubID is None:
    103115                raise RuntimeError("This Listener (on %s) already has an "
    104116                                   "unauthenticated Tub, you cannot add a "
    105                                    "second one" % self.port)
     117                                   "second one" % self.desc)
    106118            raise RuntimeError("This Listener (on %s) is already connected "
    107                                "to TubID '%s'" % (self.port, tub.tubID))
     119                               "to TubID '%s'" % (self.desc, tub.tubID))
    108120        self.tubs[tub.tubID] = tub
    109121        if self.parentTub is None:
    110122            self.parentTub = tub
    111123            self.s.setServiceParent(self.parentTub)
     124            if self.s._waitingForPort:
     125                self.s._waitingForPort.addCallback(self.setPort)
    112126
    113127    def removeTub(self, tub):
    114128        # this might return a Deferred, since the removal might cause the
    class Listener(protocol.ServerFactory): 
    124138                # do this? It looks like setServiceParent does
    125139                # disownServiceParent first, so it may glitch.
    126140                self.s.setServiceParent(self.parentTub)
     141                if self.s._waitingForPort:
     142                    self.s._waitingForPort.addCallback(self.setPort)
    127143            else:
    128144                # no more tubs, this Listener will go away now
    129145                d = self.s.disownServiceParent()