示例#1
0
    def __init__(self, port, ip_address, db, username, passwd, keys):
        """Initializes client-server network interface, connects and authenticates with the server.

        :type db: :class:`messenger.client.client_database.ClientBase`
        """

        threading.Thread.__init__(self)
        QObject.__init__(self)

        self._db = db
        self.username = username
        self.password = passwd
        self._socket = None
        self.keys = keys
        self.pubkey = None
        self.connection_init(port, ip_address)

        try:
            self.user_list_update()
            self.contact_list_update()
        except OSError as err:
            if err.errno:
                CLIENT_LOG.critical('Connection lost.')
                raise ServerError('Server connection lost!')
            CLIENT_LOG.error('Timed out while updating user lists!')
        except json.JSONDecodeError:
            CLIENT_LOG.critical('Connection lost.')
            raise ServerError('Server connection lost!')

        self.running = True
示例#2
0
    def run(self):
        """Main client transport cycle thread method.

        Receives incoming messages, passes them to the processing method and watches over the server connection."""

        CLIENT_LOG.debug('Server message transport launched.')
        while self.running:
            time.sleep(1)
            with socket_lock:
                try:
                    self._socket.settimeout(0.5)
                    message = receive_message(self._socket, CLIENT_LOG)
                except OSError as err:
                    if err.errno:
                        CLIENT_LOG.critical('Lost connection to the server!')
                        self.running = False
                        self.connection_lost.emit()
                except (ConnectionError, ConnectionResetError,
                        ConnectionAbortedError, json.JSONDecodeError,
                        TypeError):
                    CLIENT_LOG.critical('Lost connection to the server!')
                    self.running = False
                    self.connection_lost.emit()
                else:
                    CLIENT_LOG.debug(f'Got a message: {message}')
                    self.process_server_answer(message)
                finally:
                    self._socket.settimeout(5)
示例#3
0
def arg_parser():
    """ CLI parameters parser.

    Returns address, port (validated), username, password for user
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('addr', default=DEFAULT_ADDRESS, nargs='?')
    parser.add_argument('port', default=DEFAULT_PORT, type=int, nargs='?')
    parser.add_argument('-n', '--name', default=None, nargs='?')
    parser.add_argument('-p', '--password', default='', nargs='?')
    namespace = parser.parse_args(sys.argv[1:])
    server_address = namespace.addr
    server_port = namespace.port
    client_name = namespace.name
    client_passwd = namespace.password

    if not 1023 < server_port < 65536:
        CLIENT_LOG.critical(
            f'Unusable port number provided: {server_port}. Use ports between {MIN_PORT_NUMBER} and {MAX_PORT_NUMBER}.'
        )
        exit(1)

    return server_address, server_port, client_name, client_passwd
示例#4
0
    def connection_init(self, port, ip):
        """Method for starting a server connection.

        Opens socket, connects to the server over network, performs handshake and authorization."""

        self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        self._socket.settimeout(5)

        connected = False
        for i in range(5):
            CLIENT_LOG.info(f'Connecting - try #{i + 1}')
            try:
                self._socket.connect((ip, port))
            except (OSError, ConnectionRefusedError):
                pass
            else:
                connected = True
                break
            time.sleep(1)

        if not connected:
            CLIENT_LOG.critical(
                f"Couldn't connect to the server ({ip}:{port}).")
            raise ServerError("Couldn't connect to the server!")

        CLIENT_LOG.debug(
            f'Connection with server {ip}:{port} established, starting AUTH process.'
        )

        passwd_bytes = self.password.encode('utf-8')
        salt = self.username.lower().encode('utf-8')
        passwd_hash = hashlib.pbkdf2_hmac('sha512', passwd_bytes, salt, 10000)
        passwd_hash_string = binascii.hexlify(passwd_hash)
        CLIENT_LOG.debug(f'Passwd hash ready: {passwd_hash_string}')

        self.pubkey = self.keys.publickey().export_key().decode('ascii')

        try:
            with socket_lock:
                send_message(self.form_presence_message(), self._socket,
                             CLIENT_LOG)
                ans = receive_message(self._socket, CLIENT_LOG)
                if JIM.RESPONSE in ans:
                    if ans[JIM.RESPONSE] == 400:
                        raise ServerError(ans[JIM.ERROR])
                    elif ans[JIM.RESPONSE] == ResCodes.AUTH_PROCESS:
                        ans_data = ans[JIM.DATA]
                        hash = hmac.new(passwd_hash_string,
                                        ans_data.encode('utf-8'), 'MD5')
                        digest = hash.digest()
                        to_send = form_response(ResCodes.AUTH_PROCESS)
                        to_send[JIM.DATA] = binascii.b2a_base64(digest).decode(
                            'ascii')
                        send_message(to_send, self._socket, CLIENT_LOG)
                        self.process_server_answer(
                            receive_message(self._socket, CLIENT_LOG))
                # self.process_server_answer(
                #     receive_message(self._socket, CLIENT_LOG))
        except (OSError, json.JSONDecodeError) as err:
            CLIENT_LOG.critical('Connection lost.', exc_info=err)
            raise ServerError('Server connection lost!')

        CLIENT_LOG.info('Server received our presence message.')