def __listen(self): """ This method is called from the connection manager when the socket is a server socket and should bind to the port specified. """ if self.__socket or not self.__listener: return False if self.__unix_socket: if os.path.exists(self.__port): try: os.unlink(self.__port) except: self.__logger.error("Socket %s exists and cannot be " \ "removed" % self.__port) return False sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) address = (self.__port) to_what = "Unix Domain Socket %s" % self.__port else: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) address = (self.__host, self.__port) to_what = "TCP port %d" % self.__port try: sock.bind(address) sock.listen(5) self.__set_socket_options(sock) except socket.error as e: self.__logger.warning("Could not bind to %s: %s" \ % (to_what, str(e))) return False except Exception as e: # Other exceptions usually mean bad settings. Try one more time but # do not keep on trying forever.. self.__logger.error("Could not connect to %s: %s" \ % (to_what, str(e))) self.__giveup = 2 return False self.__logger.info("Socket listening on %s initialized" % to_what) self.__socket = sock self.__fileno = self.__socket.fileno() self.__connected = True mgr = IOManager() mgr.register(self) return True
def __connect(self): """ This method is called by the _do_attempt method when the socket is a connecting socket that should try to connect """ if self.__socket: return False if self.__unix_socket: sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) address = (self.__port) to_what = "Unix Domain Socket %s" % self.__port else: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) address = (self.__host, self.__port) to_what = "TCP port %d" % self.__port try: sock.connect(address) self.__set_socket_options(sock) except socket.error as e: self.__logger.error("Could not connect to %s: %s" \ % (to_what, str(e))) return False except Exception as e: # Other exceptions mean bad settings. Try one more time but do not # keep on trying forever.. self.__logger.error("Could not connect to %s: %s" \ % (to_what, str(e))) self.__giveup = 2 return False self.__socket = sock self.__connected = True self.__fileno = self.__socket.fileno() mgr = IOManager() mgr.register(self) if not self.send_buffer_empty(): mgr.set_writable(self, True) return True
def __init__( self, host="localhost", # The host to connect to or serve port=49152, # The port to connect to or serve giveup=5, # Amount of reconnect attempts use_socket=None, # Pass in a connected socket object to use retry_timeout=1, # Timeout between connection attempts server=None, # True for a server, False for clients use_pickle=True, # Whether to pickle/unpickle # send/received data bufsize="auto", # Number of bytes to send/receive at once linger=.1, # Whether to set the SO_LINGER option handler=False, # Set to true to make this a incoming # connection handler logger=None # Pass in a logger to use ): """ Initialize the socket. The parameters define the behavior of the socket. Host should be an IP address or hostname to which to connect or on which to listen. If the server argument is not specifically set, the hostname will also define whether this will be a server or client socket: if host is empty, it will be a server socket listening on all interfaces, otherwise it will be a client socket. port should be the port to listen on. When the port is numeric it is assumed to be a TCP port. When it is a string, it will be cast to an int specifying a TCP port. If the conversion failed, it is assumed to be a Unix Socket, located in /tmp. This will raise an exception if the socket is trying to connect to a remove Unix Socket, which is impractical and defeats the purpose. giveup is the amount of retries performed to connect to a socket or bind to a port. use_socket can be used to pass in an already connected socket. The same socket options will be set on this socket as newly created ones. retry_timeout defines the number of seconds to wait between connection/ binding attempts of unconnected sockets. server is a boolean that specifies whether this will be a server or a client socket. A server socket will bind and listen to a port, a client socket will attempt to connect to a port. The default value decides this automatically, based on the value of the host parameter as described above. use_pickle is a boolean specifying whether communication on this socket will proceed using the Pickle protocol. If set to true, all outgoing data will be pickled and all incoming data will be unpickled. bufsize specifies the amount of data to send or receive at once. The default is auto, meaning it will be set depending on other options. When the socket to use is a Unix Domain Socket, it will use 128 KiB. If it is a client socket connecting to a local socket, it will be a 16 KiB and if it is a server socket or a client socket connecting to a non-local host, a buffer of 8 KiB is used. linger is a number specifying whether the socket will be set in linger mode (see man page for setsockopt(2)). When in linger mode, the call to close on the socket will block for at most a set number of seconds and will then forcefully close the socket. Otherwise, the close call is non-blocking and the socket will get in a TIME_WAIT state, which effectively blocks the port for up to 4 minutes, possibly resulting in 'Port already bound' messages. If the linger parameter is 0, LINGER will not be used; otherwise this is the amount of seconds to set. handler can be set to True to activate incoming connection handler behavior. This basically makes sure that no reconnetion attempt is performed when the connection is closed by the other end. """ self.__socket = None self.__fileno = None self.__client_sockets = [] self.__connected = False self.__listener = False self.__handler = handler self.__use_pickle = use_pickle self.__send_lock = threading.RLock() self.__receive_lock = threading.RLock() self.__receive_buffer = [] self.__recv_buffer = "" self.__send_buffer = [] self.__send_buffer_ids = set([]) self.__buffer_start_pos = 0 self.__send_id = 0 self.__set_port(host, port) self.__set_buffer_size(bufsize) self.__linger = float(linger) self.__total_bytes = 0 self.__log_input = False self.__log_output = False if server is None and self.__host == "": self.__listener = True else: self.__listener = server if logger: self.__logger = logger else: self.__logger = logging.getLogger('Borg.Brain.Util.ThreadedSocket') self.__logger.addHandler(nullhandler.NullHandler()) self.__last_attempt = 0 self.__timeout = retry_timeout self.__giveup = giveup self.__attempt = 0 if use_socket: self.__socket = use_socket self.__fileno = self.__socket.fileno() self.__port = port self.__connected = True self.__set_socket_options(self.__socket) mgr = IOManager() mgr.register(self) else: mgr = IOManager() mgr.register_unconnected(self)
def __init__(self, host="localhost", # The host to connect to or serve port=49152, # The port to connect to or serve giveup=5, # Amount of reconnect attempts use_socket=None, # Pass in a connected socket object to use retry_timeout=1, # Timeout between connection attempts server=None, # True for a server, False for clients use_pickle=True, # Whether to pickle/unpickle # send/received data bufsize="auto", # Number of bytes to send/receive at once linger=.1, # Whether to set the SO_LINGER option handler=False, # Set to true to make this a incoming # connection handler logger=None # Pass in a logger to use ): """ Initialize the socket. The parameters define the behavior of the socket. Host should be an IP address or hostname to which to connect or on which to listen. If the server argument is not specifically set, the hostname will also define whether this will be a server or client socket: if host is empty, it will be a server socket listening on all interfaces, otherwise it will be a client socket. port should be the port to listen on. When the port is numeric it is assumed to be a TCP port. When it is a string, it will be cast to an int specifying a TCP port. If the conversion failed, it is assumed to be a Unix Socket, located in /tmp. This will raise an exception if the socket is trying to connect to a remove Unix Socket, which is impractical and defeats the purpose. giveup is the amount of retries performed to connect to a socket or bind to a port. use_socket can be used to pass in an already connected socket. The same socket options will be set on this socket as newly created ones. retry_timeout defines the number of seconds to wait between connection/ binding attempts of unconnected sockets. server is a boolean that specifies whether this will be a server or a client socket. A server socket will bind and listen to a port, a client socket will attempt to connect to a port. The default value decides this automatically, based on the value of the host parameter as described above. use_pickle is a boolean specifying whether communication on this socket will proceed using the Pickle protocol. If set to true, all outgoing data will be pickled and all incoming data will be unpickled. bufsize specifies the amount of data to send or receive at once. The default is auto, meaning it will be set depending on other options. When the socket to use is a Unix Domain Socket, it will use 128 KiB. If it is a client socket connecting to a local socket, it will be a 16 KiB and if it is a server socket or a client socket connecting to a non-local host, a buffer of 8 KiB is used. linger is a number specifying whether the socket will be set in linger mode (see man page for setsockopt(2)). When in linger mode, the call to close on the socket will block for at most a set number of seconds and will then forcefully close the socket. Otherwise, the close call is non-blocking and the socket will get in a TIME_WAIT state, which effectively blocks the port for up to 4 minutes, possibly resulting in 'Port already bound' messages. If the linger parameter is 0, LINGER will not be used; otherwise this is the amount of seconds to set. handler can be set to True to activate incoming connection handler behavior. This basically makes sure that no reconnetion attempt is performed when the connection is closed by the other end. """ self.__socket = None self.__fileno = None self.__client_sockets = [] self.__connected = False self.__listener = False self.__handler = handler self.__use_pickle = use_pickle self.__send_lock = threading.RLock() self.__receive_lock = threading.RLock() self.__receive_buffer = [] self.__recv_buffer = "" self.__send_buffer = [] self.__send_buffer_ids = set([]) self.__buffer_start_pos = 0 self.__send_id = 0 self.__set_port(host, port) self.__set_buffer_size(bufsize) self.__linger = float(linger) self.__total_bytes = 0 self.__log_input = False self.__log_output = False if server is None and self.__host == "": self.__listener = True else: self.__listener = server if logger: self.__logger = logger else: self.__logger = logging.getLogger('Borg.Brain.Util.ThreadedSocket') self.__logger.addHandler(nullhandler.NullHandler()) self.__last_attempt = 0 self.__timeout = retry_timeout self.__giveup = giveup self.__attempt = 0 if use_socket: self.__socket = use_socket self.__fileno = self.__socket.fileno() self.__port = port self.__connected = True self.__set_socket_options(self.__socket) mgr = IOManager() mgr.register(self) else: mgr = IOManager() mgr.register_unconnected(self)