static void client_handle_read(void *opaque) { Client *client = opaque; int length; const char *message = NULL; char packet_signature[PACKET_MAX_SIGNATURE_LENGTH]; length = io_read(client->io, (uint8_t *)&client->request + client->request_used, sizeof(Packet) - client->request_used); if (length == 0) { log_info("Client ("CLIENT_SIGNATURE_FORMAT") disconnected by peer", client_expand_signature(client)); client->disconnected = true; return; } if (length < 0) { if (length == IO_CONTINUE) { // no actual data received } else if (errno_interrupted()) { log_debug("Receiving from client ("CLIENT_SIGNATURE_FORMAT") was interrupted, retrying", client_expand_signature(client)); } else if (errno_would_block()) { log_debug("Receiving from client ("CLIENT_SIGNATURE_FORMAT") would block, retrying", client_expand_signature(client)); } else { log_error("Could not receive from client ("CLIENT_SIGNATURE_FORMAT"), disconnecting client: %s (%d)", client_expand_signature(client), get_errno_name(errno), errno); client->disconnected = true; } return; } client->request_used += length; while (!client->disconnected && client->request_used > 0) { if (client->request_used < (int)sizeof(PacketHeader)) { // wait for complete header break; } if (!client->request_header_checked) { if (!packet_header_is_valid_request(&client->request.header, &message)) { // FIXME: include packet_get_content_dump output in the error message log_error("Received invalid request (%s) from client ("CLIENT_SIGNATURE_FORMAT"), disconnecting client: %s", packet_get_request_signature(packet_signature, &client->request), client_expand_signature(client), message); client->disconnected = true; return; } client->request_header_checked = true; } length = client->request.header.length; if (client->request_used < length) { // wait for complete packet break; } if (client->request.header.function_id == FUNCTION_DISCONNECT_PROBE) { log_packet_debug("Received disconnect probe from client ("CLIENT_SIGNATURE_FORMAT"), dropping request", client_expand_signature(client)); } else { log_packet_debug("Received request (%s) from client ("CLIENT_SIGNATURE_FORMAT")", packet_get_request_signature(packet_signature, &client->request), client_expand_signature(client)); client_handle_request(client, &client->request); } memmove(&client->request, (uint8_t *)&client->request + length, client->request_used - length); client->request_used -= length; client->request_header_checked = false; } }
static void client_handle_receive(void *opaque) { Client *client = opaque; const char *message = NULL; int length; PacketHeader *pending_request; length = socket_receive(client->socket, (uint8_t *)&client->packet + client->packet_used, sizeof(Packet) - client->packet_used); if (length < 0) { if (errno_interrupted()) { log_debug("Receiving from client (socket: %d, peer: %s), got interrupted", client->socket, client->peer); } else { log_error("Could not receive from client (socket: %d, peer: %s), disconnecting it: %s (%d)", client->socket, client->peer, get_errno_name(errno), errno); network_client_disconnected(client); } return; } if (length == 0) { log_info("Client (socket: %d, peer: %s) disconnected by peer", client->socket, client->peer); network_client_disconnected(client); return; } client->packet_used += length; while (client->packet_used > 0) { if (client->packet_used < (int)sizeof(PacketHeader)) { // wait for complete header break; } length = client->packet.header.length; if (client->packet_used < length) { // wait for complete packet break; } if (!packet_header_is_valid_request(&client->packet.header, &message)) { log_warn("Got invalid request (U: %u, L: %u, F: %u, S: %u, R: %u) from client (socket: %d, peer: %s): %s", client->packet.header.uid, client->packet.header.length, client->packet.header.function_id, client->packet.header.sequence_number, client->packet.header.response_expected, client->socket, client->peer, message); if (length < (int)sizeof(PacketHeader)) { // skip the complete header if length was too small length = sizeof(PacketHeader); } } else { log_debug("Got request (U: %u, L: %u, F: %u, S: %u, R: %u) from client (socket: %d, peer: %s)", client->packet.header.uid, client->packet.header.length, client->packet.header.function_id, client->packet.header.sequence_number, client->packet.header.response_expected, client->socket, client->peer); if (client->packet.header.response_expected) { if (client->pending_requests.count >= MAX_PENDING_REQUESTS) { log_warn("Dropping %d items from pending request array of client (socket: %d, peer: %s)", client->pending_requests.count - MAX_PENDING_REQUESTS + 1, client->socket, client->peer); while (client->pending_requests.count >= MAX_PENDING_REQUESTS) { array_remove(&client->pending_requests, 0, NULL); } } pending_request = array_append(&client->pending_requests); if (pending_request == NULL) { log_error("Could not append to pending request array: %s (%d)", get_errno_name(errno), errno); return; } memcpy(pending_request, &client->packet.header, sizeof(PacketHeader)); log_debug("Added pending request (U: %u, L: %u, F: %u, S: %u) for client (socket: %d, peer: %s)", pending_request->uid, pending_request->length, pending_request->function_id, pending_request->sequence_number, client->socket, client->peer); } usb_dispatch_packet(&client->packet); } memmove(&client->packet, (uint8_t *)&client->packet + length, client->packet_used - length); client->packet_used -= length; } }