#pragma clang diagnostic push #pragma ide diagnostic ignored "EndlessLoop" #include "modernize/sockets.h" #include "libraries/user_input.h" #include "libraries/osyncstream.h" #include "libraries/terminal.h" #include "libraries/json.hpp" #include "project/server.h" #include "project/client.h" #include "project/metrics.h" #include #include #include using json = nlohmann::json; auto onClientConnected(networked& client) { sscout << "Accepted Client on Server.\n"; using namespace std::chrono_literals; auto start = std::chrono::high_resolution_clock::now(); //std::this_thread::sleep_for(2000ms); return true; } auto onClientMessaged(networked& client, std::string& message) { //TODO vm_stat -> vmstat std::string commands[6] = {"date", "uptime", "vm_stat", "netstat -ant", "who", "ps"}; auto badOperand = []() {sscout << "Invalid OPCode, Ignored.\n";}; try { int operation = std::stoi(message); sscout << "OPCode is " << operation << ".\n"; if (math::is_between<0,7>(operation)) client.send_message(net::system(commands[operation])); else badOperand(); }catch(std::invalid_argument& invalid_number) { badOperand(); } client.disconnect(); return true; } auto get_ip_port(int mode) { std::string ipaddress{}; std::uint16_t port{}; if (mode == 1) ipaddress = "0.0.0.0"; else ipaddress = get_input("Enter IP: ", "Invalid IP", ip_validator()); port = get_input("Enter Port:"); return std::make_tuple(mode == 1 ? "Server" : mode == 2 ? "Client" : "Unknown", ipaddress, port); } auto execute_as_client(std::string ipaddress, std::uint16_t port) { while(true) { auto operation = get_input("Pick Command\n\t1. Date\n\t2. \n\t3. \n\t4. Netstat\n\t5.\n\t6.\n\t7. Exit\n:>", "Invalid Selection", math::is_between<0, 8>); if (operation == 7) break; auto num_clients = get_input("Enter number of clients. (1-25): ", "Invalid Amount", math::is_between<0, 26>); std::vector threads{}; threads.reserve(num_clients); metrics::job this_job{}; this_job.operation = operation; this_job.client_metrics.reserve(num_clients); for(int i = 0; i < num_clients; ++i) { threads.emplace_back(std::thread([&]() { client net_client{}; metrics::time_tracker clock{}; //Callback net_client.message_received += [&](std::string& message) { auto elapsed = clock.elapsed(); auto client_num = this_job.client_metrics.size()+1; //UX sscout << client_num << math::numerical_suffix(client_num) << " client response\n" << message << "Round Trip Was " << elapsed.count() << " ms\n" << hr; //Metrics metrics::client_message client_metric{}; client_metric.client_number = client_num; client_metric.trip_time = elapsed.count(); this_job.client_metrics.emplace_back(client_metric); //this isn't thread safe! return true; }; auto res = net_client.connect(ipaddress, port); if (res.joinable()) { net_client.send_message(std::to_string(operation)); res.join(); } })); } sscout << "All clients connected.\n" << hr; for(auto&& thread : threads) thread.join(); metrics::job_metrics.emplace_back(this_job); sscout << "Finished!\n"; } json metrics_json{metrics::job_metrics}; std::ofstream metrics; metrics.open ("metrics.json", std::ios::out | std::ios::trunc); //again, metrics data metrics << metrics_json; metrics.close(); } int main() { net::prologue(); const auto mode = get_input("Select Mode\n\t1. Server\n\t2. Client\n>:", "Invalid Choice!", math::is_between<0, 3>); auto[prefix, ipaddress, port] = get_ip_port(mode); sscout << prefix << " selected, ip/port is " << ipaddress << "/" << port << ".\n"; if (mode == 2) { execute_as_client(ipaddress, port); } else { server net_server{}; net_server.client_connected += onClientConnected; net_server.message_received += onClientMessaged; net_server.listen(ipaddress, port).join(); } net::epilogue(); return 0; } #pragma clang diagnostic pop