| 2562 | } |
| 2563 | |
| 2564 | static bool runtime_control_request_send(const cbm_daemon_ipc_endpoint_t *endpoint, |
| 2565 | const cbm_daemon_build_identity_t *identity, |
| 2566 | cbm_daemon_runtime_operation_t operation, |
| 2567 | uint32_t timeout_ms, uint32_t response_size, |
| 2568 | uint8_t **payload_out) { |
| 2569 | *payload_out = NULL; |
| 2570 | if (!endpoint || !identity || !identity->build_fingerprint || |
| 2571 | timeout_ms == CBM_DAEMON_IPC_WAIT_FOREVER) { |
| 2572 | return false; |
| 2573 | } |
| 2574 | uint8_t request[CBM_DAEMON_CONTROL_REQUEST_SIZE]; |
| 2575 | memset(request, 0, sizeof(request)); |
| 2576 | int written = snprintf((char *)request, sizeof(request), "%s", identity->build_fingerprint); |
| 2577 | if (written <= 0 || (size_t)written != CBM_DAEMON_BUILD_FINGERPRINT_SIZE - 1U) { |
| 2578 | return false; |
| 2579 | } |
| 2580 | cbm_daemon_ipc_connection_t *connection = cbm_daemon_ipc_connect(endpoint, timeout_ms); |
| 2581 | bool sent = |
| 2582 | connection && cbm_daemon_ipc_send_frame(connection, CBM_DAEMON_FRAME_REQUEST, operation, |
| 2583 | request, (uint32_t)sizeof(request)); |
| 2584 | cbm_daemon_frame_t frame = {0}; |
| 2585 | uint8_t *payload = NULL; |
| 2586 | int received = sent ? cbm_daemon_ipc_receive_frame_bounded(connection, timeout_ms, |
| 2587 | response_size, &frame, &payload) |
| 2588 | : 0; |
| 2589 | bool valid = received == 1 && frame.type == CBM_DAEMON_FRAME_RESPONSE && |
| 2590 | frame.flags == operation && frame.length == response_size && payload && |
| 2591 | payload[0] == 1U; |
| 2592 | cbm_daemon_ipc_connection_close(connection); |
| 2593 | if (!valid) { |
| 2594 | free(payload); |
| 2595 | return false; |
| 2596 | } |
| 2597 | *payload_out = payload; |
| 2598 | return true; |
| 2599 | } |
| 2600 | |
| 2601 | static uint32_t runtime_control_read_u32(const uint8_t *bytes) { |
| 2602 | return ((uint32_t)bytes[0] << 24) | ((uint32_t)bytes[1] << 16) | ((uint32_t)bytes[2] << 8) | |
no test coverage detected