net: lib: coap_client: Add API to cancel specific request
Add a new API to cancel just one, or mathing requests, instead of cancelling all ongoing requests. Signed-off-by: Seppo Takalo <seppo.takalo@nordicsemi.no>
This commit is contained in:
parent
f0c6efe798
commit
b3f3bce23e
3 changed files with 158 additions and 0 deletions
|
@ -158,6 +158,21 @@ int coap_client_req(struct coap_client *client, int sock, const struct sockaddr
|
||||||
*/
|
*/
|
||||||
void coap_client_cancel_requests(struct coap_client *client);
|
void coap_client_cancel_requests(struct coap_client *client);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cancel matching requests.
|
||||||
|
*
|
||||||
|
* This function cancels all CoAP client request that matches the given request.
|
||||||
|
* The request is matched based on the method, path, callback and user_data, if provided.
|
||||||
|
* Any field set to NULL is considered a wildcard.
|
||||||
|
*
|
||||||
|
* (struct coap_client_request){0} cancels all requests.
|
||||||
|
* (struct coap_client_request){.method = COAP_METHOD_GET} cancels all GET requests.
|
||||||
|
*
|
||||||
|
* @param client Pointer to the CoAP client instance.
|
||||||
|
* @param req Pointer to the CoAP client request to be canceled.
|
||||||
|
*/
|
||||||
|
void coap_client_cancel_request(struct coap_client *client, struct coap_client_request *req);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialise a Block2 option to be added to a request
|
* @brief Initialise a Block2 option to be added to a request
|
||||||
*
|
*
|
||||||
|
|
|
@ -1016,6 +1016,41 @@ void coap_client_cancel_requests(struct coap_client *client)
|
||||||
k_sleep(K_MSEC(COAP_PERIODIC_TIMEOUT));
|
k_sleep(K_MSEC(COAP_PERIODIC_TIMEOUT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool requests_match(struct coap_client_request *a, struct coap_client_request *b)
|
||||||
|
{
|
||||||
|
/* enum coap_method does not have value for zero, so differentiate valid values */
|
||||||
|
if (a->method && b->method && a->method != b->method) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (a->path && b->path && strcmp(a->path, b->path) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (a->cb && b->cb && a->cb != b->cb) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (a->user_data && b->user_data && a->user_data != b->user_data) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* It is intentional that (struct coap_client_request){0} matches all */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void coap_client_cancel_request(struct coap_client *client, struct coap_client_request *req)
|
||||||
|
{
|
||||||
|
k_mutex_lock(&client->lock, K_FOREVER);
|
||||||
|
|
||||||
|
for (int i = 0; i < CONFIG_COAP_CLIENT_MAX_REQUESTS; i++) {
|
||||||
|
if (client->requests[i].request_ongoing &&
|
||||||
|
requests_match(&client->requests[i].coap_request, req)) {
|
||||||
|
LOG_DBG("Cancelling request %d", i);
|
||||||
|
report_callback_error(&client->requests[i], -ECANCELED);
|
||||||
|
release_internal_request(&client->requests[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
k_mutex_unlock(&client->lock);
|
||||||
|
}
|
||||||
|
|
||||||
void coap_client_recv(void *coap_cl, void *a, void *b)
|
void coap_client_recv(void *coap_cl, void *a, void *b)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
|
@ -1142,3 +1142,111 @@ ZTEST(coap_client, test_request_rst)
|
||||||
zassert_ok(k_sem_take(&sem, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
|
zassert_ok(k_sem_take(&sem, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
|
||||||
zassert_equal(last_response_code, -ECONNRESET, "");
|
zassert_equal(last_response_code, -ECONNRESET, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZTEST(coap_client, test_cancel)
|
||||||
|
{
|
||||||
|
struct k_sem sem1, sem2;
|
||||||
|
struct sockaddr address = {0};
|
||||||
|
struct coap_client_request req1 = {
|
||||||
|
.method = COAP_METHOD_GET,
|
||||||
|
.confirmable = true,
|
||||||
|
.path = test_path,
|
||||||
|
.fmt = COAP_CONTENT_FORMAT_TEXT_PLAIN,
|
||||||
|
.cb = coap_callback,
|
||||||
|
.payload = short_payload,
|
||||||
|
.len = strlen(short_payload),
|
||||||
|
.user_data = &sem1
|
||||||
|
};
|
||||||
|
struct coap_client_request req2 = req1;
|
||||||
|
|
||||||
|
req2.user_data = &sem2;
|
||||||
|
|
||||||
|
k_sem_init(&sem1, 0, 1);
|
||||||
|
k_sem_init(&sem2, 0, 1);
|
||||||
|
|
||||||
|
z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply;
|
||||||
|
|
||||||
|
k_sleep(K_MSEC(1));
|
||||||
|
|
||||||
|
zassert_ok(coap_client_req(&client, 0, &address, &req1, NULL));
|
||||||
|
zassert_ok(coap_client_req(&client, 0, &address, &req2, NULL));
|
||||||
|
|
||||||
|
k_sleep(K_SECONDS(1));
|
||||||
|
|
||||||
|
coap_client_cancel_request(&client, &req1);
|
||||||
|
zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
|
||||||
|
zassert_not_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
|
||||||
|
zassert_equal(last_response_code, -ECANCELED, "");
|
||||||
|
|
||||||
|
set_socket_events(client.fd, ZSOCK_POLLIN); /* First response is the cancelled one */
|
||||||
|
zassert_not_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
|
||||||
|
set_socket_events(client.fd, ZSOCK_POLLIN);
|
||||||
|
zassert_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
|
||||||
|
zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(coap_client, test_cancel_match)
|
||||||
|
{
|
||||||
|
struct k_sem sem1, sem2;
|
||||||
|
struct sockaddr address = {0};
|
||||||
|
struct coap_client_request req1 = {
|
||||||
|
.method = COAP_METHOD_GET,
|
||||||
|
.confirmable = true,
|
||||||
|
.path = test_path,
|
||||||
|
.fmt = COAP_CONTENT_FORMAT_TEXT_PLAIN,
|
||||||
|
.cb = coap_callback,
|
||||||
|
.payload = short_payload,
|
||||||
|
.len = strlen(short_payload),
|
||||||
|
.user_data = &sem1
|
||||||
|
};
|
||||||
|
struct coap_client_request req2 = req1;
|
||||||
|
|
||||||
|
req2.user_data = &sem2;
|
||||||
|
req2.path = "another";
|
||||||
|
|
||||||
|
k_sem_init(&sem1, 0, 1);
|
||||||
|
k_sem_init(&sem2, 0, 1);
|
||||||
|
|
||||||
|
z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply;
|
||||||
|
|
||||||
|
k_sleep(K_MSEC(1));
|
||||||
|
|
||||||
|
zassert_ok(coap_client_req(&client, 0, &address, &req1, NULL));
|
||||||
|
zassert_ok(coap_client_req(&client, 0, &address, &req2, NULL));
|
||||||
|
|
||||||
|
k_sleep(K_SECONDS(1));
|
||||||
|
|
||||||
|
/* match only one */
|
||||||
|
coap_client_cancel_request(&client, &(struct coap_client_request) {
|
||||||
|
.path = test_path
|
||||||
|
});
|
||||||
|
zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
|
||||||
|
zassert_not_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
|
||||||
|
zassert_equal(last_response_code, -ECANCELED, "");
|
||||||
|
|
||||||
|
zassert_ok(coap_client_req(&client, 0, &address, &req1, NULL));
|
||||||
|
|
||||||
|
/* should not match */
|
||||||
|
coap_client_cancel_request(&client, &(struct coap_client_request) {
|
||||||
|
.path = test_path,
|
||||||
|
.user_data = &sem2,
|
||||||
|
});
|
||||||
|
zassert_not_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
|
||||||
|
zassert_not_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
|
||||||
|
|
||||||
|
/* match both (all GET queries) */
|
||||||
|
coap_client_cancel_request(&client, &(struct coap_client_request) {
|
||||||
|
.method = COAP_METHOD_GET,
|
||||||
|
});
|
||||||
|
zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
|
||||||
|
zassert_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
|
||||||
|
|
||||||
|
zassert_ok(coap_client_req(&client, 0, &address, &req1, NULL));
|
||||||
|
zassert_ok(coap_client_req(&client, 0, &address, &req2, NULL));
|
||||||
|
|
||||||
|
/* match both (wildcard)*/
|
||||||
|
coap_client_cancel_request(&client, &(struct coap_client_request) {0});
|
||||||
|
zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
|
||||||
|
zassert_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue