def close(self):
     """Close the socket."""
     self.opentime = 0L
     self.authenticated = 0L
     self.connecttime = 0L
     Socket.close(self)
    def open(self, timeout=0, authenticate=1, blocking=1):
        """Attempt to open socket to the address set in __init__.  timeout
        is used to determine when the attempt should bail.  Any
        socket error will raise an OpenError exception and a timeout will
        raise an OpenTimeOut exception.  The authenticate() method is called
        when a valid connection is established."""

        # initialize the socket if it hasn't been done.
        if not self.socket: self._init_socket()

        # we want the timeout to be supported by blocking and nonblocking
        # sockets, so if blocking then temporarily set to nonblocking.  By
        # default opening a socket will block for no more than timeout
        # seconds, however, if your application is built robust enough you
        # might want opens to be non-blocking as well.
        if self.blocking and timeout:
            self.socket.setblocking(0)

        knownerrors = ('ECONNREFUSED', 'ETIMEDOUT', 'ENETUNREACH',
                       'EHOSTUNREACH', 'EHOSTDOWN', 'EBADF'
                       ', ECONNRESET')

        try:
            if not self.connecttime:
                self.connecttime = time.time()
            self.socket.connect(self.address)
        except (socket.error, socket.gaierror, socket.herror), errMsg:
            ecode = errno.errorcode.get(errMsg[0], None)
            if ecode in knownerrors:
                raise OpenError(self.address, str(errMsg), ecode=errMsg[0])
            elif ecode != 'EINPROGRESS':
                raise OpenError(self.address,
                                "unknown error: " + str(errMsg),
                                ecode=errMsg[0])

            # if the open is not meant to be blocking, then raise a WouldBlock
            # exception, it will be up to the caller to check on the socket
            # via select
            if not blocking:
                raise WouldBlock(self.address, str(errMsg), ecode=errMsg[0])

            # use select to wait for the socket to be ready
            try:
                if timeout:
                    input, output, err = select.select([self.socket],
                                                       [self.socket], [],
                                                       timeout)
                else:
                    input, output, err = select.select([self.socket],
                                                       [self.socket], [])

                if not (input or output):
                    Socket.close(self)
                    raise OpenTimeOut(
                        self.address, "Opening socket timed out "
                        "after %d seconds" % timeout)

                # call connect one more time so it raises an exception if
                # there is a problem
                self.socket.connect(self.address)
            except (socket.error, socket.gaierror, socket.herror), errMsg:
                ecode = errno.errorcode.get(errMsg[0], None)
                if ecode != 'EISCONN':
                    Socket.close(self)
                    if ecode in knownerrors:
                        raise OpenError(self.address,
                                        str(errMsg),
                                        ecode=errMsg[0])
                    else:
                        raise OpenError(self.address,
                                        "unknown error: " + str(errMsg),
                                        ecode=errMsg[0])
                self.socket.connect(self.address)
            except (socket.error, socket.gaierror, socket.herror), errMsg:
                ecode = errno.errorcode.get(errMsg[0], None)
                if ecode != 'EISCONN':
                    Socket.close(self)
                    if ecode in knownerrors:
                        raise OpenError(self.address,
                                        str(errMsg),
                                        ecode=errMsg[0])
                    else:
                        raise OpenError(self.address,
                                        "unknown error: " + str(errMsg),
                                        ecode=errMsg[0])

            except select.error, errMsg:
                Socket.close(self)
                raise OpenError(self.address,
                                "unknown error: " + str(errMsg),
                                ecode=errMsg[0])

        # set the open time now that we have definitely opened
        self.opentime = time.time()

        # set back to a blocking socket
        if self.blocking and timeout:
            self.socket.setblocking(1)

        if authenticate:
            newtimeout = timeout
            if timeout:
                newtimeout -= (time.time() - self.connecttime)