Finish project
This commit is contained in:
parent
5b0fae4589
commit
3562653d7e
@ -2,4 +2,5 @@ cmake_minimum_required(VERSION 3.17)
|
|||||||
project(Project_1)
|
project(Project_1)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
add_executable(Project_1 main.cpp modernize/sockets.cpp)
|
add_executable(Project_1 main.cpp modernize/sockets.cpp)
|
@ -7,21 +7,22 @@
|
|||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
class osyncstream_locked final
|
class osyncstream_locked final
|
||||||
{
|
{
|
||||||
std::unique_lock<std::recursive_mutex> lock_;
|
std::unique_lock<std::recursive_mutex> lock_;
|
||||||
std::ostream& stream_;
|
std::basic_ostream<T>& stream_;
|
||||||
public:
|
public:
|
||||||
osyncstream_locked(std::recursive_mutex& mtx, std::ostream& stream) : lock_(mtx), stream_(stream) {} //construct and lock the mutex from osyncstream.
|
osyncstream_locked(std::recursive_mutex& mtx, std::basic_ostream<T>& stream) : lock_(mtx), stream_(stream) {} //construct and lock the mutex from osyncstream.
|
||||||
osyncstream_locked(const osyncstream_locked& o) = delete;
|
osyncstream_locked(const osyncstream_locked& o) = delete;
|
||||||
/* A recursive mutex isn't great here (reference forwarding would be better except...only a recursive mutex can assure lock-before-release on ownership transfer */
|
/* A recursive mutex isn't great here (reference forwarding would be better except...only a recursive mutex can assure lock-before-release on ownership transfer */
|
||||||
template<typename T>
|
template<typename J>
|
||||||
friend auto operator<<(osyncstream_locked&& os, const T& d) -> osyncstream_locked&&
|
friend auto operator<<(osyncstream_locked&& os, const J& d) -> osyncstream_locked&&
|
||||||
{
|
{
|
||||||
os.stream_ << d;
|
os.stream_ << d;
|
||||||
return std::move(os); /* move semantics :( ... thanks Clang/GCC */
|
return std::move(os); /* move semantics :( ... thanks Clang/GCC */
|
||||||
}
|
}
|
||||||
friend auto operator<<(osyncstream_locked&& os, std::ostream& (*func)(std::ostream&)) -> std::ostream&
|
friend auto operator<<(osyncstream_locked&& os, std::basic_ostream<T>& (*func)(std::basic_ostream<T>&)) -> std::basic_ostream<T>&
|
||||||
{
|
{
|
||||||
return os.stream_ << func;
|
return os.stream_ << func;
|
||||||
}
|
}
|
||||||
@ -31,20 +32,21 @@ public:
|
|||||||
~osyncstream_locked() = default;
|
~osyncstream_locked() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
class osyncstream final
|
class osyncstream final
|
||||||
{
|
{
|
||||||
std::recursive_mutex mutex_{};
|
std::recursive_mutex mutex_{};
|
||||||
std::ostream& stream_;
|
std::basic_ostream<T>& stream_;
|
||||||
public:
|
public:
|
||||||
explicit osyncstream(std::ostream& stream) : stream_(stream) {}
|
explicit osyncstream(std::basic_ostream<T>& stream) : stream_(stream) {}
|
||||||
template<typename T>
|
template<typename J>
|
||||||
friend auto operator<<(osyncstream& os, const T& d) -> osyncstream_locked
|
friend auto operator<<(osyncstream& os, const J& d) -> osyncstream_locked<T>
|
||||||
{
|
{
|
||||||
std::unique_lock<std::recursive_mutex> lock(os.mutex_);
|
std::unique_lock<std::recursive_mutex> lock(os.mutex_);
|
||||||
os.stream_ << d;
|
os.stream_ << d;
|
||||||
return osyncstream_locked { os.mutex_, os.stream_ };
|
return osyncstream_locked<T> { os.mutex_, os.stream_ };
|
||||||
}
|
}
|
||||||
friend auto operator<<(osyncstream& os, std::ostream& (*func)(std::ostream&)) -> osyncstream_locked
|
friend auto operator<<(osyncstream& os, std::basic_ostream<T>& (*func)(std::basic_ostream<T>&)) -> osyncstream_locked<T>
|
||||||
{
|
{
|
||||||
std::unique_lock<std::recursive_mutex> lock(os.mutex_);
|
std::unique_lock<std::recursive_mutex> lock(os.mutex_);
|
||||||
os.stream_ << func;
|
os.stream_ << func;
|
||||||
@ -54,11 +56,17 @@ public:
|
|||||||
|
|
||||||
struct streams
|
struct streams
|
||||||
{
|
{
|
||||||
static std::ostream& cout;
|
static std::basic_ostream<char>& cout;
|
||||||
static std::ostream& cerr;
|
static std::basic_ostream<char>& cerr;
|
||||||
|
static std::basic_ostream<wchar_t>& wcout;
|
||||||
|
static std::basic_ostream<wchar_t>& wcerr;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& streams::cout = std::cout;
|
inline std::basic_ostream<char>& streams::cout = std::cout;
|
||||||
inline std::ostream& streams::cerr = std::cerr;
|
inline std::basic_ostream<char>& streams::cerr = std::cerr;
|
||||||
|
inline std::basic_ostream<wchar_t>& streams::wcout = std::wcout;
|
||||||
|
inline std::basic_ostream<wchar_t>& streams::wcerr = std::wcerr;
|
||||||
[[maybe_unused]] inline osyncstream sscout(streams::cout); // NOLINT(cert-err58-cpp)
|
[[maybe_unused]] inline osyncstream sscout(streams::cout); // NOLINT(cert-err58-cpp)
|
||||||
[[maybe_unused]] inline osyncstream sscerr(streams::cerr); // NOLINT(cert-err58-cpp)
|
[[maybe_unused]] inline osyncstream sscerr(streams::cerr); // NOLINT(cert-err58-cpp)
|
||||||
|
[[maybe_unused]] inline osyncstream sswcout(streams::wcout); // NOLINT(cert-err58-cpp)
|
||||||
|
[[maybe_unused]] inline osyncstream sswcerr(streams::wcerr); // NOLINT(cert-err58-cpp)
|
@ -1,18 +1,34 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <codecvt>
|
||||||
|
|
||||||
inline auto terminal_size()
|
|
||||||
{
|
|
||||||
struct winsize result{};
|
|
||||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &result);
|
|
||||||
return std::make_tuple(result.ws_col, result.ws_row);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class CharT, class Traits>
|
namespace term
|
||||||
std::basic_ostream<CharT,Traits>& hr(std::basic_ostream<CharT, Traits>& os)
|
|
||||||
{
|
{
|
||||||
auto [width, height] = terminal_size();
|
|
||||||
os << std::setfill('-') << std::setw(width) << "\n" << std::setfill(' ') << std::setw(0);
|
inline auto use_unicode()
|
||||||
return os;
|
{
|
||||||
|
std::locale unicode( std::locale(), new std::codecvt_utf8_utf16<wchar_t> );
|
||||||
|
std::cout.imbue(unicode);
|
||||||
|
std::wcout.imbue(unicode);
|
||||||
|
}
|
||||||
|
inline auto size()
|
||||||
|
{
|
||||||
|
struct winsize result{};
|
||||||
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &result); //POSIX
|
||||||
|
return std::make_tuple(result.ws_col, result.ws_row);
|
||||||
|
}
|
||||||
|
std::basic_ostream<char>& hr(std::basic_ostream<char>& os)
|
||||||
|
{
|
||||||
|
auto [width, height] = size();
|
||||||
|
os << std::setfill('-') << std::setw(width) << "\n" << std::setfill(' ') << std::setw(0);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
std::basic_ostream<wchar_t>& hr(std::basic_ostream<wchar_t>& os)
|
||||||
|
{
|
||||||
|
auto [width, height] = size();
|
||||||
|
os << std::setfill(L'─') << std::setw(width) << "\n" << std::setfill(L' ') << std::setw(0);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
}
|
}
|
61
main.cpp
61
main.cpp
@ -1,5 +1,3 @@
|
|||||||
#pragma clang diagnostic push
|
|
||||||
#pragma ide diagnostic ignored "EndlessLoop"
|
|
||||||
#include "modernize/sockets.h"
|
#include "modernize/sockets.h"
|
||||||
#include "libraries/user_input.h"
|
#include "libraries/user_input.h"
|
||||||
#include "libraries/osyncstream.h"
|
#include "libraries/osyncstream.h"
|
||||||
@ -12,33 +10,34 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <locale>
|
||||||
|
#include <codecvt>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
auto onClientConnected(networked& client)
|
auto onClientConnected(networked& client)
|
||||||
{
|
{
|
||||||
sscout << "Accepted Client on Server.\n";
|
sscout << "Accepted Client on Server.\n";
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
auto start = std::chrono::high_resolution_clock::now();
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
//std::this_thread::sleep_for(2000ms);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
auto onClientMessaged(networked& client, std::string& message)
|
auto onClientMessaged(networked& client, std::string& message)
|
||||||
{
|
{
|
||||||
//TODO vm_stat -> vmstat
|
std::string commands[6] = {"date", "uptime", "vmstat", "netstat -ant", "who", "ps"};
|
||||||
std::string commands[6] = {"date", "uptime", "vm_stat", "netstat -ant", "who", "ps"};
|
|
||||||
auto badOperand = []() {sscout << "Invalid OPCode, Ignored.\n";};
|
auto badOperand = []() {sscout << "Invalid OPCode, Ignored.\n";};
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int operation = std::stoi(message);
|
int operation = std::stoi(message);
|
||||||
sscout << "OPCode is " << operation << ".\n";
|
sscout << "Received OPCode " << operation << " from Client.\n";
|
||||||
if (math::is_between<0,7>(operation))
|
if (math::is_between<0,7>(operation))
|
||||||
client.send_message(net::system(commands[operation-1]));
|
client.send_message(net::system(commands[operation-1]));
|
||||||
else
|
else
|
||||||
badOperand();
|
badOperand();
|
||||||
}catch(std::invalid_argument& invalid_number) { badOperand(); }
|
}catch(std::invalid_argument& invalid_number) { badOperand(); }
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
|
sscout << "Disconnected Client.\n";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +49,7 @@ auto get_ip_port(int mode)
|
|||||||
ipaddress = "0.0.0.0";
|
ipaddress = "0.0.0.0";
|
||||||
else
|
else
|
||||||
ipaddress = get_input<std::string>("Enter IP: ", "Invalid IP", ip_validator());
|
ipaddress = get_input<std::string>("Enter IP: ", "Invalid IP", ip_validator());
|
||||||
port = get_input<std::uint16_t>("Enter Port:");
|
port = get_input<std::uint16_t>("Enter Port: ");
|
||||||
return std::make_tuple(mode == 1 ? "Server" : mode == 2 ? "Client" : "Unknown", ipaddress, port);
|
return std::make_tuple(mode == 1 ? "Server" : mode == 2 ? "Client" : "Unknown", ipaddress, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +66,7 @@ auto execute_as_client(std::string ipaddress, std::uint16_t port)
|
|||||||
metrics::job this_job{};
|
metrics::job this_job{};
|
||||||
this_job.operation = operation;
|
this_job.operation = operation;
|
||||||
this_job.client_metrics.reserve(num_clients);
|
this_job.client_metrics.reserve(num_clients);
|
||||||
|
auto failures = 0;
|
||||||
for(int i = 0; i < num_clients; ++i)
|
for(int i = 0; i < num_clients; ++i)
|
||||||
{
|
{
|
||||||
threads.emplace_back(std::thread([&]()
|
threads.emplace_back(std::thread([&]()
|
||||||
@ -81,9 +80,9 @@ auto execute_as_client(std::string ipaddress, std::uint16_t port)
|
|||||||
auto client_num = this_job.client_metrics.size()+1;
|
auto client_num = this_job.client_metrics.size()+1;
|
||||||
//UX
|
//UX
|
||||||
sscout << client_num << math::numerical_suffix(client_num) << " client response\n"
|
sscout << client_num << math::numerical_suffix(client_num) << " client response\n"
|
||||||
<< message
|
<< message
|
||||||
<< "Round Trip Was " << elapsed.count() << " ms\n"
|
<< "Round Trip Was " << elapsed.count() << " ms\n"
|
||||||
<< hr;
|
<< term::hr;
|
||||||
//Metrics
|
//Metrics
|
||||||
metrics::client_message client_metric{};
|
metrics::client_message client_metric{};
|
||||||
client_metric.client_number = client_num;
|
client_metric.client_number = client_num;
|
||||||
@ -96,12 +95,16 @@ auto execute_as_client(std::string ipaddress, std::uint16_t port)
|
|||||||
{
|
{
|
||||||
net_client.send_message(std::to_string(operation));
|
net_client.send_message(std::to_string(operation));
|
||||||
res.join();
|
res.join();
|
||||||
|
}else{
|
||||||
|
++failures;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
sscout << "All clients connected.\n" << hr;
|
sscout << "Client setup complete.\n" << term::hr;
|
||||||
for(auto&& thread : threads)
|
for(auto&& thread : threads)
|
||||||
thread.join();
|
thread.join();
|
||||||
|
if (failures)
|
||||||
|
sscout << failures << " client(s) failed to connect.";
|
||||||
metrics::job_metrics.emplace_back(this_job);
|
metrics::job_metrics.emplace_back(this_job);
|
||||||
sscout << "Finished!\n";
|
sscout << "Finished!\n";
|
||||||
}
|
}
|
||||||
@ -110,15 +113,36 @@ auto execute_as_client(std::string ipaddress, std::uint16_t port)
|
|||||||
metrics.open ("metrics.json", std::ios::out | std::ios::trunc); //again, metrics data
|
metrics.open ("metrics.json", std::ios::out | std::ios::trunc); //again, metrics data
|
||||||
metrics << metrics_json;
|
metrics << metrics_json;
|
||||||
metrics.close();
|
metrics.close();
|
||||||
|
sscout << "Metrics Saved to metrics.json\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto operator<<(std::basic_ostream<wchar_t>& os, const std::string& str) -> std::basic_ostream<wchar_t>&
|
||||||
|
{
|
||||||
|
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
|
||||||
|
std::wstring wide = converter.from_bytes(str);
|
||||||
|
os << wide;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
term::use_unicode();
|
||||||
|
sswcout
|
||||||
|
<< L"┌───────────╖\n"
|
||||||
|
<< L"│ Project 1 ║\n"
|
||||||
|
<< L"╘═══════════╝\n";
|
||||||
|
|
||||||
|
sswcout
|
||||||
|
<< L"┌────────────────────╖\n"
|
||||||
|
<< L"│ Riley Strickland ║\n"
|
||||||
|
<< L"│ Jacob Jerris ║\n"
|
||||||
|
<< L"│ Jacqueline Shrader ║\n"
|
||||||
|
<< L"╘════════════════════╝\n";
|
||||||
|
|
||||||
net::prologue();
|
net::prologue();
|
||||||
const auto mode = get_input<int>("Select Mode\n\t1. Server\n\t2. Client\n>:", "Invalid Choice!",
|
const auto mode = get_input<int>("Select Mode\n\t1. Server\n\t2. Client\n>:", "Invalid Choice!",
|
||||||
math::is_between<0, 3>);
|
math::is_between<0, 3>);
|
||||||
auto[prefix, ipaddress, port] = get_ip_port(mode);
|
auto[prefix, ipaddress, port] = get_ip_port(mode);
|
||||||
sscout << prefix << " selected, ip/port is " << ipaddress << "/" << port << ".\n";
|
sscout << prefix << " selected, ip/port is " << ipaddress << ":" << port << ".\n";
|
||||||
if (mode == 2) {
|
if (mode == 2) {
|
||||||
execute_as_client(ipaddress, port);
|
execute_as_client(ipaddress, port);
|
||||||
} else {
|
} else {
|
||||||
@ -128,6 +152,11 @@ int main() {
|
|||||||
net_server.listen(ipaddress, port).join();
|
net_server.listen(ipaddress, port).join();
|
||||||
}
|
}
|
||||||
net::epilogue();
|
net::epilogue();
|
||||||
|
|
||||||
|
sswcout
|
||||||
|
<< L"┌────────────────────╖\n"
|
||||||
|
<< L"│ Thanks for using ║\n"
|
||||||
|
<< L"╘════════════════════╝\n";
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#pragma clang diagnostic pop
|
|
Loading…
Reference in New Issue
Block a user