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 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
|
/*
* Compatibility layer between Windows and Linux
*/
#ifdef _MSC_VER
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <hvsocket.h>
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#else /* !_MSC_VER */
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <stdint.h>
#include <time.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/socket.h>
#endif /* !_MSC_VER */
#include <inttypes.h>
#ifdef _MSC_VER
typedef int socklen_t;
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
#endif
#ifndef _MSC_VER
/* Compat layer for Linux/Unix */
typedef int SOCKET;
#ifndef SOCKET_ERROR
#define SOCKET_ERROR -1
#endif
#ifndef INVALID_SOCKET
#define INVALID_SOCKET -1
#endif
#define closesocket(_fd) close(_fd)
/* Shutdown flags are different too */
#define SD_SEND SHUT_WR
#define SD_RECEIVE SHUT_RD
#define SD_BOTH SHUT_RDWR
#define __cdecl
/* GUID handling */
typedef struct _GUID {
uint32_t Data1;
uint16_t Data2;
uint16_t Data3;
uint8_t Data4[8];
} GUID;
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
const GUID name = {l, w1, w2, {b1, b2, b3, b4, b5, b6, b7, b8}}
/* HV Socket definitions */
#define AF_HYPERV 43
#define HV_PROTOCOL_RAW 1
typedef struct _SOCKADDR_HV
{
unsigned short Family;
unsigned short Reserved;
GUID VmId;
GUID ServiceId;
} SOCKADDR_HV;
DEFINE_GUID(HV_GUID_ZERO,
0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
DEFINE_GUID(HV_GUID_BROADCAST,
0xFFFFFFFF, 0xFFFF, 0xFFFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
DEFINE_GUID(HV_GUID_WILDCARD,
0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
DEFINE_GUID(HV_GUID_CHILDREN,
0x90db8b89, 0x0d35, 0x4f79, 0x8c, 0xe9, 0x49, 0xea, 0x0a, 0xc8, 0xb7, 0xcd);
DEFINE_GUID(HV_GUID_LOOPBACK,
0xe0e16197, 0xdd56, 0x4a10, 0x91, 0x95, 0x5e, 0xe7, 0xa1, 0x55, 0xa8, 0x38);
DEFINE_GUID(HV_GUID_PARENT,
0xa42e7cda, 0xd03f, 0x480c, 0x9c, 0xc2, 0xa4, 0xde, 0x20, 0xab, 0xb8, 0x78);
#endif /* !_MSC_VER */
/* Common definitions (only valid on Linux, though) */
#ifndef AF_VSOCK
#define AF_VSOCK 40
#endif
#ifndef VMADDR_CID_ANY
#define VMADDR_CID_ANY -1U
#endif
#ifndef VMADDR_CID_HYPERVISOR
#define VMADDR_CID_HYPERVISOR 0
#endif
#ifndef VMADDR_CID_RESERVED
#define VMADDR_CID_RESERVED 1
#endif
#ifndef VMADDR_CID_HOST
#define VMADDR_CID_HOST 2
#endif
typedef struct _SOCKADDR_VM
{
unsigned short Family;
unsigned short Reserved;
unsigned int SvmPort;
unsigned int SvmCID;
#ifndef _MSC_VER
unsigned char svm_zero[sizeof(struct sockaddr) -
sizeof(sa_family_t) - sizeof(unsigned short) -
sizeof(unsigned int) - sizeof(unsigned int)];
#endif
} SOCKADDR_VM;
/* Thread wrappers */
#ifdef _MSC_VER
typedef HANDLE THREAD_HANDLE;
static inline int thread_create(THREAD_HANDLE *t, void *(*f)(void *), void *arg)
{
*t = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)f, arg, 0, NULL);
return 0;
}
static inline int thread_join(THREAD_HANDLE t)
{
WaitForSingleObject(t, INFINITE);
return 0;
}
static inline int thread_detach(THREAD_HANDLE t)
{
return CloseHandle(t);
}
#else
#include <pthread.h>
typedef pthread_t THREAD_HANDLE;
static inline int thread_create(THREAD_HANDLE *t, void *(*f)(void *), void *arg)
{
return pthread_create(t, NULL, f, arg);
}
static inline int thread_join(THREAD_HANDLE t)
{
return pthread_join(t, NULL);
}
static inline int thread_detach(THREAD_HANDLE t)
{
return pthread_detach(t);
}
#endif
/* Time wrappers */
#ifdef _MSC_VER
static inline uint64_t time_ns(void)
{
LARGE_INTEGER t, freq;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&t);
t.QuadPart *= 1000000000;
return (uint64_t)t.QuadPart / freq.QuadPart;
}
static inline unsigned int sleep(unsigned int sec)
{
Sleep(sec * 1000);
return 0;
}
#else
static inline uint64_t time_ns(void)
{
struct timespec ts;
int ret;
ret = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
if (ret)
return 0;
/* We don't really mind if this overflows...There are plenty of bits */
return (uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec;
}
#endif
/*
* Finally some common utility macros and functions
*/
#include <stdio.h>
#include <string.h>
#define GUID_FMT "%08x-%04hx-%04hx-%02x%02x-%02x%02x%02x%02x%02x%02x"
#define GUID_ARGS(_g) \
(_g).Data1, (_g).Data2, (_g).Data3, \
(_g).Data4[0], (_g).Data4[1], (_g).Data4[2], (_g).Data4[3], \
(_g).Data4[4], (_g).Data4[5], (_g).Data4[6], (_g).Data4[7]
#define GUID_SARGS(_g) \
&(_g).Data1, &(_g).Data2, &(_g).Data3, \
&(_g).Data4[0], &(_g).Data4[1], &(_g).Data4[2], &(_g).Data4[3], \
&(_g).Data4[4], &(_g).Data4[5], &(_g).Data4[6], &(_g).Data4[7]
static inline int parseguid(const char *s, GUID *g)
{
int res;
int p0, p1, p2, p3, p4, p5, p6, p7;
res = sscanf(s, GUID_FMT,
&g->Data1, &g->Data2, &g->Data3,
&p0, &p1, &p2, &p3, &p4, &p5, &p6, &p7);
if (res != 11)
return 1;
g->Data4[0] = p0;
g->Data4[1] = p1;
g->Data4[2] = p2;
g->Data4[3] = p3;
g->Data4[4] = p4;
g->Data4[5] = p5;
g->Data4[6] = p6;
g->Data4[7] = p7;
return 0;
}
/* Slightly different error handling between Windows and Linux */
static inline void sockerr(const char *msg)
{
#ifdef _MSC_VER
fprintf(stderr, "%s Error: %d\n", msg, WSAGetLastError());
#else
fprintf(stderr, "%s Error: %d. %s\n", msg, errno, strerror(errno));
#endif
}
/* poll wrappers */
/* Set socket to non-blocking */
static inline int poll_enable(SOCKET s)
{
int ret;
#ifdef _MSC_VER
unsigned long mode = 1;
ret = ioctlsocket(s, FIONBIO, &mode);
#else
int flags;
flags = fcntl(s, F_GETFL, 0);
if (flags < 0)
return flags;
ret = fcntl(s, F_SETFL, flags | O_NONBLOCK);
#endif
return ret;
}
/* Set socket to non-blocking */
static inline int poll_disable(SOCKET s)
{
int ret;
#ifdef _MSC_VER
unsigned long mode = 0;
ret = ioctlsocket(s, FIONBIO, &mode);
#else
int flags;
flags = fcntl(s, F_GETFL, 0);
if (flags < 0)
return flags;
ret = fcntl(s, F_SETFL, flags & ~O_NONBLOCK);
#endif
return ret;
}
/* Return true if we should poll */
static inline int poll_check()
{
#ifdef _MSC_VER
int err = WSAGetLastError();
return err == WSAEWOULDBLOCK || err == WSAEFAULT;
#else
return errno == EWOULDBLOCK || errno == EAGAIN;
#endif
}
#ifdef _MSC_VER
static inline int poll(struct pollfd fds[], unsigned long nfds, int timeout)
{
return WSAPoll(fds, nfds, timeout);
}
#endif
/* Connect with timeout (in milliseconds), different to WinSock ConnectEx() */
static inline int connect_ex(int s, const struct sockaddr *sa,
socklen_t len, int timeout)
{
struct timeval tv;
fd_set fdset;
int ret;
ret = poll_enable(s);
if (ret < 0)
return ret;
ret = connect(s, sa, len);
if (!ret)
goto out; /* Connected */
/* Got an error, see if we should select() */
#ifdef _MSC_VER
ret = WSAGetLastError();
if (ret != WSAEWOULDBLOCK) {
ret = SOCKET_ERROR;
goto out;
}
#else
if (errno != EINPROGRESS)
goto out;
#endif
FD_ZERO(&fdset);
FD_SET(s, &fdset);
tv.tv_sec = 0;
tv.tv_usec = timeout * 1000;
ret = select(s + 1, NULL, &fdset, NULL, &tv);
if (ret != 1) {
ret = SOCKET_ERROR;
goto out;
}
/* Check status */
ret = 0;
len = sizeof(ret);
/* char * is for windows... */
getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&ret, &len);
if (ret != 0)
ret = SOCKET_ERROR;
out:
poll_disable(s);
return ret;
}
|