int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; if (mask & WLC_EVENT_ERROR) { sway_log(L_INFO, "IPC Client socket error, removing client"); client->fd = -1; ipc_client_disconnect(client); return 0; } if (mask & WLC_EVENT_HANGUP) { client->fd = -1; ipc_client_disconnect(client); return 0; } int read_available; if (ioctl(client_fd, FIONREAD, &read_available) == -1) { sway_log_errno(L_INFO, "Unable to read IPC socket buffer size"); ipc_client_disconnect(client); return 0; } // Wait for the rest of the command payload in case the header has already been read if (client->payload_length > 0) { if ((uint32_t)read_available >= client->payload_length) { ipc_client_handle_command(client); } return 0; } if (read_available < ipc_header_size) { return 0; } uint8_t buf[ipc_header_size]; uint32_t *buf32 = (uint32_t*)(buf + sizeof(ipc_magic)); ssize_t received = recv(client_fd, buf, ipc_header_size, 0); if (received == -1) { sway_log_errno(L_INFO, "Unable to receive header from IPC client"); ipc_client_disconnect(client); return 0; } if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) { sway_log(L_DEBUG, "IPC header check failed"); ipc_client_disconnect(client); return 0; } client->payload_length = buf32[0]; client->current_command = (enum ipc_command_type)buf32[1]; if (read_available - received >= (long)client->payload_length) { ipc_client_handle_command(client); } return 0; }
int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; sway_log(L_DEBUG, "Event on IPC client socket %d", client_fd); if (mask & WLC_EVENT_ERROR) { sway_log(L_INFO, "IPC Client socket error, removing client"); ipc_client_disconnect(client); return 0; } if (mask & WLC_EVENT_HANGUP) { ipc_client_disconnect(client); return 0; } int read_available; ioctl(client_fd, FIONREAD, &read_available); // Wait for the rest of the command payload in case the header has already been read if (client->payload_length > 0) { if (read_available >= client->payload_length) { ipc_client_handle_command(client); } else { sway_log(L_DEBUG, "Too little data to read payload on IPC Client socket, waiting for more (%d < %d)", read_available, client->payload_length); } return 0; } if (read_available < ipc_header_size) { sway_log(L_DEBUG, "Too little data to read header on IPC Client socket, waiting for more (%d < %d)", read_available, ipc_header_size); return 0; } char buf[ipc_header_size]; ssize_t received = recv(client_fd, buf, ipc_header_size, 0); if (received == -1) { sway_log_errno(L_INFO, "Unable to receive header from IPC client"); ipc_client_disconnect(client); return 0; } if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) { sway_log(L_DEBUG, "IPC header check failed"); ipc_client_disconnect(client); return 0; } client->payload_length = *(uint32_t *)&buf[sizeof(ipc_magic)]; client->current_command = (enum ipc_command_type) *(uint32_t *)&buf[sizeof(ipc_magic)+4]; if (read_available - received >= client->payload_length) { ipc_client_handle_command(client); } return 0; }