From 018ef43dfd3054b2d074a683a054110d24ef3c96 Mon Sep 17 00:00:00 2001 From: SashaOrlova Date: Sat, 16 Feb 2019 22:26:14 +0300 Subject: [PATCH 01/20] Update README.md --- README.md | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f1c324e..2c865a4 100644 --- a/README.md +++ b/README.md @@ -1 +1,117 @@ -# Networks Lab 2019 (Higher School of Economics) +# Сервис учета ошибок "Bug tracking" + +## Формат сообщения + + header: int message type + body: content depends on message type + +## Описание запросов + +Разработчики и тестеры идентифицируются по id. Каждая зарегистрированная ошибка также имеет id + +- Запрос на регистрацию пользователя + + type: 100 + content: user_id user_type + + user_id - положительное целое число, user_type - 1 - разработчик, 2 - тестер + + - Успех + + type: 101 + content: user_id + + - Пользователь с таким id уже существует + + type: 102 + content: user_id + + - Неизвестный тип пользователя + + type: 103 + content: user_type + +- Выдача тестеру списка ошибок + + type: 200 + content: bug_status + + bug_status - 0 - активная, 1 - закрытая + + - Успех + + type: 201 + content: int number of bugs + [ + int bug_id + int project_id + int description length + char[] description + ] + +- Подтверждение/отклонение исправления активной ошибки + + type: 300 + content: int bug_id + int verification_code + + verification_code - 0 - отклонение, 1 - подтверждение + + - Успех + + type: 301 + content: int bug_id + + - Ошибка уже не активна + + type: 302 + content: int bug_status + +- Выдача ошибок разработчику + + type: 400 + content: int user_id + + - Успех + + type: 401 + content: int number of bugs + [ + int bug_id + int description length + char[] description + ] + +- Исправления активной ошибки разработчиком + + type: 500 + content: int bug_id + + - Успех + + type: 501 + content: int bug_id + +- Прием новой ошибки + + type: 600 + content: + int user_id + int project_id + int description length + char[] description + + - Успех + + type: 601 + content: int bug_id + +- Отключение клиента + + type: 700 + content: + +- Сообщение о неизвестном типе запроса + + type: 1 + content: int type From 98462b34e3a43c98d9448301a947d9287e3b7ed5 Mon Sep 17 00:00:00 2001 From: SashaOrlova Date: Sat, 16 Feb 2019 22:31:18 +0300 Subject: [PATCH 02/20] Update README.md --- README.md | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 2c865a4..03e45cf 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,10 @@ Разработчики и тестеры идентифицируются по id. Каждая зарегистрированная ошибка также имеет id -- Запрос на регистрацию пользователя +- Запрос на регистрацию пользователя: user_id - положительное целое число, user_type - 1 - разработчик, 2 - тестер type: 100 content: user_id user_type - - user_id - положительное целое число, user_type - 1 - разработчик, 2 - тестер - Успех @@ -31,13 +29,11 @@ type: 103 content: user_type -- Выдача тестеру списка ошибок +- Выдача тестеру списка ошибок: bug_status - 0 - активная, 1 - закрытая type: 200 content: bug_status - bug_status - 0 - активная, 1 - закрытая - - Успех type: 201 @@ -49,14 +45,12 @@ char[] description ] -- Подтверждение/отклонение исправления активной ошибки +- Подтверждение/отклонение исправления активной ошибки: verification_code - 0 - отклонение, 1 - подтверждение type: 300 content: int bug_id int verification_code - - verification_code - 0 - отклонение, 1 - подтверждение - + - Успех type: 301 From 5f087f21db50b969286edb0487f74830ce9f0b0e Mon Sep 17 00:00:00 2001 From: SashaOrlova Date: Sat, 16 Feb 2019 22:57:05 +0300 Subject: [PATCH 03/20] Update README.md --- README.md | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 03e45cf..641f011 100644 --- a/README.md +++ b/README.md @@ -9,24 +9,19 @@ Разработчики и тестеры идентифицируются по id. Каждая зарегистрированная ошибка также имеет id -- Запрос на регистрацию пользователя: user_id - положительное целое число, user_type - 1 - разработчик, 2 - тестер +- Запрос на регистрацию пользователя: user_type - 1 - разработчик, 2 - тестер type: 100 - content: user_id user_type + content: int user_type - Успех type: 101 - content: user_id - - - Пользователь с таким id уже существует - - type: 102 - content: user_id - + content: int user_id + - Неизвестный тип пользователя - type: 103 + type: 102 content: user_type - Выдача тестеру списка ошибок: bug_status - 0 - активная, 1 - закрытая From 08bbf2e4978ea9721915284258a43c13a2673c84 Mon Sep 17 00:00:00 2001 From: SashaOrlova Date: Sat, 16 Feb 2019 23:20:03 +0300 Subject: [PATCH 04/20] Update README.md --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 641f011..757b473 100644 --- a/README.md +++ b/README.md @@ -81,11 +81,16 @@ type: 501 content: int bug_id + - Задача уже закрыта + + type: 502 + content: int bug_status + - Прием новой ошибки type: 600 content: - int user_id + int developer_id int project_id int description length char[] description From e04e51b2a82b067673cf545814a483e5b2559c0c Mon Sep 17 00:00:00 2001 From: SashaOrlova Date: Sun, 17 Feb 2019 10:14:38 +0300 Subject: [PATCH 05/20] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 757b473..ae52d7a 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ - Неизвестный тип пользователя type: 102 - content: user_type + content: int user_type - Выдача тестеру списка ошибок: bug_status - 0 - активная, 1 - закрытая From d941f894056194d9f079df985d4e2ce41d016604 Mon Sep 17 00:00:00 2001 From: SashaOrlova Date: Sun, 17 Feb 2019 10:48:21 +0300 Subject: [PATCH 06/20] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index ae52d7a..f997ba0 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,11 @@ type: 302 content: int bug_status + + - Ошибки с таким кодом не существует + + type: 303 + content: int bug_id - Выдача ошибок разработчику From cbe5f9320e68c044743d617d080213f66bab001c Mon Sep 17 00:00:00 2001 From: SashaOrlova Date: Sun, 17 Feb 2019 10:53:02 +0300 Subject: [PATCH 07/20] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f997ba0..eff7590 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ type: 302 content: int bug_status - - Ошибки с таким кодом не существует + - Ошибки с таким кодом не существует type: 303 content: int bug_id From aaa10ffd3c6c2d040ff5191138aedfadbf05e86f Mon Sep 17 00:00:00 2001 From: SashaOrlova Date: Sun, 17 Feb 2019 11:28:18 +0300 Subject: [PATCH 08/20] Update README.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index eff7590..9a69f1a 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,11 @@ int description length char[] description ] - + - Неизвестный id разработчика + + type: 402 + content: int user_id + - Исправления активной ошибки разработчиком type: 500 From ea66f37dc5997cafd94a11a54461d8bf4c704ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80?= =?UTF-8?q?=D0=B0=20=D0=9E=D1=80=D0=BB=D0=BE=D0=B2=D0=B0?= Date: Sun, 17 Feb 2019 17:53:03 +0300 Subject: [PATCH 09/20] add client --- tcp/client/CMakeLists.txt | 6 + tcp/client/src/client.cpp | 261 ++++++++++++++++++++++++++++++++++++++ tcp/client/src/client.h | 57 +++++++++ tcp/client/src/main.cpp | 40 ++++++ 4 files changed, 364 insertions(+) create mode 100644 tcp/client/CMakeLists.txt create mode 100644 tcp/client/src/client.cpp create mode 100644 tcp/client/src/client.h create mode 100644 tcp/client/src/main.cpp diff --git a/tcp/client/CMakeLists.txt b/tcp/client/CMakeLists.txt new file mode 100644 index 0000000..905d4d9 --- /dev/null +++ b/tcp/client/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.13) +project(client) + +set(CMAKE_CXX_STANDARD 17) + +add_executable(client src/main.cpp src/client.cpp src/client.h) \ No newline at end of file diff --git a/tcp/client/src/client.cpp b/tcp/client/src/client.cpp new file mode 100644 index 0000000..ecadfca --- /dev/null +++ b/tcp/client/src/client.cpp @@ -0,0 +1,261 @@ +#include +#include "client.h" + +client::client(const char *host, uint16_t port_number) { + sockfd = socket(AF_INET, SOCK_STREAM, 0); + hostent* server = gethostbyname(host); + + if (sockfd < 0) { + std::cerr << "ERROR opening socket\n"; + exit(1); + } + + if (server == nullptr) { + std::cerr << "ERROR, no such host\n"; + exit(0); + } + + sockaddr_in serv_addr{}; + bzero((char *) &serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + bcopy(server->h_addr, (char *) &serv_addr.sin_addr.s_addr, (size_t) server->h_length); + serv_addr.sin_port = htons(port_number); + + /* Now connect to the server */ + if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { + std::cerr << "ERROR connecting\n"; + exit(1); + } + std::cout << "Connection established\n"; +} + +void client::registerUser() { + std::string pos; + int position = 0; + std::cin >> pos; + if (pos == "tester") { + position = 2; + } + if (pos == "developer") { + position = 1; + } + if (position == 0) { + std::cout << "Undefined position: " + pos + '\n'; + return; + } + sendNum(REGISTER_USER); + sendNum(position); + int answer_type = getNum(); + switch (answer_type) { + case REGISTER_USER_SUCC: { + user_id = getNum(); + std::cout << "Register user with id: " + std::to_string(user_id) + '\n'; + break; + } + case REGISTER_USER_UNDEFINED_TYPE: { + int type = getNum(); + std::cout << "Can't register user with type code " + std::to_string(type) + '\n'; + break; + } + default: { + std::cout << "Undefined server code\n"; + } + } +} + +int client::getNum() { + int num; + int n = read(sockfd, &num, sizeof(int32_t)); + if (n < 0) { + terminate(); + } + return ntohl(num); +} + +void client::sendNum(int num) { + num = htonl(num); + write(sockfd, &num, sizeof(int32_t)); +} + +void client::sendString(std::string string_to_send) { + int length = string_to_send.length(); + sendNum(length); + write(sockfd, string_to_send.c_str(), length); +} + +std::string client::getString() { + int length = getNum(); + char* buf = new char[length + 1]; + int n = read(sockfd, buf, length); + buf[length] = '\0'; + std::string ans(buf); + delete[] buf; + if (n < 0) { + terminate(); + } + return ans; +} + +void client::terminate() { + std::cout << "Program end\n"; + exit(0); +} + +void client::getBugsTester() { + std::string bug_type; + bug_status bug_code = UNDEFINED; + std::cin >> bug_type; + if (bug_type == "active") { + bug_code = ACTIVE; + } + if (bug_type == "close") { + bug_code = CLOSE; + } + if (bug_code == UNDEFINED) { + std::cout << "Undefined type of bug: " + bug_type; + } + sendNum(GET_TESTER_BUG_LIST); + sendNum(bug_code); + int type = getNum(); + if (type != GET_TESTER_BUG_LIST_SUCC) { + std::cout << "Undefined server code\n"; + return; + } + int bug_count = getNum(); + for (int i = 0; i < bug_count; ++i) { + int bug_id = getNum(); + int project_id = getNum(); + std::string description = getString(); + std::cout << "Bug with id: " << bug_id << "project id: " << project_id << " description: " << description; + } +} + +void client::confirmBugTester() { + int bug_id; + std::cin >> bug_id; + sendNum(PROCESS_BUG_TESTER); + sendNum(bug_id); + sendNum(ACCEPT); + int type = getNum(); + switch (type) { + case PROCESS_BUG_TESTER_SUCC: { + bug_id = getNum(); + std::cout << "Accept bug with id: " << bug_id << '\n'; + break; + } + case PROCESS_BUG_TESTER_NON_ACTIVE_BUG: { + int bug_status = getNum(); + std::cout << "With bug was close with status " << bug_status << '\n'; + break; + } + case PROCESS_BUG_TESTER_NO_BUG_ID: { + bug_id = getNum(); + std::cout << "No bug with id: " << bug_id << '\n'; + break; + } + default: { + std::cout << "Undefined server code\n"; + } + } +} + +void client::rejectBugTester() { + int bug_id; + std::cin >> bug_id; + sendNum(PROCESS_BUG_TESTER); + sendNum(bug_id); + sendNum(DECLINE); + int type = getNum(); + switch (type) { + case PROCESS_BUG_TESTER_SUCC: { + bug_id = getNum(); + std::cout << "Accept bug with id: " << bug_id << '\n'; + break; + } + case PROCESS_BUG_TESTER_NON_ACTIVE_BUG: { + int bug_status = getNum(); + std::cout << "With bug was close with status " << bug_status << '\n'; + break; + } + case PROCESS_BUG_TESTER_NO_BUG_ID: { + bug_id = getNum(); + std::cout << "No bug with id: " << bug_id << '\n'; + break; + } + default: { + std::cout << "Undefined server code\n"; + } + } +} + +void client::getBugsDeveloper() { + sendNum(GET_DEVELOPER_BUGS); + sendNum(user_id); + int type = getNum(); + switch (type) { + case GET_DEVELOPER_BUGS_SUCC: { + int bugs_count = getNum(); + for (int i = 0; i < bugs_count; ++i) { + int bug_id = getNum(); + std::string description = getString(); + std::cout << "Bug with id: " << bug_id << " with description: " << description << '\n'; + } + break; + } + case GET_DEVELOPER_BUGS_NO_ID: { + int developer_id = getNum(); + std::cout << "No developer with id: " << developer_id << '\n'; + break; + } + default: { + std::cout << "Undefined server code\n"; + break; + } + } +} + +void client::closeBugDeveloper() { + int bud_id; + std::cin >> bud_id; + sendNum(CLOSE_BUG_DEVELOPER); + sendNum(bud_id); + int type = getNum(); + switch (type) { + case CLOSE_BUG_DEVELOPER_SUCC: { + bud_id = getNum(); + std::cout << "Clode bug with id: " << bud_id << '\n'; + break; + } + case CLOSE_BUG_DEVELOPER_NO_ID: { + bud_id = getNum(); + std::cout << "No bug with id: " << bud_id << '\n'; + break; + } + default: { + std::cout << "Undefined server code\n"; + break; + } + } +} + +void client::addNewBug() { + int developer_id = 0, project_id = 0; + std::string description; + std::cout << developer_id << project_id << description; + sendNum(SEND_NEW_BUG); + sendNum(developer_id); + sendNum(project_id); + sendString(description); + int type = getNum(); + if (type == SEND_NEW_BUG_SUCC) { + int bug_id = getNum(); + std::cout << "Create new bug with id: " << bug_id << '\n'; + } else { + std::cout << "Undefined server code\n"; + } +} + +void client::quit() { + sendNum(CLIENT_TERMINATE); + terminate(); +} diff --git a/tcp/client/src/client.h b/tcp/client/src/client.h new file mode 100644 index 0000000..366230c --- /dev/null +++ b/tcp/client/src/client.h @@ -0,0 +1,57 @@ +#ifndef CLIENT_TESTER_H +#define CLIENT_TESTER_H + +#include +#include +#include +#include +#include + +enum position {TESTER = 2, DEVELOPER = 1}; +enum bug_status {ACTIVE = 0, CLOSE = 1, UNDEFINED = 3}; +enum verification_code {DECLINE = 0, ACCEPT = 1}; +enum message_code { + REGISTER_USER = 100, + REGISTER_USER_SUCC = 101, + REGISTER_USER_UNDEFINED_TYPE = 102, + GET_TESTER_BUG_LIST = 200, + GET_TESTER_BUG_LIST_SUCC = 201, + PROCESS_BUG_TESTER = 300, + PROCESS_BUG_TESTER_SUCC = 301, + PROCESS_BUG_TESTER_NON_ACTIVE_BUG = 302, + PROCESS_BUG_TESTER_NO_BUG_ID = 303, + GET_DEVELOPER_BUGS = 400, + GET_DEVELOPER_BUGS_SUCC = 401, + GET_DEVELOPER_BUGS_NO_ID = 402, + CLOSE_BUG_DEVELOPER = 500, + CLOSE_BUG_DEVELOPER_SUCC = 501, + CLOSE_BUG_DEVELOPER_NO_ID = 502, + SEND_NEW_BUG = 600, + SEND_NEW_BUG_SUCC = 601, + CLIENT_TERMINATE = 700 +}; + +class client { + public: + client(const char* host, uint16_t port_number); + void registerUser(); + void getBugsTester(); + void confirmBugTester(); + void rejectBugTester(); + void getBugsDeveloper(); + void closeBugDeveloper(); + void addNewBug(); + void quit(); + + private: + int user_id; + int sockfd; + int getNum(); + void sendNum(int num); + void sendString(std::string string_to_send); + std::string getString(); + void terminate(); +}; + + +#endif //CLIENT_TESTER_H diff --git a/tcp/client/src/main.cpp b/tcp/client/src/main.cpp new file mode 100644 index 0000000..78f09e3 --- /dev/null +++ b/tcp/client/src/main.cpp @@ -0,0 +1,40 @@ +#include +#include +#include "client.h" + +int main(int argc, char *argv[]) { + if (argc < 2) { + std::cout << "Invalid arguments"; + exit(0); + } + int port_number = std::stoi(argv[2]); + client cl(argv[1], port_number); + while (true) { + std::string command; + std::cin >> command; + if (command == "create_new_bug") { + cl.addNewBug(); + } + if (command == "register_user") { + cl.registerUser(); + } + if (command == "get_bugs") { + cl.getBugsTester(); + } + if (command == "get_developer_bugs") { + cl.getBugsDeveloper(); + } + if (command == "accept_bug") { + cl.confirmBugTester(); + } + if (command == "reject_bug") { + cl.rejectBugTester(); + } + if (command == "close_bug") { + cl.closeBugDeveloper(); + } + if (command == "quit") { + cl.quit(); + } + } +} \ No newline at end of file From ed51d9fa5a4904172efcbc8baf6f3c0902aafd38 Mon Sep 17 00:00:00 2001 From: XRater Date: Sun, 17 Feb 2019 20:45:52 +0300 Subject: [PATCH 10/20] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9a69f1a..5ac0e27 100644 --- a/README.md +++ b/README.md @@ -9,17 +9,17 @@ Разработчики и тестеры идентифицируются по id. Каждая зарегистрированная ошибка также имеет id -- Запрос на регистрацию пользователя: user_type - 1 - разработчик, 2 - тестер +- Запрос на авторизацю пользователя type: 100 - content: int user_type + content: int user_id - Успех type: 101 - content: int user_id + content: int user_type - - Неизвестный тип пользователя + - Пользователь не найден type: 102 content: int user_type From 2d3278deaad2716bd5f047760131e5afd88ed394 Mon Sep 17 00:00:00 2001 From: XRater Date: Sun, 17 Feb 2019 21:33:22 +0300 Subject: [PATCH 11/20] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5ac0e27..da269d6 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ - Пользователь не найден type: 102 - content: int user_type + content: int user_id - Выдача тестеру списка ошибок: bug_status - 0 - активная, 1 - закрытая From 13343f6976d64d8c1ad46bceb58d1ebce56739f2 Mon Sep 17 00:00:00 2001 From: Aleksandr Kirakosian Date: Sun, 17 Feb 2019 21:56:02 +0300 Subject: [PATCH 12/20] Connection and disconnection supported on server --- tcp/server/CMakeLists.txt | 11 ++ tcp/server/include/BugTrackingServer.h | 50 +++++++ tcp/server/include/UserService.h | 33 +++++ tcp/server/src/BugTrackingServer.cpp | 185 +++++++++++++++++++++++++ tcp/server/src/UserService.cpp | 37 +++++ tcp/server/src/main.cpp | 26 ++++ 6 files changed, 342 insertions(+) create mode 100644 tcp/server/CMakeLists.txt create mode 100644 tcp/server/include/BugTrackingServer.h create mode 100644 tcp/server/include/UserService.h create mode 100644 tcp/server/src/BugTrackingServer.cpp create mode 100644 tcp/server/src/UserService.cpp create mode 100644 tcp/server/src/main.cpp diff --git a/tcp/server/CMakeLists.txt b/tcp/server/CMakeLists.txt new file mode 100644 index 0000000..e8251c5 --- /dev/null +++ b/tcp/server/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.13) +project(BugTrackingServer) +find_package (Threads) + +set(CMAKE_CXX_STANDARD 14) + +add_executable(server src/main.cpp + src/BugTrackingServer.cpp include/BugTrackingServer.h + src/UserService.cpp include/UserService.h +) +target_link_libraries (server ${CMAKE_THREAD_LIBS_INIT}) \ No newline at end of file diff --git a/tcp/server/include/BugTrackingServer.h b/tcp/server/include/BugTrackingServer.h new file mode 100644 index 0000000..04e79f8 --- /dev/null +++ b/tcp/server/include/BugTrackingServer.h @@ -0,0 +1,50 @@ +#ifndef NETWORKS_BUG_TRACKING_SERVER_H +#define NETWORKS_BUG_TRACKING_SERVER_H + +#include +#include +#include "UserService.h" + +class BugTrackingServer { +private: + class Client { + public: + const int sock_fd; + UserService::User user; + + explicit Client(int socket_fd, UserService* userService); + + bool isAuthorized(); + + bool authorize(int id); + private: + UserService* _userService; + }; + +public: + explicit BugTrackingServer(UserService* userService); + + void initServer(uint16_t port_number); + + bool authorize(Client& client); + + bool close(Client& client); + +private: + UserService* _userService; + std::map _clients; + std::mutex _clients_mutex; + + void process_client(int sock_fd); + + static bool writeInt32(int sock_fd, uint32_t number); + + static bool writeString(int sock_fd, std::string data); + + static bool readInt32(int sock_fd, uint32_t& dst); + + static bool readString(int sock_fd, std::string& dst); +}; + + +#endif \ No newline at end of file diff --git a/tcp/server/include/UserService.h b/tcp/server/include/UserService.h new file mode 100644 index 0000000..2c92482 --- /dev/null +++ b/tcp/server/include/UserService.h @@ -0,0 +1,33 @@ +#ifndef BUG_TRACKING_SERVER_USERS_SERVER_H +#define BUG_TRACKING_SERVER_USERS_SERVER_H + +#include +#include + +class UserService { +public: + UserService(); + + class User { + public: + User(); + User(int id, int role); + + int id; + int role; + + bool isEmpty(); + + static User emptyUser(); + }; + + User registerNewUser(int id, int role); + + User getUser(int id); + +private: + std::map _users; + std::mutex _users_mutex; +}; + +#endif diff --git a/tcp/server/src/BugTrackingServer.cpp b/tcp/server/src/BugTrackingServer.cpp new file mode 100644 index 0000000..7af77a4 --- /dev/null +++ b/tcp/server/src/BugTrackingServer.cpp @@ -0,0 +1,185 @@ +#include "../include/BugTrackingServer.h" +#include +#include +#include + +#include +#include +#include +#include +#include + +BugTrackingServer::BugTrackingServer(UserService* userService) : _userService(userService) {} + +void BugTrackingServer::initServer(uint16_t port_number) { + int socket_fd = socket(AF_INET, SOCK_STREAM, 0); + if (socket_fd < 0) { + perror("ERROR opening socket"); + exit(1); + } + + sockaddr_in server_addr = {0}, cli_addr = {0}; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(port_number); + + bzero((char *) &server_addr, sizeof(server_addr)); + + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(port_number); + + if (bind(socket_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) { + perror("ERROR on binding"); + exit(1); + } + listen(socket_fd, 5); + + while (true) { + unsigned int client = sizeof(cli_addr); + int new_socket_fd = accept(socket_fd, (struct sockaddr*) &cli_addr, &client); + if (new_socket_fd < 0) { + perror("ERROR on accept"); + exit(1); + } + std::thread thread(&BugTrackingServer::process_client, this, new_socket_fd); + thread.detach(); + } +} + +void BugTrackingServer::process_client(int sock_fd) { + std::cout << "New client connected on " << sock_fd << ".\n"; + Client client = Client(sock_fd, _userService); + _clients_mutex.lock(); + _clients[sock_fd] = &client; + _clients_mutex.unlock(); + uint32_t code; + while (true) { + if (!readInt32(sock_fd, code)) { + std::cout << "Failed to process message from client " << sock_fd << ". Closing connection.\n"; + close(client); + break; + } else { + if (code == 100) { + authorize(client); + } else if (!client.isAuthorized()) { + // process unauthorized + } else { + if (code == 200) { + + } else if (code == 300) { + + } else if (code == 400) { + + } else if (code == 500) { + + } else if (code == 600) { + + } else if (code == 700) { + close(client); + break; + } else { + writeInt32(sock_fd, 1); + } + } + } + } +} + +bool BugTrackingServer::authorize(BugTrackingServer::Client& client) { + int sock_fd = client.sock_fd; + uint32_t id; + readInt32(sock_fd, id); + if (client.user.id != id) { + // process double authorization + return false; + } + if (client.authorize(id)) { + writeInt32(sock_fd, 101); + writeInt32(sock_fd, static_cast(client.user.role)); + std::cout << "Client on socket " << sock_fd << " has authorized with id " << client.user.id; + std::cout << " and role " << client.user.role << "\n"; + return true; + } else { + writeInt32(sock_fd, 102); + writeInt32(sock_fd, id); + std::cout << "Client on socket " << sock_fd << " has failed authorization\n"; + return false; + } +} + +bool BugTrackingServer::close(BugTrackingServer::Client &client) { + _clients_mutex.lock(); + if (_clients.find(client.sock_fd) == _clients.end()) { + _clients_mutex.unlock(); + std::cout << "Client with socket " << client.sock_fd << " is already disconnected\n"; + return false; + } else { + _clients.erase(client.sock_fd); + _clients_mutex.unlock(); + std::cout << "Client with socket " << client.sock_fd << " has been disconnected\n"; + return true; + } +} + +/* READING FUNCTIONS */ + +bool BugTrackingServer::readInt32(int sock_fd, uint32_t& dst) { + ssize_t n = read(sock_fd, &dst, sizeof(uint32_t)); + if (n < 0) { + return false; + } + dst = ntohl(dst); + return true; +} + +bool BugTrackingServer::readString(int sock_fd, std::string& dst) { + uint32_t length; + if (!readInt32(sock_fd, length)) { + return false; + } + char buf[length + 1]; + buf[length] = '\0'; + ssize_t n = read(sock_fd, buf, length); + if (n < 0) { + return false; + } + dst = std::string(buf); + return true; +} + +/* WRITING FUNCTIONS */ + +bool BugTrackingServer::writeInt32(int sock_fd, uint32_t number) { + uint32_t value = htonl(number); + return ::write(sock_fd, &value, sizeof(uint32_t)) >= 0; +} + +bool BugTrackingServer::writeString(int sock_fd, std::string data) { + auto length = static_cast(data.length()); + if (!writeInt32(sock_fd, length)) { + return false; + } + ssize_t written = ::write(sock_fd, data.c_str(), length); + return written >= 0; +} + +/* CLIENT FUNCTIONS */ + +BugTrackingServer::Client::Client( + int socket_fd, + UserService* userService +) : sock_fd(socket_fd), _userService(userService) {} + +bool BugTrackingServer::Client::isAuthorized() { + return user.isEmpty(); +} + +bool BugTrackingServer::Client::authorize(int id) { + UserService::User newUser = _userService->getUser(id); + if (newUser.isEmpty()) { + return false; + } + user = newUser; + return true; +} \ No newline at end of file diff --git a/tcp/server/src/UserService.cpp b/tcp/server/src/UserService.cpp new file mode 100644 index 0000000..340a5dd --- /dev/null +++ b/tcp/server/src/UserService.cpp @@ -0,0 +1,37 @@ +#include "../include/UserService.h" + +UserService::UserService() = default; + +UserService::User UserService::registerNewUser(int id, int role) { + User user = UserService::User(id, role); + _users_mutex.lock(); + if (_users.find('2') == _users.end()) { + _users[id] = user; + } + _users_mutex.unlock(); + return user; +} + +UserService::User UserService::getUser(int id) { + User user; + _users_mutex.lock(); + if (_users.find(id) == _users.end()) { + user = _users[id]; + } else { + user = User::emptyUser(); + } + _users_mutex.unlock(); + return user; +} + +UserService::User UserService::User::emptyUser() { + return {}; +} + +UserService::User::User(int id, int role) : id(id), role(role) {} + +UserService::User::User() : User(-1, -1) {} + +bool UserService::User::isEmpty() { + return id == -1; +} diff --git a/tcp/server/src/main.cpp b/tcp/server/src/main.cpp new file mode 100644 index 0000000..937b3ac --- /dev/null +++ b/tcp/server/src/main.cpp @@ -0,0 +1,26 @@ +#include +#include +#include +#include "../include/BugTrackingServer.h" + +int main(int argc, char* argv[]) { + if (argc != 2) { + std::cout << "Invalid arguments number\n"; + return 0; + } + UserService userService; + + uint16_t port_number = static_cast(std::stoi(argv[1])); + + std::cout << "Initializing server on port " << port_number << "\n"; + BugTrackingServer server(&userService); + std::thread server_thread(&BugTrackingServer::initServer, &server, port_number); + server_thread.detach(); + + std::string in; + while (in != "exit") { + std::cin >> in; + } + std::cout << "Shutting down server\n"; + close(port_number); +} \ No newline at end of file From 1785f0e876b4b4b39652575a83fc08daf5ef883c Mon Sep 17 00:00:00 2001 From: XRater Date: Mon, 18 Feb 2019 20:53:21 +0300 Subject: [PATCH 13/20] Update README.md --- README.md | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index da269d6..7b5d104 100644 --- a/README.md +++ b/README.md @@ -17,13 +17,19 @@ - Успех type: 101 - content: int user_type + content: int user_role - Пользователь не найден type: 102 content: int user_id + - Пользователь уже авторизован + + type: 103 + content: int user_id + int user_role + - Выдача тестеру списка ошибок: bug_status - 0 - активная, 1 - закрытая type: 200 @@ -50,6 +56,7 @@ type: 301 content: int bug_id + int verification_code - Ошибка уже не активна @@ -61,6 +68,17 @@ type: 303 content: int bug_id + - Ошибки еще не исправлена + + type: 304 + content: int bug_id + + - Неизвстный код верификации + + type: 305 + content: int verification_code + + - Выдача ошибок разработчику type: 400 @@ -94,11 +112,17 @@ type: 502 content: int bug_status - + + - Задача не найдена + + type: 503 + content: int bug_id + - Прием новой ошибки type: 600 content: + int bug_id int developer_id int project_id int description length @@ -109,6 +133,11 @@ type: 601 content: int bug_id + - Ошибка с таким id уже существует + + type: 602 + content: int bug_id + - Отключение клиента type: 700 @@ -118,3 +147,12 @@ type: 1 content: int type + +- Сообщение об отутсвии авторизации + + type: 2 + +- Сообщение об отутсвии прав (неверная роль; 0 - developer, 1 - tester) + + type: 3 + content: required role From eb192f862b5d3a9eb556d459def23f25ea8d7d05 Mon Sep 17 00:00:00 2001 From: Aleksandr Kirakosian Date: Mon, 18 Feb 2019 20:53:54 +0300 Subject: [PATCH 14/20] Implemented all functions --- tcp/server/CMakeLists.txt | 1 + tcp/server/include/Bug.h | 18 ++ tcp/server/include/BugTrackingServer.h | 14 ++ tcp/server/include/UserService.h | 10 +- tcp/server/src/BugTrackingServer.cpp | 241 ++++++++++++++++++++++--- tcp/server/src/UserService.cpp | 16 +- 6 files changed, 262 insertions(+), 38 deletions(-) create mode 100644 tcp/server/include/Bug.h diff --git a/tcp/server/CMakeLists.txt b/tcp/server/CMakeLists.txt index e8251c5..a44af15 100644 --- a/tcp/server/CMakeLists.txt +++ b/tcp/server/CMakeLists.txt @@ -7,5 +7,6 @@ set(CMAKE_CXX_STANDARD 14) add_executable(server src/main.cpp src/BugTrackingServer.cpp include/BugTrackingServer.h src/UserService.cpp include/UserService.h + include/Bug.h ) target_link_libraries (server ${CMAKE_THREAD_LIBS_INIT}) \ No newline at end of file diff --git a/tcp/server/include/Bug.h b/tcp/server/include/Bug.h new file mode 100644 index 0000000..9c18b71 --- /dev/null +++ b/tcp/server/include/Bug.h @@ -0,0 +1,18 @@ +#ifndef BUG_TRACKING_SERVER_BUG_H +#define BUG_TRACKING_SERVER_BUG_H + + +struct Bug { + enum BugStatus { + NEW, QA, FIXED + }; + + uint32_t id; + uint32_t developer_id; + uint32_t project_id; + BugStatus status; + std::string description; +}; + + +#endif diff --git a/tcp/server/include/BugTrackingServer.h b/tcp/server/include/BugTrackingServer.h index 04e79f8..24b854a 100644 --- a/tcp/server/include/BugTrackingServer.h +++ b/tcp/server/include/BugTrackingServer.h @@ -4,6 +4,7 @@ #include #include #include "UserService.h" +#include "Bug.h" class BugTrackingServer { private: @@ -28,6 +29,16 @@ class BugTrackingServer { bool authorize(Client& client); + bool bugsTesterList(Client& client); + + bool bugVerification(Client& client); + + bool bugsDeveloperList(Client& client); + + bool bugFix(Client& client); + + bool bugRegister(Client& client); + bool close(Client& client); private: @@ -35,6 +46,9 @@ class BugTrackingServer { std::map _clients; std::mutex _clients_mutex; + std::map _bugs; + std::mutex _bugs_mutex; + void process_client(int sock_fd); static bool writeInt32(int sock_fd, uint32_t number); diff --git a/tcp/server/include/UserService.h b/tcp/server/include/UserService.h index 2c92482..fbec851 100644 --- a/tcp/server/include/UserService.h +++ b/tcp/server/include/UserService.h @@ -10,19 +10,21 @@ class UserService { class User { public: + enum Role { + NONE, DEVELOPER, TESTER + }; + User(); - User(int id, int role); + User(int id, Role role); int id; - int role; + Role role; bool isEmpty(); static User emptyUser(); }; - User registerNewUser(int id, int role); - User getUser(int id); private: diff --git a/tcp/server/src/BugTrackingServer.cpp b/tcp/server/src/BugTrackingServer.cpp index 7af77a4..3d5b56f 100644 --- a/tcp/server/src/BugTrackingServer.cpp +++ b/tcp/server/src/BugTrackingServer.cpp @@ -8,6 +8,7 @@ #include #include #include +#include BugTrackingServer::BugTrackingServer(UserService* userService) : _userService(userService) {} @@ -62,25 +63,22 @@ void BugTrackingServer::process_client(int sock_fd) { } else { if (code == 100) { authorize(client); - } else if (!client.isAuthorized()) { - // process unauthorized + } else if (code == 200) { + bugsTesterList(client); + } else if (code == 300) { + bugVerification(client); + } else if (code == 400) { + bugsDeveloperList(client); + } else if (code == 500) { + bugFix(client); + } else if (code == 600) { + bugRegister(client); + } else if (code == 700) { + close(client); + break; } else { - if (code == 200) { - - } else if (code == 300) { - - } else if (code == 400) { - - } else if (code == 500) { - - } else if (code == 600) { - - } else if (code == 700) { - close(client); - break; - } else { - writeInt32(sock_fd, 1); - } + std::cout << "Client with id " << sock_fd << " has sent unknown request "; + writeInt32(sock_fd, 1); } } } @@ -90,13 +88,16 @@ bool BugTrackingServer::authorize(BugTrackingServer::Client& client) { int sock_fd = client.sock_fd; uint32_t id; readInt32(sock_fd, id); - if (client.user.id != id) { - // process double authorization + if (client.isAuthorized()) { + std::cout << "Client on socket " << sock_fd << " is already authorized with id " << client.user.id; + writeInt32(sock_fd, 101); + writeInt32(sock_fd, static_cast(client.user.id)); + writeInt32(sock_fd, client.user.role); return false; } if (client.authorize(id)) { writeInt32(sock_fd, 101); - writeInt32(sock_fd, static_cast(client.user.role)); + writeInt32(sock_fd, client.user.role); std::cout << "Client on socket " << sock_fd << " has authorized with id " << client.user.id; std::cout << " and role " << client.user.role << "\n"; return true; @@ -108,6 +109,204 @@ bool BugTrackingServer::authorize(BugTrackingServer::Client& client) { } } +bool BugTrackingServer::bugsTesterList(BugTrackingServer::Client &client) { + int sock_fd = client.sock_fd; + uint32_t bugStatus; + readInt32(sock_fd, bugStatus); + if (!client.isAuthorized()) { + std::cout << "Request from unauthorized client " << client.sock_fd << "\n"; + writeInt32(sock_fd, 2); + return false; + } + if (client.user.role != UserService::User::Role::TESTER) { + std::cout << "User with id " << client.user.id << " is not tester and cannot see bugs\n"; + writeInt32(sock_fd, 3); + writeInt32(sock_fd, UserService::User::Role::TESTER); + return false; + } + std::vector bugsList; + _bugs_mutex.lock(); + for (const auto &entry : _bugs) { + if (entry.second.developer_id == client.user.id && entry.second.status == bugStatus) { + bugsList.push_back(entry.second); + } + } + _bugs_mutex.unlock(); + std::cout << "Tester with id " << client.user.id << " requested bugs with status " << bugStatus << "\n"; + writeInt32(sock_fd, static_cast(bugsList.size())); + for (const auto &bug : bugsList) { + writeInt32(sock_fd, bug.id); + writeString(sock_fd, bug.description); + } + return true; +} + +bool BugTrackingServer::bugVerification(BugTrackingServer::Client &client) { + int sock_fd = client.sock_fd; + uint32_t bugId, verificationCode; + readInt32(sock_fd, bugId); + readInt32(sock_fd, verificationCode); + if (!client.isAuthorized()) { + std::cout << "Request from unauthorized client " << client.sock_fd << "\n"; + writeInt32(sock_fd, 2); + return false; + } + if (client.user.role != UserService::User::Role::TESTER) { + std::cout << "Client with id " << client.user.id << " is not tester and cannot verify bug: " << bugId << "\n"; + writeInt32(sock_fd, 3); + writeInt32(sock_fd, UserService::User::Role::TESTER); + return false; + } + _bugs_mutex.lock(); + if (_bugs.find(bugId) == _bugs.end()) { + _bugs_mutex.unlock(); + std::cout << "Client with id " << client.user.id << " tried to verify non existing bug with id " << bugId << "\n"; + writeInt32(sock_fd, 303); + writeInt32(sock_fd, bugId); + return false; + } else { + if (_bugs[bugId].status == Bug::BugStatus::NEW) { + _bugs_mutex.unlock(); + std::cout << "Tester with id " << client.user.id << " tried to verify not fixed bug with id " << bugId << "\n"; + writeInt32(sock_fd, 304); + writeInt32(sock_fd, bugId); + return false; + } else if (_bugs[bugId].status == Bug::BugStatus::QA){ + if (verificationCode == 0) { + _bugs[bugId].status = Bug::BugStatus::NEW; + _bugs_mutex.unlock(); + std::cout << "Tester with id " << client.user.id << " has rejected bug fix with id " << bugId << "\n"; + } else if (verificationCode == 1) { + _bugs[bugId].status = Bug::BugStatus::FIXED; + _bugs_mutex.unlock(); + std::cout << "Tester with id " << client.user.id << " has approved bug fix with id " << bugId << "\n"; + } else { + _bugs_mutex.unlock(); + std::cout << "Tester with id " << client.user.id << " has sent illegal verification code " << verificationCode << "\n"; + writeInt32(sock_fd, 304); + writeInt32(sock_fd, verificationCode); + return false; + } + writeInt32(sock_fd, 301); + writeInt32(sock_fd, bugId); + writeInt32(sock_fd, verificationCode); + return true; + } else { + std::cout << "Tester with id " << client.user.id << " tried to verify closed bug with id " << bugId << "\n"; + writeInt32(sock_fd, 302); + writeInt32(sock_fd, bugId); + return false; + } + } +} + +bool BugTrackingServer::bugsDeveloperList(BugTrackingServer::Client &client) { + int sock_fd = client.sock_fd; + if (!client.isAuthorized()) { + std::cout << "Request from unauthorized client " << client.sock_fd << "\n"; + writeInt32(sock_fd, 2); + return false; + } + if (client.user.role != UserService::User::Role::DEVELOPER) { + std::cout << "User with id " << client.user.id << " is not developer and does not have bugs\n"; + writeInt32(sock_fd, 3); + writeInt32(sock_fd, UserService::User::Role::DEVELOPER); + return false; + } + std::vector clientBugs; + _bugs_mutex.lock(); + for (const auto &entry : _bugs) { + if (entry.second.developer_id == client.user.id && entry.second.status == Bug::BugStatus::NEW) { + clientBugs.push_back(entry.second); + } + } + _bugs_mutex.unlock(); + std::cout << "Developer with id " << client.user.id << " requested his bug-list\n"; + writeInt32(sock_fd, static_cast(clientBugs.size())); + for (const auto &bug : clientBugs) { + writeInt32(sock_fd, bug.id); + writeString(sock_fd, bug.description); + } + return true; +} + +bool BugTrackingServer::bugFix(BugTrackingServer::Client &client) { + int sock_fd = client.sock_fd; + uint32_t bugId; + readInt32(sock_fd, bugId); + if (!client.isAuthorized()) { + std::cout << "Request from unauthorized client " << client.sock_fd << "\n"; + writeInt32(sock_fd, 2); + return false; + } + if (client.user.role != UserService::User::Role::DEVELOPER) { + std::cout << "User with id " << client.user.id << " is not developer and cannot fix bug: " << bugId << "\n"; + writeInt32(sock_fd, 3); + writeInt32(sock_fd, UserService::User::Role::DEVELOPER); + return false; + } + _bugs_mutex.lock(); + if (_bugs.find(bugId) == _bugs.end()) { + _bugs_mutex.unlock(); + std::cout << "Developer with id " << client.user.id << " tried to fix non existing bug with id " << bugId << "\n"; + writeInt32(sock_fd, 503); + writeInt32(sock_fd, bugId); + return false; + } else { + if (_bugs[bugId].status != Bug::BugStatus::NEW) { + Bug::BugStatus status = _bugs[bugId].status; + _bugs_mutex.unlock(); + std::cout << "Developer with id " << client.user.id << " tried to fix not actual bug with id " << bugId << "\n"; + writeInt32(sock_fd, 502); + writeInt32(sock_fd, status); + return false; + } else { + _bugs[bugId].status = Bug::BugStatus::QA; + _bugs_mutex.unlock(); + std::cout << "Developer with id " << client.user.id << " has fixed bug with id " << bugId << "\n"; + writeInt32(sock_fd, 501); + writeInt32(sock_fd, bugId); + return true; + } + } +} + +bool BugTrackingServer::bugRegister(BugTrackingServer::Client &client) { + int sock_fd = client.sock_fd; + std::string description; + Bug bug; + readInt32(sock_fd, bug.id); + readInt32(sock_fd, bug.developer_id); + readInt32(sock_fd, bug.project_id); + readString(sock_fd, bug.description); + if (!client.isAuthorized()) { + std::cout << "Request from unauthorized client " << client.sock_fd << "\n"; + writeInt32(sock_fd, 2); + return false; + } + if (client.user.role != UserService::User::Role::TESTER) { + std::cout << "User with id " << client.user.id << " is not tester and cannot register bugs" << bug.id << "\n"; + writeInt32(sock_fd, 3); + writeInt32(sock_fd, UserService::User::Role::TESTER); + return false; + } + _bugs_mutex.lock(); + if (_bugs.find(bug.id) != _bugs.end()) { + _bugs_mutex.unlock(); + std::cout << "Tester with id " << client.user.id << " tried to register existing bug with id " << bug.id << "\n"; + writeInt32(sock_fd, 602); + writeInt32(sock_fd, bug.id); + return false; + } else { + _bugs[bug.id] = bug; + _bugs_mutex.unlock(); + writeInt32(sock_fd, 601); + writeInt32(sock_fd, bug.id); + std::cout << "Tester with id " << client.user.id << " has registered new bug with id " << bug.id << '\n'; + return true; + } +} + bool BugTrackingServer::close(BugTrackingServer::Client &client) { _clients_mutex.lock(); if (_clients.find(client.sock_fd) == _clients.end()) { diff --git a/tcp/server/src/UserService.cpp b/tcp/server/src/UserService.cpp index 340a5dd..a720118 100644 --- a/tcp/server/src/UserService.cpp +++ b/tcp/server/src/UserService.cpp @@ -2,16 +2,6 @@ UserService::UserService() = default; -UserService::User UserService::registerNewUser(int id, int role) { - User user = UserService::User(id, role); - _users_mutex.lock(); - if (_users.find('2') == _users.end()) { - _users[id] = user; - } - _users_mutex.unlock(); - return user; -} - UserService::User UserService::getUser(int id) { User user; _users_mutex.lock(); @@ -28,10 +18,10 @@ UserService::User UserService::User::emptyUser() { return {}; } -UserService::User::User(int id, int role) : id(id), role(role) {} +UserService::User::User(int id, Role role) : id(id), role(role) {} -UserService::User::User() : User(-1, -1) {} +UserService::User::User() : User(-1, Role::NONE) {} bool UserService::User::isEmpty() { - return id == -1; + return id == -1 || role == Role::NONE; } From afc090782f5dcb76dd7d6cf738c9401036cf992c Mon Sep 17 00:00:00 2001 From: XRater Date: Mon, 18 Feb 2019 21:00:04 +0300 Subject: [PATCH 15/20] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7b5d104..1d0d25b 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ - Выдача ошибок разработчику type: 400 - content: int user_id + content: - Успех From b09f807c19ff8d33804ffdb5be18cd509b070986 Mon Sep 17 00:00:00 2001 From: Aleksandr Kirakosian Date: Mon, 18 Feb 2019 21:03:17 +0300 Subject: [PATCH 16/20] Added method to ban client --- tcp/server/include/BugTrackingServer.h | 2 ++ tcp/server/src/BugTrackingServer.cpp | 14 ++++++++++++++ tcp/server/src/main.cpp | 5 +++++ 3 files changed, 21 insertions(+) diff --git a/tcp/server/include/BugTrackingServer.h b/tcp/server/include/BugTrackingServer.h index 24b854a..8d34f35 100644 --- a/tcp/server/include/BugTrackingServer.h +++ b/tcp/server/include/BugTrackingServer.h @@ -41,6 +41,8 @@ class BugTrackingServer { bool close(Client& client); + bool banClient(int id); + private: UserService* _userService; std::map _clients; diff --git a/tcp/server/src/BugTrackingServer.cpp b/tcp/server/src/BugTrackingServer.cpp index 3d5b56f..0d1efe4 100644 --- a/tcp/server/src/BugTrackingServer.cpp +++ b/tcp/server/src/BugTrackingServer.cpp @@ -321,6 +321,20 @@ bool BugTrackingServer::close(BugTrackingServer::Client &client) { } } +bool BugTrackingServer::banClient(int id) { + _clients_mutex.lock(); + if (_clients.find(id) == _clients.end()) { + _clients_mutex.unlock(); + std::cout << "Client with id " << id << " was not found\n"; + return false; + } else { + Client* client = _clients[id]; + _clients_mutex.unlock(); + std::cout << "Client with id " << id << " has been banned\n"; + return close(*client); + } +} + /* READING FUNCTIONS */ bool BugTrackingServer::readInt32(int sock_fd, uint32_t& dst) { diff --git a/tcp/server/src/main.cpp b/tcp/server/src/main.cpp index 937b3ac..4d22465 100644 --- a/tcp/server/src/main.cpp +++ b/tcp/server/src/main.cpp @@ -18,8 +18,13 @@ int main(int argc, char* argv[]) { server_thread.detach(); std::string in; + int id; while (in != "exit") { std::cin >> in; + if (in == "ban") { + std::cin >> id; + server.banClient(id); + } } std::cout << "Shutting down server\n"; close(port_number); From 367c8b528f8f3bce7aa15bb5c440926fb1a8846a Mon Sep 17 00:00:00 2001 From: Aleksandr Kirakosian Date: Mon, 18 Feb 2019 21:19:28 +0300 Subject: [PATCH 17/20] Extracted user from user service --- tcp/server/CMakeLists.txt | 1 + tcp/server/include/BugTrackingServer.h | 2 +- tcp/server/include/User.h | 15 +++++++++++++ tcp/server/include/UserService.h | 20 ++--------------- tcp/server/src/BugTrackingServer.cpp | 26 ++++++++++----------- tcp/server/src/UserService.cpp | 31 +++++++++++++------------- tcp/server/src/main.cpp | 2 +- 7 files changed, 48 insertions(+), 49 deletions(-) create mode 100644 tcp/server/include/User.h diff --git a/tcp/server/CMakeLists.txt b/tcp/server/CMakeLists.txt index a44af15..1116470 100644 --- a/tcp/server/CMakeLists.txt +++ b/tcp/server/CMakeLists.txt @@ -8,5 +8,6 @@ add_executable(server src/main.cpp src/BugTrackingServer.cpp include/BugTrackingServer.h src/UserService.cpp include/UserService.h include/Bug.h + include/User.h ) target_link_libraries (server ${CMAKE_THREAD_LIBS_INIT}) \ No newline at end of file diff --git a/tcp/server/include/BugTrackingServer.h b/tcp/server/include/BugTrackingServer.h index 8d34f35..94c0fb1 100644 --- a/tcp/server/include/BugTrackingServer.h +++ b/tcp/server/include/BugTrackingServer.h @@ -11,7 +11,7 @@ class BugTrackingServer { class Client { public: const int sock_fd; - UserService::User user; + User user; explicit Client(int socket_fd, UserService* userService); diff --git a/tcp/server/include/User.h b/tcp/server/include/User.h new file mode 100644 index 0000000..ab637b9 --- /dev/null +++ b/tcp/server/include/User.h @@ -0,0 +1,15 @@ +#ifndef BUG_TRACKING_SERVER_USER_H +#define BUG_TRACKING_SERVER_USER_H + + +struct User { + enum Role { + NONE, DEVELOPER, TESTER + }; + + int id = -1; + Role role = Role::NONE; +}; + + +#endif diff --git a/tcp/server/include/UserService.h b/tcp/server/include/UserService.h index fbec851..9cc532c 100644 --- a/tcp/server/include/UserService.h +++ b/tcp/server/include/UserService.h @@ -3,27 +3,11 @@ #include #include +#include "User.h" class UserService { public: - UserService(); - - class User { - public: - enum Role { - NONE, DEVELOPER, TESTER - }; - - User(); - User(int id, Role role); - - int id; - Role role; - - bool isEmpty(); - - static User emptyUser(); - }; + explicit UserService(std::string filename); User getUser(int id); diff --git a/tcp/server/src/BugTrackingServer.cpp b/tcp/server/src/BugTrackingServer.cpp index 0d1efe4..1c5117b 100644 --- a/tcp/server/src/BugTrackingServer.cpp +++ b/tcp/server/src/BugTrackingServer.cpp @@ -118,10 +118,10 @@ bool BugTrackingServer::bugsTesterList(BugTrackingServer::Client &client) { writeInt32(sock_fd, 2); return false; } - if (client.user.role != UserService::User::Role::TESTER) { + if (client.user.role != User::Role::TESTER) { std::cout << "User with id " << client.user.id << " is not tester and cannot see bugs\n"; writeInt32(sock_fd, 3); - writeInt32(sock_fd, UserService::User::Role::TESTER); + writeInt32(sock_fd, User::Role::TESTER); return false; } std::vector bugsList; @@ -151,10 +151,10 @@ bool BugTrackingServer::bugVerification(BugTrackingServer::Client &client) { writeInt32(sock_fd, 2); return false; } - if (client.user.role != UserService::User::Role::TESTER) { + if (client.user.role != User::Role::TESTER) { std::cout << "Client with id " << client.user.id << " is not tester and cannot verify bug: " << bugId << "\n"; writeInt32(sock_fd, 3); - writeInt32(sock_fd, UserService::User::Role::TESTER); + writeInt32(sock_fd, User::Role::TESTER); return false; } _bugs_mutex.lock(); @@ -207,10 +207,10 @@ bool BugTrackingServer::bugsDeveloperList(BugTrackingServer::Client &client) { writeInt32(sock_fd, 2); return false; } - if (client.user.role != UserService::User::Role::DEVELOPER) { + if (client.user.role != User::Role::DEVELOPER) { std::cout << "User with id " << client.user.id << " is not developer and does not have bugs\n"; writeInt32(sock_fd, 3); - writeInt32(sock_fd, UserService::User::Role::DEVELOPER); + writeInt32(sock_fd, User::Role::DEVELOPER); return false; } std::vector clientBugs; @@ -239,10 +239,10 @@ bool BugTrackingServer::bugFix(BugTrackingServer::Client &client) { writeInt32(sock_fd, 2); return false; } - if (client.user.role != UserService::User::Role::DEVELOPER) { + if (client.user.role != User::Role::DEVELOPER) { std::cout << "User with id " << client.user.id << " is not developer and cannot fix bug: " << bugId << "\n"; writeInt32(sock_fd, 3); - writeInt32(sock_fd, UserService::User::Role::DEVELOPER); + writeInt32(sock_fd, User::Role::DEVELOPER); return false; } _bugs_mutex.lock(); @@ -284,10 +284,10 @@ bool BugTrackingServer::bugRegister(BugTrackingServer::Client &client) { writeInt32(sock_fd, 2); return false; } - if (client.user.role != UserService::User::Role::TESTER) { + if (client.user.role != User::Role::TESTER) { std::cout << "User with id " << client.user.id << " is not tester and cannot register bugs" << bug.id << "\n"; writeInt32(sock_fd, 3); - writeInt32(sock_fd, UserService::User::Role::TESTER); + writeInt32(sock_fd, User::Role::TESTER); return false; } _bugs_mutex.lock(); @@ -385,12 +385,12 @@ BugTrackingServer::Client::Client( ) : sock_fd(socket_fd), _userService(userService) {} bool BugTrackingServer::Client::isAuthorized() { - return user.isEmpty(); + return user.role != User::Role::NONE; } bool BugTrackingServer::Client::authorize(int id) { - UserService::User newUser = _userService->getUser(id); - if (newUser.isEmpty()) { + User newUser = _userService->getUser(id); + if (newUser.role == User::Role::NONE) { return false; } user = newUser; diff --git a/tcp/server/src/UserService.cpp b/tcp/server/src/UserService.cpp index a720118..ce98424 100644 --- a/tcp/server/src/UserService.cpp +++ b/tcp/server/src/UserService.cpp @@ -1,27 +1,26 @@ +#include #include "../include/UserService.h" -UserService::UserService() = default; +UserService::UserService(std::string filename) { + std::ifstream in; + in.open(filename); + int id, role; + while (!in.eof()) { + in >> id >> role; + _users[id] = User(); + _users[id].id = id; + _users[id].role = static_cast(role); + } +} -UserService::User UserService::getUser(int id) { +User UserService::getUser(int id) { User user; _users_mutex.lock(); if (_users.find(id) == _users.end()) { user = _users[id]; } else { - user = User::emptyUser(); + user = User(); } _users_mutex.unlock(); return user; -} - -UserService::User UserService::User::emptyUser() { - return {}; -} - -UserService::User::User(int id, Role role) : id(id), role(role) {} - -UserService::User::User() : User(-1, Role::NONE) {} - -bool UserService::User::isEmpty() { - return id == -1 || role == Role::NONE; -} +} \ No newline at end of file diff --git a/tcp/server/src/main.cpp b/tcp/server/src/main.cpp index 4d22465..89c76ed 100644 --- a/tcp/server/src/main.cpp +++ b/tcp/server/src/main.cpp @@ -8,7 +8,7 @@ int main(int argc, char* argv[]) { std::cout << "Invalid arguments number\n"; return 0; } - UserService userService; + UserService userService("../users.txt"); uint16_t port_number = static_cast(std::stoi(argv[1])); From 7216b884c4ba7b37fe441c58d283ec86c998da03 Mon Sep 17 00:00:00 2001 From: Aleksandr Kirakosian Date: Mon, 18 Feb 2019 21:21:07 +0300 Subject: [PATCH 18/20] Added argument for file --- tcp/server/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tcp/server/src/main.cpp b/tcp/server/src/main.cpp index 89c76ed..7639285 100644 --- a/tcp/server/src/main.cpp +++ b/tcp/server/src/main.cpp @@ -4,11 +4,11 @@ #include "../include/BugTrackingServer.h" int main(int argc, char* argv[]) { - if (argc != 2) { + if (argc != 3) { std::cout << "Invalid arguments number\n"; return 0; } - UserService userService("../users.txt"); + UserService userService(argv[2]); uint16_t port_number = static_cast(std::stoi(argv[1])); From e778ab3c47dd32ccfce3224725cab9db303d36f8 Mon Sep 17 00:00:00 2001 From: Aleksandr Kirakosian Date: Mon, 18 Feb 2019 21:25:50 +0300 Subject: [PATCH 19/20] Small fixes --- tcp/client/src/client.cpp | 3 ++- tcp/server/src/UserService.cpp | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tcp/client/src/client.cpp b/tcp/client/src/client.cpp index ecadfca..9cc242c 100644 --- a/tcp/client/src/client.cpp +++ b/tcp/client/src/client.cpp @@ -1,4 +1,5 @@ #include +#include #include "client.h" client::client(const char *host, uint16_t port_number) { @@ -217,7 +218,7 @@ void client::getBugsDeveloper() { void client::closeBugDeveloper() { int bud_id; std::cin >> bud_id; - sendNum(CLOSE_BUG_DEVELOPER); + sendNum(6686); sendNum(bud_id); int type = getNum(); switch (type) { diff --git a/tcp/server/src/UserService.cpp b/tcp/server/src/UserService.cpp index ce98424..449e835 100644 --- a/tcp/server/src/UserService.cpp +++ b/tcp/server/src/UserService.cpp @@ -1,9 +1,14 @@ #include +#include #include "../include/UserService.h" UserService::UserService(std::string filename) { std::ifstream in; in.open(filename); + if (!in) { + std::cerr << "File was not found\n"; + return; + } int id, role; while (!in.eof()) { in >> id >> role; @@ -11,6 +16,7 @@ UserService::UserService(std::string filename) { _users[id].id = id; _users[id].role = static_cast(role); } + in.close(); } User UserService::getUser(int id) { From 87dd3eeaf9e408960034dffc2b8595c127a358f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80?= =?UTF-8?q?=D0=B0=20=D0=9E=D1=80=D0=BB=D0=BE=D0=B2=D0=B0?= Date: Tue, 19 Feb 2019 21:44:46 +0300 Subject: [PATCH 20/20] littel fixes --- tcp/client/src/client.cpp | 183 ++++++++++++++++++++++++++++++-------- tcp/client/src/client.h | 14 ++- 2 files changed, 156 insertions(+), 41 deletions(-) diff --git a/tcp/client/src/client.cpp b/tcp/client/src/client.cpp index 9cc242c..67185fb 100644 --- a/tcp/client/src/client.cpp +++ b/tcp/client/src/client.cpp @@ -31,31 +31,26 @@ client::client(const char *host, uint16_t port_number) { } void client::registerUser() { - std::string pos; - int position = 0; - std::cin >> pos; - if (pos == "tester") { - position = 2; - } - if (pos == "developer") { - position = 1; - } - if (position == 0) { - std::cout << "Undefined position: " + pos + '\n'; - return; - } + int usr_id; + std::cin >> usr_id; sendNum(REGISTER_USER); - sendNum(position); + sendNum(usr_id); int answer_type = getNum(); switch (answer_type) { case REGISTER_USER_SUCC: { - user_id = getNum(); - std::cout << "Register user with id: " + std::to_string(user_id) + '\n'; + int role = getNum(); + std::cout << "Register user with id: " + std::to_string(role) + '\n'; break; } - case REGISTER_USER_UNDEFINED_TYPE: { + case REGISTER_USER_UNDEFINED_ID: { int type = getNum(); - std::cout << "Can't register user with type code " + std::to_string(type) + '\n'; + std::cout << "Can't register user id " + std::to_string(type) + '\n'; + break; + } + case REGISTER_USER_AUTORIZE: { + int user_id = getNum(); + int user_role = getNum(); + std::cout << "User with id " << user_id << " and role " << user_role << " already authorized\n"; break; } default: { @@ -118,16 +113,33 @@ void client::getBugsTester() { sendNum(GET_TESTER_BUG_LIST); sendNum(bug_code); int type = getNum(); - if (type != GET_TESTER_BUG_LIST_SUCC) { - std::cout << "Undefined server code\n"; - return; - } - int bug_count = getNum(); - for (int i = 0; i < bug_count; ++i) { - int bug_id = getNum(); - int project_id = getNum(); - std::string description = getString(); - std::cout << "Bug with id: " << bug_id << "project id: " << project_id << " description: " << description; + switch (type) { + case GET_TESTER_BUG_LIST_SUCC: { + int bug_count = getNum(); + for (int i = 0; i < bug_count; ++i) { + int bug_id = getNum(); + int project_id = getNum(); + std::string description = getString(); + std::cout << "Bug with id: " << bug_id << "project id: " << project_id << " description: " << description; + } + break; + } + case UNKNOWN_REQUEST: { + int ver_code = getNum(); + std::cout << "Unknown request code " << ver_code << '\n'; + break; + } + case UNAUTORIZE: { + std::cout << "You not authorize\n"; + break; + } + case CHECK_RIGHTS: { + std::cout << "You don't have rights\n"; + break; + } + default: { + std::cout << "Undefined server code\n"; + } } } @@ -154,6 +166,29 @@ void client::confirmBugTester() { std::cout << "No bug with id: " << bug_id << '\n'; break; } + case PROCESS_BUG_TESTER_NOT_FIX: { + bug_id = getNum(); + std::cout << "Bug with id: " << bug_id << ' not fix' << '\n'; + break; + } + case PROCESS_BUG_TESTER_UNKNOWN_CODE: { + int ver_code = getNum(); + std::cout << "Unknown verify code " << ver_code << '\n'; + break; + } + case UNKNOWN_REQUEST: { + int ver_code = getNum(); + std::cout << "Unknown request code " << ver_code << '\n'; + break; + } + case UNAUTORIZE: { + std::cout << "You not authorize\n"; + break; + } + case CHECK_RIGHTS: { + std::cout << "You don't have rights\n"; + break; + } default: { std::cout << "Undefined server code\n"; } @@ -183,6 +218,29 @@ void client::rejectBugTester() { std::cout << "No bug with id: " << bug_id << '\n'; break; } + case PROCESS_BUG_TESTER_NOT_FIX: { + bug_id = getNum(); + std::cout << "Bug with id: " << bug_id << ' not fix' << '\n'; + break; + } + case PROCESS_BUG_TESTER_UNKNOWN_CODE: { + int ver_code = getNum(); + std::cout << "Unknown verify code " << ver_code << '\n'; + break; + } + case UNKNOWN_REQUEST: { + int ver_code = getNum(); + std::cout << "Unknown request code " << ver_code << '\n'; + break; + } + case UNAUTORIZE: { + std::cout << "You not authorize\n"; + break; + } + case CHECK_RIGHTS: { + std::cout << "You don't have rights\n"; + break; + } default: { std::cout << "Undefined server code\n"; } @@ -191,7 +249,6 @@ void client::rejectBugTester() { void client::getBugsDeveloper() { sendNum(GET_DEVELOPER_BUGS); - sendNum(user_id); int type = getNum(); switch (type) { case GET_DEVELOPER_BUGS_SUCC: { @@ -208,6 +265,19 @@ void client::getBugsDeveloper() { std::cout << "No developer with id: " << developer_id << '\n'; break; } + case UNKNOWN_REQUEST: { + int ver_code = getNum(); + std::cout << "Unknown request code " << ver_code << '\n'; + break; + } + case UNAUTORIZE: { + std::cout << "You not authorize\n"; + break; + } + case CHECK_RIGHTS: { + std::cout << "You don't have rights\n"; + break; + } default: { std::cout << "Undefined server code\n"; break; @@ -218,7 +288,7 @@ void client::getBugsDeveloper() { void client::closeBugDeveloper() { int bud_id; std::cin >> bud_id; - sendNum(6686); + sendNum(CLOSE_BUG_DEVELOPER); sendNum(bud_id); int type = getNum(); switch (type) { @@ -232,6 +302,24 @@ void client::closeBugDeveloper() { std::cout << "No bug with id: " << bud_id << '\n'; break; } + case CLOSE_BUG_DEVELOPER_ALREADY_CLOSE: { + int bug_status = getNum(); + std::cout << "Bug already close : " << bug_status << '\n'; + break; + } + case UNKNOWN_REQUEST: { + int ver_code = getNum(); + std::cout << "Unknown request code " << ver_code << '\n'; + break; + } + case UNAUTORIZE: { + std::cout << "You not authorize\n"; + break; + } + case CHECK_RIGHTS: { + std::cout << "You don't have rights\n"; + break; + } default: { std::cout << "Undefined server code\n"; break; @@ -240,19 +328,40 @@ void client::closeBugDeveloper() { } void client::addNewBug() { - int developer_id = 0, project_id = 0; + int developer_id = 0, project_id = 0, bug_id = 0; std::string description; - std::cout << developer_id << project_id << description; + std::cout << bug_id << developer_id << project_id << description; sendNum(SEND_NEW_BUG); + sendNum(bug_id); sendNum(developer_id); sendNum(project_id); sendString(description); int type = getNum(); - if (type == SEND_NEW_BUG_SUCC) { - int bug_id = getNum(); - std::cout << "Create new bug with id: " << bug_id << '\n'; - } else { - std::cout << "Undefined server code\n"; + switch (type) { + case SEND_NEW_BUG_SUCC: { + int bug_id = getNum(); + std::cout << "Create new bug with id: " << bug_id << '\n'; + break; + } + case SEND_NEW_BUG_EXIST: { + int bug_id = getNum(); + std::cout << "Bud with id: " << bug_id << "exist \n"; + break; + } + case UNKNOWN_REQUEST: { + int ver_code = getNum(); + std::cout << "Unknown request code " << ver_code << '\n'; + break; + } + case UNAUTORIZE: { + std::cout << "You not authorize\n"; + break; + } + case CHECK_RIGHTS: { + std::cout << "You don't have rights\n"; + break; + } + default:break; } } diff --git a/tcp/client/src/client.h b/tcp/client/src/client.h index 366230c..e2da73a 100644 --- a/tcp/client/src/client.h +++ b/tcp/client/src/client.h @@ -7,28 +7,35 @@ #include #include -enum position {TESTER = 2, DEVELOPER = 1}; enum bug_status {ACTIVE = 0, CLOSE = 1, UNDEFINED = 3}; enum verification_code {DECLINE = 0, ACCEPT = 1}; enum message_code { REGISTER_USER = 100, REGISTER_USER_SUCC = 101, - REGISTER_USER_UNDEFINED_TYPE = 102, + REGISTER_USER_UNDEFINED_ID = 102, + REGISTER_USER_AUTORIZE = 103, GET_TESTER_BUG_LIST = 200, GET_TESTER_BUG_LIST_SUCC = 201, PROCESS_BUG_TESTER = 300, PROCESS_BUG_TESTER_SUCC = 301, PROCESS_BUG_TESTER_NON_ACTIVE_BUG = 302, PROCESS_BUG_TESTER_NO_BUG_ID = 303, + PROCESS_BUG_TESTER_NOT_FIX = 304, + PROCESS_BUG_TESTER_UNKNOWN_CODE = 305, GET_DEVELOPER_BUGS = 400, GET_DEVELOPER_BUGS_SUCC = 401, GET_DEVELOPER_BUGS_NO_ID = 402, CLOSE_BUG_DEVELOPER = 500, CLOSE_BUG_DEVELOPER_SUCC = 501, CLOSE_BUG_DEVELOPER_NO_ID = 502, + CLOSE_BUG_DEVELOPER_ALREADY_CLOSE = 503, SEND_NEW_BUG = 600, SEND_NEW_BUG_SUCC = 601, - CLIENT_TERMINATE = 700 + SEND_NEW_BUG_EXIST = 602, + CLIENT_TERMINATE = 700, + UNKNOWN_REQUEST = 1, + UNAUTORIZE = 2, + CHECK_RIGHTS = 3, }; class client { @@ -44,7 +51,6 @@ class client { void quit(); private: - int user_id; int sockfd; int getNum(); void sendNum(int num);