| 2531 | } |
| 2532 | |
| 2533 | static bool runtime_control_request_send(const cbm_daemon_ipc_endpoint_t *endpoint, |
| 2534 | const cbm_daemon_build_identity_t *identity, |
| 2535 | cbm_daemon_runtime_operation_t operation, |
| 2536 | uint32_t timeout_ms, uint32_t response_size, |
| 2537 | uint8_t **payload_out) { |
| 2538 | *payload_out = NULL; |
| 2539 | if (!endpoint || !identity || !identity->build_fingerprint || |
| 2540 | timeout_ms == CBM_DAEMON_IPC_WAIT_FOREVER) { |
| 2541 | return false; |
| 2542 | } |
| 2543 | uint8_t request[CBM_DAEMON_CONTROL_REQUEST_SIZE]; |
| 2544 | memset(request, 0, sizeof(request)); |
| 2545 | int written = snprintf((char *)request, sizeof(request), "%s", identity->build_fingerprint); |
| 2546 | if (written <= 0 || (size_t)written != CBM_DAEMON_BUILD_FINGERPRINT_SIZE - 1U) { |
| 2547 | return false; |
| 2548 | } |
| 2549 | cbm_daemon_ipc_connection_t *connection = cbm_daemon_ipc_connect(endpoint, timeout_ms); |
| 2550 | bool sent = |
| 2551 | connection && cbm_daemon_ipc_send_frame(connection, CBM_DAEMON_FRAME_REQUEST, operation, |
| 2552 | request, (uint32_t)sizeof(request)); |
| 2553 | cbm_daemon_frame_t frame = {0}; |
| 2554 | uint8_t *payload = NULL; |
| 2555 | int received = sent ? cbm_daemon_ipc_receive_frame_bounded(connection, timeout_ms, |
| 2556 | response_size, &frame, &payload) |
| 2557 | : 0; |
| 2558 | bool valid = received == 1 && frame.type == CBM_DAEMON_FRAME_RESPONSE && |
| 2559 | frame.flags == operation && frame.length == response_size && payload && |
| 2560 | payload[0] == 1U; |
| 2561 | cbm_daemon_ipc_connection_close(connection); |
| 2562 | if (!valid) { |
| 2563 | free(payload); |
| 2564 | return false; |
| 2565 | } |
| 2566 | *payload_out = payload; |
| 2567 | return true; |
| 2568 | } |
| 2569 | |
| 2570 | static uint32_t runtime_control_read_u32(const uint8_t *bytes) { |
| 2571 | return ((uint32_t)bytes[0] << 24) | ((uint32_t)bytes[1] << 16) | ((uint32_t)bytes[2] << 8) | |
no test coverage detected