From e559aa44b9145e9f6de77fa199fc4f99cf2e4d3b Mon Sep 17 00:00:00 2001 From: theguydie Date: Fri, 25 Oct 2024 14:30:28 +0300 Subject: [PATCH 01/13] entity definition: Deamon Logger Config --- AsanovDamir/.gitignore | 1 + AsanovDamir/CMakeLists.txt | 7 +++++++ AsanovDamir/Config.cpp | 7 +++++++ AsanovDamir/Config.hpp | 9 +++++++++ AsanovDamir/Deamon.cpp | 14 ++++++++++++++ AsanovDamir/Deamon.hpp | 13 +++++++++++++ AsanovDamir/Logger.hpp | 18 ++++++++++++++++++ AsanovDamir/build.sh | 5 +++++ AsanovDamir/main.cpp | 6 ++++++ AsanovDamir/run.sh | 1 + 10 files changed, 81 insertions(+) create mode 100644 AsanovDamir/.gitignore create mode 100644 AsanovDamir/CMakeLists.txt create mode 100644 AsanovDamir/Config.cpp create mode 100644 AsanovDamir/Config.hpp create mode 100644 AsanovDamir/Deamon.cpp create mode 100644 AsanovDamir/Deamon.hpp create mode 100644 AsanovDamir/Logger.hpp create mode 100644 AsanovDamir/build.sh create mode 100644 AsanovDamir/main.cpp create mode 100644 AsanovDamir/run.sh diff --git a/AsanovDamir/.gitignore b/AsanovDamir/.gitignore new file mode 100644 index 0000000..c795b05 --- /dev/null +++ b/AsanovDamir/.gitignore @@ -0,0 +1 @@ +build \ No newline at end of file diff --git a/AsanovDamir/CMakeLists.txt b/AsanovDamir/CMakeLists.txt new file mode 100644 index 0000000..f6dcab7 --- /dev/null +++ b/AsanovDamir/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.5) + +project(DamirAsanov) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror") + +add_executable(DamirAsanov main.cpp Deamon.cpp Config.cpp) diff --git a/AsanovDamir/Config.cpp b/AsanovDamir/Config.cpp new file mode 100644 index 0000000..01185c0 --- /dev/null +++ b/AsanovDamir/Config.cpp @@ -0,0 +1,7 @@ +#include "Config.hpp" + +bool Config::readConfig(const std::string& path) +{ + // TODO: implemnt + return false; +} \ No newline at end of file diff --git a/AsanovDamir/Config.hpp b/AsanovDamir/Config.hpp new file mode 100644 index 0000000..9984bfc --- /dev/null +++ b/AsanovDamir/Config.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include + +class Config +{ +public: + bool readConfig(const std::string& path); +}; diff --git a/AsanovDamir/Deamon.cpp b/AsanovDamir/Deamon.cpp new file mode 100644 index 0000000..4fc9ff9 --- /dev/null +++ b/AsanovDamir/Deamon.cpp @@ -0,0 +1,14 @@ +#include "Deamon.hpp" +#include "Logger.hpp" +#include "Config.hpp" + +Deamon& Deamon::getInstance() +{ + static Deamon instance; + return instance; +} + +void Deamon::start() +{ + // TODO: implement +} diff --git a/AsanovDamir/Deamon.hpp b/AsanovDamir/Deamon.hpp new file mode 100644 index 0000000..221efe0 --- /dev/null +++ b/AsanovDamir/Deamon.hpp @@ -0,0 +1,13 @@ +#pragma once + +class Deamon +{ +public: + static Deamon& getInstance(); + void start(); + +private: + Deamon() = default; + Deamon(const Deamon&) = delete; + Deamon& operator=(const Deamon&) = delete; +}; diff --git a/AsanovDamir/Logger.hpp b/AsanovDamir/Logger.hpp new file mode 100644 index 0000000..c9b1135 --- /dev/null +++ b/AsanovDamir/Logger.hpp @@ -0,0 +1,18 @@ +#pragma once + +class Logger +{ +public: + Logger& get_instance() + { + static Logger instance; + return instance; + } + + // TODO: implement + +private: + Logger(); + Logger(const Logger&) = delete; + Logger& operator=(const Logger&) = delete; +}; diff --git a/AsanovDamir/build.sh b/AsanovDamir/build.sh new file mode 100644 index 0000000..b45dd0a --- /dev/null +++ b/AsanovDamir/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +mkdir -p build +cd build +cmake .. +make diff --git a/AsanovDamir/main.cpp b/AsanovDamir/main.cpp new file mode 100644 index 0000000..26ec6d8 --- /dev/null +++ b/AsanovDamir/main.cpp @@ -0,0 +1,6 @@ +#include "Deamon.hpp" + +int main() +{ + return 0; +} \ No newline at end of file diff --git a/AsanovDamir/run.sh b/AsanovDamir/run.sh new file mode 100644 index 0000000..98e5d4f --- /dev/null +++ b/AsanovDamir/run.sh @@ -0,0 +1 @@ +./build/DamirAsanov \ No newline at end of file From 9b09b11ab99e846f37c4f31d3fc8f7f5884a1ec4 Mon Sep 17 00:00:00 2001 From: theguydie Date: Fri, 25 Oct 2024 14:31:07 +0300 Subject: [PATCH 02/13] Logger: method open_log method log method close_log --- AsanovDamir/Logger.hpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/AsanovDamir/Logger.hpp b/AsanovDamir/Logger.hpp index c9b1135..1fd288c 100644 --- a/AsanovDamir/Logger.hpp +++ b/AsanovDamir/Logger.hpp @@ -1,5 +1,14 @@ #pragma once +#include +#include + +enum class Status : short +{ +INFO = LOG_INFO, +ERROR = LOG_ERR +}; + class Logger { public: @@ -9,7 +18,15 @@ class Logger return instance; } - // TODO: implement + void open_log(const std::string& identifier) const + { + openlog(identifier.c_str(), LOG_PID, LOG_DAEMON); + } + void log(Status status, const std::string& message) + { + syslog(static_cast(status), "%s", message.c_str()); + } + void close_log() { closelog(); } private: Logger(); From 9441e3fc2d64bad9dbdcfa718c129f0ccd8d2583 Mon Sep 17 00:00:00 2001 From: theguydie Date: Fri, 25 Oct 2024 14:31:54 +0300 Subject: [PATCH 03/13] Config: get absolute path of config file in constructor make success/unsuccess read config --- AsanovDamir/Config.cpp | 24 +++++++++++++++++++++--- AsanovDamir/Config.hpp | 11 ++++++++++- AsanovDamir/Config.txt | 3 +++ AsanovDamir/Deamon.cpp | 4 +--- AsanovDamir/Deamon.hpp | 5 ++++- AsanovDamir/main.cpp | 1 + 6 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 AsanovDamir/Config.txt diff --git a/AsanovDamir/Config.cpp b/AsanovDamir/Config.cpp index 01185c0..489ace4 100644 --- a/AsanovDamir/Config.cpp +++ b/AsanovDamir/Config.cpp @@ -1,7 +1,25 @@ #include "Config.hpp" +#include -bool Config::readConfig(const std::string& path) +std::string Config::get_absolute_path(const char* path) { - // TODO: implemnt - return false; + char absolute_path_buffer[4096]; + if (!realpath(path, absolute_path_buffer)) return ""; + return absolute_path_buffer; +} + +Config::Config() : pathToConfig{get_absolute_path("Config.txt")} +{} + +bool Config::read_config() +{ + std::ifstream config(pathToConfig.c_str()); + if (!config) return false; + + std::getline(config, folder1); + std::getline(config, folder2); + config >> seconds; + + if (folder1.empty() || folder2.empty() || seconds == 0) return false; + return true; } \ No newline at end of file diff --git a/AsanovDamir/Config.hpp b/AsanovDamir/Config.hpp index 9984bfc..fe15c61 100644 --- a/AsanovDamir/Config.hpp +++ b/AsanovDamir/Config.hpp @@ -5,5 +5,14 @@ class Config { public: - bool readConfig(const std::string& path); + Config(); + bool read_config(); + +private: + std::string get_absolute_path(const char* path); + + std::string pathToConfig; + std::string folder1; + std::string folder2; + int seconds; }; diff --git a/AsanovDamir/Config.txt b/AsanovDamir/Config.txt new file mode 100644 index 0000000..2e79302 --- /dev/null +++ b/AsanovDamir/Config.txt @@ -0,0 +1,3 @@ +folder1 +folder2 +60 \ No newline at end of file diff --git a/AsanovDamir/Deamon.cpp b/AsanovDamir/Deamon.cpp index 4fc9ff9..eac2026 100644 --- a/AsanovDamir/Deamon.cpp +++ b/AsanovDamir/Deamon.cpp @@ -1,8 +1,6 @@ #include "Deamon.hpp" -#include "Logger.hpp" -#include "Config.hpp" -Deamon& Deamon::getInstance() +Deamon& Deamon::get_instance() { static Deamon instance; return instance; diff --git a/AsanovDamir/Deamon.hpp b/AsanovDamir/Deamon.hpp index 221efe0..4cec81c 100644 --- a/AsanovDamir/Deamon.hpp +++ b/AsanovDamir/Deamon.hpp @@ -1,9 +1,12 @@ #pragma once +#include "Logger.hpp" +#include "Config.hpp" + class Deamon { public: - static Deamon& getInstance(); + static Deamon& get_instance(); void start(); private: diff --git a/AsanovDamir/main.cpp b/AsanovDamir/main.cpp index 26ec6d8..af5d6d0 100644 --- a/AsanovDamir/main.cpp +++ b/AsanovDamir/main.cpp @@ -2,5 +2,6 @@ int main() { + Config config; return 0; } \ No newline at end of file From f07bb11b209d70d78bfd0aa799009678623f595c Mon Sep 17 00:00:00 2001 From: theguydie Date: Fri, 25 Oct 2024 14:32:35 +0300 Subject: [PATCH 04/13] Deamon: handle SIGHUP and SIGTERM signals create pid file read config cooping files --- AsanovDamir/Config.hpp | 4 ++ AsanovDamir/Deamon.cpp | 153 ++++++++++++++++++++++++++++++++++++++++- AsanovDamir/Deamon.hpp | 13 +++- AsanovDamir/Logger.hpp | 8 +-- AsanovDamir/kill | 2 + AsanovDamir/main.cpp | 2 +- AsanovDamir/reconfig | 2 + AsanovDamir/run.sh | 2 +- 8 files changed, 178 insertions(+), 8 deletions(-) create mode 100644 AsanovDamir/kill create mode 100644 AsanovDamir/reconfig diff --git a/AsanovDamir/Config.hpp b/AsanovDamir/Config.hpp index fe15c61..b6067ed 100644 --- a/AsanovDamir/Config.hpp +++ b/AsanovDamir/Config.hpp @@ -8,6 +8,10 @@ class Config Config(); bool read_config(); + const std::string& get_folder1() const { return folder1; } + const std::string& get_folder2() const { return folder2; } + int get_seconds() const { return seconds; } + private: std::string get_absolute_path(const char* path); diff --git a/AsanovDamir/Deamon.cpp b/AsanovDamir/Deamon.cpp index eac2026..2182a02 100644 --- a/AsanovDamir/Deamon.cpp +++ b/AsanovDamir/Deamon.cpp @@ -1,4 +1,12 @@ #include "Deamon.hpp" +#include +#include +#include +#include + +Config Deamon::config; + +const char* PID = "/var/run/Deamon.pid"; Deamon& Deamon::get_instance() { @@ -6,7 +14,150 @@ Deamon& Deamon::get_instance() return instance; } +void Deamon::destroy_prev_deamon_if_exist() +{ + if (std::ifstream pid_file(PID); pid_file) { + pid_t pid; + pid_file >> pid; + if (kill(pid, 0) == 0) { + Logger::get_instance().log(Status::INFO, "Deamon is already running. Killing the old instance..."); + if (kill(pid, SIGTERM) != 0) { + Logger::get_instance().log(Status::ERROR, "Failed to terminate the existing daemon process."); + unlink(PID); + } + } + } +} + +bool Deamon::crate_pid_file() +{ + std::ofstream new_pid_file(PID); + if (!new_pid_file) { + Logger::get_instance().log(Status::ERROR, "Failed to create PID file."); + return false; + } + + new_pid_file << getpid(); + return true; +} + +void Deamon::daemonize() +{ + pid_t pid = fork(); + if (pid < 0) + exit(EXIT_FAILURE); + if (pid > 0) + exit(EXIT_SUCCESS); + + if (setsid() < 0) + exit(EXIT_FAILURE); + + signal(SIGHUP, SIG_IGN); + + pid = fork(); + if (pid < 0) + exit(EXIT_FAILURE); + if (pid > 0) + exit(EXIT_SUCCESS); + + umask(0); + chdir("/"); + + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); +} + +bool Deamon::coping() +{ + namespace fs = std::filesystem; + + const std::string& folder1 = config.get_folder1(); + const std::string& folder2 = config.get_folder2(); + + const std::string imgDir = folder2 + "/IMG"; + const std::string othersDir = folder2 + "/OTHERS"; + + try { + // Clear folder 2 + if (fs::exists(folder2)) { + for (const auto& entry : fs::directory_iterator(folder2)) { + fs::remove_all(entry.path()); + } + } else { + fs::create_directories(folder2); + } + + // Craate IMG and OTHERS folders + fs::create_directories(imgDir); + fs::create_directories(othersDir); + + // coping + for (const auto& entry : fs::directory_iterator(folder1)) { + if (entry.is_regular_file()) { + std::string fileName = entry.path().filename().string(); + std::string destPath; + if (entry.path().extension() == ".png") { + destPath = imgDir + "/" + fileName; + } else { + destPath = othersDir + "/" + fileName; + } + fs::copy(entry.path(), destPath); + } + } + } catch (const std::exception& ex) { + Logger::get_instance().log(Status::ERROR, "Error during copying: " + std::string(ex.what())); + return false; + } + + Logger::get_instance().log(Status::INFO, "Copied files from" + folder1 + "to " + folder2); + return true; +} + void Deamon::start() { - // TODO: implement + destroy_prev_deamon_if_exist(); + daemonize(); + + Logger::get_instance().open_log(); + Logger::get_instance().log(Status::INFO, "Start deamon"); + + if (!config.read_config()) { + + Logger::get_instance().log(Status::ERROR, std::string("Failed to read config")); + exit(EXIT_FAILURE); + } + + if (!crate_pid_file()) + exit(EXIT_FAILURE); + + handle_signals(); + + while (true) { + coping(); + sleep(config.get_seconds()); + } +} + +void Deamon::handle_signals() +{ + signal(SIGHUP, sighup_handler); + signal(SIGTERM, sigterm_handler); +} + +void Deamon::sighup_handler(int) +{ + Logger::get_instance().log(Status::INFO, "Re-reading config"); + if (!config.read_config()) { + Logger::get_instance().log(Status::ERROR, "Failed to read config"); + exit(EXIT_FAILURE); + } +} + +void Deamon::sigterm_handler(int) +{ + Logger::get_instance().log(Status::INFO, "Terminating"); + Logger::get_instance().close_log(); + unlink(PID); + exit(0); } diff --git a/AsanovDamir/Deamon.hpp b/AsanovDamir/Deamon.hpp index 4cec81c..03d6d56 100644 --- a/AsanovDamir/Deamon.hpp +++ b/AsanovDamir/Deamon.hpp @@ -8,9 +8,20 @@ class Deamon public: static Deamon& get_instance(); void start(); + bool coping(); private: Deamon() = default; Deamon(const Deamon&) = delete; Deamon& operator=(const Deamon&) = delete; -}; + + void handle_signals(); + static void sighup_handler(int signum); + static void sigterm_handler(int signum); + + void daemonize(); + bool crate_pid_file(); + void destroy_prev_deamon_if_exist(); + + static Config config; +}; \ No newline at end of file diff --git a/AsanovDamir/Logger.hpp b/AsanovDamir/Logger.hpp index 1fd288c..53e9d7c 100644 --- a/AsanovDamir/Logger.hpp +++ b/AsanovDamir/Logger.hpp @@ -12,15 +12,15 @@ ERROR = LOG_ERR class Logger { public: - Logger& get_instance() + static Logger& get_instance() { static Logger instance; return instance; } - void open_log(const std::string& identifier) const + void open_log() { - openlog(identifier.c_str(), LOG_PID, LOG_DAEMON); + openlog("Deamon", LOG_PID, LOG_DAEMON); } void log(Status status, const std::string& message) { @@ -29,7 +29,7 @@ class Logger void close_log() { closelog(); } private: - Logger(); + Logger() = default; Logger(const Logger&) = delete; Logger& operator=(const Logger&) = delete; }; diff --git a/AsanovDamir/kill b/AsanovDamir/kill new file mode 100644 index 0000000..e479856 --- /dev/null +++ b/AsanovDamir/kill @@ -0,0 +1,2 @@ +#!/bin/bash +sudo kill -SIGTERM $(cat /var/run/Deamon.pid) diff --git a/AsanovDamir/main.cpp b/AsanovDamir/main.cpp index af5d6d0..cad675b 100644 --- a/AsanovDamir/main.cpp +++ b/AsanovDamir/main.cpp @@ -2,6 +2,6 @@ int main() { - Config config; + Deamon::get_instance().start(); return 0; } \ No newline at end of file diff --git a/AsanovDamir/reconfig b/AsanovDamir/reconfig new file mode 100644 index 0000000..f2bf687 --- /dev/null +++ b/AsanovDamir/reconfig @@ -0,0 +1,2 @@ +#!/bin/bash +sudo kill -SIGHUP $(cat /var/run/Deamon.pid) diff --git a/AsanovDamir/run.sh b/AsanovDamir/run.sh index 98e5d4f..b0524c7 100644 --- a/AsanovDamir/run.sh +++ b/AsanovDamir/run.sh @@ -1 +1 @@ -./build/DamirAsanov \ No newline at end of file +sudo ./build/DamirAsanov \ No newline at end of file From edbc4c7db5605bacf650f1ebbad8aec44cc8803a Mon Sep 17 00:00:00 2001 From: theguydie Date: Fri, 25 Oct 2024 14:44:40 +0300 Subject: [PATCH 05/13] Add Readme.md --- AsanovDamir/Config.cpp | 9 +++++++-- AsanovDamir/Config.hpp | 1 + AsanovDamir/Deamon.cpp | 4 +++- AsanovDamir/Deamon.hpp | 2 +- AsanovDamir/README.md | 22 ++++++++++++++++++++++ AsanovDamir/main.cpp | 11 +++++++++-- AsanovDamir/run.sh | 2 +- 7 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 AsanovDamir/README.md diff --git a/AsanovDamir/Config.cpp b/AsanovDamir/Config.cpp index 489ace4..d2f46d9 100644 --- a/AsanovDamir/Config.cpp +++ b/AsanovDamir/Config.cpp @@ -20,6 +20,11 @@ bool Config::read_config() std::getline(config, folder2); config >> seconds; - if (folder1.empty() || folder2.empty() || seconds == 0) return false; + if (folder1.empty() || folder2.empty() || seconds == 0 || pathToConfig.empty()) return false; return true; -} \ No newline at end of file +} + +void Config::set_path_to_config(const char* path_to_config) +{ + pathToConfig = get_absolute_path(path_to_config); +} diff --git a/AsanovDamir/Config.hpp b/AsanovDamir/Config.hpp index b6067ed..d2c1d56 100644 --- a/AsanovDamir/Config.hpp +++ b/AsanovDamir/Config.hpp @@ -11,6 +11,7 @@ class Config const std::string& get_folder1() const { return folder1; } const std::string& get_folder2() const { return folder2; } int get_seconds() const { return seconds; } + void set_path_to_config(const char* path_to_config); private: std::string get_absolute_path(const char* path); diff --git a/AsanovDamir/Deamon.cpp b/AsanovDamir/Deamon.cpp index 2182a02..fd13d83 100644 --- a/AsanovDamir/Deamon.cpp +++ b/AsanovDamir/Deamon.cpp @@ -114,8 +114,10 @@ bool Deamon::coping() return true; } -void Deamon::start() +void Deamon::start(const char* config_path) { + config.set_path_to_config(config_path); + destroy_prev_deamon_if_exist(); daemonize(); diff --git a/AsanovDamir/Deamon.hpp b/AsanovDamir/Deamon.hpp index 03d6d56..e4496eb 100644 --- a/AsanovDamir/Deamon.hpp +++ b/AsanovDamir/Deamon.hpp @@ -7,7 +7,7 @@ class Deamon { public: static Deamon& get_instance(); - void start(); + void start(const char* config_path); bool coping(); private: diff --git a/AsanovDamir/README.md b/AsanovDamir/README.md new file mode 100644 index 0000000..ceb5ae7 --- /dev/null +++ b/AsanovDamir/README.md @@ -0,0 +1,22 @@ +# Проект: Demon + +# Автор + +Асанов Дамир Русланович 5030102/10201 Лабораторная работа №1 вариант №9: + +## Описание + +Копировать содержимое папки 1 в папку 2(предварительно очищая содержимое папки 2) следующим образом: файлы с расширением “*.png” +должны помещаться в подпапку “IMG” папки 2, остальные — в подпапку “OTHERS” + +## Запуск + +введите команду ```bash build.sh```, чтобы собрать проект +введите команду ```bash run.sh```, чтобы запустить демона +введите команду ```bash kill```, чтобы остановить демона +введите команду ```bash reconfig```, чтобы демон перепрочитал конфиг + +форма конфига: +первая строчка - путь к первой папке, откуда будет происоходить копирование +вторая строчка - путь ко второй папке, куда будет копироваться +третья строчка - целое число - количество секунд между операцией копирования diff --git a/AsanovDamir/main.cpp b/AsanovDamir/main.cpp index cad675b..17d41c2 100644 --- a/AsanovDamir/main.cpp +++ b/AsanovDamir/main.cpp @@ -1,7 +1,14 @@ #include "Deamon.hpp" +#include -int main() +int main(int argc, char* argv[]) { - Deamon::get_instance().start(); + if (argc != 2) + { + std::cout << "Wrong count of argument. Expected path to config" << std::endl; + return 1; + } + const char* config_path = argv[1]; + Deamon::get_instance().start(config_path); return 0; } \ No newline at end of file diff --git a/AsanovDamir/run.sh b/AsanovDamir/run.sh index b0524c7..05aa569 100644 --- a/AsanovDamir/run.sh +++ b/AsanovDamir/run.sh @@ -1 +1 @@ -sudo ./build/DamirAsanov \ No newline at end of file +sudo ./build/DamirAsanov ./Config.txt \ No newline at end of file From f50eb8fc4e8166c7e97cb589825f436dd65d2168 Mon Sep 17 00:00:00 2001 From: theguydie Date: Sat, 2 Nov 2024 00:34:54 +0300 Subject: [PATCH 06/13] Fixing --- AsanovDamir/Config.txt | 3 --- AsanovDamir/build.sh | 5 ----- AsanovDamir/{ => laba1}/.gitignore | 0 AsanovDamir/{ => laba1}/CMakeLists.txt | 0 AsanovDamir/{ => laba1}/Config.cpp | 15 +++++++++++---- AsanovDamir/{ => laba1}/Config.hpp | 0 AsanovDamir/laba1/Config.txt | 3 +++ AsanovDamir/{ => laba1}/Deamon.cpp | 4 +++- AsanovDamir/{ => laba1}/Deamon.hpp | 0 AsanovDamir/laba1/FirstFolder/some.png | 0 AsanovDamir/laba1/FirstFolder/some.txt | 0 AsanovDamir/{ => laba1}/Logger.hpp | 0 AsanovDamir/{ => laba1}/README.md | 0 AsanovDamir/laba1/SecondFolder/IMG/some.png | 0 AsanovDamir/laba1/SecondFolder/OTHERS/some.txt | 0 AsanovDamir/laba1/build.sh | 11 +++++++++++ AsanovDamir/{ => laba1}/kill | 0 AsanovDamir/{ => laba1}/main.cpp | 0 AsanovDamir/{ => laba1}/reconfig | 0 AsanovDamir/laba1/run.sh | 1 + AsanovDamir/run.sh | 1 - 21 files changed, 29 insertions(+), 14 deletions(-) delete mode 100644 AsanovDamir/Config.txt delete mode 100644 AsanovDamir/build.sh rename AsanovDamir/{ => laba1}/.gitignore (100%) rename AsanovDamir/{ => laba1}/CMakeLists.txt (100%) rename AsanovDamir/{ => laba1}/Config.cpp (57%) rename AsanovDamir/{ => laba1}/Config.hpp (100%) create mode 100644 AsanovDamir/laba1/Config.txt rename AsanovDamir/{ => laba1}/Deamon.cpp (97%) rename AsanovDamir/{ => laba1}/Deamon.hpp (100%) create mode 100644 AsanovDamir/laba1/FirstFolder/some.png create mode 100644 AsanovDamir/laba1/FirstFolder/some.txt rename AsanovDamir/{ => laba1}/Logger.hpp (100%) rename AsanovDamir/{ => laba1}/README.md (100%) create mode 100644 AsanovDamir/laba1/SecondFolder/IMG/some.png create mode 100644 AsanovDamir/laba1/SecondFolder/OTHERS/some.txt create mode 100644 AsanovDamir/laba1/build.sh rename AsanovDamir/{ => laba1}/kill (100%) rename AsanovDamir/{ => laba1}/main.cpp (100%) rename AsanovDamir/{ => laba1}/reconfig (100%) create mode 100644 AsanovDamir/laba1/run.sh delete mode 100644 AsanovDamir/run.sh diff --git a/AsanovDamir/Config.txt b/AsanovDamir/Config.txt deleted file mode 100644 index 2e79302..0000000 --- a/AsanovDamir/Config.txt +++ /dev/null @@ -1,3 +0,0 @@ -folder1 -folder2 -60 \ No newline at end of file diff --git a/AsanovDamir/build.sh b/AsanovDamir/build.sh deleted file mode 100644 index b45dd0a..0000000 --- a/AsanovDamir/build.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -mkdir -p build -cd build -cmake .. -make diff --git a/AsanovDamir/.gitignore b/AsanovDamir/laba1/.gitignore similarity index 100% rename from AsanovDamir/.gitignore rename to AsanovDamir/laba1/.gitignore diff --git a/AsanovDamir/CMakeLists.txt b/AsanovDamir/laba1/CMakeLists.txt similarity index 100% rename from AsanovDamir/CMakeLists.txt rename to AsanovDamir/laba1/CMakeLists.txt diff --git a/AsanovDamir/Config.cpp b/AsanovDamir/laba1/Config.cpp similarity index 57% rename from AsanovDamir/Config.cpp rename to AsanovDamir/laba1/Config.cpp index d2f46d9..3eb1621 100644 --- a/AsanovDamir/Config.cpp +++ b/AsanovDamir/laba1/Config.cpp @@ -1,11 +1,16 @@ #include "Config.hpp" #include +#include -std::string Config::get_absolute_path(const char* path) +std::string Config::get_absolute_path(const char* pathStr) { - char absolute_path_buffer[4096]; - if (!realpath(path, absolute_path_buffer)) return ""; - return absolute_path_buffer; + std::filesystem::path absPath = std::filesystem::absolute(pathStr); + if (std::filesystem::exists(absPath)) + return absPath.c_str(); + else + return ""; + + return std::filesystem::absolute(pathStr).c_str(); } Config::Config() : pathToConfig{get_absolute_path("Config.txt")} @@ -17,7 +22,9 @@ bool Config::read_config() if (!config) return false; std::getline(config, folder1); + folder1 = get_absolute_path(folder1.c_str()); std::getline(config, folder2); + folder2 = get_absolute_path(folder2.c_str()); config >> seconds; if (folder1.empty() || folder2.empty() || seconds == 0 || pathToConfig.empty()) return false; diff --git a/AsanovDamir/Config.hpp b/AsanovDamir/laba1/Config.hpp similarity index 100% rename from AsanovDamir/Config.hpp rename to AsanovDamir/laba1/Config.hpp diff --git a/AsanovDamir/laba1/Config.txt b/AsanovDamir/laba1/Config.txt new file mode 100644 index 0000000..ba258b0 --- /dev/null +++ b/AsanovDamir/laba1/Config.txt @@ -0,0 +1,3 @@ +FirstFolder +SecondFolder +10 \ No newline at end of file diff --git a/AsanovDamir/Deamon.cpp b/AsanovDamir/laba1/Deamon.cpp similarity index 97% rename from AsanovDamir/Deamon.cpp rename to AsanovDamir/laba1/Deamon.cpp index fd13d83..78b4a0c 100644 --- a/AsanovDamir/Deamon.cpp +++ b/AsanovDamir/laba1/Deamon.cpp @@ -110,7 +110,7 @@ bool Deamon::coping() return false; } - Logger::get_instance().log(Status::INFO, "Copied files from" + folder1 + "to " + folder2); + Logger::get_instance().log(Status::INFO, "Copied files from" + folder1 + " to " + folder2); return true; } @@ -152,6 +152,8 @@ void Deamon::sighup_handler(int) Logger::get_instance().log(Status::INFO, "Re-reading config"); if (!config.read_config()) { Logger::get_instance().log(Status::ERROR, "Failed to read config"); + Logger::get_instance().close_log(); + unlink(PID); exit(EXIT_FAILURE); } } diff --git a/AsanovDamir/Deamon.hpp b/AsanovDamir/laba1/Deamon.hpp similarity index 100% rename from AsanovDamir/Deamon.hpp rename to AsanovDamir/laba1/Deamon.hpp diff --git a/AsanovDamir/laba1/FirstFolder/some.png b/AsanovDamir/laba1/FirstFolder/some.png new file mode 100644 index 0000000..e69de29 diff --git a/AsanovDamir/laba1/FirstFolder/some.txt b/AsanovDamir/laba1/FirstFolder/some.txt new file mode 100644 index 0000000..e69de29 diff --git a/AsanovDamir/Logger.hpp b/AsanovDamir/laba1/Logger.hpp similarity index 100% rename from AsanovDamir/Logger.hpp rename to AsanovDamir/laba1/Logger.hpp diff --git a/AsanovDamir/README.md b/AsanovDamir/laba1/README.md similarity index 100% rename from AsanovDamir/README.md rename to AsanovDamir/laba1/README.md diff --git a/AsanovDamir/laba1/SecondFolder/IMG/some.png b/AsanovDamir/laba1/SecondFolder/IMG/some.png new file mode 100644 index 0000000..e69de29 diff --git a/AsanovDamir/laba1/SecondFolder/OTHERS/some.txt b/AsanovDamir/laba1/SecondFolder/OTHERS/some.txt new file mode 100644 index 0000000..e69de29 diff --git a/AsanovDamir/laba1/build.sh b/AsanovDamir/laba1/build.sh new file mode 100644 index 0000000..dabf60f --- /dev/null +++ b/AsanovDamir/laba1/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash +mkdir -p build +cd build +cmake .. +make + +find . -type f -name '*.o' -delete +find . -type f -name '*.cmake' -delete +find . -type f -name 'CMakeCache.txt' -delete +find . -type f -name 'Makefile' -delete +rm -rf CMakeFiles diff --git a/AsanovDamir/kill b/AsanovDamir/laba1/kill similarity index 100% rename from AsanovDamir/kill rename to AsanovDamir/laba1/kill diff --git a/AsanovDamir/main.cpp b/AsanovDamir/laba1/main.cpp similarity index 100% rename from AsanovDamir/main.cpp rename to AsanovDamir/laba1/main.cpp diff --git a/AsanovDamir/reconfig b/AsanovDamir/laba1/reconfig similarity index 100% rename from AsanovDamir/reconfig rename to AsanovDamir/laba1/reconfig diff --git a/AsanovDamir/laba1/run.sh b/AsanovDamir/laba1/run.sh new file mode 100644 index 0000000..e33b684 --- /dev/null +++ b/AsanovDamir/laba1/run.sh @@ -0,0 +1 @@ +sudo ./build/DamirAsanov Config.txt \ No newline at end of file diff --git a/AsanovDamir/run.sh b/AsanovDamir/run.sh deleted file mode 100644 index 05aa569..0000000 --- a/AsanovDamir/run.sh +++ /dev/null @@ -1 +0,0 @@ -sudo ./build/DamirAsanov ./Config.txt \ No newline at end of file From 4787e9e14adf7a55225b09008e43e2dd9469f8a1 Mon Sep 17 00:00:00 2001 From: theguydie Date: Fri, 15 Nov 2024 17:30:26 +0300 Subject: [PATCH 07/13] Start: 1) Add build.sh 2) main.cpp 3) folder laba2 --- AsanovDamir/laba2/CMakeLists.txt | 7 +++++++ AsanovDamir/laba2/Quation.txt | 18 ++++++++++++++++++ AsanovDamir/laba2/README.md | 22 ++++++++++++++++++++++ AsanovDamir/laba2/build.sh | 11 +++++++++++ AsanovDamir/laba2/build/DamirAsanov | Bin 0 -> 15768 bytes AsanovDamir/laba2/main.cpp | 6 ++++++ AsanovDamir/laba2/run.sh | 1 + 7 files changed, 65 insertions(+) create mode 100644 AsanovDamir/laba2/CMakeLists.txt create mode 100644 AsanovDamir/laba2/Quation.txt create mode 100644 AsanovDamir/laba2/README.md create mode 100644 AsanovDamir/laba2/build.sh create mode 100755 AsanovDamir/laba2/build/DamirAsanov create mode 100644 AsanovDamir/laba2/main.cpp create mode 100644 AsanovDamir/laba2/run.sh diff --git a/AsanovDamir/laba2/CMakeLists.txt b/AsanovDamir/laba2/CMakeLists.txt new file mode 100644 index 0000000..c17dbad --- /dev/null +++ b/AsanovDamir/laba2/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.5) + +project(DamirAsanov) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror") + +add_executable(DamirAsanov main.cpp) diff --git a/AsanovDamir/laba2/Quation.txt b/AsanovDamir/laba2/Quation.txt new file mode 100644 index 0000000..a4d1032 --- /dev/null +++ b/AsanovDamir/laba2/Quation.txt @@ -0,0 +1,18 @@ +Вариант 23: + +Родственные. Один к одному. 4, 6, 7 + +Локальный сетевой чат. Хост и клиенты - участники чата. Хост может как сам отправлять личные и общие сообщения в чат, +так и передавать сообщения от других участников в общий чат или лично. Общие сообщения отображаются в чате у всех +подключенных участников, личные сообщения отображаются в чате только у отправителя и адресата. Если клиент не отправляет +сообщения больше минуты и не является хостом, то ему отправляется SIGKILL для завершения. Сообщения в чате появляются +в порядке времени их отправления. + +4. Очереди сообщений (mq_open). TYPE_CODE - mq. Работа с очередью должна производиться в каждом процессе уже после создания +дочернего (так, будто это несвязанные процессы). + +6. Именованные каналы (mkfifo). TYPE_CODE - fifo. Работа с именованным каналом должна производиться в каждом процессе уже +после создания дочернего (так, будто это несвязанные процессы). После окончания работы родительский процесс должен удалять +файл именованного канала. + +7. Сокеты (socket). TYPE_CODE – sock diff --git a/AsanovDamir/laba2/README.md b/AsanovDamir/laba2/README.md new file mode 100644 index 0000000..ceb5ae7 --- /dev/null +++ b/AsanovDamir/laba2/README.md @@ -0,0 +1,22 @@ +# Проект: Demon + +# Автор + +Асанов Дамир Русланович 5030102/10201 Лабораторная работа №1 вариант №9: + +## Описание + +Копировать содержимое папки 1 в папку 2(предварительно очищая содержимое папки 2) следующим образом: файлы с расширением “*.png” +должны помещаться в подпапку “IMG” папки 2, остальные — в подпапку “OTHERS” + +## Запуск + +введите команду ```bash build.sh```, чтобы собрать проект +введите команду ```bash run.sh```, чтобы запустить демона +введите команду ```bash kill```, чтобы остановить демона +введите команду ```bash reconfig```, чтобы демон перепрочитал конфиг + +форма конфига: +первая строчка - путь к первой папке, откуда будет происоходить копирование +вторая строчка - путь ко второй папке, куда будет копироваться +третья строчка - целое число - количество секунд между операцией копирования diff --git a/AsanovDamir/laba2/build.sh b/AsanovDamir/laba2/build.sh new file mode 100644 index 0000000..dabf60f --- /dev/null +++ b/AsanovDamir/laba2/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash +mkdir -p build +cd build +cmake .. +make + +find . -type f -name '*.o' -delete +find . -type f -name '*.cmake' -delete +find . -type f -name 'CMakeCache.txt' -delete +find . -type f -name 'Makefile' -delete +rm -rf CMakeFiles diff --git a/AsanovDamir/laba2/build/DamirAsanov b/AsanovDamir/laba2/build/DamirAsanov new file mode 100755 index 0000000000000000000000000000000000000000..c1cd62c4a47547809f1452a50492790d66bd7538 GIT binary patch literal 15768 zcmeHOU2Ggz6~4R9k4qDK0ych7gvcki7ucV_Q+?|m#gGnGsv6jFzJk76s6(o9AQJ~Sd3f{Yqfd+GRA zby)2pdq=?O@{9&5)#-Y2D|QOsLCCs3&a}b9nx+>cW78ba4$ZNxXh>X+2|~vv>y)Ye>2l~K*pPk#5l@Z@e?}#q zQA|rUz^HCXbWxlX9gy4Lbm3Jm|3=z-Ky*8dpc)m$do`_qXz%@`3*sW>w*p+|S!r*( z>yVQ810}rbc(ITh89rXj4-^aK`pUq{=*Ymxuvx2^CxWKAUj}`6Or1G*QBgGw<|K?N zxu$K@$7TDaoc*8cZGPidg@?S}#@oK~>__j){(Aq1A7mfyH*4636W50!!Zzo*P4?08 zc${)Fwh6DfKP?5sHV4-Av?-e)&S=Bi+wkRW_&bPydz*TcZBs<&?V9IQJ-g%-%EZjC zIQBxJ>=X-+x{8ZAz9Z_)%=GCA`-FMIJlV<*4J&(k?yQ}6tL|c<=DF3mvlGQi*`0H8 zMVIPYELF-^|~DP#^JMCdRt5^YaY%t$V%H^anUkP2c9<=svQ>j#mZAzYzGJ%rW$DSeKjDOMg0L zy|mt8C0?JFr+-8D3wl1kwJ|PM^><#hE{!EQYh8ZT+haXBwu_9L{l4$t z%+ukOo&Tb@?!?2SZMDz(-#oz zVRA}5I;#>Zsl=f@yE~tvAF!C`-|CyM`TjlZFu6PU1?+Ch4%6oa;sc^9HPzMk-tOBU z>0DE%4&L{Up}T{h3t7+YJ`F$0bK*KZ`aDkk=w>3@mHKpYV(+dgYMAXf#Sw@j5Jw=6 zKpcTM0&xW52*eSHBM?U*jzHT8V7(&NCt~d()@<&9O4cv#6?;_HIle_~tb;rxHr~Y! zijDP<{QkxX<$vAqD{Mb6ix{ysafx3(Dd{z>N?n)oH)&dZM(}pQKEYl=0M z?*Qw=|H~S&F7?dB#Jh}R7jyNpS2qTSXbo<9;KWcpu!sAF`44Sz9CoPJ{iqAaIYA|# zl|UHc!0UzE`SW#1sxGxG<51j{A^g)3en@zXYxqx7CZYONDx(=(Cth8hp#NH6oa$1g zK0z677xxKx9)AgShr+lA|14$N^?$qbdOoP9M>P!8u!-&Jc`@*(Q69O@KL}*|)DB}) z&$(aHC!yY~F#b{6q)fYY-+L(_2Ao1T8t?~{%7jSD_7k5{2U_t&X`1++WVga|0{n>h zN9&mg>W9}R&Jw>bc|c)2qQqvNT2_W;JMUGhHQTALsQF51x#)Us z-b}am;Fb0T+o@KaRog9l)m61nbxN+Cua`=zBneqId3sx1dBMIpzr0L-Q?uh|vv&5} zq)qGWCm%dFes+3-Xxgw~XDunUCTEp>X6F3q@frL4)YOISoIN*wdL~PX=r({1R{P&- zg}aAa#d6(Tu2z=a zs<#@Va`ggjH!0+W8b3Wfz{4SMUvg?o%FM5psR@lVvshp^WFQ(2++3c~*kRn(mT}fu%g@VQIY{3|fIaRqm7u^VA)_FeU|6nKTMZ zG`L!$`weG!UO~4EJ&SdU?i0hjLW%=lrzScR>F!Ujm|i%$K75cSz53CFn7q0zM_}avwR) z&|@A{AdbJPp~w6T$lr(I#C3$z$H?Hh5%ic30Wr@+|KSJxBJ`==lAv=v#9RLp%ke{;+}H6FsgU<~cy# zpA}Bff%^$%IR4P54P65Kf;L-6Tz?Qhr%V@pFmK1a5BmtC{;+|+B`wb(pvOFOeSk^dqHTGBDTk9mxu oKY0G}`wIFV*01r42BjaPA#DbIm23d}=-5vGzLVN(&n@)-23Qc6oB#j- literal 0 HcmV?d00001 diff --git a/AsanovDamir/laba2/main.cpp b/AsanovDamir/laba2/main.cpp new file mode 100644 index 0000000..64cd771 --- /dev/null +++ b/AsanovDamir/laba2/main.cpp @@ -0,0 +1,6 @@ + + +int main() { + + return 0; +} diff --git a/AsanovDamir/laba2/run.sh b/AsanovDamir/laba2/run.sh new file mode 100644 index 0000000..e33b684 --- /dev/null +++ b/AsanovDamir/laba2/run.sh @@ -0,0 +1 @@ +sudo ./build/DamirAsanov Config.txt \ No newline at end of file From 13912e9a79d7d7a86c3981e80bd7d01f4f957c30 Mon Sep 17 00:00:00 2001 From: theguydie Date: Sat, 23 Nov 2024 17:04:01 +0300 Subject: [PATCH 08/13] Add socket connection --- AsanovDamir/laba2/.gitignore | 1 + AsanovDamir/laba2/Book.hpp | 9 ++ AsanovDamir/laba2/CMakeLists.txt | 24 +++- .../laba2/ClientUtils/ClientWindow.cpp | 96 ++++++++++++++ .../laba2/ClientUtils/ClientWindow.hpp | 48 +++++++ .../laba2/ClientUtils/clientProcessing.hpp | 82 ++++++++++++ AsanovDamir/laba2/HostUtils/HostWindow.cpp | 56 +++++++++ AsanovDamir/laba2/HostUtils/HostWindow.hpp | 36 ++++++ .../laba2/HostUtils/hostProcessing.hpp | 119 ++++++++++++++++++ AsanovDamir/laba2/build.sh | 3 + AsanovDamir/laba2/build/DamirAsanov | Bin 15768 -> 0 bytes AsanovDamir/laba2/conn_sock.cpp | 101 +++++++++++++++ AsanovDamir/laba2/conn_sock.hpp | 28 +++++ AsanovDamir/laba2/host_sock.cpp | 63 ++++++++++ AsanovDamir/laba2/logger.hpp | 56 +++++++++ AsanovDamir/laba2/main.cpp | 6 - AsanovDamir/laba2/run.sh | 1 - AsanovDamir/laba2/runHost.sh | 2 + AsanovDamir/laba2/semaphore.cpp | 32 +++++ AsanovDamir/laba2/semaphore.hpp | 14 +++ 20 files changed, 769 insertions(+), 8 deletions(-) create mode 100644 AsanovDamir/laba2/.gitignore create mode 100644 AsanovDamir/laba2/Book.hpp create mode 100644 AsanovDamir/laba2/ClientUtils/ClientWindow.cpp create mode 100644 AsanovDamir/laba2/ClientUtils/ClientWindow.hpp create mode 100644 AsanovDamir/laba2/ClientUtils/clientProcessing.hpp create mode 100644 AsanovDamir/laba2/HostUtils/HostWindow.cpp create mode 100644 AsanovDamir/laba2/HostUtils/HostWindow.hpp create mode 100644 AsanovDamir/laba2/HostUtils/hostProcessing.hpp delete mode 100755 AsanovDamir/laba2/build/DamirAsanov create mode 100644 AsanovDamir/laba2/conn_sock.cpp create mode 100644 AsanovDamir/laba2/conn_sock.hpp create mode 100644 AsanovDamir/laba2/host_sock.cpp create mode 100644 AsanovDamir/laba2/logger.hpp delete mode 100644 AsanovDamir/laba2/main.cpp delete mode 100644 AsanovDamir/laba2/run.sh create mode 100644 AsanovDamir/laba2/runHost.sh create mode 100644 AsanovDamir/laba2/semaphore.cpp create mode 100644 AsanovDamir/laba2/semaphore.hpp diff --git a/AsanovDamir/laba2/.gitignore b/AsanovDamir/laba2/.gitignore new file mode 100644 index 0000000..378eac2 --- /dev/null +++ b/AsanovDamir/laba2/.gitignore @@ -0,0 +1 @@ +build diff --git a/AsanovDamir/laba2/Book.hpp b/AsanovDamir/laba2/Book.hpp new file mode 100644 index 0000000..824b13c --- /dev/null +++ b/AsanovDamir/laba2/Book.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include + +struct Book +{ + std::string name; + int count; +}; diff --git a/AsanovDamir/laba2/CMakeLists.txt b/AsanovDamir/laba2/CMakeLists.txt index c17dbad..50be2a4 100644 --- a/AsanovDamir/laba2/CMakeLists.txt +++ b/AsanovDamir/laba2/CMakeLists.txt @@ -4,4 +4,26 @@ project(DamirAsanov) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror") -add_executable(DamirAsanov main.cpp) +find_package(Qt5 COMPONENTS Widgets REQUIRED) + +set(CMAKE_AUTOMOC ON) # for Q_OBJECT + +set(SOURCES_SOCK + host_sock.cpp + HostUtils/HostWindow.cpp + ClientUtils/ClientWindow.cpp + conn_sock.cpp + semaphore.cpp +) + +set(HEADERS_SOCK + HostUtils/HostWindow.hpp + ClientUtils/ClientWindow.hpp + conn_sock.hpp + semaphore.hpp + logger.hpp +) + +add_executable(host_sock ${SOURCES_SOCK} ${HEADERS_SOCK}) +target_link_libraries(host_sock Qt5::Widgets) +target_include_directories(host_sock PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/AsanovDamir/laba2/ClientUtils/ClientWindow.cpp b/AsanovDamir/laba2/ClientUtils/ClientWindow.cpp new file mode 100644 index 0000000..f200f7a --- /dev/null +++ b/AsanovDamir/laba2/ClientUtils/ClientWindow.cpp @@ -0,0 +1,96 @@ +#include "ClientWindow.hpp" +#include +#include +#include "logger.hpp" + +ClientWindow::ClientWindow(const std::vector& books, QWidget* parent) + : QMainWindow(parent) { + stackedWidget = new QStackedWidget(this); + + createBookView(books); + createReadingView(); + + setCentralWidget(stackedWidget); + setWindowTitle("Client Control Panel"); + resize(400, 300); + + // Set started window + stackedWidget->setCurrentIndex(0); +} + +ClientWindow::~ClientWindow() {} + +void ClientWindow::createBookView(const std::vector& books) { + QWidget* bookView = new QWidget(this); + QVBoxLayout* layout = new QVBoxLayout(bookView); + + bookList = new QListWidget(this); + for (const auto& book : books) { + bookList->addItem(QString::fromStdString(book.name) + " - " + QString::number(book.count) + " copies"); + } + layout->addWidget(bookList); + + selectButton = new QPushButton("Select Book", this); + selectButton->setEnabled(false); + layout->addWidget(selectButton); + + terminateClientButton = new QPushButton("Terminate Client", this); + layout->addWidget(terminateClientButton); + + // Enable button if book is choosed + connect(bookList, &QListWidget::itemSelectionChanged, [this]() { + selectButton->setEnabled(bookList->currentItem() != nullptr); + }); + connect(selectButton, &QPushButton::clicked, this, &ClientWindow::selectBook); + connect(terminateClientButton, &QPushButton::clicked, this, &ClientWindow::terminateClient); + + stackedWidget->addWidget(bookView); +} + +void ClientWindow::createReadingView() { + QWidget* readingView = new QWidget(this); + QVBoxLayout* layout = new QVBoxLayout(readingView); + + readingLabel = new QLabel("Reading book: ", this); + layout->addWidget(readingLabel); + + cancelReadingButton = new QPushButton("Cancel Reading", this); + layout->addWidget(cancelReadingButton); + + connect(cancelReadingButton, &QPushButton::clicked, this, &ClientWindow::cancelReading); + + stackedWidget->addWidget(readingView); +} + +void ClientWindow::selectBook() { + if (bookList->currentItem()) { + QString bookName = bookList->currentItem()->text().split(" - ").first(); + readingLabel->setText("Reading book: " + bookName); + + emit bookSelected(bookName); + } +} + +void ClientWindow::cancelReading() { + QString bookName = readingLabel->text().split(": ").last(); + emit bookReturned(bookName); + + // Set started window + stackedWidget->setCurrentIndex(0); +} + +void ClientWindow::onSuccessTakeBook() { + // Set reading window + stackedWidget->setCurrentIndex(1); +} + +void ClientWindow::onFailedTakeBook() { + // Cannot display this window.... + // QMessageBox::warning(nullptr, "FAIL", "Failed to take book"); + LoggerClient::get_instance().log(Status::ERROR, "Failed to take book"); +} + +void ClientWindow::terminateClient() { + QMessageBox::information(this, "Terminate Client", "Client terminated."); + std::exit(0); // TODO: exit only qapp, but don't whole process +} diff --git a/AsanovDamir/laba2/ClientUtils/ClientWindow.hpp b/AsanovDamir/laba2/ClientUtils/ClientWindow.hpp new file mode 100644 index 0000000..1c6124a --- /dev/null +++ b/AsanovDamir/laba2/ClientUtils/ClientWindow.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Book.hpp" + +class ClientWindow : public QMainWindow { + Q_OBJECT + +public: + ClientWindow(const std::vector& books, QWidget* parent = nullptr); + ~ClientWindow(); + + void onSuccessTakeBook(); + void onFailedTakeBook(); + +signals: + void bookSelected(const QString& bookName); + void bookReturned(const QString& bookName); + +private slots: + void selectBook(); + void cancelReading(); + void terminateClient(); + +private: + void createBookView(const std::vector& books); + void createReadingView(); + + QStackedWidget* stackedWidget; // For switch windows (started <-> reading) + + QListWidget* bookList; + QPushButton* selectButton; + + QLabel* readingLabel; + QPushButton* cancelReadingButton; + + QPushButton* terminateClientButton; +}; diff --git a/AsanovDamir/laba2/ClientUtils/clientProcessing.hpp b/AsanovDamir/laba2/ClientUtils/clientProcessing.hpp new file mode 100644 index 0000000..561a44a --- /dev/null +++ b/AsanovDamir/laba2/ClientUtils/clientProcessing.hpp @@ -0,0 +1,82 @@ +#include +#include "ClientWindow.hpp" +#include "conn_sock.hpp" +#include "logger.hpp" +#include "semaphore.hpp" +#include +#include +#include + +void listenForHostMessages(ConnSock& conn_sock, Semaphore& semaphore, ClientWindow& window, std::atomic& is_ranning) { + auto& logger = LoggerClient::get_instance(); + + while (is_ranning) { + + semaphore.Wait(); // Start critical section + char buffer[64] = {0}; + if (conn_sock.Read(buffer, sizeof(buffer))) { + std::string response(buffer); + + if (response == "YES") { + window.onSuccessTakeBook(); + logger.log(Status::INFO, "Host gives the book"); + } + else if (response == "NO") { + window.onFailedTakeBook(); + logger.log(Status::INFO, "Host rejected the request: no such book"); + } + else { + logger.log(Status::ERROR, "Unexpected response from host: " + response); + } + } + + semaphore.Post(); // End critical section + sleep(1); + } +} + +int processClient(int port, Semaphore& semaphore, ConnSock& conn_sock, const std::vector& books) { + auto& logger = LoggerClient::get_instance(); + + int argc = 0; + char** argv = nullptr; + QApplication app(argc, argv); + ClientWindow window(books); + + std::atomic is_running(true); + + // Start thread with listenning socket + std::thread listenerThread(listenForHostMessages, std::ref(conn_sock), std::ref(semaphore), std::ref(window), std::ref(is_running)); + + QObject::connect(&window, &ClientWindow::bookSelected, [&conn_sock, &logger](const QString& bookName) { + std::string request = "TAKE " + bookName.toStdString(); + if (conn_sock.Write(request.c_str(), request.size())) { + logger.log(Status::INFO, "Requested book: " + bookName.toStdString()); + } + else { + logger.log(Status::ERROR, "Failed to request the book: " + bookName.toStdString()); + } + + }); + + QObject::connect(&window, &ClientWindow::bookReturned, [&conn_sock, &logger](const QString& bookName) { + std::string request = "RETURN " + bookName.toStdString(); + if (conn_sock.Write(request.c_str(), request.size())) { + logger.log(Status::INFO, "Returned book: " + bookName.toStdString()); + } + else { + logger.log(Status::ERROR, "Failed to return the book: " + bookName.toStdString()); + } + }); + + window.show(); + int result = app.exec(); + + // Complete thread with listenning socket + is_running = false; + if (listenerThread.joinable()) { + listenerThread.join(); + } + + return result; +} \ No newline at end of file diff --git a/AsanovDamir/laba2/HostUtils/HostWindow.cpp b/AsanovDamir/laba2/HostUtils/HostWindow.cpp new file mode 100644 index 0000000..4951de7 --- /dev/null +++ b/AsanovDamir/laba2/HostUtils/HostWindow.cpp @@ -0,0 +1,56 @@ +#include "HostWindow.hpp" +#include "logger.hpp" +#include +#include +#include +#include + +HostWindow::HostWindow(int port, const std::vector& books, QWidget* parent) + : QMainWindow(parent), hostPort(port) { + + QWidget* centralWidget = new QWidget(this); + QVBoxLayout* layout = new QVBoxLayout(centralWidget); + + portLabel = new QLabel("Host Port: " + QString::number(port), this); + layout->addWidget(portLabel); + + bookList = new QListWidget(this); + for (const auto& book : books) { + bookList->addItem(QString::fromStdString(book.name) + " - " + QString::number(book.count) + " copies"); + } + layout->addWidget(bookList); + + terminateClientButton = new QPushButton("Terminate Client", this); + layout->addWidget(terminateClientButton); + + terminateHostButton = new QPushButton("Terminate Host", this); + layout->addWidget(terminateHostButton); + + connect(terminateClientButton, &QPushButton::clicked, this, &HostWindow::terminateClient); + connect(terminateHostButton, &QPushButton::clicked, this, &HostWindow::terminateHost); + + setCentralWidget(centralWidget); + setWindowTitle("Host Control Panel"); + resize(400, 300); +} + +HostWindow::~HostWindow() {} + +void HostWindow::updateBooks(const std::vector& books) { + bookList->clear(); + for (const auto& book : books) { + bookList->addItem(QString::fromStdString(book.name) + " - " + QString::number(book.count) + " copies"); + } +} + +void HostWindow::terminateClient() { + QMessageBox::information(this, "Terminate Client", "Client terminated."); + LoggerHost::get_instance().log(Status::INFO, "Terminate Client"); + kill(clientPid, SIGKILL); +} + +void HostWindow::terminateHost() { + QMessageBox::information(this, "Terminate Host", "Host terminated."); + LoggerHost::get_instance().log(Status::INFO, "Terminate Host"); + std::exit(0); +} diff --git a/AsanovDamir/laba2/HostUtils/HostWindow.hpp b/AsanovDamir/laba2/HostUtils/HostWindow.hpp new file mode 100644 index 0000000..7094ea1 --- /dev/null +++ b/AsanovDamir/laba2/HostUtils/HostWindow.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Book.hpp" + +class HostWindow : public QMainWindow { + Q_OBJECT + +public: + HostWindow(int port, const std::vector& books, QWidget* parent = nullptr); + virtual ~HostWindow(); + + void updateBooks(const std::vector& books); + + pid_t clientPid; // for kill + +private slots: + void terminateClient(); + void terminateHost(); + +private: + QLabel* portLabel; + QListWidget* bookList; + QPushButton* terminateClientButton; + QPushButton* terminateHostButton; + int hostPort; +}; diff --git a/AsanovDamir/laba2/HostUtils/hostProcessing.hpp b/AsanovDamir/laba2/HostUtils/hostProcessing.hpp new file mode 100644 index 0000000..ded9e22 --- /dev/null +++ b/AsanovDamir/laba2/HostUtils/hostProcessing.hpp @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include "HostWindow.hpp" +#include "conn_sock.hpp" +#include "semaphore.hpp" +#include "logger.hpp" +#include "Book.hpp" +#include + +bool takeBook(std::vector& books, const std::string& bookName, LoggerHost& logger) { + for (auto& book : books) { + if (book.name == bookName) { + if (book.count > 0) { + book.count--; + logger.log(Status::INFO, "Book taken: " + bookName); + return true; + } else { + logger.log(Status::INFO, "Book not available: " + bookName); + return false; + } + } + } + + logger.log(Status::INFO, "No such Book in library: " + bookName); + return false; +} + +bool returnBook(std::vector& books, const std::string& bookName, LoggerHost& logger) { + for (auto& book : books) { + if (book.name == bookName) { + book.count++; + logger.log(Status::INFO, "Book returned: " + bookName); + return true; + } + } + + logger.log(Status::INFO, "No such Book in library: " + bookName); + return false; +} + +void listenForClientMessages(ConnSock& hostSocket, Semaphore& semaphore, std::vector& books, HostWindow& window, std::atomic& is_running) { + auto& logger = LoggerHost::get_instance(); + + ConnSock* conn = hostSocket.Accept(logger); + if (!conn) + { + logger.log(Status::ERROR, "Failed to accept connection"); + return; + } + + while (is_running) { + semaphore.Wait(); // Start critical section + + char buffer[1024] = {0}; + if (conn->Read(buffer, sizeof(buffer))) { + std::string request(buffer); + logger.log(Status::INFO, "Request is recieved: " + request); + + if (request.rfind("TAKE ", 0) == 0) { + std::string bookName = request.substr(5); + if (takeBook(books, bookName, logger)) + { + std::string response = "YES"; + if (conn->Write(response.c_str(), response.size())) { + logger.log(Status::INFO, "Host response successfully"); + } + else { + logger.log(Status::ERROR, "Failed to response"); + } + } + else + { + std::string response = "NO"; + if (conn->Write(response.c_str(), response.size())) { + logger.log(Status::INFO, "Host response successfully"); + } + else { + logger.log(Status::ERROR, "Failed to response"); + } + } + } else if (request.rfind("RETURN ", 0) == 0) { + std::string bookName = request.substr(7); + returnBook(books, bookName, logger); // client unexpected any response on this request + } + + window.updateBooks(books); + } + + semaphore.Post(); // End critical section + sleep(1); + } + + delete conn; + logger.log(Status::INFO, "listenForClientMessages is over"); +} + +int processHost(int port, Semaphore& semaphore, ConnSock& hostSocket, std::vector books, QApplication& app, pid_t pid) { + LoggerHost::get_instance().log(Status::INFO, "Host is running"); + std::atomic is_running(true); + HostWindow window(port, books); + window.clientPid = pid; + + // Start host's listenning in new thread + std::thread listenerThread(listenForClientMessages, std::ref(hostSocket), std::ref(semaphore), std::ref(books), std::ref(window), std::ref(is_running)); + + window.show(); + int result = app.exec(); // Start window in this thread + + // Complete thread with listenning socket + is_running = false; + if (listenerThread.joinable()) { + listenerThread.join(); + } + + return result; +} diff --git a/AsanovDamir/laba2/build.sh b/AsanovDamir/laba2/build.sh index dabf60f..b69e5e8 100644 --- a/AsanovDamir/laba2/build.sh +++ b/AsanovDamir/laba2/build.sh @@ -9,3 +9,6 @@ find . -type f -name '*.cmake' -delete find . -type f -name 'CMakeCache.txt' -delete find . -type f -name 'Makefile' -delete rm -rf CMakeFiles +rm -rf host_sock_autogen +rm -rf ClientUtils +rm -rf HostUtils diff --git a/AsanovDamir/laba2/build/DamirAsanov b/AsanovDamir/laba2/build/DamirAsanov deleted file mode 100755 index c1cd62c4a47547809f1452a50492790d66bd7538..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15768 zcmeHOU2Ggz6~4R9k4qDK0ych7gvcki7ucV_Q+?|m#gGnGsv6jFzJk76s6(o9AQJ~Sd3f{Yqfd+GRA zby)2pdq=?O@{9&5)#-Y2D|QOsLCCs3&a}b9nx+>cW78ba4$ZNxXh>X+2|~vv>y)Ye>2l~K*pPk#5l@Z@e?}#q zQA|rUz^HCXbWxlX9gy4Lbm3Jm|3=z-Ky*8dpc)m$do`_qXz%@`3*sW>w*p+|S!r*( z>yVQ810}rbc(ITh89rXj4-^aK`pUq{=*Ymxuvx2^CxWKAUj}`6Or1G*QBgGw<|K?N zxu$K@$7TDaoc*8cZGPidg@?S}#@oK~>__j){(Aq1A7mfyH*4636W50!!Zzo*P4?08 zc${)Fwh6DfKP?5sHV4-Av?-e)&S=Bi+wkRW_&bPydz*TcZBs<&?V9IQJ-g%-%EZjC zIQBxJ>=X-+x{8ZAz9Z_)%=GCA`-FMIJlV<*4J&(k?yQ}6tL|c<=DF3mvlGQi*`0H8 zMVIPYELF-^|~DP#^JMCdRt5^YaY%t$V%H^anUkP2c9<=svQ>j#mZAzYzGJ%rW$DSeKjDOMg0L zy|mt8C0?JFr+-8D3wl1kwJ|PM^><#hE{!EQYh8ZT+haXBwu_9L{l4$t z%+ukOo&Tb@?!?2SZMDz(-#oz zVRA}5I;#>Zsl=f@yE~tvAF!C`-|CyM`TjlZFu6PU1?+Ch4%6oa;sc^9HPzMk-tOBU z>0DE%4&L{Up}T{h3t7+YJ`F$0bK*KZ`aDkk=w>3@mHKpYV(+dgYMAXf#Sw@j5Jw=6 zKpcTM0&xW52*eSHBM?U*jzHT8V7(&NCt~d()@<&9O4cv#6?;_HIle_~tb;rxHr~Y! zijDP<{QkxX<$vAqD{Mb6ix{ysafx3(Dd{z>N?n)oH)&dZM(}pQKEYl=0M z?*Qw=|H~S&F7?dB#Jh}R7jyNpS2qTSXbo<9;KWcpu!sAF`44Sz9CoPJ{iqAaIYA|# zl|UHc!0UzE`SW#1sxGxG<51j{A^g)3en@zXYxqx7CZYONDx(=(Cth8hp#NH6oa$1g zK0z677xxKx9)AgShr+lA|14$N^?$qbdOoP9M>P!8u!-&Jc`@*(Q69O@KL}*|)DB}) z&$(aHC!yY~F#b{6q)fYY-+L(_2Ao1T8t?~{%7jSD_7k5{2U_t&X`1++WVga|0{n>h zN9&mg>W9}R&Jw>bc|c)2qQqvNT2_W;JMUGhHQTALsQF51x#)Us z-b}am;Fb0T+o@KaRog9l)m61nbxN+Cua`=zBneqId3sx1dBMIpzr0L-Q?uh|vv&5} zq)qGWCm%dFes+3-Xxgw~XDunUCTEp>X6F3q@frL4)YOISoIN*wdL~PX=r({1R{P&- zg}aAa#d6(Tu2z=a zs<#@Va`ggjH!0+W8b3Wfz{4SMUvg?o%FM5psR@lVvshp^WFQ(2++3c~*kRn(mT}fu%g@VQIY{3|fIaRqm7u^VA)_FeU|6nKTMZ zG`L!$`weG!UO~4EJ&SdU?i0hjLW%=lrzScR>F!Ujm|i%$K75cSz53CFn7q0zM_}avwR) z&|@A{AdbJPp~w6T$lr(I#C3$z$H?Hh5%ic30Wr@+|KSJxBJ`==lAv=v#9RLp%ke{;+}H6FsgU<~cy# zpA}Bff%^$%IR4P54P65Kf;L-6Tz?Qhr%V@pFmK1a5BmtC{;+|+B`wb(pvOFOeSk^dqHTGBDTk9mxu oKY0G}`wIFV*01r42BjaPA#DbIm23d}=-5vGzLVN(&n@)-23Qc6oB#j- diff --git a/AsanovDamir/laba2/conn_sock.cpp b/AsanovDamir/laba2/conn_sock.cpp new file mode 100644 index 0000000..553744d --- /dev/null +++ b/AsanovDamir/laba2/conn_sock.cpp @@ -0,0 +1,101 @@ +#include "conn_sock.hpp" +#include +#include +#include +#include + +ConnSock::ConnSock(int hostPort, LoggerHost& logger) : sock_fd(-1) { + logger.log(Status::INFO, "Creating socket for Host"); + sock_fd = socket(AF_INET, SOCK_STREAM, 0); + if (sock_fd == -1) { + logger.log(Status::ERROR, "Socket creation failed"); + return; + } + + addr.sin_family = AF_INET; + addr.sin_port = htons(hostPort); // Порт + addr.sin_addr.s_addr = INADDR_ANY; + + if (bind(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { + logger.log(Status::ERROR, "Bind failed"); + close(sock_fd); + sock_fd = -1; + return; + } + + if (listen(sock_fd, 1) == -1) { + logger.log(Status::ERROR, "Listen failed"); + close(sock_fd); + sock_fd = -1; + return; + } + + logger.log(Status::INFO, "Socket successfully created and listening"); +} + +ConnSock::ConnSock(int hostPort, LoggerClient& logger) : sock_fd(-1) { + logger.log(Status::INFO, "Creating socket for Client"); + sock_fd = socket(AF_INET, SOCK_STREAM, 0); + if (sock_fd == -1) { + logger.log(Status::ERROR, "Socket creation failed"); + return; + } + + addr.sin_family = AF_INET; + addr.sin_port = htons(hostPort); + + if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) <= 0) { + logger.log(Status::ERROR, "Invalid host IP address"); + close(sock_fd); + sock_fd = -1; + return; + } + + if (connect(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { + logger.log(Status::ERROR, "Connect failed"); + close(sock_fd); + sock_fd = -1; + return; + } + + logger.log(Status::INFO, "Connected to host successfully"); +} + +ConnSock* ConnSock::Accept(LoggerHost& logger) { + struct sockaddr_in client_addr; + socklen_t client_len = sizeof(client_addr); + int client_fd = accept(sock_fd, (struct sockaddr*)&client_addr, &client_len); + if (client_fd == -1) { + logger.log(Status::ERROR, "Accept failed"); + return nullptr; + } + + logger.log(Status::INFO, "Client connection accepted"); + // make new socket for communication with client + ConnSock* conn = new ConnSock(); + conn->sock_fd = client_fd; + conn->addr = client_addr; + return conn; +} + +bool ConnSock::Read(void* buf, size_t count) { + ssize_t bytes_read = recv(sock_fd, buf, count, 0); + if (bytes_read <= 0) { + return false; + } + return true; +} + +bool ConnSock::Write(const void* buf, size_t count) { + ssize_t bytes_sent = send(sock_fd, buf, count, 0); + if (bytes_sent <= 0) { + return false; + } + return true; +} + +ConnSock::~ConnSock() { + if (sock_fd != -1) { + close(sock_fd); + } +} diff --git a/AsanovDamir/laba2/conn_sock.hpp b/AsanovDamir/laba2/conn_sock.hpp new file mode 100644 index 0000000..d0918b5 --- /dev/null +++ b/AsanovDamir/laba2/conn_sock.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include +#include "logger.hpp" + +class ConnSock { +public: + ConnSock(int hostPort, LoggerHost& logger); + ConnSock(int hostPort, LoggerClient& logger); + ~ConnSock(); + + ConnSock* Accept(LoggerHost& logger); // only for host + + bool Read(void* buf, size_t count); + bool Write(const void* buf, size_t count); + + bool IsInitialized() const { + return sock_fd != -1; + } + +private: + int sock_fd; // Socket file Descriptor + struct sockaddr_in addr; // socket address + + ConnSock() = default; // for accept +}; diff --git a/AsanovDamir/laba2/host_sock.cpp b/AsanovDamir/laba2/host_sock.cpp new file mode 100644 index 0000000..5abe720 --- /dev/null +++ b/AsanovDamir/laba2/host_sock.cpp @@ -0,0 +1,63 @@ +#include +#include "HostUtils/HostWindow.hpp" +#include "HostUtils/hostProcessing.hpp" +#include "ClientUtils/clientProcessing.hpp" +#include "conn_sock.hpp" +#include "semaphore.hpp" +#include "logger.hpp" +#include +#include + +int main(int argc, char* argv[]) { + + // take port + if (argc != 2) { + std::cerr << "Usage: ./host " << std::endl; + return EXIT_FAILURE; + } + + // initialize some stuff + int port = std::stoi(argv[1]); + std::vector books = { + {"Book 1", 10}, + {"Book 2", 5}, + {"Book 3", 20}, + {"Book 4", 0} + }; + Semaphore semaphore(1); + + auto& logger = LoggerHost::get_instance(); + + // Create hostSocket for incomming connection requests from client + ConnSock hostSocket(port, logger); + if (!hostSocket.IsInitialized()) { + logger.log(Status::ERROR, "Failed to initialize host socket"); + return EXIT_FAILURE; + } + + // Make child process + pid_t pid = fork(); + if (pid == -1) { + + // Error + logger.log(Status::ERROR, "Failed to fork client"); + return EXIT_FAILURE; + + } else if (pid == 0) { + + // this is child process -> start client + ConnSock clientSocket(port, LoggerClient::get_instance()); + if (!clientSocket.IsInitialized()) { + logger.log(Status::ERROR, "Failed to initialize client socket"); + return EXIT_FAILURE; + } + return processClient(port, semaphore, clientSocket, books); + + } else { + + // this is main process -> start host + QApplication app(argc, argv); + return processHost(port, semaphore, hostSocket, books, app, pid); + + } +} diff --git a/AsanovDamir/laba2/logger.hpp b/AsanovDamir/laba2/logger.hpp new file mode 100644 index 0000000..65d2e86 --- /dev/null +++ b/AsanovDamir/laba2/logger.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include +#include + +enum class Status : bool +{ +INFO, +ERROR +}; + +class LoggerClient +{ +public: + static LoggerClient& get_instance() + { + static LoggerClient instance; + return instance; + } + + void log(Status status, const std::string& message) + { + if (status == Status::INFO) + std::cout << "[CLIENT][INFO] " << message << std::endl; + else + std::cout << "[CLIENT][ERROR] " << message << std::endl; + } + +private: + LoggerClient() = default; + LoggerClient(const LoggerClient&) = delete; + LoggerClient& operator=(const LoggerClient&) = delete; +}; + +class LoggerHost +{ +public: + static LoggerHost& get_instance() + { + static LoggerHost instance; + return instance; + } + + void log(Status status, const std::string& message) + { + if (status == Status::INFO) + std::cout << "[HOST][INFO] " << message << std::endl; + else + std::cout << "[HOST][ERROR] " << message << std::endl; + } + +private: + LoggerHost() = default; + LoggerHost(const LoggerHost&) = delete; + LoggerHost& operator=(const LoggerHost&) = delete; +}; diff --git a/AsanovDamir/laba2/main.cpp b/AsanovDamir/laba2/main.cpp deleted file mode 100644 index 64cd771..0000000 --- a/AsanovDamir/laba2/main.cpp +++ /dev/null @@ -1,6 +0,0 @@ - - -int main() { - - return 0; -} diff --git a/AsanovDamir/laba2/run.sh b/AsanovDamir/laba2/run.sh deleted file mode 100644 index e33b684..0000000 --- a/AsanovDamir/laba2/run.sh +++ /dev/null @@ -1 +0,0 @@ -sudo ./build/DamirAsanov Config.txt \ No newline at end of file diff --git a/AsanovDamir/laba2/runHost.sh b/AsanovDamir/laba2/runHost.sh new file mode 100644 index 0000000..acafec7 --- /dev/null +++ b/AsanovDamir/laba2/runHost.sh @@ -0,0 +1,2 @@ +#!/bin/bash +./build/host_sock 10104 diff --git a/AsanovDamir/laba2/semaphore.cpp b/AsanovDamir/laba2/semaphore.cpp new file mode 100644 index 0000000..9277f64 --- /dev/null +++ b/AsanovDamir/laba2/semaphore.cpp @@ -0,0 +1,32 @@ +#include "semaphore.hpp" +#include "logger.hpp" +#include +#include + +Semaphore::Semaphore(unsigned int value) { + if (sem_init(&semaphore, 0, value) == -1) { + LoggerHost::get_instance().log(Status::ERROR, "Semaphore initialization failed"); + } +} + +bool Semaphore::Wait() { + if (sem_wait(&semaphore) == -1) { + LoggerHost::get_instance().log(Status::ERROR, "Semaphore wait failed"); + return false; + } + return true; +} + +bool Semaphore::Post() { + if (sem_post(&semaphore) == -1) { + LoggerHost::get_instance().log(Status::ERROR, "Semaphore post failed"); + return false; + } + return true; +} + +Semaphore::~Semaphore() { + if (sem_destroy(&semaphore) == -1) { + LoggerHost::get_instance().log(Status::ERROR, "Semaphore destruction failed"); + } +} diff --git a/AsanovDamir/laba2/semaphore.hpp b/AsanovDamir/laba2/semaphore.hpp new file mode 100644 index 0000000..38cc089 --- /dev/null +++ b/AsanovDamir/laba2/semaphore.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include + +class Semaphore { +public: + Semaphore(unsigned int value); + bool Wait(); + bool Post(); + ~Semaphore(); + +private: + sem_t semaphore; +}; From c517fb59b7df9c41fea9bb91dc1b55d3663a0020 Mon Sep 17 00:00:00 2001 From: theguydie Date: Mon, 25 Nov 2024 00:11:55 +0300 Subject: [PATCH 09/13] implement conn_mq --- AsanovDamir/laba2/CMakeLists.txt | 22 ++++++ .../laba2/ClientUtils/clientProcessing.hpp | 9 +-- AsanovDamir/laba2/HostUtils/HostWindow.cpp | 6 +- AsanovDamir/laba2/HostUtils/HostWindow.hpp | 3 +- .../laba2/HostUtils/hostProcessing.hpp | 26 ++----- AsanovDamir/laba2/build.sh | 1 + AsanovDamir/laba2/conn.hpp | 11 +++ AsanovDamir/laba2/conn_mq.cpp | 76 +++++++++++++++++++ AsanovDamir/laba2/conn_mq.hpp | 24 ++++++ AsanovDamir/laba2/conn_sock.hpp | 3 +- AsanovDamir/laba2/host_mq.cpp | 57 ++++++++++++++ AsanovDamir/laba2/host_sock.cpp | 13 +++- AsanovDamir/laba2/runHostMq.sh | 2 + .../laba2/{runHost.sh => runHostSock.sh} | 0 14 files changed, 222 insertions(+), 31 deletions(-) create mode 100644 AsanovDamir/laba2/conn.hpp create mode 100644 AsanovDamir/laba2/conn_mq.cpp create mode 100644 AsanovDamir/laba2/conn_mq.hpp create mode 100644 AsanovDamir/laba2/host_mq.cpp create mode 100644 AsanovDamir/laba2/runHostMq.sh rename AsanovDamir/laba2/{runHost.sh => runHostSock.sh} (100%) diff --git a/AsanovDamir/laba2/CMakeLists.txt b/AsanovDamir/laba2/CMakeLists.txt index 50be2a4..e9dbbd9 100644 --- a/AsanovDamir/laba2/CMakeLists.txt +++ b/AsanovDamir/laba2/CMakeLists.txt @@ -8,6 +8,7 @@ find_package(Qt5 COMPONENTS Widgets REQUIRED) set(CMAKE_AUTOMOC ON) # for Q_OBJECT +############ sockets ############ set(SOURCES_SOCK host_sock.cpp HostUtils/HostWindow.cpp @@ -27,3 +28,24 @@ set(HEADERS_SOCK add_executable(host_sock ${SOURCES_SOCK} ${HEADERS_SOCK}) target_link_libraries(host_sock Qt5::Widgets) target_include_directories(host_sock PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + +############ queue ############ +set(SOURCES_MQ + host_mq.cpp + HostUtils/HostWindow.cpp + ClientUtils/ClientWindow.cpp + conn_mq.cpp + semaphore.cpp +) + +set(HEADERS_MQ + HostUtils/HostWindow.hpp + ClientUtils/ClientWindow.hpp + conn_mq.hpp + semaphore.hpp + logger.hpp +) + +add_executable(host_mq ${SOURCES_MQ} ${HEADERS_MQ}) +target_link_libraries(host_mq Qt5::Widgets) +target_include_directories(host_mq PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/AsanovDamir/laba2/ClientUtils/clientProcessing.hpp b/AsanovDamir/laba2/ClientUtils/clientProcessing.hpp index 561a44a..7c87264 100644 --- a/AsanovDamir/laba2/ClientUtils/clientProcessing.hpp +++ b/AsanovDamir/laba2/ClientUtils/clientProcessing.hpp @@ -7,14 +7,14 @@ #include #include -void listenForHostMessages(ConnSock& conn_sock, Semaphore& semaphore, ClientWindow& window, std::atomic& is_ranning) { +void listenForHostMessages(conn& conn, Semaphore& semaphore, ClientWindow& window, std::atomic& is_ranning) { auto& logger = LoggerClient::get_instance(); while (is_ranning) { semaphore.Wait(); // Start critical section char buffer[64] = {0}; - if (conn_sock.Read(buffer, sizeof(buffer))) { + if (conn.Read(buffer, sizeof(buffer))) { std::string response(buffer); if (response == "YES") { @@ -31,11 +31,11 @@ void listenForHostMessages(ConnSock& conn_sock, Semaphore& semaphore, ClientWind } semaphore.Post(); // End critical section - sleep(1); + sleep(0.1); } } -int processClient(int port, Semaphore& semaphore, ConnSock& conn_sock, const std::vector& books) { +int processClient(Semaphore& semaphore, conn& conn_sock, const std::vector& books) { auto& logger = LoggerClient::get_instance(); int argc = 0; @@ -56,7 +56,6 @@ int processClient(int port, Semaphore& semaphore, ConnSock& conn_sock, const std else { logger.log(Status::ERROR, "Failed to request the book: " + bookName.toStdString()); } - }); QObject::connect(&window, &ClientWindow::bookReturned, [&conn_sock, &logger](const QString& bookName) { diff --git a/AsanovDamir/laba2/HostUtils/HostWindow.cpp b/AsanovDamir/laba2/HostUtils/HostWindow.cpp index 4951de7..46120f9 100644 --- a/AsanovDamir/laba2/HostUtils/HostWindow.cpp +++ b/AsanovDamir/laba2/HostUtils/HostWindow.cpp @@ -5,13 +5,13 @@ #include #include -HostWindow::HostWindow(int port, const std::vector& books, QWidget* parent) - : QMainWindow(parent), hostPort(port) { +HostWindow::HostWindow(const std::string& hostTitle, const std::vector& books, QWidget* parent) + : QMainWindow(parent) { QWidget* centralWidget = new QWidget(this); QVBoxLayout* layout = new QVBoxLayout(centralWidget); - portLabel = new QLabel("Host Port: " + QString::number(port), this); + portLabel = new QLabel(QString::fromStdString(hostTitle), this); layout->addWidget(portLabel); bookList = new QListWidget(this); diff --git a/AsanovDamir/laba2/HostUtils/HostWindow.hpp b/AsanovDamir/laba2/HostUtils/HostWindow.hpp index 7094ea1..6de0a0b 100644 --- a/AsanovDamir/laba2/HostUtils/HostWindow.hpp +++ b/AsanovDamir/laba2/HostUtils/HostWindow.hpp @@ -16,7 +16,7 @@ class HostWindow : public QMainWindow { Q_OBJECT public: - HostWindow(int port, const std::vector& books, QWidget* parent = nullptr); + HostWindow(const std::string& hostTitle, const std::vector& books, QWidget* parent = nullptr); virtual ~HostWindow(); void updateBooks(const std::vector& books); @@ -32,5 +32,4 @@ private slots: QListWidget* bookList; QPushButton* terminateClientButton; QPushButton* terminateHostButton; - int hostPort; }; diff --git a/AsanovDamir/laba2/HostUtils/hostProcessing.hpp b/AsanovDamir/laba2/HostUtils/hostProcessing.hpp index ded9e22..495edfb 100644 --- a/AsanovDamir/laba2/HostUtils/hostProcessing.hpp +++ b/AsanovDamir/laba2/HostUtils/hostProcessing.hpp @@ -41,21 +41,14 @@ bool returnBook(std::vector& books, const std::string& bookName, LoggerHos return false; } -void listenForClientMessages(ConnSock& hostSocket, Semaphore& semaphore, std::vector& books, HostWindow& window, std::atomic& is_running) { +void listenForClientMessages(conn& conn, Semaphore& semaphore, std::vector& books, HostWindow& window, std::atomic& is_running) { auto& logger = LoggerHost::get_instance(); - ConnSock* conn = hostSocket.Accept(logger); - if (!conn) - { - logger.log(Status::ERROR, "Failed to accept connection"); - return; - } - while (is_running) { semaphore.Wait(); // Start critical section char buffer[1024] = {0}; - if (conn->Read(buffer, sizeof(buffer))) { + if (conn.Read(buffer, sizeof(buffer))) { std::string request(buffer); logger.log(Status::INFO, "Request is recieved: " + request); @@ -64,7 +57,7 @@ void listenForClientMessages(ConnSock& hostSocket, Semaphore& semaphore, std::ve if (takeBook(books, bookName, logger)) { std::string response = "YES"; - if (conn->Write(response.c_str(), response.size())) { + if (conn.Write(response.c_str(), response.size())) { logger.log(Status::INFO, "Host response successfully"); } else { @@ -74,7 +67,7 @@ void listenForClientMessages(ConnSock& hostSocket, Semaphore& semaphore, std::ve else { std::string response = "NO"; - if (conn->Write(response.c_str(), response.size())) { + if (conn.Write(response.c_str(), response.size())) { logger.log(Status::INFO, "Host response successfully"); } else { @@ -90,21 +83,18 @@ void listenForClientMessages(ConnSock& hostSocket, Semaphore& semaphore, std::ve } semaphore.Post(); // End critical section - sleep(1); + sleep(0.1); } - - delete conn; - logger.log(Status::INFO, "listenForClientMessages is over"); } -int processHost(int port, Semaphore& semaphore, ConnSock& hostSocket, std::vector books, QApplication& app, pid_t pid) { +int processHost(const std::string& hostTitle, Semaphore& semaphore, conn& conn, std::vector books, QApplication& app, pid_t pid) { LoggerHost::get_instance().log(Status::INFO, "Host is running"); std::atomic is_running(true); - HostWindow window(port, books); + HostWindow window(hostTitle, books); window.clientPid = pid; // Start host's listenning in new thread - std::thread listenerThread(listenForClientMessages, std::ref(hostSocket), std::ref(semaphore), std::ref(books), std::ref(window), std::ref(is_running)); + std::thread listenerThread(listenForClientMessages, std::ref(conn), std::ref(semaphore), std::ref(books), std::ref(window), std::ref(is_running)); window.show(); int result = app.exec(); // Start window in this thread diff --git a/AsanovDamir/laba2/build.sh b/AsanovDamir/laba2/build.sh index b69e5e8..e4507ec 100644 --- a/AsanovDamir/laba2/build.sh +++ b/AsanovDamir/laba2/build.sh @@ -10,5 +10,6 @@ find . -type f -name 'CMakeCache.txt' -delete find . -type f -name 'Makefile' -delete rm -rf CMakeFiles rm -rf host_sock_autogen +rm -rf host_mq_autogen rm -rf ClientUtils rm -rf HostUtils diff --git a/AsanovDamir/laba2/conn.hpp b/AsanovDamir/laba2/conn.hpp new file mode 100644 index 0000000..306846a --- /dev/null +++ b/AsanovDamir/laba2/conn.hpp @@ -0,0 +1,11 @@ +#pragma once + +class conn { +public: + virtual ~conn() {}; + + virtual bool Read(void* buf, size_t count) = 0; + virtual bool Write(const void* buf, size_t count) = 0; + + virtual bool IsInitialized() const = 0; +}; diff --git a/AsanovDamir/laba2/conn_mq.cpp b/AsanovDamir/laba2/conn_mq.cpp new file mode 100644 index 0000000..89e7d07 --- /dev/null +++ b/AsanovDamir/laba2/conn_mq.cpp @@ -0,0 +1,76 @@ +#include "conn_mq.hpp" +#include +#include +#include + +ConnMq::ConnMq(key_t key, LoggerHost& logger) : queueKey(key), isHost(true) +{ + int flags = IPC_CREAT | 0666; + queueId = msgget(key, flags); + + if (queueId == -1) { + logger.log(Status::ERROR, "Failed to open message queue"); + } +} + +ConnMq::ConnMq(key_t key, LoggerClient& logger) : queueKey(key), isHost(false) +{ + int flags = 0666; + queueId = msgget(key, flags); + + if (queueId == -1) { + logger.log(Status::ERROR, "Failed to open message queue"); + } +} + +ConnMq::~ConnMq() { + if (IsInitialized()) { + msgctl(queueId, IPC_RMID, nullptr); // TODO: some check + } +} + +bool ConnMq::Read(void* buf, size_t count) { + if (!IsInitialized()) { + return false; + } + + struct msgbuf { + long mtype; + char mtext[1024]; + } message; + + ssize_t bytesRead = msgrcv(queueId, &message, sizeof(message.mtext), !isHost + 1, 0); // !isHost: if host -> read client else read host + if (bytesRead == -1) { + return false; + } + + std::memcpy(buf, message.mtext, std::min(count, static_cast(bytesRead))); + return true; +} + +bool ConnMq::Write(const void* buf, size_t count) { + if (!IsInitialized()) { + return false; + } + + struct msgbuf { + long mtype; + char mtext[1024]; + } message; + + message.mtype = isHost + 1; // if host -> write as host (+ 1 because mtype > 0) + if (count > sizeof(message.mtext)) { + return false; + } + + std::memcpy(message.mtext, buf, count); + if (msgsnd(queueId, &message, count, 0) == -1) { + return false; + } + + return true; +} + +bool ConnMq::IsInitialized() const { + return (queueId != -1); +} diff --git a/AsanovDamir/laba2/conn_mq.hpp b/AsanovDamir/laba2/conn_mq.hpp new file mode 100644 index 0000000..115b74c --- /dev/null +++ b/AsanovDamir/laba2/conn_mq.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include +#include "conn.hpp" +#include "logger.hpp" + +class ConnMq : public conn { +public: + ConnMq(key_t key, LoggerHost& logger); + ConnMq(key_t key, LoggerClient& logger); + ~ConnMq() override; + + bool Read(void* buf, size_t count) override; + bool Write(const void* buf, size_t count) override; + + bool IsInitialized() const override; + +private: + key_t queueKey; + int queueId; + bool isHost; // for read/write msg type +}; diff --git a/AsanovDamir/laba2/conn_sock.hpp b/AsanovDamir/laba2/conn_sock.hpp index d0918b5..eedfbdf 100644 --- a/AsanovDamir/laba2/conn_sock.hpp +++ b/AsanovDamir/laba2/conn_sock.hpp @@ -4,8 +4,9 @@ #include #include #include "logger.hpp" +#include "conn.hpp" -class ConnSock { +class ConnSock : public conn { public: ConnSock(int hostPort, LoggerHost& logger); ConnSock(int hostPort, LoggerClient& logger); diff --git a/AsanovDamir/laba2/host_mq.cpp b/AsanovDamir/laba2/host_mq.cpp new file mode 100644 index 0000000..7505c36 --- /dev/null +++ b/AsanovDamir/laba2/host_mq.cpp @@ -0,0 +1,57 @@ +#include +#include "HostUtils/HostWindow.hpp" +#include "HostUtils/hostProcessing.hpp" +#include "ClientUtils/clientProcessing.hpp" +#include "conn_mq.hpp" +#include "semaphore.hpp" +#include "logger.hpp" +#include +#include + +int main(int argc, char* argv[]) { + + // initialize some stuff + key_t key = ftok("LALALA", 65); + std::vector books = { + {"Book 1", 10}, + {"Book 2", 5}, + {"Book 3", 20}, + {"Book 4", 0} + }; + Semaphore semaphore(1); + + auto& logger = LoggerHost::get_instance(); + + // TODO: replace after create child proccess + ConnMq hostMq(key, logger); + if (!hostMq.IsInitialized()) { + logger.log(Status::ERROR, "Failed to initialize host queue"); + return EXIT_FAILURE; + } + + // Make child process + pid_t pid = fork(); + if (pid == -1) { + + // Error + logger.log(Status::ERROR, "Failed to fork client"); + return EXIT_FAILURE; + + } else if (pid == 0) { + + // this is child process -> start client + ConnMq clientMq(key, LoggerClient::get_instance()); + if (!clientMq.IsInitialized()) { + logger.log(Status::ERROR, "Failed to initialize client queue"); + return EXIT_FAILURE; + } + return processClient(semaphore, clientMq, books); + + } else { + + // this is main process -> start host + QApplication app(argc, argv); + return processHost("Communication by queue", semaphore, hostMq, books, app, pid); + + } +} diff --git a/AsanovDamir/laba2/host_sock.cpp b/AsanovDamir/laba2/host_sock.cpp index 5abe720..d89150a 100644 --- a/AsanovDamir/laba2/host_sock.cpp +++ b/AsanovDamir/laba2/host_sock.cpp @@ -51,13 +51,22 @@ int main(int argc, char* argv[]) { logger.log(Status::ERROR, "Failed to initialize client socket"); return EXIT_FAILURE; } - return processClient(port, semaphore, clientSocket, books); + return processClient(semaphore, clientSocket, books); } else { // this is main process -> start host + ConnSock* conn = hostSocket.Accept(logger); + if (!conn) + { + logger.log(Status::ERROR, "Failed to accept connection"); + return EXIT_FAILURE; + } + QApplication app(argc, argv); - return processHost(port, semaphore, hostSocket, books, app, pid); + int res = processHost("Host Port: " + std::string(argv[1]), semaphore, *conn, books, app, pid); + delete conn; + return res; } } diff --git a/AsanovDamir/laba2/runHostMq.sh b/AsanovDamir/laba2/runHostMq.sh new file mode 100644 index 0000000..e21d592 --- /dev/null +++ b/AsanovDamir/laba2/runHostMq.sh @@ -0,0 +1,2 @@ +#!/bin/bash +./build/host_mq diff --git a/AsanovDamir/laba2/runHost.sh b/AsanovDamir/laba2/runHostSock.sh similarity index 100% rename from AsanovDamir/laba2/runHost.sh rename to AsanovDamir/laba2/runHostSock.sh From 1cd9b62eb5b5a19e7904daed44f1d76cb2b02f5b Mon Sep 17 00:00:00 2001 From: theguydie Date: Mon, 25 Nov 2024 11:05:34 +0300 Subject: [PATCH 10/13] implement conn_fifo --- AsanovDamir/laba2/CMakeLists.txt | 22 +++++++++ AsanovDamir/laba2/build.sh | 1 + AsanovDamir/laba2/conn_fifo.cpp | 83 ++++++++++++++++++++++++++++++++ AsanovDamir/laba2/conn_fifo.hpp | 23 +++++++++ AsanovDamir/laba2/host_fifo.cpp | 53 ++++++++++++++++++++ AsanovDamir/laba2/runHostFifo.sh | 2 + 6 files changed, 184 insertions(+) create mode 100644 AsanovDamir/laba2/conn_fifo.cpp create mode 100644 AsanovDamir/laba2/conn_fifo.hpp create mode 100644 AsanovDamir/laba2/host_fifo.cpp create mode 100644 AsanovDamir/laba2/runHostFifo.sh diff --git a/AsanovDamir/laba2/CMakeLists.txt b/AsanovDamir/laba2/CMakeLists.txt index e9dbbd9..75f3fce 100644 --- a/AsanovDamir/laba2/CMakeLists.txt +++ b/AsanovDamir/laba2/CMakeLists.txt @@ -49,3 +49,25 @@ set(HEADERS_MQ add_executable(host_mq ${SOURCES_MQ} ${HEADERS_MQ}) target_link_libraries(host_mq Qt5::Widgets) target_include_directories(host_mq PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + +############ fifo ############ +set(SOURCES_FIFO + host_fifo.cpp + HostUtils/HostWindow.cpp + ClientUtils/ClientWindow.cpp + conn_fifo.cpp + semaphore.cpp +) + +set(HEADERS_FIFO + HostUtils/HostWindow.hpp + ClientUtils/ClientWindow.hpp + conn_fifo.hpp + semaphore.hpp + logger.hpp +) + +add_executable(host_fifo ${SOURCES_FIFO} ${HEADERS_FIFO}) +target_link_libraries(host_fifo Qt5::Widgets) +target_include_directories(host_fifo PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + diff --git a/AsanovDamir/laba2/build.sh b/AsanovDamir/laba2/build.sh index e4507ec..a90ec84 100644 --- a/AsanovDamir/laba2/build.sh +++ b/AsanovDamir/laba2/build.sh @@ -11,5 +11,6 @@ find . -type f -name 'Makefile' -delete rm -rf CMakeFiles rm -rf host_sock_autogen rm -rf host_mq_autogen +rm -rf host_fifo_autogen rm -rf ClientUtils rm -rf HostUtils diff --git a/AsanovDamir/laba2/conn_fifo.cpp b/AsanovDamir/laba2/conn_fifo.cpp new file mode 100644 index 0000000..69f2bcb --- /dev/null +++ b/AsanovDamir/laba2/conn_fifo.cpp @@ -0,0 +1,83 @@ +#include "conn_fifo.hpp" + +ConnFifo::ConnFifo(const std::string& fifoPath, LoggerHost& logger) : path(fifoPath), readFd(-1), writeFd(-1) { + + if (mkfifo(path.c_str(), 0666) == -1) { + if (errno != EEXIST) { + logger.log(Status::ERROR, "Failed to create FIFO"); + return; + } + } + + readFd = open(path.c_str(), O_RDONLY | O_NONBLOCK); // open for read + if (readFd == -1) { + logger.log(Status::ERROR, "Failed to open FIFO for reading"); + return; + } + + writeFd = open(path.c_str(), O_WRONLY); // open for write + if (writeFd == -1) { + logger.log(Status::ERROR, "Failed to open FIFO for writing"); + close(readFd); + return; + } +} + +ConnFifo::ConnFifo(const std::string& fifoPath, LoggerClient& logger) : path(fifoPath), readFd(-1), writeFd(-1) { + + readFd = open(path.c_str(), O_RDONLY | O_NONBLOCK); // open for read + if (readFd == -1) { + logger.log(Status::ERROR, "Failed to open FIFO for reading"); + return; + } + + writeFd = open(path.c_str(), O_WRONLY); // open for write + if (writeFd == -1) { + logger.log(Status::ERROR, "Failed to open FIFO for writing"); + close(readFd); + return; + } +} + +bool ConnFifo::IsInitialized() const { + return writeFd != -1 && readFd != -1; +} + +ConnFifo::~ConnFifo() { + if (readFd != -1) { + close(readFd); + } + if (writeFd != -1) { + close(writeFd); + } + + if (!path.empty()) { + unlink(path.c_str()); + } +} + +bool ConnFifo::Read(void* buf, size_t count) { + if (!IsInitialized()) { + return false; + } + + ssize_t bytesRead = read(readFd, buf, count); + if (bytesRead == -1) { + return false; + } + + return bytesRead > 0; +} + +bool ConnFifo::Write(const void* buf, size_t count) { + if (!IsInitialized()) { + return false; + } + + ssize_t bytesWritten = write(writeFd, buf, count); + if (bytesWritten == -1) { + return false; + } + + return static_cast(bytesWritten) == count; +} diff --git a/AsanovDamir/laba2/conn_fifo.hpp b/AsanovDamir/laba2/conn_fifo.hpp new file mode 100644 index 0000000..113011a --- /dev/null +++ b/AsanovDamir/laba2/conn_fifo.hpp @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include "conn.hpp" +#include "logger.hpp" + +class ConnFifo : public conn { +public: + ConnFifo(const std::string& fifoPath, LoggerHost& logger); + ConnFifo(const std::string& fifoPath, LoggerClient& logger); + ~ConnFifo() override; + + bool Read(void* buf, size_t count) override; + bool Write(const void* buf, size_t count) override; + + bool IsInitialized() const override; + +private: + std::string path; + int readFd; + int writeFd; +}; diff --git a/AsanovDamir/laba2/host_fifo.cpp b/AsanovDamir/laba2/host_fifo.cpp new file mode 100644 index 0000000..c30a84b --- /dev/null +++ b/AsanovDamir/laba2/host_fifo.cpp @@ -0,0 +1,53 @@ +#include +#include "HostUtils/HostWindow.hpp" +#include "HostUtils/hostProcessing.hpp" +#include "ClientUtils/clientProcessing.hpp" +#include "conn_fifo.hpp" +#include "semaphore.hpp" +#include "logger.hpp" + +int main(int argc, char* argv[]) { + + // initialize some stuff + std::vector books = { + {"Book 1", 10}, + {"Book 2", 5}, + {"Book 3", 20}, + {"Book 4", 0} + }; + Semaphore semaphore(1); + + auto& logger = LoggerHost::get_instance(); + + ConnFifo hostFifo("/tmp/my_fifo", logger); + if (!hostFifo.IsInitialized()) { + logger.log(Status::ERROR, "Failed to initialize host queue"); + return EXIT_FAILURE; + } + + // Make child process + pid_t pid = fork(); + if (pid == -1) { + + // Error + logger.log(Status::ERROR, "Failed to fork client"); + return EXIT_FAILURE; + + } else if (pid == 0) { + + // this is child process -> start client + ConnFifo clientFifo("/tmp/my_fifo", LoggerClient::get_instance()); + if (!clientFifo.IsInitialized()) { + logger.log(Status::ERROR, "Failed to initialize client queue"); + return EXIT_FAILURE; + } + return processClient(semaphore, clientFifo, books); + + } else { + + // this is main process -> start host + QApplication app(argc, argv); + return processHost("Communication by queue", semaphore, hostFifo, books, app, pid); + + } +} diff --git a/AsanovDamir/laba2/runHostFifo.sh b/AsanovDamir/laba2/runHostFifo.sh new file mode 100644 index 0000000..d69c25f --- /dev/null +++ b/AsanovDamir/laba2/runHostFifo.sh @@ -0,0 +1,2 @@ +#!/bin/bash +./build/host_fifo From ce645b9ee0e48c46b4d3a24dda3b10d054c93ba4 Mon Sep 17 00:00:00 2001 From: theguydie Date: Mon, 25 Nov 2024 12:17:22 +0300 Subject: [PATCH 11/13] Add timer --- .../laba2/ClientUtils/ClientWindow.cpp | 6 ++-- .../laba2/ClientUtils/ClientWindow.hpp | 2 +- AsanovDamir/laba2/HostUtils/HostWindow.cpp | 32 +++++++++++++++++++ AsanovDamir/laba2/HostUtils/HostWindow.hpp | 9 ++++++ .../laba2/HostUtils/hostProcessing.hpp | 1 + AsanovDamir/laba2/runHostSock.sh | 2 +- 6 files changed, 47 insertions(+), 5 deletions(-) diff --git a/AsanovDamir/laba2/ClientUtils/ClientWindow.cpp b/AsanovDamir/laba2/ClientUtils/ClientWindow.cpp index f200f7a..cc0743a 100644 --- a/AsanovDamir/laba2/ClientUtils/ClientWindow.cpp +++ b/AsanovDamir/laba2/ClientUtils/ClientWindow.cpp @@ -34,15 +34,15 @@ void ClientWindow::createBookView(const std::vector& books) { selectButton->setEnabled(false); layout->addWidget(selectButton); - terminateClientButton = new QPushButton("Terminate Client", this); - layout->addWidget(terminateClientButton); + //terminateClientButton = new QPushButton("Terminate Client", this); + //layout->addWidget(terminateClientButton); // Enable button if book is choosed connect(bookList, &QListWidget::itemSelectionChanged, [this]() { selectButton->setEnabled(bookList->currentItem() != nullptr); }); connect(selectButton, &QPushButton::clicked, this, &ClientWindow::selectBook); - connect(terminateClientButton, &QPushButton::clicked, this, &ClientWindow::terminateClient); + //connect(terminateClientButton, &QPushButton::clicked, this, &ClientWindow::terminateClient); stackedWidget->addWidget(bookView); } diff --git a/AsanovDamir/laba2/ClientUtils/ClientWindow.hpp b/AsanovDamir/laba2/ClientUtils/ClientWindow.hpp index 1c6124a..2d1c6f8 100644 --- a/AsanovDamir/laba2/ClientUtils/ClientWindow.hpp +++ b/AsanovDamir/laba2/ClientUtils/ClientWindow.hpp @@ -44,5 +44,5 @@ private slots: QLabel* readingLabel; QPushButton* cancelReadingButton; - QPushButton* terminateClientButton; + // QPushButton* terminateClientButton; }; diff --git a/AsanovDamir/laba2/HostUtils/HostWindow.cpp b/AsanovDamir/laba2/HostUtils/HostWindow.cpp index 46120f9..a00f752 100644 --- a/AsanovDamir/laba2/HostUtils/HostWindow.cpp +++ b/AsanovDamir/laba2/HostUtils/HostWindow.cpp @@ -5,6 +5,8 @@ #include #include +static int secondsLeft = 5; + HostWindow::HostWindow(const std::string& hostTitle, const std::vector& books, QWidget* parent) : QMainWindow(parent) { @@ -26,12 +28,30 @@ HostWindow::HostWindow(const std::string& hostTitle, const std::vector& bo terminateHostButton = new QPushButton("Terminate Host", this); layout->addWidget(terminateHostButton); + timerLabel = new QLabel("Time left: 5 seconds", this); + layout->addWidget(timerLabel); + + clientTimer = new QTimer(this); + clientTimer->setInterval(1000); + connect(clientTimer, &QTimer::timeout, this, [this]() { + if (!clientTimer->isActive()) return; + + if (--secondsLeft <= 0) { + terminateClient(); + } else { + timerLabel->setText(QString("Time left: %1 seconds").arg(secondsLeft)); + } + }); + connect(terminateClientButton, &QPushButton::clicked, this, &HostWindow::terminateClient); connect(terminateHostButton, &QPushButton::clicked, this, &HostWindow::terminateHost); + connect(this, &HostWindow::resetSignalTimer, this, &HostWindow::resetTimer); setCentralWidget(centralWidget); setWindowTitle("Host Control Panel"); resize(400, 300); + + clientTimer->start(); } HostWindow::~HostWindow() {} @@ -44,6 +64,8 @@ void HostWindow::updateBooks(const std::vector& books) { } void HostWindow::terminateClient() { + clientTimer->stop(); + timerLabel->setText("Client terminated"); QMessageBox::information(this, "Terminate Client", "Client terminated."); LoggerHost::get_instance().log(Status::INFO, "Terminate Client"); kill(clientPid, SIGKILL); @@ -54,3 +76,13 @@ void HostWindow::terminateHost() { LoggerHost::get_instance().log(Status::INFO, "Terminate Host"); std::exit(0); } + +void HostWindow::resetTimer() { + secondsLeft = 5; + timerLabel->setText("Time left: 5 seconds"); + clientTimer->start(); +} + +void HostWindow::signalResetTimer() { + emit resetSignalTimer(); +} diff --git a/AsanovDamir/laba2/HostUtils/HostWindow.hpp b/AsanovDamir/laba2/HostUtils/HostWindow.hpp index 6de0a0b..7722f52 100644 --- a/AsanovDamir/laba2/HostUtils/HostWindow.hpp +++ b/AsanovDamir/laba2/HostUtils/HostWindow.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "Book.hpp" class HostWindow : public QMainWindow { @@ -20,16 +21,24 @@ class HostWindow : public QMainWindow { virtual ~HostWindow(); void updateBooks(const std::vector& books); + void signalResetTimer(); pid_t clientPid; // for kill +signals: + void resetSignalTimer(); + private slots: void terminateClient(); void terminateHost(); + void resetTimer(); private: QLabel* portLabel; QListWidget* bookList; QPushButton* terminateClientButton; QPushButton* terminateHostButton; + + QTimer* clientTimer; + QLabel* timerLabel; }; diff --git a/AsanovDamir/laba2/HostUtils/hostProcessing.hpp b/AsanovDamir/laba2/HostUtils/hostProcessing.hpp index 495edfb..2928581 100644 --- a/AsanovDamir/laba2/HostUtils/hostProcessing.hpp +++ b/AsanovDamir/laba2/HostUtils/hostProcessing.hpp @@ -49,6 +49,7 @@ void listenForClientMessages(conn& conn, Semaphore& semaphore, std::vector char buffer[1024] = {0}; if (conn.Read(buffer, sizeof(buffer))) { + window.signalResetTimer(); std::string request(buffer); logger.log(Status::INFO, "Request is recieved: " + request); diff --git a/AsanovDamir/laba2/runHostSock.sh b/AsanovDamir/laba2/runHostSock.sh index acafec7..1363b78 100644 --- a/AsanovDamir/laba2/runHostSock.sh +++ b/AsanovDamir/laba2/runHostSock.sh @@ -1,2 +1,2 @@ #!/bin/bash -./build/host_sock 10104 +./build/host_sock 10106 From 70a2093e8a06f5bdf5a02ef2012af27618c8a629 Mon Sep 17 00:00:00 2001 From: theguydie Date: Mon, 25 Nov 2024 23:15:29 +0300 Subject: [PATCH 12/13] Add history --- .../laba2/ClientUtils/ClientWindow.cpp | 25 ++++++++++++++- .../laba2/ClientUtils/ClientWindow.hpp | 3 ++ .../laba2/ClientUtils/clientProcessing.hpp | 14 ++++----- AsanovDamir/laba2/HostUtils/HostWindow.cpp | 26 ++++++++++++++-- AsanovDamir/laba2/HostUtils/HostWindow.hpp | 5 +++ .../laba2/HostUtils/hostProcessing.hpp | 15 ++++++--- AsanovDamir/laba2/Quation.txt | 18 ----------- AsanovDamir/laba2/README.md | 31 ++++++++++++------- AsanovDamir/laba2/build.sh | 20 ++++++------ AsanovDamir/laba2/conn_sock.cpp | 10 +++++- AsanovDamir/laba2/host_mq.cpp | 1 - AsanovDamir/laba2/runHostSock.sh | 2 +- 12 files changed, 114 insertions(+), 56 deletions(-) delete mode 100644 AsanovDamir/laba2/Quation.txt diff --git a/AsanovDamir/laba2/ClientUtils/ClientWindow.cpp b/AsanovDamir/laba2/ClientUtils/ClientWindow.cpp index cc0743a..e1df01e 100644 --- a/AsanovDamir/laba2/ClientUtils/ClientWindow.cpp +++ b/AsanovDamir/laba2/ClientUtils/ClientWindow.cpp @@ -1,5 +1,7 @@ #include "ClientWindow.hpp" #include +#include +#include #include #include "logger.hpp" @@ -9,9 +11,10 @@ ClientWindow::ClientWindow(const std::vector& books, QWidget* parent) createBookView(books); createReadingView(); + createHistoryView(); setCentralWidget(stackedWidget); - setWindowTitle("Client Control Panel"); + setWindowTitle("Client Window"); resize(400, 300); // Set started window @@ -62,6 +65,14 @@ void ClientWindow::createReadingView() { stackedWidget->addWidget(readingView); } +void ClientWindow::createHistoryView() { + historyList = new QListWidget(this); + historyList->setFixedWidth(350); + auto* widget = new QDockWidget("History", this); + widget->setWidget(historyList); + addDockWidget(Qt::LeftDockWidgetArea, widget); +} + void ClientWindow::selectBook() { if (bookList->currentItem()) { QString bookName = bookList->currentItem()->text().split(" - ").first(); @@ -77,17 +88,29 @@ void ClientWindow::cancelReading() { // Set started window stackedWidget->setCurrentIndex(0); + + addHistory("Cancelled reading: ", bookName, true); +} + +void ClientWindow::addHistory(const QString& action, const QString& bookName, bool success) { + QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"); + QString status = success ? "SUCCESS" : "FAIL"; + historyList->addItem(QString("[%1] %2 \"%3\": %4").arg(timestamp, action, bookName, status)); } void ClientWindow::onSuccessTakeBook() { // Set reading window stackedWidget->setCurrentIndex(1); + + addHistory("TAKE book: ", bookList->currentItem()->text().split(" - ").first(), true); } void ClientWindow::onFailedTakeBook() { // Cannot display this window.... // QMessageBox::warning(nullptr, "FAIL", "Failed to take book"); LoggerClient::get_instance().log(Status::ERROR, "Failed to take book"); + + addHistory("TAKE book: ", bookList->currentItem()->text().split(" - ").first(), false); } void ClientWindow::terminateClient() { diff --git a/AsanovDamir/laba2/ClientUtils/ClientWindow.hpp b/AsanovDamir/laba2/ClientUtils/ClientWindow.hpp index 2d1c6f8..5ade49b 100644 --- a/AsanovDamir/laba2/ClientUtils/ClientWindow.hpp +++ b/AsanovDamir/laba2/ClientUtils/ClientWindow.hpp @@ -22,6 +22,7 @@ class ClientWindow : public QMainWindow { void onSuccessTakeBook(); void onFailedTakeBook(); + void addHistory(const QString& action, const QString& bookName, bool success); signals: void bookSelected(const QString& bookName); @@ -35,9 +36,11 @@ private slots: private: void createBookView(const std::vector& books); void createReadingView(); + void createHistoryView(); QStackedWidget* stackedWidget; // For switch windows (started <-> reading) + QListWidget* historyList; QListWidget* bookList; QPushButton* selectButton; diff --git a/AsanovDamir/laba2/ClientUtils/clientProcessing.hpp b/AsanovDamir/laba2/ClientUtils/clientProcessing.hpp index 7c87264..a199881 100644 --- a/AsanovDamir/laba2/ClientUtils/clientProcessing.hpp +++ b/AsanovDamir/laba2/ClientUtils/clientProcessing.hpp @@ -31,11 +31,11 @@ void listenForHostMessages(conn& conn, Semaphore& semaphore, ClientWindow& windo } semaphore.Post(); // End critical section - sleep(0.1); + sleep(0.01); } } -int processClient(Semaphore& semaphore, conn& conn_sock, const std::vector& books) { +int processClient(Semaphore& semaphore, conn& conn, const std::vector& books) { auto& logger = LoggerClient::get_instance(); int argc = 0; @@ -46,11 +46,11 @@ int processClient(Semaphore& semaphore, conn& conn_sock, const std::vector std::atomic is_running(true); // Start thread with listenning socket - std::thread listenerThread(listenForHostMessages, std::ref(conn_sock), std::ref(semaphore), std::ref(window), std::ref(is_running)); + std::thread listenerThread(listenForHostMessages, std::ref(conn), std::ref(semaphore), std::ref(window), std::ref(is_running)); - QObject::connect(&window, &ClientWindow::bookSelected, [&conn_sock, &logger](const QString& bookName) { + QObject::connect(&window, &ClientWindow::bookSelected, [&semaphore, &conn, &logger](const QString& bookName) { std::string request = "TAKE " + bookName.toStdString(); - if (conn_sock.Write(request.c_str(), request.size())) { + if (conn.Write(request.c_str(), request.size())) { logger.log(Status::INFO, "Requested book: " + bookName.toStdString()); } else { @@ -58,9 +58,9 @@ int processClient(Semaphore& semaphore, conn& conn_sock, const std::vector } }); - QObject::connect(&window, &ClientWindow::bookReturned, [&conn_sock, &logger](const QString& bookName) { + QObject::connect(&window, &ClientWindow::bookReturned, [&conn, &logger](const QString& bookName) { std::string request = "RETURN " + bookName.toStdString(); - if (conn_sock.Write(request.c_str(), request.size())) { + if (conn.Write(request.c_str(), request.size())) { logger.log(Status::INFO, "Returned book: " + bookName.toStdString()); } else { diff --git a/AsanovDamir/laba2/HostUtils/HostWindow.cpp b/AsanovDamir/laba2/HostUtils/HostWindow.cpp index a00f752..a682d2b 100644 --- a/AsanovDamir/laba2/HostUtils/HostWindow.cpp +++ b/AsanovDamir/laba2/HostUtils/HostWindow.cpp @@ -2,6 +2,8 @@ #include "logger.hpp" #include #include +#include +#include #include #include @@ -46,10 +48,19 @@ HostWindow::HostWindow(const std::string& hostTitle, const std::vector& bo connect(terminateClientButton, &QPushButton::clicked, this, &HostWindow::terminateClient); connect(terminateHostButton, &QPushButton::clicked, this, &HostWindow::terminateHost); connect(this, &HostWindow::resetSignalTimer, this, &HostWindow::resetTimer); + connect(this, &HostWindow::stopSignalTimer, this, [this]() { + timerLabel->setText("Client reading"); + clientTimer->stop(); + }); + + historyList = new QListWidget(this); + QDockWidget* historyDock = new QDockWidget("History", this); + historyDock->setWidget(historyList); + addDockWidget(Qt::RightDockWidgetArea, historyDock); setCentralWidget(centralWidget); - setWindowTitle("Host Control Panel"); - resize(400, 300); + setWindowTitle("Host Window"); + resize(600, 450); clientTimer->start(); } @@ -63,6 +74,12 @@ void HostWindow::updateBooks(const std::vector& books) { } } +void HostWindow::addHistory(const QString& action, const QString& bookName, bool success) { + QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"); + QString status = success ? "SUCCESS" : "FAIL"; + historyList->addItem(QString("[%1] Client ID: 1, %2 \"%3\": %4").arg(timestamp, action, bookName, status)); +} + void HostWindow::terminateClient() { clientTimer->stop(); timerLabel->setText("Client terminated"); @@ -74,6 +91,7 @@ void HostWindow::terminateClient() { void HostWindow::terminateHost() { QMessageBox::information(this, "Terminate Host", "Host terminated."); LoggerHost::get_instance().log(Status::INFO, "Terminate Host"); + kill(clientPid, SIGKILL); // and kill client too std::exit(0); } @@ -86,3 +104,7 @@ void HostWindow::resetTimer() { void HostWindow::signalResetTimer() { emit resetSignalTimer(); } + +void HostWindow::signalStopTimer() { + emit stopSignalTimer(); +} diff --git a/AsanovDamir/laba2/HostUtils/HostWindow.hpp b/AsanovDamir/laba2/HostUtils/HostWindow.hpp index 7722f52..fdf0083 100644 --- a/AsanovDamir/laba2/HostUtils/HostWindow.hpp +++ b/AsanovDamir/laba2/HostUtils/HostWindow.hpp @@ -22,11 +22,15 @@ class HostWindow : public QMainWindow { void updateBooks(const std::vector& books); void signalResetTimer(); + void signalStopTimer(); + + void addHistory(const QString& action, const QString& bookName, bool success); pid_t clientPid; // for kill signals: void resetSignalTimer(); + void stopSignalTimer(); private slots: void terminateClient(); @@ -36,6 +40,7 @@ private slots: private: QLabel* portLabel; QListWidget* bookList; + QListWidget* historyList; QPushButton* terminateClientButton; QPushButton* terminateHostButton; diff --git a/AsanovDamir/laba2/HostUtils/hostProcessing.hpp b/AsanovDamir/laba2/HostUtils/hostProcessing.hpp index 2928581..9ff5353 100644 --- a/AsanovDamir/laba2/HostUtils/hostProcessing.hpp +++ b/AsanovDamir/laba2/HostUtils/hostProcessing.hpp @@ -49,14 +49,15 @@ void listenForClientMessages(conn& conn, Semaphore& semaphore, std::vector char buffer[1024] = {0}; if (conn.Read(buffer, sizeof(buffer))) { - window.signalResetTimer(); std::string request(buffer); logger.log(Status::INFO, "Request is recieved: " + request); if (request.rfind("TAKE ", 0) == 0) { std::string bookName = request.substr(5); - if (takeBook(books, bookName, logger)) + bool res = takeBook(books, bookName, logger); + if (res) { + window.signalStopTimer(); std::string response = "YES"; if (conn.Write(response.c_str(), response.size())) { logger.log(Status::INFO, "Host response successfully"); @@ -67,6 +68,7 @@ void listenForClientMessages(conn& conn, Semaphore& semaphore, std::vector } else { + window.signalResetTimer(); std::string response = "NO"; if (conn.Write(response.c_str(), response.size())) { logger.log(Status::INFO, "Host response successfully"); @@ -75,16 +77,21 @@ void listenForClientMessages(conn& conn, Semaphore& semaphore, std::vector logger.log(Status::ERROR, "Failed to response"); } } + + window.addHistory("TAKE book: ", QString::fromStdString(bookName), res); } else if (request.rfind("RETURN ", 0) == 0) { + window.signalResetTimer(); std::string bookName = request.substr(7); - returnBook(books, bookName, logger); // client unexpected any response on this request + bool res = returnBook(books, bookName, logger); // client unexpected any response on this request + + window.addHistory("RETURN book: ", QString::fromStdString(bookName), res); } window.updateBooks(books); } semaphore.Post(); // End critical section - sleep(0.1); + sleep(0.01); } } diff --git a/AsanovDamir/laba2/Quation.txt b/AsanovDamir/laba2/Quation.txt deleted file mode 100644 index a4d1032..0000000 --- a/AsanovDamir/laba2/Quation.txt +++ /dev/null @@ -1,18 +0,0 @@ -Вариант 23: - -Родственные. Один к одному. 4, 6, 7 - -Локальный сетевой чат. Хост и клиенты - участники чата. Хост может как сам отправлять личные и общие сообщения в чат, -так и передавать сообщения от других участников в общий чат или лично. Общие сообщения отображаются в чате у всех -подключенных участников, личные сообщения отображаются в чате только у отправителя и адресата. Если клиент не отправляет -сообщения больше минуты и не является хостом, то ему отправляется SIGKILL для завершения. Сообщения в чате появляются -в порядке времени их отправления. - -4. Очереди сообщений (mq_open). TYPE_CODE - mq. Работа с очередью должна производиться в каждом процессе уже после создания -дочернего (так, будто это несвязанные процессы). - -6. Именованные каналы (mkfifo). TYPE_CODE - fifo. Работа с именованным каналом должна производиться в каждом процессе уже -после создания дочернего (так, будто это несвязанные процессы). После окончания работы родительский процесс должен удалять -файл именованного канала. - -7. Сокеты (socket). TYPE_CODE – sock diff --git a/AsanovDamir/laba2/README.md b/AsanovDamir/laba2/README.md index ceb5ae7..ec0b2e9 100644 --- a/AsanovDamir/laba2/README.md +++ b/AsanovDamir/laba2/README.md @@ -2,21 +2,30 @@ # Автор -Асанов Дамир Русланович 5030102/10201 Лабораторная работа №1 вариант №9: +Асанов Дамир Русланович 5030102/10201 Лабораторная работа №2 вариант №23: ## Описание -Копировать содержимое папки 1 в папку 2(предварительно очищая содержимое папки 2) следующим образом: файлы с расширением “*.png” -должны помещаться в подпапку “IMG” папки 2, остальные — в подпапку “OTHERS” +Родственные. Один к одному. 4, 6, 7 + +Библиотека. Хост - библиотека, клиенты - читатели. Хост по запросу выдает книги (при наличии их в библиотеке), либо говорит что +книга занята/отсутсвует и получает их обратно. Клиенты запрашивают интересующие их книги, читают их какое-то время и возвращают +в библиотеку (скорость чтения случайна и линейна во времени). Статус всех книг библиотеки (название, сколько доступно свободных +копий, кем и когда взята) отражаются в графическом интерфейсе. В интерфейсе клиентов их история запросов (когда и какие книги +они брали и возвращали). + +4. Очереди сообщений (mq_open). TYPE_CODE - mq. Работа с очередью должна производиться в каждом процессе уже после создания +дочернего (так, будто это несвязанные процессы). + +6. Именованные каналы (mkfifo). TYPE_CODE - fifo. Работа с именованным каналом должна производиться в каждом процессе уже +после создания дочернего (так, будто это несвязанные процессы). После окончания работы родительский процесс должен удалять +файл именованного канала. + +7. Сокеты (socket). TYPE_CODE – sock ## Запуск введите команду ```bash build.sh```, чтобы собрать проект -введите команду ```bash run.sh```, чтобы запустить демона -введите команду ```bash kill```, чтобы остановить демона -введите команду ```bash reconfig```, чтобы демон перепрочитал конфиг - -форма конфига: -первая строчка - путь к первой папке, откуда будет происоходить копирование -вторая строчка - путь ко второй папке, куда будет копироваться -третья строчка - целое число - количество секунд между операцией копирования +введите команду ```bash runHostSock.sh```, чтобы запустить сокетное взаимодействие +введите команду ```bash runHostMq.sh```, чтобы запустить очередь сообщений взаимодействие +введите команду ```bash runHostFifo.sh```, чтобы запустить именнованный канал взаимодействие diff --git a/AsanovDamir/laba2/build.sh b/AsanovDamir/laba2/build.sh index a90ec84..2f8a9ff 100644 --- a/AsanovDamir/laba2/build.sh +++ b/AsanovDamir/laba2/build.sh @@ -4,13 +4,13 @@ cd build cmake .. make -find . -type f -name '*.o' -delete -find . -type f -name '*.cmake' -delete -find . -type f -name 'CMakeCache.txt' -delete -find . -type f -name 'Makefile' -delete -rm -rf CMakeFiles -rm -rf host_sock_autogen -rm -rf host_mq_autogen -rm -rf host_fifo_autogen -rm -rf ClientUtils -rm -rf HostUtils +# find . -type f -name '*.o' -delete +# find . -type f -name '*.cmake' -delete +# find . -type f -name 'CMakeCache.txt' -delete +# find . -type f -name 'Makefile' -delete +# rm -rf CMakeFiles +# rm -rf host_sock_autogen +# rm -rf host_mq_autogen +# rm -rf host_fifo_autogen +# rm -rf ClientUtils +# rm -rf HostUtils diff --git a/AsanovDamir/laba2/conn_sock.cpp b/AsanovDamir/laba2/conn_sock.cpp index 553744d..172ae76 100644 --- a/AsanovDamir/laba2/conn_sock.cpp +++ b/AsanovDamir/laba2/conn_sock.cpp @@ -13,7 +13,7 @@ ConnSock::ConnSock(int hostPort, LoggerHost& logger) : sock_fd(-1) { } addr.sin_family = AF_INET; - addr.sin_port = htons(hostPort); // Порт + addr.sin_port = htons(hostPort); addr.sin_addr.s_addr = INADDR_ANY; if (bind(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { @@ -79,6 +79,10 @@ ConnSock* ConnSock::Accept(LoggerHost& logger) { } bool ConnSock::Read(void* buf, size_t count) { + if (!IsInitialized()) { + return false; + } + ssize_t bytes_read = recv(sock_fd, buf, count, 0); if (bytes_read <= 0) { return false; @@ -87,6 +91,10 @@ bool ConnSock::Read(void* buf, size_t count) { } bool ConnSock::Write(const void* buf, size_t count) { + if (!IsInitialized()) { + return false; + } + ssize_t bytes_sent = send(sock_fd, buf, count, 0); if (bytes_sent <= 0) { return false; diff --git a/AsanovDamir/laba2/host_mq.cpp b/AsanovDamir/laba2/host_mq.cpp index 7505c36..84aa3b2 100644 --- a/AsanovDamir/laba2/host_mq.cpp +++ b/AsanovDamir/laba2/host_mq.cpp @@ -22,7 +22,6 @@ int main(int argc, char* argv[]) { auto& logger = LoggerHost::get_instance(); - // TODO: replace after create child proccess ConnMq hostMq(key, logger); if (!hostMq.IsInitialized()) { logger.log(Status::ERROR, "Failed to initialize host queue"); diff --git a/AsanovDamir/laba2/runHostSock.sh b/AsanovDamir/laba2/runHostSock.sh index 1363b78..303f51c 100644 --- a/AsanovDamir/laba2/runHostSock.sh +++ b/AsanovDamir/laba2/runHostSock.sh @@ -1,2 +1,2 @@ #!/bin/bash -./build/host_sock 10106 +./build/host_sock 10107 From fec1ab30af1c689a2680fe3d034aa6cc7778f310 Mon Sep 17 00:00:00 2001 From: theguydie Date: Mon, 25 Nov 2024 23:28:39 +0300 Subject: [PATCH 13/13] Delete trash files --- AsanovDamir/laba2/build.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/AsanovDamir/laba2/build.sh b/AsanovDamir/laba2/build.sh index 2f8a9ff..a90ec84 100644 --- a/AsanovDamir/laba2/build.sh +++ b/AsanovDamir/laba2/build.sh @@ -4,13 +4,13 @@ cd build cmake .. make -# find . -type f -name '*.o' -delete -# find . -type f -name '*.cmake' -delete -# find . -type f -name 'CMakeCache.txt' -delete -# find . -type f -name 'Makefile' -delete -# rm -rf CMakeFiles -# rm -rf host_sock_autogen -# rm -rf host_mq_autogen -# rm -rf host_fifo_autogen -# rm -rf ClientUtils -# rm -rf HostUtils +find . -type f -name '*.o' -delete +find . -type f -name '*.cmake' -delete +find . -type f -name 'CMakeCache.txt' -delete +find . -type f -name 'Makefile' -delete +rm -rf CMakeFiles +rm -rf host_sock_autogen +rm -rf host_mq_autogen +rm -rf host_fifo_autogen +rm -rf ClientUtils +rm -rf HostUtils