1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
// net_compat.h
#pragma once
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define NOGDI
#define NOUSER
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
// Map POSIX names to Winsock equivalents
#define close(s) closesocket(s)
#define MSG_DONTWAIT 0 // no direct equivalent, use non-blocking mode instead
static inline int net_errno(void) { return WSAGetLastError(); }
#define NET_EAGAIN WSAEWOULDBLOCK
#define NET_EINTR WSAEINTR
typedef int socklen_t;
// err.h doesn't exist on Windows — provide a minimal shim
#include <stdio.h>
#include <stdlib.h>
static inline void err(int code, const char *msg) {
fprintf(stderr, "%s: WSA error %d\n", msg, WSAGetLastError());
exit(code);
}
// Winsock requires explicit init/cleanup
static inline void net_init(void) {
WSADATA wsa;
if (WSAStartup(MAKEWORD(2,2), &wsa) != 0) {
fprintf(stderr, "WSAStartup failed\n");
exit(EXIT_FAILURE);
}
}
static inline void net_cleanup(void) { WSACleanup(); }
// Non-blocking: Winsock uses ioctlsocket instead of MSG_DONTWAIT
#include <winsock2.h>
static inline void set_nonblocking(SOCKET s) {
u_long mode = 1;
ioctlsocket(s, FIONBIO, &mode);
}
#include <windows.h>
static inline void sleep_us(int microseconds) {
Sleep(microseconds / 1000); // Windows uses milliseconds
}
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <arpa/inet.h>
static inline void net_init(void) {} // no-op on POSIX
static inline void net_cleanup(void) {} // no-op on POSIX
static inline void set_nonblocking(int s) {
fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK);
}
static inline void sleep_us(int microseconds) {
usleep(microseconds);
}
static inline int net_errno(void) { return errno; }
#define NET_EAGAIN EAGAIN
#define NET_EINTR EINTR
#endif
|