From e642f987c7f40e89e8a00bcefabd98e872991062 Mon Sep 17 00:00:00 2001 From: andrey Date: Tue, 5 Feb 2019 20:53:24 +0300 Subject: [PATCH 01/48] getting started --- tcp/server/.gitkeep | 0 tcp/server/CMakeLists.txt | 7 ++++ tcp/server/src/client_abstraction.cpp | 4 +++ tcp/server/src/client_abstraction.h | 16 +++++++++ tcp/server/src/main.cpp | 16 +++++++++ tcp/server/src/server.cpp | 48 +++++++++++++++++++++++++++ tcp/server/src/server.h | 15 +++++++++ 7 files changed, 106 insertions(+) delete mode 100644 tcp/server/.gitkeep create mode 100644 tcp/server/CMakeLists.txt create mode 100644 tcp/server/src/client_abstraction.cpp create mode 100644 tcp/server/src/client_abstraction.h create mode 100644 tcp/server/src/main.cpp create mode 100644 tcp/server/src/server.cpp create mode 100644 tcp/server/src/server.h diff --git a/tcp/server/.gitkeep b/tcp/server/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/tcp/server/CMakeLists.txt b/tcp/server/CMakeLists.txt new file mode 100644 index 0000000..b22f7e6 --- /dev/null +++ b/tcp/server/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.13) +project(server) + +set(CMAKE_CXX_STANDARD 17) +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") + +add_executable(server src/main.cpp src/server.cpp src/server.h src/client_abstraction.cpp src/client_abstraction.h) \ No newline at end of file diff --git a/tcp/server/src/client_abstraction.cpp b/tcp/server/src/client_abstraction.cpp new file mode 100644 index 0000000..2606593 --- /dev/null +++ b/tcp/server/src/client_abstraction.cpp @@ -0,0 +1,4 @@ +// +// Created by andrey on 28.01.19. +// + diff --git a/tcp/server/src/client_abstraction.h b/tcp/server/src/client_abstraction.h new file mode 100644 index 0000000..e8aa7dc --- /dev/null +++ b/tcp/server/src/client_abstraction.h @@ -0,0 +1,16 @@ +#ifndef SERVER_CLIENT_ABSTRACTION_H +#define SERVER_CLIENT_ABSTRACTION_H + + +#include +#include + +class ClientAbstraction { + private: + const std::string name; + const sockaddr_in addr; + const int socket_fd; +}; + + +#endif //SERVER_CLIENT_ABSTRACTION_H diff --git a/tcp/server/src/main.cpp b/tcp/server/src/main.cpp new file mode 100644 index 0000000..5af6351 --- /dev/null +++ b/tcp/server/src/main.cpp @@ -0,0 +1,16 @@ +#include +#include "server.cpp" + +int main(int argc, char** argv) { + if (argc != 2) { + std::cout << "Usage: ./roulette_server "; + return 0; + } + + uint16_t port_number = static_cast(std::stoi(argv[1])); + + RouletteServer server; + server.StartServer(port_number); + + return 0; +} \ No newline at end of file diff --git a/tcp/server/src/server.cpp b/tcp/server/src/server.cpp new file mode 100644 index 0000000..d7ccb1e --- /dev/null +++ b/tcp/server/src/server.cpp @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include +#include "server.h" + + +void +RouletteServer::WorkWithClient(RouletteServer* server, int sock_fd, const sockaddr_in& cli_addr) { + +} + +void RouletteServer::StartServer(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 serv_addr = {0}, cli_addr = {0}; + + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = INADDR_ANY; + serv_addr.sin_port = htons(port_number); + + if (bind(socket_fd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) { + perror("ERROR on binding"); + exit(1); + } + listen(socket_fd, 5); + + while (true) { + + unsigned int cli_len = sizeof(cli_addr); + + int new_socket_fd = accept(socket_fd, (struct sockaddr*) &cli_addr, &cli_len); + + if (new_socket_fd < 0) { + perror("ERROR on accept"); + exit(1); + } + + std::thread thread(WorkWithClient, this, new_socket_fd, cli_addr); + } +} diff --git a/tcp/server/src/server.h b/tcp/server/src/server.h new file mode 100644 index 0000000..9950fa1 --- /dev/null +++ b/tcp/server/src/server.h @@ -0,0 +1,15 @@ +#ifndef SERVER_SERVER_H +#define SERVER_SERVER_H + +class RouletteServer { + public: + + static void WorkWithClient(RouletteServer* server, int sock_fd, const sockaddr_in& cli_addr); + + void StartServer(uint16_t port_number); + + private: + volatile int croupier = -1; +}; + +#endif //SERVER_SERVER_H From 5cf9cc28a1a1e9ebb5e3bb0622d24fcf01c9b481 Mon Sep 17 00:00:00 2001 From: oquechy Date: Tue, 5 Feb 2019 22:14:23 +0300 Subject: [PATCH 02/48] Update README.md --- README.md | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f1c324e..9df900b 100644 --- a/README.md +++ b/README.md @@ -1 +1,80 @@ -# Networks Lab 2019 (Higher School of Economics) +# Протокол игры "Рулетка" + +## Формат сообщений + + +--------------------+--------------------+-------------+ + | int message type | int body length | char[] body | + +--------------------+--------------------+-------------+ + +## Клиент + +- Запрос на добавление игрока + + type: 100 + body: "Name" + +- Запрос на вход крупье по паролю + + type: 200 + body: "Password" + +- Запрос на добавление ставки + + type: 300 + body: "N" | "even" | "odd" + +- Запрос на начало розыгрыша + + type: 400 + +## Сервер + +- Отчёт об успешной операции + + type: 0 + body: "Optional message" + +- Отчёт о получении сообщения от неавторизованного игрока или крупье + + type: 1 + body: "Optional message" + +- Отчёт о получении некорректного сообщения + + type: 2 + body: "Optional message" + +- Отчёт об отказе в добавлении игрока + + type: 101 + body: "Optional message, ex: name is taken" + +- Отчёт об ошибке ввода пароля крупье + + type: 201 + body: "Optional message, ex: wrong passord" + +- Отчёт об отказе входа крупье + + type: 202 + body: "Optional message, ex: croupier already authorised" + +- Отчёт о повторной ставке + + type: 301 + body: "Optional message, ex: you already made your bet" + +- Отчёт о несвоевременной ставке + + type: 302 + body: "Optional message, ex: game in progress" + +- Отчёт об отклонении начала розыгрыша + + type: 401 + body: "Optional message, ex: game in progress" + +- Оповещение о завершении розыгрыша + + type: 500 + body: "N GAIN" From 10f00bdf97d5603af07368d2cdab184dc60e5d41 Mon Sep 17 00:00:00 2001 From: oquechy Date: Thu, 7 Feb 2019 23:28:03 +0300 Subject: [PATCH 03/48] add message class --- tcp/message/CMakeLists.txt | 7 ++ tcp/message/src/message.cpp | 78 +++++++++++++ tcp/message/src/message.h | 104 ++++++++++++++++++ tcp_template/client_linux/CMakeLists.txt | 2 +- tcp_template/server_linux/CMakeLists.txt | 8 +- .../server_linux/{main.c => main.cpp} | 18 +-- 6 files changed, 205 insertions(+), 12 deletions(-) create mode 100644 tcp/message/CMakeLists.txt create mode 100644 tcp/message/src/message.cpp create mode 100644 tcp/message/src/message.h rename tcp_template/server_linux/{main.c => main.cpp} (79%) diff --git a/tcp/message/CMakeLists.txt b/tcp/message/CMakeLists.txt new file mode 100644 index 0000000..4b67908 --- /dev/null +++ b/tcp/message/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.13) +project(message) + +set(CMAKE_CXX_STANDARD 17) +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") + +add_executable(message src/message.h src/message.cpp) \ No newline at end of file diff --git a/tcp/message/src/message.cpp b/tcp/message/src/message.cpp new file mode 100644 index 0000000..6cc76d5 --- /dev/null +++ b/tcp/message/src/message.cpp @@ -0,0 +1,78 @@ +// +// Created by oquechy on 2/7/19. +// + +#include +#include "message.h" + +#include +#include + +#include +#include +#include + +#include + +int main(int argc, char *argv[]) { + int sockfd, n; + uint16_t portno; + sockaddr_in serv_addr{}; + hostent *server; + + char buffer[256]; + + if (argc < 3) { + fprintf(stderr, "usage %s hostname port\n", argv[0]); + exit(0); + } + + portno = (uint16_t) atoi(argv[2]); + + /* Create a socket point */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + + if (sockfd < 0) { + perror("ERROR opening socket"); + exit(1); + } + + server = gethostbyname(argv[1]); + + if (server == NULL) { + fprintf(stderr, "ERROR, no such host\n"); + exit(0); + } + + 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(portno); + + /* Now connect to the server */ + if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { + perror("ERROR connecting"); + exit(1); + } + + /* Send message to the server */ + bool b = Message(Message::SUCCESS, "Hello my little kitty").write(sockfd); + + if (!b) { + perror("ERROR writing to socket"); + exit(1); + } + + /* Now read server response */ + Message m = Message::read(sockfd); + + if (m.type == Message::UNDEFINED) { + perror("ERROR reading from socket"); + exit(1); + } + + + printf("Response: {type = %zu, length = %zu, message = %s}\n", m.type, m.body.size(), m.body.c_str()); + close(sockfd); + return 0; +} \ No newline at end of file diff --git a/tcp/message/src/message.h b/tcp/message/src/message.h new file mode 100644 index 0000000..f56343c --- /dev/null +++ b/tcp/message/src/message.h @@ -0,0 +1,104 @@ +#include + +// +// Created by oquechy on 2/7/19. +// + +#ifndef CLIENT_LINUX_MESSAGE_H +#define CLIENT_LINUX_MESSAGE_H + +#include +#include +#include +#include +#include +#include + +class Message { +public: + enum Type { + UNDEFINED = -1, + SUCCESS = 0, + }; + + Message(Type type, std::string message) : type(type), body(std::move(message)) {} + + bool write(int sockfd) { + size_t message_len = 2 * sizeof(uint32_t) + body.size(); + char *data = new char[message_len]; + put_int32(type, data); + put_int32(static_cast(body.size()), data + sizeof(uint32_t)); + put_body(data + 2 * sizeof(uint32_t)); + + for (ssize_t written = 0; message_len; written = ::write(sockfd, data, message_len)) { + if (written < 0) { + std::cerr << strerror(errno) << std::endl; + return false; + } else { + data += written; + message_len -= written; + } + } + + return true; + } + + static Message read(int sockfd) { + uint32_t type, length; + std::string data; + if (get_int32(&type, sockfd) && + get_int32(&length, sockfd) && + get_body(&data, length, sockfd)) { + return Message(Type(type), data); + } + return Message(); + } + + Type type; + std::string body; + +private: + Message() : type(UNDEFINED), body() {} + + static void put_int32(uint32_t i, char *buf) { + i = htonl(i); + memcpy(buf, &i, sizeof(uint32_t)); + } + + void put_body(char *buf) { + memcpy(buf, body.c_str(), body.size()); + } + + static bool get_int32(uint32_t *i, int sockfd) { + if (get(reinterpret_cast(i), sizeof(uint32_t), sockfd)) { + *i = ntohl(*i); + return true; + } + return false; + } + + static bool get_body(std::string *body, size_t length, int sockfd) { + char *buf = new char[length]; + if (get(buf, length, sockfd)) { + *body = std::string(buf); + return true; + } + return false; + } + + static bool get(char *dst, size_t message_len, int sockfd) { + for (ssize_t read = 0; message_len; read = ::read(sockfd, dst, message_len)) { + if (read < 0) { + std::cerr << strerror(errno) << std::endl; + return false; + } else { + dst += read; + message_len -= read; + } + } + return true; + } +}; + + +#endif //CLIENT_LINUX_MESSAGE_H diff --git a/tcp_template/client_linux/CMakeLists.txt b/tcp_template/client_linux/CMakeLists.txt index 311326d..c1a0803 100644 --- a/tcp_template/client_linux/CMakeLists.txt +++ b/tcp_template/client_linux/CMakeLists.txt @@ -3,5 +3,5 @@ project(client_linux) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") -set(SOURCE_FILES main.c) +set(SOURCE_FILES main.c ../../tcp/message/src/message.cpp ../../tcp/message/message.h) add_executable(client_linux ${SOURCE_FILES}) \ No newline at end of file diff --git a/tcp_template/server_linux/CMakeLists.txt b/tcp_template/server_linux/CMakeLists.txt index ac88ba4..b1dcbb8 100644 --- a/tcp_template/server_linux/CMakeLists.txt +++ b/tcp_template/server_linux/CMakeLists.txt @@ -1,7 +1,7 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.13) project(server_linux) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") +set(CMAKE_CXX_STANDARD 17) +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") -set(SOURCE_FILES main.c) -add_executable(server_linux ${SOURCE_FILES}) \ No newline at end of file +add_executable(server_linux main.cpp ../../tcp/message/src/message.h) \ No newline at end of file diff --git a/tcp_template/server_linux/main.c b/tcp_template/server_linux/main.cpp similarity index 79% rename from tcp_template/server_linux/main.c rename to tcp_template/server_linux/main.cpp index 30c7084..2d4c171 100644 --- a/tcp_template/server_linux/main.c +++ b/tcp_template/server_linux/main.cpp @@ -7,6 +7,8 @@ #include +#include "../../tcp/message/src/message.h" + int main(int argc, char *argv[]) { int sockfd, newsockfd; uint16_t portno; @@ -52,24 +54,26 @@ int main(int argc, char *argv[]) { exit(1); } - /* If connection is established then start communicating */ - bzero(buffer, 256); - n = read(newsockfd, buffer, 255); // recv on Windows - if (n < 0) { + Message m = Message::read(newsockfd); + + if (m.type == Message::UNDEFINED) { perror("ERROR reading from socket"); exit(1); } - printf("Here is the message: %s\n", buffer); + printf("Message: {type = %zu, length = %zu, message = %s}\n", static_cast(m.type), + m.body.size(), m.body.c_str()); /* Write a response to the client */ - n = write(newsockfd, "I got your message", 18); // send on Windows + bool b = Message(Message::SUCCESS, "I got your message").write(newsockfd); - if (n < 0) { + if (!b) { perror("ERROR writing to socket"); exit(1); } + close(sockfd); + close(newsockfd); return 0; } From a83eb6a8a7f255b929f008e6c6628e1276c0ee79 Mon Sep 17 00:00:00 2001 From: AndreySmirdin Date: Fri, 8 Feb 2019 13:43:17 +0300 Subject: [PATCH 04/48] Update README.md --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9df900b..ac5f17f 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,10 @@ - Запрос на начало розыгрыша type: 400 + +- Запрос на конец розыгрыша + + type: 500 ## Сервер @@ -73,8 +77,13 @@ type: 401 body: "Optional message, ex: game in progress" + + - Отчёт об отклонении конца розыгрыша + + type: 501 + body: "Optional message, ex: game is already fineshed" - Оповещение о завершении розыгрыша - type: 500 + type: 600 body: "N GAIN" From 145984bdfbb3edec34b2f6a901cb1be7020a7c92 Mon Sep 17 00:00:00 2001 From: AndreySmirdin Date: Fri, 8 Feb 2019 19:55:09 +0300 Subject: [PATCH 05/48] Update README.md --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index ac5f17f..2b95aaa 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,10 @@ - Запрос на конец розыгрыша type: 500 + +- Получить список всех ставок + + type 700 ## Сервер @@ -87,3 +91,8 @@ type: 600 body: "N GAIN" + +- Список ставок всех игроков + + type: 800 + body: "NAME1 BET1 NAME2 BET2 ..." From 5b64a9c6e3c68769270c40103cd43d91427da8a7 Mon Sep 17 00:00:00 2001 From: andrey Date: Fri, 8 Feb 2019 22:49:56 +0300 Subject: [PATCH 06/48] Server is pretty great now. --- tcp/message/src/message.cpp | 191 ++++++++++++++------- tcp/message/src/message.h | 115 +++++-------- tcp/server/CMakeLists.txt | 5 +- tcp/server/src/client_abstraction.cpp | 4 - tcp/server/src/client_abstraction.h | 16 -- tcp/server/src/main.cpp | 4 +- tcp/server/src/server.cpp | 205 ++++++++++++++++++++++- tcp/server/src/server.h | 54 +++++- tcp_template/server_linux/CMakeLists.txt | 2 +- tcp_template/server_linux/main.cpp | 6 +- 10 files changed, 432 insertions(+), 170 deletions(-) delete mode 100644 tcp/server/src/client_abstraction.cpp delete mode 100644 tcp/server/src/client_abstraction.h diff --git a/tcp/message/src/message.cpp b/tcp/message/src/message.cpp index 6cc76d5..6e8c711 100644 --- a/tcp/message/src/message.cpp +++ b/tcp/message/src/message.cpp @@ -1,7 +1,3 @@ -// -// Created by oquechy on 2/7/19. -// - #include #include "message.h" @@ -14,65 +10,144 @@ #include -int main(int argc, char *argv[]) { - int sockfd, n; - uint16_t portno; - sockaddr_in serv_addr{}; - hostent *server; - - char buffer[256]; - - if (argc < 3) { - fprintf(stderr, "usage %s hostname port\n", argv[0]); - exit(0); - } - - portno = (uint16_t) atoi(argv[2]); - - /* Create a socket point */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd < 0) { - perror("ERROR opening socket"); - exit(1); +//int main(int argc, char* argv[]) { +// int sockfd, n; +// uint16_t portno; +// sockaddr_in serv_addr{}; +// hostent* server; +// +// char buffer[256]; +// +// if (argc < 3) { +// fprintf(stderr, "usage %s hostname port\n", argv[0]); +// exit(0); +// } +// +// portno = (uint16_t) atoi(argv[2]); +// +// /* Create a socket point */ +// sockfd = socket(AF_INET, SOCK_STREAM, 0); +// +// if (sockfd < 0) { +// perror("ERROR opening socket"); +// exit(1); +// } +// +// server = gethostbyname(argv[1]); +// +// if (server == NULL) { +// fprintf(stderr, "ERROR, no such host\n"); +// exit(0); +// } +// +// 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(portno); +// +// /* Now connect to the server */ +// if (connect(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) { +// perror("ERROR connecting"); +// exit(1); +// } +// while (true) { +// int type; +// std::string text; +// std::cin >> type; +// std::cin >> text; +// +// /* Send message to the server */ +// bool b = Message((Message::Type) type, text).Write(sockfd); +// +// if (!b) { +// perror("ERROR writing to socket"); +// exit(1); +// } +// +// /* Now Read server response */ +// Message m = Message::Read(sockfd); +// +// if (m.type == Message::UNDEFINED) { +// perror("ERROR reading from socket"); +// exit(1); +// } +// +// +// printf("Response: {type = %zu, length = %zu, message = %s}\n", m.type, m.body.size(), +// m.body.c_str()); +// +// } +// close(sockfd); +// return 0; +//} + +bool Message::Write(int sockfd) { + size_t message_len = 2 * sizeof(uint32_t) + body.size(); + char* data = new char[message_len]; + PutInt32(type, data); + PutInt32(static_cast(body.size()), data + sizeof(uint32_t)); + PutBody(data + 2 * sizeof(uint32_t)); + + for (ssize_t written = 0; message_len; written = ::write(sockfd, data, message_len)) { + if (written < 0) { + std::cerr << strerror(errno) << std::endl; + return false; + } else { + data += written; + message_len -= written; + } } - server = gethostbyname(argv[1]); + return true; +} - if (server == NULL) { - fprintf(stderr, "ERROR, no such host\n"); - exit(0); +Message Message::Read(int sockfd) { + uint32_t type, length; + std::string data; + if (GetInt32(&type, sockfd) && + GetInt32(&length, sockfd) && + GetBody(&data, length, sockfd)) { + return Message(Type(type), data); } - - 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(portno); - - /* Now connect to the server */ - if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { - perror("ERROR connecting"); - exit(1); + return Message(); +} + +void Message::PutInt32(uint32_t i, char* buf) { + i = htonl(i); + memcpy(buf, &i, sizeof(uint32_t)); +} + +void Message::PutBody(char* buf) { + memcpy(buf, body.c_str(), body.size()); +} + +bool Message::GetInt32(uint32_t* i, int sockfd) { + if (Get(reinterpret_cast(i), sizeof(uint32_t), sockfd)) { + *i = ntohl(*i); + return true; } - - /* Send message to the server */ - bool b = Message(Message::SUCCESS, "Hello my little kitty").write(sockfd); - - if (!b) { - perror("ERROR writing to socket"); - exit(1); + return false; +} + +bool Message::GetBody(std::string* body, size_t length, int sockfd) { + char* buf = new char[length]; + if (Get(buf, length, sockfd)) { + *body = std::string(buf); + return true; } - - /* Now read server response */ - Message m = Message::read(sockfd); - - if (m.type == Message::UNDEFINED) { - perror("ERROR reading from socket"); - exit(1); + return false; +} + +bool Message::Get(char* dst, size_t message_len, int sockfd) { + for (ssize_t read = 0; message_len; read = ::read(sockfd, dst, message_len)) { + if (read < 0) { + std::cerr << strerror(errno) << std::endl; + return false; + } else { + dst += read; + message_len -= read; + } } - - - printf("Response: {type = %zu, length = %zu, message = %s}\n", m.type, m.body.size(), m.body.c_str()); - close(sockfd); - return 0; -} \ No newline at end of file + return true; +} diff --git a/tcp/message/src/message.h b/tcp/message/src/message.h index f56343c..7efb04d 100644 --- a/tcp/message/src/message.h +++ b/tcp/message/src/message.h @@ -1,9 +1,5 @@ #include -// -// Created by oquechy on 2/7/19. -// - #ifndef CLIENT_LINUX_MESSAGE_H #define CLIENT_LINUX_MESSAGE_H @@ -12,92 +8,57 @@ #include #include #include -#include + + class Message { -public: + public: enum Type { UNDEFINED = -1, SUCCESS = 0, + UNAUTHORIZED = 1, + INCORRECT_MESSAGE = 2, + NEW_PLAYER = 100, + CANT_ADD_PLAYER = 101, + NEW_CROUPIER = 200, + CANT_ADD_CROUPIER = 201, + CROUPIER_ALREADY_EXISTS = 202, + NEW_BET = 300, + REPEATED_BET = 301, + UNTIMELY_BET = 302, + START_DRAW = 400, + CANT_START_DRAW = 401, + END_DRAW = 500, + CANT_END_DWAW = 501, + DRAW_RESULTS = 600, + GET_ALL_BETS = 700, + LIST_OF_BETS = 800 }; + Message() : type(UNDEFINED), body() {} // I dont like -1 because we cast to uint then. + + explicit Message(Type type) : type(type), body() {} + Message(Type type, std::string message) : type(type), body(std::move(message)) {} - bool write(int sockfd) { - size_t message_len = 2 * sizeof(uint32_t) + body.size(); - char *data = new char[message_len]; - put_int32(type, data); - put_int32(static_cast(body.size()), data + sizeof(uint32_t)); - put_body(data + 2 * sizeof(uint32_t)); - - for (ssize_t written = 0; message_len; written = ::write(sockfd, data, message_len)) { - if (written < 0) { - std::cerr << strerror(errno) << std::endl; - return false; - } else { - data += written; - message_len -= written; - } - } - - return true; - } - - static Message read(int sockfd) { - uint32_t type, length; - std::string data; - if (get_int32(&type, sockfd) && - get_int32(&length, sockfd) && - get_body(&data, length, sockfd)) { - return Message(Type(type), data); - } - return Message(); - } + bool Write(int sockfd); + + static Message Read(int sockfd); Type type; std::string body; -private: - Message() : type(UNDEFINED), body() {} - - static void put_int32(uint32_t i, char *buf) { - i = htonl(i); - memcpy(buf, &i, sizeof(uint32_t)); - } - - void put_body(char *buf) { - memcpy(buf, body.c_str(), body.size()); - } - - static bool get_int32(uint32_t *i, int sockfd) { - if (get(reinterpret_cast(i), sizeof(uint32_t), sockfd)) { - *i = ntohl(*i); - return true; - } - return false; - } - - static bool get_body(std::string *body, size_t length, int sockfd) { - char *buf = new char[length]; - if (get(buf, length, sockfd)) { - *body = std::string(buf); - return true; - } - return false; - } - - static bool get(char *dst, size_t message_len, int sockfd) { - for (ssize_t read = 0; message_len; read = ::read(sockfd, dst, message_len)) { - if (read < 0) { - std::cerr << strerror(errno) << std::endl; - return false; - } else { - dst += read; - message_len -= read; - } - } - return true; - } + private: + + static void PutInt32(uint32_t i, char* buf); + + void PutBody(char* buf); + + static bool GetInt32(uint32_t* i, int sockfd); + + static bool GetBody(std::string* body, size_t length, int sockfd); + + static bool Get(char* dst, size_t message_len, int sockfd); }; diff --git a/tcp/server/CMakeLists.txt b/tcp/server/CMakeLists.txt index b22f7e6..1013898 100644 --- a/tcp/server/CMakeLists.txt +++ b/tcp/server/CMakeLists.txt @@ -4,4 +4,7 @@ project(server) set(CMAKE_CXX_STANDARD 17) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") -add_executable(server src/main.cpp src/server.cpp src/server.h src/client_abstraction.cpp src/client_abstraction.h) \ No newline at end of file +add_executable(server + src/main.cpp + src/server.cpp src/server.h + ../message/src/message.cpp ../message/src/message.h) \ No newline at end of file diff --git a/tcp/server/src/client_abstraction.cpp b/tcp/server/src/client_abstraction.cpp deleted file mode 100644 index 2606593..0000000 --- a/tcp/server/src/client_abstraction.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// -// Created by andrey on 28.01.19. -// - diff --git a/tcp/server/src/client_abstraction.h b/tcp/server/src/client_abstraction.h deleted file mode 100644 index e8aa7dc..0000000 --- a/tcp/server/src/client_abstraction.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SERVER_CLIENT_ABSTRACTION_H -#define SERVER_CLIENT_ABSTRACTION_H - - -#include -#include - -class ClientAbstraction { - private: - const std::string name; - const sockaddr_in addr; - const int socket_fd; -}; - - -#endif //SERVER_CLIENT_ABSTRACTION_H diff --git a/tcp/server/src/main.cpp b/tcp/server/src/main.cpp index 5af6351..c7f33ae 100644 --- a/tcp/server/src/main.cpp +++ b/tcp/server/src/main.cpp @@ -1,7 +1,7 @@ #include -#include "server.cpp" +#include "server.h" -int main(int argc, char** argv) { +int main(int argc, char* argv[]) { if (argc != 2) { std::cout << "Usage: ./roulette_server "; return 0; diff --git a/tcp/server/src/server.cpp b/tcp/server/src/server.cpp index d7ccb1e..a1e2808 100644 --- a/tcp/server/src/server.cpp +++ b/tcp/server/src/server.cpp @@ -1,17 +1,55 @@ -#include #include #include #include #include #include + #include "server.h" -void -RouletteServer::WorkWithClient(RouletteServer* server, int sock_fd, const sockaddr_in& cli_addr) { +void RouletteServer::AuthoriseClient(int sock_fd) { + std::function workWithClient = nullptr; + while (true) { + Message message = Message::Read(sock_fd); + Message::Type ans_type; + if (Message::NEW_PLAYER == message.type) { + players_mutex_.lock(); + if (players.count(message.body) == 0) { + auto* player = new Player(sock_fd); + players[message.body] = player; + workWithClient = std::bind(&RouletteServer::WorkWithPlayer, this, *player); + ans_type = Message::SUCCESS; + } else { + ans_type = Message::CANT_ADD_PLAYER; + } + players_mutex_.unlock(); + } else if (Message::NEW_CROUPIER == message.type) { + croupier_mutex_.lock(); + if (have_croupier_) { + ans_type = Message::CROUPIER_ALREADY_EXISTS; + } else if (message.body == CROUPIER_PASSWORD) { + have_croupier_ = true; + workWithClient = std::bind(&RouletteServer::WorkWithCroupier, this, sock_fd); + ans_type = Message::SUCCESS; + } else { + ans_type = Message::CANT_ADD_CROUPIER; + } + croupier_mutex_.unlock(); + } else { + ans_type = Message::UNAUTHORIZED; + } + + Message ans_message(ans_type); + ans_message.Write(sock_fd); + if (workWithClient != nullptr) { + break; + } + } + workWithClient(); } + void RouletteServer::StartServer(uint16_t port_number) { int socket_fd = socket(AF_INET, SOCK_STREAM, 0); @@ -43,6 +81,165 @@ void RouletteServer::StartServer(uint16_t port_number) { exit(1); } - std::thread thread(WorkWithClient, this, new_socket_fd, cli_addr); + std::thread thread(&RouletteServer::AuthoriseClient, this, new_socket_fd); + thread.detach(); + } +} + +void RouletteServer::WorkWithCroupier(int sock_fd) { + while (true) { + Message message = Message::Read(sock_fd); + Message ans_message; + switch (message.type) { + case Message::START_DRAW: { + ans_message = ProcessStartDraw(); + break; + } + case Message::END_DRAW: { + ans_message = ProcessEndDraw(); + break; + } + case Message::GET_ALL_BETS: { + ans_message = ProcessGetAllBets(); + break; + } + + default: { + ans_message = Message(Message::INCORRECT_MESSAGE); + } + + } + ans_message.Write(sock_fd); + } +} + +void RouletteServer::WorkWithPlayer(Player& player) { + while (true) { + Message message = Message::Read(player.socket_fd); + Message ans_message; + switch (message.type) { + case Message::NEW_BET: { + if (!rolling_mutex_.try_lock_shared()) { + ans_message = Message(Message::UNTIMELY_BET); + break; + } + + // Otherwise game wasn't started. + ans_message = ProcessBet(player, message.body); + rolling_mutex_.unlock_shared(); + break; + } + case Message::GET_ALL_BETS: { + ans_message = ProcessGetAllBets(); + break; + } + + default: { + ans_message = Message(Message::INCORRECT_MESSAGE); + } + } + ans_message.Write(player.socket_fd); + } +} + +Message RouletteServer::ProcessStartDraw() { + if (!is_rolling_) { + rolling_mutex_.lock(); + is_rolling_ = true; + return Message(Message::SUCCESS); + } + return Message(Message::CANT_START_DRAW, "Game is already in progress."); + +} + +Message RouletteServer::ProcessEndDraw() { + if (is_rolling_) { + players_mutex_.lock(); + for (auto& player: players) { + int winning_number = rand() % AMOUNT_OF_NUMBERS; + int profit = player.second->CalculateProfit(winning_number); + Message msg(Message::DRAW_RESULTS, + std::to_string(winning_number) + " " + std::to_string(profit)); + player.second->bet = 0; + player.second->bet_type = Player::NO_BET; + msg.Write(player.second->socket_fd); + } + players_mutex_.unlock(); + rolling_mutex_.unlock(); + is_rolling_ = false; + return Message(Message::SUCCESS); + } + return Message(Message::CANT_END_DWAW, "Game wasnt in progress."); +} + +Message RouletteServer::ProcessGetAllBets() { + players_mutex_.lock(); + std::string result; + for (auto& p: players) { + result += p.first; + result += std::to_string(p.second->bet); } + players_mutex_.unlock(); + return Message(Message::LIST_OF_BETS, result); +} + +Message RouletteServer::ProcessBet(RouletteServer::Player& player, std::string bet) { + std::string bet_type_str; + Player::BetType bet_type; + int betting_number = -1; + size_t delimeter_pos = bet.find(' '); + bet_type_str = bet.substr(0, delimeter_pos); + if (bet_type_str == "even") { + bet_type = Player::EVEN; + } else if (bet_type_str == "odd") { + bet_type = Player::ODD; + } else { + try { + betting_number = std::stoi(bet_type_str); + } catch (...) { + return Message(Message::INCORRECT_MESSAGE, "Incorrect bet type " + bet_type_str); + } + if (betting_number >= 0 && betting_number < AMOUNT_OF_NUMBERS) { + bet_type = Player::NUMBER; + } else { + return Message(Message::INCORRECT_MESSAGE, "Incorrect bet type " + bet_type_str); + } + } + + int bet_sum = 0; + try { + bet_sum = std::stoi(bet.substr(delimeter_pos, bet.size() - delimeter_pos)); + } catch (...) { + return Message(Message::INCORRECT_MESSAGE, + "Incorrect bet sum " + + bet.substr(delimeter_pos, bet.size() - delimeter_pos)); + } + + players_mutex_.lock(); + Message::Type result; + if (player.bet != 0) { + result = Message::REPEATED_BET; + } else { + player.bet = bet_sum; + player.bet_type = bet_type; + player.number = betting_number; + result = Message::SUCCESS; + } + players_mutex_.unlock(); + return Message(result); +} + +RouletteServer::~RouletteServer() { + for (auto& p: players) { + delete p.second; + } +} + +int RouletteServer::Player::CalculateProfit(int winning_number) { + if ((winning_number % 2 == 0 && bet_type == EVEN) || + (winning_number % 2 == 1 && bet_type == ODD)) + return 2 * bet; + if (winning_number == number && bet_type == NUMBER) + return 35 * bet; + return 0; } diff --git a/tcp/server/src/server.h b/tcp/server/src/server.h index 9950fa1..c226a05 100644 --- a/tcp/server/src/server.h +++ b/tcp/server/src/server.h @@ -1,15 +1,61 @@ #ifndef SERVER_SERVER_H #define SERVER_SERVER_H +#include +#include +#include +#include +#include "../../message/src/message.h" + class RouletteServer { public: - - static void WorkWithClient(RouletteServer* server, int sock_fd, const sockaddr_in& cli_addr); - void StartServer(uint16_t port_number); + ~RouletteServer(); private: - volatile int croupier = -1; + struct Player { + explicit Player(int socket_fd) : socket_fd(socket_fd) {}; + const int socket_fd; + + int bet = 0; + enum BetType { + NO_BET, + EVEN, + ODD, + NUMBER + }; + BetType bet_type = NO_BET; + int number = -1; + + int CalculateProfit(int winning_number); + }; + + const char* CROUPIER_PASSWORD = "ANDREY_THE_BEST"; + const int AMOUNT_OF_NUMBERS = 37; + bool have_croupier_ = false; + bool is_rolling_ = false; + + std::map players; + + std::mutex players_mutex_; + std::mutex croupier_mutex_; + + std::shared_timed_mutex rolling_mutex_; + + Message ProcessStartDraw(); + + Message ProcessEndDraw(); + + void AuthoriseClient(int sock_fd); + + void WorkWithCroupier(int sock_fd); + + void WorkWithPlayer(Player& player); + + Message ProcessGetAllBets(); + + Message ProcessBet(Player& player, std::string bet); + }; #endif //SERVER_SERVER_H diff --git a/tcp_template/server_linux/CMakeLists.txt b/tcp_template/server_linux/CMakeLists.txt index b1dcbb8..ef0fc75 100644 --- a/tcp_template/server_linux/CMakeLists.txt +++ b/tcp_template/server_linux/CMakeLists.txt @@ -4,4 +4,4 @@ project(server_linux) set(CMAKE_CXX_STANDARD 17) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") -add_executable(server_linux main.cpp ../../tcp/message/src/message.h) \ No newline at end of file +add_executable(server_linux main.cpp ../../tcp/message/src/message.h ../../tcp/message/src/message.cpp) diff --git a/tcp_template/server_linux/main.cpp b/tcp_template/server_linux/main.cpp index 2d4c171..ef7c6f7 100644 --- a/tcp_template/server_linux/main.cpp +++ b/tcp_template/server_linux/main.cpp @@ -27,7 +27,7 @@ int main(int argc, char *argv[]) { /* Initialize socket structure */ bzero((char *) &serv_addr, sizeof(serv_addr)); - portno = 5001; + portno = 10239; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; @@ -55,7 +55,7 @@ int main(int argc, char *argv[]) { } - Message m = Message::read(newsockfd); + Message m = Message::Read(newsockfd); if (m.type == Message::UNDEFINED) { perror("ERROR reading from socket"); @@ -66,7 +66,7 @@ int main(int argc, char *argv[]) { m.body.size(), m.body.c_str()); /* Write a response to the client */ - bool b = Message(Message::SUCCESS, "I got your message").write(newsockfd); + bool b = Message(Message::SUCCESS, "I got your message").Write(newsockfd); if (!b) { perror("ERROR writing to socket"); From 06ad62513162381f69ca63a6cf587f55abe0bf1c Mon Sep 17 00:00:00 2001 From: andrey Date: Fri, 8 Feb 2019 23:05:08 +0300 Subject: [PATCH 07/48] Closing listening socket. --- tcp/server/src/main.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tcp/server/src/main.cpp b/tcp/server/src/main.cpp index c7f33ae..b3f8c67 100644 --- a/tcp/server/src/main.cpp +++ b/tcp/server/src/main.cpp @@ -1,4 +1,5 @@ #include +#include #include "server.h" int main(int argc, char* argv[]) { @@ -10,7 +11,14 @@ int main(int argc, char* argv[]) { uint16_t port_number = static_cast(std::stoi(argv[1])); RouletteServer server; - server.StartServer(port_number); + std::thread server_thread(&RouletteServer::StartServer, &server, port_number); + server_thread.detach(); + + std::string in; + while (in != "exit") { + std::cin >> in; + } + close(port_number); return 0; } \ No newline at end of file From a6b5e0dd095269ef5345a484ce9b5590218bd7e3 Mon Sep 17 00:00:00 2001 From: oquechy Date: Sun, 10 Feb 2019 13:33:59 +0300 Subject: [PATCH 08/48] remove success type and build with cmake --- tcp/CMakeLists.txt | 9 ++++ tcp/client/.gitkeep | 0 tcp/client/CMakeLists.txt | 10 +++++ tcp/message/CMakeLists.txt | 9 +--- tcp/message/src/message.cpp | 88 +++++-------------------------------- tcp/message/src/message.h | 36 ++++++++------- tcp/server/CMakeLists.txt | 6 +-- 7 files changed, 54 insertions(+), 104 deletions(-) create mode 100644 tcp/CMakeLists.txt delete mode 100644 tcp/client/.gitkeep create mode 100644 tcp/client/CMakeLists.txt diff --git a/tcp/CMakeLists.txt b/tcp/CMakeLists.txt new file mode 100644 index 0000000..5889844 --- /dev/null +++ b/tcp/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.13) +project(roulette) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") + +add_subdirectory (client) +add_subdirectory (message) +add_subdirectory (server) \ No newline at end of file diff --git a/tcp/client/.gitkeep b/tcp/client/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/tcp/client/CMakeLists.txt b/tcp/client/CMakeLists.txt new file mode 100644 index 0000000..1d7bce1 --- /dev/null +++ b/tcp/client/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.13) +project(client) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -lboost_system -lboost_date_time -lboost_thread") + +find_package(Boost REQUIRED COMPONENTS thread) + +add_executable(client src/main.cpp src/client.cpp src/client.h) +target_link_libraries (client LINK_PUBLIC message ${Boost_LIBRARIES}) \ No newline at end of file diff --git a/tcp/message/CMakeLists.txt b/tcp/message/CMakeLists.txt index 4b67908..7da9c8c 100644 --- a/tcp/message/CMakeLists.txt +++ b/tcp/message/CMakeLists.txt @@ -1,7 +1,2 @@ -cmake_minimum_required(VERSION 3.13) -project(message) - -set(CMAKE_CXX_STANDARD 17) -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") - -add_executable(message src/message.h src/message.cpp) \ No newline at end of file +add_library (message src/message.cpp src/message.h) +target_include_directories (message PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src) diff --git a/tcp/message/src/message.cpp b/tcp/message/src/message.cpp index 6e8c711..a96bbb9 100644 --- a/tcp/message/src/message.cpp +++ b/tcp/message/src/message.cpp @@ -1,90 +1,24 @@ #include #include "message.h" -#include -#include +#include +#include #include #include #include -#include +#include +Message::Message() : type(UNDEFINED), body() {} -//int main(int argc, char* argv[]) { -// int sockfd, n; -// uint16_t portno; -// sockaddr_in serv_addr{}; -// hostent* server; -// -// char buffer[256]; -// -// if (argc < 3) { -// fprintf(stderr, "usage %s hostname port\n", argv[0]); -// exit(0); -// } -// -// portno = (uint16_t) atoi(argv[2]); -// -// /* Create a socket point */ -// sockfd = socket(AF_INET, SOCK_STREAM, 0); -// -// if (sockfd < 0) { -// perror("ERROR opening socket"); -// exit(1); -// } -// -// server = gethostbyname(argv[1]); -// -// if (server == NULL) { -// fprintf(stderr, "ERROR, no such host\n"); -// exit(0); -// } -// -// 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(portno); -// -// /* Now connect to the server */ -// if (connect(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) { -// perror("ERROR connecting"); -// exit(1); -// } -// while (true) { -// int type; -// std::string text; -// std::cin >> type; -// std::cin >> text; -// -// /* Send message to the server */ -// bool b = Message((Message::Type) type, text).Write(sockfd); -// -// if (!b) { -// perror("ERROR writing to socket"); -// exit(1); -// } -// -// /* Now Read server response */ -// Message m = Message::Read(sockfd); -// -// if (m.type == Message::UNDEFINED) { -// perror("ERROR reading from socket"); -// exit(1); -// } -// -// -// printf("Response: {type = %zu, length = %zu, message = %s}\n", m.type, m.body.size(), -// m.body.c_str()); -// -// } -// close(sockfd); -// return 0; -//} +Message::Message(Message::Type type) : type(type), body() {} + +Message::Message(Message::Type type, std::string message) : type(type), body(std::move(message)) {} bool Message::Write(int sockfd) { size_t message_len = 2 * sizeof(uint32_t) + body.size(); - char* data = new char[message_len]; + auto data = new char[message_len]; PutInt32(type, data); PutInt32(static_cast(body.size()), data + sizeof(uint32_t)); PutBody(data + 2 * sizeof(uint32_t)); @@ -107,7 +41,7 @@ Message Message::Read(int sockfd) { std::string data; if (GetInt32(&type, sockfd) && GetInt32(&length, sockfd) && - GetBody(&data, length, sockfd)) { + (!length || GetBody(&data, length, sockfd))) { return Message(Type(type), data); } return Message(); @@ -131,12 +65,12 @@ bool Message::GetInt32(uint32_t* i, int sockfd) { } bool Message::GetBody(std::string* body, size_t length, int sockfd) { - char* buf = new char[length]; + auto buf = new char[length]; if (Get(buf, length, sockfd)) { *body = std::string(buf); return true; } - return false; + return length != 0; } bool Message::Get(char* dst, size_t message_len, int sockfd) { diff --git a/tcp/message/src/message.h b/tcp/message/src/message.h index 7efb04d..c3dc96f 100644 --- a/tcp/message/src/message.h +++ b/tcp/message/src/message.h @@ -14,40 +14,44 @@ class Message { public: enum Type { - UNDEFINED = -1, - SUCCESS = 0, + UNDEFINED = 0, UNAUTHORIZED = 1, INCORRECT_MESSAGE = 2, NEW_PLAYER = 100, - CANT_ADD_PLAYER = 101, + PLAYER_ADDED = 101, + CANT_ADD_PLAYER = 102, NEW_CROUPIER = 200, - CANT_ADD_CROUPIER = 201, - CROUPIER_ALREADY_EXISTS = 202, + CROUPIER_ADDED = 201, + CANT_ADD_CROUPIER = 202, + CROUPIER_ALREADY_EXISTS = 203, NEW_BET = 300, - REPEATED_BET = 301, - UNTIMELY_BET = 302, + BET_ACCEPTED = 301, + REPEATED_BET = 302, + UNTIMELY_BET = 303, START_DRAW = 400, - CANT_START_DRAW = 401, + DRAW_STARTED = 401, + CANT_START_DRAW = 402, END_DRAW = 500, - CANT_END_DWAW = 501, + DRAW_ENDED = 501, + CANT_END_DRAW = 502, DRAW_RESULTS = 600, GET_ALL_BETS = 700, - LIST_OF_BETS = 800 + LIST_OF_BETS = 701 }; - Message() : type(UNDEFINED), body() {} // I dont like -1 because we cast to uint then. + Type type; + std::string body; + + Message(); - explicit Message(Type type) : type(type), body() {} + explicit Message(Type type); - Message(Type type, std::string message) : type(type), body(std::move(message)) {} + Message(Type type, std::string message); bool Write(int sockfd); static Message Read(int sockfd); - Type type; - std::string body; - private: static void PutInt32(uint32_t i, char* buf); diff --git a/tcp/server/CMakeLists.txt b/tcp/server/CMakeLists.txt index 1013898..d8313f8 100644 --- a/tcp/server/CMakeLists.txt +++ b/tcp/server/CMakeLists.txt @@ -4,7 +4,5 @@ project(server) set(CMAKE_CXX_STANDARD 17) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") -add_executable(server - src/main.cpp - src/server.cpp src/server.h - ../message/src/message.cpp ../message/src/message.h) \ No newline at end of file +add_executable(server src/main.cpp src/server.cpp src/server.h) +target_link_libraries (server LINK_PUBLIC message) \ No newline at end of file From cfbc44fa2248748131520ed15fbd348802e132de Mon Sep 17 00:00:00 2001 From: oquechy Date: Sun, 10 Feb 2019 16:49:18 +0300 Subject: [PATCH 09/48] client --- tcp/client/src/client.cpp | 249 ++++++++++++++++++++++++++++++++++++ tcp/client/src/client.h | 66 ++++++++++ tcp/client/src/main.cpp | 60 +++++++++ tcp/message/src/message.cpp | 12 +- 4 files changed, 381 insertions(+), 6 deletions(-) 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/src/client.cpp b/tcp/client/src/client.cpp new file mode 100644 index 0000000..04a0fe2 --- /dev/null +++ b/tcp/client/src/client.cpp @@ -0,0 +1,249 @@ +#include +#include +#include +#include "client.h" + +bool RouletteClient::StartClient(const char *host, uint16_t port_number) { + + sockfd_ = socket(AF_INET, SOCK_STREAM, 0); + + if (sockfd_ < 0) { + std::cerr << "failed to open socket\n"; + exit(1); + } + + hostent *server = gethostbyname(host); + + if (server == nullptr) { + std::cerr << "host not found\n"; + exit(0); + } + + sockaddr_in serv_addr{0}; + serv_addr.sin_family = AF_INET; + bcopy(server->h_addr, static_cast(&serv_addr.sin_addr.s_addr), static_cast(server->h_length)); + serv_addr.sin_port = htons(port_number); + + if (connect(sockfd_, reinterpret_cast(&serv_addr), sizeof(serv_addr)) < 0) { + std::cerr << "connection failed\n"; + exit(1); + } + + PrintHeader("AUTHORISATION"); + + request_sender_ = std::thread([this]() { + while (!requests_.closed()) { + try { + Message m = requests_.pull(); + m.Write(sockfd_); + } catch (boost::sync_queue_is_closed &) { + break; + } + } + }); + + response_receiver_ = std::thread([this]() { + while (!responses_.closed()) { + try { + Message m = Message::Read(sockfd_); + if (m.type == Message::DRAW_RESULTS) { + int number, win; + std::sscanf(m.body.c_str(), "%d %d", &number, &win); + PrintHeader("DRAW ENDED\nWINNING NUMBER " + std::to_string(number) + + "\nYOUR PROFIT " + std::to_string(win)); + } else { + responses_.push(m); + } + } catch (boost::sync_queue_is_closed &) { + break; + } + } + }); + + return true; +} + +void RouletteClient::AuthorisePlayer(const std::string &name) { + Message request{Message::NEW_PLAYER, name}; + requests_.push(request); + for (Message response = responses_.pull();; response = responses_.pull()) { + switch (response.type) { + case Message::PLAYER_ADDED: + Cout("enjoy the game, " + name); + return; + case Message::CANT_ADD_PLAYER: + Cout(response.body.empty() ? "sorry, this name is taken" : response.body); + return; + case Message::DRAW_RESULTS: + continue; + default: + HandleResponse(response); + return; + } + } +} + +void RouletteClient::AuthoriseCroupier(const std::string &key) { + Message request{Message::NEW_CROUPIER, key}; + requests_.push(request); + for (Message response = responses_.pull();; response = responses_.pull()) { + switch (response.type) { + case Message::CROUPIER_ADDED: + Cout("welcome ruler"); + return; + case Message::CANT_ADD_CROUPIER: + Cout(response.body.empty() ? "wrong password" : response.body); + return; + case Message::CROUPIER_ALREADY_EXISTS: + Cout(response.body.empty() ? "there can't be two masters" : response.body); + return; + case Message::DRAW_RESULTS: + continue; + default: + HandleResponse(response); + return; + } + } +} + +void RouletteClient::StartDraw() { + Message request{Message::START_DRAW}; + requests_.push(request); + for (Message response = responses_.pull();; response = responses_.pull()) { + switch (response.type) { + case Message::DRAW_STARTED: + Cout("whirrr!"); + return; + case Message::CANT_START_DRAW: + Cout(response.body.empty() ? "draw declined" : response.body); + return; + case Message::DRAW_RESULTS: + PrintResults(response); + continue; + default: + HandleResponse(response); + return; + } + } +} + +void RouletteClient::FinishDraw() { + Message request{Message::END_DRAW}; + requests_.push(request); + for (Message response = responses_.pull();; response = responses_.pull()) { + switch (response.type) { + case Message::DRAW_ENDED: + Cout("draw ended"); + return; + case Message::CANT_END_DRAW: + Cout(response.body.empty() ? "can't finish" : response.body); + return; + case Message::DRAW_RESULTS: + PrintResults(response); + continue; + default: + HandleResponse(response); + return; + } + } +} + +void RouletteClient::NewBet(const std::string &type, int sum) { + Message request{Message::NEW_BET, type + " " + std::to_string(sum)}; + requests_.push(request); + for (Message response = responses_.pull();; response = responses_.pull()) { + switch (response.type) { + case Message::BET_ACCEPTED: + Cout("good luck!"); + return; + case Message::REPEATED_BET: + Cout(response.body.empty() ? "you already made a bet" : response.body); + return; + case Message::DRAW_RESULTS: + PrintResults(response); + continue; + default: + HandleResponse(response); + return; + } + } +} + +void RouletteClient::ListBets() { + Message request{Message::GET_ALL_BETS}; + requests_.push(request); + for (Message response = responses_.pull();; response = responses_.pull()) { + switch (response.type) { + case Message::LIST_OF_BETS: + Cout(response.body); + return; + case Message::DRAW_RESULTS: + PrintResults(response); + continue; + default: + HandleResponse(response); + return; + } + } +} + +void RouletteClient::HandleUnexpectedServerResponse(const Message &response) { + Cout("server responded with {type: " + std::to_string(response.type) + ", message: " + response.body + "}"); +} + +void RouletteClient::PrintResults(const Message &response) { Cout(response.body); } + +void RouletteClient::HandleUnauthorised() { Cout("introduce yourself"); } + +void RouletteClient::HandleIncorrectMessage(const Message &response) { + Cout(response.body.empty() ? "unexpected request" : response.body); +} + +void RouletteClient::HandleResponse(const Message &response) { + switch (response.type) { + case Message::INCORRECT_MESSAGE: + HandleIncorrectMessage(response); + return; + case Message::UNAUTHORIZED: + HandleUnauthorised(); + return; + default: + HandleUnexpectedServerResponse(response); + return; + } +} + +void RouletteClient::Quit() { + Cout("closing connection..."); + requests_.close(); + responses_.close(); + request_sender_.join(); + response_receiver_.join(); + close(sockfd_); + Cout("bye!"); +} + +void RouletteClient::PrintHeader(const std::string &header) { + io_mutex_.lock(); + system("clear"); + std::cout << header << '\n' << "> "; + io_mutex_.unlock(); +} + +void RouletteClient::PrintPrompt() { + io_mutex_.lock(); + std::cout << "> "; + io_mutex_.unlock(); +} + +void RouletteClient::Cout(const std::string &message) { + io_mutex_.lock(); + std::cout << message << '\n'; + io_mutex_.unlock(); +} + +bool RouletteClient::GetLine(std::string &message) { + auto &result = getline(std::cin, message); + return bool(result); +} + diff --git a/tcp/client/src/client.h b/tcp/client/src/client.h new file mode 100644 index 0000000..a051ac5 --- /dev/null +++ b/tcp/client/src/client.h @@ -0,0 +1,66 @@ + +#ifndef ROULETTE_CLIENT_H +#define ROULETTE_CLIENT_H + + +#include +#include +#include +#include +#include +#include + +class RouletteClient { +public: + + bool StartClient(const char *host, uint16_t port_number); + +private: + + int sockfd_; + + boost::sync_queue requests_; + boost::sync_queue responses_; + + std::thread request_sender_; + std::thread response_receiver_; + + std::mutex io_mutex_; + +public: + void AuthorisePlayer(const std::string &name); + + void AuthoriseCroupier(const std::string &key); + + void StartDraw(); + + void FinishDraw(); + + void NewBet(const std::string &type, int sum); + + void HandleIncorrectMessage(const Message &response); + + void HandleUnauthorised(); + + void PrintResults(const Message &response); + + void HandleUnexpectedServerResponse(const Message &response); + + void HandleResponse(const Message &response); + + void ListBets(); + + void Quit(); + + void PrintHeader(const std::string &header); + + void PrintPrompt(); + + void Cout(const std::string &message); + + bool GetLine(std::string &message); + +}; + + +#endif //ROULETTE_CLIENT_H diff --git a/tcp/client/src/main.cpp b/tcp/client/src/main.cpp new file mode 100644 index 0000000..860df0a --- /dev/null +++ b/tcp/client/src/main.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include +#include "client.h" + +void usage(char *const *argv) { std::cerr << "Usage: " << argv[0] << " \n"; } + +void help() { std::cerr << "List of commands:\n" + "\ta player \n" + "\ta croupier \n" + "\tbet (odd|even|)\n" + "\tspin\n" + "\tlist\n" + "\tbye\n"; } + +int main(int argc, char *argv[]) { + if (argc < 3) { + usage(argv); + exit(0); + } + + auto port_number = static_cast(std::stoi(argv[2])); + + RouletteClient client{}; + + if (!client.StartClient(argv[1], port_number)) + exit(1); + + char arg[256]; + int number, sum; + for (std::string line; client.GetLine(line);) { + if (sscanf(line.c_str(), "a player %s", arg)) { + client.AuthorisePlayer(arg); + } else if (sscanf(line.c_str(), "a croupier %s", arg)) { + client.AuthoriseCroupier(arg); + } else if (line == "spin") { + client.StartDraw(); + } else if (line == "finish") { + client.FinishDraw(); + } else if (line == "list") { + client.ListBets(); + } else if (line == "bye") { + client.Quit(); + } else if (sscanf(line.c_str(), "bet %d odd", &sum) and sum > 0) { + client.NewBet("odd", sum); + } else if (sscanf(line.c_str(), "bet %d even", &sum) and sum > 0) { + client.NewBet("even", sum); + } else if (sscanf(line.c_str(), "bet %d %d", &sum, &number) == 2 and sum > 0) { + client.NewBet(std::to_string(number), sum); + } else { + help(); + } + client.PrintPrompt(); + } + + return 0; +} diff --git a/tcp/message/src/message.cpp b/tcp/message/src/message.cpp index a96bbb9..da754a3 100644 --- a/tcp/message/src/message.cpp +++ b/tcp/message/src/message.cpp @@ -47,24 +47,24 @@ Message Message::Read(int sockfd) { return Message(); } -void Message::PutInt32(uint32_t i, char* buf) { +void Message::PutInt32(uint32_t i, char *buf) { i = htonl(i); memcpy(buf, &i, sizeof(uint32_t)); } -void Message::PutBody(char* buf) { +void Message::PutBody(char *buf) { memcpy(buf, body.c_str(), body.size()); } -bool Message::GetInt32(uint32_t* i, int sockfd) { - if (Get(reinterpret_cast(i), sizeof(uint32_t), sockfd)) { +bool Message::GetInt32(uint32_t *i, int sockfd) { + if (Get(reinterpret_cast(i), sizeof(uint32_t), sockfd)) { *i = ntohl(*i); return true; } return false; } -bool Message::GetBody(std::string* body, size_t length, int sockfd) { +bool Message::GetBody(std::string *body, size_t length, int sockfd) { auto buf = new char[length]; if (Get(buf, length, sockfd)) { *body = std::string(buf); @@ -73,7 +73,7 @@ bool Message::GetBody(std::string* body, size_t length, int sockfd) { return length != 0; } -bool Message::Get(char* dst, size_t message_len, int sockfd) { +bool Message::Get(char *dst, size_t message_len, int sockfd) { for (ssize_t read = 0; message_len; read = ::read(sockfd, dst, message_len)) { if (read < 0) { std::cerr << strerror(errno) << std::endl; From 90ec30ce348fffa77187516fb547052e26a94c5f Mon Sep 17 00:00:00 2001 From: andrey Date: Sun, 10 Feb 2019 17:30:21 +0300 Subject: [PATCH 10/48] a bug with 0 bets --- tcp/server/src/server.cpp | 24 +++++++++++++----------- tcp/server/src/server.h | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/tcp/server/src/server.cpp b/tcp/server/src/server.cpp index a1e2808..e6afdab 100644 --- a/tcp/server/src/server.cpp +++ b/tcp/server/src/server.cpp @@ -17,8 +17,8 @@ void RouletteServer::AuthoriseClient(int sock_fd) { if (players.count(message.body) == 0) { auto* player = new Player(sock_fd); players[message.body] = player; - workWithClient = std::bind(&RouletteServer::WorkWithPlayer, this, *player); - ans_type = Message::SUCCESS; + workWithClient = std::bind(&RouletteServer::WorkWithPlayer, this, player); + ans_type = Message::PLAYER_ADDED; } else { ans_type = Message::CANT_ADD_PLAYER; } @@ -30,7 +30,7 @@ void RouletteServer::AuthoriseClient(int sock_fd) { } else if (message.body == CROUPIER_PASSWORD) { have_croupier_ = true; workWithClient = std::bind(&RouletteServer::WorkWithCroupier, this, sock_fd); - ans_type = Message::SUCCESS; + ans_type = Message::CROUPIER_ADDED; } else { ans_type = Message::CANT_ADD_CROUPIER; } @@ -113,9 +113,9 @@ void RouletteServer::WorkWithCroupier(int sock_fd) { } } -void RouletteServer::WorkWithPlayer(Player& player) { +void RouletteServer::WorkWithPlayer(Player* player) { while (true) { - Message message = Message::Read(player.socket_fd); + Message message = Message::Read(player->socket_fd); Message ans_message; switch (message.type) { case Message::NEW_BET: { @@ -125,7 +125,7 @@ void RouletteServer::WorkWithPlayer(Player& player) { } // Otherwise game wasn't started. - ans_message = ProcessBet(player, message.body); + ans_message = ProcessBet(*player, message.body); rolling_mutex_.unlock_shared(); break; } @@ -138,7 +138,7 @@ void RouletteServer::WorkWithPlayer(Player& player) { ans_message = Message(Message::INCORRECT_MESSAGE); } } - ans_message.Write(player.socket_fd); + ans_message.Write(player->socket_fd); } } @@ -146,7 +146,7 @@ Message RouletteServer::ProcessStartDraw() { if (!is_rolling_) { rolling_mutex_.lock(); is_rolling_ = true; - return Message(Message::SUCCESS); + return Message(Message::DRAW_STARTED); } return Message(Message::CANT_START_DRAW, "Game is already in progress."); @@ -167,9 +167,9 @@ Message RouletteServer::ProcessEndDraw() { players_mutex_.unlock(); rolling_mutex_.unlock(); is_rolling_ = false; - return Message(Message::SUCCESS); + return Message(Message::DRAW_ENDED); } - return Message(Message::CANT_END_DWAW, "Game wasnt in progress."); + return Message(Message::CANT_END_DRAW, "Game wasnt in progress."); } Message RouletteServer::ProcessGetAllBets() { @@ -177,7 +177,9 @@ Message RouletteServer::ProcessGetAllBets() { std::string result; for (auto& p: players) { result += p.first; + result += " "; result += std::to_string(p.second->bet); + result += '\n'; } players_mutex_.unlock(); return Message(Message::LIST_OF_BETS, result); @@ -223,7 +225,7 @@ Message RouletteServer::ProcessBet(RouletteServer::Player& player, std::string b player.bet = bet_sum; player.bet_type = bet_type; player.number = betting_number; - result = Message::SUCCESS; + result = Message::BET_ACCEPTED; } players_mutex_.unlock(); return Message(result); diff --git a/tcp/server/src/server.h b/tcp/server/src/server.h index c226a05..0d6953a 100644 --- a/tcp/server/src/server.h +++ b/tcp/server/src/server.h @@ -50,7 +50,7 @@ class RouletteServer { void WorkWithCroupier(int sock_fd); - void WorkWithPlayer(Player& player); + void WorkWithPlayer(Player* player); Message ProcessGetAllBets(); From e1db3dff993490f7eccbbb9390ff46826edb3284 Mon Sep 17 00:00:00 2001 From: andrey Date: Sun, 10 Feb 2019 18:27:50 +0300 Subject: [PATCH 11/48] safely writing 2 socket --- tcp/message/src/message.h | 1 - tcp/server/CMakeLists.txt | 6 ++++-- tcp/server/src/server.cpp | 26 ++++++++++++++++++++++++-- tcp/server/src/server.h | 14 ++++++++++++-- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/tcp/message/src/message.h b/tcp/message/src/message.h index c3dc96f..20af61e 100644 --- a/tcp/message/src/message.h +++ b/tcp/message/src/message.h @@ -10,7 +10,6 @@ #include - class Message { public: enum Type { diff --git a/tcp/server/CMakeLists.txt b/tcp/server/CMakeLists.txt index d8313f8..a4d2523 100644 --- a/tcp/server/CMakeLists.txt +++ b/tcp/server/CMakeLists.txt @@ -2,7 +2,9 @@ cmake_minimum_required(VERSION 3.13) project(server) set(CMAKE_CXX_STANDARD 17) -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -lboost_system -lboost_date_time -lboost_thread") + +find_package(Boost REQUIRED COMPONENTS thread) add_executable(server src/main.cpp src/server.cpp src/server.h) -target_link_libraries (server LINK_PUBLIC message) \ No newline at end of file +target_link_libraries(server LINK_PUBLIC message ${Boost_LIBRARIES}) \ No newline at end of file diff --git a/tcp/server/src/server.cpp b/tcp/server/src/server.cpp index e6afdab..60ea804 100644 --- a/tcp/server/src/server.cpp +++ b/tcp/server/src/server.cpp @@ -138,7 +138,7 @@ void RouletteServer::WorkWithPlayer(Player* player) { ans_message = Message(Message::INCORRECT_MESSAGE); } } - ans_message.Write(player->socket_fd); + player->messages_.push(ans_message); } } @@ -162,7 +162,7 @@ Message RouletteServer::ProcessEndDraw() { std::to_string(winning_number) + " " + std::to_string(profit)); player.second->bet = 0; player.second->bet_type = Player::NO_BET; - msg.Write(player.second->socket_fd); + player.second->messages_.push(msg); } players_mutex_.unlock(); rolling_mutex_.unlock(); @@ -237,6 +237,10 @@ RouletteServer::~RouletteServer() { } } +RouletteServer::RouletteServer() { + srand(time(NULL)); +} + int RouletteServer::Player::CalculateProfit(int winning_number) { if ((winning_number % 2 == 0 && bet_type == EVEN) || (winning_number % 2 == 1 && bet_type == ODD)) @@ -245,3 +249,21 @@ int RouletteServer::Player::CalculateProfit(int winning_number) { return 35 * bet; return 0; } + +RouletteServer::Player::Player(int socket_fd) : socket_fd(socket_fd) { + writer = std::thread([this]() { + while (!messages_.closed()) { + try { + Message m = messages_.pull(); + m.Write(this->socket_fd); + } catch (boost::sync_queue_is_closed&) { + break; + } + } + }); +} + +RouletteServer::Player::~Player() { + messages_.close(); + writer.join(); +} diff --git a/tcp/server/src/server.h b/tcp/server/src/server.h index 0d6953a..d5bc679 100644 --- a/tcp/server/src/server.h +++ b/tcp/server/src/server.h @@ -5,16 +5,23 @@ #include #include #include +#include #include "../../message/src/message.h" class RouletteServer { public: + RouletteServer(); + void StartServer(uint16_t port_number); ~RouletteServer(); private: - struct Player { - explicit Player(int socket_fd) : socket_fd(socket_fd) {}; + class Player { + public: + explicit Player(int socket_fd); + + ~Player(); + const int socket_fd; int bet = 0; @@ -27,6 +34,9 @@ class RouletteServer { BetType bet_type = NO_BET; int number = -1; + std::thread writer; + boost::sync_queue messages_; + int CalculateProfit(int winning_number); }; From 92fcf9ddc907342ae96f9c4967f34cdd9eef2a60 Mon Sep 17 00:00:00 2001 From: andrey Date: Sun, 10 Feb 2019 18:39:20 +0300 Subject: [PATCH 12/48] logging new connections --- tcp/message/src/message.cpp | 6 ++---- tcp/server/src/server.cpp | 3 +++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tcp/message/src/message.cpp b/tcp/message/src/message.cpp index da754a3..d346ca7 100644 --- a/tcp/message/src/message.cpp +++ b/tcp/message/src/message.cpp @@ -1,14 +1,12 @@ #include -#include "message.h" - #include #include - #include #include #include +#include -#include +#include "message.h" Message::Message() : type(UNDEFINED), body() {} diff --git a/tcp/server/src/server.cpp b/tcp/server/src/server.cpp index 60ea804..4369296 100644 --- a/tcp/server/src/server.cpp +++ b/tcp/server/src/server.cpp @@ -19,6 +19,7 @@ void RouletteServer::AuthoriseClient(int sock_fd) { players[message.body] = player; workWithClient = std::bind(&RouletteServer::WorkWithPlayer, this, player); ans_type = Message::PLAYER_ADDED; + std::cout << "New player\n"; } else { ans_type = Message::CANT_ADD_PLAYER; } @@ -31,6 +32,7 @@ void RouletteServer::AuthoriseClient(int sock_fd) { have_croupier_ = true; workWithClient = std::bind(&RouletteServer::WorkWithCroupier, this, sock_fd); ans_type = Message::CROUPIER_ADDED; + std::cout << "New croupier\n"; } else { ans_type = Message::CANT_ADD_CROUPIER; } @@ -146,6 +148,7 @@ Message RouletteServer::ProcessStartDraw() { if (!is_rolling_) { rolling_mutex_.lock(); is_rolling_ = true; + std::cout << "New spin\n"; return Message(Message::DRAW_STARTED); } return Message(Message::CANT_START_DRAW, "Game is already in progress."); From 3cbb26e8467776a5c6c6d24c303ab263fa913831 Mon Sep 17 00:00:00 2001 From: andrey Date: Sun, 10 Feb 2019 18:49:15 +0300 Subject: [PATCH 13/48] architecture is great again --- tcp/server/CMakeLists.txt | 5 ++- tcp/server/src/main.cpp | 2 +- .../src/{server.cpp => roulette_server.cpp} | 41 +------------------ .../src/{server.h => roulette_server.h} | 9 ++-- tcp/server/src/tcp_server.cpp | 38 +++++++++++++++++ tcp/server/src/tcp_server.h | 17 ++++++++ 6 files changed, 66 insertions(+), 46 deletions(-) rename tcp/server/src/{server.cpp => roulette_server.cpp} (87%) rename tcp/server/src/{server.h => roulette_server.h} (89%) create mode 100644 tcp/server/src/tcp_server.cpp create mode 100644 tcp/server/src/tcp_server.h diff --git a/tcp/server/CMakeLists.txt b/tcp/server/CMakeLists.txt index a4d2523..ffd0d06 100644 --- a/tcp/server/CMakeLists.txt +++ b/tcp/server/CMakeLists.txt @@ -6,5 +6,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -lboost_system -lboost_date_tim find_package(Boost REQUIRED COMPONENTS thread) -add_executable(server src/main.cpp src/server.cpp src/server.h) +add_executable(server + src/main.cpp + src/roulette_server.cpp src/roulette_server.h + src/tcp_server.cpp src/tcp_server.h) target_link_libraries(server LINK_PUBLIC message ${Boost_LIBRARIES}) \ No newline at end of file diff --git a/tcp/server/src/main.cpp b/tcp/server/src/main.cpp index b3f8c67..bc8049a 100644 --- a/tcp/server/src/main.cpp +++ b/tcp/server/src/main.cpp @@ -1,6 +1,6 @@ #include #include -#include "server.h" +#include "roulette_server.h" int main(int argc, char* argv[]) { if (argc != 2) { diff --git a/tcp/server/src/server.cpp b/tcp/server/src/roulette_server.cpp similarity index 87% rename from tcp/server/src/server.cpp rename to tcp/server/src/roulette_server.cpp index 4369296..7e83b2d 100644 --- a/tcp/server/src/server.cpp +++ b/tcp/server/src/roulette_server.cpp @@ -4,10 +4,10 @@ #include #include -#include "server.h" +#include "roulette_server.h" -void RouletteServer::AuthoriseClient(int sock_fd) { +void RouletteServer::StartWorkingWithClient(int sock_fd) { std::function workWithClient = nullptr; while (true) { Message message = Message::Read(sock_fd); @@ -51,43 +51,6 @@ void RouletteServer::AuthoriseClient(int sock_fd) { workWithClient(); } - -void RouletteServer::StartServer(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 serv_addr = {0}, cli_addr = {0}; - - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = INADDR_ANY; - serv_addr.sin_port = htons(port_number); - - if (bind(socket_fd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) { - perror("ERROR on binding"); - exit(1); - } - listen(socket_fd, 5); - - while (true) { - - unsigned int cli_len = sizeof(cli_addr); - - int new_socket_fd = accept(socket_fd, (struct sockaddr*) &cli_addr, &cli_len); - - if (new_socket_fd < 0) { - perror("ERROR on accept"); - exit(1); - } - - std::thread thread(&RouletteServer::AuthoriseClient, this, new_socket_fd); - thread.detach(); - } -} - void RouletteServer::WorkWithCroupier(int sock_fd) { while (true) { Message message = Message::Read(sock_fd); diff --git a/tcp/server/src/server.h b/tcp/server/src/roulette_server.h similarity index 89% rename from tcp/server/src/server.h rename to tcp/server/src/roulette_server.h index d5bc679..fea4c2a 100644 --- a/tcp/server/src/server.h +++ b/tcp/server/src/roulette_server.h @@ -6,14 +6,13 @@ #include #include #include -#include "../../message/src/message.h" +#include "message.h" +#include "tcp_server.h" -class RouletteServer { +class RouletteServer : public TcpServer { public: RouletteServer(); - void StartServer(uint16_t port_number); - ~RouletteServer(); private: class Player { @@ -56,7 +55,7 @@ class RouletteServer { Message ProcessEndDraw(); - void AuthoriseClient(int sock_fd); + void StartWorkingWithClient(int sock_fd) override; void WorkWithCroupier(int sock_fd); diff --git a/tcp/server/src/tcp_server.cpp b/tcp/server/src/tcp_server.cpp new file mode 100644 index 0000000..b2e1002 --- /dev/null +++ b/tcp/server/src/tcp_server.cpp @@ -0,0 +1,38 @@ +#include +#include "tcp_server.h" + +void TcpServer::StartServer(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 serv_addr = {0}, cli_addr = {0}; + + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = INADDR_ANY; + serv_addr.sin_port = htons(port_number); + + if (bind(socket_fd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) { + perror("ERROR on binding"); + exit(1); + } + listen(socket_fd, 5); + + while (true) { + + unsigned int cli_len = sizeof(cli_addr); + + int new_socket_fd = accept(socket_fd, (struct sockaddr*) &cli_addr, &cli_len); + + if (new_socket_fd < 0) { + perror("ERROR on accept"); + exit(1); + } + + std::thread thread(&TcpServer::StartWorkingWithClient, this, new_socket_fd); + thread.detach(); + } +} diff --git a/tcp/server/src/tcp_server.h b/tcp/server/src/tcp_server.h new file mode 100644 index 0000000..04caeb0 --- /dev/null +++ b/tcp/server/src/tcp_server.h @@ -0,0 +1,17 @@ +#ifndef SERVER_TCP_SERVER_H +#define SERVER_TCP_SERVER_H + + +#include +#include + +class TcpServer { + public: + void StartServer(uint16_t port_number); + + private: + virtual void StartWorkingWithClient(int sock_fd) = 0; +}; + + +#endif //SERVER_TCP_SERVER_H From 15ccc29ad3277fdfdd8702cef44f90779a175c0e Mon Sep 17 00:00:00 2001 From: oquechy Date: Sun, 10 Feb 2019 19:22:19 +0300 Subject: [PATCH 14/48] fix prompt --- tcp/client/src/client.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tcp/client/src/client.cpp b/tcp/client/src/client.cpp index 04a0fe2..4416b32 100644 --- a/tcp/client/src/client.cpp +++ b/tcp/client/src/client.cpp @@ -226,19 +226,19 @@ void RouletteClient::Quit() { void RouletteClient::PrintHeader(const std::string &header) { io_mutex_.lock(); system("clear"); - std::cout << header << '\n' << "> "; + std::cout << header + "\n> " << std::flush; io_mutex_.unlock(); } void RouletteClient::PrintPrompt() { io_mutex_.lock(); - std::cout << "> "; + std::cout << "> " << std::flush; io_mutex_.unlock(); } void RouletteClient::Cout(const std::string &message) { io_mutex_.lock(); - std::cout << message << '\n'; + std::cout << message << std::endl; io_mutex_.unlock(); } From d098c959df234557780a38089bcfdecb5020f85a Mon Sep 17 00:00:00 2001 From: andrey Date: Sun, 10 Feb 2019 19:22:38 +0300 Subject: [PATCH 15/48] bug with zero --- tcp/server/src/roulette_server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcp/server/src/roulette_server.cpp b/tcp/server/src/roulette_server.cpp index 7e83b2d..741e502 100644 --- a/tcp/server/src/roulette_server.cpp +++ b/tcp/server/src/roulette_server.cpp @@ -208,7 +208,7 @@ RouletteServer::RouletteServer() { } int RouletteServer::Player::CalculateProfit(int winning_number) { - if ((winning_number % 2 == 0 && bet_type == EVEN) || + if ((winning_number % 2 == 0 && bet_type == EVEN && winning_number != 0) || (winning_number % 2 == 1 && bet_type == ODD)) return 2 * bet; if (winning_number == number && bet_type == NUMBER) From 7808551bfde23119d7ef0562237ac2e75e203b68 Mon Sep 17 00:00:00 2001 From: andrey Date: Sun, 10 Feb 2019 19:56:36 +0300 Subject: [PATCH 16/48] Closing sockets on server --- tcp/message/src/message.cpp | 13 ++++++------- tcp/server/src/roulette_server.cpp | 30 ++++++++++++++++++++++++++---- tcp/server/src/roulette_server.h | 5 ++++- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/tcp/message/src/message.cpp b/tcp/message/src/message.cpp index d346ca7..af1e3fc 100644 --- a/tcp/message/src/message.cpp +++ b/tcp/message/src/message.cpp @@ -72,14 +72,13 @@ bool Message::GetBody(std::string *body, size_t length, int sockfd) { } bool Message::Get(char *dst, size_t message_len, int sockfd) { - for (ssize_t read = 0; message_len; read = ::read(sockfd, dst, message_len)) { - if (read < 0) { - std::cerr << strerror(errno) << std::endl; + ssize_t read = 0; + while (read < message_len) { + ssize_t cur = read = ::read(sockfd, dst, message_len); + if (cur == 0) return false; - } else { - dst += read; - message_len -= read; - } + dst += cur; + read += cur; } return true; } diff --git a/tcp/server/src/roulette_server.cpp b/tcp/server/src/roulette_server.cpp index 741e502..1382c3b 100644 --- a/tcp/server/src/roulette_server.cpp +++ b/tcp/server/src/roulette_server.cpp @@ -15,7 +15,7 @@ void RouletteServer::StartWorkingWithClient(int sock_fd) { if (Message::NEW_PLAYER == message.type) { players_mutex_.lock(); if (players.count(message.body) == 0) { - auto* player = new Player(sock_fd); + auto* player = new Player(message.body, sock_fd); players[message.body] = player; workWithClient = std::bind(&RouletteServer::WorkWithPlayer, this, player); ans_type = Message::PLAYER_ADDED; @@ -68,6 +68,13 @@ void RouletteServer::WorkWithCroupier(int sock_fd) { ans_message = ProcessGetAllBets(); break; } + case Message::UNDEFINED: { + croupier_mutex_.lock(); + have_croupier_ = false; + croupier_mutex_.unlock(); + close(sock_fd); + return; + } default: { ans_message = Message(Message::INCORRECT_MESSAGE); @@ -99,6 +106,11 @@ void RouletteServer::WorkWithPlayer(Player* player) { break; } + case Message::UNDEFINED: { + DeletePlayer(player); + return; + } + default: { ans_message = Message(Message::INCORRECT_MESSAGE); } @@ -198,8 +210,8 @@ Message RouletteServer::ProcessBet(RouletteServer::Player& player, std::string b } RouletteServer::~RouletteServer() { - for (auto& p: players) { - delete p.second; + for (const auto& p: players) { + close(p.second->socket_fd); } } @@ -207,6 +219,14 @@ RouletteServer::RouletteServer() { srand(time(NULL)); } +void RouletteServer::DeletePlayer(RouletteServer::Player* player) { + players_mutex_.lock(); + players.erase(player->name); + players_mutex_.unlock(); + + delete player; +} + int RouletteServer::Player::CalculateProfit(int winning_number) { if ((winning_number % 2 == 0 && bet_type == EVEN && winning_number != 0) || (winning_number % 2 == 1 && bet_type == ODD)) @@ -216,7 +236,8 @@ int RouletteServer::Player::CalculateProfit(int winning_number) { return 0; } -RouletteServer::Player::Player(int socket_fd) : socket_fd(socket_fd) { +RouletteServer::Player::Player(const std::string& name, int socket_fd) : name(name), + socket_fd(socket_fd) { writer = std::thread([this]() { while (!messages_.closed()) { try { @@ -231,5 +252,6 @@ RouletteServer::Player::Player(int socket_fd) : socket_fd(socket_fd) { RouletteServer::Player::~Player() { messages_.close(); + close(socket_fd); writer.join(); } diff --git a/tcp/server/src/roulette_server.h b/tcp/server/src/roulette_server.h index fea4c2a..2376805 100644 --- a/tcp/server/src/roulette_server.h +++ b/tcp/server/src/roulette_server.h @@ -17,12 +17,14 @@ class RouletteServer : public TcpServer { private: class Player { public: - explicit Player(int socket_fd); + explicit Player(const std::string& name, int socket_fd); ~Player(); const int socket_fd; + const std::string name; + int bet = 0; enum BetType { NO_BET, @@ -65,6 +67,7 @@ class RouletteServer : public TcpServer { Message ProcessBet(Player& player, std::string bet); + void DeletePlayer(Player* player); }; #endif //SERVER_SERVER_H From 772fdec231350ad781e4b5448dae0ced1472c6a6 Mon Sep 17 00:00:00 2001 From: andrey Date: Sun, 10 Feb 2019 20:04:49 +0300 Subject: [PATCH 17/48] logging leaves --- tcp/server/src/roulette_server.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tcp/server/src/roulette_server.cpp b/tcp/server/src/roulette_server.cpp index 1382c3b..357e6d4 100644 --- a/tcp/server/src/roulette_server.cpp +++ b/tcp/server/src/roulette_server.cpp @@ -73,6 +73,7 @@ void RouletteServer::WorkWithCroupier(int sock_fd) { have_croupier_ = false; croupier_mutex_.unlock(); close(sock_fd); + std::cout << "Croupier left\n"; return; } @@ -108,6 +109,7 @@ void RouletteServer::WorkWithPlayer(Player* player) { case Message::UNDEFINED: { DeletePlayer(player); + std::cout << "Player left\n"; return; } From 09be2c6131c531153257f4abe664f1ab6101b850 Mon Sep 17 00:00:00 2001 From: oquechy Date: Mon, 11 Feb 2019 10:40:37 +0300 Subject: [PATCH 18/48] handle client request to exit --- tcp/client/src/client.cpp | 163 ++++++++++++++++-------------------- tcp/client/src/main.cpp | 1 + tcp/message/src/message.cpp | 16 ++-- 3 files changed, 79 insertions(+), 101 deletions(-) diff --git a/tcp/client/src/client.cpp b/tcp/client/src/client.cpp index 4416b32..6ae760c 100644 --- a/tcp/client/src/client.cpp +++ b/tcp/client/src/client.cpp @@ -66,124 +66,104 @@ bool RouletteClient::StartClient(const char *host, uint16_t port_number) { void RouletteClient::AuthorisePlayer(const std::string &name) { Message request{Message::NEW_PLAYER, name}; requests_.push(request); - for (Message response = responses_.pull();; response = responses_.pull()) { - switch (response.type) { - case Message::PLAYER_ADDED: - Cout("enjoy the game, " + name); - return; - case Message::CANT_ADD_PLAYER: - Cout(response.body.empty() ? "sorry, this name is taken" : response.body); - return; - case Message::DRAW_RESULTS: - continue; - default: - HandleResponse(response); - return; - } + Message response = responses_.pull(); + switch (response.type) { + case Message::PLAYER_ADDED: + Cout("enjoy the game, " + name); + return; + case Message::CANT_ADD_PLAYER: + Cout(response.body.empty() ? "sorry, this name is taken" : response.body); + return; + default: + HandleResponse(response); + return; } + } void RouletteClient::AuthoriseCroupier(const std::string &key) { Message request{Message::NEW_CROUPIER, key}; requests_.push(request); - for (Message response = responses_.pull();; response = responses_.pull()) { - switch (response.type) { - case Message::CROUPIER_ADDED: - Cout("welcome ruler"); - return; - case Message::CANT_ADD_CROUPIER: - Cout(response.body.empty() ? "wrong password" : response.body); - return; - case Message::CROUPIER_ALREADY_EXISTS: - Cout(response.body.empty() ? "there can't be two masters" : response.body); - return; - case Message::DRAW_RESULTS: - continue; - default: - HandleResponse(response); - return; - } + Message response = responses_.pull(); + switch (response.type) { + case Message::CROUPIER_ADDED: + Cout("welcome ruler"); + return; + case Message::CANT_ADD_CROUPIER: + Cout(response.body.empty() ? "wrong password" : response.body); + return; + case Message::CROUPIER_ALREADY_EXISTS: + Cout(response.body.empty() ? "there can't be two masters" : response.body); + return; + default: + HandleResponse(response); + return; } } void RouletteClient::StartDraw() { Message request{Message::START_DRAW}; requests_.push(request); - for (Message response = responses_.pull();; response = responses_.pull()) { - switch (response.type) { - case Message::DRAW_STARTED: - Cout("whirrr!"); - return; - case Message::CANT_START_DRAW: - Cout(response.body.empty() ? "draw declined" : response.body); - return; - case Message::DRAW_RESULTS: - PrintResults(response); - continue; - default: - HandleResponse(response); - return; - } + Message response = responses_.pull(); + switch (response.type) { + case Message::DRAW_STARTED: + Cout("whirrr!"); + return; + case Message::CANT_START_DRAW: + Cout(response.body.empty() ? "draw declined" : response.body); + return; + default: + HandleResponse(response); + return; } } void RouletteClient::FinishDraw() { Message request{Message::END_DRAW}; requests_.push(request); - for (Message response = responses_.pull();; response = responses_.pull()) { - switch (response.type) { - case Message::DRAW_ENDED: - Cout("draw ended"); - return; - case Message::CANT_END_DRAW: - Cout(response.body.empty() ? "can't finish" : response.body); - return; - case Message::DRAW_RESULTS: - PrintResults(response); - continue; - default: - HandleResponse(response); - return; - } + Message response = responses_.pull(); + switch (response.type) { + case Message::DRAW_ENDED: + Cout("draw ended"); + return; + case Message::CANT_END_DRAW: + Cout(response.body.empty() ? "can't finish" : response.body); + return; + default: + HandleResponse(response); + return; } } void RouletteClient::NewBet(const std::string &type, int sum) { Message request{Message::NEW_BET, type + " " + std::to_string(sum)}; requests_.push(request); - for (Message response = responses_.pull();; response = responses_.pull()) { - switch (response.type) { - case Message::BET_ACCEPTED: - Cout("good luck!"); - return; - case Message::REPEATED_BET: - Cout(response.body.empty() ? "you already made a bet" : response.body); - return; - case Message::DRAW_RESULTS: - PrintResults(response); - continue; - default: - HandleResponse(response); - return; - } + Message response = responses_.pull(); + switch (response.type) { + case Message::BET_ACCEPTED: + Cout("good luck!"); + return; + case Message::REPEATED_BET: + Cout(response.body.empty() ? "you already made a bet" : response.body); + return; + default: + HandleResponse(response); + return; } } void RouletteClient::ListBets() { Message request{Message::GET_ALL_BETS}; requests_.push(request); - for (Message response = responses_.pull();; response = responses_.pull()) { - switch (response.type) { - case Message::LIST_OF_BETS: - Cout(response.body); - return; - case Message::DRAW_RESULTS: - PrintResults(response); - continue; - default: - HandleResponse(response); - return; - } + Message response = responses_.pull(); + switch (response.type) { + case Message::LIST_OF_BETS: + Cout(response.body); + return; + default: + HandleResponse(response); + return; + } } @@ -191,8 +171,6 @@ void RouletteClient::HandleUnexpectedServerResponse(const Message &response) { Cout("server responded with {type: " + std::to_string(response.type) + ", message: " + response.body + "}"); } -void RouletteClient::PrintResults(const Message &response) { Cout(response.body); } - void RouletteClient::HandleUnauthorised() { Cout("introduce yourself"); } void RouletteClient::HandleIncorrectMessage(const Message &response) { @@ -207,6 +185,9 @@ void RouletteClient::HandleResponse(const Message &response) { case Message::UNAUTHORIZED: HandleUnauthorised(); return; + case Message::UNDEFINED: + Quit(); + exit(0); default: HandleUnexpectedServerResponse(response); return; @@ -215,11 +196,11 @@ void RouletteClient::HandleResponse(const Message &response) { void RouletteClient::Quit() { Cout("closing connection..."); + shutdown(sockfd_, SHUT_RDWR); requests_.close(); responses_.close(); request_sender_.join(); response_receiver_.join(); - close(sockfd_); Cout("bye!"); } diff --git a/tcp/client/src/main.cpp b/tcp/client/src/main.cpp index 860df0a..ff1646d 100644 --- a/tcp/client/src/main.cpp +++ b/tcp/client/src/main.cpp @@ -44,6 +44,7 @@ int main(int argc, char *argv[]) { client.ListBets(); } else if (line == "bye") { client.Quit(); + return 0; } else if (sscanf(line.c_str(), "bet %d odd", &sum) and sum > 0) { client.NewBet("odd", sum); } else if (sscanf(line.c_str(), "bet %d even", &sum) and sum > 0) { diff --git a/tcp/message/src/message.cpp b/tcp/message/src/message.cpp index d346ca7..492c15e 100644 --- a/tcp/message/src/message.cpp +++ b/tcp/message/src/message.cpp @@ -21,14 +21,10 @@ bool Message::Write(int sockfd) { PutInt32(static_cast(body.size()), data + sizeof(uint32_t)); PutBody(data + 2 * sizeof(uint32_t)); - for (ssize_t written = 0; message_len; written = ::write(sockfd, data, message_len)) { - if (written < 0) { - std::cerr << strerror(errno) << std::endl; - return false; - } else { - data += written; - message_len -= written; - } + ssize_t written = ::write(sockfd, data, message_len); + if (written < 0) { + std::cerr << strerror(errno) << std::endl; + return false; } return true; @@ -72,8 +68,8 @@ bool Message::GetBody(std::string *body, size_t length, int sockfd) { } bool Message::Get(char *dst, size_t message_len, int sockfd) { - for (ssize_t read = 0; message_len; read = ::read(sockfd, dst, message_len)) { - if (read < 0) { + for (ssize_t read = ::read(sockfd, dst, message_len); message_len; read = ::read(sockfd, dst, message_len)) { + if (read <= 0) { std::cerr << strerror(errno) << std::endl; return false; } else { From d9009eef63a64cc97b28cd8eb7a59e5b7bcaaebf Mon Sep 17 00:00:00 2001 From: andrey Date: Mon, 11 Feb 2019 23:58:41 +0300 Subject: [PATCH 19/48] created include folders --- tcp/client/{src => include}/client.h | 0 tcp/message/{src => include}/message.h | 0 tcp/message/src/message.cpp | 2 +- tcp/server/{src => include}/roulette_server.h | 2 +- tcp/server/{src => include}/tcp_server.h | 0 tcp/server/src/main.cpp | 2 +- tcp/server/src/roulette_server.cpp | 2 +- tcp/server/src/tcp_server.cpp | 2 +- 8 files changed, 5 insertions(+), 5 deletions(-) rename tcp/client/{src => include}/client.h (100%) rename tcp/message/{src => include}/message.h (100%) rename tcp/server/{src => include}/roulette_server.h (97%) rename tcp/server/{src => include}/tcp_server.h (100%) diff --git a/tcp/client/src/client.h b/tcp/client/include/client.h similarity index 100% rename from tcp/client/src/client.h rename to tcp/client/include/client.h diff --git a/tcp/message/src/message.h b/tcp/message/include/message.h similarity index 100% rename from tcp/message/src/message.h rename to tcp/message/include/message.h diff --git a/tcp/message/src/message.cpp b/tcp/message/src/message.cpp index 492c15e..0b1d6ef 100644 --- a/tcp/message/src/message.cpp +++ b/tcp/message/src/message.cpp @@ -6,7 +6,7 @@ #include #include -#include "message.h" +#include "../include/message.h" Message::Message() : type(UNDEFINED), body() {} diff --git a/tcp/server/src/roulette_server.h b/tcp/server/include/roulette_server.h similarity index 97% rename from tcp/server/src/roulette_server.h rename to tcp/server/include/roulette_server.h index 2376805..c027fb9 100644 --- a/tcp/server/src/roulette_server.h +++ b/tcp/server/include/roulette_server.h @@ -6,7 +6,7 @@ #include #include #include -#include "message.h" +#include "../include/message.h" #include "tcp_server.h" class RouletteServer : public TcpServer { diff --git a/tcp/server/src/tcp_server.h b/tcp/server/include/tcp_server.h similarity index 100% rename from tcp/server/src/tcp_server.h rename to tcp/server/include/tcp_server.h diff --git a/tcp/server/src/main.cpp b/tcp/server/src/main.cpp index bc8049a..9b2d3b2 100644 --- a/tcp/server/src/main.cpp +++ b/tcp/server/src/main.cpp @@ -1,6 +1,6 @@ #include #include -#include "roulette_server.h" +#include "../include/roulette_server.h" int main(int argc, char* argv[]) { if (argc != 2) { diff --git a/tcp/server/src/roulette_server.cpp b/tcp/server/src/roulette_server.cpp index 357e6d4..ef80128 100644 --- a/tcp/server/src/roulette_server.cpp +++ b/tcp/server/src/roulette_server.cpp @@ -4,7 +4,7 @@ #include #include -#include "roulette_server.h" +#include "../include/roulette_server.h" void RouletteServer::StartWorkingWithClient(int sock_fd) { diff --git a/tcp/server/src/tcp_server.cpp b/tcp/server/src/tcp_server.cpp index b2e1002..6dd63b1 100644 --- a/tcp/server/src/tcp_server.cpp +++ b/tcp/server/src/tcp_server.cpp @@ -1,5 +1,5 @@ #include -#include "tcp_server.h" +#include "../include/tcp_server.h" void TcpServer::StartServer(uint16_t port_number) { int socket_fd = socket(AF_INET, SOCK_STREAM, 0); From c02985dfcdc0168c526bbfb25f30265ce85dd7b1 Mon Sep 17 00:00:00 2001 From: andrey Date: Tue, 12 Feb 2019 00:22:40 +0300 Subject: [PATCH 20/48] Can remove players now --- tcp/client/CMakeLists.txt | 2 +- tcp/client/include/client.h | 2 +- tcp/client/src/client.cpp | 2 +- tcp/client/src/main.cpp | 2 +- tcp/message/CMakeLists.txt | 2 +- tcp/message/src/message.cpp | 1 - tcp/server/CMakeLists.txt | 4 ++-- tcp/server/include/roulette_server.h | 3 +++ tcp/server/src/main.cpp | 17 ++++++++++++++++- tcp/server/src/roulette_server.cpp | 11 +++++++++++ 10 files changed, 37 insertions(+), 9 deletions(-) diff --git a/tcp/client/CMakeLists.txt b/tcp/client/CMakeLists.txt index 1d7bce1..819688d 100644 --- a/tcp/client/CMakeLists.txt +++ b/tcp/client/CMakeLists.txt @@ -6,5 +6,5 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -lboost_system -lboost_date_tim find_package(Boost REQUIRED COMPONENTS thread) -add_executable(client src/main.cpp src/client.cpp src/client.h) +add_executable(client src/main.cpp src/client.cpp include/client.h) target_link_libraries (client LINK_PUBLIC message ${Boost_LIBRARIES}) \ No newline at end of file diff --git a/tcp/client/include/client.h b/tcp/client/include/client.h index a051ac5..511f781 100644 --- a/tcp/client/include/client.h +++ b/tcp/client/include/client.h @@ -4,7 +4,7 @@ #include -#include +#include <../include/message.h> #include #include #include diff --git a/tcp/client/src/client.cpp b/tcp/client/src/client.cpp index 6ae760c..8c81340 100644 --- a/tcp/client/src/client.cpp +++ b/tcp/client/src/client.cpp @@ -1,7 +1,7 @@ #include #include #include -#include "client.h" +#include "../include/client.h" bool RouletteClient::StartClient(const char *host, uint16_t port_number) { diff --git a/tcp/client/src/main.cpp b/tcp/client/src/main.cpp index ff1646d..0d8a5fc 100644 --- a/tcp/client/src/main.cpp +++ b/tcp/client/src/main.cpp @@ -4,7 +4,7 @@ #include #include #include -#include "client.h" +#include "../include/client.h" void usage(char *const *argv) { std::cerr << "Usage: " << argv[0] << " \n"; } diff --git a/tcp/message/CMakeLists.txt b/tcp/message/CMakeLists.txt index 7da9c8c..ea26e7e 100644 --- a/tcp/message/CMakeLists.txt +++ b/tcp/message/CMakeLists.txt @@ -1,2 +1,2 @@ -add_library (message src/message.cpp src/message.h) +add_library(message src/message.cpp include/message.h) target_include_directories (message PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src) diff --git a/tcp/message/src/message.cpp b/tcp/message/src/message.cpp index 0b1d6ef..a068aeb 100644 --- a/tcp/message/src/message.cpp +++ b/tcp/message/src/message.cpp @@ -70,7 +70,6 @@ bool Message::GetBody(std::string *body, size_t length, int sockfd) { bool Message::Get(char *dst, size_t message_len, int sockfd) { for (ssize_t read = ::read(sockfd, dst, message_len); message_len; read = ::read(sockfd, dst, message_len)) { if (read <= 0) { - std::cerr << strerror(errno) << std::endl; return false; } else { dst += read; diff --git a/tcp/server/CMakeLists.txt b/tcp/server/CMakeLists.txt index ffd0d06..d60e302 100644 --- a/tcp/server/CMakeLists.txt +++ b/tcp/server/CMakeLists.txt @@ -8,6 +8,6 @@ find_package(Boost REQUIRED COMPONENTS thread) add_executable(server src/main.cpp - src/roulette_server.cpp src/roulette_server.h - src/tcp_server.cpp src/tcp_server.h) + src/roulette_server.cpp include/roulette_server.h + src/tcp_server.cpp include/tcp_server.h) target_link_libraries(server LINK_PUBLIC message ${Boost_LIBRARIES}) \ No newline at end of file diff --git a/tcp/server/include/roulette_server.h b/tcp/server/include/roulette_server.h index c027fb9..beec1bd 100644 --- a/tcp/server/include/roulette_server.h +++ b/tcp/server/include/roulette_server.h @@ -14,6 +14,9 @@ class RouletteServer : public TcpServer { RouletteServer(); ~RouletteServer(); + + bool BanPlayer(const std::string& name); + private: class Player { public: diff --git a/tcp/server/src/main.cpp b/tcp/server/src/main.cpp index 9b2d3b2..4e83c77 100644 --- a/tcp/server/src/main.cpp +++ b/tcp/server/src/main.cpp @@ -2,11 +2,17 @@ #include #include "../include/roulette_server.h" +const std::string USAGE = "Usage: ./roulette_server "; + +const std::string CMDS = "exit -- close server\n" + "ban -- to disconnect a player from game"; + int main(int argc, char* argv[]) { if (argc != 2) { - std::cout << "Usage: ./roulette_server "; + std::cout << USAGE; return 0; } + std::cout << CMDS << std::endl; uint16_t port_number = static_cast(std::stoi(argv[1])); @@ -17,6 +23,15 @@ int main(int argc, char* argv[]) { std::string in; while (in != "exit") { std::cin >> in; + if (in == "ban") { + std::string name; + std::cin >> name; + if (server.BanPlayer(name)) { + std::cout << "A player was successfully banned. Good job!\n"; + } else { + std::cout << name << " doesn't play at this moment.\n"; + } + } } close(port_number); diff --git a/tcp/server/src/roulette_server.cpp b/tcp/server/src/roulette_server.cpp index ef80128..869e54c 100644 --- a/tcp/server/src/roulette_server.cpp +++ b/tcp/server/src/roulette_server.cpp @@ -229,6 +229,17 @@ void RouletteServer::DeletePlayer(RouletteServer::Player* player) { delete player; } +bool RouletteServer::BanPlayer(const std::string& name) { + bool result = false; + players_mutex_.lock(); + if (players.count(name)) { + close(players[name]->socket_fd); + result = true; + } + players_mutex_.unlock(); + return result; +} + int RouletteServer::Player::CalculateProfit(int winning_number) { if ((winning_number % 2 == 0 && bet_type == EVEN && winning_number != 0) || (winning_number % 2 == 1 && bet_type == ODD)) From 37d0dcd607f3c9bd18a71340629a557bfe4709b8 Mon Sep 17 00:00:00 2001 From: oquechy Date: Tue, 12 Feb 2019 01:15:31 +0300 Subject: [PATCH 21/48] revert tcp_template --- tcp_template/client_linux/CMakeLists.txt | 2 +- tcp_template/server_linux/CMakeLists.txt | 8 ++++---- .../server_linux/{main.cpp => main.c} | 20 ++++++++----------- 3 files changed, 13 insertions(+), 17 deletions(-) rename tcp_template/server_linux/{main.cpp => main.c} (78%) diff --git a/tcp_template/client_linux/CMakeLists.txt b/tcp_template/client_linux/CMakeLists.txt index c1a0803..311326d 100644 --- a/tcp_template/client_linux/CMakeLists.txt +++ b/tcp_template/client_linux/CMakeLists.txt @@ -3,5 +3,5 @@ project(client_linux) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") -set(SOURCE_FILES main.c ../../tcp/message/src/message.cpp ../../tcp/message/message.h) +set(SOURCE_FILES main.c) add_executable(client_linux ${SOURCE_FILES}) \ No newline at end of file diff --git a/tcp_template/server_linux/CMakeLists.txt b/tcp_template/server_linux/CMakeLists.txt index ef0fc75..ac88ba4 100644 --- a/tcp_template/server_linux/CMakeLists.txt +++ b/tcp_template/server_linux/CMakeLists.txt @@ -1,7 +1,7 @@ -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 2.8) project(server_linux) -set(CMAKE_CXX_STANDARD 17) -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") -add_executable(server_linux main.cpp ../../tcp/message/src/message.h ../../tcp/message/src/message.cpp) +set(SOURCE_FILES main.c) +add_executable(server_linux ${SOURCE_FILES}) \ No newline at end of file diff --git a/tcp_template/server_linux/main.cpp b/tcp_template/server_linux/main.c similarity index 78% rename from tcp_template/server_linux/main.cpp rename to tcp_template/server_linux/main.c index ef7c6f7..30c7084 100644 --- a/tcp_template/server_linux/main.cpp +++ b/tcp_template/server_linux/main.c @@ -7,8 +7,6 @@ #include -#include "../../tcp/message/src/message.h" - int main(int argc, char *argv[]) { int sockfd, newsockfd; uint16_t portno; @@ -27,7 +25,7 @@ int main(int argc, char *argv[]) { /* Initialize socket structure */ bzero((char *) &serv_addr, sizeof(serv_addr)); - portno = 10239; + portno = 5001; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; @@ -54,26 +52,24 @@ int main(int argc, char *argv[]) { exit(1); } + /* If connection is established then start communicating */ + bzero(buffer, 256); + n = read(newsockfd, buffer, 255); // recv on Windows - Message m = Message::Read(newsockfd); - - if (m.type == Message::UNDEFINED) { + if (n < 0) { perror("ERROR reading from socket"); exit(1); } - printf("Message: {type = %zu, length = %zu, message = %s}\n", static_cast(m.type), - m.body.size(), m.body.c_str()); + printf("Here is the message: %s\n", buffer); /* Write a response to the client */ - bool b = Message(Message::SUCCESS, "I got your message").Write(newsockfd); + n = write(newsockfd, "I got your message", 18); // send on Windows - if (!b) { + if (n < 0) { perror("ERROR writing to socket"); exit(1); } - close(sockfd); - close(newsockfd); return 0; } From 12b1578e3af8c46ee093956c931b2d2bcea28faf Mon Sep 17 00:00:00 2001 From: oquechy Date: Tue, 12 Feb 2019 11:57:18 +0300 Subject: [PATCH 22/48] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b95aaa..5045413 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,12 @@ +# Зависимости +- Boost 1.058.00 + # Протокол игры "Рулетка" ## Формат сообщений +--------------------+--------------------+-------------+ - | int message type | int body length | char[] body | + | int message type | int body length | char[] body | +--------------------+--------------------+-------------+ ## Клиент From 4b795121ebfb555334a2707238a51057e8098d44 Mon Sep 17 00:00:00 2001 From: oquechy Date: Tue, 12 Feb 2019 12:03:54 +0300 Subject: [PATCH 23/48] Update README.md --- README.md | 52 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 5045413..220a589 100644 --- a/README.md +++ b/README.md @@ -40,11 +40,6 @@ ## Сервер -- Отчёт об успешной операции - - type: 0 - body: "Optional message" - - Отчёт о получении сообщения от неавторизованного игрока или крупье type: 1 @@ -55,42 +50,67 @@ type: 2 body: "Optional message" -- Отчёт об отказе в добавлении игрока +- Отчёт о добавлении игрока type: 101 + body: "Optional message" + +- Отчёт об отказе в добавлении игрока + + type: 102 body: "Optional message, ex: name is taken" -- Отчёт об ошибке ввода пароля крупье +- Отчёт об авторизации крупье type: 201 + body: "Optional message" + +- Отчёт об ошибке ввода пароля крупье + + type: 202 body: "Optional message, ex: wrong passord" - Отчёт об отказе входа крупье - type: 202 + type: 203 body: "Optional message, ex: croupier already authorised" -- Отчёт о повторной ставке +- Отчёт о принятии ставки type: 301 + body: "Optional message" + +- Отчёт о повторной ставке + + type: 302 body: "Optional message, ex: you already made your bet" - Отчёт о несвоевременной ставке - type: 302 + type: 303 body: "Optional message, ex: game in progress" -- Отчёт об отклонении начала розыгрыша +- Отчёт о начале розыгрыша type: 401 + body: "Optional message" + +- Отчёт об отклонении начала розыгрыша + + type: 402 body: "Optional message, ex: game in progress" - - - Отчёт об отклонении конца розыгрыша - type: 501 - body: "Optional message, ex: game is already fineshed" + - Отчёт о завершении розыгрыша + + type: 501 + body: "Optional message" + +- Отчёт об отклонении конца розыгрыша + + type: 502 + body: "Optional message, ex: game is already fineshed" -- Оповещение о завершении розыгрыша +- Оповещение с результатами розыгрыша type: 600 body: "N GAIN" From be0caa40b4c441c8df539b9d269e228273dbca4d Mon Sep 17 00:00:00 2001 From: oquechy Date: Tue, 12 Feb 2019 12:06:59 +0300 Subject: [PATCH 24/48] fix sscanf of two numbers --- tcp/client/src/main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tcp/client/src/main.cpp b/tcp/client/src/main.cpp index 0d8a5fc..67c4ed1 100644 --- a/tcp/client/src/main.cpp +++ b/tcp/client/src/main.cpp @@ -13,6 +13,7 @@ void help() { std::cerr << "List of commands:\n" "\ta croupier \n" "\tbet (odd|even|)\n" "\tspin\n" + "\tfinish\n" "\tlist\n" "\tbye\n"; } @@ -45,12 +46,12 @@ int main(int argc, char *argv[]) { } else if (line == "bye") { client.Quit(); return 0; + } else if (sscanf(line.c_str(), "bet %d %d", &sum, &number) == 2 and sum > 0) { + client.NewBet(std::to_string(number), sum); } else if (sscanf(line.c_str(), "bet %d odd", &sum) and sum > 0) { client.NewBet("odd", sum); } else if (sscanf(line.c_str(), "bet %d even", &sum) and sum > 0) { client.NewBet("even", sum); - } else if (sscanf(line.c_str(), "bet %d %d", &sum, &number) == 2 and sum > 0) { - client.NewBet(std::to_string(number), sum); } else { help(); } From 067e8e7aa538695a1f478f63a0e937a5733d678d Mon Sep 17 00:00:00 2001 From: oquechy Date: Sun, 17 Feb 2019 16:44:39 +0300 Subject: [PATCH 25/48] market readme --- README.md | 155 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 94 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index 220a589..42bd1ba 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Зависимости - Boost 1.058.00 -# Протокол игры "Рулетка" +# Протокол общения на бирже фрилансеров ## Формат сообщений @@ -11,36 +11,57 @@ ## Клиент -- Запрос на добавление игрока +- Запрос на вход заказчика type: 100 body: "Name" -- Запрос на вход крупье по паролю +- Запрос на вход фрилансера type: 200 - body: "Password" + body: "Name" -- Запрос на добавление ставки +- Добавление заказа от заказчика type: 300 - body: "N" | "even" | "odd" + body: "Description" -- Запрос на начало розыгрыша +- Вывод списка заказов определённого заказчика с их статусами type: 400 -- Запрос на конец розыгрыша +- Вывод всех открытых заказов type: 500 -- Получить список всех ставок +- Заявка от фрилансера на выполнение заказа - type 700 + type: 600 + body: "task_id" + +- Утверждение заявки заказчиком + + type: 700 + body: "task_id name" + +- Начало выполнения работы фрилансером + + type: 800 + body: "task_id" + +- Конец выполнения работы фрилансером + + type: 900 + body: "task_id" + +- Принятие работы заказчиком + + type: 1000 + body: "task_id" ## Сервер -- Отчёт о получении сообщения от неавторизованного игрока или крупье +- Ответ на сообщение от неавторизованного пользователя type: 1 body: "Optional message" @@ -50,72 +71,84 @@ type: 2 body: "Optional message" -- Отчёт о добавлении игрока - +- Отчёт о добавлении заказчика + type: 101 - body: "Optional message" - -- Отчёт об отказе в добавлении игрока + body: "" +- Отчёт о том, что заказчик не был добавлен + type: 102 - body: "Optional message, ex: name is taken" - -- Отчёт об авторизации крупье + body: "Reason" +- Отчёт о добавлении фрилансера + type: 201 - body: "Optional message" - -- Отчёт об ошибке ввода пароля крупье + body: "" +- Отчёт о том, что фрилансер не был добавлен + type: 202 - body: "Optional message, ex: wrong passord" - -- Отчёт об отказе входа крупье - - type: 203 - body: "Optional message, ex: croupier already authorised" - -- Отчёт о принятии ставки + body: "Reason" + +- Добавлен заказ от заказчика type: 301 - body: "Optional message" + body: "task_id" -- Отчёт о повторной ставке - - type: 302 - body: "Optional message, ex: you already made your bet" +- Вывод списка заказов определённого заказчика с их статусами -- Отчёт о несвоевременной ставке - - type: 303 - body: "Optional message, ex: game in progress" - -- Отчёт о начале розыгрыша - type: 401 - body: "Optional message" + body: "*> -- Отчёт об отклонении начала розыгрыша - - type: 402 - body: "Optional message, ex: game in progress" +- Список всех открытых заказов + + type: 501 + body: "*" + +- Принятние заявки фрилансера на выполнение + + type: 601 - - Отчёт о завершении розыгрыша +- Отклонение заявки фрилансера на выполнение + + type: 602 + body: "Reason" + +- Заявка успешно подтверждена заказчиком + + type: 701 - type: 501 - body: "Optional message" - -- Отчёт об отклонении конца розыгрыша +- Отклонение подтверждения заявки + + type: 702 + body: "Reason" + +- Начало выполнения фрилансером работы принято + + type: 801 - type: 502 - body: "Optional message, ex: game is already fineshed" - -- Оповещение с результатами розыгрыша +- Ответ на некорректное сообщение о начале работы + + type: 802 + body: "Reason" + +- Конец выполнения фрилансером работы зафиксирован + + type: 901 - type: 600 - body: "N GAIN" +- Ответ на некорректное сообщение о завершении работы + + type: 902 + body: "Reason" + +- Отчёт об успешном принятии работы заказчиком -- Список ставок всех игроков + type: 1001 + body: "task_id" - type: 800 - body: "NAME1 BET1 NAME2 BET2 ..." +- Ответ на некорректное сообщение о принятии готового заказа + + type: 1002 + body: "Reason" + From 8d94fcfe00bcd829ec1f3b2bdf6d9e4002312c2f Mon Sep 17 00:00:00 2001 From: andrey Date: Mon, 18 Feb 2019 15:38:05 +0300 Subject: [PATCH 26/48] new msg types --- tcp/message/include/message.h | 47 ++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/tcp/message/include/message.h b/tcp/message/include/message.h index 20af61e..75f0e92 100644 --- a/tcp/message/include/message.h +++ b/tcp/message/include/message.h @@ -16,26 +16,33 @@ class Message { UNDEFINED = 0, UNAUTHORIZED = 1, INCORRECT_MESSAGE = 2, - NEW_PLAYER = 100, - PLAYER_ADDED = 101, - CANT_ADD_PLAYER = 102, - NEW_CROUPIER = 200, - CROUPIER_ADDED = 201, - CANT_ADD_CROUPIER = 202, - CROUPIER_ALREADY_EXISTS = 203, - NEW_BET = 300, - BET_ACCEPTED = 301, - REPEATED_BET = 302, - UNTIMELY_BET = 303, - START_DRAW = 400, - DRAW_STARTED = 401, - CANT_START_DRAW = 402, - END_DRAW = 500, - DRAW_ENDED = 501, - CANT_END_DRAW = 502, - DRAW_RESULTS = 600, - GET_ALL_BETS = 700, - LIST_OF_BETS = 701 + NEW_CUSTOMER = 100, + CUSTOMER_ADDED = 101, + CANT_ADD_CUSTOMER = 102, + NEW_FREELANCER = 200, + FREELANCER_ADDED = 201, + CANT_ADD_FREELANCER = 202, + NEW_ORDER = 300, + ORDER_ACCEPTED = 301, + GET_MY_ORDERS = 400, + LIST_OF_MY_ORDERS = 401, + GET_OPEN_ORDERS = 500, + LIST_OF_OPEN_ORDERS = 501, + TAKE_ORDER = 600, + TAKE_ORDER_SUCCESSFUL = 601, + TAKE_ORDER_NOT_SUCCESSFUL = 601, + GIVE_ORDER_TO_FREELANCER = 700, + GIVE_ORDER_SUCCESSFUL = 701, + GIVE_ORDER_NOT_SUCCESSFUL = 702, + WORK_STARTED = 800, + WORK_STARTED_SUCCESSFUL = 801, + WORK_STARTED_NOT_SUCCESSFUL = 802, + WORK_FINISHED = 900, + WORK_FINISHED_SUCCESSFUL = 801, + WORK_FINISHED_NOT_SUCCESSFUL = 802, + WORK_ACCEPTED = 1000, + WORK_ACCEPTED_SUCCESSFUL = 1001, + WORK_ACCEPTED_NOT_SUCCESSFUL = 1002, }; Type type; From e1d9aa9c2a14a663610cf0c99883ef90b69aac58 Mon Sep 17 00:00:00 2001 From: andrey Date: Mon, 18 Feb 2019 15:38:43 +0300 Subject: [PATCH 27/48] Updated readme --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 42bd1ba..55b8346 100644 --- a/README.md +++ b/README.md @@ -109,38 +109,42 @@ - Принятние заявки фрилансера на выполнение type: 601 + body: "task_id" - Отклонение заявки фрилансера на выполнение type: 602 - body: "Reason" + body: "task_id Reason" - Заявка успешно подтверждена заказчиком type: 701 + body: "task_id" - Отклонение подтверждения заявки type: 702 - body: "Reason" + body: "task_id Reason" - Начало выполнения фрилансером работы принято type: 801 + body: "task_id" - Ответ на некорректное сообщение о начале работы type: 802 - body: "Reason" + body: "task_id Reason" - Конец выполнения фрилансером работы зафиксирован type: 901 + body: "task_id" - Ответ на некорректное сообщение о завершении работы type: 902 - body: "Reason" + body: "task_id Reason" - Отчёт об успешном принятии работы заказчиком @@ -150,5 +154,5 @@ - Ответ на некорректное сообщение о принятии готового заказа type: 1002 - body: "Reason" + body: "task_id Reason" From bebeaf6d696bb2d495693b71fff1eeb8dd44bcea Mon Sep 17 00:00:00 2001 From: andrey Date: Mon, 18 Feb 2019 17:08:24 +0300 Subject: [PATCH 28/48] Client implementation --- tcp/client/include/client.h | 33 ++++-- tcp/client/src/client.cpp | 216 ++++++++++++++++++++-------------- tcp/client/src/main.cpp | 141 ++++++++++++++++------ tcp/message/include/message.h | 2 +- 4 files changed, 254 insertions(+), 138 deletions(-) diff --git a/tcp/client/include/client.h b/tcp/client/include/client.h index 511f781..62c9f16 100644 --- a/tcp/client/include/client.h +++ b/tcp/client/include/client.h @@ -1,16 +1,15 @@ - #ifndef ROULETTE_CLIENT_H #define ROULETTE_CLIENT_H #include -#include <../include/message.h> #include #include #include #include +#include <../include/message.h> -class RouletteClient { +class MarketClient { public: bool StartClient(const char *host, uint16_t port_number); @@ -27,29 +26,39 @@ class RouletteClient { std::mutex io_mutex_; + Message SendMessage(Message::Type type); + + Message SendMessage(Message::Type type, const std::string& text); + public: - void AuthorisePlayer(const std::string &name); + bool AuthoriseCustomer(const std::string& name); + + bool AuthoriseFreelancer(const std::string& name); - void AuthoriseCroupier(const std::string &key); + void ListMyOrders(); - void StartDraw(); + void ListOpenOrders(); - void FinishDraw(); + void NewOrder(const std::string& description); - void NewBet(const std::string &type, int sum); + void RequestOrder(int order_id); + + void StartOrder(int order_id); + + void FinishOrder(int order_id); + + void GiveOrder(int order_id); + + void ApproveDoneOrder(int order_id); void HandleIncorrectMessage(const Message &response); void HandleUnauthorised(); - void PrintResults(const Message &response); - void HandleUnexpectedServerResponse(const Message &response); void HandleResponse(const Message &response); - void ListBets(); - void Quit(); void PrintHeader(const std::string &header); diff --git a/tcp/client/src/client.cpp b/tcp/client/src/client.cpp index 8c81340..e8fea40 100644 --- a/tcp/client/src/client.cpp +++ b/tcp/client/src/client.cpp @@ -1,10 +1,9 @@ #include -#include #include +#include #include "../include/client.h" -bool RouletteClient::StartClient(const char *host, uint16_t port_number) { - +bool MarketClient::StartClient(const char* host, uint16_t port_number) { sockfd_ = socket(AF_INET, SOCK_STREAM, 0); if (sockfd_ < 0) { @@ -46,14 +45,14 @@ bool RouletteClient::StartClient(const char *host, uint16_t port_number) { while (!responses_.closed()) { try { Message m = Message::Read(sockfd_); - if (m.type == Message::DRAW_RESULTS) { - int number, win; - std::sscanf(m.body.c_str(), "%d %d", &number, &win); - PrintHeader("DRAW ENDED\nWINNING NUMBER " + std::to_string(number) + - "\nYOUR PROFIT " + std::to_string(win)); - } else { +// if (m.type == Message::DRAW_RESULTS) { +// int number, win; +// std::sscanf(m.body.c_str(), "%d %d", &number, &win); +// PrintHeader("DRAW ENDED\nWINNING NUMBER " + std::to_string(number) + +// "\nYOUR PROFIT " + std::to_string(win)); +// } else { responses_.push(m); - } + //} } catch (boost::sync_queue_is_closed &) { break; } @@ -63,37 +62,54 @@ bool RouletteClient::StartClient(const char *host, uint16_t port_number) { return true; } -void RouletteClient::AuthorisePlayer(const std::string &name) { - Message request{Message::NEW_PLAYER, name}; - requests_.push(request); - Message response = responses_.pull(); +bool MarketClient::AuthoriseCustomer(const std::string& name) { + Message response = SendMessage(Message::NEW_CUSTOMER, name); switch (response.type) { - case Message::PLAYER_ADDED: - Cout("enjoy the game, " + name); - return; - case Message::CANT_ADD_PLAYER: - Cout(response.body.empty() ? "sorry, this name is taken" : response.body); - return; + case Message::CUSTOMER_ADDED: + Cout("Authorisation successful, you can create orders now, " + name); + return true; + case Message::CANT_ADD_CUSTOMER: + Cout(response.body.empty() ? "Sorry, something went wrong" : response.body); + return false; default: HandleResponse(response); - return; + return false; } } -void RouletteClient::AuthoriseCroupier(const std::string &key) { - Message request{Message::NEW_CROUPIER, key}; - requests_.push(request); - Message response = responses_.pull(); +bool MarketClient::AuthoriseFreelancer(const std::string& name) { + Message response = SendMessage(Message::NEW_FREELANCER, name); + switch (response.type) { + case Message::FREELANCER_ADDED: + Cout("You can look for orders now"); + return true; + case Message::CANT_ADD_FREELANCER: + Cout(response.body.empty() ? "Sorry, something went wrong" : response.body); + return false; + default: + HandleResponse(response); + return false; + } +} + +void MarketClient::ListMyOrders() { + Message response = SendMessage(Message::GET_MY_ORDERS); switch (response.type) { - case Message::CROUPIER_ADDED: - Cout("welcome ruler"); + case Message::LIST_OF_MY_ORDERS: + Cout(response.body); return; - case Message::CANT_ADD_CROUPIER: - Cout(response.body.empty() ? "wrong password" : response.body); + default: + HandleResponse(response); return; - case Message::CROUPIER_ALREADY_EXISTS: - Cout(response.body.empty() ? "there can't be two masters" : response.body); + } +} + +void MarketClient::ListOpenOrders() { + Message response = SendMessage(Message::GET_OPEN_ORDERS); + switch (response.type) { + case Message::LIST_OF_OPEN_ORDERS: + Cout(response.body); return; default: HandleResponse(response); @@ -101,130 +117,154 @@ void RouletteClient::AuthoriseCroupier(const std::string &key) { } } -void RouletteClient::StartDraw() { - Message request{Message::START_DRAW}; - requests_.push(request); - Message response = responses_.pull(); +void MarketClient::HandleUnexpectedServerResponse(const Message& response) { + Cout("server responded with {type: " + std::to_string(response.type) + ", message: " + response.body + "}"); +} + +void MarketClient::HandleUnauthorised() { Cout("Please enter who u are"); } + +void MarketClient::HandleIncorrectMessage(const Message& response) { + Cout(response.body.empty() ? "You are not permitted to do it" : response.body); +} + +void MarketClient::HandleResponse(const Message& response) { switch (response.type) { - case Message::DRAW_STARTED: - Cout("whirrr!"); + case Message::INCORRECT_MESSAGE: + HandleIncorrectMessage(response); return; - case Message::CANT_START_DRAW: - Cout(response.body.empty() ? "draw declined" : response.body); + case Message::UNAUTHORIZED: + HandleUnauthorised(); return; + case Message::UNDEFINED: + Quit(); + exit(0); default: - HandleResponse(response); + HandleUnexpectedServerResponse(response); return; } } -void RouletteClient::FinishDraw() { - Message request{Message::END_DRAW}; - requests_.push(request); - Message response = responses_.pull(); +void MarketClient::RequestOrder(int order_id) { + Message response = SendMessage(Message::TAKE_ORDER, std::to_string(order_id)); switch (response.type) { - case Message::DRAW_ENDED: - Cout("draw ended"); - return; - case Message::CANT_END_DRAW: - Cout(response.body.empty() ? "can't finish" : response.body); + case Message::TAKE_ORDER_SUCCESSFUL: + Cout("Order" + response.body + " requested."); return; + case Message::TAKE_ORDER_NOT_SUCCESSFUL: + Cout(response.body); default: HandleResponse(response); return; } } -void RouletteClient::NewBet(const std::string &type, int sum) { - Message request{Message::NEW_BET, type + " " + std::to_string(sum)}; - requests_.push(request); - Message response = responses_.pull(); +void MarketClient::StartOrder(int order_id) { + Message response = SendMessage(Message::WORK_STARTED, std::to_string(order_id)); switch (response.type) { - case Message::BET_ACCEPTED: - Cout("good luck!"); - return; - case Message::REPEATED_BET: - Cout(response.body.empty() ? "you already made a bet" : response.body); + case Message::WORK_STARTED: + Cout("Order" + response.body + " started successfully."); return; + case Message::WORK_STARTED_SUCCESSFUL: + Cout(response.body); default: HandleResponse(response); return; } } -void RouletteClient::ListBets() { - Message request{Message::GET_ALL_BETS}; - requests_.push(request); - Message response = responses_.pull(); +void MarketClient::FinishOrder(int order_id) { + Message response = SendMessage(Message::WORK_FINISHED, std::to_string(order_id)); switch (response.type) { - case Message::LIST_OF_BETS: - Cout(response.body); + case Message::WORK_FINISHED_SUCCESSFUL: + Cout("Order" + response.body + " finished successfully."); return; + case Message::WORK_FINISHED_NOT_SUCCESSFUL: + Cout(response.body); default: HandleResponse(response); return; - } } -void RouletteClient::HandleUnexpectedServerResponse(const Message &response) { - Cout("server responded with {type: " + std::to_string(response.type) + ", message: " + response.body + "}"); +void MarketClient::NewOrder(const std::string& description) { + Message response = SendMessage(Message::NEW_ORDER, description); + switch (response.type) { + case Message::ORDER_ACCEPTED: + Cout("You can now track this order by id: " + response.body); + default: + HandleResponse(response); + return; + } } -void RouletteClient::HandleUnauthorised() { Cout("introduce yourself"); } - -void RouletteClient::HandleIncorrectMessage(const Message &response) { - Cout(response.body.empty() ? "unexpected request" : response.body); +void MarketClient::GiveOrder(int order_id) { + Message response = SendMessage(Message::GIVE_ORDER_TO_FREELANCER, std::to_string(order_id)); + switch (response.type) { + case Message::GIVE_ORDER_SUCCESSFUL: + Cout("Order" + response.body + " given successfully."); + return; + case Message::GIVE_ORDER_NOT_SUCCESSFUL: + Cout(response.body); + default: + HandleResponse(response); + return; + } } -void RouletteClient::HandleResponse(const Message &response) { +void MarketClient::ApproveDoneOrder(int order_id) { + Message response = SendMessage(Message::WORK_ACCEPTED, std::to_string(order_id)); switch (response.type) { - case Message::INCORRECT_MESSAGE: - HandleIncorrectMessage(response); + case Message::WORK_ACCEPTED_SUCCESSFUL: + Cout("Work for order" + response.body + " accepted successfully."); return; - case Message::UNAUTHORIZED: - HandleUnauthorised(); - return; - case Message::UNDEFINED: - Quit(); - exit(0); + case Message::WORK_ACCEPTED_NOT_SUCCESSFUL: + Cout(response.body); default: - HandleUnexpectedServerResponse(response); + HandleResponse(response); return; } } -void RouletteClient::Quit() { - Cout("closing connection..."); +void MarketClient::Quit() { + Cout("Closing connection..."); shutdown(sockfd_, SHUT_RDWR); requests_.close(); responses_.close(); request_sender_.join(); response_receiver_.join(); - Cout("bye!"); + Cout("Bye! Hope to see u again!"); } -void RouletteClient::PrintHeader(const std::string &header) { +void MarketClient::PrintHeader(const std::string& header) { io_mutex_.lock(); system("clear"); std::cout << header + "\n> " << std::flush; io_mutex_.unlock(); } -void RouletteClient::PrintPrompt() { +void MarketClient::PrintPrompt() { io_mutex_.lock(); std::cout << "> " << std::flush; io_mutex_.unlock(); } -void RouletteClient::Cout(const std::string &message) { +void MarketClient::Cout(const std::string& message) { io_mutex_.lock(); std::cout << message << std::endl; io_mutex_.unlock(); } -bool RouletteClient::GetLine(std::string &message) { +bool MarketClient::GetLine(std::string& message) { auto &result = getline(std::cin, message); return bool(result); } +Message MarketClient::SendMessage(Message::Type type) { + SendMessage(type, ""); +} + +Message MarketClient::SendMessage(Message::Type type, const std::string& text) { + Message request{type, text}; + requests_.push(request); + return responses_.pull(); +} diff --git a/tcp/client/src/main.cpp b/tcp/client/src/main.cpp index 67c4ed1..329af49 100644 --- a/tcp/client/src/main.cpp +++ b/tcp/client/src/main.cpp @@ -6,56 +6,123 @@ #include #include "../include/client.h" -void usage(char *const *argv) { std::cerr << "Usage: " << argv[0] << " \n"; } - -void help() { std::cerr << "List of commands:\n" - "\ta player \n" - "\ta croupier \n" - "\tbet (odd|even|)\n" - "\tspin\n" - "\tfinish\n" - "\tlist\n" - "\tbye\n"; } - -int main(int argc, char *argv[]) { +void Usage(char* const* argv) { std::cerr << "Usage: " << argv[0] << " \n"; } + +void AuthHelp() { + std::cout << "Please authorize as a customer or as a freelancer:\n" + "\ta freelancer \n" + "\ta customer \n"; +} + +void FreelancerHelp() { + std::cout << "List of commands:\n" + "\t orders\n" + "\t request \n" + "\t start \n" + "\t finish \n" + "\t bye\n"; +} + +void CustomerHelp() { + std::cout << "List of commands\n" + "\t new order \n" + "\t all orders\n" + "\t my orders\n" + "\t give \n" + "\t done \n" + "\t bye\n"; +} + +void WorkWithFreelancer(MarketClient& client) { + std::string line; + int order_id; + + FreelancerHelp(); + client.PrintPrompt(); + + while (true) { + client.GetLine(line); + if (line == "orders") { + client.ListOpenOrders(); + } else if (sscanf(line.c_str(), "request %d", &order_id)) { + client.RequestOrder(order_id); + } else if (sscanf(line.c_str(), "start %d", &order_id)) { + client.StartOrder(order_id); + } else if (sscanf(line.c_str(), "start %d", &order_id)) { + client.FinishOrder(order_id); + } else if (line == "bye") { + client.Quit(); + return; + } else { + FreelancerHelp(); + } + client.PrintPrompt(); + } +} + +void WorkWithCustomer(MarketClient& client) { + char arg[256]; + std::string line; + int order_id; + + CustomerHelp(); + client.PrintPrompt(); + while (true) { + client.GetLine(line); + if (line == "all orders") { + client.ListOpenOrders(); + } else if (line == "my orders") { + client.ListMyOrders(); + } else if (sscanf(line.c_str(), "give %d", &order_id)) { + client.GiveOrder(order_id); + } else if (sscanf(line.c_str(), "done %d", &order_id)) { + client.ApproveDoneOrder(order_id); + } else if (sscanf(line.c_str(), "new order %s", arg)) { + client.NewOrder(arg); + } else if (line == "bye") { + client.Quit(); + return; + } else { + CustomerHelp(); + } + client.PrintPrompt(); + } + +} + +int main(int argc, char* argv[]) { if (argc < 3) { - usage(argv); + Usage(argv); exit(0); } auto port_number = static_cast(std::stoi(argv[2])); - RouletteClient client{}; + MarketClient client{}; if (!client.StartClient(argv[1], port_number)) exit(1); char arg[256]; - int number, sum; - for (std::string line; client.GetLine(line);) { - if (sscanf(line.c_str(), "a player %s", arg)) { - client.AuthorisePlayer(arg); - } else if (sscanf(line.c_str(), "a croupier %s", arg)) { - client.AuthoriseCroupier(arg); - } else if (line == "spin") { - client.StartDraw(); - } else if (line == "finish") { - client.FinishDraw(); - } else if (line == "list") { - client.ListBets(); - } else if (line == "bye") { - client.Quit(); - return 0; - } else if (sscanf(line.c_str(), "bet %d %d", &sum, &number) == 2 and sum > 0) { - client.NewBet(std::to_string(number), sum); - } else if (sscanf(line.c_str(), "bet %d odd", &sum) and sum > 0) { - client.NewBet("odd", sum); - } else if (sscanf(line.c_str(), "bet %d even", &sum) and sum > 0) { - client.NewBet("even", sum); + std::string line; + + AuthHelp(); + + while (true) { + client.GetLine(line); + if (sscanf(line.c_str(), "a customer %s", arg)) { + if (client.AuthoriseCustomer(arg)) { + WorkWithCustomer(client); + break; + } + } else if (sscanf(line.c_str(), "a freelancer %s", arg)) { + if (client.AuthoriseFreelancer(arg)) { + WorkWithFreelancer(client); + break; + } } else { - help(); + AuthHelp(); } - client.PrintPrompt(); } return 0; diff --git a/tcp/message/include/message.h b/tcp/message/include/message.h index 75f0e92..846d67a 100644 --- a/tcp/message/include/message.h +++ b/tcp/message/include/message.h @@ -30,7 +30,7 @@ class Message { LIST_OF_OPEN_ORDERS = 501, TAKE_ORDER = 600, TAKE_ORDER_SUCCESSFUL = 601, - TAKE_ORDER_NOT_SUCCESSFUL = 601, + TAKE_ORDER_NOT_SUCCESSFUL = 602, GIVE_ORDER_TO_FREELANCER = 700, GIVE_ORDER_SUCCESSFUL = 701, GIVE_ORDER_NOT_SUCCESSFUL = 702, From 04313aa4741ba9b8adcc074c189daf414c0882ef Mon Sep 17 00:00:00 2001 From: oquechy Date: Tue, 19 Feb 2019 20:47:25 +0300 Subject: [PATCH 29/48] server authorization --- tcp/CMakeLists.txt | 2 +- tcp/server/CMakeLists.txt | 2 +- tcp/server/include/market_server.h | 104 +++++++++++ tcp/server/include/roulette_server.h | 76 -------- tcp/server/src/main.cpp | 12 +- tcp/server/src/market_server.cpp | 252 +++++++++++++++++++++++++ tcp/server/src/roulette_server.cpp | 270 --------------------------- 7 files changed, 364 insertions(+), 354 deletions(-) create mode 100644 tcp/server/include/market_server.h delete mode 100644 tcp/server/include/roulette_server.h create mode 100644 tcp/server/src/market_server.cpp delete mode 100644 tcp/server/src/roulette_server.cpp diff --git a/tcp/CMakeLists.txt b/tcp/CMakeLists.txt index 5889844..d7fc155 100644 --- a/tcp/CMakeLists.txt +++ b/tcp/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.13) -project(roulette) +project(market) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") diff --git a/tcp/server/CMakeLists.txt b/tcp/server/CMakeLists.txt index d60e302..f6729c3 100644 --- a/tcp/server/CMakeLists.txt +++ b/tcp/server/CMakeLists.txt @@ -8,6 +8,6 @@ find_package(Boost REQUIRED COMPONENTS thread) add_executable(server src/main.cpp - src/roulette_server.cpp include/roulette_server.h + src/market_server.cpp include/market_server.h src/tcp_server.cpp include/tcp_server.h) target_link_libraries(server LINK_PUBLIC message ${Boost_LIBRARIES}) \ No newline at end of file diff --git a/tcp/server/include/market_server.h b/tcp/server/include/market_server.h new file mode 100644 index 0000000..6cc7356 --- /dev/null +++ b/tcp/server/include/market_server.h @@ -0,0 +1,104 @@ +#ifndef SERVER_SERVER_H +#define SERVER_SERVER_H + +#include +#include +#include +#include +#include +#include +#include "../include/message.h" +#include "tcp_server.h" + +class MarketServer : public TcpServer { +public: + MarketServer(); + + ~MarketServer(); + + bool BanUser(const std::string &name); + +private: + class Freelancer { + public: + explicit Freelancer(const std::string &name, int socket_fd); + + ~Freelancer(); + + const int socket_fd; + const std::string name; + std::thread writer; + boost::sync_queue messages_; + }; + + class Customer { + public: + explicit Customer(const std::string &name, int socket_fd); + + ~Customer(); + + const int socket_fd; + const std::string name; + std::thread writer; + boost::sync_queue messages_; + }; + + class Order { + public: + enum State { + OPEN, + IN_PROGRESS, + DONE + }; + + explicit Order(const std::string &customer, const std::string &description) + : customer(customer), description(description), task_id(task_counter++), state(OPEN) {} + + const int task_id; + const std::string description; + const std::string customer; + State state; + std::mutex workers_mutex; + std::set workers; + + private: + static int task_counter; + }; + + std::map freelancers; + std::map customers; + std::map orders; + + std::mutex customers_mutex_; + std::mutex freelancers_mutex_; + + std::shared_timed_mutex orders_mutex_; + + Message ProcessStartDraw(); + + Message ProcessEndDraw(); + + void StartWorkingWithClient(int sock_fd) override; + + void WorkWithFreelancer(Freelancer *freelancer); + + void WorkWithCustomer(Customer *customer); + + Message LookupOrdersOf(Customer *customer); + + Message LookupOpenOrders(); + + Message ProcessBet(Freelancer &player, std::string bet); + + void DeleteCustomer(Customer *customer); + + void DeleteFreelancer(Freelancer *freelancer); + + std::string StateToString(Order::State state); + + std::string WorkersToString(std::set set); + + void OrderToString(std::string &result, Order *o); +}; + +#endif //SERVER_SERVER_H diff --git a/tcp/server/include/roulette_server.h b/tcp/server/include/roulette_server.h deleted file mode 100644 index beec1bd..0000000 --- a/tcp/server/include/roulette_server.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef SERVER_SERVER_H -#define SERVER_SERVER_H - -#include -#include -#include -#include -#include -#include "../include/message.h" -#include "tcp_server.h" - -class RouletteServer : public TcpServer { - public: - RouletteServer(); - - ~RouletteServer(); - - bool BanPlayer(const std::string& name); - - private: - class Player { - public: - explicit Player(const std::string& name, int socket_fd); - - ~Player(); - - const int socket_fd; - - const std::string name; - - int bet = 0; - enum BetType { - NO_BET, - EVEN, - ODD, - NUMBER - }; - BetType bet_type = NO_BET; - int number = -1; - - std::thread writer; - boost::sync_queue messages_; - - int CalculateProfit(int winning_number); - }; - - const char* CROUPIER_PASSWORD = "ANDREY_THE_BEST"; - const int AMOUNT_OF_NUMBERS = 37; - bool have_croupier_ = false; - bool is_rolling_ = false; - - std::map players; - - std::mutex players_mutex_; - std::mutex croupier_mutex_; - - std::shared_timed_mutex rolling_mutex_; - - Message ProcessStartDraw(); - - Message ProcessEndDraw(); - - void StartWorkingWithClient(int sock_fd) override; - - void WorkWithCroupier(int sock_fd); - - void WorkWithPlayer(Player* player); - - Message ProcessGetAllBets(); - - Message ProcessBet(Player& player, std::string bet); - - void DeletePlayer(Player* player); -}; - -#endif //SERVER_SERVER_H diff --git a/tcp/server/src/main.cpp b/tcp/server/src/main.cpp index 4e83c77..e728a42 100644 --- a/tcp/server/src/main.cpp +++ b/tcp/server/src/main.cpp @@ -1,11 +1,11 @@ #include #include -#include "../include/roulette_server.h" +#include "../include/market_server.h" -const std::string USAGE = "Usage: ./roulette_server "; +const std::string USAGE = "Usage: ./server "; const std::string CMDS = "exit -- close server\n" - "ban -- to disconnect a player from game"; + "ban -- force user disconnect"; int main(int argc, char* argv[]) { if (argc != 2) { @@ -16,8 +16,8 @@ int main(int argc, char* argv[]) { uint16_t port_number = static_cast(std::stoi(argv[1])); - RouletteServer server; - std::thread server_thread(&RouletteServer::StartServer, &server, port_number); + MarketServer server; + std::thread server_thread(&MarketServer::StartServer, &server, port_number); server_thread.detach(); std::string in; @@ -26,7 +26,7 @@ int main(int argc, char* argv[]) { if (in == "ban") { std::string name; std::cin >> name; - if (server.BanPlayer(name)) { + if (server.BanUser(name)) { std::cout << "A player was successfully banned. Good job!\n"; } else { std::cout << name << " doesn't play at this moment.\n"; diff --git a/tcp/server/src/market_server.cpp b/tcp/server/src/market_server.cpp new file mode 100644 index 0000000..7f977f5 --- /dev/null +++ b/tcp/server/src/market_server.cpp @@ -0,0 +1,252 @@ +#include +#include +#include +#include +#include + +#include "../include/market_server.h" + +int MarketServer::Order::task_counter = 0; + +void MarketServer::StartWorkingWithClient(int sock_fd) { + std::cout << "client accepted\n"; + std::function workWithClient = nullptr; + while (true) { + Message message = Message::Read(sock_fd); + Message::Type ans_type; + std::string &name = message.body; + if (Message::NEW_CUSTOMER == message.type) { + customers_mutex_.lock(); + if (customers.count(name) == 0 and freelancers.count(name) == 0) { + auto *customer = new Customer(name, sock_fd); + customers[name] = customer; + workWithClient = std::bind(&MarketServer::WorkWithCustomer, this, customer); + ans_type = Message::CUSTOMER_ADDED; + std::cout << "New customer\n"; + } else { + ans_type = Message::CANT_ADD_CUSTOMER; + } + customers_mutex_.unlock(); + } else if (Message::NEW_FREELANCER == message.type) { + freelancers_mutex_.lock(); + if (freelancers.count(name) == 0 and customers.count(name) == 0) { + auto *freelancer = new Freelancer(name, sock_fd); + freelancers[name] = freelancer; + workWithClient = std::bind(&MarketServer::WorkWithFreelancer, this, freelancer); + ans_type = Message::FREELANCER_ADDED; + std::cout << "New freelancer\n"; + } else { + ans_type = Message::CANT_ADD_FREELANCER; + } + freelancers_mutex_.unlock(); + } else { + std::cout << "unauthorized\n"; + ans_type = Message::UNAUTHORIZED; + } + + Message ans_message(ans_type); + ans_message.Write(sock_fd); + + if (workWithClient != nullptr) { + break; + } + } + workWithClient(); +} + +void MarketServer::WorkWithFreelancer(Freelancer *freelancer) { + while (true) { + Message message = Message::Read(freelancer->socket_fd); + Message ans_message; + switch (message.type) { + case Message::GET_OPEN_ORDERS: { + ans_message = LookupOpenOrders(); + break; + } + case Message::TAKE_ORDER: { + orders_mutex_.lock(); + int id = stoi(message.body); + if (orders.count(id) and orders[id]->state == Order::OPEN) { + orders[id]->workers.insert(freelancer->name); + } + orders_mutex_.unlock(); + break; + } + case Message::UNDEFINED: { + DeleteFreelancer(freelancer); + std::cout << "Freelancer left\n"; + return; + } + + default: { + ans_message = Message(Message::INCORRECT_MESSAGE); + } + + } + freelancer->messages_.push(ans_message); + } +} + +void MarketServer::WorkWithCustomer(Customer *customer) { + while (true) { + Message message = Message::Read(customer->socket_fd); + Message ans_message; + switch (message.type) { + case Message::NEW_ORDER: { + orders_mutex_.lock(); + auto *order = new Order(customer->name, message.body); + orders[order->task_id] = order; + ans_message = Message(Message::ORDER_ACCEPTED); + orders_mutex_.unlock_shared(); + break; + } + case Message::GET_MY_ORDERS: { + ans_message = LookupOrdersOf(customer); + break; + } + case Message::UNDEFINED: { + DeleteCustomer(customer); + std::cout << "Customer left\n"; + return; + } + + default: { + ans_message = Message(Message::INCORRECT_MESSAGE); + } + } + customer->messages_.push(ans_message); + } +} + +Message MarketServer::LookupOpenOrders() { + orders_mutex_.lock_shared(); + std::string result; + for (auto &o: orders) { + if (o.second->state == Order::OPEN) { + OrderToString(result, o.second); + } + } + orders_mutex_.unlock_shared(); + return Message(Message::LIST_OF_MY_ORDERS, result); +} + +void MarketServer::OrderToString(std::string &result, MarketServer::Order *o) { + result += std::to_string(o->task_id); + result += " "; + result += o->description; + result += " "; + result += StateToString(o->state); + result += " "; + result += WorkersToString(o->workers); + result += '\n'; +} + +Message MarketServer::LookupOrdersOf(Customer *customer) { + orders_mutex_.lock_shared(); + std::string result; + for (auto &o: orders) { + if (o.second->customer == customer->name) { + OrderToString(result, o.second); + } + } + orders_mutex_.unlock_shared(); + return Message(Message::LIST_OF_MY_ORDERS, result); +} + +MarketServer::~MarketServer() { + for (const auto &p : customers) { + close(p.second->socket_fd); + delete p.second; + } + for (const auto &p : freelancers) { + close(p.second->socket_fd); + delete p.second; + } + for (const auto &p : orders) { + delete p.second; + } +} + +MarketServer::MarketServer() { + srand(static_cast(time(nullptr))); +} + +void MarketServer::DeleteCustomer(MarketServer::Customer *customer) { + customers_mutex_.lock(); + customers.erase(customer->name); + customers_mutex_.unlock(); + + delete customer; +} + +bool MarketServer::BanUser(const std::string &name) { + bool result = false; + freelancers_mutex_.lock(); + if (freelancers.count(name)) { + DeleteFreelancer(freelancers[name]); + result = true; + } + freelancers_mutex_.unlock(); + customers_mutex_.lock(); + if (customers.count(name)) { + DeleteCustomer(customers[name]); + result = true; + } + customers_mutex_.unlock(); + return result; +} + +std::string MarketServer::StateToString(MarketServer::Order::State state) { + switch (state) { + case Order::OPEN: + return "OPEN"; + case Order::IN_PROGRESS: + return "IN_PROGRESS"; + case Order::DONE: + return "DONE"; + } +} + +std::string MarketServer::WorkersToString(std::set set) { + std::string result; + for (auto &s : set) + result += s + " "; + return result; +} + +void MarketServer::DeleteFreelancer(MarketServer::Freelancer *freelancer) { + freelancers_mutex_.lock(); + customers.erase(freelancer->name); + freelancers_mutex_.unlock(); + + delete freelancer; + +} + +MarketServer::Freelancer::Freelancer(const std::string &name, int socket_fd) : name(name), + socket_fd(socket_fd) { + writer = std::thread([this]() { + while (!messages_.closed()) { + try { + Message m = messages_.pull(); + m.Write(this->socket_fd); + } catch (boost::sync_queue_is_closed &) { + break; + } + } + }); +} + +MarketServer::Freelancer::~Freelancer() { + messages_.close(); + close(socket_fd); + writer.join(); +} + +MarketServer::Customer::Customer(const std::string &name, int socket_fd) : name(name), socket_fd(socket_fd) {} + +MarketServer::Customer::~Customer() { + messages_.close(); + close(socket_fd); + writer.join(); +} diff --git a/tcp/server/src/roulette_server.cpp b/tcp/server/src/roulette_server.cpp deleted file mode 100644 index 869e54c..0000000 --- a/tcp/server/src/roulette_server.cpp +++ /dev/null @@ -1,270 +0,0 @@ -#include -#include -#include -#include -#include - -#include "../include/roulette_server.h" - - -void RouletteServer::StartWorkingWithClient(int sock_fd) { - std::function workWithClient = nullptr; - while (true) { - Message message = Message::Read(sock_fd); - Message::Type ans_type; - if (Message::NEW_PLAYER == message.type) { - players_mutex_.lock(); - if (players.count(message.body) == 0) { - auto* player = new Player(message.body, sock_fd); - players[message.body] = player; - workWithClient = std::bind(&RouletteServer::WorkWithPlayer, this, player); - ans_type = Message::PLAYER_ADDED; - std::cout << "New player\n"; - } else { - ans_type = Message::CANT_ADD_PLAYER; - } - players_mutex_.unlock(); - } else if (Message::NEW_CROUPIER == message.type) { - croupier_mutex_.lock(); - if (have_croupier_) { - ans_type = Message::CROUPIER_ALREADY_EXISTS; - } else if (message.body == CROUPIER_PASSWORD) { - have_croupier_ = true; - workWithClient = std::bind(&RouletteServer::WorkWithCroupier, this, sock_fd); - ans_type = Message::CROUPIER_ADDED; - std::cout << "New croupier\n"; - } else { - ans_type = Message::CANT_ADD_CROUPIER; - } - croupier_mutex_.unlock(); - } else { - ans_type = Message::UNAUTHORIZED; - } - - Message ans_message(ans_type); - ans_message.Write(sock_fd); - - if (workWithClient != nullptr) { - break; - } - } - workWithClient(); -} - -void RouletteServer::WorkWithCroupier(int sock_fd) { - while (true) { - Message message = Message::Read(sock_fd); - Message ans_message; - switch (message.type) { - case Message::START_DRAW: { - ans_message = ProcessStartDraw(); - break; - } - case Message::END_DRAW: { - ans_message = ProcessEndDraw(); - break; - } - case Message::GET_ALL_BETS: { - ans_message = ProcessGetAllBets(); - break; - } - case Message::UNDEFINED: { - croupier_mutex_.lock(); - have_croupier_ = false; - croupier_mutex_.unlock(); - close(sock_fd); - std::cout << "Croupier left\n"; - return; - } - - default: { - ans_message = Message(Message::INCORRECT_MESSAGE); - } - - } - ans_message.Write(sock_fd); - } -} - -void RouletteServer::WorkWithPlayer(Player* player) { - while (true) { - Message message = Message::Read(player->socket_fd); - Message ans_message; - switch (message.type) { - case Message::NEW_BET: { - if (!rolling_mutex_.try_lock_shared()) { - ans_message = Message(Message::UNTIMELY_BET); - break; - } - - // Otherwise game wasn't started. - ans_message = ProcessBet(*player, message.body); - rolling_mutex_.unlock_shared(); - break; - } - case Message::GET_ALL_BETS: { - ans_message = ProcessGetAllBets(); - break; - } - - case Message::UNDEFINED: { - DeletePlayer(player); - std::cout << "Player left\n"; - return; - } - - default: { - ans_message = Message(Message::INCORRECT_MESSAGE); - } - } - player->messages_.push(ans_message); - } -} - -Message RouletteServer::ProcessStartDraw() { - if (!is_rolling_) { - rolling_mutex_.lock(); - is_rolling_ = true; - std::cout << "New spin\n"; - return Message(Message::DRAW_STARTED); - } - return Message(Message::CANT_START_DRAW, "Game is already in progress."); - -} - -Message RouletteServer::ProcessEndDraw() { - if (is_rolling_) { - players_mutex_.lock(); - for (auto& player: players) { - int winning_number = rand() % AMOUNT_OF_NUMBERS; - int profit = player.second->CalculateProfit(winning_number); - Message msg(Message::DRAW_RESULTS, - std::to_string(winning_number) + " " + std::to_string(profit)); - player.second->bet = 0; - player.second->bet_type = Player::NO_BET; - player.second->messages_.push(msg); - } - players_mutex_.unlock(); - rolling_mutex_.unlock(); - is_rolling_ = false; - return Message(Message::DRAW_ENDED); - } - return Message(Message::CANT_END_DRAW, "Game wasnt in progress."); -} - -Message RouletteServer::ProcessGetAllBets() { - players_mutex_.lock(); - std::string result; - for (auto& p: players) { - result += p.first; - result += " "; - result += std::to_string(p.second->bet); - result += '\n'; - } - players_mutex_.unlock(); - return Message(Message::LIST_OF_BETS, result); -} - -Message RouletteServer::ProcessBet(RouletteServer::Player& player, std::string bet) { - std::string bet_type_str; - Player::BetType bet_type; - int betting_number = -1; - size_t delimeter_pos = bet.find(' '); - bet_type_str = bet.substr(0, delimeter_pos); - if (bet_type_str == "even") { - bet_type = Player::EVEN; - } else if (bet_type_str == "odd") { - bet_type = Player::ODD; - } else { - try { - betting_number = std::stoi(bet_type_str); - } catch (...) { - return Message(Message::INCORRECT_MESSAGE, "Incorrect bet type " + bet_type_str); - } - if (betting_number >= 0 && betting_number < AMOUNT_OF_NUMBERS) { - bet_type = Player::NUMBER; - } else { - return Message(Message::INCORRECT_MESSAGE, "Incorrect bet type " + bet_type_str); - } - } - - int bet_sum = 0; - try { - bet_sum = std::stoi(bet.substr(delimeter_pos, bet.size() - delimeter_pos)); - } catch (...) { - return Message(Message::INCORRECT_MESSAGE, - "Incorrect bet sum " + - bet.substr(delimeter_pos, bet.size() - delimeter_pos)); - } - - players_mutex_.lock(); - Message::Type result; - if (player.bet != 0) { - result = Message::REPEATED_BET; - } else { - player.bet = bet_sum; - player.bet_type = bet_type; - player.number = betting_number; - result = Message::BET_ACCEPTED; - } - players_mutex_.unlock(); - return Message(result); -} - -RouletteServer::~RouletteServer() { - for (const auto& p: players) { - close(p.second->socket_fd); - } -} - -RouletteServer::RouletteServer() { - srand(time(NULL)); -} - -void RouletteServer::DeletePlayer(RouletteServer::Player* player) { - players_mutex_.lock(); - players.erase(player->name); - players_mutex_.unlock(); - - delete player; -} - -bool RouletteServer::BanPlayer(const std::string& name) { - bool result = false; - players_mutex_.lock(); - if (players.count(name)) { - close(players[name]->socket_fd); - result = true; - } - players_mutex_.unlock(); - return result; -} - -int RouletteServer::Player::CalculateProfit(int winning_number) { - if ((winning_number % 2 == 0 && bet_type == EVEN && winning_number != 0) || - (winning_number % 2 == 1 && bet_type == ODD)) - return 2 * bet; - if (winning_number == number && bet_type == NUMBER) - return 35 * bet; - return 0; -} - -RouletteServer::Player::Player(const std::string& name, int socket_fd) : name(name), - socket_fd(socket_fd) { - writer = std::thread([this]() { - while (!messages_.closed()) { - try { - Message m = messages_.pull(); - m.Write(this->socket_fd); - } catch (boost::sync_queue_is_closed&) { - break; - } - } - }); -} - -RouletteServer::Player::~Player() { - messages_.close(); - close(socket_fd); - writer.join(); -} From f8ba097805e969e3f4f9a9ac770b2020414cad96 Mon Sep 17 00:00:00 2001 From: andrey Date: Tue, 19 Feb 2019 21:48:20 +0300 Subject: [PATCH 30/48] added fucking return --- tcp/client/src/client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tcp/client/src/client.cpp b/tcp/client/src/client.cpp index e8fea40..c3f5d2e 100644 --- a/tcp/client/src/client.cpp +++ b/tcp/client/src/client.cpp @@ -118,7 +118,7 @@ void MarketClient::ListOpenOrders() { } void MarketClient::HandleUnexpectedServerResponse(const Message& response) { - Cout("server responded with {type: " + std::to_string(response.type) + ", message: " + response.body + "}"); + Cout("server responded with {type: " + std::to_string(response.type) + ", message: " + "}"); } void MarketClient::HandleUnauthorised() { Cout("Please enter who u are"); } @@ -260,7 +260,7 @@ bool MarketClient::GetLine(std::string& message) { } Message MarketClient::SendMessage(Message::Type type) { - SendMessage(type, ""); + return SendMessage(type, ""); } Message MarketClient::SendMessage(Message::Type type, const std::string& text) { From c5e9b3fdee0b38b05cb76fec023d4885c5ac4cd9 Mon Sep 17 00:00:00 2001 From: oquechy Date: Tue, 19 Feb 2019 21:52:30 +0300 Subject: [PATCH 31/48] add customer writer --- tcp/server/include/market_server.h | 20 +++---- tcp/server/src/market_server.cpp | 90 +++++++++++++++++++++++++++--- 2 files changed, 92 insertions(+), 18 deletions(-) diff --git a/tcp/server/include/market_server.h b/tcp/server/include/market_server.h index 6cc7356..4281c6f 100644 --- a/tcp/server/include/market_server.h +++ b/tcp/server/include/market_server.h @@ -1,3 +1,5 @@ +#include + #ifndef SERVER_SERVER_H #define SERVER_SERVER_H @@ -12,8 +14,6 @@ class MarketServer : public TcpServer { public: - MarketServer(); - ~MarketServer(); bool BanUser(const std::string &name); @@ -47,18 +47,22 @@ class MarketServer : public TcpServer { public: enum State { OPEN, + ASSIGNED, IN_PROGRESS, + PENDING, DONE }; - explicit Order(const std::string &customer, const std::string &description) - : customer(customer), description(description), task_id(task_counter++), state(OPEN) {} + explicit Order(std::string customer, std::string description) + : customer(std::move(customer)), + description(std::move(description)), + task_id(task_counter++), + state(OPEN) {} const int task_id; const std::string description; const std::string customer; State state; - std::mutex workers_mutex; std::set workers; private: @@ -74,10 +78,6 @@ class MarketServer : public TcpServer { std::shared_timed_mutex orders_mutex_; - Message ProcessStartDraw(); - - Message ProcessEndDraw(); - void StartWorkingWithClient(int sock_fd) override; void WorkWithFreelancer(Freelancer *freelancer); @@ -88,8 +88,6 @@ class MarketServer : public TcpServer { Message LookupOpenOrders(); - Message ProcessBet(Freelancer &player, std::string bet); - void DeleteCustomer(Customer *customer); void DeleteFreelancer(Freelancer *freelancer); diff --git a/tcp/server/src/market_server.cpp b/tcp/server/src/market_server.cpp index 7f977f5..a9c985f 100644 --- a/tcp/server/src/market_server.cpp +++ b/tcp/server/src/market_server.cpp @@ -68,6 +68,39 @@ void MarketServer::WorkWithFreelancer(Freelancer *freelancer) { int id = stoi(message.body); if (orders.count(id) and orders[id]->state == Order::OPEN) { orders[id]->workers.insert(freelancer->name); + ans_message.type = Message::TAKE_ORDER_SUCCESSFUL; + } else { + ans_message = Message(Message::TAKE_ORDER_NOT_SUCCESSFUL, "no such open order"); + } + orders_mutex_.unlock(); + break; + } + case Message::WORK_STARTED: { + orders_mutex_.lock(); + int id = stoi(message.body); + Order *o = orders[id]; + if (orders.count(id) and + o->state == Order::ASSIGNED and + o->workers.count(freelancer->name)) { + o->state = Order::IN_PROGRESS; + ans_message.type = Message::WORK_STARTED_SUCCESSFUL; + } else { + ans_message.type = Message::WORK_STARTED_NOT_SUCCESSFUL; + } + orders_mutex_.unlock(); + break; + } + case Message::WORK_FINISHED: { + orders_mutex_.lock(); + int id = stoi(message.body); + Order *o = orders[id]; + if (orders.count(id) and + o->state == Order::IN_PROGRESS and + o->workers.count(freelancer->name)) { + o->state = Order::PENDING; + ans_message.type = Message::WORK_FINISHED_SUCCESSFUL; + } else { + ans_message.type = Message::WORK_FINISHED_NOT_SUCCESSFUL; } orders_mutex_.unlock(); break; @@ -104,6 +137,41 @@ void MarketServer::WorkWithCustomer(Customer *customer) { ans_message = LookupOrdersOf(customer); break; } + case Message::GET_OPEN_ORDERS: { + ans_message = LookupOpenOrders(); + break; + } + case Message::GIVE_ORDER_TO_FREELANCER: { + int id; + char name[256]; + if (sscanf(message.body.c_str(), "%i %s", &id, name) == 2) { + orders_mutex_.lock(); + if (orders.count(id) and orders[id]->state == Order::OPEN) { + orders[id]->state = Order::ASSIGNED; + orders[id]->workers = {std::string(name)}; + ans_message.type = Message::GIVE_ORDER_SUCCESSFUL; + } else { + ans_message.type = Message::GIVE_ORDER_NOT_SUCCESSFUL; + ans_message.body = "no such open order"; + } + orders_mutex_.unlock(); + } else { + ans_message.type = Message::GIVE_ORDER_NOT_SUCCESSFUL; + } + break; + } + case Message::WORK_ACCEPTED: { + int id = std::stoi(message.body); + orders_mutex_.lock(); + if (orders.count(id) and orders[id]->state == Order::IN_PROGRESS) { + orders[id]->state = Order::DONE; + ans_message.type = Message::WORK_ACCEPTED_SUCCESSFUL; + } else { + ans_message.type = Message::WORK_ACCEPTED_NOT_SUCCESSFUL; + } + orders_mutex_.unlock(); + break; + } case Message::UNDEFINED: { DeleteCustomer(customer); std::cout << "Customer left\n"; @@ -127,7 +195,7 @@ Message MarketServer::LookupOpenOrders() { } } orders_mutex_.unlock_shared(); - return Message(Message::LIST_OF_MY_ORDERS, result); + return Message(Message::LIST_OF_OPEN_ORDERS, result); } void MarketServer::OrderToString(std::string &result, MarketServer::Order *o) { @@ -156,21 +224,15 @@ Message MarketServer::LookupOrdersOf(Customer *customer) { MarketServer::~MarketServer() { for (const auto &p : customers) { close(p.second->socket_fd); - delete p.second; } for (const auto &p : freelancers) { close(p.second->socket_fd); - delete p.second; } for (const auto &p : orders) { delete p.second; } } -MarketServer::MarketServer() { - srand(static_cast(time(nullptr))); -} - void MarketServer::DeleteCustomer(MarketServer::Customer *customer) { customers_mutex_.lock(); customers.erase(customer->name); @@ -237,6 +299,20 @@ MarketServer::Freelancer::Freelancer(const std::string &name, int socket_fd) : n }); } +MarketServer::Customer::Customer(const std::string &name, int socket_fd) : name(name), + socket_fd(socket_fd) { + writer = std::thread([this]() { + while (!messages_.closed()) { + try { + Message m = messages_.pull(); + m.Write(this->socket_fd); + } catch (boost::sync_queue_is_closed &) { + break; + } + } + }); +} + MarketServer::Freelancer::~Freelancer() { messages_.close(); close(socket_fd); From 5ec178a564e0865cc5aa7b9d9fbcc8ad05aeae9d Mon Sep 17 00:00:00 2001 From: oquechy Date: Tue, 19 Feb 2019 21:54:09 +0300 Subject: [PATCH 32/48] remove duplicate customer constructor --- tcp/server/src/market_server.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tcp/server/src/market_server.cpp b/tcp/server/src/market_server.cpp index a9c985f..b38c153 100644 --- a/tcp/server/src/market_server.cpp +++ b/tcp/server/src/market_server.cpp @@ -319,8 +319,6 @@ MarketServer::Freelancer::~Freelancer() { writer.join(); } -MarketServer::Customer::Customer(const std::string &name, int socket_fd) : name(name), socket_fd(socket_fd) {} - MarketServer::Customer::~Customer() { messages_.close(); close(socket_fd); From c25c415f6ad3369fdce45be4ae79ef9a5610dbcc Mon Sep 17 00:00:00 2001 From: andrey Date: Tue, 19 Feb 2019 22:16:40 +0300 Subject: [PATCH 33/48] some client bugs --- tcp/client/include/client.h | 2 +- tcp/client/src/client.cpp | 7 +++++-- tcp/client/src/main.cpp | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tcp/client/include/client.h b/tcp/client/include/client.h index 62c9f16..a60441f 100644 --- a/tcp/client/include/client.h +++ b/tcp/client/include/client.h @@ -47,7 +47,7 @@ class MarketClient { void FinishOrder(int order_id); - void GiveOrder(int order_id); + void GiveOrder(int order_id, const std::string& name); void ApproveDoneOrder(int order_id); diff --git a/tcp/client/src/client.cpp b/tcp/client/src/client.cpp index c3f5d2e..bba752a 100644 --- a/tcp/client/src/client.cpp +++ b/tcp/client/src/client.cpp @@ -152,6 +152,7 @@ void MarketClient::RequestOrder(int order_id) { return; case Message::TAKE_ORDER_NOT_SUCCESSFUL: Cout(response.body); + break; default: HandleResponse(response); return; @@ -191,14 +192,16 @@ void MarketClient::NewOrder(const std::string& description) { switch (response.type) { case Message::ORDER_ACCEPTED: Cout("You can now track this order by id: " + response.body); + break; default: HandleResponse(response); return; } } -void MarketClient::GiveOrder(int order_id) { - Message response = SendMessage(Message::GIVE_ORDER_TO_FREELANCER, std::to_string(order_id)); +void MarketClient::GiveOrder(int order_id, const std::string& name) { + Message response = SendMessage(Message::GIVE_ORDER_TO_FREELANCER, + std::to_string(order_id) + name); switch (response.type) { case Message::GIVE_ORDER_SUCCESSFUL: Cout("Order" + response.body + " given successfully."); diff --git a/tcp/client/src/main.cpp b/tcp/client/src/main.cpp index 329af49..1899ac7 100644 --- a/tcp/client/src/main.cpp +++ b/tcp/client/src/main.cpp @@ -73,8 +73,8 @@ void WorkWithCustomer(MarketClient& client) { client.ListOpenOrders(); } else if (line == "my orders") { client.ListMyOrders(); - } else if (sscanf(line.c_str(), "give %d", &order_id)) { - client.GiveOrder(order_id); + } else if (sscanf(line.c_str(), "give %d %s", &order_id, arg)) { + client.GiveOrder(order_id, arg); } else if (sscanf(line.c_str(), "done %d", &order_id)) { client.ApproveDoneOrder(order_id); } else if (sscanf(line.c_str(), "new order %s", arg)) { From 5d556ee2c32c6e5deb2a1f9b1fbd13b9fcc92351 Mon Sep 17 00:00:00 2001 From: andrey Date: Tue, 19 Feb 2019 22:26:11 +0300 Subject: [PATCH 34/48] fixed typo --- tcp/client/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcp/client/src/main.cpp b/tcp/client/src/main.cpp index 1899ac7..de3e6bc 100644 --- a/tcp/client/src/main.cpp +++ b/tcp/client/src/main.cpp @@ -48,7 +48,7 @@ void WorkWithFreelancer(MarketClient& client) { client.RequestOrder(order_id); } else if (sscanf(line.c_str(), "start %d", &order_id)) { client.StartOrder(order_id); - } else if (sscanf(line.c_str(), "start %d", &order_id)) { + } else if (sscanf(line.c_str(), "finish %d", &order_id)) { client.FinishOrder(order_id); } else if (line == "bye") { client.Quit(); From e6ffa96792f0ddd15f750237b6c2c02b60c5bc01 Mon Sep 17 00:00:00 2001 From: andrey Date: Tue, 19 Feb 2019 22:32:49 +0300 Subject: [PATCH 35/48] return for each switch --- tcp/client/src/client.cpp | 12 ++++++++---- tcp/server/src/tcp_server.cpp | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/tcp/client/src/client.cpp b/tcp/client/src/client.cpp index bba752a..4b2a059 100644 --- a/tcp/client/src/client.cpp +++ b/tcp/client/src/client.cpp @@ -152,7 +152,7 @@ void MarketClient::RequestOrder(int order_id) { return; case Message::TAKE_ORDER_NOT_SUCCESSFUL: Cout(response.body); - break; + return; default: HandleResponse(response); return; @@ -162,11 +162,12 @@ void MarketClient::RequestOrder(int order_id) { void MarketClient::StartOrder(int order_id) { Message response = SendMessage(Message::WORK_STARTED, std::to_string(order_id)); switch (response.type) { - case Message::WORK_STARTED: + case Message::WORK_STARTED_SUCCESSFUL: Cout("Order" + response.body + " started successfully."); return; - case Message::WORK_STARTED_SUCCESSFUL: + case Message::WORK_ACCEPTED_NOT_SUCCESSFUL: Cout(response.body); + return; default: HandleResponse(response); return; @@ -181,6 +182,7 @@ void MarketClient::FinishOrder(int order_id) { return; case Message::WORK_FINISHED_NOT_SUCCESSFUL: Cout(response.body); + return; default: HandleResponse(response); return; @@ -192,7 +194,7 @@ void MarketClient::NewOrder(const std::string& description) { switch (response.type) { case Message::ORDER_ACCEPTED: Cout("You can now track this order by id: " + response.body); - break; + return; default: HandleResponse(response); return; @@ -208,6 +210,7 @@ void MarketClient::GiveOrder(int order_id, const std::string& name) { return; case Message::GIVE_ORDER_NOT_SUCCESSFUL: Cout(response.body); + return; default: HandleResponse(response); return; @@ -222,6 +225,7 @@ void MarketClient::ApproveDoneOrder(int order_id) { return; case Message::WORK_ACCEPTED_NOT_SUCCESSFUL: Cout(response.body); + return; default: HandleResponse(response); return; diff --git a/tcp/server/src/tcp_server.cpp b/tcp/server/src/tcp_server.cpp index 6dd63b1..273fdb4 100644 --- a/tcp/server/src/tcp_server.cpp +++ b/tcp/server/src/tcp_server.cpp @@ -1,4 +1,5 @@ #include +#include #include "../include/tcp_server.h" void TcpServer::StartServer(uint16_t port_number) { From 7af41068404e7cdfc93a7e9b4cf5afe579ee69ff Mon Sep 17 00:00:00 2001 From: oquechy Date: Tue, 19 Feb 2019 22:37:01 +0300 Subject: [PATCH 36/48] check before give order --- tcp/server/src/market_server.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/tcp/server/src/market_server.cpp b/tcp/server/src/market_server.cpp index b38c153..b7d8e41 100644 --- a/tcp/server/src/market_server.cpp +++ b/tcp/server/src/market_server.cpp @@ -129,7 +129,7 @@ void MarketServer::WorkWithCustomer(Customer *customer) { orders_mutex_.lock(); auto *order = new Order(customer->name, message.body); orders[order->task_id] = order; - ans_message = Message(Message::ORDER_ACCEPTED); + ans_message = Message(Message::ORDER_ACCEPTED, std::to_string(order->task_id)); orders_mutex_.unlock_shared(); break; } @@ -146,28 +146,37 @@ void MarketServer::WorkWithCustomer(Customer *customer) { char name[256]; if (sscanf(message.body.c_str(), "%i %s", &id, name) == 2) { orders_mutex_.lock(); - if (orders.count(id) and orders[id]->state == Order::OPEN) { - orders[id]->state = Order::ASSIGNED; - orders[id]->workers = {std::string(name)}; + Order *o = orders[id]; + if (orders.count(id) and + o->state == Order::OPEN and + o->customer == customer->name and + o->workers.count(name)) { + o->state = Order::ASSIGNED; + o->workers = {std::string(name)}; ans_message.type = Message::GIVE_ORDER_SUCCESSFUL; } else { ans_message.type = Message::GIVE_ORDER_NOT_SUCCESSFUL; - ans_message.body = "no such open order"; + ans_message.body = "no such open order owned by you"; } orders_mutex_.unlock(); } else { ans_message.type = Message::GIVE_ORDER_NOT_SUCCESSFUL; + ans_message.body = "parsing error: expected got " + message.body; } break; } case Message::WORK_ACCEPTED: { int id = std::stoi(message.body); orders_mutex_.lock(); - if (orders.count(id) and orders[id]->state == Order::IN_PROGRESS) { - orders[id]->state = Order::DONE; + Order *o = orders[id]; + if (orders.count(id) and + o->state == Order::IN_PROGRESS and + o->customer == customer->name) { + o->state = Order::DONE; ans_message.type = Message::WORK_ACCEPTED_SUCCESSFUL; } else { ans_message.type = Message::WORK_ACCEPTED_NOT_SUCCESSFUL; + ans_message.body = "no such work in progress owned by you"; } orders_mutex_.unlock(); break; From 33e3f58627eb8e0d79ae2b8045a246d25bf00ff8 Mon Sep 17 00:00:00 2001 From: oquechy Date: Tue, 19 Feb 2019 22:59:40 +0300 Subject: [PATCH 37/48] clean up memory in message --- tcp/message/src/message.cpp | 2 ++ tcp/server/src/market_server.cpp | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tcp/message/src/message.cpp b/tcp/message/src/message.cpp index a068aeb..bfbfd41 100644 --- a/tcp/message/src/message.cpp +++ b/tcp/message/src/message.cpp @@ -27,6 +27,7 @@ bool Message::Write(int sockfd) { return false; } + delete[] data; return true; } @@ -64,6 +65,7 @@ bool Message::GetBody(std::string *body, size_t length, int sockfd) { *body = std::string(buf); return true; } + delete[] buf; return length != 0; } diff --git a/tcp/server/src/market_server.cpp b/tcp/server/src/market_server.cpp index b7d8e41..5785d61 100644 --- a/tcp/server/src/market_server.cpp +++ b/tcp/server/src/market_server.cpp @@ -9,7 +9,6 @@ int MarketServer::Order::task_counter = 0; void MarketServer::StartWorkingWithClient(int sock_fd) { - std::cout << "client accepted\n"; std::function workWithClient = nullptr; while (true) { Message message = Message::Read(sock_fd); @@ -40,7 +39,6 @@ void MarketServer::StartWorkingWithClient(int sock_fd) { } freelancers_mutex_.unlock(); } else { - std::cout << "unauthorized\n"; ans_type = Message::UNAUTHORIZED; } @@ -86,6 +84,7 @@ void MarketServer::WorkWithFreelancer(Freelancer *freelancer) { ans_message.type = Message::WORK_STARTED_SUCCESSFUL; } else { ans_message.type = Message::WORK_STARTED_NOT_SUCCESSFUL; + ans_message.body = "no such work assigned to you"; } orders_mutex_.unlock(); break; @@ -101,6 +100,7 @@ void MarketServer::WorkWithFreelancer(Freelancer *freelancer) { ans_message.type = Message::WORK_FINISHED_SUCCESSFUL; } else { ans_message.type = Message::WORK_FINISHED_NOT_SUCCESSFUL; + ans_message.body = "no such work in progress assigned to you"; } orders_mutex_.unlock(); break; @@ -170,7 +170,7 @@ void MarketServer::WorkWithCustomer(Customer *customer) { orders_mutex_.lock(); Order *o = orders[id]; if (orders.count(id) and - o->state == Order::IN_PROGRESS and + o->state == Order::PENDING and o->customer == customer->name) { o->state = Order::DONE; ans_message.type = Message::WORK_ACCEPTED_SUCCESSFUL; @@ -275,6 +275,10 @@ std::string MarketServer::StateToString(MarketServer::Order::State state) { return "IN_PROGRESS"; case Order::DONE: return "DONE"; + case Order::ASSIGNED: + return "ASSIGNED"; + case Order::PENDING: + return "PENDING"; } } From 2e3930a019ef2ee2c3b29bd1a50c0ae91ad98abb Mon Sep 17 00:00:00 2001 From: andrey Date: Tue, 19 Feb 2019 23:35:43 +0300 Subject: [PATCH 38/48] added delitions --- tcp/message/src/message.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tcp/message/src/message.cpp b/tcp/message/src/message.cpp index bfbfd41..b1027f4 100644 --- a/tcp/message/src/message.cpp +++ b/tcp/message/src/message.cpp @@ -24,6 +24,7 @@ bool Message::Write(int sockfd) { ssize_t written = ::write(sockfd, data, message_len); if (written < 0) { std::cerr << strerror(errno) << std::endl; + delete[] data; return false; } @@ -63,6 +64,7 @@ bool Message::GetBody(std::string *body, size_t length, int sockfd) { auto buf = new char[length]; if (Get(buf, length, sockfd)) { *body = std::string(buf); + delete[] buf; return true; } delete[] buf; From 4ed5632d9e71da701db4b49daf67c7badc7c7420 Mon Sep 17 00:00:00 2001 From: andrey Date: Tue, 19 Feb 2019 23:39:55 +0300 Subject: [PATCH 39/48] deleted queues --- tcp/client/include/client.h | 6 ------ tcp/client/src/client.cpp | 37 ++----------------------------------- 2 files changed, 2 insertions(+), 41 deletions(-) diff --git a/tcp/client/include/client.h b/tcp/client/include/client.h index a60441f..7210cf7 100644 --- a/tcp/client/include/client.h +++ b/tcp/client/include/client.h @@ -18,12 +18,6 @@ class MarketClient { int sockfd_; - boost::sync_queue requests_; - boost::sync_queue responses_; - - std::thread request_sender_; - std::thread response_receiver_; - std::mutex io_mutex_; Message SendMessage(Message::Type type); diff --git a/tcp/client/src/client.cpp b/tcp/client/src/client.cpp index 4b2a059..8c2d1c8 100644 --- a/tcp/client/src/client.cpp +++ b/tcp/client/src/client.cpp @@ -30,35 +30,6 @@ bool MarketClient::StartClient(const char* host, uint16_t port_number) { PrintHeader("AUTHORISATION"); - request_sender_ = std::thread([this]() { - while (!requests_.closed()) { - try { - Message m = requests_.pull(); - m.Write(sockfd_); - } catch (boost::sync_queue_is_closed &) { - break; - } - } - }); - - response_receiver_ = std::thread([this]() { - while (!responses_.closed()) { - try { - Message m = Message::Read(sockfd_); -// if (m.type == Message::DRAW_RESULTS) { -// int number, win; -// std::sscanf(m.body.c_str(), "%d %d", &number, &win); -// PrintHeader("DRAW ENDED\nWINNING NUMBER " + std::to_string(number) + -// "\nYOUR PROFIT " + std::to_string(win)); -// } else { - responses_.push(m); - //} - } catch (boost::sync_queue_is_closed &) { - break; - } - } - }); - return true; } @@ -235,10 +206,6 @@ void MarketClient::ApproveDoneOrder(int order_id) { void MarketClient::Quit() { Cout("Closing connection..."); shutdown(sockfd_, SHUT_RDWR); - requests_.close(); - responses_.close(); - request_sender_.join(); - response_receiver_.join(); Cout("Bye! Hope to see u again!"); } @@ -272,6 +239,6 @@ Message MarketClient::SendMessage(Message::Type type) { Message MarketClient::SendMessage(Message::Type type, const std::string& text) { Message request{type, text}; - requests_.push(request); - return responses_.pull(); + request.Write(sockfd_); + return Message::Read(sockfd_); } From 48a246000aa83650519f9fda01be8a3cdeb43a5f Mon Sep 17 00:00:00 2001 From: andrey Date: Tue, 19 Feb 2019 23:45:19 +0300 Subject: [PATCH 40/48] simpified output --- tcp/client/src/client.cpp | 60 ++++++++++++++++++--------------------- tcp/client/src/main.cpp | 2 +- 2 files changed, 29 insertions(+), 33 deletions(-) diff --git a/tcp/client/src/client.cpp b/tcp/client/src/client.cpp index 8c2d1c8..5d697ec 100644 --- a/tcp/client/src/client.cpp +++ b/tcp/client/src/client.cpp @@ -11,7 +11,7 @@ bool MarketClient::StartClient(const char* host, uint16_t port_number) { exit(1); } - hostent *server = gethostbyname(host); + hostent* server = gethostbyname(host); if (server == nullptr) { std::cerr << "host not found\n"; @@ -20,10 +20,11 @@ bool MarketClient::StartClient(const char* host, uint16_t port_number) { sockaddr_in serv_addr{0}; serv_addr.sin_family = AF_INET; - bcopy(server->h_addr, static_cast(&serv_addr.sin_addr.s_addr), static_cast(server->h_length)); + bcopy(server->h_addr, static_cast(&serv_addr.sin_addr.s_addr), + static_cast(server->h_length)); serv_addr.sin_port = htons(port_number); - if (connect(sockfd_, reinterpret_cast(&serv_addr), sizeof(serv_addr)) < 0) { + if (connect(sockfd_, reinterpret_cast(&serv_addr), sizeof(serv_addr)) < 0) { std::cerr << "connection failed\n"; exit(1); } @@ -37,10 +38,10 @@ bool MarketClient::AuthoriseCustomer(const std::string& name) { Message response = SendMessage(Message::NEW_CUSTOMER, name); switch (response.type) { case Message::CUSTOMER_ADDED: - Cout("Authorisation successful, you can create orders now, " + name); + std::cout << "Authorisation successful, you can create orders now, " + name; return true; case Message::CANT_ADD_CUSTOMER: - Cout(response.body.empty() ? "Sorry, something went wrong" : response.body); + std::cout << response.body.empty() ? "Sorry, something went wrong" : response.body; return false; default: HandleResponse(response); @@ -53,10 +54,10 @@ bool MarketClient::AuthoriseFreelancer(const std::string& name) { Message response = SendMessage(Message::NEW_FREELANCER, name); switch (response.type) { case Message::FREELANCER_ADDED: - Cout("You can look for orders now"); + std::cout << "You can look for orders now"; return true; case Message::CANT_ADD_FREELANCER: - Cout(response.body.empty() ? "Sorry, something went wrong" : response.body); + std::cout << response.body.empty() ? "Sorry, something went wrong" : response.body; return false; default: HandleResponse(response); @@ -68,7 +69,7 @@ void MarketClient::ListMyOrders() { Message response = SendMessage(Message::GET_MY_ORDERS); switch (response.type) { case Message::LIST_OF_MY_ORDERS: - Cout(response.body); + std::cout << response.body; return; default: HandleResponse(response); @@ -80,7 +81,7 @@ void MarketClient::ListOpenOrders() { Message response = SendMessage(Message::GET_OPEN_ORDERS); switch (response.type) { case Message::LIST_OF_OPEN_ORDERS: - Cout(response.body); + std::cout << response.body; return; default: HandleResponse(response); @@ -89,13 +90,14 @@ void MarketClient::ListOpenOrders() { } void MarketClient::HandleUnexpectedServerResponse(const Message& response) { - Cout("server responded with {type: " + std::to_string(response.type) + ", message: " + "}"); + std::cout << "server responded with {type: " + std::to_string(response.type) + ", message: " + + "}"; } -void MarketClient::HandleUnauthorised() { Cout("Please enter who u are"); } +void MarketClient::HandleUnauthorised() { std::cout << "Please enter who u are"; } void MarketClient::HandleIncorrectMessage(const Message& response) { - Cout(response.body.empty() ? "You are not permitted to do it" : response.body); + std::cout << response.body.empty() ? "You are not permitted to do it" : response.body; } void MarketClient::HandleResponse(const Message& response) { @@ -119,10 +121,10 @@ void MarketClient::RequestOrder(int order_id) { Message response = SendMessage(Message::TAKE_ORDER, std::to_string(order_id)); switch (response.type) { case Message::TAKE_ORDER_SUCCESSFUL: - Cout("Order" + response.body + " requested."); + std::cout << "Order" + response.body + " requested."; return; case Message::TAKE_ORDER_NOT_SUCCESSFUL: - Cout(response.body); + std::cout << response.body; return; default: HandleResponse(response); @@ -134,10 +136,10 @@ void MarketClient::StartOrder(int order_id) { Message response = SendMessage(Message::WORK_STARTED, std::to_string(order_id)); switch (response.type) { case Message::WORK_STARTED_SUCCESSFUL: - Cout("Order" + response.body + " started successfully."); + std::cout << "Order" + response.body + " started successfully."; return; case Message::WORK_ACCEPTED_NOT_SUCCESSFUL: - Cout(response.body); + std::cout << response.body; return; default: HandleResponse(response); @@ -149,10 +151,10 @@ void MarketClient::FinishOrder(int order_id) { Message response = SendMessage(Message::WORK_FINISHED, std::to_string(order_id)); switch (response.type) { case Message::WORK_FINISHED_SUCCESSFUL: - Cout("Order" + response.body + " finished successfully."); + std::cout << "Order" + response.body + " finished successfully."; return; case Message::WORK_FINISHED_NOT_SUCCESSFUL: - Cout(response.body); + std::cout << response.body; return; default: HandleResponse(response); @@ -164,7 +166,7 @@ void MarketClient::NewOrder(const std::string& description) { Message response = SendMessage(Message::NEW_ORDER, description); switch (response.type) { case Message::ORDER_ACCEPTED: - Cout("You can now track this order by id: " + response.body); + std::cout << "You can now track this order by id: " + response.body; return; default: HandleResponse(response); @@ -177,10 +179,10 @@ void MarketClient::GiveOrder(int order_id, const std::string& name) { std::to_string(order_id) + name); switch (response.type) { case Message::GIVE_ORDER_SUCCESSFUL: - Cout("Order" + response.body + " given successfully."); + std::cout << "Order" + response.body + " given successfully."; return; case Message::GIVE_ORDER_NOT_SUCCESSFUL: - Cout(response.body); + std::cout << response.body; return; default: HandleResponse(response); @@ -192,10 +194,10 @@ void MarketClient::ApproveDoneOrder(int order_id) { Message response = SendMessage(Message::WORK_ACCEPTED, std::to_string(order_id)); switch (response.type) { case Message::WORK_ACCEPTED_SUCCESSFUL: - Cout("Work for order" + response.body + " accepted successfully."); + std::cout << "Work for order" + response.body + " accepted successfully."; return; case Message::WORK_ACCEPTED_NOT_SUCCESSFUL: - Cout(response.body); + std::cout << response.body; return; default: HandleResponse(response); @@ -204,9 +206,9 @@ void MarketClient::ApproveDoneOrder(int order_id) { } void MarketClient::Quit() { - Cout("Closing connection..."); + std::cout << "Closing connection..."; shutdown(sockfd_, SHUT_RDWR); - Cout("Bye! Hope to see u again!"); + std::cout << "Bye! Hope to see u again!"; } void MarketClient::PrintHeader(const std::string& header) { @@ -222,14 +224,8 @@ void MarketClient::PrintPrompt() { io_mutex_.unlock(); } -void MarketClient::Cout(const std::string& message) { - io_mutex_.lock(); - std::cout << message << std::endl; - io_mutex_.unlock(); -} - bool MarketClient::GetLine(std::string& message) { - auto &result = getline(std::cin, message); + auto& result = getline(std::cin, message); return bool(result); } diff --git a/tcp/client/src/main.cpp b/tcp/client/src/main.cpp index de3e6bc..9798c5a 100644 --- a/tcp/client/src/main.cpp +++ b/tcp/client/src/main.cpp @@ -28,7 +28,7 @@ void CustomerHelp() { "\t new order \n" "\t all orders\n" "\t my orders\n" - "\t give \n" + "\t give \n" "\t done \n" "\t bye\n"; } From 5e502cc7f5d488551d0cbde3fb210bccdf3ef8cb Mon Sep 17 00:00:00 2001 From: andrey Date: Tue, 19 Feb 2019 23:47:52 +0300 Subject: [PATCH 41/48] removed boost --- tcp/client/CMakeLists.txt | 6 ++---- tcp/client/include/client.h | 12 +++--------- tcp/client/src/client.cpp | 5 ----- 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/tcp/client/CMakeLists.txt b/tcp/client/CMakeLists.txt index 819688d..680fef8 100644 --- a/tcp/client/CMakeLists.txt +++ b/tcp/client/CMakeLists.txt @@ -2,9 +2,7 @@ cmake_minimum_required(VERSION 3.13) project(client) set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -lboost_system -lboost_date_time -lboost_thread") - -find_package(Boost REQUIRED COMPONENTS thread) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") add_executable(client src/main.cpp src/client.cpp include/client.h) -target_link_libraries (client LINK_PUBLIC message ${Boost_LIBRARIES}) \ No newline at end of file +target_link_libraries(client LINK_PUBLIC message) \ No newline at end of file diff --git a/tcp/client/include/client.h b/tcp/client/include/client.h index 7210cf7..d114f69 100644 --- a/tcp/client/include/client.h +++ b/tcp/client/include/client.h @@ -1,12 +1,11 @@ -#ifndef ROULETTE_CLIENT_H -#define ROULETTE_CLIENT_H +#ifndef MARKET_CLIENT_H +#define MARKET_CLIENT_H #include #include #include #include -#include #include <../include/message.h> class MarketClient { @@ -18,8 +17,6 @@ class MarketClient { int sockfd_; - std::mutex io_mutex_; - Message SendMessage(Message::Type type); Message SendMessage(Message::Type type, const std::string& text); @@ -59,11 +56,8 @@ class MarketClient { void PrintPrompt(); - void Cout(const std::string &message); - bool GetLine(std::string &message); - }; -#endif //ROULETTE_CLIENT_H +#endif //MARKET_CLIENT_H diff --git a/tcp/client/src/client.cpp b/tcp/client/src/client.cpp index 5d697ec..4798926 100644 --- a/tcp/client/src/client.cpp +++ b/tcp/client/src/client.cpp @@ -1,6 +1,5 @@ #include #include -#include #include "../include/client.h" bool MarketClient::StartClient(const char* host, uint16_t port_number) { @@ -212,16 +211,12 @@ void MarketClient::Quit() { } void MarketClient::PrintHeader(const std::string& header) { - io_mutex_.lock(); system("clear"); std::cout << header + "\n> " << std::flush; - io_mutex_.unlock(); } void MarketClient::PrintPrompt() { - io_mutex_.lock(); std::cout << "> " << std::flush; - io_mutex_.unlock(); } bool MarketClient::GetLine(std::string& message) { From dda95bd57f1712cae0c25a5a8a63c5cba0170d01 Mon Sep 17 00:00:00 2001 From: andrey Date: Wed, 20 Feb 2019 00:56:33 +0300 Subject: [PATCH 42/48] added new lines --- tcp/client/src/client.cpp | 44 ++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/tcp/client/src/client.cpp b/tcp/client/src/client.cpp index 4798926..8bf4ccb 100644 --- a/tcp/client/src/client.cpp +++ b/tcp/client/src/client.cpp @@ -37,10 +37,11 @@ bool MarketClient::AuthoriseCustomer(const std::string& name) { Message response = SendMessage(Message::NEW_CUSTOMER, name); switch (response.type) { case Message::CUSTOMER_ADDED: - std::cout << "Authorisation successful, you can create orders now, " + name; + std::cout << "Authorisation successful, you can create orders now, " + name + "\n"; return true; case Message::CANT_ADD_CUSTOMER: - std::cout << response.body.empty() ? "Sorry, something went wrong" : response.body; + std::cout << response.body.empty() ? "Sorry, something went wrong" : response.body + + "\n"; return false; default: HandleResponse(response); @@ -53,10 +54,11 @@ bool MarketClient::AuthoriseFreelancer(const std::string& name) { Message response = SendMessage(Message::NEW_FREELANCER, name); switch (response.type) { case Message::FREELANCER_ADDED: - std::cout << "You can look for orders now"; + std::cout << "You can look for orders now\n"; return true; case Message::CANT_ADD_FREELANCER: - std::cout << response.body.empty() ? "Sorry, something went wrong" : response.body; + std::cout << response.body.empty() ? "Sorry, something went wrong\n" : response.body + + "\n"; return false; default: HandleResponse(response); @@ -68,7 +70,7 @@ void MarketClient::ListMyOrders() { Message response = SendMessage(Message::GET_MY_ORDERS); switch (response.type) { case Message::LIST_OF_MY_ORDERS: - std::cout << response.body; + std::cout << response.body << "\n"; return; default: HandleResponse(response); @@ -80,7 +82,7 @@ void MarketClient::ListOpenOrders() { Message response = SendMessage(Message::GET_OPEN_ORDERS); switch (response.type) { case Message::LIST_OF_OPEN_ORDERS: - std::cout << response.body; + std::cout << response.body << "\n"; return; default: HandleResponse(response); @@ -90,13 +92,13 @@ void MarketClient::ListOpenOrders() { void MarketClient::HandleUnexpectedServerResponse(const Message& response) { std::cout << "server responded with {type: " + std::to_string(response.type) + ", message: " + - "}"; + "}\n"; } -void MarketClient::HandleUnauthorised() { std::cout << "Please enter who u are"; } +void MarketClient::HandleUnauthorised() { std::cout << "Please enter who u are\n"; } void MarketClient::HandleIncorrectMessage(const Message& response) { - std::cout << response.body.empty() ? "You are not permitted to do it" : response.body; + std::cout << response.body.empty() ? "You are not permitted to do it" : response.body + "\n"; } void MarketClient::HandleResponse(const Message& response) { @@ -120,10 +122,10 @@ void MarketClient::RequestOrder(int order_id) { Message response = SendMessage(Message::TAKE_ORDER, std::to_string(order_id)); switch (response.type) { case Message::TAKE_ORDER_SUCCESSFUL: - std::cout << "Order" + response.body + " requested."; + std::cout << "Order" + response.body + " requested.\n"; return; case Message::TAKE_ORDER_NOT_SUCCESSFUL: - std::cout << response.body; + std::cout << response.body << "\n"; return; default: HandleResponse(response); @@ -135,10 +137,10 @@ void MarketClient::StartOrder(int order_id) { Message response = SendMessage(Message::WORK_STARTED, std::to_string(order_id)); switch (response.type) { case Message::WORK_STARTED_SUCCESSFUL: - std::cout << "Order" + response.body + " started successfully."; + std::cout << "Order" + response.body + " started successfully.\n"; return; case Message::WORK_ACCEPTED_NOT_SUCCESSFUL: - std::cout << response.body; + std::cout << response.body << "\n"; return; default: HandleResponse(response); @@ -150,10 +152,10 @@ void MarketClient::FinishOrder(int order_id) { Message response = SendMessage(Message::WORK_FINISHED, std::to_string(order_id)); switch (response.type) { case Message::WORK_FINISHED_SUCCESSFUL: - std::cout << "Order" + response.body + " finished successfully."; + std::cout << "Order" + response.body + " finished successfully.\n"; return; case Message::WORK_FINISHED_NOT_SUCCESSFUL: - std::cout << response.body; + std::cout << response.body << "\n"; return; default: HandleResponse(response); @@ -165,7 +167,7 @@ void MarketClient::NewOrder(const std::string& description) { Message response = SendMessage(Message::NEW_ORDER, description); switch (response.type) { case Message::ORDER_ACCEPTED: - std::cout << "You can now track this order by id: " + response.body; + std::cout << "You can now track this order by id: " + response.body + "\n"; return; default: HandleResponse(response); @@ -178,10 +180,10 @@ void MarketClient::GiveOrder(int order_id, const std::string& name) { std::to_string(order_id) + name); switch (response.type) { case Message::GIVE_ORDER_SUCCESSFUL: - std::cout << "Order" + response.body + " given successfully."; + std::cout << "Order" + response.body + " given successfully.\n"; return; case Message::GIVE_ORDER_NOT_SUCCESSFUL: - std::cout << response.body; + std::cout << response.body << "\n"; return; default: HandleResponse(response); @@ -193,10 +195,10 @@ void MarketClient::ApproveDoneOrder(int order_id) { Message response = SendMessage(Message::WORK_ACCEPTED, std::to_string(order_id)); switch (response.type) { case Message::WORK_ACCEPTED_SUCCESSFUL: - std::cout << "Work for order" + response.body + " accepted successfully."; + std::cout << "Work for order" + response.body + " accepted successfully.\n"; return; case Message::WORK_ACCEPTED_NOT_SUCCESSFUL: - std::cout << response.body; + std::cout << response.body << "\n"; return; default: HandleResponse(response); @@ -205,7 +207,7 @@ void MarketClient::ApproveDoneOrder(int order_id) { } void MarketClient::Quit() { - std::cout << "Closing connection..."; + std::cout << "Closing connection...\n"; shutdown(sockfd_, SHUT_RDWR); std::cout << "Bye! Hope to see u again!"; } From c5cdd385d5b2a2a153e977ec007b4d547986ee94 Mon Sep 17 00:00:00 2001 From: oquechy Date: Wed, 20 Feb 2019 02:42:05 +0300 Subject: [PATCH 43/48] fixed access to orders map on server --- tcp/server/src/market_server.cpp | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/tcp/server/src/market_server.cpp b/tcp/server/src/market_server.cpp index 5785d61..7871418 100644 --- a/tcp/server/src/market_server.cpp +++ b/tcp/server/src/market_server.cpp @@ -76,11 +76,10 @@ void MarketServer::WorkWithFreelancer(Freelancer *freelancer) { case Message::WORK_STARTED: { orders_mutex_.lock(); int id = stoi(message.body); - Order *o = orders[id]; if (orders.count(id) and - o->state == Order::ASSIGNED and - o->workers.count(freelancer->name)) { - o->state = Order::IN_PROGRESS; + orders[id]->state == Order::ASSIGNED and + orders[id]->workers.count(freelancer->name)) { + orders[id]->state = Order::IN_PROGRESS; ans_message.type = Message::WORK_STARTED_SUCCESSFUL; } else { ans_message.type = Message::WORK_STARTED_NOT_SUCCESSFUL; @@ -92,11 +91,10 @@ void MarketServer::WorkWithFreelancer(Freelancer *freelancer) { case Message::WORK_FINISHED: { orders_mutex_.lock(); int id = stoi(message.body); - Order *o = orders[id]; if (orders.count(id) and - o->state == Order::IN_PROGRESS and - o->workers.count(freelancer->name)) { - o->state = Order::PENDING; + orders[id]->state == Order::IN_PROGRESS and + orders[id]->workers.count(freelancer->name)) { + orders[id]->state = Order::PENDING; ans_message.type = Message::WORK_FINISHED_SUCCESSFUL; } else { ans_message.type = Message::WORK_FINISHED_NOT_SUCCESSFUL; @@ -146,13 +144,12 @@ void MarketServer::WorkWithCustomer(Customer *customer) { char name[256]; if (sscanf(message.body.c_str(), "%i %s", &id, name) == 2) { orders_mutex_.lock(); - Order *o = orders[id]; if (orders.count(id) and - o->state == Order::OPEN and - o->customer == customer->name and - o->workers.count(name)) { - o->state = Order::ASSIGNED; - o->workers = {std::string(name)}; + orders[id]->state == Order::OPEN and + orders[id]->customer == customer->name and + orders[id]->workers.count(name)) { + orders[id]->state = Order::ASSIGNED; + orders[id]->workers = {std::string(name)}; ans_message.type = Message::GIVE_ORDER_SUCCESSFUL; } else { ans_message.type = Message::GIVE_ORDER_NOT_SUCCESSFUL; @@ -168,11 +165,10 @@ void MarketServer::WorkWithCustomer(Customer *customer) { case Message::WORK_ACCEPTED: { int id = std::stoi(message.body); orders_mutex_.lock(); - Order *o = orders[id]; if (orders.count(id) and - o->state == Order::PENDING and - o->customer == customer->name) { - o->state = Order::DONE; + orders[id]->state == Order::PENDING and + orders[id]->customer == customer->name) { + orders[id]->state = Order::DONE; ans_message.type = Message::WORK_ACCEPTED_SUCCESSFUL; } else { ans_message.type = Message::WORK_ACCEPTED_NOT_SUCCESSFUL; From 1d2cb86bfe915feded7daf72acac9cc83e52b517 Mon Sep 17 00:00:00 2001 From: andrey Date: Wed, 20 Feb 2019 11:07:09 +0300 Subject: [PATCH 44/48] fixed incorrect case --- tcp/client/src/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tcp/client/src/client.cpp b/tcp/client/src/client.cpp index 8bf4ccb..1343087 100644 --- a/tcp/client/src/client.cpp +++ b/tcp/client/src/client.cpp @@ -139,7 +139,7 @@ void MarketClient::StartOrder(int order_id) { case Message::WORK_STARTED_SUCCESSFUL: std::cout << "Order" + response.body + " started successfully.\n"; return; - case Message::WORK_ACCEPTED_NOT_SUCCESSFUL: + case Message::WORK_STARTED_NOT_SUCCESSFUL: std::cout << response.body << "\n"; return; default: From b24545a8ddf1eb0538d6b9bd8e5e9b88607f4bc7 Mon Sep 17 00:00:00 2001 From: oquechy Date: Sat, 23 Mar 2019 23:42:04 +0300 Subject: [PATCH 45/48] fix CMakeLists and README --- README.md | 4 ++++ tcp/CMakeLists.txt | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 55b8346..043b75d 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ ## Формат сообщений +Для передачи численных значений используется тип `uint32_t`, далее обозначаемый как `int`. Порядок байт big endian, что контролируется функцией `htons`. + +--------------------+--------------------+-------------+ | int message type | int body length | char[] body | +--------------------+--------------------+-------------+ @@ -21,6 +23,8 @@ type: 200 body: "Name" +Следующие команды доступны только после авторизации пользователя с помощью одной из двух предыдущих команд. + - Добавление заказа от заказчика type: 300 diff --git a/tcp/CMakeLists.txt b/tcp/CMakeLists.txt index d7fc155..fff93cc 100644 --- a/tcp/CMakeLists.txt +++ b/tcp/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13) project(market) set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") +find_package(Threads REQUIRED) add_subdirectory (client) add_subdirectory (message) From 8e919643b5b41a8a8458694b96d3bcc988bcaa68 Mon Sep 17 00:00:00 2001 From: oquechy Date: Sat, 23 Mar 2019 23:44:39 +0300 Subject: [PATCH 46/48] fix boost linking in CMakeLists --- tcp/client/CMakeLists.txt | 2 +- tcp/server/CMakeLists.txt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tcp/client/CMakeLists.txt b/tcp/client/CMakeLists.txt index 680fef8..7d60e59 100644 --- a/tcp/client/CMakeLists.txt +++ b/tcp/client/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13) project(client) set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") +find_package(Boost REQUIRED COMPONENTS thread) add_executable(client src/main.cpp src/client.cpp include/client.h) target_link_libraries(client LINK_PUBLIC message) \ No newline at end of file diff --git a/tcp/server/CMakeLists.txt b/tcp/server/CMakeLists.txt index f6729c3..a873e4a 100644 --- a/tcp/server/CMakeLists.txt +++ b/tcp/server/CMakeLists.txt @@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 3.13) project(server) set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -lboost_system -lboost_date_time -lboost_thread") find_package(Boost REQUIRED COMPONENTS thread) From 34e5893db014f158ed0b802ba7bc2dd019c73b08 Mon Sep 17 00:00:00 2001 From: oquechy Date: Wed, 27 Mar 2019 00:56:43 +0300 Subject: [PATCH 47/48] remove multiple while loops --- tcp/server/include/market_server.h | 17 +- tcp/server/include/tcp_server.h | 6 +- tcp/server/src/market_server.cpp | 324 +++++++++++++++-------------- tcp/server/src/tcp_server.cpp | 2 +- 4 files changed, 189 insertions(+), 160 deletions(-) diff --git a/tcp/server/include/market_server.h b/tcp/server/include/market_server.h index 4281c6f..b625cc7 100644 --- a/tcp/server/include/market_server.h +++ b/tcp/server/include/market_server.h @@ -43,6 +43,14 @@ class MarketServer : public TcpServer { boost::sync_queue messages_; }; + enum ClientStatus { + NEW, + FREELANCER, + CUSTOMER, + FINISH, + UNCHANGED + }; + class Order { public: enum State { @@ -78,11 +86,14 @@ class MarketServer : public TcpServer { std::shared_timed_mutex orders_mutex_; - void StartWorkingWithClient(int sock_fd) override; + void UserInteractionLoop(int sock_fd) override; + + MarketServer::ClientStatus + WorkWithUnauthorized(int sock_fd, const Message &message, Freelancer **freelancer, Customer **customer); - void WorkWithFreelancer(Freelancer *freelancer); + MarketServer::ClientStatus WorkWithFreelancer(Freelancer *freelancer, const Message &message); - void WorkWithCustomer(Customer *customer); + MarketServer::ClientStatus WorkWithCustomer(Customer *customer, const Message &message); Message LookupOrdersOf(Customer *customer); diff --git a/tcp/server/include/tcp_server.h b/tcp/server/include/tcp_server.h index 04caeb0..726d732 100644 --- a/tcp/server/include/tcp_server.h +++ b/tcp/server/include/tcp_server.h @@ -4,13 +4,17 @@ #include #include +#include class TcpServer { public: void StartServer(uint16_t port_number); + protected: + std::vector threads_; + private: - virtual void StartWorkingWithClient(int sock_fd) = 0; + virtual void UserInteractionLoop(int sock_fd) = 0; }; diff --git a/tcp/server/src/market_server.cpp b/tcp/server/src/market_server.cpp index 7871418..874c261 100644 --- a/tcp/server/src/market_server.cpp +++ b/tcp/server/src/market_server.cpp @@ -8,187 +8,201 @@ int MarketServer::Order::task_counter = 0; -void MarketServer::StartWorkingWithClient(int sock_fd) { - std::function workWithClient = nullptr; - while (true) { +void MarketServer::UserInteractionLoop(int sock_fd) { + ClientStatus status = ClientStatus::NEW; + Freelancer *freelancer; + Customer *customer; + while (status != ClientStatus::FINISH) { Message message = Message::Read(sock_fd); - Message::Type ans_type; - std::string &name = message.body; - if (Message::NEW_CUSTOMER == message.type) { - customers_mutex_.lock(); - if (customers.count(name) == 0 and freelancers.count(name) == 0) { - auto *customer = new Customer(name, sock_fd); - customers[name] = customer; - workWithClient = std::bind(&MarketServer::WorkWithCustomer, this, customer); - ans_type = Message::CUSTOMER_ADDED; - std::cout << "New customer\n"; - } else { - ans_type = Message::CANT_ADD_CUSTOMER; - } - customers_mutex_.unlock(); - } else if (Message::NEW_FREELANCER == message.type) { - freelancers_mutex_.lock(); - if (freelancers.count(name) == 0 and customers.count(name) == 0) { - auto *freelancer = new Freelancer(name, sock_fd); - freelancers[name] = freelancer; - workWithClient = std::bind(&MarketServer::WorkWithFreelancer, this, freelancer); - ans_type = Message::FREELANCER_ADDED; - std::cout << "New freelancer\n"; - } else { - ans_type = Message::CANT_ADD_FREELANCER; - } - freelancers_mutex_.unlock(); - } else { - ans_type = Message::UNAUTHORIZED; + ClientStatus request_status; + if (status == ClientStatus::NEW) { + request_status = WorkWithUnauthorized(sock_fd, message, &freelancer, &customer); + } else if (status == ClientStatus::FREELANCER) { + request_status = WorkWithFreelancer(freelancer, message); + } else if (status == ClientStatus::CUSTOMER) { + request_status = WorkWithCustomer(customer, message); } - Message ans_message(ans_type); - ans_message.Write(sock_fd); + if (request_status != UNCHANGED) { + status = request_status; + } + } +} - if (workWithClient != nullptr) { - break; +MarketServer::ClientStatus +MarketServer::WorkWithUnauthorized(int sock_fd, const Message &message, Freelancer **freelancer, Customer **customer) { + Message::Type ans_type; + const std::string &name = message.body; + ClientStatus status = ClientStatus::NEW; + if (Message::NEW_CUSTOMER == message.type) { + customers_mutex_.lock(); + if (customers.count(name) == 0 and freelancers.count(name) == 0) { + *customer = new Customer(name, sock_fd); + customers[name] = *customer; + ans_type = Message::CUSTOMER_ADDED; + std::cout << "New customer\n"; + status = ClientStatus::CUSTOMER; + } else { + ans_type = Message::CANT_ADD_CUSTOMER; } + customers_mutex_.unlock(); + } else if (Message::NEW_FREELANCER == message.type) { + freelancers_mutex_.lock(); + if (freelancers.count(name) == 0 and customers.count(name) == 0) { + *freelancer = new Freelancer(name, sock_fd); + freelancers[name] = *freelancer; + ans_type = Message::FREELANCER_ADDED; + std::cout << "New freelancer\n"; + status = ClientStatus::FREELANCER; + } else { + ans_type = Message::CANT_ADD_FREELANCER; + } + freelancers_mutex_.unlock(); + } else if (Message::UNDEFINED == message.type) { + close(sock_fd); + return ClientStatus::FINISH; + } else { + ans_type = Message::UNAUTHORIZED; } - workWithClient(); + + Message ans_message(ans_type); + ans_message.Write(sock_fd); + return status; } -void MarketServer::WorkWithFreelancer(Freelancer *freelancer) { - while (true) { - Message message = Message::Read(freelancer->socket_fd); - Message ans_message; - switch (message.type) { - case Message::GET_OPEN_ORDERS: { - ans_message = LookupOpenOrders(); - break; - } - case Message::TAKE_ORDER: { - orders_mutex_.lock(); - int id = stoi(message.body); - if (orders.count(id) and orders[id]->state == Order::OPEN) { - orders[id]->workers.insert(freelancer->name); - ans_message.type = Message::TAKE_ORDER_SUCCESSFUL; - } else { - ans_message = Message(Message::TAKE_ORDER_NOT_SUCCESSFUL, "no such open order"); - } - orders_mutex_.unlock(); - break; - } - case Message::WORK_STARTED: { - orders_mutex_.lock(); - int id = stoi(message.body); - if (orders.count(id) and - orders[id]->state == Order::ASSIGNED and - orders[id]->workers.count(freelancer->name)) { - orders[id]->state = Order::IN_PROGRESS; - ans_message.type = Message::WORK_STARTED_SUCCESSFUL; - } else { - ans_message.type = Message::WORK_STARTED_NOT_SUCCESSFUL; - ans_message.body = "no such work assigned to you"; - } - orders_mutex_.unlock(); - break; - } - case Message::WORK_FINISHED: { - orders_mutex_.lock(); - int id = stoi(message.body); - if (orders.count(id) and - orders[id]->state == Order::IN_PROGRESS and - orders[id]->workers.count(freelancer->name)) { - orders[id]->state = Order::PENDING; - ans_message.type = Message::WORK_FINISHED_SUCCESSFUL; - } else { - ans_message.type = Message::WORK_FINISHED_NOT_SUCCESSFUL; - ans_message.body = "no such work in progress assigned to you"; - } - orders_mutex_.unlock(); - break; +MarketServer::ClientStatus MarketServer::WorkWithFreelancer(Freelancer *freelancer, const Message &message) { + Message ans_message; + switch (message.type) { + case Message::GET_OPEN_ORDERS: { + ans_message = LookupOpenOrders(); + break; + } + case Message::TAKE_ORDER: { + orders_mutex_.lock(); + int id = stoi(message.body); + if (orders.count(id) and orders[id]->state == Order::OPEN) { + orders[id]->workers.insert(freelancer->name); + ans_message.type = Message::TAKE_ORDER_SUCCESSFUL; + } else { + ans_message = Message(Message::TAKE_ORDER_NOT_SUCCESSFUL, "no such open order"); } - case Message::UNDEFINED: { - DeleteFreelancer(freelancer); - std::cout << "Freelancer left\n"; - return; + orders_mutex_.unlock(); + break; + } + case Message::WORK_STARTED: { + orders_mutex_.lock(); + int id = stoi(message.body); + if (orders.count(id) and + orders[id]->state == Order::ASSIGNED and + orders[id]->workers.count(freelancer->name)) { + orders[id]->state = Order::IN_PROGRESS; + ans_message.type = Message::WORK_STARTED_SUCCESSFUL; + } else { + ans_message.type = Message::WORK_STARTED_NOT_SUCCESSFUL; + ans_message.body = "no such work assigned to you"; } - - default: { - ans_message = Message(Message::INCORRECT_MESSAGE); + orders_mutex_.unlock(); + break; + } + case Message::WORK_FINISHED: { + orders_mutex_.lock(); + int id = stoi(message.body); + if (orders.count(id) and + orders[id]->state == Order::IN_PROGRESS and + orders[id]->workers.count(freelancer->name)) { + orders[id]->state = Order::PENDING; + ans_message.type = Message::WORK_FINISHED_SUCCESSFUL; + } else { + ans_message.type = Message::WORK_FINISHED_NOT_SUCCESSFUL; + ans_message.body = "no such work in progress assigned to you"; } + orders_mutex_.unlock(); + break; + } + case Message::UNDEFINED: { + DeleteFreelancer(freelancer); + std::cout << "Freelancer left\n"; + return FINISH; + } + default: { + ans_message = Message(Message::INCORRECT_MESSAGE); } - freelancer->messages_.push(ans_message); + } + freelancer->messages_.push(ans_message); + return UNCHANGED; } -void MarketServer::WorkWithCustomer(Customer *customer) { - while (true) { - Message message = Message::Read(customer->socket_fd); - Message ans_message; - switch (message.type) { - case Message::NEW_ORDER: { - orders_mutex_.lock(); - auto *order = new Order(customer->name, message.body); - orders[order->task_id] = order; - ans_message = Message(Message::ORDER_ACCEPTED, std::to_string(order->task_id)); - orders_mutex_.unlock_shared(); - break; - } - case Message::GET_MY_ORDERS: { - ans_message = LookupOrdersOf(customer); - break; - } - case Message::GET_OPEN_ORDERS: { - ans_message = LookupOpenOrders(); - break; - } - case Message::GIVE_ORDER_TO_FREELANCER: { - int id; - char name[256]; - if (sscanf(message.body.c_str(), "%i %s", &id, name) == 2) { - orders_mutex_.lock(); - if (orders.count(id) and - orders[id]->state == Order::OPEN and - orders[id]->customer == customer->name and - orders[id]->workers.count(name)) { - orders[id]->state = Order::ASSIGNED; - orders[id]->workers = {std::string(name)}; - ans_message.type = Message::GIVE_ORDER_SUCCESSFUL; - } else { - ans_message.type = Message::GIVE_ORDER_NOT_SUCCESSFUL; - ans_message.body = "no such open order owned by you"; - } - orders_mutex_.unlock(); - } else { - ans_message.type = Message::GIVE_ORDER_NOT_SUCCESSFUL; - ans_message.body = "parsing error: expected got " + message.body; - } - break; - } - case Message::WORK_ACCEPTED: { - int id = std::stoi(message.body); +MarketServer::ClientStatus MarketServer::WorkWithCustomer(Customer *customer, const Message &message) { + Message ans_message; + switch (message.type) { + case Message::NEW_ORDER: { + orders_mutex_.lock(); + auto *order = new Order(customer->name, message.body); + orders[order->task_id] = order; + ans_message = Message(Message::ORDER_ACCEPTED, std::to_string(order->task_id)); + orders_mutex_.unlock_shared(); + break; + } + case Message::GET_MY_ORDERS: { + ans_message = LookupOrdersOf(customer); + break; + } + case Message::GET_OPEN_ORDERS: { + ans_message = LookupOpenOrders(); + break; + } + case Message::GIVE_ORDER_TO_FREELANCER: { + int id; + char name[256]; + if (sscanf(message.body.c_str(), "%i %s", &id, name) == 2) { orders_mutex_.lock(); if (orders.count(id) and - orders[id]->state == Order::PENDING and - orders[id]->customer == customer->name) { - orders[id]->state = Order::DONE; - ans_message.type = Message::WORK_ACCEPTED_SUCCESSFUL; + orders[id]->state == Order::OPEN and + orders[id]->customer == customer->name and + orders[id]->workers.count(name)) { + orders[id]->state = Order::ASSIGNED; + orders[id]->workers = {std::string(name)}; + ans_message.type = Message::GIVE_ORDER_SUCCESSFUL; } else { - ans_message.type = Message::WORK_ACCEPTED_NOT_SUCCESSFUL; - ans_message.body = "no such work in progress owned by you"; + ans_message.type = Message::GIVE_ORDER_NOT_SUCCESSFUL; + ans_message.body = "no such open order owned by you"; } orders_mutex_.unlock(); - break; + } else { + ans_message.type = Message::GIVE_ORDER_NOT_SUCCESSFUL; + ans_message.body = "parsing error: expected got " + message.body; } - case Message::UNDEFINED: { - DeleteCustomer(customer); - std::cout << "Customer left\n"; - return; + break; + } + case Message::WORK_ACCEPTED: { + int id = std::stoi(message.body); + orders_mutex_.lock(); + if (orders.count(id) and + orders[id]->state == Order::PENDING and + orders[id]->customer == customer->name) { + orders[id]->state = Order::DONE; + ans_message.type = Message::WORK_ACCEPTED_SUCCESSFUL; + } else { + ans_message.type = Message::WORK_ACCEPTED_NOT_SUCCESSFUL; + ans_message.body = "no such work in progress owned by you"; } + orders_mutex_.unlock(); + break; + } + case Message::UNDEFINED: { + DeleteCustomer(customer); + std::cout << "Customer left\n"; + return FINISH; + } - default: { - ans_message = Message(Message::INCORRECT_MESSAGE); - } + default: { + ans_message = Message(Message::INCORRECT_MESSAGE); } - customer->messages_.push(ans_message); } + customer->messages_.push(ans_message); + return UNCHANGED; } Message MarketServer::LookupOpenOrders() { diff --git a/tcp/server/src/tcp_server.cpp b/tcp/server/src/tcp_server.cpp index 273fdb4..489a3fc 100644 --- a/tcp/server/src/tcp_server.cpp +++ b/tcp/server/src/tcp_server.cpp @@ -33,7 +33,7 @@ void TcpServer::StartServer(uint16_t port_number) { exit(1); } - std::thread thread(&TcpServer::StartWorkingWithClient, this, new_socket_fd); + std::thread thread(&TcpServer::UserInteractionLoop, this, new_socket_fd); thread.detach(); } } From 0f3fd15f9bff997e87602eed2b95a1ff9cc2931c Mon Sep 17 00:00:00 2001 From: oquechy Date: Wed, 27 Mar 2019 01:09:17 +0300 Subject: [PATCH 48/48] use std::lock_guard instead of direct locking --- tcp/server/src/market_server.cpp | 39 ++++++++++++++------------------ 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/tcp/server/src/market_server.cpp b/tcp/server/src/market_server.cpp index 874c261..87c8809 100644 --- a/tcp/server/src/market_server.cpp +++ b/tcp/server/src/market_server.cpp @@ -35,7 +35,7 @@ MarketServer::WorkWithUnauthorized(int sock_fd, const Message &message, Freelanc const std::string &name = message.body; ClientStatus status = ClientStatus::NEW; if (Message::NEW_CUSTOMER == message.type) { - customers_mutex_.lock(); + std::lock_guard customers_lock(customers_mutex_); if (customers.count(name) == 0 and freelancers.count(name) == 0) { *customer = new Customer(name, sock_fd); customers[name] = *customer; @@ -45,9 +45,8 @@ MarketServer::WorkWithUnauthorized(int sock_fd, const Message &message, Freelanc } else { ans_type = Message::CANT_ADD_CUSTOMER; } - customers_mutex_.unlock(); } else if (Message::NEW_FREELANCER == message.type) { - freelancers_mutex_.lock(); + std::lock_guard freelancers_lock(freelancers_mutex_); if (freelancers.count(name) == 0 and customers.count(name) == 0) { *freelancer = new Freelancer(name, sock_fd); freelancers[name] = *freelancer; @@ -57,7 +56,6 @@ MarketServer::WorkWithUnauthorized(int sock_fd, const Message &message, Freelanc } else { ans_type = Message::CANT_ADD_FREELANCER; } - freelancers_mutex_.unlock(); } else if (Message::UNDEFINED == message.type) { close(sock_fd); return ClientStatus::FINISH; @@ -253,27 +251,27 @@ MarketServer::~MarketServer() { } void MarketServer::DeleteCustomer(MarketServer::Customer *customer) { - customers_mutex_.lock(); + std::lock_guard customers_lock(customers_mutex_); customers.erase(customer->name); - customers_mutex_.unlock(); - delete customer; } bool MarketServer::BanUser(const std::string &name) { bool result = false; - freelancers_mutex_.lock(); - if (freelancers.count(name)) { - DeleteFreelancer(freelancers[name]); - result = true; + { + std::lock_guard freelancers_lock(freelancers_mutex_); + if (freelancers.count(name)) { + DeleteFreelancer(freelancers[name]); + result = true; + } } - freelancers_mutex_.unlock(); - customers_mutex_.lock(); - if (customers.count(name)) { - DeleteCustomer(customers[name]); - result = true; + { + std::lock_guard customers_lock(customers_mutex_); + if (customers.count(name)) { + DeleteCustomer(customers[name]); + result = true; + } } - customers_mutex_.unlock(); return result; } @@ -300,12 +298,9 @@ std::string MarketServer::WorkersToString(std::set set) { } void MarketServer::DeleteFreelancer(MarketServer::Freelancer *freelancer) { - freelancers_mutex_.lock(); - customers.erase(freelancer->name); - freelancers_mutex_.unlock(); - + std::lock_guard freelancers_lock(freelancers_mutex_); + freelancers.erase(freelancer->name); delete freelancer; - } MarketServer::Freelancer::Freelancer(const std::string &name, int socket_fd) : name(name),