| 2503 | } |
| 2504 | |
| 2505 | static bool runtime_control_request_send(const cbm_daemon_ipc_endpoint_t *endpoint, |
| 2506 | const cbm_daemon_build_identity_t *identity, |
| 2507 | cbm_daemon_runtime_operation_t operation, |
| 2508 | uint32_t timeout_ms, uint32_t response_size, |
| 2509 | uint8_t **payload_out) { |
| 2510 | *payload_out = NULL; |
| 2511 | if (!endpoint || !identity || !identity->build_fingerprint || |
| 2512 | timeout_ms == CBM_DAEMON_IPC_WAIT_FOREVER) { |
| 2513 | return false; |
| 2514 | } |
| 2515 | uint8_t request[CBM_DAEMON_CONTROL_REQUEST_SIZE]; |
| 2516 | memset(request, 0, sizeof(request)); |
| 2517 | int written = snprintf((char *)request, sizeof(request), "%s", identity->build_fingerprint); |
| 2518 | if (written <= 0 || (size_t)written != CBM_DAEMON_BUILD_FINGERPRINT_SIZE - 1U) { |
| 2519 | return false; |
| 2520 | } |
| 2521 | cbm_daemon_ipc_connection_t *connection = cbm_daemon_ipc_connect(endpoint, timeout_ms); |
| 2522 | bool sent = |
| 2523 | connection && cbm_daemon_ipc_send_frame(connection, CBM_DAEMON_FRAME_REQUEST, operation, |
| 2524 | request, (uint32_t)sizeof(request)); |
| 2525 | cbm_daemon_frame_t frame = {0}; |
| 2526 | uint8_t *payload = NULL; |
| 2527 | int received = sent ? cbm_daemon_ipc_receive_frame_bounded(connection, timeout_ms, |
| 2528 | response_size, &frame, &payload) |
| 2529 | : 0; |
| 2530 | bool valid = received == 1 && frame.type == CBM_DAEMON_FRAME_RESPONSE && |
| 2531 | frame.flags == operation && frame.length == response_size && payload && |
| 2532 | payload[0] == 1U; |
| 2533 | cbm_daemon_ipc_connection_close(connection); |
| 2534 | if (!valid) { |
| 2535 | free(payload); |
| 2536 | return false; |
| 2537 | } |
| 2538 | *payload_out = payload; |
| 2539 | return true; |
| 2540 | } |
| 2541 | |
| 2542 | static uint32_t runtime_control_read_u32(const uint8_t *bytes) { |
| 2543 | return ((uint32_t)bytes[0] << 24) | ((uint32_t)bytes[1] << 16) | ((uint32_t)bytes[2] << 8) | |
no test coverage detected