#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 #include #include #include using json = nlohmann::json; std::mutex metrics_mutex {}; auto onClientConnected(networked& client) { sscout << "Accepted Client on Server.\n"; using namespace std::chrono_literals; auto start = std::chrono::high_resolution_clock::now(); return true; } auto onClientMessaged(networked& client, std::string& message) { std::string commands[6] = {"date", "uptime", "vmstat", "netstat -ant", "who", "ps"}; auto badOperand = []() {sscout << "Invalid OPCode, Ignored.\n";}; try { int operation = std::stoi(message); sscout << "Received OPCode " << operation << " from Client.\n"; if (math::is_between<0,7>(operation)) client.send_message(net::system(commands[operation-1])); else badOperand(); }catch(std::invalid_argument& invalid_number) { badOperand(); } client.disconnect(); sscout << "Disconnected Client.\n"; 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. Uptime\n\t3. Memory Use\n\t4. Netstat\n\t5. Current Users\n\t6. Running Processes\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-100): ", "Invalid Amount", math::is_between<0, 101>); std::vector threads{}; threads.reserve(num_clients); metrics::job this_job{}; this_job.operation = operation; this_job.client_metrics.reserve(num_clients); auto failures = 0; 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(); const std::lock_guard lock(metrics_mutex); 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" << term::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(); }else{ ++failures; } })); } sscout << "Client setup complete.\n" << term::hr; for(auto&& thread : threads) thread.join(); if (failures) sscout << failures << " client(s) failed to connect."; 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(); sscout << "Metrics Saved to metrics.json\n"; } int main() { term::use_unicode(); sscout << "┌───────────╖\n" << "│ Project 1 ║\n" << "╘═══════════╝\n"; sscout << "┌────────────────────╖\n" << "│ Riley Strickland ║\n" << "│ Jacob Jerris ║\n" << "│ Jacqueline Shrader ║\n" << "╘════════════════════╝\n"; 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(); sscout << "┌────────────────────╖\n" << "│ Thanks for using ║\n" << "╘════════════════════╝\n"; return 0; }