summaryrefslogtreecommitdiff
path: root/shared/net_compat.h
blob: 65fa46deb39c1e34aa0b5bf8429d69a13295dae4 (plain)
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