#pragma once #include "modernize/sockets.h" #include "libraries/event.h" #include "libraries/osyncstream.h" #include class networked { protected: SOCKET socket; public: explicit networked(SOCKET existing) { socket = existing; } auto disconnect() -> void { if (!is_valid()) return; //socket is closed. net::closesocket(socket); socket = INVALID_SOCKET; } [[nodiscard]] auto receive_message() const -> std::string { if (!is_valid()) return ""; return net::recv(socket); } auto send_message(const std::string& message) const -> void { if (!is_valid()) return; net::send(socket, message);} [[nodiscard]] auto is_valid() const -> bool { return socket != INVALID_SOCKET; } }; class client : public networked { auto accept_message() -> void //add const later { while(is_valid()) /* Accept all messages */ { auto message = receive_message(); if (message.empty() && is_valid()) //connection is closed or broken. { disconnect(); break; } message_received.execute(message); } } public: event message_received {}; explicit client() : networked(net::socket(AF_INET, SOCK_STREAM, 0)){} auto connect(const std::string& ip, const port port) -> std::thread { const auto address = net::getaddrinfo(ip, std::to_string(port)); auto remote_address = net::getaddrinfo(ip, std::to_string(port)); if (net::connect(socket, remote_address) < 0) return std::thread(); auto thread = std::thread(&client::accept_message, this); return thread; } }; class server : networked { auto accept_clients() -> void { while(is_valid()) { auto client = networked(accept(socket, nullptr, nullptr)); client_connected.execute(client); #ifdef THREADED std::thread(&server::accept_client_message, this, client).detach(); #else std::thread(&server::accept_client_message, this, client).join(); #endif } } auto accept_client_message(networked client) -> void //add const later { //using namespace std::chrono_literals; //std::this_thread::sleep_for(2000ms); while(client.is_valid()) /* Accept all messages */ { auto message = client.receive_message(); if (message.empty() && client.is_valid()) //Client could have disconnected after check but PRIOR to recv. { sscout << "Client Connection Lost\n"; client.disconnect(); break; } message_received.execute(client, message); } } public: event client_connected {}; event message_received {}; auto listen(const std::string& ip, const port port) -> std::thread { const auto address = net::getaddrinfo(ip, std::to_string(port)); if (net::bind(socket, address) < 0) { sscout << "Error binding.\n"; return std::thread(); } if (net::listen(socket) < 0) { sscout << "Error listening.\n"; return std::thread(); } sscout << "Listening ... \n"; return std::thread(&server::accept_clients, this); } explicit server() : networked(net::socket(AF_INET, SOCK_STREAM, 0)){} };