diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/ocl/net/unique_socket.hpp | 142 |
1 files changed, 93 insertions, 49 deletions
diff --git a/include/ocl/net/unique_socket.hpp b/include/ocl/net/unique_socket.hpp index b47dbac..ed1d549 100644 --- a/include/ocl/net/unique_socket.hpp +++ b/include/ocl/net/unique_socket.hpp @@ -9,6 +9,7 @@ #include <core/config.hpp> +#include <stdexcept> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> @@ -22,26 +23,20 @@ namespace ocl::net { - class unique_socket; - - /// ============================================================================= - /// @brief Modem container concept, a container to read and write on a network stream. - /// ============================================================================= class unique_socket final { public: - using socket_type = int64_t; + using socket_type = int; using error_type = bool; using condition_type = bool; + using socket_state = int; private: - socket_type fd_{}; + socket_type socket_{}; condition_type is_server_{false}; - error_type bad_{true}; + error_type bad_{false}; public: - const error_type& bad{bad_}; - unique_socket() = default; ~unique_socket() @@ -50,64 +45,113 @@ namespace ocl::net } unique_socket& operator=(const unique_socket&) = delete; - unique_socket(const unique_socket&) = default; + unique_socket(const unique_socket&) = delete; + + unique_socket& operator=(unique_socket&& other) noexcept + { + if (this != &other) + { + destroy(); + socket_ = other.socket_; + is_server_ = other.is_server_; + bad_ = other.bad_; + other.socket_ = 0; + other.bad_ = true; + } - static constexpr auto local_address_ip4 = "127.0.0.1"; - static constexpr auto local_address_ip6 = "::1"; - static constexpr const auto backlog_count = 5U; + return *this; + } - unique_socket read(const char* out, std::size_t len) noexcept + unique_socket(unique_socket&& other) noexcept + : socket_(other.socket_), is_server_(other.is_server_), bad_(other.bad_) { - if (!out || !len) - return {}; + other.socket_ = 0; + other.bad_ = true; + } - socket_type cl_{fd_}; + static constexpr auto local_address_ip4 = "127.0.0.1"; + static constexpr auto backlog_count = 5U; - if (this->is_server_) - cl_ = ::accept(fd_, nullptr, nullptr); + const error_type& bad() + { + return bad_; + } + + unique_socket::socket_state state() noexcept + { + socket_state error = 0; + socklen_t len = sizeof(error); + getsockopt(socket_, SOL_SOCKET, SO_ERROR, &error, &len); - auto ret = ::recv(cl_, static_cast<void*>(const_cast<char*>(out)), len, 0); + return error; + } - unique_socket sock; + unique_socket accept() noexcept + { + socket_type cl_{-1}; + + if (this->is_server_) + cl_ = ::accept(socket_, nullptr, nullptr); - sock.fd_ = cl_; - sock.bad_ = ret > 0L; + unique_socket ret_sock; + ret_sock.socket_ = cl_; - return std::move(sock); + return std::move(ret_sock); } - unique_socket& write(const char* out, std::size_t len) noexcept + unique_socket read_server_buffer(char* out, std::size_t len) { - if (!out) - return *this; + if (!out || !len) + return {}; - if (!len) - return *this; + if (!is_server_) + { + return {}; + } - auto ret = ::send(fd_, out, len, 0); + auto ret_sock = accept(); - bad_ = !(ret >= 0L); + if (ret_sock.socket_ == -1) + throw std::invalid_argument("no connection to accept."); - return *this; + auto ret = ::recv(ret_sock.socket_, static_cast<void*>(out), len, 0); + ret_sock.bad_ = ret < 0L; + + return ret_sock; } - unique_socket& write(const std::string& out) noexcept + void read_client_buffer(char* out, std::size_t len) { - if (out.empty()) - return *this; + if (!out || !len) + return; - auto ret = ::send(fd_, out.data(), out.size(), 0); + if (is_server_) + return; - bad_ = !(ret >= 0L); + auto ret = ::recv(this->socket_, static_cast<void*>(out), len, 0); + this->bad_ = ret < 0L; + } - return *this; + void write_from_buffer(const char* out, std::size_t len) + { + if (!out) + return; + + if (!len) + return; + + auto ret = ::send(socket_, out, len, 0); + + bad_ = ret < 0L; } template <uint16_t port> static unique_socket make_socket(const std::string& address, const bool is_server) { unique_socket sock; - sock.construct<AF_INET, SOCK_STREAM, port>(address.c_str(), is_server); + + if (!sock.construct<AF_INET, SOCK_STREAM, port>(address.c_str(), is_server)) + throw std::invalid_argument("invalid socket argument"); return sock; } @@ -119,10 +163,10 @@ namespace ocl::net static_assert(af != 0, "Address family is zero"); static_assert(kind != 0, "Kind is zero"); - fd_ = ::socket(af, kind, 0); + socket_ = ::socket(af, kind, 0); is_server_ = is_server; - if (fd_ == -1) + if (socket_ == -1) return false; struct sockaddr_in addr_; @@ -134,28 +178,28 @@ namespace ocl::net if (!is_server) { - const auto ret = ::connect(fd_, reinterpret_cast<struct sockaddr*>(&addr_), sizeof(addr_)); + const auto ret = ::connect(socket_, reinterpret_cast<struct sockaddr*>(&addr_), sizeof(addr_)); return ret == 0L; } - int ret = ::bind(fd_, (struct sockaddr*)&addr_, sizeof(addr_)); + int ret = ::bind(socket_, (struct sockaddr*)&addr_, sizeof(addr_)); bad_ = ret == -1; - ::listen(fd_, unique_socket::backlog_count); + ::listen(socket_, unique_socket::backlog_count); return bad_ == false; } bool destroy() noexcept { - if (!fd_) + if (!socket_) return false; - ::shutdown(fd_, SHUT_RDWR); - ::close(fd_); + ::shutdown(socket_, SHUT_RDWR); + ::close(socket_); - fd_ = 0L; + socket_ = 0L; return true; } |
