The open source OpenXR runtime
0
fork

Configure Feed

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

ipc: Add Windows support

authored by

Julian Petrov and committed by
Ryan Pavlik
d0f713c4 7669d2c5

+738 -52
+1 -1
CMakeLists.txt
··· 241 241 option(XRT_FEATURE_COLOR_LOG "Enable logging in color on supported platforms" ON) 242 242 option_with_deps(XRT_FEATURE_COMPOSITOR_MAIN "Build main compositor host functionality" DEPENDS XRT_HAVE_VULKAN "XRT_HAVE_WAYLAND OR XRT_HAVE_XCB OR ANDROID OR WIN32") 243 243 option_with_deps(XRT_FEATURE_COMPOSITOR_NULL "Build testing null compositor" DEPENDS XRT_HAVE_VULKAN) 244 - option_with_deps(XRT_FEATURE_IPC "Enable the build of the IPC layer" DEPENDS "NOT WIN32") 244 + option(XRT_FEATURE_IPC "Enable the build of the IPC layer" ON) 245 245 option_with_deps(XRT_FEATURE_OPENXR "Build OpenXR runtime target" DEPENDS "XRT_FEATURE_COMPOSITOR_MAIN OR XRT_FEATURE_COMPOSITOR_NULL") 246 246 option_with_deps(XRT_FEATURE_RENDERDOC "Enable RenderDoc API" DEPENDS "RT_LIBRARY OR WIN32") 247 247 option_with_deps(XRT_FEATURE_SERVICE "Enable separate service module for OpenXR runtime" DEPENDS XRT_FEATURE_IPC XRT_FEATURE_OPENXR)
+17
src/xrt/ipc/CMakeLists.txt
··· 39 39 target_include_directories( 40 40 ipc_shared PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} 41 41 ) 42 + 43 + if(WIN32) 44 + target_sources(ipc_shared PRIVATE shared/ipc_utils_windows.cpp) 45 + endif() 46 + 42 47 target_link_libraries(ipc_shared PRIVATE aux_util) 43 48 44 49 if(RT_LIBRARY) ··· 61 66 target_include_directories( 62 67 ipc_client PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} 63 68 ) 69 + if(WIN32) 70 + if(XRT_SERVICE_EXECUTABLE) 71 + target_compile_definitions( 72 + ipc_client PUBLIC XRT_SERVICE_EXECUTABLE="${XRT_SERVICE_EXECUTABLE}.exe" 73 + ) 74 + endif() 75 + endif() 64 76 target_link_libraries(ipc_client PRIVATE aux_util ipc_shared) 65 77 66 78 ### ··· 110 122 elseif(XRT_HAVE_LINUX) 111 123 target_sources( 112 124 ipc_server PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/server/ipc_server_mainloop_linux.c 125 + ) 126 + elseif(WIN32) 127 + target_sources( 128 + ipc_server 129 + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/server/ipc_server_mainloop_windows.cpp 113 130 ) 114 131 endif()
+7 -6
src/xrt/ipc/client/ipc_client_compositor.c
··· 13 13 #include "xrt/xrt_defines.h" 14 14 #include "xrt/xrt_config_os.h" 15 15 16 + #include "util/u_misc.h" 17 + #include "util/u_handles.h" 18 + #include "util/u_trace_marker.h" 19 + 16 20 #include "os/os_time.h" 17 21 18 22 #include "util/u_wait.h" ··· 25 29 26 30 #include <string.h> 27 31 #include <stdio.h> 32 + #if !defined(XRT_OS_WINDOWS) 28 33 #include <unistd.h> 29 34 #include <sys/socket.h> 30 35 #include <sys/un.h> 36 + #endif 31 37 #include <errno.h> 32 38 #include <assert.h> 33 39 ··· 711 717 // Reset. 712 718 icc->layers.layer_count = 0; 713 719 714 - #ifdef XRT_GRAPHICS_SYNC_HANDLE_IS_FD 715 720 // Need to consume this handle. 716 721 if (valid_sync) { 717 - close(sync_handle); 718 - sync_handle = XRT_GRAPHICS_SYNC_HANDLE_INVALID; 722 + u_graphics_sync_unref(&sync_handle); 719 723 } 720 - #else 721 - #error "Not yet implemented for this platform" 722 - #endif 723 724 724 725 return res; 725 726 }
-1
src/xrt/ipc/client/ipc_client_device.c
··· 9 9 10 10 #include <math.h> 11 11 #include <stdio.h> 12 - #include <unistd.h> 13 12 #include <stdlib.h> 14 13 #include <string.h> 15 14 #include <assert.h>
-1
src/xrt/ipc/client/ipc_client_hmd.c
··· 9 9 10 10 #include <math.h> 11 11 #include <stdio.h> 12 - #include <unistd.h> 13 12 #include <stdlib.h> 14 13 #include <string.h> 15 14 #include <assert.h>
+136 -6
src/xrt/ipc/client/ipc_client_instance.c
··· 7 7 * @ingroup ipc_client 8 8 */ 9 9 10 + #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) 11 + #define _CRT_SECURE_NO_WARNINGS 12 + #endif 13 + 10 14 #include "xrt/xrt_instance.h" 11 15 #include "xrt/xrt_gfx_native.h" 12 16 #include "xrt/xrt_handles.h" ··· 25 29 #include "util/u_file.h" 26 30 27 31 #include <stdio.h> 32 + #if !defined(XRT_OS_WINDOWS) 28 33 #include <sys/socket.h> 29 34 #include <sys/un.h> 30 35 #include <sys/types.h> ··· 34 39 #include <errno.h> 35 40 #include <fcntl.h> 36 41 #include <unistd.h> 42 + #endif 37 43 #include <limits.h> 38 44 39 45 #ifdef XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER ··· 104 110 return false; 105 111 } 106 112 107 - ipc_c->imc.socket_fd = socket; 113 + ipc_c->imc.ipc_handle = socket; 108 114 ipc_c->imc.log_level = ipc_c->log_level; 109 115 110 116 return true; 111 117 } 112 118 119 + #elif defined(XRT_OS_WINDOWS) 120 + 121 + #if defined(NO_XRT_SERVICE_LAUNCH) || !defined(XRT_SERVICE_EXECUTABLE) 122 + static HANDLE 123 + ipc_connect_pipe(struct ipc_connection *ipc_c, const char *pipe_name) 124 + { 125 + HANDLE pipe_inst = CreateFileA(pipe_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 126 + if (pipe_inst == INVALID_HANDLE_VALUE) { 127 + DWORD err = GetLastError(); 128 + IPC_ERROR(ipc_c, "Connect to %s failed: %d %s", pipe_name, err, ipc_winerror(err)); 129 + } 130 + return pipe_inst; 131 + } 132 + #else 133 + // N.B. quality of life fallback to try launch the XRT_SERVICE_EXECUTABLE if pipe is not found 134 + static HANDLE 135 + ipc_connect_pipe(struct ipc_connection *ipc_c, const char *pipe_name) 136 + { 137 + HANDLE pipe_inst = CreateFileA(pipe_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 138 + if (pipe_inst != INVALID_HANDLE_VALUE) { 139 + return pipe_inst; 140 + } 141 + DWORD err = GetLastError(); 142 + IPC_ERROR(ipc_c, "Connect to %s failed: %d %s", pipe_name, err, ipc_winerror(err)); 143 + if (err != ERROR_FILE_NOT_FOUND) { 144 + return INVALID_HANDLE_VALUE; 145 + } 146 + IPC_INFO(ipc_c, "Trying to launch " XRT_SERVICE_EXECUTABLE "..."); 147 + HMODULE hmod; 148 + if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, 149 + (LPCSTR)ipc_connect_pipe, &hmod)) { 150 + IPC_ERROR(ipc_c, "GetModuleHandleExA failed: %d %s", err, ipc_winerror(err)); 151 + return INVALID_HANDLE_VALUE; 152 + } 153 + char service_path[MAX_PATH]; 154 + if (!GetModuleFileNameA(hmod, service_path, sizeof(service_path))) { 155 + IPC_ERROR(ipc_c, "GetModuleFileNameA failed: %d %s", err, ipc_winerror(err)); 156 + return INVALID_HANDLE_VALUE; 157 + } 158 + char *p = strrchr(service_path, '\\'); 159 + if (!p) { 160 + IPC_ERROR(ipc_c, "failed to parse the path %s", service_path); 161 + return INVALID_HANDLE_VALUE; 162 + } 163 + strcpy(p + 1, XRT_SERVICE_EXECUTABLE); 164 + STARTUPINFOA si = {.cb = sizeof(si)}; 165 + PROCESS_INFORMATION pi; 166 + if (!CreateProcessA(NULL, service_path, NULL, NULL, false, 0, NULL, NULL, &si, &pi)) { 167 + *p = 0; 168 + p = strrchr(service_path, '\\'); 169 + if (!p) { 170 + err = GetLastError(); 171 + IPC_INFO(ipc_c, XRT_SERVICE_EXECUTABLE " not found in %s: %d %s", service_path, err, 172 + ipc_winerror(err)); 173 + return INVALID_HANDLE_VALUE; 174 + } 175 + strcpy(p + 1, "service\\" XRT_SERVICE_EXECUTABLE); 176 + if (!CreateProcessA(NULL, service_path, NULL, NULL, false, 0, NULL, NULL, &si, &pi)) { 177 + err = GetLastError(); 178 + IPC_INFO(ipc_c, XRT_SERVICE_EXECUTABLE " not found at %s: %d %s", service_path, err, 179 + ipc_winerror(err)); 180 + return INVALID_HANDLE_VALUE; 181 + } 182 + } 183 + IPC_INFO(ipc_c, "Launched %s (pid %d)... Waiting for %s...", service_path, pi.dwProcessId, pipe_name); 184 + CloseHandle(pi.hThread); 185 + for (int i = 0;; i++) { 186 + pipe_inst = CreateFileA(pipe_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 187 + if (pipe_inst != INVALID_HANDLE_VALUE) { 188 + IPC_INFO(ipc_c, "Connected to %s after %d msec on try %d!", pipe_name, i * 100, i + 1); 189 + break; 190 + } 191 + err = GetLastError(); 192 + if (err != ERROR_FILE_NOT_FOUND || WaitForSingleObject(pi.hProcess, 100) != WAIT_TIMEOUT) { 193 + IPC_ERROR(ipc_c, "Connect to %s failed: %d %s", pipe_name, err, ipc_winerror(err)); 194 + break; 195 + } 196 + } 197 + CloseHandle(pi.hProcess); 198 + return pipe_inst; 199 + } 200 + #endif 201 + 202 + static bool 203 + ipc_connect(struct ipc_connection *ipc_c) 204 + { 205 + ipc_c->log_level = debug_get_log_option_ipc_log(); 206 + 207 + const char pipe_prefix[] = "\\\\.\\pipe\\"; 208 + #define prefix_len sizeof(pipe_prefix) - 1 209 + char pipe_name[MAX_PATH + prefix_len]; 210 + strcpy(pipe_name, pipe_prefix); 211 + 212 + if (u_file_get_path_in_runtime_dir(XRT_IPC_MSG_SOCK_FILENAME, pipe_name + prefix_len, MAX_PATH) == -1) { 213 + U_LOG_E("u_file_get_path_in_runtime_dir failed!"); 214 + return false; 215 + } 216 + 217 + HANDLE pipe_inst = ipc_connect_pipe(ipc_c, pipe_name); 218 + if (pipe_inst == INVALID_HANDLE_VALUE) { 219 + return false; 220 + } 221 + DWORD mode = PIPE_READMODE_MESSAGE | PIPE_WAIT; 222 + if (!SetNamedPipeHandleState(pipe_inst, &mode, NULL, NULL)) { 223 + DWORD err = GetLastError(); 224 + IPC_ERROR(ipc_c, "SetNamedPipeHandleState(PIPE_READMODE_MESSAGE | PIPE_WAIT) failed: %d %s", err, 225 + ipc_winerror(err)); 226 + return false; 227 + } 228 + 229 + ipc_c->imc.ipc_handle = pipe_inst; 230 + ipc_c->imc.log_level = ipc_c->log_level; 231 + return true; 232 + } 233 + 234 + int 235 + getpid() 236 + { 237 + return GetCurrentProcessId(); 238 + } 113 239 114 240 #else 115 241 static bool ··· 135 261 int size = u_file_get_path_in_runtime_dir(XRT_IPC_MSG_SOCK_FILENAME, sock_file, PATH_MAX); 136 262 if (size == -1) { 137 263 IPC_ERROR(ipc_c, "Could not get socket file name"); 138 - return -1; 264 + return false; 139 265 } 140 266 141 267 memset(&addr, 0, sizeof(addr)); ··· 149 275 return false; 150 276 } 151 277 152 - ipc_c->imc.socket_fd = socket; 278 + ipc_c->imc.ipc_handle = socket; 153 279 ipc_c->imc.log_level = ipc_c->log_level; 154 280 155 281 return true; ··· 299 425 ii->base.get_prober = ipc_client_instance_get_prober; 300 426 ii->base.destroy = ipc_client_instance_destroy; 301 427 302 - // FDs needs to be set to something negative. 303 - ii->ipc_c.imc.socket_fd = -1; 428 + ii->ipc_c.imc.ipc_handle = XRT_IPC_HANDLE_INVALID; 304 429 ii->ipc_c.ism_handle = XRT_SHMEM_HANDLE_INVALID; 305 430 306 431 os_mutex_init(&ii->ipc_c.mutex); ··· 340 465 return xret; 341 466 } 342 467 468 + const size_t size = sizeof(struct ipc_shared_memory); 469 + 470 + #ifdef XRT_OS_WINDOWS 471 + ii->ipc_c.ism = MapViewOfFile(ii->ipc_c.ism_handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size); 472 + #else 343 473 const int flags = MAP_SHARED; 344 474 const int access = PROT_READ | PROT_WRITE; 345 - const size_t size = sizeof(struct ipc_shared_memory); 346 475 347 476 ii->ipc_c.ism = mmap(NULL, size, access, flags, ii->ipc_c.ism_handle, 0); 477 + #endif 348 478 if (ii->ipc_c.ism == NULL) { 349 479 IPC_ERROR((&ii->ipc_c), "Failed to mmap shm!"); 350 480 free(ii);
+19 -2
src/xrt/ipc/server/ipc_server.h
··· 236 236 #define XRT_IPC_GOT_IMPL 237 237 #endif 238 238 239 + #if defined(XRT_OS_WINDOWS) || defined(XRT_DOXYGEN) 240 + /*! 241 + * @name Desktop Windows Mainloop Members 242 + * @{ 243 + */ 244 + 245 + //! Named Pipe that we accept connections on. 246 + HANDLE pipe_handle; 247 + 248 + //! Name of the Pipe that we accept connections on. 249 + char *pipe_name; 250 + 251 + /*! @} */ 252 + 253 + #define XRT_IPC_GOT_IMPL 254 + #endif 255 + 239 256 #ifndef XRT_IPC_GOT_IMPL 240 257 #error "Need port" 241 258 #endif ··· 397 414 * @{ 398 415 */ 399 416 /*! 400 - * Start a thread for a client connected at the other end of the file descriptor @p fd. 417 + * Start a thread for a client connected at the other end of the ipc handle @p ipc_handle. 401 418 * @memberof ipc_server 402 419 */ 403 420 void 404 - ipc_server_start_client_listener_thread(struct ipc_server *vs, int fd); 421 + ipc_server_start_client_listener_thread(struct ipc_server *vs, xrt_ipc_handle_t ipc_handle); 405 422 406 423 /*! 407 424 * Perform whatever needs to be done when the mainloop polling encounters a failure.
+2 -2
src/xrt/ipc/server/ipc_server_handler.c
··· 637 637 } 638 638 volatile struct ipc_client_state *ics = &_ics->server->threads[id].ics; 639 639 640 - if (ics->imc.socket_fd <= 0) { 640 + if (!xrt_ipc_handle_is_valid(ics->imc.ipc_handle)) { 641 641 return XRT_ERROR_IPC_FAILURE; 642 642 } 643 643 ··· 707 707 708 708 ics = &_ics->server->threads[client_id].ics; 709 709 710 - if (ics->imc.socket_fd <= 0) { 710 + if (!xrt_ipc_handle_is_valid(ics->imc.ipc_handle)) { 711 711 return XRT_ERROR_IPC_FAILURE; 712 712 } 713 713
+160
src/xrt/ipc/server/ipc_server_mainloop_windows.cpp
··· 1 + // Copyright 2022, Magic Leap, Inc. 2 + // Copyright 2020-2022, Collabora, Ltd. 3 + // SPDX-License-Identifier: BSL-1.0 4 + /*! 5 + * @file 6 + * @brief Server mainloop details on Windows. 7 + * @author Julian Petrov <jpetrov@magicleap.com> 8 + * @author Ryan Pavlik <ryan.pavlik@collabora.com> 9 + * @author Jakob Bornecrantz <jakob@collabora.com> 10 + * @ingroup ipc_server 11 + */ 12 + 13 + #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) 14 + #define _CRT_SECURE_NO_WARNINGS 15 + #endif 16 + 17 + #include "xrt/xrt_device.h" 18 + #include "xrt/xrt_instance.h" 19 + #include "xrt/xrt_compositor.h" 20 + #include "xrt/xrt_config_have.h" 21 + #include "xrt/xrt_config_os.h" 22 + 23 + #include "os/os_time.h" 24 + #include "util/u_var.h" 25 + #include "util/u_misc.h" 26 + #include "util/u_debug.h" 27 + #include "util/u_trace_marker.h" 28 + #include "util/u_file.h" 29 + 30 + #include "shared/ipc_shmem.h" 31 + #include "server/ipc_server.h" 32 + 33 + #include <conio.h> 34 + 35 + /* 36 + * 37 + * Static functions. 38 + * 39 + */ 40 + static void 41 + ipc_server_create_another_pipe_instance(struct ipc_server *vs, struct ipc_server_mainloop *ml) 42 + { 43 + ml->pipe_handle = 44 + CreateNamedPipeA(ml->pipe_name, PIPE_ACCESS_DUPLEX, 45 + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT | PIPE_REJECT_REMOTE_CLIENTS, 46 + IPC_MAX_CLIENTS, IPC_BUF_SIZE, IPC_BUF_SIZE, 0, NULL); 47 + if (ml->pipe_handle == INVALID_HANDLE_VALUE) { 48 + DWORD err = GetLastError(); 49 + if (err == ERROR_PIPE_BUSY) { 50 + U_LOG_W("CreateNamedPipeA failed: %d %s An existing client must disconnect first!", err, 51 + ipc_winerror(err)); 52 + } else { 53 + U_LOG_E("CreateNamedPipeA failed: %d %s", err, ipc_winerror(err)); 54 + ipc_server_handle_failure(vs); 55 + } 56 + } 57 + } 58 + 59 + /* 60 + * 61 + * Exported functions 62 + * 63 + */ 64 + 65 + void 66 + ipc_server_mainloop_poll(struct ipc_server *vs, struct ipc_server_mainloop *ml) 67 + { 68 + IPC_TRACE_MARKER(); 69 + 70 + if (_kbhit()) { 71 + U_LOG_E("console input! exiting..."); 72 + ipc_server_handle_shutdown_signal(vs); 73 + return; 74 + } 75 + 76 + if (!ml->pipe_handle) { 77 + ipc_server_create_another_pipe_instance(vs, ml); 78 + } 79 + if (!ml->pipe_handle) { 80 + return; 81 + } 82 + 83 + if (ConnectNamedPipe(ml->pipe_handle, NULL)) { 84 + U_LOG_E("ConnectNamedPipe unexpected return TRUE (last error: %d). Treating as failure...", 85 + GetLastError()); 86 + ipc_server_handle_failure(vs); 87 + return; 88 + } 89 + switch (DWORD err = GetLastError()) { 90 + case ERROR_PIPE_LISTENING: return; 91 + case ERROR_PIPE_CONNECTED: { 92 + DWORD mode = PIPE_READMODE_MESSAGE | PIPE_WAIT; 93 + if (!SetNamedPipeHandleState(ml->pipe_handle, &mode, NULL, NULL)) { 94 + err = GetLastError(); 95 + U_LOG_E("SetNamedPipeHandleState(PIPE_READMODE_MESSAGE | PIPE_WAIT) failed: %d %s", err, 96 + ipc_winerror(err)); 97 + ipc_server_handle_failure(vs); 98 + return; 99 + } 100 + ipc_server_start_client_listener_thread(vs, ml->pipe_handle); 101 + ipc_server_create_another_pipe_instance(vs, ml); 102 + return; 103 + } 104 + default: 105 + U_LOG_E("ConnectNamedPipe failed: %d %s", err, ipc_winerror(err)); 106 + ipc_server_handle_failure(vs); 107 + return; 108 + } 109 + } 110 + 111 + int 112 + ipc_server_mainloop_init(struct ipc_server_mainloop *ml) 113 + { 114 + IPC_TRACE_MARKER(); 115 + 116 + ml->pipe_handle = INVALID_HANDLE_VALUE; 117 + ml->pipe_name = nullptr; 118 + 119 + constexpr char pipe_prefix[] = "\\\\.\\pipe\\"; 120 + constexpr int prefix_len = sizeof(pipe_prefix) - 1; 121 + char pipe_name[MAX_PATH + prefix_len]; 122 + strcpy(pipe_name, pipe_prefix); 123 + 124 + if (u_file_get_path_in_runtime_dir(XRT_IPC_MSG_SOCK_FILENAME, pipe_name + prefix_len, MAX_PATH) == -1) { 125 + U_LOG_E("u_file_get_path_in_runtime_dir failed!"); 126 + return -1; 127 + } 128 + 129 + ml->pipe_name = _strdup(pipe_name); 130 + if (!ml->pipe_name) { 131 + U_LOG_E("_strdup(\"%s\") failed!", pipe_name); 132 + } else { 133 + ml->pipe_handle = CreateNamedPipeA(ml->pipe_name, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, 134 + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT | 135 + PIPE_REJECT_REMOTE_CLIENTS, 136 + IPC_MAX_CLIENTS, IPC_BUF_SIZE, IPC_BUF_SIZE, 0, NULL); 137 + if (ml->pipe_handle != INVALID_HANDLE_VALUE) { 138 + return 0; 139 + } 140 + DWORD err = GetLastError(); 141 + U_LOG_E("CreateNamedPipeA \"%s\" first instance failed: %d %s", ml->pipe_name, err, ipc_winerror(err)); 142 + } 143 + ipc_server_mainloop_deinit(ml); 144 + return -1; 145 + } 146 + 147 + void 148 + ipc_server_mainloop_deinit(struct ipc_server_mainloop *ml) 149 + { 150 + IPC_TRACE_MARKER(); 151 + 152 + if (ml->pipe_handle != INVALID_HANDLE_VALUE) { 153 + CloseHandle(ml->pipe_handle); 154 + ml->pipe_handle = INVALID_HANDLE_VALUE; 155 + } 156 + if (ml->pipe_name) { 157 + free(ml->pipe_name); 158 + ml->pipe_name = nullptr; 159 + } 160 + }
+60 -2
src/xrt/ipc/server/ipc_server_per_client_thread.c
··· 15 15 #include "server/ipc_server.h" 16 16 #include "ipc_server_generated.h" 17 17 18 + #ifndef XRT_OS_WINDOWS 19 + 18 20 #include <unistd.h> 19 21 #include <fcntl.h> 20 22 #include <errno.h> ··· 34 36 static int 35 37 setup_epoll(volatile struct ipc_client_state *ics) 36 38 { 37 - int listen_socket = ics->imc.socket_fd; 39 + int listen_socket = ics->imc.ipc_handle; 38 40 assert(listen_socket >= 0); 39 41 40 42 int ret = epoll_create1(EPOLL_CLOEXEC); ··· 101 103 102 104 // Finally get the data that is waiting for us. 103 105 //! @todo replace this call 104 - ssize_t len = recv(ics->imc.socket_fd, &buf, IPC_BUF_SIZE, 0); 106 + ssize_t len = recv(ics->imc.ipc_handle, &buf, IPC_BUF_SIZE, 0); 105 107 if (len < 4) { 106 108 IPC_ERROR(ics->server, "Invalid packet received, disconnecting client."); 107 109 break; ··· 140 142 ipc_server_deactivate_session(ics); 141 143 } 142 144 145 + #else // XRT_OS_WINDOWS 146 + 147 + static void 148 + client_loop(volatile struct ipc_client_state *ics) 149 + { 150 + IPC_INFO(ics->server, "Client connected"); 151 + 152 + uint8_t buf[IPC_BUF_SIZE]; 153 + 154 + while (ics->server->running) { 155 + DWORD len; 156 + if (!ReadFile(ics->imc.ipc_handle, buf, sizeof(buf), &len, NULL)) { 157 + DWORD err = GetLastError(); 158 + if (err == ERROR_BROKEN_PIPE) { 159 + IPC_INFO(ics->server, "ReadFile from pipe: %d %s", err, ipc_winerror(err)); 160 + } else { 161 + IPC_ERROR(ics->server, "ReadFile from pipe failed: %d %s", err, ipc_winerror(err)); 162 + } 163 + break; 164 + } 165 + if (len < sizeof(ipc_command_t)) { 166 + IPC_ERROR(ics->server, "Invalid packet received, disconnecting client."); 167 + break; 168 + } else { 169 + // Check the first 4 bytes of the message and dispatch. 170 + ipc_command_t *ipc_command = (ipc_command_t *)buf; 171 + xrt_result_t result = ipc_dispatch(ics, ipc_command); 172 + if (result != XRT_SUCCESS) { 173 + IPC_ERROR(ics->server, "During packet handling, disconnecting client."); 174 + break; 175 + } 176 + } 177 + } 178 + 179 + // Multiple threads might be looking at these fields. 180 + os_mutex_lock(&ics->server->global_state.lock); 181 + 182 + ipc_message_channel_close((struct ipc_message_channel *)&ics->imc); 183 + 184 + ics->server->threads[ics->server_thread_index].state = IPC_THREAD_STOPPING; 185 + ics->server_thread_index = -1; 186 + memset((void *)&ics->client_state, 0, sizeof(struct ipc_app_state)); 187 + 188 + os_mutex_unlock(&ics->server->global_state.lock); 189 + 190 + ipc_server_client_destroy_compositor(ics); 191 + 192 + // Should we stop the server when a client disconnects? 193 + if (ics->server->exit_on_disconnect) { 194 + ics->server->running = false; 195 + } 196 + 197 + ipc_server_deactivate_session(ics); 198 + } 199 + 200 + #endif // XRT_OS_WINDOWS 143 201 144 202 /* 145 203 *
+10 -14
src/xrt/ipc/server/ipc_server_process.c
··· 30 30 #include "server/ipc_server.h" 31 31 32 32 #include <stdlib.h> 33 - #include <unistd.h> 34 33 #include <inttypes.h> 35 34 #include <stdbool.h> 36 35 #include <sys/types.h> 37 36 #include <sys/stat.h> 38 - #include <sys/mman.h> 39 - #include <sys/socket.h> 40 - #include <sys/un.h> 41 37 #include <fcntl.h> 42 38 #include <errno.h> 43 39 #include <stdio.h> ··· 196 192 isbp->name = xbp->name; 197 193 198 194 // Copy the initial state and also count the number in input_pairs. 199 - size_t input_pair_start = input_pair_index; 195 + uint32_t input_pair_start = input_pair_index; 200 196 for (size_t k = 0; k < xbp->input_count; k++) { 201 197 ism->input_pairs[input_pair_index++] = xbp->inputs[k]; 202 198 } ··· 208 204 } 209 205 210 206 // Copy the initial state and also count the number in outputs. 211 - size_t output_pair_start = output_pair_index; 207 + uint32_t output_pair_start = output_pair_index; 212 208 for (size_t k = 0; k < xbp->output_count; k++) { 213 209 ism->output_pairs[output_pair_index++] = xbp->outputs[k]; 214 210 } ··· 309 305 310 306 // Setup the tracking origin. 311 307 isdev->tracking_origin_index = (uint32_t)-1; 312 - for (size_t k = 0; k < XRT_SYSTEM_MAX_DEVICES; k++) { 308 + for (uint32_t k = 0; k < XRT_SYSTEM_MAX_DEVICES; k++) { 313 309 if (xdev->tracking_origin != s->xtracks[k]) { 314 310 continue; 315 311 } ··· 324 320 xrt_device_update_inputs(xdev); 325 321 326 322 // Bindings 327 - size_t binding_start = binding_index; 323 + uint32_t binding_start = binding_index; 328 324 for (size_t k = 0; k < xdev->binding_profile_count; k++) { 329 325 handle_binding(ism, &xdev->binding_profiles[k], &ism->binding_profiles[binding_index++], 330 326 &input_pair_index, &output_pair_index); ··· 337 333 } 338 334 339 335 // Copy the initial state and also count the number in inputs. 340 - size_t input_start = input_index; 336 + uint32_t input_start = input_index; 341 337 for (size_t k = 0; k < xdev->input_count; k++) { 342 338 ism->inputs[input_index++] = xdev->inputs[k]; 343 339 } ··· 349 345 } 350 346 351 347 // Copy the initial state and also count the number in outputs. 352 - size_t output_start = output_index; 348 + uint32_t output_start = output_index; 353 349 for (size_t k = 0; k < xdev->output_count; k++) { 354 350 ism->outputs[output_index++] = xdev->outputs[k]; 355 351 } ··· 392 388 } 393 389 394 390 void 395 - ipc_server_start_client_listener_thread(struct ipc_server *vs, int fd) 391 + ipc_server_start_client_listener_thread(struct ipc_server *vs, xrt_ipc_handle_t ipc_handle) 396 392 { 397 393 volatile struct ipc_client_state *ics = NULL; 398 394 int32_t cs_index = -1; ··· 410 406 } 411 407 } 412 408 if (ics == NULL) { 413 - close(fd); 409 + xrt_ipc_handle_close(ipc_handle); 414 410 415 411 // Unlock when we are done. 416 412 os_mutex_unlock(&vs->global_state.lock); ··· 422 418 struct ipc_thread *it = &vs->threads[cs_index]; 423 419 if (it->state != IPC_THREAD_READY && it->state != IPC_THREAD_STOPPING) { 424 420 // we should not get here 425 - close(fd); 421 + xrt_ipc_handle_close(ipc_handle); 426 422 427 423 // Unlock when we are done. 428 424 os_mutex_unlock(&vs->global_state.lock); ··· 438 434 } 439 435 440 436 it->state = IPC_THREAD_STARTING; 441 - ics->imc.socket_fd = fd; 437 + ics->imc.ipc_handle = ipc_handle; 442 438 ics->server = vs; 443 439 ics->server_thread_index = cs_index; 444 440 ics->io_active = true;
+4
src/xrt/ipc/shared/ipc_protocol.h
··· 41 41 // example: v21.0.0-560-g586d33b5 42 42 #define IPC_VERSION_NAME_LEN 64 43 43 44 + #ifdef XRT_OS_WINDOWS 45 + typedef int pid_t; 46 + #endif 47 + 44 48 /* 45 49 * 46 50 * Shared memory structs.
+46
src/xrt/ipc/shared/ipc_shmem.c
··· 78 78 return XRT_SUCCESS; 79 79 } 80 80 81 + #elif defined(XRT_OS_WINDOWS) 82 + 83 + xrt_result_t 84 + ipc_shmem_create(size_t size, xrt_shmem_handle_t *out_handle, void **out_map) 85 + { 86 + *out_handle = NULL; 87 + LARGE_INTEGER sz = {.QuadPart = size}; 88 + HANDLE handle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, sz.HighPart, sz.LowPart, NULL); 89 + if (handle == NULL) { 90 + return XRT_ERROR_IPC_FAILURE; 91 + } 92 + 93 + xrt_result_t result = ipc_shmem_map(handle, size, out_map); 94 + if (result != XRT_SUCCESS) { 95 + CloseHandle(handle); 96 + return result; 97 + } 98 + 99 + *out_handle = handle; 100 + return XRT_SUCCESS; 101 + } 102 + 81 103 #else 82 104 #error "OS not yet supported" 83 105 #endif ··· 110 132 *out_map = ptr; 111 133 return XRT_SUCCESS; 112 134 } 135 + #elif defined(XRT_OS_WINDOWS) 136 + void 137 + ipc_shmem_destroy(xrt_shmem_handle_t *handle_ptr) 138 + { 139 + if (handle_ptr == NULL) { 140 + return; 141 + } 142 + xrt_shmem_handle_t handle = *handle_ptr; 143 + CloseHandle(handle); 144 + *handle_ptr = NULL; 145 + } 146 + 147 + xrt_result_t 148 + ipc_shmem_map(xrt_shmem_handle_t handle, size_t size, void **out_map) 149 + { 150 + void *ptr = MapViewOfFile(handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size); 151 + if (ptr == NULL) { 152 + return XRT_ERROR_IPC_FAILURE; 153 + } 154 + *out_map = ptr; 155 + return XRT_SUCCESS; 156 + } 157 + 158 + // BUGBUG: unmap? 113 159 #else 114 160 #error "OS not yet supported" 115 161 #endif
+19 -12
src/xrt/ipc/shared/ipc_utils.c
··· 15 15 #include "shared/ipc_protocol.h" 16 16 17 17 #include <errno.h> 18 + #if !defined(XRT_OS_WINDOWS) 18 19 #include <sys/socket.h> 19 20 #include <unistd.h> 21 + #endif 20 22 21 23 #include <stdio.h> 22 24 #include <string.h> ··· 37 39 #define IPC_WARN(d, ...) U_LOG_IFL_W(d->log_level, __VA_ARGS__) 38 40 #define IPC_ERROR(d, ...) U_LOG_IFL_E(d->log_level, __VA_ARGS__) 39 41 42 + #if !defined(XRT_OS_WINDOWS) 40 43 void 41 44 ipc_message_channel_close(struct ipc_message_channel *imc) 42 45 { 43 - if (imc->socket_fd < 0) { 46 + if (imc->ipc_handle < 0) { 44 47 return; 45 48 } 46 - close(imc->socket_fd); 47 - imc->socket_fd = -1; 49 + close(imc->ipc_handle); 50 + imc->ipc_handle = -1; 48 51 } 49 52 50 53 xrt_result_t ··· 62 65 msg.msg_iovlen = 1; 63 66 msg.msg_flags = 0; 64 67 65 - ssize_t ret = sendmsg(imc->socket_fd, &msg, MSG_NOSIGNAL); 68 + ssize_t ret = sendmsg(imc->ipc_handle, &msg, MSG_NOSIGNAL); 66 69 if (ret < 0) { 67 70 int code = errno; 68 71 IPC_ERROR(imc, "ERROR: Sending plain message on socket %d failed with error: '%i' '%s'!", 69 - (int)imc->socket_fd, code, strerror(code)); 72 + (int)imc->ipc_handle, code, strerror(code)); 70 73 return XRT_ERROR_IPC_FAILURE; 71 74 } 72 75 ··· 90 93 msg.msg_iovlen = 1; 91 94 msg.msg_flags = 0; 92 95 93 - ssize_t len = recvmsg(imc->socket_fd, &msg, MSG_NOSIGNAL); 96 + ssize_t len = recvmsg(imc->ipc_handle, &msg, MSG_NOSIGNAL); 94 97 95 98 if (len < 0) { 96 99 int code = errno; 97 100 IPC_ERROR(imc, "ERROR: Receiving plain message on socket '%d' failed with error: '%i' '%s'!", 98 - (int)imc->socket_fd, code, strerror(code)); 101 + (int)imc->ipc_handle, code, strerror(code)); 99 102 return XRT_ERROR_IPC_FAILURE; 100 103 } 101 104 ··· 135 138 msg.msg_control = u.buf; 136 139 msg.msg_controllen = cmsg_size; 137 140 138 - ssize_t len = recvmsg(imc->socket_fd, &msg, MSG_NOSIGNAL); 141 + ssize_t len = recvmsg(imc->ipc_handle, &msg, MSG_NOSIGNAL); 139 142 if (len < 0) { 140 143 IPC_ERROR(imc, "recvmsg failed with error: '%s'!", strerror(errno)); 141 144 return XRT_ERROR_IPC_FAILURE; ··· 187 190 188 191 memcpy(CMSG_DATA(cmsg), handles, fds_size); 189 192 190 - ssize_t ret = sendmsg(imc->socket_fd, &msg, MSG_NOSIGNAL); 193 + ssize_t ret = sendmsg(imc->ipc_handle, &msg, MSG_NOSIGNAL); 191 194 if (ret < 0) { 192 195 IPC_ERROR(imc, "ERROR: sending %d FDs on socket %d failed with error: '%i' '%s'!", (int)handle_count, 193 - imc->socket_fd, errno, strerror(errno)); 196 + imc->ipc_handle, errno, strerror(errno)); 194 197 for (uint32_t i = 0; i < handle_count; i++) { 195 198 IPC_ERROR(imc, "\tfd #%i: %i", i, handles[i]); 196 199 } ··· 199 202 return XRT_SUCCESS; 200 203 } 201 204 205 + #endif 206 + 202 207 xrt_result_t 203 208 ipc_receive_handles_shmem(struct ipc_message_channel *imc, 204 209 void *out_data, ··· 244 249 } 245 250 bool failed = false; 246 251 for (uint32_t i = 0; i < handle_count; ++i) { 247 - int err = AHardwareBuffer_recvHandleFromUnixSocket(imc->socket_fd, &(out_handles[i])); 252 + int err = AHardwareBuffer_recvHandleFromUnixSocket(imc->ipc_handle, &(out_handles[i])); 248 253 if (err != 0) { 249 254 failed = true; 250 255 } ··· 266 271 } 267 272 bool failed = false; 268 273 for (uint32_t i = 0; i < handle_count; ++i) { 269 - int err = AHardwareBuffer_sendHandleToUnixSocket(handles[i], imc->socket_fd); 274 + int err = AHardwareBuffer_sendHandleToUnixSocket(handles[i], imc->ipc_handle); 270 275 if (err != 0) { 271 276 failed = true; 272 277 } ··· 303 308 return ipc_send_fds(imc, data, size, handles, handle_count); 304 309 } 305 310 311 + #elif defined(XRT_OS_WINDOWS) 306 312 #else 307 313 #error "Need port to transport these graphics buffers" 308 314 #endif ··· 344 350 return ipc_send_fds(imc, data, size, handles, handle_count); 345 351 } 346 352 353 + #elif defined(XRT_OS_WINDOWS) 347 354 #else 348 355 #error "Need port to transport these graphics buffers" 349 356 #endif
+52 -1
src/xrt/ipc/shared/ipc_utils.h
··· 27 27 */ 28 28 struct ipc_message_channel 29 29 { 30 - int socket_fd; 30 + xrt_ipc_handle_t ipc_handle; 31 31 enum u_logging_level log_level; 32 32 }; 33 33 ··· 111 111 */ 112 112 xrt_result_t 113 113 ipc_send_fds(struct ipc_message_channel *imc, const void *data, size_t size, const int *handles, uint32_t handle_count); 114 + #elif defined(XRT_OS_WINDOWS) 115 + /*! 116 + * Receive a message along with a known number of file HANDLEs over the IPC 117 + * channel. 118 + * 119 + * @param imc Message channel to use 120 + * @param[out] out_data Pointer to the buffer to fill with data. Must not be 121 + * null. 122 + * @param[in] size Maximum size to read, must be greater than 0 123 + * @param[out] out_handles Array of file HANDLEs to populate. Must not be 124 + * null. 125 + * @param[in] handle_count Number of elements to receive into @p out_handles, 126 + * must be greater than 0 and must match the value provided at the other end. 127 + * 128 + * @public @memberof ipc_message_channel 129 + */ 130 + xrt_result_t 131 + ipc_receive_fds( 132 + struct ipc_message_channel *imc, void *out_data, size_t size, HANDLE *out_handles, uint32_t handle_count); 133 + 134 + /*! 135 + * Send a message along with file HANDLEs over the IPC channel. 136 + * 137 + * @param imc Message channel to use 138 + * @param[in] data Pointer to the data buffer to send. Must not be 139 + * null: use a filler message if necessary. 140 + * @param[in] size Size of data pointed-to by @p data, must be greater than 0 141 + * @param[out] handles Array of file HANDLEs to send. Must not be 142 + * null. 143 + * @param[in] handle_count Number of elements in @p handles, must be greater 144 + * than 0. If this is variable, it must also be separately transmitted ahead of 145 + * time, because the receiver must have the same value in its receive call. 146 + * 147 + * @public @memberof ipc_message_channel 148 + */ 149 + xrt_result_t 150 + ipc_send_fds( 151 + struct ipc_message_channel *imc, const void *data, size_t size, const HANDLE *handles, uint32_t handle_count); 152 + 153 + /*! 154 + * Helper to convert windows error codes to human readable strings for logging 155 + * N.B. This routine is not thread safe 156 + * 157 + * @param err windows error code 158 + * @return human readable string corresponding to the error code 159 + * 160 + * @public @memberof ipc_message_channel 161 + */ 162 + const char * 163 + ipc_winerror(DWORD err); 164 + 114 165 #endif // XRT_OS_UNIX 115 166 /*! 116 167 * @}
+201
src/xrt/ipc/shared/ipc_utils_windows.cpp
··· 1 + // Copyright 2022, Magic Leap, Inc. 2 + // Copyright 2020-2022, Collabora, Ltd. 3 + // SPDX-License-Identifier: BSL-1.0 4 + /*! 5 + * @file 6 + * @brief IPC util helpers on Windows, for internal use only 7 + * @author Julian Petrov <jpetrov@magicleap.com> 8 + * @author Ryan Pavlik <ryan.pavlik@collabora.com> 9 + * @author Pete Black <pblack@collabora.com> 10 + * @author Jakob Bornecrantz <jakob@collabora.com> 11 + * @ingroup ipc_shared 12 + */ 13 + 14 + #include "xrt/xrt_config_os.h" 15 + 16 + #include "shared/ipc_utils.h" 17 + #include "shared/ipc_protocol.h" 18 + 19 + #include <stdio.h> 20 + #include <string.h> 21 + #include <stdint.h> 22 + #include <assert.h> 23 + 24 + #include "util/u_logging.h" 25 + 26 + #include <vector> 27 + 28 + /* 29 + * 30 + * Logging 31 + * 32 + */ 33 + 34 + #define IPC_TRACE(d, ...) U_LOG_IFL_T(d->log_level, __VA_ARGS__) 35 + #define IPC_DEBUG(d, ...) U_LOG_IFL_D(d->log_level, __VA_ARGS__) 36 + #define IPC_INFO(d, ...) U_LOG_IFL_I(d->log_level, __VA_ARGS__) 37 + #define IPC_WARN(d, ...) U_LOG_IFL_W(d->log_level, __VA_ARGS__) 38 + #define IPC_ERROR(d, ...) U_LOG_IFL_E(d->log_level, __VA_ARGS__) 39 + 40 + const char * 41 + ipc_winerror(DWORD err) 42 + { 43 + static char s_buf[4096]; // N.B. Not thread-safe. If needed, use a thread var 44 + if (!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, LANG_SYSTEM_DEFAULT, s_buf, sizeof(s_buf), NULL)) { 45 + s_buf[0] = 0; 46 + } 47 + return s_buf; 48 + } 49 + 50 + void 51 + ipc_message_channel_close(struct ipc_message_channel *imc) 52 + { 53 + if (imc->ipc_handle != INVALID_HANDLE_VALUE) { 54 + CloseHandle(imc->ipc_handle); 55 + imc->ipc_handle = INVALID_HANDLE_VALUE; 56 + } 57 + } 58 + 59 + xrt_result_t 60 + ipc_send(struct ipc_message_channel *imc, const void *data, size_t size) 61 + { 62 + DWORD len; 63 + if (!WriteFile(imc->ipc_handle, data, DWORD(size), &len, NULL)) { 64 + DWORD err = GetLastError(); 65 + IPC_ERROR(imc, "WriteFile on pipe %p failed: %d %s", imc->ipc_handle, err, ipc_winerror(err)); 66 + return XRT_ERROR_IPC_FAILURE; 67 + } 68 + return XRT_SUCCESS; 69 + } 70 + 71 + xrt_result_t 72 + ipc_receive(struct ipc_message_channel *imc, void *out_data, size_t size) 73 + { 74 + DWORD len; 75 + if (!ReadFile(imc->ipc_handle, out_data, DWORD(size), &len, NULL)) { 76 + DWORD err = GetLastError(); 77 + IPC_ERROR(imc, "ReadFile from pipe %p failed: %d %s", imc->ipc_handle, err, ipc_winerror(err)); 78 + return XRT_ERROR_IPC_FAILURE; 79 + } 80 + return XRT_SUCCESS; 81 + } 82 + 83 + xrt_result_t 84 + ipc_receive_fds( 85 + struct ipc_message_channel *imc, void *out_data, size_t size, HANDLE *out_handles, uint32_t handle_count) 86 + { 87 + auto rc = ipc_receive(imc, out_data, size); 88 + if (rc != XRT_SUCCESS || !handle_count) { 89 + return rc; 90 + } 91 + return ipc_receive(imc, out_handles, handle_count * sizeof(*out_handles)); 92 + } 93 + 94 + HANDLE 95 + open_target_process_dup_handle(struct ipc_message_channel *imc) 96 + { 97 + DWORD flags; 98 + if (!GetNamedPipeInfo(imc->ipc_handle, &flags, NULL, NULL, NULL)) { 99 + DWORD err = GetLastError(); 100 + IPC_ERROR(imc, "GetNamedPipeInfo(%p) failed: %d %s", imc->ipc_handle, err, ipc_winerror(err)); 101 + return NULL; 102 + } 103 + ULONG pid; 104 + if (flags & PIPE_SERVER_END) { 105 + if (!GetNamedPipeClientProcessId(imc->ipc_handle, &pid)) { 106 + DWORD err = GetLastError(); 107 + IPC_ERROR(imc, "GetNamedPipeClientProcessId(%p) failed: %d %s", imc->ipc_handle, err, 108 + ipc_winerror(err)); 109 + return NULL; 110 + } 111 + } else { 112 + if (!GetNamedPipeServerProcessId(imc->ipc_handle, &pid)) { 113 + DWORD err = GetLastError(); 114 + IPC_ERROR(imc, "GetNamedPipeServerProcessId(%p) failed: %d %s", imc->ipc_handle, err, 115 + ipc_winerror(err)); 116 + return NULL; 117 + } 118 + } 119 + HANDLE h = OpenProcess(PROCESS_DUP_HANDLE, false, pid); 120 + if (!h) { 121 + DWORD err = GetLastError(); 122 + IPC_ERROR(imc, "OpenProcess(PROCESS_DUP_HANDLE, pid %d) failed: %d %s", pid, err, ipc_winerror(err)); 123 + } 124 + return h; 125 + } 126 + 127 + xrt_result_t 128 + ipc_send_fds( 129 + struct ipc_message_channel *imc, const void *data, size_t size, const HANDLE *handles, uint32_t handle_count) 130 + { 131 + auto rc = ipc_send(imc, data, size); 132 + if (rc != XRT_SUCCESS) { 133 + return rc; 134 + } 135 + if (!handle_count) { 136 + return ipc_send(imc, nullptr, 0); 137 + } 138 + HANDLE target_process = open_target_process_dup_handle(imc); 139 + if (!target_process) { 140 + DWORD err = GetLastError(); 141 + IPC_ERROR(imc, "open_target_process_dup_handle failed: %d %s", err, ipc_winerror(err)); 142 + return XRT_ERROR_IPC_FAILURE; 143 + } 144 + 145 + HANDLE current_process = GetCurrentProcess(); 146 + std::vector<HANDLE> v; 147 + v.reserve(handle_count); 148 + for (uint32_t i = 0; i < handle_count; i++) { 149 + HANDLE handle; 150 + if (!DuplicateHandle(current_process, handles[i], target_process, &handle, 0, false, 151 + DUPLICATE_SAME_ACCESS)) { 152 + DWORD err = GetLastError(); 153 + IPC_ERROR(imc, "DuplicateHandle(%p) failed: %d %s", handles[i], err, ipc_winerror(err)); 154 + CloseHandle(target_process); 155 + return XRT_ERROR_IPC_FAILURE; 156 + } 157 + v.push_back(handle); 158 + } 159 + CloseHandle(target_process); 160 + return ipc_send(imc, v.data(), v.size() * sizeof(*v.data())); 161 + } 162 + 163 + xrt_result_t 164 + ipc_receive_handles_graphics_sync(struct ipc_message_channel *imc, 165 + void *out_data, 166 + size_t size, 167 + xrt_graphics_sync_handle_t *out_handles, 168 + uint32_t handle_count) 169 + { 170 + return ipc_receive_fds(imc, out_data, size, out_handles, handle_count); 171 + } 172 + 173 + xrt_result_t 174 + ipc_send_handles_graphics_sync(struct ipc_message_channel *imc, 175 + const void *data, 176 + size_t size, 177 + const xrt_graphics_sync_handle_t *handles, 178 + uint32_t handle_count) 179 + { 180 + return ipc_send_fds(imc, data, size, handles, handle_count); 181 + } 182 + 183 + xrt_result_t 184 + ipc_receive_handles_graphics_buffer(struct ipc_message_channel *imc, 185 + void *out_data, 186 + size_t size, 187 + xrt_graphics_buffer_handle_t *out_handles, 188 + uint32_t handle_count) 189 + { 190 + return ipc_receive_fds(imc, out_data, size, out_handles, handle_count); 191 + } 192 + 193 + xrt_result_t 194 + ipc_send_handles_graphics_buffer(struct ipc_message_channel *imc, 195 + const void *data, 196 + size_t size, 197 + const xrt_graphics_buffer_handle_t *handles, 198 + uint32_t handle_count) 199 + { 200 + return ipc_send_fds(imc, data, size, handles, handle_count); 201 + }
+4 -4
src/xrt/targets/ctl/main.c
··· 216 216 * Connenct. 217 217 */ 218 218 219 - ipc_c->imc.socket_fd = socket(PF_UNIX, SOCK_STREAM, 0); 220 - if (ipc_c->imc.socket_fd < 0) { 221 - ret = ipc_c->imc.socket_fd; 219 + ipc_c->imc.ipc_handle = socket(PF_UNIX, SOCK_STREAM, 0); 220 + if (ipc_c->imc.ipc_handle < 0) { 221 + ret = ipc_c->imc.ipc_handle; 222 222 PE("Socket create error '%i'!\n", ret); 223 223 return -1; 224 224 } ··· 235 235 addr.sun_family = AF_UNIX; 236 236 strcpy(addr.sun_path, sock_file); 237 237 238 - ret = connect(ipc_c->imc.socket_fd, // socket 238 + ret = connect(ipc_c->imc.ipc_handle, // socket 239 239 (struct sockaddr *)&addr, // address 240 240 sizeof(addr)); // size 241 241 if (ret < 0) {