From 21e2f6f999bac65dd1d9de6c88f90ad0eb44c0a5 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 11 Jan 2025 21:29:55 +0100 Subject: [PATCH] Prepare TCP support --- src/common/network/tcp_client_socket.cpp | 40 ++++++++++++++++++++++++ src/common/network/tcp_client_socket.hpp | 33 +++++++++++++++++++ src/common/network/tcp_server_socket.cpp | 35 +++++++++++++++++++++ src/common/network/tcp_server_socket.hpp | 25 +++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 src/common/network/tcp_client_socket.cpp create mode 100644 src/common/network/tcp_client_socket.hpp create mode 100644 src/common/network/tcp_server_socket.cpp create mode 100644 src/common/network/tcp_server_socket.hpp diff --git a/src/common/network/tcp_client_socket.cpp b/src/common/network/tcp_client_socket.cpp new file mode 100644 index 00000000..a30e4d5a --- /dev/null +++ b/src/common/network/tcp_client_socket.cpp @@ -0,0 +1,40 @@ +#include "tcp_client_socket.hpp" + +namespace network +{ + tcp_client_socket::tcp_client_socket(SOCKET s, const address& target) + : socket(s), + target_(target) + { + } + + bool tcp_client_socket::send(const void* data, const size_t size) const + { + const auto res = ::send(this->get_socket(), static_cast(data), static_cast(size), 0); + return static_cast(res) == size; + } + + bool tcp_client_socket::send(const std::string_view data) const + { + return this->send(data.data(), data.size()); + } + + bool tcp_client_socket::receive(std::string& data) const + { + char buffer[0x2000]; + + const auto result = recv(this->get_socket(), buffer, static_cast(sizeof(buffer)), 0); + if (result == SOCKET_ERROR) + { + return false; + } + + data.assign(buffer, buffer + result); + return true; + } + + address tcp_client_socket::get_target() const + { + return this->target_; + } +} diff --git a/src/common/network/tcp_client_socket.hpp b/src/common/network/tcp_client_socket.hpp new file mode 100644 index 00000000..f09bbf9a --- /dev/null +++ b/src/common/network/tcp_client_socket.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "socket.hpp" + +#include + +namespace network +{ + class tcp_server_socket; + + class tcp_client_socket : public socket + { + // TODO: Construct and connect client! + + tcp_client_socket() = default; + ~tcp_client_socket() = default; + + tcp_client_socket(tcp_client_socket&& obj) noexcept = default; + tcp_client_socket& operator=(tcp_client_socket&& obj) noexcept = default; + + [[maybe_unused]] bool send(const void* data, size_t size) const; + [[maybe_unused]] bool send(std::string_view data) const; + bool receive(std::string& data) const; + + address get_target() const; + + private: + address target_{}; + + friend tcp_server_socket; + tcp_client_socket(SOCKET s, const address& target); + }; +} diff --git a/src/common/network/tcp_server_socket.cpp b/src/common/network/tcp_server_socket.cpp new file mode 100644 index 00000000..da9b5437 --- /dev/null +++ b/src/common/network/tcp_server_socket.cpp @@ -0,0 +1,35 @@ +#include "tcp_server_socket.hpp" + +namespace network +{ + tcp_server_socket::tcp_server_socket(const int af) + : socket(af, SOCK_STREAM, IPPROTO_TCP) + { + } + + tcp_client_socket tcp_server_socket::accept() + { + this->listen(); + + address a{}; + auto len = a.get_max_size(); + auto s = ::accept(this->get_socket(), &a.get_addr(), &len); + + if (s == INVALID_SOCKET) + { + return {}; + } + + return tcp_client_socket{s, a}; + } + + void tcp_server_socket::listen() + { + if (this->listening_) + { + return; + } + + this->listening_ = ::listen(this->get_socket(), 32) == 0; + } +} diff --git a/src/common/network/tcp_server_socket.hpp b/src/common/network/tcp_server_socket.hpp new file mode 100644 index 00000000..78289f01 --- /dev/null +++ b/src/common/network/tcp_server_socket.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "socket.hpp" +#include "tcp_client_socket.hpp" + +namespace network +{ + class tcp_server_socket : public socket + { + tcp_server_socket(int af); + + tcp_server_socket() = default; + ~tcp_server_socket() = default; + + tcp_server_socket(tcp_server_socket&& obj) noexcept = default; + tcp_server_socket& operator=(tcp_server_socket&& obj) noexcept = default; + + tcp_client_socket accept(); + + private: + bool listening_{false}; + + void listen(); + }; +}