1
#pragma once
2
// NOLINT(namespace-envoy)
3

            
4
// This common "platform.h" header exists to simplify the most common references
5
// to non-ANSI C/C++ headers, required on Windows, Posix, Linux, BSD etc,
6
// and to provide substitute definitions when absolutely required.
7
//
8
// The goal is to eventually not require this file of envoy header declarations,
9
// but limit the use of these architecture-specific types and declarations
10
// to the corresponding .cc implementation files.
11
#include "absl/strings/string_view.h"
12

            
13
#ifdef _MSC_VER
14

            
15
#include <windows.h>
16
#include <winsock2.h>
17

            
18
// These must follow afterwards
19
#include <mstcpip.h>
20
#include <mswsock.h>
21
#include <ws2tcpip.h>
22

            
23
// This is introduced in Windows SDK 10.0.17063.0 which is required
24
// to build Envoy on Windows (we will reevaluate whether earlier builds
25
// of Windows can be detected and PipeInstance marked unsupported at runtime.)
26
#include <afunix.h>
27

            
28
// <windows.h> defines some frequently used symbols, so we need to undef these
29
// interfering symbols.
30
#undef ASSERT
31
#undef DELETE
32
#undef ERROR
33
#undef GetMessage
34
#undef interface
35
#undef TRUE
36
#undef IGNORE
37

            
38
#include <io.h>
39
#include <stdint.h>
40
#include <time.h>
41

            
42
#define htole16(x) (x)
43
#define htole32(x) (x)
44
#define htole64(x) (x)
45
#define le16toh(x) (x)
46
#define le32toh(x) (x)
47
#define le64toh(x) (x)
48

            
49
#define htobe16(x) htons((x))
50
#define htobe32(x) htonl((x))
51
#define htobe64(x) htonll((x))
52
#define be16toh(x) ntohs((x))
53
#define be32toh(x) ntohl((x))
54
#define be64toh(x) ntohll((x))
55

            
56
#define PACKED_STRUCT(definition, ...)                                                             \
57
  __pragma(pack(push, 1)) definition, ##__VA_ARGS__;                                               \
58
  __pragma(pack(pop))
59

            
60
typedef ptrdiff_t ssize_t;
61

            
62
// This is needed so the OsSysCalls interface compiles on Windows,
63
// shmOpen takes mode_t as an argument.
64
typedef uint32_t mode_t;
65

            
66
typedef SOCKET os_fd_t;
67
typedef HANDLE filesystem_os_id_t; // NOLINT(modernize-use-using)
68
typedef DWORD signal_t;            // NOLINT(modernize-use-using)
69

            
70
typedef unsigned int sa_family_t;
71

            
72
// Posix structure for scatter/gather I/O, not present on Windows.
73
struct iovec {
74
  void* iov_base;
75
  size_t iov_len;
76
};
77

            
78
// Posix structure for describing messages sent by 'sendmsg` and received by
79
// 'recvmsg'
80
struct msghdr {
81
  void* msg_name;
82
  socklen_t msg_namelen;
83
  iovec* msg_iov;
84
  size_t msg_iovlen;
85
  void* msg_control;
86
  size_t msg_controllen;
87
  int msg_flags;
88
};
89

            
90
// Windows cmsghdr elements are just slightly different than Posix,
91
// they are defined with the cmsg_len as a 32 bit uint, not size_t
92
// We express our sendmsg and recvmsg in terms of Posix structures
93
// and semantics, but won't adjust the cmsghdr elements.
94
// The default Windows macros dereference the Windows style msghdr
95
// member Control, which is an indirection that doesn't exist on posix.
96

            
97
#undef CMSG_FIRSTHDR
98
#define CMSG_FIRSTHDR(msg)                                                                         \
99
  (((msg)->msg_controllen >= sizeof(WSACMSGHDR)) ? (LPWSACMSGHDR)(msg)->msg_control                \
100
                                                 : (LPWSACMSGHDR)NULL)
101

            
102
#undef CMSG_NXTHDR
103
#define CMSG_NXTHDR(msg, cmsg)                                                                     \
104
  (((cmsg) == NULL)                                                                                \
105
       ? CMSG_FIRSTHDR(msg)                                                                        \
106
       : ((((PUCHAR)(cmsg) + WSA_CMSGHDR_ALIGN((cmsg)->cmsg_len) + sizeof(WSACMSGHDR)) >           \
107
           (PUCHAR)((msg)->msg_control) + (msg)->msg_controllen)                                   \
108
              ? (LPWSACMSGHDR)NULL                                                                 \
109
              : (LPWSACMSGHDR)((PUCHAR)(cmsg) + WSA_CMSGHDR_ALIGN((cmsg)->cmsg_len))))
110

            
111
#ifdef CMSG_DATA
112
#undef CMSG_DATA
113
#endif
114
#define CMSG_DATA(msg) WSA_CMSG_DATA(msg)
115

            
116
// Following Cygwin's porting example (may not be comprehensive)
117
#define SO_REUSEPORT SO_REUSEADDR
118

            
119
// Solve for rfc2292 (need to address rfc3542?)
120
#ifndef IPV6_RECVPKTINFO
121
#define IPV6_RECVPKTINFO IPV6_PKTINFO
122
#endif
123

            
124
#define INVALID_HANDLE INVALID_HANDLE_VALUE
125
#define SOCKET_VALID(sock) ((sock) != INVALID_SOCKET)
126
#define SOCKET_INVALID(sock) ((sock) == INVALID_SOCKET)
127
#define SOCKET_FAILURE(rc) ((rc) == SOCKET_ERROR)
128
#define SET_SOCKET_INVALID(sock) (sock) = INVALID_SOCKET
129

            
130
// arguments to shutdown
131
#define ENVOY_SHUT_RD SD_RECEIVE
132
#define ENVOY_SHUT_WR SD_SEND
133
#define ENVOY_SHUT_RDWR SD_BOTH
134

            
135
// winsock2 functions return distinct set of error codes, disjoint from POSIX errors (that are
136
// also available on Windows and set by POSIX function invocations). Here we map winsock2 error
137
// codes with platform agnostic macros that correspond to the same or roughly similar errors on
138
// POSIX systems for use in cross-platform socket error handling.
139
#define SOCKET_ERROR_AGAIN WSAEWOULDBLOCK
140
#define SOCKET_ERROR_NOT_SUP WSAEOPNOTSUPP
141
#define SOCKET_ERROR_AF_NO_SUP WSAEAFNOSUPPORT
142
#define SOCKET_ERROR_IN_PROGRESS WSAEINPROGRESS
143
// winsock2 does not differentiate between PERM and ACCESS violations
144
#define SOCKET_ERROR_PERM WSAEACCES
145
#define SOCKET_ERROR_ACCESS WSAEACCES
146
#define SOCKET_ERROR_MSG_SIZE WSAEMSGSIZE
147
#define SOCKET_ERROR_INTR WSAEINTR
148
#define SOCKET_ERROR_ADDR_NOT_AVAIL WSAEADDRNOTAVAIL
149
#define SOCKET_ERROR_INVAL WSAEINVAL
150
#define SOCKET_ERROR_ADDR_IN_USE WSAEADDRINUSE
151
#define SOCKET_ERROR_BADF WSAEBADF
152
#define SOCKET_ERROR_CONNRESET WSAECONNRESET
153
#define SOCKET_ERROR_NETUNREACH WSAENETUNREACH
154
#define SOCKET_ERROR_NOBUFS ENOBUFS
155

            
156
#define HANDLE_ERROR_PERM ERROR_ACCESS_DENIED
157
#define HANDLE_ERROR_INVALID ERROR_INVALID_HANDLE
158

            
159
#define ENVOY_WIN32_SIGNAL_COUNT 1
160
#define ENVOY_SIGTERM 0
161

            
162
namespace Platform {
163
constexpr absl::string_view null_device_path{"NUL"};
164

            
165
constexpr bool win32SupportsOriginalDestination() {
166
#if defined(SIO_QUERY_WFP_CONNECTION_REDIRECT_RECORDS) && defined(SO_ORIGINAL_DST)
167
  return true;
168
#else
169
  return false;
170
#endif
171
}
172

            
173
} // namespace Platform
174

            
175
#else // POSIX
176

            
177
#include <arpa/inet.h>
178
#include <fcntl.h>
179
#include <ifaddrs.h>
180
#include <netdb.h>
181
#include <netinet/in.h>
182
#if !defined(DO_NOT_INCLUDE_NETINET_TCP_H)
183
#include <netinet/tcp.h>
184
#endif
185
#include <netinet/udp.h> // for UDP_GRO
186
#include <sys/ioctl.h>
187
#include <sys/mman.h> // for mode_t
188
#include <sys/socket.h>
189
#include <sys/stat.h>
190
#include <sys/uio.h> // for iovec
191
#include <sys/un.h>
192
#include <sys/wait.h>
193
#include <unistd.h>
194

            
195
#ifdef __APPLE__
196
#include <libkern/OSByteOrder.h>
197
#define htole16(x) OSSwapHostToLittleInt16((x))
198
#define htole32(x) OSSwapHostToLittleInt32((x))
199
#define htole64(x) OSSwapHostToLittleInt64((x))
200
#define le16toh(x) OSSwapLittleToHostInt16((x))
201
#define le32toh(x) OSSwapLittleToHostInt32((x))
202
#define le64toh(x) OSSwapLittleToHostInt64((x))
203
#define htobe16(x) OSSwapHostToBigInt16((x))
204
#define htobe32(x) OSSwapHostToBigInt32((x))
205
#define htobe64(x) OSSwapHostToBigInt64((x))
206
#define be16toh(x) OSSwapBigToHostInt16((x))
207
#define be32toh(x) OSSwapBigToHostInt32((x))
208
#define be64toh(x) OSSwapBigToHostInt64((x))
209

            
210
#undef TRUE
211
#else
212
#include <endian.h>
213
#endif
214

            
215
#if defined(__linux__)
216
#include <linux/netfilter_ipv4.h>
217
#endif
218

            
219
38
#define PACKED_STRUCT(definition, ...) definition, ##__VA_ARGS__ __attribute__((packed))
220

            
221
#ifndef IP6T_SO_ORIGINAL_DST
222
// From linux/netfilter_ipv6/ip6_tables.h
223
#define IP6T_SO_ORIGINAL_DST 80
224
#endif
225

            
226
#ifndef SOL_UDP
227
#define SOL_UDP 17
228
#endif
229

            
230
#ifndef UDP_GRO
231
#define UDP_GRO 104
232
#endif
233

            
234
#ifndef UDP_SEGMENT
235
#define UDP_SEGMENT 103
236
#endif
237

            
238
#ifndef IPPROTO_MPTCP
239
3
#define IPPROTO_MPTCP 262
240
#endif
241

            
242
typedef int os_fd_t;            // NOLINT(modernize-use-using)
243
typedef int filesystem_os_id_t; // NOLINT(modernize-use-using)
244
typedef int signal_t;           // NOLINT(modernize-use-using)
245

            
246
87728
#define INVALID_HANDLE -1
247
10
#define INVALID_SOCKET -1
248
8516669
#define SOCKET_VALID(sock) ((sock) >= 0)
249
108937
#define SOCKET_INVALID(sock) ((sock) == -1)
250
202606
#define SOCKET_FAILURE(rc) ((rc) == -1)
251
152419
#define SET_SOCKET_INVALID(sock) (sock) = -1
252

            
253
// arguments to shutdown
254
#define ENVOY_SHUT_RD SHUT_RD
255
3079
#define ENVOY_SHUT_WR SHUT_WR
256
#define ENVOY_SHUT_RDWR SHUT_RDWR
257

            
258
// Mapping POSIX socket errors to common error names
259
1137804
#define SOCKET_ERROR_AGAIN EAGAIN
260
31
#define SOCKET_ERROR_NOT_SUP ENOTSUP
261
2
#define SOCKET_ERROR_AF_NO_SUP EAFNOSUPPORT
262
53581
#define SOCKET_ERROR_IN_PROGRESS EINPROGRESS
263
2
#define SOCKET_ERROR_PERM EPERM
264
4
#define SOCKET_ERROR_ACCESS EACCES
265
10
#define SOCKET_ERROR_MSG_SIZE EMSGSIZE
266
6
#define SOCKET_ERROR_INTR EINTR
267
6
#define SOCKET_ERROR_ADDR_NOT_AVAIL EADDRNOTAVAIL
268
568809
#define SOCKET_ERROR_INVAL EINVAL
269
112
#define SOCKET_ERROR_ADDR_IN_USE EADDRINUSE
270
63
#define SOCKET_ERROR_BADF EBADF
271
433
#define SOCKET_ERROR_CONNRESET ECONNRESET
272
1
#define SOCKET_ERROR_NETUNREACH ENETUNREACH
273
#define SOCKET_ERROR_NOBUFS ENOBUFS
274

            
275
// Mapping POSIX file errors to common error names
276
2
#define HANDLE_ERROR_PERM EACCES
277
4
#define HANDLE_ERROR_INVALID EBADF
278

            
279
10608
#define ENVOY_SIGTERM SIGTERM
280

            
281
namespace Platform {
282
constexpr absl::string_view null_device_path{"/dev/null"};
283
}
284
#endif
285

            
286
// Note: chromium disabled recvmmsg regardless of ndk version. However, the only Android target
287
// currently actively using Envoy is Envoy Mobile, where recvmmsg is not actively disabled. In fact,
288
// defining mmsghdr here caused a conflicting definition with the ndk's definition of the struct
289
// (https://github.com/envoyproxy/envoy-mobile/pull/772/checks?check_run_id=534152886#step:4:64).
290
// Therefore, we decided to remove the Android check introduced here in
291
// https://github.com/envoyproxy/envoy/pull/10120. If someone out there encounters problems with
292
// this please bring up in Envoy's slack channel #envoy-udp-quic-dev.
293
#if defined(__linux__) || defined(__EMSCRIPTEN__)
294
#define ENVOY_MMSG_MORE 1
295
#else
296
#define ENVOY_MMSG_MORE 0
297
#define MSG_WAITFORONE 0x10000 // recvmmsg(): block until 1+ packets avail.
298
// Posix structure for describing messages sent by 'sendmmsg` and received by
299
// 'recvmmsg'
300
struct mmsghdr {
301
  struct msghdr msg_hdr;
302
  unsigned int msg_len;
303
};
304
#endif
305

            
306
// TODO: Remove once bazel supports NDKs > 21
307
#define SUPPORTS_CPP_17_CONTIGUOUS_ITERATOR
308
#ifdef __ANDROID_API__
309
#if __ANDROID_API__ < 24
310
#undef SUPPORTS_CPP_17_CONTIGUOUS_ITERATOR
311
#endif // __ANDROID_API__ < 24
312
#endif // ifdef __ANDROID_API__
313

            
314
// https://android.googlesource.com/platform/bionic/+/master/docs/status.md
315
// ``pthread_getname_np`` is introduced in API 26
316
#define SUPPORTS_PTHREAD_NAMING 0
317
#if defined(__ANDROID_API__)
318
#if __ANDROID_API__ >= 26
319
#undef SUPPORTS_PTHREAD_NAMING
320
#define SUPPORTS_PTHREAD_NAMING 1
321
#endif // __ANDROID_API__ >= 26
322
#elif defined(__linux__)
323
#undef SUPPORTS_PTHREAD_NAMING
324
#define SUPPORTS_PTHREAD_NAMING 1
325
#endif // defined(__ANDROID_API__)
326

            
327
#if defined(__linux__)
328
// On Linux, default listen backlog size to net.core.somaxconn which is runtime configurable
329
10
#define ENVOY_TCP_BACKLOG_SIZE -1
330
#else
331
// On non-Linux platforms use 128 which is libevent listener default
332
#define ENVOY_TCP_BACKLOG_SIZE 128
333
#endif
334

            
335
#if defined(__linux__)
336
#define ENVOY_PLATFORM_ENABLE_SEND_RST 1
337
#else
338
#define ENVOY_PLATFORM_ENABLE_SEND_RST 0
339
#endif