def run(self) -> None: try: self._socket_connection.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._socket_connection.bind(self._address) logger.info( f"Server is now listening on: {self._address[0]}:{self._address[1]}" ) self._socket_connection.listen(4) except OSError as e: # [WinError 10038] socket closed before logger.error(e) self._exit.set() except socket.gaierror: raise ValueError( f"Address error. {self._address} is not a valid address. Address must be of type {SocketAddress}" ) while not self._exit.is_set(): try: (connection, addr) = self._socket_connection.accept() logger.info("New client connected: (%s)", str(addr)) client_id = self._produce_next_client_id() client_communicator_id = to_server_id(client_id) client = self._client_communicator( client_communicator_id, self._address, connection, self._remove_disconnected_client) self._add_client(client_communicator_id, client) except OSError as e: if not isinstance(e, socket.timeout): if not self._exit.is_set(): logger.error("TCP connection closed while listening")
def _connect(self, seconds_till_next_try: float = 2, timeout: float = -1) -> bool: waited = 0 while not self._exit.is_set() and not self._is_connected: # TODO: Get timeout time from Connector.connect try: self._socket_connection = socket.create_connection(self._address) self._socket_connection.settimeout(self._recv_timeout) self._is_connected = True logger.info(f"Successfully connected to: {str(self._address)}") return True except ConnectionRefusedError: logger.warning("Could not connect to server with address: (%s)", str(self._address)) except OSError as e: logger.error("Is already connected to server") logger.debug(e) self._is_connected = True except socket.gaierror: raise ValueError( f"Address error. {self._address} is not a valid address. Address must be of type {SocketAddress}") self._exit.wait(seconds_till_next_try) waited += seconds_till_next_try if waited > timeout >= 0: logger.warning("Connection timeout") return False return False
def _recv_data(self, plain_byte_stream: ByteStream, encrypted_byte_stream: ByteStream) -> \ Optional[bytes]: """Returns every chunk, that can be decrypted""" data = plain_byte_stream.next_all_bytes() plain_byte_stream.remove_consumed_bytes() if len(data) > 0: return data encrypted_data = encrypted_byte_stream.next_all_bytes() encrypted_byte_stream.remove_consumed_bytes() try: while not self._exit.is_set(): chunk_data = self._socket_connection.recv(self.CHUNK_SIZE) if chunk_data == b"": logger.info("Connection reset, (%s)", str(self._address)) self._is_connected = False return None else: if not self.cryptographer.is_encrypted_communication: return chunk_data if b"%%" in chunk_data: corresponding_data = chunk_data.split(b"%%")[0] encrypted_data += corresponding_data encrypted_byte_stream += chunk_data[len(corresponding_data) + 2:] data += self.cryptographer.decrypt(encrypted_data) return data else: encrypted_data += chunk_data except ConnectionResetError: if not self._exit.is_set(): logger.warning(f"Connection reset at ID({self._id}), {self._address}") self._is_connected = False except ConnectionAbortedError: if not self._exit.is_set(): logger.warning(f"Connection aborted at ID({self._id}), {self._address}") self._is_connected = False except OSError as e: if not isinstance(e, socket.timeout): if not self._exit.is_set(): logger.warning("TCP connection closed while listening") self._is_connected = False
def stop(self, is_same_thread=False) -> None: """Stops all listening and the thread is joined. Send processes are not stopped and it the thread first stops when all data is sent.""" if self._closed: logger.debug("Prevented closing already closed communicator") else: communicator_side = "Client" if self._id >= CLIENT_ID_START else "Server" logger.info(f"Stopping {communicator_side}side communicator: {self._id}") self._exit.set() if self._socket_connection is not None: self._socket_connection.close() self._is_connected = False if not is_same_thread: self.join() remove_manager(self._id) if self._on_close is not None: try: self._on_close(self) except TypeError: pass # no function provided self._closed = True
def stop_listening(self) -> None: self._exit.set() self._socket_connection.close() self.join() logger.info("Closed server listener")