def __init__(self, host, port, bindAddress, connector, reactor=None): # BaseClient.__init__ is invoked later self.connector = connector self.addr = (host, port) whenDone = self.resolveAddress err = None skt = None if abstract.isIPAddress(host): self._requiresResolution = False elif abstract.isIPv6Address(host): self._requiresResolution = False self.addr = _resolveIPv6(host, port) self.addressFamily = socket.AF_INET6 self._addressType = address.IPv6Address else: self._requiresResolution = True try: skt = self.createInternetSocket() except socket.error as se: err = error.ConnectBindError(se.args[0], se.args[1]) whenDone = None if whenDone and bindAddress is not None: try: if abstract.isIPv6Address(bindAddress[0]): bindinfo = _resolveIPv6(*bindAddress) else: bindinfo = bindAddress skt.bind(bindinfo) except socket.error as se: err = error.ConnectBindError(se.args[0], se.args[1]) whenDone = None self._finishInit(whenDone, skt, err, reactor)
class _SubConnector: state = "connecting" socket = None def __init__(self, sf): self.sf = sf def startConnecting(self): d = defer.maybeDeferred(self.sf.resolveAddress) d.addCallback(self._cbResolveDone) d.addErrback(self._ebResolveErr) def _cbResolveDone(self, addr): if self.state == "dead": return try: skt = socket.socket(*self.sf.sockinfo) except socket.error, se: raise error.ConnectBindError(se[0], se[1]) try: if self.sf.bindAddress is None: self.sf.bindAddress = ("", 0) # necessary for ConnectEx skt.bind(self.sf.bindAddress) except socket.error, se: raise error.ConnectBindError(se[0], se[1])
def _cbResolveDone(self, addr): if self.state == "dead": return try: skt = socket.socket(*self.sf.sockinfo) except socket.error, se: raise error.ConnectBindError(se[0], se[1])
def initConnection(self): """ Initialize connection by creating the appropriate socket. """ err = None skt = None result = True try: skt = self.createInternetSocket() except socket.error, se: err = error.ConnectBindError(se[0], se[1]) result = None
def __init__(self, host, port, bindAddress, connector, reactor=None): # BaseClient.__init__ is invoked later self.connector = connector self.addr = (host, port) whenDone = self.resolveAddress err = None skt = None try: skt = self.createInternetSocket() except socket.error, se: err = error.ConnectBindError(se[0], se[1]) whenDone = None
def __init__(self, host, port, bindAddress, connector, reactor): self.connector = connector self.addr = (host, port) self.reactor = reactor # ConnectEx documentation says socket _has_ to be bound if bindAddress is None: bindAddress = ('', 0) try: try: skt = reactor.createSocket(self.addressFamily, self.socketType) except socket.error, se: raise error.ConnectBindError(se[0], se[1]) else:
class Client(BaseClient): """A TCP client.""" def __init__(self, host, port, bindAddress, connector, reactor=None): # BaseClient.__init__ is invoked later self.connector = connector self.addr = (host, port) whenDone = self.resolveAddress err = None skt = None try: skt = self.createInternetSocket() except socket.error, se: err = error.ConnectBindError(se.args[0], se.args[1]) whenDone = None if whenDone and bindAddress is not None: try: skt.bind(bindAddress) except socket.error, se: err = error.ConnectBindError(se.args[0], se.args[1]) whenDone = None
def connectUTP(self, host, port, factory, timeout=30, bindAddress=None): if bindAddress is None: bindAddress = ['', 0] adapter = None try: adapter = self.createUTPAdapter(bindAddress[1], Protocol(), interface=bindAddress[0]) except error.CannotListenError: e = sys.exc_info()[1] c = Connector(host, port, factory, None, timeout, self) se = e.socketError # We have to call connect to trigger the factory start and connection # start events, but we already know the connection failed because the # UDP socket couldn't bind. So we set soError, which causes the connect # call to fail. c.soError = error.ConnectBindError(se[0], se[1]) c.connect() return c try: return self.connectUTPUsingAdapter(host, port, factory, adapter, timeout=timeout) except: adapter.maybeStopUDPPort() raise
class _BaseTCPClient(object): """ Code shared with other (non-POSIX) reactors for management of outgoing TCP connections (both TCPv4 and TCPv6). @note: In order to be functional, this class must be mixed into the same hierarchy as L{_BaseBaseClient}. It would subclass L{_BaseBaseClient} directly, but the class hierarchy here is divided in strange ways out of the need to share code along multiple axes; specifically, with the IOCP reactor and also with UNIX clients in other reactors. @ivar _addressType: The Twisted _IPAddress implementation for this client @type _addressType: L{IPv4Address} or L{IPv6Address} @ivar connector: The L{Connector} which is driving this L{_BaseTCPClient}'s connection attempt. @ivar addr: The address that this socket will be connecting to. @type addr: If IPv4, a 2-C{tuple} of C{(str host, int port)}. If IPv6, a 4-C{tuple} of (C{str host, int port, int ignored, int scope}). @ivar createInternetSocket: Subclasses must implement this as a method to create a python socket object of the appropriate address family and socket type. @type createInternetSocket: 0-argument callable returning C{socket._socketobject}. """ _addressType = address.IPv4Address def __init__(self, host, port, bindAddress, connector, reactor=None): # BaseClient.__init__ is invoked later self.connector = connector self.addr = (host, port) whenDone = self.resolveAddress err = None skt = None if abstract.isIPAddress(host): self._requiresResolution = False elif abstract.isIPv6Address(host): self._requiresResolution = False self.addr = _resolveIPv6(host, port) self.addressFamily = socket.AF_INET6 self._addressType = address.IPv6Address else: self._requiresResolution = True try: skt = self.createInternetSocket() except socket.error, se: err = error.ConnectBindError(se.args[0], se.args[1]) whenDone = None if whenDone and bindAddress is not None: try: if abstract.isIPv6Address(bindAddress[0]): bindinfo = _resolveIPv6(*bindAddress) else: bindinfo = bindAddress skt.bind(bindinfo) except socket.error, se: err = error.ConnectBindError(se.args[0], se.args[1]) whenDone = None
self.addr = (host, port) self.reactor = reactor # ConnectEx documentation says socket _has_ to be bound if bindAddress is None: bindAddress = ('', 0) try: try: skt = reactor.createSocket(self.addressFamily, self.socketType) except socket.error, se: raise error.ConnectBindError(se[0], se[1]) else: try: skt.bind(bindAddress) except socket.error, se: raise error.ConnectBindError(se[0], se[1]) self.socket = skt Connection.__init__(self, skt, None, reactor) reactor.callLater(0, self.resolveAddress) except error.ConnectBindError, err: reactor.callLater(0, self.failIfNotConnected, err) def resolveAddress(self): if 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])
class BaseClient(Connection): """A base class for client TCP (and similiar) sockets. """ _addressType = address.IPv4Address 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 self.doConnect() 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]) or abstract.isIPv6Address( 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, addr): """ Set the real IP address for this client. Once the IP address is set, the socket is created using the correct address family. """ if abstract.isIPv6Address(addr): self.addressFamily = socket.AF_INET6 self._addressType = address.IPv6Address self.realAddress = (addr, self.addr[1]) # create the socket and wait finish init after that self.initConnection() def initConnection(self): """ Initialize connection by creating the appropriate socket. """ err = None skt = None result = True try: skt = self.createInternetSocket() except socket.error, se: err = error.ConnectBindError(se[0], se[1]) result = None if result and self.bindAddress is not None: try: skt.bind(self.bindAddress) except socket.error, se: err = error.ConnectBindError(se[0], se[1]) result = None