Example #1
0
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;
    }
}
Example #2
0
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;
	}
}