#if WIN32 #define NOMINMAX #endif #include "modernize/sockets.h" #include "libraries/user_input.h" #include "libraries/osyncstream.h" #include "libraries/terminal.h" #include "libraries/json.hpp" #include #include "project/server.h" #include "project/client.h" #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) { try { int operation = std::stoi(message); sscout << "OPCode is " << operation << ".\n"; switch(operation) { case 1: client.send_message(net::system("date")); break; case 4: client.send_message(net::system("netstat -ant")); break; default: break; } }catch(std::invalid_argument& invalid_number) { sscout << "Invalid OPCode, Ignored.\n"; } 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: "); 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) { auto num_clients = get_input("Enter number of clients. (1-25): ", "Invalid Amount", math::is_between<0, 26>); auto operation = get_input("Pick Command\n\t1. Date\n\t2. \n\t3. \n\t4. Netstat\n:>", "Invalid Selection", math::is_between<0, 5>); std::vector threads{}; threads.reserve(num_clients); auto internal_tracker = 0; //Stats tracking. std::vector internal_stats{}; internal_stats.reserve(num_clients); for(int i = 0; i < num_clients; ++i) { threads.emplace_back(std::thread([&]() { client net_client{}; auto start = std::chrono::high_resolution_clock::now(); net_client.message_received += [start, &internal_tracker, &internal_stats](std::string& message) { auto end = std::chrono::high_resolution_clock::now(); std::chrono::duration elapsed = end-start; sscout << internal_tracker << math::numerical_suffix(internal_tracker++) << " client response\n" << message << "Round Trip Was " << elapsed.count() << " ms\n" << hr; internal_stats.emplace_back(elapsed.count()); //Stats tracking 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(); sscout << "Finished!\n"; json metrics_json = internal_stats; 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>); while (true) { 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(); } } }