#include "socket/socket.h" namespace Network { Socket::Socket(int domain, int type, int protocol) { init(domain, type, protocol); } Socket::~Socket() { destruct(); } int Socket::init(int domain, int type, int protocol) { this->domain = domain; sock = ::socket(domain, type, protocol); // sock = ::WSASocket(domain, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED); if (sock == INVALID_SOCKET) spdlog::critical("socket()"); valid_ = true; return 0; } void Socket::destruct() { if (!valid_) return; #ifdef _WIN32 ::closesocket(sock); #elif __linux__ ::close(sock); #endif valid_ = false; } Socket::operator SOCKET() { if (valid_) { valid_ = false; return sock; } spdlog::critical("No valid socket created."); return INVALID_SOCKET; } void Socket::set(const SOCKET __sock, int __domain) { if (__sock == INVALID_SOCKET) { spdlog::critical("socket()"); std::exit(EXIT_FAILURE); } destruct(); sock = __sock; valid_ = true; }; int Socket::setsockopt(int level, int optname, const char* optval, int optlen) { return ::setsockopt(sock, level, optname, optval, optlen); } int Socket::bind(Address __addr) { bindAddr = __addr; int retVal = ::bind(sock, &__addr.addr, __addr.length); if (retVal == INVALID_SOCKET) { spdlog::critical("bind()"); std::exit(EXIT_FAILURE); } return retVal; } int Socket::connect(Address& serveraddr) { std::string addr_string = serveraddr; int retVal = -1; if (serveraddr.family == AF_INET) retVal = ::connect(sock, (const sockaddr*)&serveraddr.addr_in, serveraddr.length); else retVal = ::connect(sock, (const sockaddr*)&serveraddr.addr_in6, serveraddr.length); memcpy(&remoteAddr, &serveraddr, sizeof(Address)); if (retVal == INVALID_SOCKET) { #ifdef _WIN32 int err = WSAGetLastError(); spdlog::error("connect() failed: WSA error {} (0x{:X})", err, err); #endif spdlog::error("connect()"); } return retVal; } int Socket::recvfrom(void* __restrict __buf, size_t __n, int __flags, struct Address& __addr) { std::lock_guard lock(readMutex); int retVal = ::recvfrom(sock, (char*)__buf, __n, __flags, &__addr.addr, &__addr.length); if (retVal == SOCKET_ERROR) spdlog::error("recvfrom()"); return retVal; } int Socket::sendto(const void* __buf, size_t __n, int __flags, struct Address __addr) { std::lock_guard lock(writeMutex); int retVal = ::sendto(sock, (char*)__buf, __n, __flags, &__addr.addr, __addr.length); if (retVal == SOCKET_ERROR) spdlog::error("sendto()"); return retVal; } Socket::Socket(const Socket& other_) { memcpy(this, &other_, sizeof(Socket)); valid_ = false; } Socket::Socket(Socket&& other_) noexcept { other_.valid_ = false; memcpy(this, &other_, sizeof(Socket)); valid_ = true; } Socket& Socket::operator=(const Socket& other_) { memcpy(this, &other_, sizeof(Socket)); valid_ = false; return *this; } Socket& Socket::operator=(Socket&& other_) noexcept { other_.valid_ = false; memcpy(this, &other_, sizeof(Socket)); valid_ = true; return *this; } } // namespace Socket