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