The open source OpenXR runtime

ipc: Add IPC server client connection callbacks

Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2612>

authored by

Michael Haselton and committed by
Jakob Bornecrantz
b17c9d6e eeb2df58

+91 -5
+12
src/xrt/ipc/server/ipc_server.h
··· 24 #include "shared/ipc_protocol.h" 25 #include "shared/ipc_message_channel.h" 26 27 #include <stdio.h> 28 29 ··· 411 412 struct os_mutex lock; 413 } global_state; 414 }; 415 416 /*!
··· 24 #include "shared/ipc_protocol.h" 25 #include "shared/ipc_message_channel.h" 26 27 + #include "ipc_server_interface.h" 28 + 29 #include <stdio.h> 30 31 ··· 413 414 struct os_mutex lock; 415 } global_state; 416 + 417 + /*! 418 + * Callbacks for server events. 419 + */ 420 + const struct ipc_server_callbacks *callbacks; 421 + 422 + /*! 423 + * User data passed to callbacks. 424 + */ 425 + void *callback_data; 426 }; 427 428 /*!
+18
src/xrt/ipc/server/ipc_server_interface.h
··· 73 * @param[in] data User data given passed into the main function. 74 */ 75 void (*mainloop_leaving)(struct ipc_server *s, struct xrt_instance *xinst, void *data); 76 }; 77 78 /*!
··· 73 * @param[in] data User data given passed into the main function. 74 */ 75 void (*mainloop_leaving)(struct ipc_server *s, struct xrt_instance *xinst, void *data); 76 + 77 + /*! 78 + * A new client has connected to the IPC server. 79 + * 80 + * param s The IPC server. 81 + * param client_id The ID of the newly connected client. 82 + * param data User data given passed into the main function. 83 + */ 84 + void (*client_connected)(struct ipc_server *s, uint32_t client_id, void *data); 85 + 86 + /*! 87 + * A client has disconnected from the IPC server. 88 + * 89 + * param s The IPC server. 90 + * param client_id The ID of the newly connected client. 91 + * param data User data given passed into the main function. 92 + */ 93 + void (*client_disconnected)(struct ipc_server *s, uint32_t client_id, void *data); 94 }; 95 96 /*!
+23 -3
src/xrt/ipc/server/ipc_server_per_client_thread.c
··· 1 // Copyright 2020-2023, Collabora, Ltd. 2 // SPDX-License-Identifier: BSL-1.0 3 /*! 4 * @file ··· 200 { 201 U_TRACE_SET_THREAD_NAME("IPC Client"); 202 203 - IPC_INFO(ics->server, "Client %u connected", ics->client_state.id); 204 205 // Claim the client fd. 206 int epoll_fd = setup_epoll(ics); ··· 231 232 // Detect clients disconnecting gracefully. 233 if (ret > 0 && (event.events & EPOLLHUP) != 0) { 234 - IPC_INFO(ics->server, "Client disconnected."); 235 break; 236 } 237 ··· 273 274 close(epoll_fd); 275 epoll_fd = -1; 276 277 // Following code is same for all platforms. 278 common_shutdown(ics); ··· 297 { 298 U_TRACE_SET_THREAD_NAME("IPC Client"); 299 300 - IPC_INFO(ics->server, "Client connected"); 301 302 while (ics->server->running) { 303 uint8_t buf[IPC_BUF_SIZE] = {0}; ··· 353 break; 354 } 355 } 356 357 // Following code is same for all platforms. 358 common_shutdown(ics);
··· 1 // Copyright 2020-2023, Collabora, Ltd. 2 + // Copyright 2025, NVIDIA CORPORATION. 3 // SPDX-License-Identifier: BSL-1.0 4 /*! 5 * @file ··· 201 { 202 U_TRACE_SET_THREAD_NAME("IPC Client"); 203 204 + // Call the client connected callback. 205 + ics->server->callbacks->client_connected( // 206 + ics->server, // 207 + ics->client_state.id, // 208 + ics->server->callback_data); // 209 210 // Claim the client fd. 211 int epoll_fd = setup_epoll(ics); ··· 236 237 // Detect clients disconnecting gracefully. 238 if (ret > 0 && (event.events & EPOLLHUP) != 0) { 239 break; 240 } 241 ··· 277 278 close(epoll_fd); 279 epoll_fd = -1; 280 + 281 + // Call the client disconnected callback. 282 + ics->server->callbacks->client_disconnected( // 283 + ics->server, // 284 + ics->client_state.id, // 285 + ics->server->callback_data); // 286 287 // Following code is same for all platforms. 288 common_shutdown(ics); ··· 307 { 308 U_TRACE_SET_THREAD_NAME("IPC Client"); 309 310 + // Call the client connected callback. 311 + ics->server->callbacks->client_connected( // 312 + ics->server, // 313 + ics->client_state.id, // 314 + ics->server->callback_data); // 315 316 while (ics->server->running) { 317 uint8_t buf[IPC_BUF_SIZE] = {0}; ··· 367 break; 368 } 369 } 370 + 371 + // Call the client disconnected callback. 372 + ics->server->callbacks->client_disconnected( // 373 + ics->server, // 374 + ics->client_state.id, // 375 + ics->server->callback_data); // 376 377 // Following code is same for all platforms. 378 common_shutdown(ics);
+24 -2
src/xrt/ipc/server/ipc_server_process.c
··· 462 } 463 464 static xrt_result_t 465 - init_all(struct ipc_server *s, enum u_logging_level log_level, bool exit_on_disconnect) 466 { 467 xrt_result_t xret = XRT_SUCCESS; 468 int ret; 469 470 // First order of business set the log level. 471 s->log_level = log_level; 472 473 // This should never fail. 474 ret = os_mutex_init(&s->global_state.lock); ··· 1074 */ 1075 u_debug_gui_create(&ismi->udgci, &s->debug_gui); 1076 1077 - xret = init_all(s, log_level, ismi->exit_on_disconnect); 1078 U_LOG_CHK_ONLY_PRINT(log_level, xret, "init_all"); 1079 if (xret != XRT_SUCCESS) { 1080 // Propegate the failure. ··· 1148 // No-op 1149 } 1150 1151 int 1152 ipc_server_main(int argc, char **argv, const struct ipc_server_main_info *ismi) 1153 { ··· 1155 .init_failed = init_failed, 1156 .mainloop_entering = mainloop_entering, 1157 .mainloop_leaving = mainloop_leaving, 1158 }; 1159 1160 return ipc_server_main_common(ismi, &callbacks, NULL);
··· 462 } 463 464 static xrt_result_t 465 + init_all(struct ipc_server *s, 466 + enum u_logging_level log_level, 467 + const struct ipc_server_callbacks *callbacks, 468 + void *callback_data, 469 + bool exit_on_disconnect) 470 { 471 xrt_result_t xret = XRT_SUCCESS; 472 int ret; 473 474 // First order of business set the log level. 475 s->log_level = log_level; 476 + 477 + // Store callbacks and data 478 + s->callbacks = callbacks; 479 + s->callback_data = callback_data; 480 481 // This should never fail. 482 ret = os_mutex_init(&s->global_state.lock); ··· 1082 */ 1083 u_debug_gui_create(&ismi->udgci, &s->debug_gui); 1084 1085 + xret = init_all(s, log_level, callbacks, data, ismi->exit_on_disconnect); 1086 U_LOG_CHK_ONLY_PRINT(log_level, xret, "init_all"); 1087 if (xret != XRT_SUCCESS) { 1088 // Propegate the failure. ··· 1156 // No-op 1157 } 1158 1159 + void 1160 + client_connected(struct ipc_server *s, uint32_t client_id, void *data) 1161 + { 1162 + IPC_INFO(s, "Client %u connected", client_id); 1163 + } 1164 + 1165 + void 1166 + client_disconnected(struct ipc_server *s, uint32_t client_id, void *data) 1167 + { 1168 + IPC_INFO(s, "Client %u disconnected", client_id); 1169 + } 1170 + 1171 int 1172 ipc_server_main(int argc, char **argv, const struct ipc_server_main_info *ismi) 1173 { ··· 1175 .init_failed = init_failed, 1176 .mainloop_entering = mainloop_entering, 1177 .mainloop_leaving = mainloop_leaving, 1178 + .client_connected = client_connected, 1179 + .client_disconnected = client_disconnected, 1180 }; 1181 1182 return ipc_server_main_common(ismi, &callbacks, NULL);
+14
src/xrt/targets/service-lib/service_target.cpp
··· 78 // No-op 79 } 80 81 int32_t 82 addClient(int fd) 83 { ··· 140 .init_failed = signalInitFailed, 141 .mainloop_entering = signalStartupCompleteTrampoline, 142 .mainloop_leaving = signalShuttingDownTrampoline, 143 }; 144 145 //! Reference to the ipc_server, managed by ipc_server_process
··· 78 // No-op 79 } 80 81 + static void 82 + signalClientConnectedTrampoline(struct ipc_server *s, uint32_t client_id, void *data) 83 + { 84 + // No-op 85 + } 86 + 87 + static void 88 + signalClientDisconnectedTrampoline(struct ipc_server *s, uint32_t client_id, void *data) 89 + { 90 + // No-op 91 + } 92 + 93 int32_t 94 addClient(int fd) 95 { ··· 152 .init_failed = signalInitFailed, 153 .mainloop_entering = signalStartupCompleteTrampoline, 154 .mainloop_leaving = signalShuttingDownTrampoline, 155 + .client_connected = signalClientConnectedTrampoline, 156 + .client_disconnected = signalClientDisconnectedTrampoline, 157 }; 158 159 //! Reference to the ipc_server, managed by ipc_server_process