PageRenderTime 51ms CodeModel.GetById 2ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 1ms

/desktop/core/ext-py/Twisted/twisted/internet/tcp.py

https://github.com/qzem/hortonworks-sandbox
Python | 1033 lines | 899 code | 28 blank | 106 comment | 26 complexity | e13f0c80ba7d9633eb5e34043103e3e1 MD5 | raw file
   1# -*- test-case-name: twisted.test.test_tcp -*-
   2# Copyright (c) 2001-2007 Twisted Matrix Laboratories.
   3# See LICENSE for details.
   4
   5"""
   6Various asynchronous TCP/IP classes.
   7
   8End users shouldn't use this module directly - use the reactor APIs instead.
   9
  10Maintainer: Itamar Shtull-Trauring
  11"""
  12
  13
  14# System Imports
  15import os
  16import types
  17import socket
  18import sys
  19import operator
  20
  21try:
  22    import fcntl
  23except ImportError:
  24    fcntl = None
  25from zope.interface import implements, classImplements
  26
  27try:
  28    from OpenSSL import SSL
  29except ImportError:
  30    SSL = None
  31
  32from twisted.python.runtime import platformType
  33
  34
  35if platformType == 'win32':
  36    # no such thing as WSAEPERM or error code 10001 according to winsock.h or MSDN
  37    EPERM = object()
  38    from errno import WSAEINVAL as EINVAL
  39    from errno import WSAEWOULDBLOCK as EWOULDBLOCK
  40    from errno import WSAEINPROGRESS as EINPROGRESS
  41    from errno import WSAEALREADY as EALREADY
  42    from errno import WSAECONNRESET as ECONNRESET
  43    from errno import WSAEISCONN as EISCONN
  44    from errno import WSAENOTCONN as ENOTCONN
  45    from errno import WSAEINTR as EINTR
  46    from errno import WSAENOBUFS as ENOBUFS
  47    from errno import WSAEMFILE as EMFILE
  48    # No such thing as WSAENFILE, either.
  49    ENFILE = object()
  50    # Nor ENOMEM
  51    ENOMEM = object()
  52    EAGAIN = EWOULDBLOCK
  53    from errno import WSAECONNRESET as ECONNABORTED
  54
  55    from twisted.python.win32 import formatError as strerror
  56else:
  57    from errno import EPERM
  58    from errno import EINVAL
  59    from errno import EWOULDBLOCK
  60    from errno import EINPROGRESS
  61    from errno import EALREADY
  62    from errno import ECONNRESET
  63    from errno import EISCONN
  64    from errno import ENOTCONN
  65    from errno import EINTR
  66    from errno import ENOBUFS
  67    from errno import EMFILE
  68    from errno import ENFILE
  69    from errno import ENOMEM
  70    from errno import EAGAIN
  71    from errno import ECONNABORTED
  72
  73    from os import strerror
  74
  75from errno import errorcode
  76
  77# Twisted Imports
  78from twisted.internet import defer, base, address
  79from twisted.python import log, failure, reflect
  80from twisted.python.util import unsignedID
  81from twisted.internet.error import CannotListenError
  82from twisted.internet import abstract, main, interfaces, error
  83
  84
  85
  86class _SocketCloser:
  87    _socketShutdownMethod = 'shutdown'
  88
  89    def _closeSocket(self):
  90        # socket.close() doesn't *really* close if there's another reference
  91        # to it in the TCP/IP stack, e.g. if it was was inherited by a
  92        # subprocess. And we really do want to close the connection. So we
  93        # use shutdown() instead, and then close() in order to release the
  94        # filedescriptor.
  95        skt = self.socket
  96        try:
  97            getattr(skt, self._socketShutdownMethod)(2)
  98        except socket.error:
  99            pass
 100        try:
 101            skt.close()
 102        except socket.error:
 103            pass
 104
 105
 106
 107class _TLSMixin:
 108    _socketShutdownMethod = 'sock_shutdown'
 109
 110    writeBlockedOnRead = 0
 111    readBlockedOnWrite = 0
 112    _userWantRead = _userWantWrite = True
 113
 114    def getPeerCertificate(self):
 115        return self.socket.get_peer_certificate()
 116
 117    def doRead(self):
 118        if self.disconnected:
 119            # See the comment in the similar check in doWrite below.
 120            # Additionally, in order for anything other than returning
 121            # CONNECTION_DONE here to make sense, it will probably be necessary
 122            # to implement a way to switch back to TCP from TLS (actually, if
 123            # we did something other than return CONNECTION_DONE, that would be
 124            # a big part of implementing that feature).  In other words, the
 125            # expectation is that doRead will be called when self.disconnected
 126            # is True only when the connection has been lost.  It's possible
 127            # that the other end could stop speaking TLS and then send us some
 128            # non-TLS data.  We'll end up ignoring that data and dropping the
 129            # connection.  There's no unit tests for this check in the cases
 130            # where it makes a difference.  The test suite only hits this
 131            # codepath when it would have otherwise hit the SSL.ZeroReturnError
 132            # exception handler below, which has exactly the same behavior as
 133            # this conditional.  Maybe that's the only case that can ever be
 134            # triggered, I'm not sure.  -exarkun
 135            return main.CONNECTION_DONE
 136        if self.writeBlockedOnRead:
 137            self.writeBlockedOnRead = 0
 138            self._resetReadWrite()
 139        try:
 140            return Connection.doRead(self)
 141        except SSL.ZeroReturnError:
 142            return main.CONNECTION_DONE
 143        except SSL.WantReadError:
 144            return
 145        except SSL.WantWriteError:
 146            self.readBlockedOnWrite = 1
 147            Connection.startWriting(self)
 148            Connection.stopReading(self)
 149            return
 150        except SSL.SysCallError, (retval, desc):
 151            if ((retval == -1 and desc == 'Unexpected EOF')
 152                or retval > 0):
 153                return main.CONNECTION_LOST
 154            log.err()
 155            return main.CONNECTION_LOST
 156        except SSL.Error, e:
 157            return e
 158
 159    def doWrite(self):
 160        # Retry disconnecting
 161        if self.disconnected:
 162            # This case is triggered when "disconnected" is set to True by a
 163            # call to _postLoseConnection from FileDescriptor.doWrite (to which
 164            # we upcall at the end of this overridden version of that API).  It
 165            # means that while, as far as any protocol connected to this
 166            # transport is concerned, the connection no longer exists, the
 167            # connection *does* actually still exist.  Instead of closing the
 168            # connection in the overridden _postLoseConnection, we probably
 169            # tried (and failed) to send a TLS close alert.  The TCP connection
 170            # is still up and we're waiting for the socket to become writeable
 171            # enough for the TLS close alert to actually be sendable.  Only
 172            # then will the connection actually be torn down. -exarkun
 173            return self._postLoseConnection()
 174        if self._writeDisconnected:
 175            return self._closeWriteConnection()
 176
 177        if self.readBlockedOnWrite:
 178            self.readBlockedOnWrite = 0
 179            self._resetReadWrite()
 180        return Connection.doWrite(self)
 181
 182    def writeSomeData(self, data):
 183        try:
 184            return Connection.writeSomeData(self, data)
 185        except SSL.WantWriteError:
 186            return 0
 187        except SSL.WantReadError:
 188            self.writeBlockedOnRead = 1
 189            Connection.stopWriting(self)
 190            Connection.startReading(self)
 191            return 0
 192        except SSL.ZeroReturnError:
 193            return main.CONNECTION_LOST
 194        except SSL.SysCallError, e:
 195            if e[0] == -1 and data == "":
 196                # errors when writing empty strings are expected
 197                # and can be ignored
 198                return 0
 199            else:
 200                return main.CONNECTION_LOST
 201        except SSL.Error, e:
 202            return e
 203
 204
 205    def _postLoseConnection(self):
 206        """
 207        Gets called after loseConnection(), after buffered data is sent.
 208
 209        We try to send an SSL shutdown alert, but if it doesn't work, retry
 210        when the socket is writable.
 211        """
 212        # Here, set "disconnected" to True to trick higher levels into thinking
 213        # the connection is really gone.  It's not, and we're not going to
 214        # close it yet.  Instead, we'll try to send a TLS close alert to shut
 215        # down the TLS connection cleanly.  Only after we actually get the
 216        # close alert into the socket will we disconnect the underlying TCP
 217        # connection.
 218        self.disconnected = True
 219        if hasattr(self.socket, 'set_shutdown'):
 220            # If possible, mark the state of the TLS connection as having
 221            # already received a TLS close alert from the peer.  Why do
 222            # this???
 223            self.socket.set_shutdown(SSL.RECEIVED_SHUTDOWN)
 224        return self._sendCloseAlert()
 225
 226
 227    def _sendCloseAlert(self):
 228        # Okay, *THIS* is a bit complicated.
 229
 230        # Basically, the issue is, OpenSSL seems to not actually return
 231        # errors from SSL_shutdown. Therefore, the only way to
 232        # determine if the close notification has been sent is by
 233        # SSL_shutdown returning "done". However, it will not claim it's
 234        # done until it's both sent *and* received a shutdown notification.
 235
 236        # I don't actually want to wait for a received shutdown
 237        # notification, though, so, I have to set RECEIVED_SHUTDOWN
 238        # before calling shutdown. Then, it'll return True once it's
 239        # *SENT* the shutdown.
 240
 241        # However, RECEIVED_SHUTDOWN can't be left set, because then
 242        # reads will fail, breaking half close.
 243
 244        # Also, since shutdown doesn't report errors, an empty write call is
 245        # done first, to try to detect if the connection has gone away.
 246        # (*NOT* an SSL_write call, because that fails once you've called
 247        # shutdown)
 248        try:
 249            os.write(self.socket.fileno(), '')
 250        except OSError, se:
 251            if se.args[0] in (EINTR, EWOULDBLOCK, ENOBUFS):
 252                return 0
 253            # Write error, socket gone
 254            return main.CONNECTION_LOST
 255
 256        try:
 257            if hasattr(self.socket, 'set_shutdown'):
 258                laststate = self.socket.get_shutdown()
 259                self.socket.set_shutdown(laststate | SSL.RECEIVED_SHUTDOWN)
 260                done = self.socket.shutdown()
 261                if not (laststate & SSL.RECEIVED_SHUTDOWN):
 262                    self.socket.set_shutdown(SSL.SENT_SHUTDOWN)
 263            else:
 264                #warnings.warn("SSL connection shutdown possibly unreliable, "
 265                #              "please upgrade to ver 0.XX", category=UserWarning)
 266                self.socket.shutdown()
 267                done = True
 268        except SSL.Error, e:
 269            return e
 270
 271        if done:
 272            self.stopWriting()
 273            # Note that this is tested for by identity below.
 274            return main.CONNECTION_DONE
 275        else:
 276            # For some reason, the close alert wasn't sent.  Start writing
 277            # again so that we'll get another chance to send it.
 278            self.startWriting()
 279            # On Linux, select will sometimes not report a closed file
 280            # descriptor in the write set (in particular, it seems that if a
 281            # send() fails with EPIPE, the socket will not appear in the write
 282            # set).  The shutdown call above (which calls down to SSL_shutdown)
 283            # may have swallowed a write error.  Therefore, also start reading
 284            # so that if the socket is closed we will notice.  This doesn't
 285            # seem to be a problem for poll (because poll reports errors
 286            # separately) or with select on BSD (presumably because, unlike
 287            # Linux, it doesn't implement select in terms of poll and then map
 288            # POLLHUP to select's in fd_set).
 289            self.startReading()
 290            return None
 291
 292    def _closeWriteConnection(self):
 293        result = self._sendCloseAlert()
 294
 295        if result is main.CONNECTION_DONE:
 296            return Connection._closeWriteConnection(self)
 297
 298        return result
 299
 300    def startReading(self):
 301        self._userWantRead = True
 302        if not self.readBlockedOnWrite:
 303            return Connection.startReading(self)
 304
 305    def stopReading(self):
 306        self._userWantRead = False
 307        if not self.writeBlockedOnRead:
 308            return Connection.stopReading(self)
 309
 310    def startWriting(self):
 311        self._userWantWrite = True
 312        if not self.writeBlockedOnRead:
 313            return Connection.startWriting(self)
 314
 315    def stopWriting(self):
 316        self._userWantWrite = False
 317        if not self.readBlockedOnWrite:
 318            return Connection.stopWriting(self)
 319
 320    def _resetReadWrite(self):
 321        # After changing readBlockedOnWrite or writeBlockedOnRead,
 322        # call this to reset the state to what the user requested.
 323        if self._userWantWrite:
 324            self.startWriting()
 325        else:
 326            self.stopWriting()
 327
 328        if self._userWantRead:
 329            self.startReading()
 330        else:
 331            self.stopReading()
 332
 333
 334
 335class _TLSDelayed(object):
 336    """
 337    State tracking record for TLS startup parameters.  Used to remember how
 338    TLS should be started when starting it is delayed to wait for the output
 339    buffer to be flushed.
 340
 341    @ivar bufferedData: A C{list} which contains all the data which was
 342        written to the transport after an attempt to start TLS was made but
 343        before the buffers outstanding at that time could be flushed and TLS
 344        could really be started.  This is appended to by the transport's
 345        write and writeSequence methods until it is possible to actually
 346        start TLS, then it is written to the TLS-enabled transport.
 347
 348    @ivar context: An SSL context factory object to use to start TLS.
 349
 350    @ivar extra: An extra argument to pass to the transport's C{startTLS}
 351        method.
 352    """
 353    def __init__(self, bufferedData, context, extra):
 354        self.bufferedData = bufferedData
 355        self.context = context
 356        self.extra = extra
 357
 358
 359
 360def _getTLSClass(klass, _existing={}):
 361    if klass not in _existing:
 362        class TLSConnection(_TLSMixin, klass):
 363            implements(interfaces.ISSLTransport)
 364        _existing[klass] = TLSConnection
 365    return _existing[klass]
 366
 367
 368
 369class Connection(abstract.FileDescriptor, _SocketCloser):
 370    """
 371    Superclass of all socket-based FileDescriptors.
 372
 373    This is an abstract superclass of all objects which represent a TCP/IP
 374    connection based socket.
 375
 376    @ivar logstr: prefix used when logging events related to this connection.
 377    @type logstr: C{str}
 378    """
 379
 380    implements(interfaces.ITCPTransport, interfaces.ISystemHandle)
 381
 382    TLS = 0
 383
 384    def __init__(self, skt, protocol, reactor=None):
 385        abstract.FileDescriptor.__init__(self, reactor=reactor)
 386        self.socket = skt
 387        self.socket.setblocking(0)
 388        self.fileno = skt.fileno
 389        self.protocol = protocol
 390
 391    if SSL:
 392        _tlsWaiting = None
 393        def startTLS(self, ctx, extra):
 394            assert not self.TLS
 395            if self.dataBuffer or self._tempDataBuffer:
 396                # pre-TLS bytes are still being written.  Starting TLS now
 397                # will do the wrong thing.  Instead, mark that we're trying
 398                # to go into the TLS state.
 399                self._tlsWaiting = _TLSDelayed([], ctx, extra)
 400                return False
 401
 402            self.stopReading()
 403            self.stopWriting()
 404            self._startTLS()
 405            self.socket = SSL.Connection(ctx.getContext(), self.socket)
 406            self.fileno = self.socket.fileno
 407            self.startReading()
 408            return True
 409
 410
 411        def _startTLS(self):
 412            self.TLS = 1
 413            self.__class__ = _getTLSClass(self.__class__)
 414
 415
 416        def write(self, bytes):
 417            if self._tlsWaiting is not None:
 418                self._tlsWaiting.bufferedData.append(bytes)
 419            else:
 420                abstract.FileDescriptor.write(self, bytes)
 421
 422
 423        def writeSequence(self, iovec):
 424            if self._tlsWaiting is not None:
 425                self._tlsWaiting.bufferedData.extend(iovec)
 426            else:
 427                abstract.FileDescriptor.writeSequence(self, iovec)
 428
 429
 430        def doWrite(self):
 431            result = abstract.FileDescriptor.doWrite(self)
 432            if self._tlsWaiting is not None:
 433                if not self.dataBuffer and not self._tempDataBuffer:
 434                    waiting = self._tlsWaiting
 435                    self._tlsWaiting = None
 436                    self.startTLS(waiting.context, waiting.extra)
 437                    self.writeSequence(waiting.bufferedData)
 438            return result
 439
 440
 441    def getHandle(self):
 442        """Return the socket for this connection."""
 443        return self.socket
 444
 445
 446    def doRead(self):
 447        """Calls self.protocol.dataReceived with all available data.
 448
 449        This reads up to self.bufferSize bytes of data from its socket, then
 450        calls self.dataReceived(data) to process it.  If the connection is not
 451        lost through an error in the physical recv(), this function will return
 452        the result of the dataReceived call.
 453        """
 454        try:
 455            data = self.socket.recv(self.bufferSize)
 456        except socket.error, se:
 457            if se.args[0] == EWOULDBLOCK:
 458                return
 459            else:
 460                return main.CONNECTION_LOST
 461        if not data:
 462            return main.CONNECTION_DONE
 463        return self.protocol.dataReceived(data)
 464
 465
 466    def writeSomeData(self, data):
 467        """Connection.writeSomeData(data) -> #of bytes written | CONNECTION_LOST
 468        This writes as much data as possible to the socket and returns either
 469        the number of bytes read (which is positive) or a connection error code
 470        (which is negative)
 471        """
 472        try:
 473            # Limit length of buffer to try to send, because some OSes are too
 474            # stupid to do so themselves (ahem windows)
 475            return self.socket.send(buffer(data, 0, self.SEND_LIMIT))
 476        except socket.error, se:
 477            if se.args[0] == EINTR:
 478                return self.writeSomeData(data)
 479            elif se.args[0] in (EWOULDBLOCK, ENOBUFS):
 480                return 0
 481            else:
 482                return main.CONNECTION_LOST
 483
 484
 485    def _closeWriteConnection(self):
 486        try:
 487            getattr(self.socket, self._socketShutdownMethod)(1)
 488        except socket.error:
 489            pass
 490        p = interfaces.IHalfCloseableProtocol(self.protocol, None)
 491        if p:
 492            try:
 493                p.writeConnectionLost()
 494            except:
 495                f = failure.Failure()
 496                log.err()
 497                self.connectionLost(f)
 498
 499
 500    def readConnectionLost(self, reason):
 501        p = interfaces.IHalfCloseableProtocol(self.protocol, None)
 502        if p:
 503            try:
 504                p.readConnectionLost()
 505            except:
 506                log.err()
 507                self.connectionLost(failure.Failure())
 508        else:
 509            self.connectionLost(reason)
 510
 511    def connectionLost(self, reason):
 512        """See abstract.FileDescriptor.connectionLost().
 513        """
 514        abstract.FileDescriptor.connectionLost(self, reason)
 515        self._closeSocket()
 516        protocol = self.protocol
 517        del self.protocol
 518        del self.socket
 519        del self.fileno
 520        protocol.connectionLost(reason)
 521
 522    logstr = "Uninitialized"
 523
 524    def logPrefix(self):
 525        """Return the prefix to log with when I own the logging thread.
 526        """
 527        return self.logstr
 528
 529    def getTcpNoDelay(self):
 530        return operator.truth(self.socket.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY))
 531
 532    def setTcpNoDelay(self, enabled):
 533        self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, enabled)
 534
 535    def getTcpKeepAlive(self):
 536        return operator.truth(self.socket.getsockopt(socket.SOL_SOCKET,
 537                                                     socket.SO_KEEPALIVE))
 538
 539    def setTcpKeepAlive(self, enabled):
 540        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, enabled)
 541
 542if SSL:
 543    classImplements(Connection, interfaces.ITLSTransport)
 544
 545class BaseClient(Connection):
 546    """A base class for client TCP (and similiar) sockets.
 547    """
 548    addressFamily = socket.AF_INET
 549    socketType = socket.SOCK_STREAM
 550
 551    def _finishInit(self, whenDone, skt, error, reactor):
 552        """Called by base classes to continue to next stage of initialization."""
 553        if whenDone:
 554            Connection.__init__(self, skt, None, reactor)
 555            self.doWrite = self.doConnect
 556            self.doRead = self.doConnect
 557            reactor.callLater(0, whenDone)
 558        else:
 559            reactor.callLater(0, self.failIfNotConnected, error)
 560
 561    def startTLS(self, ctx, client=1):
 562        if Connection.startTLS(self, ctx, client):
 563            if client:
 564                self.socket.set_connect_state()
 565            else:
 566                self.socket.set_accept_state()
 567
 568
 569    def stopConnecting(self):
 570        """Stop attempt to connect."""
 571        self.failIfNotConnected(error.UserError())
 572
 573    def failIfNotConnected(self, err):
 574        """
 575        Generic method called when the attemps to connect failed. It basically
 576        cleans everything it can: call connectionFailed, stop read and write,
 577        delete socket related members.
 578        """
 579        if (self.connected or self.disconnected or
 580            not hasattr(self, "connector")):
 581            return
 582
 583        self.connector.connectionFailed(failure.Failure(err))
 584        if hasattr(self, "reactor"):
 585            # this doesn't happen if we failed in __init__
 586            self.stopReading()
 587            self.stopWriting()
 588            del self.connector
 589
 590        try:
 591            self._closeSocket()
 592        except AttributeError:
 593            pass
 594        else:
 595            del self.socket, self.fileno
 596
 597    def createInternetSocket(self):
 598        """(internal) Create a non-blocking socket using
 599        self.addressFamily, self.socketType.
 600        """
 601        s = socket.socket(self.addressFamily, self.socketType)
 602        s.setblocking(0)
 603        if fcntl and hasattr(fcntl, 'FD_CLOEXEC'):
 604            old = fcntl.fcntl(s.fileno(), fcntl.F_GETFD)
 605            fcntl.fcntl(s.fileno(), fcntl.F_SETFD, old | fcntl.FD_CLOEXEC)
 606        return s
 607
 608    def resolveAddress(self):
 609        if abstract.isIPAddress(self.addr[0]):
 610            self._setRealAddress(self.addr[0])
 611        else:
 612            d = self.reactor.resolve(self.addr[0])
 613            d.addCallbacks(self._setRealAddress, self.failIfNotConnected)
 614
 615    def _setRealAddress(self, address):
 616        self.realAddress = (address, self.addr[1])
 617        self.doConnect()
 618
 619    def doConnect(self):
 620        """I connect the socket.
 621
 622        Then, call the protocol's makeConnection, and start waiting for data.
 623        """
 624        if not hasattr(self, "connector"):
 625            # this happens when connection failed but doConnect
 626            # was scheduled via a callLater in self._finishInit
 627            return
 628
 629        err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
 630        if err:
 631            self.failIfNotConnected(error.getConnectError((err, strerror(err))))
 632            return
 633
 634
 635        # doConnect gets called twice.  The first time we actually need to
 636        # start the connection attempt.  The second time we don't really
 637        # want to (SO_ERROR above will have taken care of any errors, and if
 638        # it reported none, the mere fact that doConnect was called again is
 639        # sufficient to indicate that the connection has succeeded), but it
 640        # is not /particularly/ detrimental to do so.  This should get
 641        # cleaned up some day, though.
 642        try:
 643            connectResult = self.socket.connect_ex(self.realAddress)
 644        except socket.error, se:
 645            connectResult = se.args[0]
 646        if connectResult:
 647            if connectResult == EISCONN:
 648                pass
 649            # on Windows EINVAL means sometimes that we should keep trying:
 650            # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/connect_2.asp
 651            elif ((connectResult in (EWOULDBLOCK, EINPROGRESS, EALREADY)) or
 652                  (connectResult == EINVAL and platformType == "win32")):
 653                self.startReading()
 654                self.startWriting()
 655                return
 656            else:
 657                self.failIfNotConnected(error.getConnectError((connectResult, strerror(connectResult))))
 658                return
 659
 660        # If I have reached this point without raising or returning, that means
 661        # that the socket is connected.
 662        del self.doWrite
 663        del self.doRead
 664        # we first stop and then start, to reset any references to the old doRead
 665        self.stopReading()
 666        self.stopWriting()
 667        self._connectDone()
 668
 669    def _connectDone(self):
 670        self.protocol = self.connector.buildProtocol(self.getPeer())
 671        self.connected = 1
 672        self.logstr = self.protocol.__class__.__name__ + ",client"
 673        self.startReading()
 674        self.protocol.makeConnection(self)
 675
 676    def connectionLost(self, reason):
 677        if not self.connected:
 678            self.failIfNotConnected(error.ConnectError(string=reason))
 679        else:
 680            Connection.connectionLost(self, reason)
 681            self.connector.connectionLost(reason)
 682
 683
 684class Client(BaseClient):
 685    """A TCP client."""
 686
 687    def __init__(self, host, port, bindAddress, connector, reactor=None):
 688        # BaseClient.__init__ is invoked later
 689        self.connector = connector
 690        self.addr = (host, port)
 691
 692        whenDone = self.resolveAddress
 693        err = None
 694        skt = None
 695
 696        try:
 697            skt = self.createInternetSocket()
 698        except socket.error, se:
 699            err = error.ConnectBindError(se[0], se[1])
 700            whenDone = None
 701        if whenDone and bindAddress is not None:
 702            try:
 703                skt.bind(bindAddress)
 704            except socket.error, se:
 705                err = error.ConnectBindError(se[0], se[1])
 706                whenDone = None
 707        self._finishInit(whenDone, skt, err, reactor)
 708
 709    def getHost(self):
 710        """Returns an IPv4Address.
 711
 712        This indicates the address from which I am connecting.
 713        """
 714        return address.IPv4Address('TCP', *(self.socket.getsockname() + ('INET',)))
 715
 716    def getPeer(self):
 717        """Returns an IPv4Address.
 718
 719        This indicates the address that I am connected to.
 720        """
 721        return address.IPv4Address('TCP', *(self.realAddress + ('INET',)))
 722
 723    def __repr__(self):
 724        s = '<%s to %s at %x>' % (self.__class__, self.addr, unsignedID(self))
 725        return s
 726
 727
 728class Server(Connection):
 729    """
 730    Serverside socket-stream connection class.
 731
 732    This is a serverside network connection transport; a socket which came from
 733    an accept() on a server.
 734    """
 735
 736    def __init__(self, sock, protocol, client, server, sessionno, reactor):
 737        """
 738        Server(sock, protocol, client, server, sessionno)
 739
 740        Initialize it with a socket, a protocol, a descriptor for my peer (a
 741        tuple of host, port describing the other end of the connection), an
 742        instance of Port, and a session number.
 743        """
 744        Connection.__init__(self, sock, protocol, reactor)
 745        self.server = server
 746        self.client = client
 747        self.sessionno = sessionno
 748        self.hostname = client[0]
 749        self.logstr = "%s,%s,%s" % (self.protocol.__class__.__name__,
 750                                    sessionno,
 751                                    self.hostname)
 752        self.repstr = "<%s #%s on %s>" % (self.protocol.__class__.__name__,
 753                                          self.sessionno,
 754                                          self.server._realPortNumber)
 755        self.startReading()
 756        self.connected = 1
 757
 758    def __repr__(self):
 759        """A string representation of this connection.
 760        """
 761        return self.repstr
 762
 763    def startTLS(self, ctx, server=1):
 764        if Connection.startTLS(self, ctx, server):
 765            if server:
 766                self.socket.set_accept_state()
 767            else:
 768                self.socket.set_connect_state()
 769
 770
 771    def getHost(self):
 772        """Returns an IPv4Address.
 773
 774        This indicates the server's address.
 775        """
 776        return address.IPv4Address('TCP', *(self.socket.getsockname() + ('INET',)))
 777
 778    def getPeer(self):
 779        """Returns an IPv4Address.
 780
 781        This indicates the client's address.
 782        """
 783        return address.IPv4Address('TCP', *(self.client + ('INET',)))
 784
 785class Port(base.BasePort, _SocketCloser):
 786    """
 787    A TCP server port, listening for connections.
 788
 789    When a connection is accepted, this will call a factory's buildProtocol
 790    with the incoming address as an argument, according to the specification
 791    described in L{twisted.internet.interfaces.IProtocolFactory}.
 792
 793    If you wish to change the sort of transport that will be used, the
 794    C{transport} attribute will be called with the signature expected for
 795    C{Server.__init__}, so it can be replaced.
 796
 797    @ivar deferred: a deferred created when L{stopListening} is called, and
 798        that will fire when connection is lost. This is not to be used it
 799        directly: prefer the deferred returned by L{stopListening} instead.
 800    @type deferred: L{defer.Deferred}
 801
 802    @ivar disconnecting: flag indicating that the L{stopListening} method has
 803        been called and that no connections should be accepted anymore.
 804    @type disconnecting: C{bool}
 805
 806    @ivar connected: flag set once the listen has successfully been called on
 807        the socket.
 808    @type connected: C{bool}
 809    """
 810
 811    implements(interfaces.IListeningPort)
 812
 813    addressFamily = socket.AF_INET
 814    socketType = socket.SOCK_STREAM
 815
 816    transport = Server
 817    sessionno = 0
 818    interface = ''
 819    backlog = 50
 820
 821    # Actual port number being listened on, only set to a non-None
 822    # value when we are actually listening.
 823    _realPortNumber = None
 824
 825    def __init__(self, port, factory, backlog=50, interface='', reactor=None):
 826        """Initialize with a numeric port to listen on.
 827        """
 828        base.BasePort.__init__(self, reactor=reactor)
 829        self.port = port
 830        self.factory = factory
 831        self.backlog = backlog
 832        self.interface = interface
 833
 834    def __repr__(self):
 835        if self._realPortNumber is not None:
 836            return "<%s of %s on %s>" % (self.__class__, self.factory.__class__,
 837                                         self._realPortNumber)
 838        else:
 839            return "<%s of %s (not listening)>" % (self.__class__, self.factory.__class__)
 840
 841    def createInternetSocket(self):
 842        s = base.BasePort.createInternetSocket(self)
 843        if platformType == "posix" and sys.platform != "cygwin":
 844            s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 845        return s
 846
 847
 848    def startListening(self):
 849        """Create and bind my socket, and begin listening on it.
 850
 851        This is called on unserialization, and must be called after creating a
 852        server to begin listening on the specified port.
 853        """
 854        try:
 855            skt = self.createInternetSocket()
 856            skt.bind((self.interface, self.port))
 857        except socket.error, le:
 858            raise CannotListenError, (self.interface, self.port, le)
 859
 860        # Make sure that if we listened on port 0, we update that to
 861        # reflect what the OS actually assigned us.
 862        self._realPortNumber = skt.getsockname()[1]
 863
 864        log.msg("%s starting on %s" % (self.factory.__class__, self._realPortNumber))
 865
 866        # The order of the next 6 lines is kind of bizarre.  If no one
 867        # can explain it, perhaps we should re-arrange them.
 868        self.factory.doStart()
 869        skt.listen(self.backlog)
 870        self.connected = True
 871        self.socket = skt
 872        self.fileno = self.socket.fileno
 873        self.numberAccepts = 100
 874
 875        self.startReading()
 876
 877
 878    def _buildAddr(self, (host, port)):
 879        return address._ServerFactoryIPv4Address('TCP', host, port)
 880
 881
 882    def doRead(self):
 883        """Called when my socket is ready for reading.
 884
 885        This accepts a connection and calls self.protocol() to handle the
 886        wire-level protocol.
 887        """
 888        try:
 889            if platformType == "posix":
 890                numAccepts = self.numberAccepts
 891            else:
 892                # win32 event loop breaks if we do more than one accept()
 893                # in an iteration of the event loop.
 894                numAccepts = 1
 895            for i in range(numAccepts):
 896                # we need this so we can deal with a factory's buildProtocol
 897                # calling our loseConnection
 898                if self.disconnecting:
 899                    return
 900                try:
 901                    skt, addr = self.socket.accept()
 902                except socket.error, e:
 903                    if e.args[0] in (EWOULDBLOCK, EAGAIN):
 904                        self.numberAccepts = i
 905                        break
 906                    elif e.args[0] == EPERM:
 907                        # Netfilter on Linux may have rejected the
 908                        # connection, but we get told to try to accept()
 909                        # anyway.
 910                        continue
 911                    elif e.args[0] in (EMFILE, ENOBUFS, ENFILE, ENOMEM, ECONNABORTED):
 912
 913                        # Linux gives EMFILE when a process is not allowed
 914                        # to allocate any more file descriptors.  *BSD and
 915                        # Win32 give (WSA)ENOBUFS.  Linux can also give
 916                        # ENFILE if the system is out of inodes, or ENOMEM
 917                        # if there is insufficient memory to allocate a new
 918                        # dentry.  ECONNABORTED is documented as possible on
 919                        # both Linux and Windows, but it is not clear
 920                        # whether there are actually any circumstances under
 921                        # which it can happen (one might expect it to be
 922                        # possible if a client sends a FIN or RST after the
 923                        # server sends a SYN|ACK but before application code
 924                        # calls accept(2), however at least on Linux this
 925                        # _seems_ to be short-circuited by syncookies.
 926
 927                        log.msg("Could not accept new connection (%s)" % (
 928                            errorcode[e.args[0]],))
 929                        break
 930                    raise
 931
 932                protocol = self.factory.buildProtocol(self._buildAddr(addr))
 933                if protocol is None:
 934                    skt.close()
 935                    continue
 936                s = self.sessionno
 937                self.sessionno = s+1
 938                transport = self.transport(skt, protocol, addr, self, s, self.reactor)
 939                transport = self._preMakeConnection(transport)
 940                protocol.makeConnection(transport)
 941            else:
 942                self.numberAccepts = self.numberAccepts+20
 943        except:
 944            # Note that in TLS mode, this will possibly catch SSL.Errors
 945            # raised by self.socket.accept()
 946            #
 947            # There is no "except SSL.Error:" above because SSL may be
 948            # None if there is no SSL support.  In any case, all the
 949            # "except SSL.Error:" suite would probably do is log.deferr()
 950            # and return, so handling it here works just as well.
 951            log.deferr()
 952
 953    def _preMakeConnection(self, transport):
 954        return transport
 955
 956    def loseConnection(self, connDone=failure.Failure(main.CONNECTION_DONE)):
 957        """
 958        Stop accepting connections on this port.
 959
 960        This will shut down the socket and call self.connectionLost().  It
 961        returns a deferred which will fire successfully when the port is
 962        actually closed.
 963        """
 964        self.disconnecting = True
 965        self.stopReading()
 966        if self.connected:
 967            self.deferred = defer.Deferred()
 968            self.reactor.callLater(0, self.connectionLost, connDone)
 969            return self.deferred
 970
 971    stopListening = loseConnection
 972
 973
 974    def connectionLost(self, reason):
 975        """
 976        Cleans up the socket.
 977        """
 978        log.msg('(Port %s Closed)' % self._realPortNumber)
 979        self._realPortNumber = None
 980        d = None
 981        if hasattr(self, "deferred"):
 982            d = self.deferred
 983            del self.deferred
 984
 985        base.BasePort.connectionLost(self, reason)
 986        self.connected = False
 987        self._closeSocket()
 988        del self.socket
 989        del self.fileno
 990
 991        try:
 992            self.factory.doStop()
 993        except:
 994            self.disconnecting = False
 995            if d is not None:
 996                d.errback(failure.Failure())
 997            else:
 998                raise
 999        else:
1000            self.disconnecting = False
1001            if d is not None:
1002                d.callback(None)
1003
1004
1005    def logPrefix(self):
1006        """Returns the name of my class, to prefix log entries with.
1007        """
1008        return reflect.qual(self.factory.__class__)
1009
1010    def getHost(self):
1011        """Returns an IPv4Address.
1012
1013        This indicates the server's address.
1014        """
1015        return address.IPv4Address('TCP', *(self.socket.getsockname() + ('INET',)))
1016
1017class Connector(base.BaseConnector):
1018    def __init__(self, host, port, factory, timeout, bindAddress, reactor=None):
1019        self.host = host
1020        if isinstance(port, types.StringTypes):
1021            try:
1022                port = socket.getservbyname(port, 'tcp')
1023            except socket.error, e:
1024                raise error.ServiceNameUnknownError(string="%s (%r)" % (e, port))
1025        self.port = port
1026        self.bindAddress = bindAddress
1027        base.BaseConnector.__init__(self, factory, timeout, reactor)
1028
1029    def _makeTransport(self):
1030        return Client(self.host, self.port, self.bindAddress, self, self.reactor)
1031
1032    def getDestination(self):
1033        return address.IPv4Address('TCP', self.host, self.port, 'INET')