Example #1
0
    def doConnect(self):
        """
        Initiate the outgoing connection attempt.

        @note: Applications do not need to call this method; it will be invoked
            internally as part of L{IReactorTCP.connectTCP}.
        """
        self.doWrite = self.doConnect
        self.doRead = self.doConnect
        if not hasattr(self, "connector"):
            # this happens when connection failed but doConnect
            # was scheduled via a callLater in self._finishInit
            return

        err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
        if err:
            self.failIfNotConnected(error.getConnectError(
                (err, strerror(err))))
            return

        # doConnect gets called twice.  The first time we actually need to
        # start the connection attempt.  The second time we don't really
        # want to (SO_ERROR above will have taken care of any errors, and if
        # it reported none, the mere fact that doConnect was called again is
        # sufficient to indicate that the connection has succeeded), but it
        # is not /particularly/ detrimental to do so.  This should get
        # cleaned up some day, though.
        try:
            connectResult = self.socket.connect_ex(self.realAddress)
        except socket.error as se:
            connectResult = se.args[0]
        if connectResult:
            if connectResult == EISCONN:
                pass
            # on Windows EINVAL means sometimes that we should keep trying:
            # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/connect_2.asp
            elif ((connectResult in (EWOULDBLOCK, EINPROGRESS, EALREADY))
                  or (connectResult == EINVAL and platformType == "win32")):
                self.startReading()
                self.startWriting()
                return
            else:
                self.failIfNotConnected(
                    error.getConnectError(
                        (connectResult, strerror(connectResult))))
                return

        # If I have reached this point without raising or returning, that means
        # that the socket is connected.
        del self.doWrite
        del self.doRead
        # we first stop and then start, to reset any references to the old doRead
        self.stopReading()
        self.stopWriting()
        self._connectDone()
Example #2
0
    def doConnect(self):
        """
        Initiate the outgoing connection attempt.

        @note: Applications do not need to call this method; it will be invoked
            internally as part of L{IReactorTCP.connectTCP}.
        """
        self.doWrite = self.doConnect
        self.doRead = self.doConnect
        if not hasattr(self, "connector"):
            # this happens when connection failed but doConnect
            # was scheduled via a callLater in self._finishInit
            return

        err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
        if err:
            self.failIfNotConnected(error.getConnectError((err, strerror(err))))
            return

        # doConnect gets called twice.  The first time we actually need to
        # start the connection attempt.  The second time we don't really
        # want to (SO_ERROR above will have taken care of any errors, and if
        # it reported none, the mere fact that doConnect was called again is
        # sufficient to indicate that the connection has succeeded), but it
        # is not /particularly/ detrimental to do so.  This should get
        # cleaned up some day, though.
        try:
            connectResult = self.socket.connect_ex(self.realAddress)
        except socket.error as se:
            connectResult = se.args[0]
        if connectResult:
            if connectResult == EISCONN:
                pass
            # on Windows EINVAL means sometimes that we should keep trying:
            # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/connect_2.asp
            elif (connectResult in (EWOULDBLOCK, EINPROGRESS, EALREADY)) or (
                connectResult == EINVAL and platformType == "win32"
            ):
                self.startReading()
                self.startWriting()
                return
            else:
                self.failIfNotConnected(error.getConnectError((connectResult, strerror(connectResult))))
                return

        # If I have reached this point without raising or returning, that means
        # that the socket is connected.
        del self.doWrite
        del self.doRead
        # we first stop and then start, to reset any references to the old doRead
        self.stopReading()
        self.stopWriting()
        self._connectDone()
    def doConnect(self):
        """I connect the socket.

        Then, call the protocol's makeConnection, and start waiting for data.
        """
        if not hasattr(self, "connector"):
            # this happens when connection failed but doConnect
            # was scheduled via a callLater in self._finishInit
            return

        err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
        if err:
            self.failIfNotConnected(error.getConnectError((err, strerror(err))))
            return


        # doConnect gets called twice.  The first time we actually need to
        # start the connection attempt.  The second time we don't really
        # want to (SO_ERROR above will have taken care of any errors, and if
        # it reported none, the mere fact that doConnect was called again is
        # sufficient to indicate that the connection has succeeded), but it
        # is not /particularly/ detrimental to do so.  This should get
        # cleaned up some day, though.
        try:
            connectResult = self.socket.connect_ex(self.realAddress)
        except socket.error, se:
            connectResult = se.args[0]
Example #4
0
    def doConnect(self):
        """
        Initiate the outgoing connection attempt.

        @note: Applications do not need to call this method; it will be invoked
            internally as part of L{IReactorTCP.connectTCP}.
        """
        self.doWrite = self.doConnect
        self.doRead = self.doConnect
        if not hasattr(self, "connector"):
            # this happens when connection failed but doConnect
            # was scheduled via a callLater in self._finishInit
            return

        err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
        if err:
            self.failIfNotConnected(error.getConnectError((err, strerror(err))))
            return

        # doConnect gets called twice.  The first time we actually need to
        # start the connection attempt.  The second time we don't really
        # want to (SO_ERROR above will have taken care of any errors, and if
        # it reported none, the mere fact that doConnect was called again is
        # sufficient to indicate that the connection has succeeded), but it
        # is not /particularly/ detrimental to do so.  This should get
        # cleaned up some day, though.
        try:
            connectResult = self.socket.connect_ex(self.realAddress)
        except socket.error, se:
            connectResult = se.args[0]
Example #5
0
 def cbConnect(self, rc, bytes, evt):
     if rc:
         rc = connectExErrors.get(rc, rc)
         self.failIfNotConnected(error.getConnectError((rc,
                                 errno.errorcode.get(rc, 'Unknown error'))))
     else:
         self.socket.setsockopt(
             socket.SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT,
             struct.pack('P', self.socket.fileno()))
         self.protocol = self.connector.buildProtocol(self.getPeer())
         self.connected = True
         logPrefix = self._getLogPrefix(self.protocol)
         self.logstr = logPrefix + ",client"
         if self.protocol is None:
             # Factory.buildProtocol is allowed to return None.  In that
             # case, make up a protocol to satisfy the rest of the
             # implementation; connectionLost is going to be called on
             # something, for example.  This is easier than adding special
             # case support for a None protocol throughout the rest of the
             # transport implementation.
             self.protocol = Protocol()
             # But dispose of the connection quickly.
             self.loseConnection()
         else:
             self.protocol.makeConnection(self)
             self.startReading()
Example #6
0
 def cbConnect(self, rc, data, evt):
     if rc:
         rc = connectExErrors.get(rc, rc)
         self.failIfNotConnected(
             error.getConnectError(
                 (rc, errno.errorcode.get(rc, "Unknown error"))))
     else:
         self.socket.setsockopt(
             socket.SOL_SOCKET,
             SO_UPDATE_CONNECT_CONTEXT,
             struct.pack("P", self.socket.fileno()),
         )
         self.protocol = self.connector.buildProtocol(self.getPeer())
         self.connected = True
         logPrefix = self._getLogPrefix(self.protocol)
         self.logstr = logPrefix + ",client"
         if self.protocol is None:
             # Factory.buildProtocol is allowed to return None.  In that
             # case, make up a protocol to satisfy the rest of the
             # implementation; connectionLost is going to be called on
             # something, for example.  This is easier than adding special
             # case support for a None protocol throughout the rest of the
             # transport implementation.
             self.protocol = Protocol()
             # But dispose of the connection quickly.
             self.loseConnection()
         else:
             self.protocol.makeConnection(self)
             self.startReading()
Example #7
0
    def doHandshake(self):
        self.stopWriting()
        try:
            self.socket.handshake()
        except (OperationWouldBlock, OperationInterrupted):
            if self.socket.interrupted_while_writing:
                self.startWriting()
            return
        except GNUTLSError as e:
            del self.doRead
            self.failIfNotConnected(err=e)
            return

        # reset any references to the old doRead
        del self.doRead
        self.stopReading()

        try:
            self._verifyPeer()
        except GNUTLSError as e:
            self.closeTLSSession(e)
            self.failIfNotConnected(err=e)
            return
        except Exception as e:
            self.closeTLSSession(e)
            self.failIfNotConnected(err=error.getConnectError(str(e)))
            return

        # TLS handshake (including certificate verification) finished succesfully
        tcp.Client._connectDone(self)
 def test_gaierror(self):
     """
     L{error.getConnectError} converts to a L{error.UnknownHostError} given
     a C{socket.gaierror} instance.
     """
     result = error.getConnectError(socket.gaierror(12, "hello"))
     self.assertCorrectException(12, "hello", result, error.UnknownHostError)
Example #9
0
 def test_gaierror(self):
     """
     L{error.getConnectError} converts to a L{error.UnknownHostError} given
     a C{socket.gaierror} instance.
     """
     result = error.getConnectError(socket.gaierror(12, "hello"))
     self.assertCorrectException(12, "hello", result, error.UnknownHostError)
 def test_nonTuple(self):
     """
     L{error.getConnectError} converts to a L{error.ConnectError} given
     an argument that cannot be unpacked.
     """
     e = Exception()
     result = error.getConnectError(e)
     self.assertCorrectException(None, e, result, error.ConnectError)
Example #11
0
 def test_nonTuple(self):
     """
     L{error.getConnectError} converts to a L{error.ConnectError} given
     an argument that cannot be unpacked.
     """
     e = Exception()
     result = error.getConnectError(e)
     self.assertCorrectException(None, e, result, error.ConnectError)
 def assertErrnoException(self, errno, expectedClass):
     """
     When called with a tuple with the given errno,
     L{error.getConnectError} returns an exception which is an instance of
     the expected class.
     """
     e = (errno, "lalala")
     result = error.getConnectError(e)
     self.assertCorrectException(errno, "lalala", result, expectedClass)
Example #13
0
 def assertErrnoException(self, errno, expectedClass):
     """
     When called with a tuple with the given errno,
     L{error.getConnectError} returns an exception which is an instance of
     the expected class.
     """
     e = (errno, "lalala")
     result = error.getConnectError(e)
     self.assertCorrectException(errno, "lalala", result, expectedClass)
Example #14
0
 def cbConnect(self, rc, bytes, evt):
     if rc:
         rc = connectExErrors.get(rc, rc)
         self.failIfNotConnected(error.getConnectError((rc, errno.errorcode.get(rc, "Unknown error"))))
     else:
         self.socket.setsockopt(socket.SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, struct.pack("I", self.socket.fileno()))
         self.protocol = self.connector.buildProtocol(self.getPeer())
         self.connected = True
         self.logstr = self.protocol.__class__.__name__ + ",client"
         self.protocol.makeConnection(self)
         self.startReading()
Example #15
0
    def fakeRead(self):
        sock = self.transport.socket
        try:
            data = sock.recv(self.transport.bufferSize, socket.MSG_PEEK)
        except socket.error as se:
            if se.args[0] == socket.EWOULDBLOCK:
                return
            else:
                return error.getConnectError(se)

        host = parse_host(data)
        self.parent.passTo(host, self)
Example #16
0
 def cbConnect(self, rc, bytes, evt):
     if rc:
         rc = connectExErrors.get(rc, rc)
         self.failIfNotConnected(
             error.getConnectError(
                 (rc, errno.errorcode.get(rc, 'Unknown error'))))
     else:
         self.socket.setsockopt(socket.SOL_SOCKET,
                                SO_UPDATE_CONNECT_CONTEXT,
                                struct.pack('I', self.socket.fileno()))
         self.protocol = self.connector.buildProtocol(self.getPeer())
         self.connected = True
         self.logstr = self.protocol.__class__.__name__ + ",client"
         self.protocol.makeConnection(self)
         self.startReading()
Example #17
0
 def cbConnect(self, rc, bytes, evt):
     if rc:
         rc = connectExErrors.get(rc, rc)
         self.failIfNotConnected(error.getConnectError((rc,
                                 errno.errorcode.get(rc, 'Unknown error'))))
     else:
         self.socket.setsockopt(
             socket.SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT,
             struct.pack('P', self.socket.fileno()))
         self.protocol = self.connector.buildProtocol(self.getPeer())
         self.connected = True
         logPrefix = self._getLogPrefix(self.protocol)
         self.logstr = logPrefix + ",client"
         self.protocol.makeConnection(self)
         self.startReading()
Example #18
0
 def connect(self, serialFactory):
     """
     Implement L{IStreamClientEndpoint.connect} to connect to serial ports
     @param serialFactory: The protocol factory which will build protocols
         for connections to this service.
     @type serialFactory: L{twisted.internet.interfaces.IProtocolFactory}
     """
     try:
         if self._serialport is None:
             raise ImportError
         else:
             # noinspection PyArgumentList
             proto = serialFactory.buildProtocol(
                 SerialAddress(self._deviceNameOrPortNumber))
             self._serialport(proto, self._deviceNameOrPortNumber,
                              self._reactor, *self._args, **self._kwargs)
             return defer.succeed(proto)
     except Exception, e:
         return defer.fail(getConnectError(e))
Example #19
0
 def connect(self, serialFactory):
     """
     Implement L{IStreamClientEndpoint.connect} to connect to serial ports
     @param serialFactory: The protocol factory which will build protocols
         for connections to this service.
     @type serialFactory: L{twisted.internet.interfaces.IProtocolFactory}
     """
     try:
         if self._serialport is None:
             raise ImportError
         else:
             # noinspection PyArgumentList
             proto = serialFactory.buildProtocol(
                 SerialAddress(self._deviceNameOrPortNumber)  )
             self._serialport(proto, self._deviceNameOrPortNumber,
                     self._reactor, *self._args, **self._kwargs)
             return defer.succeed(proto)
     except Exception, e:
         return defer.fail(getConnectError(e))
Example #20
0
 def threadedThing(self, sock, addr):
     res = sock.connect_ex(addr)
     if res:
         raise error.getConnectError((res, os.strerror(res)))
Example #21
0
            connectResult = self.socket.connect_ex(self.realAddress)
        except socket.error, se:
            connectResult = se.args[0]
        if connectResult:
            if connectResult == EISCONN:
                pass
            # on Windows EINVAL means sometimes that we should keep trying:
            # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/connect_2.asp
            elif ((connectResult in (EWOULDBLOCK, EINPROGRESS, EALREADY))
                  or (connectResult == EINVAL and platformType == "win32")):
                self.startReading()
                self.startWriting()
                return
            else:
                self.failIfNotConnected(
                    error.getConnectError(
                        (connectResult, strerror(connectResult))))
                return

        # If I have reached this point without raising or returning, that means
        # that the socket is connected.
        del self.doWrite
        del self.doRead
        # we first stop and then start, to reset any references to the old doRead
        self.stopReading()
        self.stopWriting()
        self._connectDone()

    def _connectDone(self):
        self.protocol = self.connector.buildProtocol(self.getPeer())
        self.connected = 1
        self.logstr = self.protocol.__class__.__name__ + ",client"
Example #22
0
        try:
            connectResult = self.socket.connect_ex(self.realAddress)
        except socket.error, se:
            connectResult = se.args[0]
        if connectResult:
            if connectResult == EISCONN:
                pass
            # on Windows EINVAL means sometimes that we should keep trying:
            # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/connect_2.asp
            elif ((connectResult in (EWOULDBLOCK, EINPROGRESS, EALREADY)) or
                  (connectResult == EINVAL and platformType == "win32")):
                self.startReading()
                self.startWriting()
                return
            else:
                self.failIfNotConnected(error.getConnectError((connectResult, strerror(connectResult))))
                return

        # If I have reached this point without raising or returning, that means
        # that the socket is connected.
        del self.doWrite
        del self.doRead
        # we first stop and then start, to reset any references to the old doRead
        self.stopReading()
        self.stopWriting()
        self._connectDone()

    def _connectDone(self):
        self.protocol = self.connector.buildProtocol(self.getPeer())
        self.connected = 1
        self.logstr = self.protocol.__class__.__name__ + ",client"
class BaseClient(Connection):
    """A base class for client TCP (and similiar) sockets.
    """
    addressFamily = socket.AF_INET
    socketType = socket.SOCK_STREAM

    def _finishInit(self, whenDone, skt, error, reactor):
        """Called by base classes to continue to next stage of initialization."""
        if whenDone:
            Connection.__init__(self, skt, None, reactor)
            self.doWrite = self.doConnect
            self.doRead = self.doConnect
            reactor.callLater(0, whenDone)
        else:
            reactor.callLater(0, self.failIfNotConnected, error)

    def startTLS(self, ctx, client=1):
        if Connection.startTLS(self, ctx, client):
            if client:
                self.socket.set_connect_state()
            else:
                self.socket.set_accept_state()


    def stopConnecting(self):
        """Stop attempt to connect."""
        self.failIfNotConnected(error.UserError())

    def failIfNotConnected(self, err):
        """
        Generic method called when the attemps to connect failed. It basically
        cleans everything it can: call connectionFailed, stop read and write,
        delete socket related members.
        """
        if (self.connected or self.disconnected or
            not hasattr(self, "connector")):
            return

        self.connector.connectionFailed(failure.Failure(err))
        if hasattr(self, "reactor"):
            # this doesn't happen if we failed in __init__
            self.stopReading()
            self.stopWriting()
            del self.connector

        try:
            self._closeSocket()
        except AttributeError:
            pass
        else:
            del self.socket, self.fileno

    def createInternetSocket(self):
        """(internal) Create a non-blocking socket using
        self.addressFamily, self.socketType.
        """
        s = socket.socket(self.addressFamily, self.socketType)
        s.setblocking(0)
        fdesc._setCloseOnExec(s.fileno())
        return s

    def resolveAddress(self):
        if abstract.isIPAddress(self.addr[0]):
            self._setRealAddress(self.addr[0])
        else:
            d = self.reactor.resolve(self.addr[0])
            d.addCallbacks(self._setRealAddress, self.failIfNotConnected)

    def _setRealAddress(self, address):
        self.realAddress = (address, self.addr[1])
        self.doConnect()

    def doConnect(self):
        """I connect the socket.

        Then, call the protocol's makeConnection, and start waiting for data.
        """
        if not hasattr(self, "connector"):
            # this happens when connection failed but doConnect
            # was scheduled via a callLater in self._finishInit
            return

        err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
        if err:
            self.failIfNotConnected(error.getConnectError((err, strerror(err))))
            return


        # doConnect gets called twice.  The first time we actually need to
        # start the connection attempt.  The second time we don't really
        # want to (SO_ERROR above will have taken care of any errors, and if
        # it reported none, the mere fact that doConnect was called again is
        # sufficient to indicate that the connection has succeeded), but it
        # is not /particularly/ detrimental to do so.  This should get
        # cleaned up some day, though.
        try:
            connectResult = self.socket.connect_ex(self.realAddress)
        except socket.error, se:
            connectResult = se.args[0]
        if connectResult:
            if connectResult == EISCONN:
                pass
            # on Windows EINVAL means sometimes that we should keep trying:
            # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/connect_2.asp
            elif ((connectResult in (EWOULDBLOCK, EINPROGRESS, EALREADY)) or
                  (connectResult == EINVAL and platformType == "win32")):
                self.startReading()
                self.startWriting()
                return
            else:
                self.failIfNotConnected(error.getConnectError((connectResult, strerror(connectResult))))
                return

        # If I have reached this point without raising or returning, that means
        # that the socket is connected.
        del self.doWrite
        del self.doRead
        # we first stop and then start, to reset any references to the old doRead
        self.stopReading()
        self.stopWriting()
        self._connectDone()
Example #24
0
class BaseClient(_BaseBaseClient, _TLSClientMixin, Connection):
    """
    A base class for client TCP (and similiar) sockets.

    @ivar realAddress: The address object that will be used for socket.connect;
        this address is an address tuple (the number of elements dependent upon
        the address family) which does not contain any names which need to be
        resolved.
    @type realAddress: C{tuple}

    @ivar _base: L{Connection}, which is the base class of this class which has
        all of the useful file descriptor methods.  This is used by
        L{_TLSServerMixin} to call the right methods to directly manipulate the
        transport, as is necessary for writing TLS-encrypted bytes (whereas
        those methods on L{Server} will go through another layer of TLS if it
        has been enabled).
    """

    _base = Connection
    _commonConnection = Connection

    def _stopReadingAndWriting(self):
        """
        Implement the POSIX-ish (i.e.
        L{twisted.internet.interfaces.IReactorFDSet}) method of detaching this
        socket from the reactor for L{_BaseBaseClient}.
        """
        if hasattr(self, "reactor"):
            # this doesn't happen if we failed in __init__
            self.stopReading()
            self.stopWriting()


    def _collectSocketDetails(self):
        """
        Clean up references to the socket and its file descriptor.

        @see: L{_BaseBaseClient}
        """
        del self.socket, self.fileno


    def createInternetSocket(self):
        """(internal) Create a non-blocking socket using
        self.addressFamily, self.socketType.
        """
        s = socket.socket(self.addressFamily, self.socketType)
        s.setblocking(0)
        fdesc._setCloseOnExec(s.fileno())
        return s


    def doConnect(self):
        """
        Initiate the outgoing connection attempt.

        @note: Applications do not need to call this method; it will be invoked
            internally as part of L{IReactorTCP.connectTCP}.
        """
        self.doWrite = self.doConnect
        self.doRead = self.doConnect
        if not hasattr(self, "connector"):
            # this happens when connection failed but doConnect
            # was scheduled via a callLater in self._finishInit
            return

        err = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
        if err:
            self.failIfNotConnected(error.getConnectError((err, strerror(err))))
            return

        # doConnect gets called twice.  The first time we actually need to
        # start the connection attempt.  The second time we don't really
        # want to (SO_ERROR above will have taken care of any errors, and if
        # it reported none, the mere fact that doConnect was called again is
        # sufficient to indicate that the connection has succeeded), but it
        # is not /particularly/ detrimental to do so.  This should get
        # cleaned up some day, though.
        try:
            connectResult = self.socket.connect_ex(self.realAddress)
        except socket.error, se:
            connectResult = se.args[0]
        if connectResult:
            if connectResult == EISCONN:
                pass
            # on Windows EINVAL means sometimes that we should keep trying:
            # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/connect_2.asp
            elif ((connectResult in (EWOULDBLOCK, EINPROGRESS, EALREADY)) or
                  (connectResult == EINVAL and platformType == "win32")):
                self.startReading()
                self.startWriting()
                return
            else:
                self.failIfNotConnected(error.getConnectError((connectResult, strerror(connectResult))))
                return

        # If I have reached this point without raising or returning, that means
        # that the socket is connected.
        del self.doWrite
        del self.doRead
        # we first stop and then start, to reset any references to the old doRead
        self.stopReading()
        self.stopWriting()
        self._connectDone()