Ticket #3014: Twisted-11.0.0-ipv6.chjurk.diff

File Twisted-11.0.0-ipv6.chjurk.diff, 17.3 KB (added by chjurk, 3 years ago)

IPv6 patch for Twisted 11.0.0

  • twisted/internet/abstract.py

    diff -ru ../Twisted-11.0.0/twisted/internet/abstract.py ./twisted/internet/abstract.py
    old new  
    99Maintainer: Itamar Shtull-Trauring 
    1010""" 
    1111 
     12import socket 
     13 
    1214from zope.interface import implements 
    1315 
    1416# Twisted Imports 
     
    412414        return -1 
    413415 
    414416 
    415 def isIPAddress(addr): 
     417def isIPv6Address(addr): 
     418    """ 
     419    Determine whether the given string represents an IPv6 address. 
     420 
     421        @param addr: A string which may or may not be the hexadecimal 
     422        representation of an IPv6 address. 
     423 
     424        @rtype: C{bool} 
     425        @return: C{True} if C{addr} represents an IPv6 address, C{False} 
     426    otherwise. 
     427    """ 
     428    if addr.find(":") != 1: 
     429        try: 
     430            socket.getaddrinfo(addr, 0, socket.AF_INET6, 0, 0, socket.AI_NUMERICHOST) 
     431        except socket.gaierror: 
     432            pass 
     433        else: 
     434            return True 
     435    return False 
     436 
     437def isIPv4Address(addr): 
    416438    """ 
    417439    Determine whether the given string represents an IPv4 address. 
    418440 
     
    437459        return True 
    438460    return False 
    439461 
     462def isIPAddress(addr): 
     463    """ 
     464    Determine whether the given string represents an IPv4 or IPv6 address. 
     465     
     466    @type addr: C{str} 
     467    @param addr: A string which may or may not be the decimal dotted 
     468    representation of an IPv4 address. 
     469 
     470    @rtype: C{bool} 
     471    @return: C{True} if C{addr} represents an IPv4 address, C{False} 
     472    """ 
     473    return isIPv4Address(addr) or isIPv6Address(addr) 
    440474 
    441475__all__ = ["FileDescriptor"] 
  • twisted/internet/address.py

    diff -ru ../Twisted-11.0.0/twisted/internet/address.py ./twisted/internet/address.py
    old new  
    55Address objects for network connections. 
    66""" 
    77 
    8 import warnings, os 
     8import warnings, os, socket 
    99 
    1010from zope.interface import implements 
    1111 
     
    1313from twisted.python import util 
    1414 
    1515 
    16 class IPv4Address(object, util.FancyEqMixin): 
     16class IPAddress(object, util.FancyEqMixin): 
    1717    """ 
    18     Object representing an IPv4 socket endpoint. 
     18    Object representing an IP socket endpoint. 
    1919 
    2020    @ivar type: A string describing the type of transport, either 'TCP' or 
    2121        'UDP'. 
     
    2525 
    2626    implements(IAddress) 
    2727 
    28     compareAttributes = ('type', 'host', 'port') 
     28    compareAttributes = ('type', 'family', 'host', 'port') 
    2929 
    30     def __init__(self, type, host, port, _bwHack = None): 
     30    def __init__(self, type, family, host, port, _bwHack = None): 
    3131        assert type in ('TCP', 'UDP') 
    3232        self.type = type 
     33        self.family = family 
    3334        self.host = host 
    3435        self.port = port 
    3536        if _bwHack is not None: 
     
    3738                    DeprecationWarning, stacklevel=2) 
    3839 
    3940    def __repr__(self): 
    40         return 'IPv4Address(%s, %r, %d)' % (self.type, self.host, self.port) 
     41        family_str = "IPv4" if self.family == socket.AF_INET else "IPv6" 
     42        return 'IPAddress(%s, %s, %r, %d)' % (self.type, family_str, self.host, self.port) 
    4143 
    4244 
    4345    def __hash__(self): 
    44         return hash((self.type, self.host, self.port)) 
    45  
     46        return hash((self.type, self.family, self.host, self.port)) 
    4647 
     48class IPv4Address(IPAddress): 
     49    """ 
     50    Generic version of IPv4Address. 
     51    """ 
     52    def __init(self, type, host, port): 
     53        IPAddress.__init__(type, socket.AF_INET, host, port, None)         
    4754 
    4855class UNIXAddress(object, util.FancyEqMixin): 
    4956    """ 
     
    9299 
    93100 
    94101 
     102class _ServerFactoryIPAddress(IPAddress): 
     103    def __eq__(self, other): 
     104        if isinstance(other, IPAddress): 
     105            a = (self.type, self.family, self.host, self.port) 
     106            b = (other.type, other.family, other.host, other.port) 
     107            return a == b 
     108        return False 
     109 
    95110# These are for buildFactory backwards compatability due to 
    96111# stupidity-induced inconsistency. 
    97112 
  • twisted/internet/base.py

    diff -ru ../Twisted-11.0.0/twisted/internet/base.py ./twisted/internet/base.py
    old new  
    249249            else: 
    250250                userDeferred.callback(result) 
    251251 
     252    def _lookup(self, name): 
     253        """ 
     254        Replacement for gethostbyname. 
     255        """ 
     256        ai = socket.getaddrinfo(name, 0) 
     257        assert len(ai) > 0 and len(ai[0]) >= 5 
     258         
     259        # Sort the result. IPv4 addresses should be preferred over 
     260        # IPv6 addresses to keep legacy applications working. 
     261        ai = sorted(ai, key=lambda fields: fields[0]) 
     262         
     263        return ai[0][4][0] 
    252264 
    253265    def getHostByName(self, name, timeout = (1, 3, 11, 45)): 
    254266        """ 
     
    265277        userDeferred = defer.Deferred() 
    266278        lookupDeferred = threads.deferToThreadPool( 
    267279            self.reactor, self.reactor.getThreadPool(), 
    268             socket.gethostbyname, name) 
     280            self._lookup, name) 
    269281        cancelCall = self.reactor.callLater( 
    270282            timeoutDelay, self._cleanup, name, lookupDeferred) 
    271283        self._runningQueries[lookupDeferred] = (userDeferred, cancelCall) 
  • twisted/internet/endpoints.py

    diff -ru ../Twisted-11.0.0/twisted/internet/endpoints.py ./twisted/internet/endpoints.py
    old new  
    145145 
    146146 
    147147 
    148 class TCP4ServerEndpoint(object): 
     148class TCPServerEndpoint(object): 
    149149    """ 
    150     TCP server endpoint with an IPv4 configuration 
     150    TCP server endpoint with an IP configuration 
    151151 
    152152    @ivar _reactor: An L{IReactorTCP} provider. 
    153153 
     
    186186                             backlog=self._backlog, 
    187187                             interface=self._interface) 
    188188 
     189""" Legacy: TCP4ServerEndpoint """ 
     190class TCP4ServerEndpoint(TCPServerEndpoint): 
     191    pass 
    189192 
    190  
    191 class TCP4ClientEndpoint(object): 
     193class TCPClientEndpoint(object): 
    192194    """ 
    193     TCP client endpoint with an IPv4 configuration. 
     195    TCP client endpoint with an IP configuration. 
    194196 
    195197    @ivar _reactor: An L{IReactorTCP} provider. 
    196198 
     
    245247        except: 
    246248            return defer.fail() 
    247249 
     250""" Legacy: TCP4ClientEndpoint """ 
     251class TCP4ClientEndpoint(TCPClientEndpoint): 
     252    pass 
    248253 
    249  
    250 class SSL4ServerEndpoint(object): 
     254class SSLServerEndpoint(object): 
    251255    """ 
    252     SSL secured TCP server endpoint with an IPv4 configuration. 
     256    SSL secured TCP server endpoint with an IP configuration. 
    253257 
    254258    @ivar _reactor: An L{IReactorSSL} provider. 
    255259 
     
    301305                             backlog=self._backlog, 
    302306                             interface=self._interface) 
    303307 
     308""" Legacy: SSL4ServerEndpoint """ 
     309class SSL4ServerEndpoint(SSLServerEndpoint): 
     310    pass 
    304311 
    305  
    306 class SSL4ClientEndpoint(object): 
     312class SSLClientEndpoint(object): 
    307313    """ 
    308     SSL secured TCP client endpoint with an IPv4 configuration 
     314    SSL secured TCP client endpoint with an IP configuration 
    309315 
    310316    @ivar _reactor: An L{IReactorSSL} provider. 
    311317 
     
    369375        except: 
    370376            return defer.fail() 
    371377 
    372  
     378""" Legacy: SSL4ClientEndpoint """ 
     379class SSL4ClientEndpoint(SSLClientEndpoint): 
     380    pass 
    373381 
    374382class UNIXServerEndpoint(object): 
    375383    """ 
     
    652660 
    653661# Mappings from description "names" to endpoint constructors. 
    654662_endpointServerFactories = { 
    655     'TCP': TCP4ServerEndpoint, 
    656     'SSL': SSL4ServerEndpoint, 
     663    'TCP': TCPServerEndpoint, 
     664    'SSL': SSLServerEndpoint, 
    657665    'UNIX': UNIXServerEndpoint, 
    658666    } 
    659667 
    660668_endpointClientFactories = { 
    661     'TCP': TCP4ClientEndpoint, 
    662     'SSL': SSL4ClientEndpoint, 
     669    'TCP': TCPClientEndpoint, 
     670    'SSL': SSLClientEndpoint, 
    663671    'UNIX': UNIXClientEndpoint, 
    664672    } 
    665673 
  • twisted/internet/iocpreactor/tcp.py

    diff -ru ../Twisted-11.0.0/twisted/internet/iocpreactor/tcp.py ./twisted/internet/iocpreactor/tcp.py
    old new  
    261261    def __init__(self, host, port, bindAddress, connector, reactor): 
    262262        self.connector = connector 
    263263        self.addr = (host, port) 
     264        self.addressFamily = connector.family 
    264265        self.reactor = reactor 
    265266        # ConnectEx documentation says socket _has_ to be bound 
    266267        if bindAddress is None: 
     
    352353 
    353354    def getHost(self): 
    354355        """ 
    355         Returns an IPv4Address. 
     356        Returns an IPAddress. 
    356357 
    357358        This indicates the address from which I am connecting. 
    358359        """ 
    359         return address.IPv4Address('TCP', *self.socket.getsockname()) 
     360        return address.IPAddress('TCP', self.socket.family, *self.socket.getsockname()) 
    360361 
    361362 
    362363    def getPeer(self): 
    363364        """ 
    364         Returns an IPv4Address. 
     365        Returns an IPAddress. 
    365366 
    366367        This indicates the address that I am connected to. 
    367368        """ 
    368         return address.IPv4Address('TCP', *self.realAddress) 
     369        return address.IPv4Address('TCP', self.addressFamily, *self.realAddress) 
    369370 
    370371 
    371372    def __repr__(self): 
     
    423424 
    424425    def getHost(self): 
    425426        """ 
    426         Returns an IPv4Address. 
     427        Returns an IPAddress. 
    427428 
    428429        This indicates the server's address. 
    429430        """ 
     
    432433 
    433434    def getPeer(self): 
    434435        """ 
    435         Returns an IPv4Address. 
     436        Returns an IPAddress. 
    436437 
    437438        This indicates the client's address. 
    438439        """ 
     
    482483 
    483484 
    484485    def startListening(self): 
     486        # Get the correct address family by using getaddrinfo() on the interface address 
     487        ai = socket.getaddrinfo(self.interface, self.port) 
     488        self.addressFamily = ai[0][0] 
     489         
    485490        try: 
    486491            skt = self.reactor.createSocket(self.addressFamily, 
    487492                                            self.socketType) 
     
    574579 
    575580    def getHost(self): 
    576581        """ 
    577         Returns an IPv4Address. 
     582        Returns an IPAddress. 
    578583 
    579584        This indicates the server's address. 
    580585        """ 
    581         return address.IPv4Address('TCP', *self.socket.getsockname()) 
     586        return address.IPAddress('TCP', self.socket.family, *self.socket.getsockname()) 
    582587 
    583588 
    584589    def cbAccept(self, rc, bytes, evt): 
     
    605610            assert family == self.addressFamily 
    606611 
    607612            protocol = self.factory.buildProtocol( 
    608                 address._ServerFactoryIPv4Address('TCP', rAddr[0], rAddr[1])) 
     613                address._ServerFactoryIPAddress('TCP', family, rAddr[0], rAddr[1])) 
    609614            if protocol is None: 
    610615                evt.newskt.close() 
    611616            else: 
    612617                s = self.sessionno 
    613618                self.sessionno = s+1 
    614619                transport = Server(evt.newskt, protocol, 
    615                         address.IPv4Address('TCP', rAddr[0], rAddr[1]), 
    616                         address.IPv4Address('TCP', lAddr[0], lAddr[1]), 
     620                        address.IPAddress('TCP', family, rAddr[0], rAddr[1]), 
     621                        address.IPAddress('TCP', family, lAddr[0], lAddr[1]), 
    617622                        s, self.reactor) 
    618623                protocol.makeConnection(transport) 
    619624            return True 
  • twisted/internet/iocpreactor/udp.py

    diff -ru ../Twisted-11.0.0/twisted/internet/iocpreactor/udp.py ./twisted/internet/iocpreactor/udp.py
    old new  
    5151 
    5252        abstract.FileHandle.__init__(self, reactor) 
    5353 
     54        # Get the correct address family by using getaddrinfo() on the interface address 
     55        ai = socket.getaddrinfo(self.interface, self.port) 
     56        self.addressFamily = ai[0][0] 
     57         
    5458        skt = socket.socket(self.addressFamily, self.socketType) 
    5559        addrLen = _iocp.maxAddrLen(skt.fileno()) 
    5660        self.addressBuffer = _iocp.AllocateReadBuffer(addrLen) 
     
    269273 
    270274    def getHost(self): 
    271275        """ 
    272         Returns an IPv4Address. 
     276        Returns an IPAddress. 
    273277 
    274278        This indicates the address from which I am connecting. 
    275279        """ 
    276         return address.IPv4Address('UDP', *self.socket.getsockname()) 
     280        return address.IPAddress('UDP', self.socket.family, *self.socket.getsockname()) 
    277281 
    278282 
    279283 
  • twisted/internet/tcp.py

    diff -ru ../Twisted-11.0.0/twisted/internet/tcp.py ./twisted/internet/tcp.py
    old new  
    695695        # BaseClient.__init__ is invoked later 
    696696        self.connector = connector 
    697697        self.addr = (host, port) 
    698  
     698        self.addressFamily = connector.family 
     699         
    699700        whenDone = self.resolveAddress 
    700701        err = None 
    701702        skt = None 
     
    714715        self._finishInit(whenDone, skt, err, reactor) 
    715716 
    716717    def getHost(self): 
    717         """Returns an IPv4Address. 
     718        """Returns an IPAddress. 
    718719 
    719720        This indicates the address from which I am connecting. 
    720721        """ 
    721         return address.IPv4Address('TCP', *self.socket.getsockname()) 
     722        return address.IPAddress('TCP', self.socket.family, *self.socket.getsockname()) 
    722723 
    723724    def getPeer(self): 
    724         """Returns an IPv4Address. 
     725        """Returns an IPAddress. 
    725726 
    726727        This indicates the address that I am connected to. 
    727728        """ 
    728         return address.IPv4Address('TCP', *self.realAddress) 
     729        return address.IPAddress('TCP', self.addressFamily, *self.realAddress) 
    729730 
    730731    def __repr__(self): 
    731732        s = '<%s to %s at %x>' % (self.__class__, self.addr, unsignedID(self)) 
     
    776777 
    777778 
    778779    def getHost(self): 
    779         """Returns an IPv4Address. 
     780        """Returns an IPAddress. 
    780781 
    781782        This indicates the server's address. 
    782783        """ 
    783         return address.IPv4Address('TCP', *self.socket.getsockname()) 
     784        return address.IPAddress('TCP', self.socket.family, *self.socket.getsockname()) 
    784785 
    785786    def getPeer(self): 
    786         """Returns an IPv4Address. 
     787        """Returns an IPAddress. 
    787788 
    788789        This indicates the client's address. 
    789790        """ 
    790         return address.IPv4Address('TCP', *self.client) 
     791        return address.IPAddress('TCP', self.socket.family, *self.client) 
    791792 
    792793 
    793794 
     
    848849            return "<%s of %s (not listening)>" % (self.__class__, self.factory.__class__) 
    849850 
    850851    def createInternetSocket(self): 
     852        # Get the correct address family by using getaddrinfo() on the interface address 
     853        ai = socket.getaddrinfo(self.interface, self.port) 
     854        self.addressFamily = ai[0][0] 
    851855        s = base.BasePort.createInternetSocket(self) 
    852856        if platformType == "posix" and sys.platform != "cygwin": 
    853857            s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
     
    863867        try: 
    864868            skt = self.createInternetSocket() 
    865869            skt.bind((self.interface, self.port)) 
     870            pass 
    866871        except socket.error, le: 
    867872            raise CannotListenError, (self.interface, self.port, le) 
    868873 
     
    885890 
    886891 
    887892    def _buildAddr(self, (host, port)): 
    888         return address._ServerFactoryIPv4Address('TCP', host, port) 
     893        return address._ServerFactoryIPAddress('TCP', self.addressFamily, host, port) 
    889894 
    890895 
    891896    def doRead(self): 
     
    939944                    raise 
    940945 
    941946                fdesc._setCloseOnExec(skt.fileno()) 
     947                 
     948                # IPv6 addresses have usually more than two fields, reduce them. 
     949                if len(addr) > 2: 
     950                    addr = addr[0:2] 
     951                 
    942952                protocol = self.factory.buildProtocol(self._buildAddr(addr)) 
    943953                if protocol is None: 
    944954                    skt.close() 
     
    10091019        return reflect.qual(self.factory.__class__) 
    10101020 
    10111021    def getHost(self): 
    1012         """Returns an IPv4Address. 
     1022        """Returns an IPAddress. 
    10131023 
    10141024        This indicates the server's address. 
    10151025        """ 
    1016         return address.IPv4Address('TCP', *self.socket.getsockname()) 
     1026        return address.IPAddress('TCP', self.socket.family, *self.socket.getsockname()) 
    10171027 
    10181028class Connector(base.BaseConnector): 
    10191029    def __init__(self, host, port, factory, timeout, bindAddress, reactor=None): 
     1030        ai = socket.getaddrinfo(host, port) 
     1031        self.family = ai[0][0] 
    10201032        self.host = host 
    10211033        if isinstance(port, types.StringTypes): 
    10221034            try: 
     
    10311043        return Client(self.host, self.port, self.bindAddress, self, self.reactor) 
    10321044 
    10331045    def getDestination(self): 
    1034         return address.IPv4Address('TCP', self.host, self.port) 
     1046        return address.IPAddress('TCP', self.family, self.host, self.port) 
  • twisted/internet/udp.py

    diff -ru ../Twisted-11.0.0/twisted/internet/udp.py ./twisted/internet/udp.py
    old new  
    8686        self._connectToProtocol() 
    8787 
    8888    def _bindSocket(self): 
     89        # Get the correct address family by using getaddrinfo() on the interface address 
     90        ai = socket.getaddrinfo(self.interface, self.port) 
     91        self.addressFamily = ai[0][0] 
     92         
    8993        try: 
    9094            skt = self.createInternetSocket() 
    9195            skt.bind((self.interface, self.port)) 
     
    238242 
    239243    def getHost(self): 
    240244        """ 
    241         Returns an IPv4Address. 
     245        Returns an IPAddress. 
    242246 
    243247        This indicates the address from which I am connecting. 
    244248        """ 
    245         return address.IPv4Address('UDP', *self.socket.getsockname()) 
     249        return address.IPAddress('UDP', self.socket.family, *self.socket.getsockname()) 
    246250 
    247251 
    248252