Ticket #5085: twisted-tcp6_v2.patch
| File twisted-tcp6_v2.patch, 20.6 KB (added by chjurk, 20 months ago) |
|---|
-
twisted/internet/address.py
diff -ru ../listentcp-ipv6-5084-3/twisted/internet/address.py ./twisted/internet/address.py
old new 19 19 20 20 @ivar type: A string describing the type of transport, either 'TCP' or 21 21 'UDP'. 22 @ivar host: A string containing the dotted-quadIP address.22 @ivar host: A string containing the native IP address. 23 23 @ivar port: An integer representing the port number. 24 24 """ 25 25 … … 47 47 class IPv4Address(_IPAddress): 48 48 """ 49 49 Object representing an IPv4 socket endpoint. 50 51 @ivar type: A string describing the type of transport, either 'TCP' or 52 'UDP'. 53 @ivar host: A string containing the dotted-quad IP address. 54 @ivar port: An integer representing the port number. 50 55 """ 51 56 def __init__(self, type, host, port, _bwHack=None): 52 57 _IPAddress.__init__(self, type, host, port) … … 55 60 DeprecationWarning, stacklevel=2) 56 61 57 62 63 def __str__(self): 64 """ 65 Returns human-readable IP address version. 66 67 @return: A string containing the word "IPv6". 68 """ 69 return "IPv4" 70 71 58 72 59 73 class IPv6Address(_IPAddress): 60 74 """ 61 75 Object representing an IPv6 socket endpoint. 76 77 @ivar type: A string describing the type of transport, either 'TCP' or 78 'UDP'. 79 @ivar host: A string containing the hexadecimal formatted IP address. 80 @ivar port: An integer representing the port number. 81 @ivar flow_info: An integer specifying IPv6 flow info flags. 82 @ivar scope_id: A string containing the address scope identifier. 62 83 """ 84 def __init__(self, type, host, port, flow_info=0, scope_id=0): 85 self.flow_info = flow_info 86 self.scope_id = scope_id 87 _IPAddress.__init__(self, type, host, port) 88 89 90 def __hash__(self): 91 return hash((self.type, self.host, self.port, self.flow_info, self.scope_id)) 92 93 94 def __str__(self): 95 """ 96 Returns human-readable IP address version. 97 98 @return: A string containing the word "IPv6". 99 """ 100 return "IPv6" 63 101 64 102 65 103 -
twisted/internet/endpoints.py
diff -ru ../listentcp-ipv6-5084-3/twisted/internet/endpoints.py ./twisted/internet/endpoints.py
old new 25 25 26 26 __all__ = ["clientFromString", "serverFromString", 27 27 "TCP4ServerEndpoint", "TCP4ClientEndpoint", 28 "TCP6ServerEndpoint", "TCP6ClientEndpoint", 28 29 "UNIXServerEndpoint", "UNIXClientEndpoint", 29 30 "SSL4ServerEndpoint", "SSL4ClientEndpoint"] 30 31 … … 145 146 146 147 147 148 148 class TCP4ServerEndpoint(object):149 class _TCPServerEndpoint(object): 149 150 """ 150 TCP server endpoint with an IPv4configuration151 TCP server endpoint with an generic IP configuration 151 152 152 153 @ivar _reactor: An L{IReactorTCP} provider. 153 154 … … 188 189 189 190 190 191 191 class TCP4 ClientEndpoint(object):192 class TCP4ServerEndpoint(_TCPServerEndpoint): 192 193 """ 193 TCP client endpoint with an IPv4 configuration. 194 TCP server endpoint with an IPv4 configuration 195 196 @ivar _reactor: An L{IReactorTCP} provider. 197 198 @type _port: int 199 @ivar _port: The port number on which to listen for incoming connections. 200 201 @type _backlog: int 202 @ivar _backlog: size of the listen queue 203 204 @type _interface: str 205 @ivar _interface: the hostname to bind to, defaults to '' (all) 206 """ 207 pass 208 209 210 211 class TCP6ServerEndpoint(_TCPServerEndpoint): 212 """ 213 TCP server endpoint with an IPv6 configuration 214 215 @ivar _reactor: An L{IReactorTCP} provider. 216 217 @type _port: int 218 @ivar _port: The port number on which to listen for incoming connections. 219 220 @type _backlog: int 221 @ivar _backlog: size of the listen queue 222 223 @type _interface: str 224 @ivar _interface: the hostname to bind to, defaults to '::' (all) 225 """ 226 def __init__(self, reactor, port, backlog=50, interface='::'): 227 _TCPServerEndpoint.__init__(self, reactor, port, backlog, interface) 228 229 230 231 class _TCPClientEndpoint(object): 232 """ 233 TCP client endpoint with an generic IP configuration. 194 234 195 235 @ivar _reactor: An L{IReactorTCP} provider. 196 236 … … 247 287 248 288 249 289 250 class SSL4ServerEndpoint(object):290 class TCP4ClientEndpoint(_TCPClientEndpoint): 251 291 """ 252 SSL secured TCP server endpoint with an IPv4 configuration. 292 TCP client endpoint with an IPv4 configuration. 293 294 @ivar _reactor: An L{IReactorTCP} provider. 295 296 @type _host: str 297 @ivar _host: The hostname to connect to as a C{str} 298 299 @type _port: int 300 @ivar _port: The port to connect to as C{int} 301 302 @type _timeout: int 303 @ivar _timeout: number of seconds to wait before assuming the 304 connection has failed. 305 306 @type _bindAddress: tuple 307 @type _bindAddress: a (host, port) tuple of local address to bind 308 to, or None. 309 """ 310 pass 311 312 313 314 class TCP6ClientEndpoint(_TCPClientEndpoint): 315 """ 316 TCP client endpoint with an IPv6 configuration. 317 318 @ivar _reactor: An L{IReactorTCP} provider. 319 320 @type _host: str 321 @ivar _host: The hostname to connect to as a C{str} 322 323 @type _port: int 324 @ivar _port: The port to connect to as C{int} 325 326 @type _timeout: int 327 @ivar _timeout: number of seconds to wait before assuming the 328 connection has failed. 329 330 @type _bindAddress: tuple 331 @type _bindAddress: a (host, port) tuple of local address to bind 332 to, or None. 333 """ 334 pass 335 336 337 338 class _SSLServerEndpoint(object): 339 """ 340 SSL secured TCP server endpoint with an generic IP configuration. 253 341 254 342 @ivar _reactor: An L{IReactorSSL} provider. 255 343 … … 303 391 304 392 305 393 306 class SSL4 ClientEndpoint(object):394 class SSL4ServerEndpoint(_SSLServerEndpoint): 307 395 """ 308 SSL secured TCP client endpoint with an IPv4 configuration 396 SSL secured TCP server endpoint with an IPv4 configuration. 397 398 @ivar _reactor: An L{IReactorSSL} provider. 399 400 @type _host: str 401 @ivar _host: The hostname to connect to as a C{str} 402 403 @type _port: int 404 @ivar _port: The port to connect to as C{int} 405 406 @type _sslContextFactory: L{OpenSSLCertificateOptions} 407 @var _sslContextFactory: SSL Configuration information as an 408 L{OpenSSLCertificateOptions} 409 410 @type _backlog: int 411 @ivar _backlog: size of the listen queue 412 413 @type _interface: str 414 @ivar _interface: the hostname to bind to, defaults to '' (all) 415 """ 416 pass 417 418 419 420 class SSL6ServerEndpoint(_SSLServerEndpoint): 421 """ 422 SSL secured TCP server endpoint with an IPv6 configuration. 423 424 @ivar _reactor: An L{IReactorSSL} provider. 425 426 @type _host: str 427 @ivar _host: The hostname to connect to as a C{str} 428 429 @type _port: int 430 @ivar _port: The port to connect to as C{int} 431 432 @type _sslContextFactory: L{OpenSSLCertificateOptions} 433 @var _sslContextFactory: SSL Configuration information as an 434 L{OpenSSLCertificateOptions} 435 436 @type _backlog: int 437 @ivar _backlog: size of the listen queue 438 439 @type _interface: str 440 @ivar _interface: the hostname to bind to, defaults to '::' (all) 441 """ 442 pass 443 444 445 446 447 class _SSLClientEndpoint(object): 448 """ 449 SSL secured TCP client endpoint with an generic IP configuration 309 450 310 451 @ivar _reactor: An L{IReactorSSL} provider. 311 452 … … 368 509 return wf._onConnection 369 510 except: 370 511 return defer.fail() 512 513 514 515 class SSL4ClientEndpoint(_SSLClientEndpoint): 516 """ 517 SSL secured TCP client endpoint with an IPv4 configuration 518 519 @ivar _reactor: An L{IReactorSSL} provider. 520 521 @type _host: str 522 @ivar _host: The hostname to connect to as a C{str} 523 524 @type _port: int 525 @ivar _port: The port to connect to as C{int} 526 527 @type _sslContextFactory: L{OpenSSLCertificateOptions} 528 @var _sslContextFactory: SSL Configuration information as an 529 L{OpenSSLCertificateOptions} 530 531 @type _timeout: int 532 @ivar _timeout: number of seconds to wait before assuming the 533 connection has failed. 534 535 @type _bindAddress: tuple 536 @ivar _bindAddress: a (host, port) tuple of local address to bind 537 to, or None. 538 """ 539 pass 540 541 542 543 class SSL6ClientEndpoint(_SSLClientEndpoint): 544 """ 545 SSL secured TCP client endpoint with an IPv6 configuration 546 547 @ivar _reactor: An L{IReactorSSL} provider. 548 549 @type _host: str 550 @ivar _host: The hostname to connect to as a C{str} 551 552 @type _port: int 553 @ivar _port: The port to connect to as C{int} 554 555 @type _sslContextFactory: L{OpenSSLCertificateOptions} 556 @var _sslContextFactory: SSL Configuration information as an 557 L{OpenSSLCertificateOptions} 558 559 @type _timeout: int 560 @ivar _timeout: number of seconds to wait before assuming the 561 connection has failed. 562 563 @type _bindAddress: tuple 564 @ivar _bindAddress: a (host, port) tuple of local address to bind 565 to, or None. 566 """ 567 pass 371 568 372 569 373 570 -
twisted/internet/tcp.py
diff -ru ../listentcp-ipv6-5084-3/twisted/internet/tcp.py ./twisted/internet/tcp.py
old new 258 258 A base class for client TCP (and similiar) sockets. 259 259 """ 260 260 _base = Connection 261 _addressType = address.IPv4Address 261 262 262 263 addressFamily = socket.AF_INET 263 264 socketType = socket.SOCK_STREAM … … 270 271 Connection.__init__(self, skt, None, reactor) 271 272 self.doWrite = self.doConnect 272 273 self.doRead = self.doConnect 273 reactor.callLater(0, whenDone)274 self.doConnect() 274 275 else: 275 276 reactor.callLater(0, self.failIfNotConnected, error) 276 277 … … 312 313 return s 313 314 314 315 def resolveAddress(self): 315 if abstract.isIPAddress(self.addr[0]) :316 if abstract.isIPAddress(self.addr[0]) or abstract.isIPv6Address(self.addr[0]): 316 317 self._setRealAddress(self.addr[0]) 317 318 else: 318 319 d = self.reactor.resolve(self.addr[0]) 319 320 d.addCallbacks(self._setRealAddress, self.failIfNotConnected) 320 321 321 def _setRealAddress(self, address): 322 self.realAddress = (address, self.addr[1]) 323 self.doConnect() 322 def _setRealAddress(self, addr): 323 """ 324 Set the real IP address for this client. 325 Once the IP address is set, the socket is created using the correct 326 address family. 327 """ 328 if abstract.isIPv6Address(addr): 329 self.addressFamily = socket.AF_INET6 330 self._addressType = address.IPv6Address 331 self.realAddress = (addr, self.addr[1]) 332 333 # create the socket and wait finish init after that 334 self.initConnection() 335 336 def initConnection(self): 337 """ 338 Initialize connection by creating the appropriate socket. 339 """ 340 err = None 341 skt = None 342 result = True 343 344 try: 345 skt = self.createInternetSocket() 346 except socket.error, se: 347 err = error.ConnectBindError(se[0], se[1]) 348 result = None 349 if result and self.bindAddress is not None: 350 try: 351 skt.bind(self.bindAddress) 352 except socket.error, se: 353 err = error.ConnectBindError(se[0], se[1]) 354 result = None 355 self._finishInit(result, skt, err, self.reactor) 324 356 325 357 def doConnect(self): 326 358 """I connect the socket. … … 394 426 # BaseClient.__init__ is invoked later 395 427 self.connector = connector 396 428 self.addr = (host, port) 429 self.bindAddress = bindAddress 430 self.reactor = reactor 397 431 398 whenDone = self.resolveAddress 399 err = None 400 skt = None 401 402 try: 403 skt = self.createInternetSocket() 404 except socket.error, se: 405 err = error.ConnectBindError(se[0], se[1]) 406 whenDone = None 407 if whenDone and bindAddress is not None: 408 try: 409 skt.bind(bindAddress) 410 except socket.error, se: 411 err = error.ConnectBindError(se[0], se[1]) 412 whenDone = None 413 self._finishInit(whenDone, skt, err, reactor) 432 # Do outstanding initialization when real address is resolved 433 self.resolveAddress() 414 434 415 435 def getHost(self): 416 """Returns an IPv4Address. 436 """ 437 Returns an L{IPv4Address} or L{IPv6Address}. 417 438 418 439 This indicates the address from which I am connecting. 419 440 """ 420 return address.IPv4Address('TCP', *self.socket.getsockname())441 return self._addressType('TCP', *self.socket.getsockname()) 421 442 422 443 def getPeer(self): 423 """Returns an IPv4Address. 444 """ 445 Returns an L{IPv4Address} or L{IPv6Address}. 424 446 425 447 This indicates the address that I am connected to. 426 448 """ 427 return address.IPv4Address('TCP', *self.realAddress)449 return self._addressType('TCP', *self.realAddress) 428 450 429 451 def __repr__(self): 430 452 s = '<%s to %s at %x>' % (self.__class__, self.addr, unsignedID(self)) … … 556 578 557 579 def __repr__(self): 558 580 if self._realPortNumber is not None: 559 return "<%s of %s on %s >" % (self.__class__, self.factory.__class__,560 self._realPortNumber )581 return "<%s of %s on %s (%s)>" % (self.__class__, self.factory.__class__, 582 self._realPortNumber, self._addressType) 561 583 else: 562 584 return "<%s of %s (not listening)>" % (self.__class__, self.factory.__class__) 563 585 586 564 587 def createInternetSocket(self): 565 588 s = base.BasePort.createInternetSocket(self) 566 589 if platformType == "posix" and sys.platform != "cygwin": … … 588 611 # reflect what the OS actually assigned us. 589 612 self._realPortNumber = skt.getsockname()[1] 590 613 591 log.msg("%s starting on %s" % (self.factory.__class__, self._realPortNumber)) 614 log.msg("%s starting on %s (%s)" % (self.factory.__class__, self._realPortNumber, 615 self._addressType)) 592 616 593 617 # The order of the next 6 lines is kind of bizarre. If no one 594 618 # can explain it, perhaps we should re-arrange them. … … 739 763 740 764 741 765 class Connector(base.BaseConnector): 766 _addressType = address.IPv4Address 767 742 768 def __init__(self, host, port, factory, timeout, bindAddress, reactor=None): 743 self.host = host744 769 if isinstance(port, types.StringTypes): 745 770 try: 746 771 port = socket.getservbyname(port, 'tcp') 747 772 except socket.error, e: 748 773 raise error.ServiceNameUnknownError(string="%s (%r)" % (e, port)) 774 775 self.host, self.port = host, port 776 777 if abstract.isIPv6Address(host): 778 self._addressType = address.IPv6Address 779 elif not abstract.isIPAddress(host): 780 # do a host lookup to make sure we have the correct address family 781 try: 782 addressInfo = socket.getaddrinfo(host, port) 783 except socket.gaierror: 784 raise error.DNSLookupError(host) 785 else: 786 assert len(addressInfo) > 0 787 788 # Sort addressInfo. IPv4 addresses should be preferred over 789 # IPv6 addresses to keep legacy applications working. 790 addressInfo = sorted(addressInfo, key=lambda fields: fields[0]) 791 792 if addressInfo[0][0] == socket.AF_INET6: 793 self._addressType = address.IPv6Address 794 795 host, port = addressInfo[0][4][:2] 796 797 self.host = host 749 798 self.port = port 750 799 self.bindAddress = bindAddress 751 800 base.BaseConnector.__init__(self, factory, timeout, reactor) … … 754 803 return Client(self.host, self.port, self.bindAddress, self, self.reactor) 755 804 756 805 def getDestination(self): 757 return address.IPv4Address('TCP', self.host, self.port)806 return self._addressType('TCP', self.host, self.port) -
twisted/internet/test/test_tcp.py
diff -ru ../listentcp-ipv6-5084-3/twisted/internet/test/test_tcp.py ./twisted/internet/test/test_tcp.py
old new 20 20 IResolverSimple, IConnector, IReactorFDSet) 21 21 from twisted.internet.address import IPv4Address, IPv6Address 22 22 from twisted.internet.defer import Deferred, DeferredList, succeed, fail, maybeDeferred 23 from twisted.internet.endpoints import TCP4ServerEndpoint, TCP4ClientEndpoint 23 from twisted.internet.endpoints import TCP4ServerEndpoint, TCP4ClientEndpoint, TCP6ServerEndpoint, TCP6ClientEndpoint 24 24 from twisted.internet.protocol import ServerFactory, ClientFactory, Protocol 25 25 from twisted.python.failure import Failure 26 26 from twisted.python import log … … 114 114 """ 115 115 def __init__(self, reactor): 116 116 self.reactor = reactor 117 118 117 118 119 119 def clientConnectionFailed(self, connector, reason): 120 120 self.reactor.stop() 121 121 … … 605 605 606 606 607 607 608 class TCP6ClientTestsBuilder(ReactorBuilder, ConnectionTestsMixin): 609 """ 610 Builder defining tests relating to L{IReactorTCP.connectTCP}, IPv6 version. 611 """ 612 def serverEndpoint(self, reactor): 613 """ 614 Create a L{TCP6ServerEndpoint} listening on localhost on a 615 TCP/IP-selected port. 616 """ 617 return TCP6ServerEndpoint(reactor, 0, interface='::1') 618 619 620 def clientEndpoint(self, reactor, serverAddress): 621 """ 622 Create a L{TCP6ClientEndpoint} which will connect to localhost 623 on the port given by C{serverAddress}. 624 625 @type serverAddress: L{IPv6Address} 626 """ 627 return TCP6ClientEndpoint(reactor, '::1', serverAddress.port) 628 629 630 def test_interface(self): 631 """ 632 L{IReactorTCP.connectTCP} returns an object providing L{IConnector}. 633 """ 634 reactor = self.buildReactor() 635 connector = reactor.connectTCP("::1", 1234, ClientFactory()) 636 self.assertTrue(verifyObject(IConnector, connector)) 637 638 639 def test_clientConnectionFailedStopsReactor(self): 640 """ 641 The reactor can be stopped by a client factory's 642 C{clientConnectionFailed} method. 643 """ 644 host, port = findFreePort("::1", socket.AF_INET6)[:2] 645 reactor = self.buildReactor() 646 reactor.connectTCP(host, port, Stop(reactor)) 647 self.runReactor(reactor) 648 649 650 def test_addresses(self): 651 """ 652 A client's transport's C{getHost} and C{getPeer} return L{IPv6Address} 653 instances which give the hexadecimal formatted string form of the local 654 and remote endpoints of the connection respectively. 655 """ 656 host, port = findFreePort("::1", socket.AF_INET6)[:2] 657 reactor = self.buildReactor() 658 659 server = reactor.listenTCP( 660 0, serverFactoryFor(Protocol), interface=host) 661 serverAddress = server.getHost() 662 663 addresses = {'host': None, 'peer': None} 664 class CheckAddress(Protocol): 665 def makeConnection(self, transport): 666 addresses['host'] = transport.getHost() 667 addresses['peer'] = transport.getPeer() 668 reactor.stop() 669 670 clientFactory = Stop(reactor) 671 clientFactory.protocol = CheckAddress 672 reactor.connectTCP( 673 '::1', server.getHost().port, clientFactory, 674 bindAddress=('::1', port)) 675 676 self.runReactor(reactor) 677 678 self.assertEqual( 679 addresses['host'], 680 IPv6Address('TCP', '::1', port)) 681 self.assertEqual( 682 addresses['peer'], 683 IPv6Address('TCP', '::1', serverAddress.port)) 684 685 686 608 687 class StreamTransportTestsMixin: 609 688 """ 610 689 Mixin defining tests which apply to any port/connection based transport. … … 1024 1103 1025 1104 1026 1105 globals().update(TCPClientTestsBuilder.makeTestCaseClasses()) 1106 globals().update(TCP6ClientTestsBuilder.makeTestCaseClasses()) 1027 1107 globals().update(TCPPortTestsBuilder.makeTestCaseClasses()) 1028 1108 globals().update(TCPConnectionTestsBuilder.makeTestCaseClasses())
