/** * Platform compatibility layer for POSIX functions on Windows */ #ifndef PLATFORM_COMPAT_H #define PLATFORM_COMPAT_H #ifdef _WIN32 #include #include #include #include #include #include #include // Byte order conversion functions #ifdef _WIN32 #include #define htobe64(x) _byteswap_uint64(x) #define be64toh(x) _byteswap_uint64(x) #elif defined(__linux__) #include #endif // POSIX functions missing on Windows #define strcasecmp _stricmp #define strncasecmp _strnicmp // poll() and pollfd are already defined in winsock2.h on MSYS2 UCRT64 // Only define if not already present #ifndef POLLIN #define POLLIN 0x0001 #endif #ifndef POLLOUT #define POLLOUT 0x0004 #endif #ifndef POLLERR #define POLLERR 0x0008 #endif #ifndef POLLHUP #define POLLHUP 0x0010 #endif #ifndef POLLNVAL #define POLLNVAL 0x0020 #endif #ifndef POLLPRI #define POLLPRI 0x0002 #endif // ssize_t for Windows (signed size type) #ifndef _SSIZE_T_DEFINED typedef long ssize_t; #define _SSIZE_T_DEFINED #endif // gettimeofday for Windows - provide our own implementation if not already defined #ifndef _GETTIMEOFDAY_DEFINED #define _GETTIMEOFDAY_DEFINED static inline int utun_gettimeofday(struct timeval *tv, void *tz) { FILETIME ft; unsigned __int64 tmpres = 0; if (tv != NULL) { GetSystemTimeAsFileTime(&ft); tmpres |= ft.dwHighDateTime; tmpres <<= 32; tmpres |= ft.dwLowDateTime; // Convert from 100-nanosecond intervals to microseconds tmpres /= 10; // Convert to Unix epoch (January 1, 1970) tmpres -= 11644473600000000ULL; tv->tv_sec = (long)(tmpres / 1000000UL); tv->tv_usec = (long)(tmpres % 1000000UL); } // tz parameter is ignored (for compatibility with POSIX) return 0; } #endif // _GETTIMEOFDAY_DEFINED // Pipe creation for Windows static inline int platform_pipe(int pipefd[2]) { return _pipe(pipefd, 4096, _O_BINARY); } #define pipe platform_pipe // nfds_t already defined in winsock2.h on MSYS2 // fcntl replacement for Windows (simplified - only supports F_GETFL/F_SETFL with O_NONBLOCK) #ifndef F_GETFL #define F_GETFL 3 #endif #ifndef F_SETFL #define F_SETFL 4 #endif #ifndef O_NONBLOCK #define O_NONBLOCK 0x4000 #endif static inline int platform_fcntl(int fd, int cmd, ... /* arg */ ) { va_list ap; va_start(ap, cmd); if (cmd == F_GETFL) { va_end(ap); // Return current flags (always 0 on Windows, can't query easily) return 0; } else if (cmd == F_SETFL) { int flags = va_arg(ap, int); va_end(ap); if (flags & O_NONBLOCK) { // Set non-blocking mode u_long mode = 1; return ioctlsocket(fd, FIONBIO, &mode); } return 0; } va_end(ap); errno = EINVAL; return -1; } #define fcntl platform_fcntl // nanosleep already defined in pthread_time.h on MSYS2 // poll() and pollfd already defined in winsock2.h on MSYS2 // Use WSAPoll on Windows (available in Vista and later) #define poll WSAPoll // sa_family_t might not be defined on some Windows setups #ifndef sa_family_t typedef unsigned short sa_family_t; #endif #else // POSIX - include standard headers #include #include #include #include #include #include #include #include #include #define utun_gettimeofday(A,B) gettimeofday(A,B) #endif #include // Generate cryptographically secure random bytes // Returns 0 on success, -1 on error int random_bytes(uint8_t *buffer, size_t len); // Get IPv4 address of interface with default route (0.0.0.0 destination) // Returns IPv4 address in network byte order, 0 on error uint32_t get_default_route_ip(void); #endif // PLATFORM_COMPAT_H