Skip to content

Commit 1890dbd

Browse files
SeppoTakalommahadevan108
authored andcommitted
net: lib: coap_client: Fix reset handling
Fix handling of received CoAP reset. Signed-off-by: Seppo Takalo <seppo.takalo@nordicsemi.no>
1 parent a14f083 commit 1890dbd

File tree

2 files changed

+43
-13
lines changed

2 files changed

+43
-13
lines changed

include/zephyr/net/coap_client.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ struct coap_client_option {
8888
struct coap_client_internal_request {
8989
uint8_t request_token[COAP_TOKEN_MAX_LEN];
9090
uint32_t offset;
91-
uint32_t last_id;
91+
uint16_t last_id;
9292
uint8_t request_tkl;
9393
bool request_ongoing;
9494
atomic_t in_callback;

subsys/net/lib/coap/coap_client.c

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ static void cancel_requests_with(struct coap_client *client, int error);
3131
static int recv_response(struct coap_client *client, struct coap_packet *response, bool *truncated);
3232
static int handle_response(struct coap_client *client, const struct coap_packet *response,
3333
bool response_truncated);
34+
static struct coap_client_internal_request *get_request_with_mid(
35+
struct coap_client *client, const struct coap_packet *resp);
3436

3537

3638
static int send_request(int sock, const void *buf, size_t len, int flags,
@@ -689,6 +691,23 @@ static struct coap_client_internal_request *get_request_with_token(
689691
return NULL;
690692
}
691693

694+
static struct coap_client_internal_request *get_request_with_mid(
695+
struct coap_client *client, const struct coap_packet *resp)
696+
{
697+
uint16_t mid = coap_header_get_id(resp);
698+
699+
for (int i = 0; i < CONFIG_COAP_CLIENT_MAX_REQUESTS; i++) {
700+
if (client->requests[i].request_ongoing) {
701+
if (client->requests[i].last_id == mid) {
702+
return &client->requests[i];
703+
}
704+
}
705+
}
706+
707+
return NULL;
708+
}
709+
710+
692711
static bool find_echo_option(const struct coap_packet *response, struct coap_option *option)
693712
{
694713
return coap_find_options(response, COAP_OPTION_ECHO, option, 1);
@@ -698,7 +717,6 @@ static int handle_response(struct coap_client *client, const struct coap_packet
698717
bool response_truncated)
699718
{
700719
int ret = 0;
701-
int response_type;
702720
int block_option;
703721
int block_num;
704722
bool blockwise_transfer = false;
@@ -711,33 +729,45 @@ static int handle_response(struct coap_client *client, const struct coap_packet
711729
* NCON request results only as a separate CON or NCON message as there is no ACK
712730
* With RESET, just drop gloves and call the callback.
713731
*/
714-
response_type = coap_header_get_type(response);
715-
716-
internal_req = get_request_with_token(client, response);
717-
/* Reset and Ack need to match the message ID with request */
718-
if ((response_type == COAP_TYPE_ACK || response_type == COAP_TYPE_RESET) &&
719-
internal_req == NULL) {
720-
LOG_ERR("Unexpected ACK or Reset");
721-
return -EFAULT;
722-
} else if (response_type == COAP_TYPE_RESET) {
723-
coap_pending_clear(&internal_req->pending);
724-
}
725732

726733
/* CON, NON_CON and piggybacked ACK need to match the token with original request */
727734
uint16_t payload_len;
735+
uint8_t response_type = coap_header_get_type(response);
728736
uint8_t response_code = coap_header_get_code(response);
729737
uint16_t response_id = coap_header_get_id(response);
730738
const uint8_t *payload = coap_packet_get_payload(response, &payload_len);
731739

740+
if (response_type == COAP_TYPE_RESET) {
741+
internal_req = get_request_with_mid(client, response);
742+
if (!internal_req) {
743+
LOG_WRN("No matching request for RESET");
744+
return 0;
745+
}
746+
report_callback_error(internal_req, -ECONNRESET);
747+
reset_internal_request(internal_req);
748+
return 0;
749+
}
750+
732751
/* Separate response coming */
733752
if (payload_len == 0 && response_type == COAP_TYPE_ACK &&
734753
response_code == COAP_CODE_EMPTY) {
754+
internal_req = get_request_with_mid(client, response);
755+
if (!internal_req) {
756+
LOG_WRN("No matching request for ACK");
757+
return 0;
758+
}
735759
internal_req->pending.t0 = k_uptime_get();
736760
internal_req->pending.timeout = internal_req->pending.t0 + COAP_SEPARATE_TIMEOUT;
737761
internal_req->pending.retries = 0;
738762
return 1;
739763
}
740764

765+
internal_req = get_request_with_token(client, response);
766+
if (!internal_req) {
767+
LOG_WRN("No matching request for response");
768+
return 0;
769+
}
770+
741771
if (internal_req == NULL || !token_compare(internal_req, response)) {
742772
LOG_WRN("Not matching tokens");
743773
return 1;

0 commit comments

Comments
 (0)