-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient.py
More file actions
117 lines (100 loc) · 4.86 KB
/
client.py
File metadata and controls
117 lines (100 loc) · 4.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import argparse
import os
import sys
from Cryptodome.PublicKey import RSA
from PyQt5.QtWidgets import QApplication, QMessageBox
from client.database import ClientDatabase
from client.main_window import ClientMainWindow
from client.start_dialog import UserNameDialog
from client.transport import ClientTransport
from common.deccor_log import log
from common.errors import ServerError
from common.settings import *
# Инициализация клиентского логера
logger = logging.getLogger('client')
# Парсер аргументов коммандной строки
@log
def arg_parser():
'''
Парсер аргументов командной строки, возвращает кортеж из 4 элементов
адрес сервера, порт, имя пользователя, пароль.
Выполняет проверку на корректность номера порта.
'''
parser = argparse.ArgumentParser()
parser.add_argument('addr', default=DEFAULT_IP_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:
logger.critical(
f'Попытка запуска клиента с неподходящим номером порта: {server_port}. Допустимы адреса с 1024 до 65535. Клиент завершается.')
exit(1)
return server_address, server_port, client_name, client_passwd
# Основная функция клиента
if __name__ == '__main__':
# Загружаем параметы коммандной строки
server_address, server_port, client_name, client_passwd = arg_parser()
logger.debug('Args loaded')
# Создаём клиентокое приложение
client_app = QApplication(sys.argv)
# Если имя пользователя не было указано в командной строке то запросим его
start_dialog = UserNameDialog()
if not client_name or not client_passwd:
client_app.exec_()
# Если пользователь ввёл имя и нажал ОК, то сохраняем ведённое и
# удаляем объект, инааче выходим
if start_dialog.ok_pressed:
client_name = start_dialog.client_name.text()
client_passwd = start_dialog.client_passwd.text()
logger.debug(f'Using USERNAME = {client_name}, PASSWD = {client_passwd}.')
else:
exit(0)
# Записываем логи
logger.info(
f'Запущен клиент с парамертами: адрес сервера: {server_address} , порт: {server_port}, имя пользователя: {client_name}')
# Загружаем ключи с файла, если же файла нет, то генерируем новую пару.
dir_path = os.path.dirname(os.path.realpath(__file__))
key_file = os.path.join(dir_path, f'{client_name}.key')
if not os.path.exists(key_file):
keys = RSA.generate(2048, os.urandom)
with open(key_file, 'wb') as key:
key.write(keys.export_key())
else:
with open(key_file, 'rb') as key:
keys = RSA.import_key(key.read())
# !!!keys.publickey().export_key()
logger.debug("Keys sucsessfully loaded.")
# Создаём объект базы данных
database = ClientDatabase(client_name)
# Создаём объект - транспорт и запускаем транспортный поток
try:
transport = ClientTransport(
server_port,
server_address,
database,
client_name,
client_passwd,
keys)
logger.debug("Transport ready.")
except ServerError as error:
message = QMessageBox()
message.critical(start_dialog, 'Ошибка сервера', error.text)
exit(1)
transport.setDaemon(True)
transport.start()
# Удалим объект диалога за ненадобностью
del start_dialog
# Создаём GUI
main_window = ClientMainWindow(database, transport, keys)
main_window.make_connection(transport)
main_window.setWindowTitle(f'Чат Программа alpha release - {client_name}')
client_app.exec_()
# Раз графическая оболочка закрылась, закрываем транспорт
transport.transport_shutdown()
transport.join()