X Tutup
 #include "List.h" #ifdef POSIX #include #include #include #endif namespace Socket { List::List() noexcept { #ifdef WIN32 this->obj_list = INVALID_HANDLE_VALUE; #elif POSIX this->obj_list = ~0; #else #error "Undefine platform" #endif } List::List(List &&obj) noexcept : obj_list(obj.obj_list) { #ifdef WIN32 obj.obj_list = INVALID_HANDLE_VALUE; obj.poll_events.swap(this->poll_events); #elif POSIX obj.obj_list = ~0; obj.epoll_events.swap(this->epoll_events); #else #error "Undefine platform" #endif } List::~List() noexcept { this->destroy(); } bool List::create(const size_t startListSize) { this->destroy(); #ifdef WIN32 this->obj_list = (HANDLE) 1; if (startListSize > 0) { this->poll_events.reserve(startListSize); } return true; #elif POSIX this->obj_list = ::epoll_create(startListSize); if (this->obj_list == ~0) { return false; } if (startListSize > 0) { this->epoll_events.reserve(startListSize); } return true; #else #error "Undefine platform" #endif } void List::destroy() noexcept { if (this->is_created() ) { #ifdef WIN32 this->obj_list = INVALID_HANDLE_VALUE; this->poll_events.clear(); #elif POSIX ::close(this->obj_list); this->obj_list = ~0; this->epoll_events.clear(); #else #error "Undefine platform" #endif } } bool List::is_created() const noexcept { #ifdef WIN32 return this->obj_list != INVALID_HANDLE_VALUE; #elif POSIX return this->obj_list != ~0; #else #error "Undefine platform" #endif } bool List::addSocket(const Socket &sock) noexcept { if (this->is_created() == false) { return false; } #ifdef WIN32 WSAPOLLFD event = { sock.get_handle(), POLLRDNORM, 0 }; poll_events.emplace_back(event); return true; #elif POSIX struct ::epoll_event event = { EPOLLIN | EPOLLET | EPOLLRDHUP, reinterpret_cast(sock.get_handle() ) }; const int result = ::epoll_ctl(this->obj_list, EPOLL_CTL_ADD, sock.get_handle(), &event); if (result == ~0) { return false; } this->epoll_events.emplace_back(); return true; #else #error "Undefine platform" #endif } bool List::removeSocket(const Socket &sock) noexcept { if (this->is_created() == false) { return false; } #ifdef WIN32 for (size_t i = 0; i < poll_events.size(); ++i) { if (sock.get_handle() == poll_events[i].fd) { poll_events.erase(poll_events.begin() + i); return true; } } return false; #elif POSIX const int result = ::epoll_ctl(this->obj_list, EPOLL_CTL_DEL, sock.get_handle(), nullptr); if (result == ~0) { return false; } this->epoll_events.pop_back(); return true; #else #error "Undefine platform" #endif } bool List::accept(std::vector &sockets) const noexcept { if (this->is_created() ) { #ifdef WIN32 const int count = ::WSAPoll(this->poll_events.data(), static_cast<::ULONG>(this->poll_events.size() ), ~0); if (SOCKET_ERROR == count) { return false; } for (size_t i = 0; i < this->poll_events.size(); ++i) { const WSAPOLLFD &event = this->poll_events[i]; if (event.revents & POLLRDNORM) { System::native_socket_type client_socket = ~0; do { client_socket = ::accept(event.fd, static_cast(nullptr), static_cast(nullptr) ); if (~0 != client_socket) { sockets.emplace_back(Socket(client_socket) ); } } while (~0 != client_socket); } } return false == sockets.empty(); #elif POSIX const int count = ::epoll_wait(this->obj_list, this->epoll_events.data(), this->epoll_events.size(), ~0); if (count == ~0) { return false; } for (int i = 0; i < count; ++i) { const epoll_event &event = this->epoll_events[i]; if (event.events & EPOLLIN) { System::native_socket_type client_socket = ~0; do { client_socket = ::accept(event.data.fd, static_cast(nullptr), static_cast(nullptr) ); if (~0 != client_socket) { sockets.emplace_back(Socket(client_socket) ); } } while (~0 != client_socket); } } return false == sockets.empty(); #else #error "Undefine platform" #endif } return false; } bool List::accept(std::vector &sockets, std::vector &socketsAddress) const noexcept { if (this->is_created() ) { #ifdef WIN32 const int count = ::WSAPoll(this->poll_events.data(), static_cast<::ULONG>(this->poll_events.size() ), ~0); if (SOCKET_ERROR == count) { return false; } for (size_t i = 0; i < this->poll_events.size(); ++i) { const WSAPOLLFD &event = this->poll_events[i]; if (event.revents & POLLRDNORM) { System::native_socket_type client_socket = ~0; do { ::sockaddr_in client_addr {}; socklen_t client_addr_len = sizeof(client_addr); client_socket = ::accept(event.fd, reinterpret_cast<::sockaddr *>(&client_addr), &client_addr_len); if (~0 != client_socket) { sockets.emplace_back(Socket(client_socket) ); socketsAddress.emplace_back(client_addr); } } while (~0 != client_socket); } } return false == sockets.empty(); #elif POSIX const int count = ::epoll_wait(this->obj_list, this->epoll_events.data(), this->epoll_events.size(), ~0); if (count == ~0) { return false; } for (int i = 0; i < count; ++i) { const epoll_event &event = this->epoll_events[i]; if (event.events & EPOLLIN) { System::native_socket_type client_socket = ~0; do { ::sockaddr_in client_addr {}; socklen_t client_addr_len = sizeof(client_addr); client_socket = ::accept(event.data.fd, reinterpret_cast<::sockaddr *>(&client_addr), &client_addr_len); if (~0 != client_socket) { sockets.emplace_back(Socket(client_socket) ); socketsAddress.emplace_back(client_addr); } } while (~0 != client_socket); } } return false == sockets.empty(); #else #error "Undefine platform" #endif } return false; } bool List::recv(std::vector &sockets, std::vector &disconnected, std::chrono::milliseconds timeout) const noexcept { if (this->is_created() == false) { return false; } #ifdef WIN32 const int count = ::WSAPoll(this->poll_events.data(), static_cast<::ULONG>(this->poll_events.size() ), static_cast<::INT>(timeout.count() ) ); if (SOCKET_ERROR == count) { return false; } for (size_t i = 0; i < this->poll_events.size(); ++i) { const WSAPOLLFD &event = this->poll_events[i]; if (event.revents & POLLRDNORM) { sockets.emplace_back(Socket(event.fd) ); } else if (event.revents & POLLHUP) { disconnected.emplace_back(Socket(event.fd) ); } } return false == sockets.empty() || false == disconnected.empty(); #elif POSIX const int count = ::epoll_wait(this->obj_list, this->epoll_events.data(), this->epoll_events.size(), timeout.count() ); if (count == ~0) { return false; } for (int i = 0; i < count; ++i) { const epoll_event &event = this->epoll_events[i]; if (event.events & EPOLLIN) { sockets.emplace_back(Socket(event.data.fd) ); } else if (event.events & EPOLLRDHUP) { disconnected.emplace_back(Socket(event.data.fd) ); } } return false == sockets.empty() || false == disconnected.empty(); #else #error "Undefine platform" #endif } }
X Tutup