The open source OpenXR runtime
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

d/remote: Support r_hub for Windows

Signed-off-by: utzcoz <utzcoz@outlook.com>

authored by

utzcoz and committed by
Jakob Bornecrantz
58193ad1 d7468d22

+172 -41
+172 -41
src/xrt/drivers/remote/r_hub.c
··· 1 - // Copyright 2020-2022, Collabora, Ltd. 1 + // Copyright 2020-2023, Collabora, Ltd. 2 2 // SPDX-License-Identifier: BSL-1.0 3 3 /*! 4 4 * @file ··· 17 17 #include <stdio.h> 18 18 #include <stdlib.h> 19 19 #include <string.h> 20 - #include <unistd.h> 20 + 21 + #if defined(XRT_OS_WINDOWS) 22 + #include <winsock2.h> 23 + #include <ws2tcpip.h> 24 + #include <windows.h> 21 25 26 + #pragma comment(lib, "ws2_32.lib") 27 + #else 28 + #include <unistd.h> 22 29 #include <sys/socket.h> 23 30 #include <sys/types.h> 24 31 #include <netdb.h> 25 32 #include <arpa/inet.h> 26 33 #include <netinet/in.h> 34 + #include <netinet/tcp.h> 27 35 28 - #ifndef __USE_MISC 29 - #define __USE_MISC // SOL_TCP on C11 30 - #endif 31 36 #ifndef _BSD_SOURCE 32 37 #define _BSD_SOURCE // same, but for musl // NOLINT 33 38 #endif 39 + #endif 34 40 35 - #include <netinet/tcp.h> 41 + #ifndef SOCKET 42 + #define SOCKET int 43 + #endif 44 + 45 + #ifndef __USE_MISC 46 + #define __USE_MISC // SOL_TCP on C11 47 + #endif 36 48 37 49 38 50 /* ··· 62 74 * 63 75 */ 64 76 77 + 78 + 79 + #if defined(XRT_OS_WINDOWS) 80 + static void 81 + socket_close(SOCKET id) 82 + { 83 + closesocket(id); 84 + } 85 + 86 + static SOCKET 87 + socket_create(void) 88 + { 89 + return socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 90 + } 91 + 92 + static int 93 + socket_set_opt(SOCKET id, int flag) 94 + { 95 + return setsockopt(id, SOL_SOCKET, SO_REUSEADDR, (const char *)&flag, sizeof(flag)); 96 + } 97 + 98 + static ssize_t 99 + socket_read(SOCKET id, void *ptr, size_t size, size_t current) 100 + { 101 + return recv(id, (char *)ptr, size - current, 0); 102 + } 103 + 104 + static size_t 105 + socket_write(SOCKET id, void *ptr, size_t size, size_t current) 106 + { 107 + return send(id, (const char *)ptr, size - current, 0); 108 + } 109 + 110 + #else 111 + static void 112 + socket_close(SOCKET id) 113 + { 114 + close(id); 115 + } 116 + 117 + static SOCKET 118 + socket_create(void) 119 + { 120 + return socket(AF_INET, SOCK_STREAM, 0); 121 + } 122 + 123 + static int 124 + socket_set_opt(SOCKET id, int flag) 125 + { 126 + return setsockopt(id, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); 127 + } 128 + 129 + static ssize_t 130 + socket_read(SOCKET id, void *ptr, size_t size, size_t current) 131 + { 132 + return read(id, ptr, size - current); 133 + } 134 + 135 + static ssize_t 136 + socket_write(SOCKET id, void *ptr, size_t size, size_t current) 137 + { 138 + return write(id, ptr, size - current); 139 + } 140 + #endif 141 + 65 142 static int 66 143 setup_accept_fd(struct r_hub *r) 67 144 { 68 145 struct sockaddr_in server_address = {0}; 69 - int ret; 146 + #if defined(XRT_OS_WINDOWS) 147 + // Initialize Winsock. 148 + WSADATA wsaData; 149 + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { 150 + int error = WSAGetLastError(); 151 + R_ERROR(r, "Failed to do WSAStartup %ld", error); 152 + return error; 153 + } 154 + #endif 155 + SOCKET ret = socket_create(); 70 156 71 - ret = socket(AF_INET, SOCK_STREAM, 0); 72 157 if (ret < 0) { 73 158 R_ERROR(r, "socket: %i", ret); 74 - return ret; 159 + goto cleanup; 75 160 } 76 161 77 162 r->accept_fd = ret; 78 163 79 164 int flag = 1; 80 - ret = setsockopt(r->accept_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); 165 + ret = socket_set_opt(r->accept_fd, flag); 81 166 if (ret < 0) { 82 167 R_ERROR(r, "setsockopt: %i", ret); 83 - close(r->accept_fd); 168 + socket_close(r->accept_fd); 84 169 r->accept_fd = -1; 85 - return ret; 170 + goto cleanup; 86 171 } 87 172 88 173 server_address.sin_family = AF_INET; ··· 92 177 ret = bind(r->accept_fd, (struct sockaddr *)&server_address, sizeof(server_address)); 93 178 if (ret < 0) { 94 179 R_ERROR(r, "bind: %i", ret); 95 - close(r->accept_fd); 180 + socket_close(r->accept_fd); 96 181 r->accept_fd = -1; 97 - return ret; 182 + goto cleanup; 98 183 } 99 184 185 + R_INFO(r, "Listen address %s on port %d", inet_ntoa(server_address.sin_addr), r->port); 186 + 100 187 listen(r->accept_fd, 5); 101 188 102 189 return 0; 190 + cleanup: 191 + #if defined(XRT_OS_WINDOWS) 192 + WSACleanup(); 193 + #endif 194 + return ret; 103 195 } 104 196 105 197 static bool 106 - wait_for_read_and_to_continue(struct r_hub *r, int socket) 198 + wait_for_read_and_to_continue(struct r_hub *r, SOCKET socket) 107 199 { 108 200 fd_set set; 109 201 int ret = 0; ··· 139 231 { 140 232 struct sockaddr_in addr = {0}; 141 233 int ret = 0; 142 - int conn_fd; 143 - 144 234 if (!wait_for_read_and_to_continue(r, r->accept_fd)) { 235 + R_ERROR(r, "Failed to wait for id %d", r->accept_fd); 145 236 return -1; 146 237 } 147 238 ··· 152 243 return ret; 153 244 } 154 245 155 - conn_fd = ret; 246 + SOCKET conn_fd = ret; 156 247 157 248 int flags = 1; 158 - ret = setsockopt(conn_fd, SOL_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)); 249 + ret = socket_set_opt(r->accept_fd, flags); 159 250 if (ret < 0) { 160 251 R_ERROR(r, "setsockopt: %i", ret); 161 - close(conn_fd); 252 + socket_close(conn_fd); 162 253 return ret; 163 254 } 164 255 ··· 184 275 return -1; 185 276 } 186 277 187 - ssize_t ret = read(rc->fd, ptr, size - current); 278 + ssize_t ret = socket_read(rc->fd, ptr, size, current); 188 279 if (ret < 0) { 280 + #if defined(XRT_OS_WINDOWS) 281 + RC_ERROR(rc, "recv: %zi", WSAGetLastError()); 282 + #else 189 283 RC_ERROR(rc, "read: %zi", ret); 284 + #endif 190 285 return ret; 191 286 } else if (ret > 0) { 192 287 current += (size_t)ret; ··· 257 352 258 353 // Should be safe to destroy the sockets now. 259 354 if (r->accept_fd >= 0) { 260 - close(r->accept_fd); 355 + socket_close(r->accept_fd); 261 356 r->accept_fd = -1; 262 357 } 263 358 ··· 267 362 } 268 363 269 364 free(r); 365 + 366 + #if defined(XRT_OS_WINDOWS) 367 + // Clean up Winsock. 368 + WSACleanup(); 369 + #endif 270 370 } 271 371 272 372 ··· 359 459 u_var_add_bool(r, &r->latest.right.active, "right.active"); 360 460 u_var_add_pose(r, &r->latest.right.pose, "right.pose"); 361 461 362 - 363 462 /* 364 463 * Done now. 365 464 */ ··· 386 485 // Set log level. 387 486 rc->log_level = debug_get_log_option_remote_log(); 388 487 488 + #if defined(XRT_OS_WINDOWS) 489 + // Initialize Winsock. 490 + WSADATA wsaData; 491 + ret = WSAStartup(MAKEWORD(2, 2), &wsaData); 492 + if (ret != 0) { 493 + RC_ERROR(rc, "Failed to do WSAStartup %ld", WSAGetLastError()); 494 + return ret; 495 + } 496 + #endif 497 + 389 498 // Address 390 499 addr.sin_family = AF_INET; 391 500 addr.sin_port = htons(port); 392 501 393 - ret = inet_pton(AF_INET, ip_addr, &addr.sin_addr); 502 + // inet_pton/InetPton resolves "localhost" as 0.0.0.0 or 255.255.255.255, and it causes connection error. To 503 + // avoid this issue, the following logic converts "localhost" to "127.0.0.1" first. 504 + if (strcmp("localhost", ip_addr) == 0) { 505 + ret = inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr); 506 + } else { 507 + ret = inet_pton(AF_INET, ip_addr, &addr.sin_addr); 508 + } 394 509 if (ret < 0) { 395 - RC_ERROR(rc, "inet_pton: %i", ret); 396 - return ret; 510 + RC_ERROR(rc, "Failed to do inet pton for %s: %i", ip_addr, ret); 511 + goto cleanup; 397 512 } 398 513 399 - ret = socket(AF_INET, SOCK_STREAM, 0); 514 + ret = socket_create(); 400 515 if (ret < 0) { 401 - RC_ERROR(rc, "socket: %i", ret); 402 - return ret; 516 + #if defined(XRT_OS_WINDOWS) 517 + RC_ERROR(rc, "Failed to create socket %ld", WSAGetLastError()); 518 + #else 519 + RC_ERROR(rc, "Failed to create socket: %i", ret); 520 + #endif 521 + goto cleanup; 403 522 } 404 523 405 524 conn_fd = ret; 406 525 407 526 ret = connect(conn_fd, (struct sockaddr *)&addr, sizeof(addr)); 408 - if (ret < 0) { 409 - RC_ERROR(rc, "connect: %i", ret); 410 - close(conn_fd); 411 - return ret; 527 + // If connect operation succeed, both Windows and POSIX returns 0. 528 + if (ret != 0) { 529 + #if defined(XRT_OS_WINDOWS) 530 + RC_ERROR(rc, "Failed to connect id %d and addr %s with failure %d", conn_fd, inet_ntoa(addr.sin_addr), 531 + WSAGetLastError()); 532 + #else 533 + RC_ERROR(rc, "Failed to connect id %d and addr %s with failure %d", conn_fd, inet_ntoa(addr.sin_addr), 534 + ret); 535 + #endif 536 + socket_close(conn_fd); 537 + goto cleanup; 412 538 } 413 539 414 540 int flags = 1; 415 - ret = setsockopt(conn_fd, SOL_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)); 541 + ret = socket_set_opt(conn_fd, flags); 416 542 if (ret < 0) { 417 - RC_ERROR(rc, "setsockopt: %i", ret); 418 - close(conn_fd); 419 - return ret; 543 + RC_ERROR(rc, "Failed to setsockopt: %i", ret); 544 + socket_close(conn_fd); 545 + goto cleanup; 420 546 } 421 547 422 548 rc->fd = conn_fd; 423 549 424 550 return 0; 551 + 552 + cleanup: 553 + #if defined(XRT_OS_WINDOWS) 554 + WSACleanup(); 555 + #endif 556 + return ret; 425 557 } 426 558 427 559 int ··· 432 564 433 565 while (current < size) { 434 566 void *ptr = (uint8_t *)data + current; 435 - 436 - ssize_t ret = read(rc->fd, ptr, size - current); 567 + ssize_t ret = socket_read(rc->fd, ptr, size, current); 437 568 if (ret < 0) { 438 569 RC_ERROR(rc, "read: %zi", ret); 439 570 return ret; ··· 456 587 size_t current = 0; 457 588 458 589 while (current < size) { 459 - const void *ptr = (const uint8_t *)data + current; 590 + void *ptr = (uint8_t *)data + current; 460 591 461 - ssize_t ret = write(rc->fd, ptr, size - current); 592 + ssize_t ret = socket_write(rc->fd, ptr, size, current); 462 593 if (ret < 0) { 463 594 RC_ERROR(rc, "write: %zi", ret); 464 595 return ret;