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): """ 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]
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]
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()
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()
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)
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)
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()
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)
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()
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()
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))
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))
def threadedThing(self, sock, addr): res = sock.connect_ex(addr) if res: raise error.getConnectError((res, os.strerror(res)))
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"
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()
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()