diff --git a/src/net.c b/src/net.c index a54939587b..bbb6e7f9cc 100644 --- a/src/net.c +++ b/src/net.c @@ -1535,12 +1535,58 @@ handle_request(coap_context_t *context, coap_queue_t *node) { assert(response == NULL); } +static int +coap_remove_separate_from_queue(coap_context_t *context, const coap_address_t *dst, + const unsigned char *token, size_t token_length, coap_queue_t **sent) { + coap_queue_t *p, *q; + if (!context->sendqueue) + return 0; + + if (coap_address_equals(dst, &context->sendqueue->remote) && + token_match(token, token_length, + context->sendqueue->pdu->hdr->token, + context->sendqueue->pdu->hdr->token_length) && + context->sendqueue->retransmit_cnt > COAP_DEFAULT_MAX_RETRANSMIT) { + *sent = context->sendqueue; + context->sendqueue = context->sendqueue->next; + return 1; + } + + p = context->sendqueue; + q = p->next; + + /* when q is not NULL, it does not match (dst, token), so we can skip it */ + while (q) { + if (coap_address_equals(dst, &context->sendqueue->remote) && + token_match(token, token_length, + context->sendqueue->pdu->hdr->token, + context->sendqueue->pdu->hdr->token_length) && + context->sendqueue->retransmit_cnt > COAP_DEFAULT_MAX_RETRANSMIT) { + p->next = q->next; + q->next = NULL; + *sent = q; + return 1; + } else { + p = q; + q = q->next; + } + } + return 0; +} + static inline void handle_response(coap_context_t *context, coap_queue_t *sent, coap_queue_t *rcvd) { coap_send_ack(context, &rcvd->local_if, &rcvd->remote, rcvd->pdu); - + + /* Find separate response's request */ + if (sent == NULL) { + coap_remove_separate_from_queue(context, &rcvd->remote, + rcvd->pdu->hdr->token, + rcvd->pdu->hdr->token_length, &sent); + } + /* In a lossy context, the ACK of a separate response may have * been lost, so we need to stop retransmitting requests with the * same token. @@ -1580,8 +1626,15 @@ coap_dispatch(coap_context_t *context, coap_queue_t *rcvd) { /* find transaction in sendqueue to stop retransmission */ coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent); - if (rcvd->pdu->hdr->code == 0) + if (rcvd->pdu->hdr->code == 0) { + if (sent != NULL) { + sent->retransmit_cnt = COAP_DEFAULT_MAX_RETRANSMIT + 1; + sent->t = sent->timeout << COAP_DEFAULT_MAX_RETRANSMIT; + coap_insert_node(&context->sendqueue, sent); + sent = NULL; + } goto cleanup; + } /* if sent code was >= 64 the message might have been a * notification. Then, we must flag the observer to be alive