Example #1
0
// drop all pending requests for the given UID from the global list
static void network_drop_pending_requests(uint32_t uid) {
	Node *pending_request_global_node = _pending_request_sentinel.next;
	Node *pending_request_global_node_next;
	PendingRequest *pending_request;
	char base58[BASE58_MAX_LENGTH];
	int count = 0;

	while (pending_request_global_node != &_pending_request_sentinel) {
		pending_request = containerof(pending_request_global_node,
		                              PendingRequest, global_node);
		pending_request_global_node_next = pending_request_global_node->next;

		if (pending_request->header.uid == uid) {
			pending_request_remove_and_free(pending_request);

			++count;
		}

		pending_request_global_node = pending_request_global_node_next;
	}

	if (count > 0) {
		log_warn("Dropped %d pending request(s) (uid: %s)",
		         count, base58_encode(base58, uint32_from_le(uid)));
	}
}
Example #2
0
void client_destroy(Client *client) {
    bool destroy_pending_requests = false;
    PendingRequest *pending_request;

    if (client->pending_request_count > 0) {
        log_warn("Destroying client ("CLIENT_SIGNATURE_FORMAT") while %d request(s) are still pending",
                 client_expand_signature(client), client->pending_request_count);

        if (network_create_zombie(client) < 0) {
            log_error("Could not create zombie for %d pending request(s) of ("CLIENT_SIGNATURE_FORMAT")",
                      client->pending_request_count, client_expand_signature(client));

            destroy_pending_requests = true;
        }
    }

    writer_destroy(&client->response_writer);

    event_remove_source(client->io->handle, EVENT_SOURCE_TYPE_GENERIC);
    io_destroy(client->io);
    free(client->io);

    if (destroy_pending_requests) {
        while (client->pending_request_sentinel.next != &client->pending_request_sentinel) {
            pending_request = containerof(client->pending_request_sentinel.next, PendingRequest, client_node);

            pending_request_remove_and_free(pending_request);
        }
    }

    if (client->destroy_done != NULL) {
        client->destroy_done();
    }
}
Example #3
0
void network_client_expects_response(Client *client, Packet *request) {
	PendingRequest *pending_request;
	char packet_signature[PACKET_MAX_SIGNATURE_LENGTH];

	if (client->pending_request_count >= CLIENT_MAX_PENDING_REQUESTS) {
		log_warn("Pending requests list for client ("CLIENT_SIGNATURE_FORMAT") is full, dropping %d pending request(s)",
		         client_expand_signature(client),
		         client->pending_request_count - CLIENT_MAX_PENDING_REQUESTS + 1);

		while (client->pending_request_count >= CLIENT_MAX_PENDING_REQUESTS) {
			pending_request = containerof(client->pending_request_sentinel.next, PendingRequest, client_node);

			pending_request_remove_and_free(pending_request);
		}
	}

	pending_request = calloc(1, sizeof(PendingRequest));

	if (pending_request == NULL) {
		log_error("Could not allocate pending request: %s (%d)",
		          get_errno_name(ENOMEM), ENOMEM);

		return;
	}

	node_reset(&pending_request->global_node);
	node_insert_before(&_pending_request_sentinel, &pending_request->global_node);

	node_reset(&pending_request->client_node);
	node_insert_before(&client->pending_request_sentinel, &pending_request->client_node);

	++client->pending_request_count;

	pending_request->client = client;
	pending_request->zombie = NULL;

	memcpy(&pending_request->header, &request->header, sizeof(PacketHeader));

#ifdef BRICKD_WITH_PROFILING
	pending_request->arrival_time = microseconds();
#endif

	log_packet_debug("Added pending request (%s) for client ("CLIENT_SIGNATURE_FORMAT")",
	                 packet_get_request_signature(packet_signature, request),
	                 client_expand_signature(client));
}
Example #4
0
void client_dispatch_response(Client *client, PendingRequest *pending_request,
                              Packet *response, bool force, bool ignore_authentication) {
    Node *pending_request_client_node = NULL;
    int enqueued = 0;
#ifdef BRICKD_WITH_PROFILING
    uint64_t elapsed;
#endif

    if (!ignore_authentication &&
            client->authentication_state != CLIENT_AUTHENTICATION_STATE_DISABLED &&
            client->authentication_state != CLIENT_AUTHENTICATION_STATE_DONE) {
        log_packet_debug("Ignoring non-authenticated client ("CLIENT_SIGNATURE_FORMAT")",
                         client_expand_signature(client));

        goto cleanup;
    }

    // find matching pending request if not forced and no pending request is
    // already given. do this before the disconnect check to ensure that even
    // for a disconnected client the pending request list is updated correctly
    if (!force && pending_request == NULL) {
        pending_request_client_node = client->pending_request_sentinel.next;

        while (pending_request_client_node != &client->pending_request_sentinel) {
            pending_request = containerof(pending_request_client_node, PendingRequest, client_node);

            if (packet_is_matching_response(response, &pending_request->header)) {
                break;
            }

            pending_request_client_node = pending_request_client_node->next;
        }

        if (pending_request_client_node == &client->pending_request_sentinel) {
            pending_request = NULL;

            goto cleanup;
        }
    }

    if (client->disconnected) {
        log_debug("Ignoring disconnected client ("CLIENT_SIGNATURE_FORMAT")",
                  client_expand_signature(client));

        goto cleanup;
    }

    if (force || pending_request != NULL) {
        enqueued = writer_write(&client->response_writer, response);

        if (enqueued < 0) {
            goto cleanup;
        }

        if (force) {
            log_packet_debug("Forced to %s response to client ("CLIENT_SIGNATURE_FORMAT")",
                             enqueued ? "enqueue" : "send", client_expand_signature(client));
        } else {
#ifdef BRICKD_WITH_PROFILING
            elapsed = microseconds() - pending_request->arrival_time;

            log_packet_debug("%s response to client ("CLIENT_SIGNATURE_FORMAT"), was requested %u.%03u msec ago, %d request(s) still pending",
                             enqueued ? "Enqueued" : "Sent", client_expand_signature(client),
                             (unsigned int)(elapsed / 1000), (unsigned int)(elapsed % 1000),
                             client->pending_request_count - 1);
#else
            log_packet_debug("%s response to client ("CLIENT_SIGNATURE_FORMAT"), %d request(s) still pending",
                             enqueued ? "Enqueued" : "Sent", client_expand_signature(client),
                             client->pending_request_count - 1);
#endif
        }
    }

cleanup:
    if (pending_request != NULL) {
        pending_request_remove_and_free(pending_request);
    }
}