21 # include <winsock2.h>
26 # pragma comment(lib, "ws2_32.lib")
33 # include <sys/epoll.h>
37 # include "TargetConditionals.h"
39 # include <sys/event.h>
40 # include <sys/time.h>
41 # include <sys/types.h>
45 # include <arpa/inet.h>
48 # include <netinet/in.h>
49 # include <netinet/tcp.h>
50 # include <sys/socket.h>
55 # define _Out_cap_(size)
58 #if defined(HAVE_CONSOLE_LOG) && !defined(LOG_DEBUG)
62 # define LOG_DEBUG(fmt_, ...) printf(" " fmt_ "\n", ##__VA_ARGS__)
63 # define LOG_TRACE(fmt_, ...) printf(" " fmt_ "\n", ##__VA_ARGS__)
64 # define LOG_INFO(fmt_, ...) printf(" " fmt_ "\n", ##__VA_ARGS__)
65 # define LOG_WARN(fmt_, ...) printf(" " fmt_ "\n", ##__VA_ARGS__)
66 # define LOG_ERROR(fmt_, ...) printf(" " fmt_ "\n", ##__VA_ARGS__)
72 # define LOG_DEBUG(fmt_, ...)
73 # define LOG_TRACE(fmt_, ...)
74 # define LOG_INFO(fmt_, ...)
75 # define LOG_WARN(fmt_, ...)
76 # define LOG_ERROR(fmt_, ...)
112 if (m_thread.joinable())
143 struct WsaInitializer
148 WSAStartup(MAKEWORD(2, 2), &wsaData);
151 ~WsaInitializer() { WSACleanup(); }
154 static WsaInitializer g_wsaInitializer;
175 sockaddr_in &inet4 =
reinterpret_cast<sockaddr_in &
>(
m_data);
176 inet4.sin_family = AF_INET;
177 inet4.sin_port = htons(
static_cast<unsigned short>(
port));
178 inet4.sin_addr.s_addr = htonl(addr);
184 INT addrlen =
sizeof(
m_data);
186 for (
int i = 0; i <
sizeof(buf) && addr[i]; i++)
191 ::WSAStringToAddressW(buf, AF_INET,
nullptr, &
m_data, &addrlen);
193 sockaddr_in &inet4 =
reinterpret_cast<sockaddr_in &
>(
m_data);
194 inet4.sin_family = AF_INET;
195 char const *colon = strchr(addr,
':');
198 inet4.sin_port = htons(atoi(colon + 1));
200 memcpy(buf, addr, (std::min<ptrdiff_t>)(15, colon - addr));
202 ::inet_pton(AF_INET, buf, &inet4.sin_addr);
207 ::inet_pton(AF_INET, addr, &inet4.sin_addr);
216 operator sockaddr *() {
return &
m_data; }
218 operator const sockaddr *()
const {
return &
m_data; }
225 sockaddr_in
const &inet4 =
reinterpret_cast<sockaddr_in
const &
>(
m_data);
226 return ntohs(inet4.sin_port);
236 std::ostringstream os;
241 sockaddr_in
const &inet4 =
reinterpret_cast<sockaddr_in
const &
>(
m_data);
242 u_long addr = ntohl(inet4.sin_addr.s_addr);
243 os << (addr >> 24) <<
'.' << ((addr >> 16) & 255) <<
'.' << ((addr >> 8) & 255) <<
'.'
245 os <<
':' << ntohs(inet4.sin_port);
250 os <<
"[?AF?" <<
m_data.sa_family <<
']';
273 Socket(
int af,
int type,
int proto) :
m_sock(::socket(af, type, proto)) {}
292 ::ioctlsocket(
m_sock, FIONBIO, &value);
294 int flags = ::fcntl(
m_sock, F_GETFL, 0);
295 ::fcntl(
m_sock, F_SETFL, flags | O_NONBLOCK);
307 return (::setsockopt(
m_sock, SOL_SOCKET, SO_REUSEADDR,
reinterpret_cast<char *
>(&value),
308 sizeof(value)) == 0);
319 return (::setsockopt(
m_sock, IPPROTO_TCP, TCP_NODELAY,
reinterpret_cast<char *
>(&value),
320 sizeof(value)) == 0);
344 return static_cast<int>(
::recv(
m_sock,
reinterpret_cast<char *
>(buffer),
size, flags));
350 return static_cast<int>(
::send(
m_sock,
reinterpret_cast<char const *
>(buffer),
size, 0));
356 return (::
bind(
m_sock, addr,
sizeof(addr)) == 0);
363 int addrlen =
sizeof(addr);
365 socklen_t addrlen =
sizeof(addr);
380 int addrlen =
sizeof(caddr);
382 socklen_t addrlen =
sizeof(caddr);
397 return ::WSAGetLastError();
475 std::vector<WSAEVENT> m_events{};
485 # define KQUEUE_SIZE 32
487 struct kevent m_events[KQUEUE_SIZE];
495 m_epollFd = ::epoll_create(0);
497 m_epollFd = ::epoll_create1(0);
502 bzero(&m_events[0],
sizeof(m_events));
533 LOG_TRACE(
"Reactor: Adding socket 0x%x with flags 0x%x",
static_cast<int>(socket), flags);
535 m_events.push_back(::WSACreateEvent());
538 epoll_event
event = {};
539 event.data.fd = socket;
541 ::epoll_ctl(m_epollFd, EPOLL_CTL_ADD, socket, &event);
545 bzero(&event,
sizeof(event));
546 event.ident = socket.
m_sock;
547 EV_SET(&event, event.ident, EVFILT_READ, EV_ADD, 0, 0, NULL);
548 kevent(kq, &event, 1, NULL, 0, NULL);
549 EV_SET(&event, event.ident, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
550 kevent(kq, &event, 1, NULL, 0, NULL);
559 LOG_TRACE(
"Reactor: Updating socket 0x%x with flags 0x%x",
static_cast<int>(socket), flags);
562 if (it->flags != flags)
566 long lNetworkEvents = 0;
569 lNetworkEvents |= FD_READ;
573 lNetworkEvents |= FD_WRITE;
577 lNetworkEvents |= FD_ACCEPT;
581 lNetworkEvents |= FD_CLOSE;
583 auto eventIt = m_events.begin() + std::distance(
m_sockets.begin(), it);
584 ::WSAEventSelect(socket, *eventIt, lNetworkEvents);
601 epoll_event
event = {};
602 event.data.fd = socket;
603 event.events = events;
604 ::epoll_ctl(m_epollFd, EPOLL_CTL_MOD, socket, &event);
619 LOG_TRACE(
"Reactor: Removing socket 0x%x",
static_cast<int>(socket));
624 auto eventIt = m_events.begin() + std::distance(
m_sockets.begin(), it);
625 ::WSAEventSelect(it->socket, *eventIt, 0);
626 ::WSACloseEvent(*eventIt);
627 m_events.erase(eventIt);
630 ::epoll_ctl(m_epollFd, EPOLL_CTL_DEL, socket,
nullptr);
634 bzero(&event,
sizeof(event));
635 event.ident = socket;
636 EV_SET(&event, socket, EVFILT_READ, EV_DELETE, 0, 0, NULL);
637 if (-1 == kevent(kq, &event, 1, NULL, 0, NULL))
640 LOG_ERROR(
"cannot delete fd=0x%x from kqueue!", event.ident);
642 EV_SET(&event, socket, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
643 if (-1 == kevent(kq, &event, 1, NULL, 0, NULL))
646 LOG_ERROR(
"cannot delete fd=0x%x from kqueue!", event.ident);
670 for (
auto &hEvent : m_events)
672 ::WSACloseEvent(hEvent);
678 ::epoll_ctl(m_epollFd, EPOLL_CTL_DEL, sd.socket,
nullptr);
680 # ifdef TARGET_OS_MAC
682 bzero(&event,
sizeof(event));
683 event.ident = sd.socket;
684 EV_SET(&event, sd.socket, EVFILT_READ, EV_DELETE, 0, 0, NULL);
685 if (-1 == kevent(kq, &event, 1, NULL, 0, NULL))
687 LOG_ERROR(
"cannot delete fd=0x%x from kqueue!", event.ident);
689 EV_SET(&event, sd.socket, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
690 if (-1 == kevent(kq, &event, 1, NULL, 0, NULL))
692 LOG_ERROR(
"cannot delete fd=0x%x from kqueue!", event.ident);
705 LOG_INFO(
"Reactor: Thread started");
709 DWORD dwResult = ::WSAWaitForMultipleEvents(
static_cast<DWORD
>(m_events.size()),
711 if (dwResult == WSA_WAIT_TIMEOUT)
716 assert(dwResult <= WSA_WAIT_EVENT_0 + m_events.size());
717 int index = dwResult - WSA_WAIT_EVENT_0;
722 ::WSAEnumNetworkEvents(socket, m_events[index], &ne);
724 "Reactor: Handling socket 0x%x (index %d) with active flags 0x%x "
726 static_cast<int>(socket), index, ne.lNetworkEvents, flags);
728 if ((flags &
Readable) && (ne.lNetworkEvents & FD_READ))
732 if ((flags &
Writable) && (ne.lNetworkEvents & FD_WRITE))
736 if ((flags &
Acceptable) && (ne.lNetworkEvents & FD_ACCEPT))
740 if ((flags &
Closed) && (ne.lNetworkEvents & FD_CLOSE))
747 epoll_event events[4];
748 int result = ::epoll_wait(m_epollFd, events,
sizeof(events) /
sizeof(events[0]), 500);
749 if (result == 0 || (result == -1 && errno == EINTR))
754 assert(result >= 1 &&
static_cast<size_t>(result) <=
sizeof(events) /
sizeof(events[0]));
755 for (
int i = 0; i < result; i++)
759 Socket socket = it->socket;
760 int flags = it->flags;
762 LOG_TRACE(
"Reactor: Handling socket 0x%x active flags 0x%x (armed 0x%x)",
763 static_cast<int>(socket), events[i].events, flags);
765 if ((flags &
Readable) && (events[i].events & EPOLLIN))
769 if ((flags &
Writable) && (events[i].events & EPOLLOUT))
773 if ((flags &
Acceptable) && (events[i].events & EPOLLIN))
777 if ((flags &
Closed) && (events[i].events & (EPOLLHUP | EPOLLERR)))
784 #if defined(TARGET_OS_MAC)
785 unsigned waitms = 500;
786 struct timespec timeout;
787 timeout.tv_sec = waitms / 1000;
788 timeout.tv_nsec = (waitms % 1000) * 1000 * 1000;
790 int nev = kevent(kq, NULL, 0, m_events, KQUEUE_SIZE, &timeout);
791 for (
int i = 0; i < nev; i++)
793 struct kevent &
event = m_events[i];
794 int fd = (int)event.ident;
797 Socket socket = it->socket;
798 int flags = it->flags;
800 LOG_TRACE(
"Handling socket 0x%x active flags 0x%x (armed 0x%x)",
static_cast<int>(socket),
801 event.flags, event.fflags);
803 if (event.filter == EVFILT_READ)
816 if (event.filter == EVFILT_WRITE)
825 if ((event.flags & EV_EOF) || (event.flags & EV_ERROR))
827 LOG_TRACE(
"event.filter=%s",
"EVFILT_WRITE");
831 EV_SET(&kevt, event.ident, EVFILT_READ, EV_DELETE, 0, 0, NULL);
832 if (-1 == kevent(kq, &kevt, 1, NULL, 0, NULL))
834 LOG_ERROR(
"cannot delete fd=0x%x from kqueue!", event.ident);
836 EV_SET(&kevt, event.ident, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
837 if (-1 == kevent(kq, &kevt, 1, NULL, 0, NULL))
839 LOG_ERROR(
"cannot delete fd=0x%x from kqueue!", event.ident);