network: enable IPv4 UDP sockets on POSIX

This commit is contained in:
nmzik committed 2026-08-29 03:57:09 +04:00
1 parent 62eaead3a3
commit b870a77176
1 file changed
+73 -63
+73 -63
View File
@@ -16,11 +16,6 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
// POSIX uses plain int file descriptors for sockets; provide the Winsock spellings
// the shared (non-guarded) code paths reference.
using SOCKET = int;
static constexpr SOCKET INVALID_SOCKET = -1;
#endif #endif
#include "common/assert.h" #include "common/assert.h"
@@ -823,9 +818,11 @@ struct NetEtherAddr {
#if defined(_WIN32) #if defined(_WIN32)
using NativeSocket = SOCKET; using NativeSocket = SOCKET;
static constexpr NativeSocket INVALID_NATIVE_SOCKET = INVALID_SOCKET; static constexpr NativeSocket INVALID_NATIVE_SOCKET = INVALID_SOCKET;
using SocketLength = int;
#else #else
using NativeSocket = int; using NativeSocket = int;
static constexpr NativeSocket INVALID_NATIVE_SOCKET = -1; static constexpr NativeSocket INVALID_NATIVE_SOCKET = -1;
using SocketLength = socklen_t;
#endif #endif
struct SocketSlot { struct SocketSlot {
@@ -898,7 +895,12 @@ static bool EnsureSocketBackend() {
return true; return true;
} }
static int SetPosixSocketError(int error) { static int SetGuestSocketError(int error) {
*Posix::GetErrorAddr() = error;
return -1;
}
static int SetHostSocketError(int error) {
int posix_error = Posix::POSIX_EIO; int posix_error = Posix::POSIX_EIO;
#if defined(_WIN32) #if defined(_WIN32)
switch (error) { switch (error) {
@@ -933,17 +935,31 @@ static int SetPosixSocketError(int error) {
default: break; default: break;
} }
#else #else
posix_error = error; switch (error) {
case EACCES: posix_error = Posix::POSIX_EACCES; break;
case EADDRINUSE: posix_error = Posix::POSIX_EADDRINUSE; break;
case EADDRNOTAVAIL: posix_error = Posix::POSIX_EADDRNOTAVAIL; break;
case EAFNOSUPPORT: posix_error = Posix::POSIX_EAFNOSUPPORT; break;
case EBADF: posix_error = Posix::POSIX_EBADF; break;
case EFAULT: posix_error = Posix::POSIX_EFAULT; break;
case EINVAL: posix_error = Posix::POSIX_EINVAL; break;
case EMFILE: posix_error = Posix::POSIX_EMFILE; break;
case ENFILE: posix_error = Posix::POSIX_ENFILE; break;
case ENOBUFS: posix_error = Posix::POSIX_ENOBUFS; break;
case ENOMEM: posix_error = Posix::POSIX_ENOMEM; break;
case ENOTSOCK: posix_error = Posix::POSIX_ENOTSOCK; break;
case EPROTONOSUPPORT: posix_error = Posix::POSIX_EPROTONOSUPPORT; break;
default: break;
}
#endif #endif
*Posix::GetErrorAddr() = posix_error; return SetGuestSocketError(posix_error);
return -1;
} }
static int SetPosixSocketError() { static int SetHostSocketError() {
#if defined(_WIN32) #if defined(_WIN32)
return SetPosixSocketError(WSAGetLastError()); return SetHostSocketError(WSAGetLastError());
#else #else
return SetPosixSocketError(errno); return SetHostSocketError(errno);
#endif #endif
} }
@@ -991,9 +1007,8 @@ static int ConvertMessageFlags(int flags) {
#endif #endif
} }
#if defined(_WIN32)
static int ConvertGuestSockaddr(const void* addr, uint32_t addrlen, sockaddr_storage* out, static int ConvertGuestSockaddr(const void* addr, uint32_t addrlen, sockaddr_storage* out,
int* out_len) { SocketLength* out_len) {
EXIT_IF(out == nullptr); EXIT_IF(out == nullptr);
EXIT_IF(out_len == nullptr); EXIT_IF(out_len == nullptr);
@@ -1028,6 +1043,7 @@ static int ConvertGuestSockaddr(const void* addr, uint32_t addrlen, sockaddr_sto
return 0; return 0;
} }
#if defined(_WIN32)
static int ConvertHostSockaddr(const sockaddr_storage* addr, int addrlen, void* out, static int ConvertHostSockaddr(const sockaddr_storage* addr, int addrlen, void* out,
uint32_t* out_len) { uint32_t* out_len) {
EXIT_IF(addr == nullptr); EXIT_IF(addr == nullptr);
@@ -1364,7 +1380,7 @@ int KYTY_SYSV_ABI NetGetSockInfo(int s, void* info, int n, int flags) {
int KYTY_SYSV_ABI EpollCreate(const char* name, int flags) { int KYTY_SYSV_ABI EpollCreate(const char* name, int flags) {
if (name == nullptr || flags != 0) { if (name == nullptr || flags != 0) {
return SetPosixSocketError(Posix::POSIX_EINVAL); return SetGuestSocketError(Posix::POSIX_EINVAL);
} }
std::lock_guard lock(g_epoll_mutex); std::lock_guard lock(g_epoll_mutex);
@@ -1378,7 +1394,7 @@ int KYTY_SYSV_ABI EpollCreate(const char* name, int flags) {
} }
} }
return SetPosixSocketError(Posix::POSIX_EMFILE); return SetGuestSocketError(Posix::POSIX_EMFILE);
} }
int KYTY_SYSV_ABI EpollControl(int eid, int op, int id, const NetEpollEvent* event) { int KYTY_SYSV_ABI EpollControl(int eid, int op, int id, const NetEpollEvent* event) {
@@ -1387,22 +1403,22 @@ int KYTY_SYSV_ABI EpollControl(int eid, int op, int id, const NetEpollEvent* eve
constexpr int EPOLL_CTL_DEL = 3; constexpr int EPOLL_CTL_DEL = 3;
if ((op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD) && event == nullptr) { if ((op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD) && event == nullptr) {
return SetPosixSocketError(Posix::POSIX_EINVAL); return SetGuestSocketError(Posix::POSIX_EINVAL);
} }
if (op == EPOLL_CTL_DEL && event != nullptr) { if (op == EPOLL_CTL_DEL && event != nullptr) {
return SetPosixSocketError(Posix::POSIX_EINVAL); return SetGuestSocketError(Posix::POSIX_EINVAL);
} }
if (op < EPOLL_CTL_ADD || op > EPOLL_CTL_DEL) { if (op < EPOLL_CTL_ADD || op > EPOLL_CTL_DEL) {
return SetPosixSocketError(Posix::POSIX_EINVAL); return SetGuestSocketError(Posix::POSIX_EINVAL);
} }
if (!IsSocket(id)) { if (!IsSocket(id)) {
return SetPosixSocketError(Posix::POSIX_EBADF); return SetGuestSocketError(Posix::POSIX_EBADF);
} }
std::lock_guard lock(g_epoll_mutex); std::lock_guard lock(g_epoll_mutex);
auto* slot = GetEpollSlot(eid); auto* slot = GetEpollSlot(eid);
if (slot == nullptr) { if (slot == nullptr) {
return SetPosixSocketError(Posix::POSIX_EBADF); return SetGuestSocketError(Posix::POSIX_EBADF);
} }
auto registration = std::find_if(slot->registrations.begin(), slot->registrations.end(), auto registration = std::find_if(slot->registrations.begin(), slot->registrations.end(),
@@ -1410,19 +1426,19 @@ int KYTY_SYSV_ABI EpollControl(int eid, int op, int id, const NetEpollEvent* eve
switch (op) { switch (op) {
case EPOLL_CTL_ADD: case EPOLL_CTL_ADD:
if (registration != slot->registrations.end()) { if (registration != slot->registrations.end()) {
return SetPosixSocketError(Posix::POSIX_EEXIST); return SetGuestSocketError(Posix::POSIX_EEXIST);
} }
slot->registrations.push_back({id, *event}); slot->registrations.push_back({id, *event});
break; break;
case EPOLL_CTL_MOD: case EPOLL_CTL_MOD:
if (registration == slot->registrations.end()) { if (registration == slot->registrations.end()) {
return SetPosixSocketError(Posix::POSIX_ENOENT); return SetGuestSocketError(Posix::POSIX_ENOENT);
} }
registration->event = *event; registration->event = *event;
break; break;
case EPOLL_CTL_DEL: case EPOLL_CTL_DEL:
if (registration == slot->registrations.end()) { if (registration == slot->registrations.end()) {
return SetPosixSocketError(Posix::POSIX_ENOENT); return SetGuestSocketError(Posix::POSIX_ENOENT);
} }
slot->registrations.erase(registration); slot->registrations.erase(registration);
break; break;
@@ -1435,10 +1451,10 @@ int KYTY_SYSV_ABI EpollControl(int eid, int op, int id, const NetEpollEvent* eve
int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int timeout) { int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int timeout) {
if (events == nullptr) { if (events == nullptr) {
return SetPosixSocketError(Posix::POSIX_EFAULT); return SetGuestSocketError(Posix::POSIX_EFAULT);
} }
if (maxevents <= 0 || timeout < -1) { if (maxevents <= 0 || timeout < -1) {
return SetPosixSocketError(Posix::POSIX_EINVAL); return SetGuestSocketError(Posix::POSIX_EINVAL);
} }
std::vector<EpollRegistration> registrations; std::vector<EpollRegistration> registrations;
@@ -1446,7 +1462,7 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
std::unique_lock lock(g_epoll_mutex); std::unique_lock lock(g_epoll_mutex);
auto* slot = GetEpollSlot(eid); auto* slot = GetEpollSlot(eid);
if (slot == nullptr) { if (slot == nullptr) {
return SetPosixSocketError(Posix::POSIX_EBADF); return SetGuestSocketError(Posix::POSIX_EBADF);
} }
if (slot->registrations.empty() && timeout != 0) { if (slot->registrations.empty() && timeout != 0) {
@@ -1461,7 +1477,7 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
} }
slot = GetEpollSlot(eid); slot = GetEpollSlot(eid);
if (slot == nullptr) { if (slot == nullptr) {
return SetPosixSocketError(Posix::POSIX_EBADF); return SetGuestSocketError(Posix::POSIX_EBADF);
} }
} }
registrations = slot->registrations; registrations = slot->registrations;
@@ -1492,7 +1508,7 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
continue; continue;
} }
if (host_registrations.size() >= FD_SETSIZE) { if (host_registrations.size() >= FD_SETSIZE) {
return SetPosixSocketError(Posix::POSIX_EINVAL); return SetGuestSocketError(Posix::POSIX_EINVAL);
} }
if ((registration.event.events & EPOLL_IN) != 0) { if ((registration.event.events & EPOLL_IN) != 0) {
FD_SET(socket, &host_read); FD_SET(socket, &host_read);
@@ -1518,7 +1534,7 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
const int result = ::select(0, &host_read, &host_write, &host_except, host_timeout_ptr); const int result = ::select(0, &host_read, &host_write, &host_except, host_timeout_ptr);
if (result == SOCKET_ERROR) { if (result == SOCKET_ERROR) {
return SetPosixSocketError(); return SetHostSocketError();
} }
if (result == 0) { if (result == 0) {
return 0; return 0;
@@ -1552,7 +1568,7 @@ int KYTY_SYSV_ABI EpollWait(int eid, NetEpollEvent* events, int maxevents, int t
return count; return count;
#else #else
(void)timeout; (void)timeout;
return SetPosixSocketError(Posix::POSIX_ENOSYS); return SetGuestSocketError(Posix::POSIX_ENOSYS);
#endif #endif
} }
@@ -1560,7 +1576,7 @@ int KYTY_SYSV_ABI EpollDestroy(int eid) {
std::lock_guard lock(g_epoll_mutex); std::lock_guard lock(g_epoll_mutex);
auto* slot = GetEpollSlot(eid); auto* slot = GetEpollSlot(eid);
if (slot == nullptr) { if (slot == nullptr) {
return SetPosixSocketError(Posix::POSIX_EBADF); return SetGuestSocketError(Posix::POSIX_EBADF);
} }
slot->used = false; slot->used = false;
@@ -1582,14 +1598,15 @@ int KYTY_SYSV_ABI SocketClose(int s) {
RemoveSocketFromEpolls(s); RemoveSocketFromEpolls(s);
#if defined(_WIN32) #if defined(_WIN32)
if (closesocket(socket) == SOCKET_ERROR) { const int result = closesocket(socket);
#else
const int result = ::close(socket);
#endif
if (result != 0) {
return NET_ERROR_EBADF; return NET_ERROR_EBADF;
} }
return OK; return OK;
#else
return NET_ERROR_ENOSYS;
#endif
} }
int KYTY_SYSV_ABI Socket(int family, int type, int protocol) { int KYTY_SYSV_ABI Socket(int family, int type, int protocol) {
@@ -1601,7 +1618,7 @@ int KYTY_SYSV_ABI Socket(int family, int type, int protocol) {
family, type, protocol); family, type, protocol);
if (!EnsureSocketBackend()) { if (!EnsureSocketBackend()) {
return SetPosixSocketError(Posix::POSIX_ENETDOWN); return SetGuestSocketError(Posix::POSIX_ENETDOWN);
} }
const int host_family = ConvertFamily(family); const int host_family = ConvertFamily(family);
@@ -1610,25 +1627,24 @@ int KYTY_SYSV_ABI Socket(int family, int type, int protocol) {
return -1; return -1;
} }
#if defined(_WIN32)
NativeSocket socket = ::socket(host_family, type, protocol); NativeSocket socket = ::socket(host_family, type, protocol);
if (socket == INVALID_NATIVE_SOCKET) { if (socket == INVALID_NATIVE_SOCKET) {
return SetPosixSocketError(); return SetHostSocketError();
} }
const int fd = AllocSocketFd(socket); const int fd = AllocSocketFd(socket);
if (fd < 0) { if (fd < 0) {
#if defined(_WIN32)
closesocket(socket); closesocket(socket);
#else
::close(socket);
#endif
*Posix::GetErrorAddr() = Posix::POSIX_EMFILE; *Posix::GetErrorAddr() = Posix::POSIX_EMFILE;
return -1; return -1;
} }
LOGF("\t fd = %d\n", fd); LOGF("\t fd = %d\n", fd);
return fd; return fd;
#else
*Posix::GetErrorAddr() = Posix::POSIX_ENOSYS;
return -1;
#endif
} }
int KYTY_SYSV_ABI Bind(int s, const void* addr, uint32_t addrlen) { int KYTY_SYSV_ABI Bind(int s, const void* addr, uint32_t addrlen) {
@@ -1645,23 +1661,17 @@ int KYTY_SYSV_ABI Bind(int s, const void* addr, uint32_t addrlen) {
return -1; return -1;
} }
#if defined(_WIN32)
sockaddr_storage host_addr {}; sockaddr_storage host_addr {};
int host_addrlen = 0; SocketLength host_addrlen = 0;
if (ConvertGuestSockaddr(addr, addrlen, &host_addr, &host_addrlen) != 0) { if (ConvertGuestSockaddr(addr, addrlen, &host_addr, &host_addrlen) != 0) {
return -1; return -1;
} }
if (::bind(socket, reinterpret_cast<const sockaddr*>(&host_addr), host_addrlen) == if (::bind(socket, reinterpret_cast<const sockaddr*>(&host_addr), host_addrlen) != 0) {
SOCKET_ERROR) { return SetHostSocketError();
return SetPosixSocketError();
} }
return 0; return 0;
#else
*Posix::GetErrorAddr() = Posix::POSIX_ENOSYS;
return -1;
#endif
} }
int KYTY_SYSV_ABI Connect(int s, const void* addr, uint32_t addrlen) { int KYTY_SYSV_ABI Connect(int s, const void* addr, uint32_t addrlen) {
@@ -1687,7 +1697,7 @@ int KYTY_SYSV_ABI Connect(int s, const void* addr, uint32_t addrlen) {
if (::connect(socket, reinterpret_cast<const sockaddr*>(&host_addr), host_addrlen) == if (::connect(socket, reinterpret_cast<const sockaddr*>(&host_addr), host_addrlen) ==
SOCKET_ERROR) { SOCKET_ERROR) {
return SetPosixSocketError(); return SetHostSocketError();
} }
return 0; return 0;
@@ -1712,7 +1722,7 @@ int KYTY_SYSV_ABI Listen(int s, int backlog) {
#if defined(_WIN32) #if defined(_WIN32)
if (::listen(socket, backlog) == SOCKET_ERROR) { if (::listen(socket, backlog) == SOCKET_ERROR) {
return SetPosixSocketError(); return SetHostSocketError();
} }
return 0; return 0;
@@ -1742,7 +1752,7 @@ int KYTY_SYSV_ABI Accept(int s, void* addr, uint32_t* addrlen) {
NativeSocket accepted = NativeSocket accepted =
::accept(socket, reinterpret_cast<sockaddr*>(&host_addr), &host_addrlen); ::accept(socket, reinterpret_cast<sockaddr*>(&host_addr), &host_addrlen);
if (accepted == INVALID_NATIVE_SOCKET) { if (accepted == INVALID_NATIVE_SOCKET) {
return SetPosixSocketError(); return SetHostSocketError();
} }
const int fd = AllocSocketFd(accepted); const int fd = AllocSocketFd(accepted);
@@ -1791,7 +1801,7 @@ int KYTY_SYSV_ABI Shutdown(int s, int how) {
#if defined(_WIN32) #if defined(_WIN32)
if (::shutdown(socket, how) == SOCKET_ERROR) { if (::shutdown(socket, how) == SOCKET_ERROR) {
return SetPosixSocketError(); return SetHostSocketError();
} }
return 0; return 0;
@@ -1821,7 +1831,7 @@ int KYTY_SYSV_ABI Getsockname(int s, void* addr, uint32_t* addrlen) {
int host_addrlen = sizeof(host_addr); int host_addrlen = sizeof(host_addr);
if (::getsockname(socket, reinterpret_cast<sockaddr*>(&host_addr), &host_addrlen) == if (::getsockname(socket, reinterpret_cast<sockaddr*>(&host_addr), &host_addrlen) ==
SOCKET_ERROR) { SOCKET_ERROR) {
return SetPosixSocketError(); return SetHostSocketError();
} }
return ConvertHostSockaddr(&host_addr, host_addrlen, addr, addrlen); return ConvertHostSockaddr(&host_addr, host_addrlen, addr, addrlen);
@@ -1850,7 +1860,7 @@ int KYTY_SYSV_ABI Getsockopt(int s, int level, int optname, void* optval, uint32
int len = static_cast<int>(*optlen); int len = static_cast<int>(*optlen);
if (::getsockopt(socket, ConvertSocketOptionLevel(level), optname, static_cast<char*>(optval), if (::getsockopt(socket, ConvertSocketOptionLevel(level), optname, static_cast<char*>(optval),
&len) == SOCKET_ERROR) { &len) == SOCKET_ERROR) {
return SetPosixSocketError(); return SetHostSocketError();
} }
*optlen = static_cast<uint32_t>(len); *optlen = static_cast<uint32_t>(len);
return 0; return 0;
@@ -1881,14 +1891,14 @@ int KYTY_SYSV_ABI Setsockopt(int s, int level, int optname, const void* optval,
optlen >= sizeof(int)) { optlen >= sizeof(int)) {
u_long enabled = (*static_cast<const int*>(optval) != 0 ? 1 : 0); u_long enabled = (*static_cast<const int*>(optval) != 0 ? 1 : 0);
if (ioctlsocket(socket, FIONBIO, &enabled) == SOCKET_ERROR) { if (ioctlsocket(socket, FIONBIO, &enabled) == SOCKET_ERROR) {
return SetPosixSocketError(); return SetHostSocketError();
} }
return 0; return 0;
} }
if (::setsockopt(socket, ConvertSocketOptionLevel(level), optname, if (::setsockopt(socket, ConvertSocketOptionLevel(level), optname,
static_cast<const char*>(optval), static_cast<int>(optlen)) == SOCKET_ERROR) { static_cast<const char*>(optval), static_cast<int>(optlen)) == SOCKET_ERROR) {
return SetPosixSocketError(); return SetHostSocketError();
} }
return 0; return 0;
@@ -1941,7 +1951,7 @@ int64_t KYTY_SYSV_ABI Sendto(int s, const void* buf, uint64_t len, int flags, co
reinterpret_cast<const sockaddr*>(&host_addr), host_addrlen); reinterpret_cast<const sockaddr*>(&host_addr), host_addrlen);
} }
if (result == SOCKET_ERROR) { if (result == SOCKET_ERROR) {
return SetPosixSocketError(); return SetHostSocketError();
} }
return result; return result;
@@ -2000,7 +2010,7 @@ int64_t KYTY_SYSV_ABI Recvfrom(int s, void* buf, uint64_t len, int flags, void*
} }
} }
if (result == SOCKET_ERROR) { if (result == SOCKET_ERROR) {
return SetPosixSocketError(); return SetHostSocketError();
} }
return result; return result;
@@ -2101,7 +2111,7 @@ int KYTY_SYSV_ABI Select(int nfds, void* readfds, void* writefds, void* exceptfd
const int result = ::select(0, read_ptr, write_ptr, except_ptr, host_timeout_ptr); const int result = ::select(0, read_ptr, write_ptr, except_ptr, host_timeout_ptr);
if (result == SOCKET_ERROR) { if (result == SOCKET_ERROR) {
return SetPosixSocketError(); return SetHostSocketError();
} }
GuestFdZero(readfds, nfds); GuestFdZero(readfds, nfds);