net: coap: Fix response matching algorithm
The algorithm for matching request with response was incorrect, which could lead to false matches (for example if request had a token, and piggybacked reply had no token but matching message ID only, that would still be counted as a match). This commit fixes it. The request/reply matching is implemented based on RFC now, with separate conditions for piggybacked/separate responses. Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
parent
3e1efedac1
commit
13cd48a431
1 changed files with 41 additions and 9 deletions
|
@ -1808,32 +1808,63 @@ struct coap_reply *coap_response_received(
|
|||
{
|
||||
struct coap_reply *r;
|
||||
uint8_t token[COAP_TOKEN_MAX_LEN];
|
||||
bool piggybacked = false;
|
||||
uint8_t type;
|
||||
uint16_t id;
|
||||
uint8_t tkl;
|
||||
size_t i;
|
||||
|
||||
if (!is_empty_message(response) && coap_packet_is_request(response)) {
|
||||
/* Request can't be response */
|
||||
type = coap_header_get_type(response);
|
||||
id = coap_header_get_id(response);
|
||||
tkl = coap_header_get_token(response, token);
|
||||
|
||||
if ((type == COAP_TYPE_ACK && is_empty_message(response)) ||
|
||||
coap_packet_is_request(response)) {
|
||||
/* Request or empty ACK can't be response */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
id = coap_header_get_id(response);
|
||||
tkl = coap_header_get_token(response, token);
|
||||
if (type == COAP_TYPE_ACK) {
|
||||
piggybacked = true;
|
||||
}
|
||||
|
||||
for (i = 0, r = replies; i < len; i++, r++) {
|
||||
int age;
|
||||
|
||||
if ((r->id == 0U) && (r->tkl == 0U)) {
|
||||
/* Skip unused entry. */
|
||||
if (r->reply == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Piggybacked must match id when token is empty */
|
||||
if ((r->id != id) && (tkl == 0U)) {
|
||||
/* Reset should only be handled if Message ID matches. */
|
||||
if (type == COAP_TYPE_RESET) {
|
||||
if (r->id != id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
goto handle_reply;
|
||||
}
|
||||
|
||||
/* In a piggybacked response, the Message ID of the Confirmable
|
||||
* request and the Acknowledgment MUST match, and the tokens of
|
||||
* the response and original request MUST match. In a separate
|
||||
* response, just the tokens of the response and original request
|
||||
* MUST match.
|
||||
*/
|
||||
if (piggybacked) {
|
||||
if (r->id != id) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (r->tkl != tkl) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tkl > 0 && memcmp(r->token, token, tkl)) {
|
||||
continue;
|
||||
if (r->tkl > 0) {
|
||||
if (memcmp(r->token, token, r->tkl) != 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
age = coap_get_option_int(response, COAP_OPTION_OBSERVE);
|
||||
|
@ -1841,6 +1872,7 @@ struct coap_reply *coap_response_received(
|
|||
if (age == -ENOENT || coap_age_is_newer(r->age, age)) {
|
||||
r->age = age;
|
||||
if (coap_header_get_code(response) != COAP_RESPONSE_CODE_CONTINUE) {
|
||||
handle_reply:
|
||||
r->reply(response, r, from);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue