//Simulation of an external IP-TCP client using ASIO lib #include #include "asio.hpp" #include #include #include #include #include #include "PublisherData.h" #include "DataModel.h" #include "IpTcpClient.h" #include "NetClient.h" #include #include #include #include #include #include #include "easylogging++.h" INITIALIZE_EASYLOGGINGPP constexpr unsigned int BUFFER_SIZE = 256; //Format of Date in the log files constexpr char logDateFormat[] = "%Y-%m-%d %H:%M:%S"; constexpr unsigned short DATE_HEADER_SIZE = 19; const auto session_id = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); using asio::ip::tcp; std::atomic_char keyboardInput = '0'; void readInput() { while (1){ keyboardInput = std::cin.get(); std::cin.get(); } } //Takes a message with log file body and extracts the last written log date //This values is taken for the next log file downloading, to minimize download data size //and prevent the aplication from downloading data twice long long parseDate(net::Message& msg) { if (msg.header.size < DATE_HEADER_SIZE) return 0; std::stringstream ss; //Find last occurence of '\n' with reverse iteration auto res = std::find_if(msg.body.rbegin(), msg.body.rend(), [](const uint8_t i) { return i == '\n'; }); if (res == msg.body.rend()) { //No occurence of '\n', log file is empty return 0; } //Find last but one occurence of '\n' using reverse iteration res = std::find_if(res+1, msg.body.rend(), [](const uint8_t i) { return i == '\n'; }); if (res == msg.body.rend()) { //No second occurence of '\n' //-> only one line of log, set iterator to first position res = msg.body.rend(); } //Extreact the header and parse it to proper date format for (size_t i = 0; i < DATE_HEADER_SIZE; i++) { ss << *(--res); } std::tm tm = {}; ss >> std::get_time(&tm, logDateFormat); long long tp = std::chrono::system_clock::from_time_t(std::mktime(&tm)).time_since_epoch().count(); return tp; } void writeToFile(net::Message& msg) { std::ofstream file; std::stringstream fileName; switch(msg.header.id){ case net::MessageTypes::ServerData: fileName << "backup_data_" << session_id << ".log"; break; case net::MessageTypes::ServerLog: fileName << "backup_log_" << session_id << ".log"; break; default: break; } file.open(fileName.str(), std::ios_base::app); for (auto c : msg.body) file << c; file.close(); } int main() { NetClient c; long long lastLog = 0; LOG(INFO) << "press key to connect"; std::cin.get(); c.Connect("127.0.0.1", 7777); std::thread keyboardInputThread(readInput); bool connectionCancelled = false; while (!connectionCancelled) { if (c.IsConnected()) { if (!c.Incoming().empty()) { auto msg = c.Incoming().pop_front().msg; net::Message messageSend; std::string buf = ""; switch (msg.header.id) { case net::MessageTypes::ServerAlert: // Server has responded to a ping request LOG(INFO) << "Server Alert notification"; for (size_t index = 0; index < msg.header.size; index++) { buf += msg.body.at(index); } LOG(INFO) << buf; break; case net::MessageTypes::ServerAccept: // Server has responded to a ping request LOG(INFO) << "Server Accepted Connection"; break; case net::MessageTypes::ServerDeny: // Server has responded to a ping request LOG(INFO) << "Server Denied Connection"; connectionCancelled = true; break; case net::MessageTypes::ServerLog: // Server has send log data LOG(INFO) << "Received Server Log File"; LOG(INFO) << "Received " << msg.header.size << " Bytes"; writeToFile(msg); lastLog = parseDate(msg); break; case net::MessageTypes::ServerData: LOG(INFO) << "Received Server Data"; LOG(INFO) << "Received " << msg.header.size << " Bytes"; writeToFile(msg); break; default: break; } } if (keyboardInput != '0') { net::Message messageSend; switch (keyboardInput) { //Log case 'l': LOG(INFO) << "Request server log files"; messageSend.header.id = net::MessageTypes::ServerLog; messageSend << lastLog; c.Send(messageSend); break; case 'd': LOG(INFO) << "Request permanent server data"; messageSend.header.id = net::MessageTypes::ServerData; c.Send(messageSend); break; case 't': LOG(INFO) << "Request temporary server data"; messageSend.header.id = net::MessageTypes::ServerData; c.Send(messageSend); break; case 'c': LOG(INFO) << "Request closing connection"; messageSend.header.id = net::MessageTypes::ServerCloseConnection; c.Send(messageSend); break; default: break; } keyboardInput = '0'; } } else { LOG(INFO) << "Server Down"; break; } } LOG(INFO) << "End excution"; return 0; }