| 6153 | #endif /* _WIN32 */ |
| 6154 | |
| 6155 | bool cbm_daemon_ipc_send_frame(cbm_daemon_ipc_connection_t *connection, |
| 6156 | cbm_daemon_frame_type_t type, uint16_t flags, const void *payload, |
| 6157 | uint32_t length) { |
| 6158 | if (!connection || atomic_load_explicit(&connection->poisoned, memory_order_acquire) || |
| 6159 | (length > 0 && !payload)) { |
| 6160 | return false; |
| 6161 | } |
| 6162 | uint8_t header[CBM_DAEMON_FRAME_HEADER_SIZE]; |
| 6163 | if (!cbm_daemon_frame_header_encode(header, type, flags, length)) { |
| 6164 | return false; |
| 6165 | } |
| 6166 | uint64_t deadline_ms = ipc_deadline_after(CBM_DAEMON_IPC_SEND_TIMEOUT_MS); |
| 6167 | if (connection_write_full(connection, header, sizeof(header), deadline_ms) != 1) { |
| 6168 | return false; |
| 6169 | } |
| 6170 | if (length > 0 && connection_write_full(connection, payload, length, deadline_ms) != 1) { |
| 6171 | /* The peer has already received a complete header and will interpret |
| 6172 | * subsequent bytes as this payload, so this stream cannot be reused. */ |
| 6173 | atomic_store_explicit(&connection->poisoned, true, memory_order_release); |
| 6174 | return false; |
| 6175 | } |
| 6176 | return true; |
| 6177 | } |
| 6178 | |
| 6179 | int cbm_daemon_ipc_receive_frame_bounded(cbm_daemon_ipc_connection_t *connection, |
| 6180 | uint32_t timeout_ms, uint32_t max_payload_length, |