122 lines
3.1 KiB
C++
122 lines
3.1 KiB
C++
#pragma once
|
|
|
|
|
|
// STL includes
|
|
#include <array>
|
|
#include <cerrno>
|
|
#include <cstdint>
|
|
#include <expected>
|
|
#include <span>
|
|
|
|
// C stdlib includes
|
|
#include <netinet/in.h>
|
|
#include <sys/poll.h>
|
|
|
|
|
|
namespace tcp {
|
|
|
|
|
|
using HostString = std::array<char, 64>;
|
|
|
|
//
|
|
//
|
|
// Non blocking server
|
|
//
|
|
//
|
|
|
|
struct ServerSettings {
|
|
uint16_t port = 0;
|
|
};
|
|
|
|
class NonBlockingServer {
|
|
public:
|
|
NonBlockingServer(ServerSettings settings);
|
|
NonBlockingServer(const NonBlockingServer&) = delete;
|
|
NonBlockingServer(NonBlockingServer&&) = delete;
|
|
NonBlockingServer& operator=(const NonBlockingServer&) = delete;
|
|
NonBlockingServer& operator=(NonBlockingServer&&) = delete;
|
|
~NonBlockingServer();
|
|
|
|
[[nodiscard]] std::expected<void, int> start_listening();
|
|
|
|
bool next_client_available();
|
|
[[nodiscard]] std::expected<void, int> accept_next_client();
|
|
void disconnect();
|
|
|
|
[[nodiscard]] std::expected<int, int>
|
|
send(std::span<const std::byte> data);
|
|
|
|
[[nodiscard]] std::expected<int, int>
|
|
recv(std::span<std::byte> buffer);
|
|
|
|
bool data_available();
|
|
|
|
[[nodiscard]] std::expected<std::array<char, 16>, int>
|
|
get_client_ip_as_string();
|
|
|
|
private:
|
|
ServerSettings m_settings;
|
|
const struct sockaddr_in m_serverAddress;
|
|
int m_serverSocket = -1;
|
|
|
|
pollfd m_serverPfdIn = {.fd = -1, .events = POLLIN};
|
|
pollfd m_clientPfdIn = {.fd = -1, .events = POLLIN};
|
|
|
|
int m_clientSocket = -1;
|
|
struct sockaddr m_clientAddress;
|
|
socklen_t m_clientAddrLen = sizeof(m_clientAddress);
|
|
|
|
|
|
[[nodiscard]] std::expected<void, int> create_socket();
|
|
void close_server_socket();
|
|
void close_client_socket();
|
|
};
|
|
|
|
|
|
//
|
|
//
|
|
// Non blocking client
|
|
//
|
|
//
|
|
|
|
|
|
class NonBlockingClient {
|
|
public:
|
|
NonBlockingClient() = default;
|
|
NonBlockingClient(const NonBlockingClient&) = delete;
|
|
NonBlockingClient(NonBlockingClient&&) = delete;
|
|
NonBlockingClient& operator=(const NonBlockingClient&) = delete;
|
|
NonBlockingClient& operator=(NonBlockingClient&&) = delete;
|
|
~NonBlockingClient();
|
|
|
|
// clang-format off
|
|
[[nodiscard]] std::expected<void, int>
|
|
connect(HostString host, uint16_t port);
|
|
// clang-format on
|
|
|
|
void disconnect();
|
|
|
|
[[nodiscard]] std::expected<int, int> get_last_connection_status();
|
|
|
|
bool data_available();
|
|
|
|
[[nodiscard]] std::expected<int, int> recv(std::span<std::byte> buffer);
|
|
[[nodiscard]] std::expected<int, int> send(std::span<const std::byte> data);
|
|
|
|
private:
|
|
int m_socket = -1;
|
|
pollfd m_pfdOut = {.fd = -1, .events = POLLOUT};
|
|
pollfd m_pfdIn = {.fd = -1, .events = POLLIN};
|
|
|
|
bool m_startedNewConAttempt = false;
|
|
int m_lastKnownConStatus = ENOTCONN;
|
|
|
|
void close_socket();
|
|
|
|
[[nodiscard]] std::expected<void, int> create_socket();
|
|
[[nodiscard]] std::expected<bool, int> new_error_codes_available();
|
|
};
|
|
|
|
|
|
} // namespace tcp
|